Monado OpenXR Runtime
Loading...
Searching...
No Matches
lm_rotations_ceres.inl
Go to the documentation of this file.
1// Copyright 2022, Google, Inc.
2// Copyright 2022, Collabora, Ltd.
3// SPDX-License-Identifier: BSD-3-Clause
4/*!
5 * @file
6 * @brief Autodiff-safe rotations for Levenberg-Marquardt kinematic optimizer.
7 * Copied out of Ceres's `rotation.h` with some modifications.
8 * @author Kier Mierle <kier@google.com>
9 * @author Sameer Agarwal <sameeragarwal@google.com>
10 * @author Moshi Turner <moshiturner@protonmail.com>
11 * @ingroup tracking
12 */
13
14// Redistribution and use in source and binary forms, with or without
15// modification, are permitted provided that the following conditions are met:
16//
17// * Redistributions of source code must retain the above copyright notice,
18// this list of conditions and the following disclaimer.
19// * Redistributions in binary form must reproduce the above copyright notice,
20// this list of conditions and the following disclaimer in the documentation
21// and/or other materials provided with the distribution.
22// * Neither the name of Google Inc. nor the names of its contributors may be
23// used to endorse or promote products derived from this software without
24// specific prior written permission.
25//
26// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
27// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
30// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36// POSSIBILITY OF SUCH DAMAGE.
37
38
39template <typename T>
40inline void
41QuaternionProduct(const Quat<T> &z, const Quat<T> &w, Quat<T> &zw)
42{
43 // Inplace product is not supported
44 assert(&z != &zw);
45 assert(&w != &zw);
46
47 assert_quat_length_1(z);
48 assert_quat_length_1(w);
49
50
51 // clang-format off
52 zw.w = z.w * w.w - z.x * w.x - z.y * w.y - z.z * w.z;
53 zw.x = z.w * w.x + z.x * w.w + z.y * w.z - z.z * w.y;
54 zw.y = z.w * w.y - z.x * w.z + z.y * w.w + z.z * w.x;
55 zw.z = z.w * w.z + z.x * w.y - z.y * w.x + z.z * w.w;
56 // clang-format on
57}
58
59
60template <typename T>
61inline void
62UnitQuaternionRotatePoint(const Quat<T> &q, const Vec3<T> &pt, Vec3<T> &result)
63{
64 // clang-format off
65 T uv0 = q.y * pt.z - q.z * pt.y;
66 T uv1 = q.z * pt.x - q.x * pt.z;
67 T uv2 = q.x * pt.y - q.y * pt.x;
68 uv0 += uv0;
69 uv1 += uv1;
70 uv2 += uv2;
71 result.x = pt.x + q.w * uv0;
72 result.y = pt.y + q.w * uv1;
73 result.z = pt.z + q.w * uv2;
74 result.x += q.y * uv2 - q.z * uv1;
75 result.y += q.z * uv0 - q.x * uv2;
76 result.z += q.x * uv1 - q.y * uv0;
77 // clang-format on
78}
79
80template <typename T>
81inline void
82UnitQuaternionRotateAndScalePoint(const Quat<T> &q, const Vec3<T> &pt, const T scale, Vec3<T> &result)
83{
84 T uv0 = q.y * pt.z - q.z * pt.y;
85 T uv1 = q.z * pt.x - q.x * pt.z;
86 T uv2 = q.x * pt.y - q.y * pt.x;
87 uv0 += uv0;
88 uv1 += uv1;
89 uv2 += uv2;
90 result.x = pt.x + q.w * uv0;
91 result.y = pt.y + q.w * uv1;
92 result.z = pt.z + q.w * uv2;
93 result.x += q.y * uv2 - q.z * uv1;
94 result.y += q.z * uv0 - q.x * uv2;
95 result.z += q.x * uv1 - q.y * uv0;
96
97 result.x *= scale;
98 result.y *= scale;
99 result.z *= scale;
100}
101
102
103template <typename T>
104inline void
105AngleAxisToQuaternion(const Vec3<T> angle_axis, Quat<T> &result)
106{
107 const T &a0 = angle_axis.x;
108 const T &a1 = angle_axis.y;
109 const T &a2 = angle_axis.z;
110 const T theta_squared = a0 * a0 + a1 * a1 + a2 * a2;
111
112 // For points not at the origin, the full conversion is numerically stable.
113 if (likely(theta_squared > T(0.0))) {
114 const T theta = sqrt(theta_squared);
115 const T half_theta = theta * T(0.5);
116 const T k = sin(half_theta) / theta;
117 result.w = cos(half_theta);
118 result.x = a0 * k;
119 result.y = a1 * k;
120 result.z = a2 * k;
121 } else {
122 // At the origin, sqrt() will produce NaN in the derivative since
123 // the argument is zero. By approximating with a Taylor series,
124 // and truncating at one term, the value and first derivatives will be
125 // computed correctly when Jets are used.
126 const T k(0.5);
127 result.w = T(1.0);
128 result.x = a0 * k;
129 result.y = a1 * k;
130 result.z = a2 * k;
131 }
132}
133