Eigen-unsupported  5.0.1-dev+284dcc12
 
Loading...
Searching...
No Matches
EulerSystem.h
1// This file is part of Eigen, a lightweight C++ template library
2// for linear algebra.
3//
4// Copyright (C) 2015 Tal Hadad <tal_hd@hotmail.com>
5//
6// This Source Code Form is subject to the terms of the Mozilla
7// Public License v. 2.0. If a copy of the MPL was not distributed
8// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
9
10#ifndef EIGEN_EULERSYSTEM_H
11#define EIGEN_EULERSYSTEM_H
12
13// IWYU pragma: private
14#include "./InternalHeaderCheck.h"
15
16namespace Eigen {
17// Forward declarations
18template <typename Scalar_, class _System>
19class EulerAngles;
20
21namespace internal {
22// TODO: Add this trait to the Eigen internal API?
23template <int Num, bool IsPositive = (Num > 0)>
24struct Abs {
25 enum { value = Num };
26};
27
28template <int Num>
29struct Abs<Num, false> {
30 enum { value = -Num };
31};
32
33template <int Axis>
34struct IsValidAxis {
35 enum { value = Axis != 0 && Abs<Axis>::value <= 3 };
36};
37
38template <typename System, typename Other, int OtherRows = Other::RowsAtCompileTime,
39 int OtherCols = Other::ColsAtCompileTime>
40struct eulerangles_assign_impl;
41} // namespace internal
42
43#define EIGEN_EULER_ANGLES_CLASS_STATIC_ASSERT(COND, MSG) typedef char static_assertion_##MSG[(COND) ? 1 : -1]
44
58 EULER_X = 1,
59 EULER_Y = 2,
61};
62
120template <int _AlphaAxis, int _BetaAxis, int _GammaAxis>
122 public:
123 // It's defined this way and not as enum, because I think
124 // that enum is not guerantee to support negative numbers
125
127 static constexpr int AlphaAxis = _AlphaAxis;
128
130 static constexpr int BetaAxis = _BetaAxis;
131
133 static constexpr int GammaAxis = _GammaAxis;
134
135 enum {
136 AlphaAxisAbs = internal::Abs<AlphaAxis>::value,
137 BetaAxisAbs = internal::Abs<BetaAxis>::value,
138 GammaAxisAbs = internal::Abs<GammaAxis>::value,
139
140 IsAlphaOpposite = (AlphaAxis < 0) ? 1 : 0,
141 IsBetaOpposite = (BetaAxis < 0) ? 1 : 0,
142 IsGammaOpposite = (GammaAxis < 0) ? 1 : 0,
143
144 // Parity is even if alpha axis X is followed by beta axis Y, or Y is followed
145 // by Z, or Z is followed by X; otherwise it is odd.
146 IsOdd = ((AlphaAxisAbs) % 3 == (BetaAxisAbs - 1) % 3) ? 0 : 1,
147 IsEven = IsOdd ? 0 : 1,
148
150 ((unsigned)AlphaAxisAbs != (unsigned)GammaAxisAbs) ? 1 : 0
151 };
152
153 private:
154 EIGEN_EULER_ANGLES_CLASS_STATIC_ASSERT(internal::IsValidAxis<AlphaAxis>::value, ALPHA_AXIS_IS_INVALID);
155
156 EIGEN_EULER_ANGLES_CLASS_STATIC_ASSERT(internal::IsValidAxis<BetaAxis>::value, BETA_AXIS_IS_INVALID);
157
158 EIGEN_EULER_ANGLES_CLASS_STATIC_ASSERT(internal::IsValidAxis<GammaAxis>::value, GAMMA_AXIS_IS_INVALID);
159
160 EIGEN_EULER_ANGLES_CLASS_STATIC_ASSERT((unsigned)AlphaAxisAbs != (unsigned)BetaAxisAbs,
161 ALPHA_AXIS_CANT_BE_EQUAL_TO_BETA_AXIS);
162
163 EIGEN_EULER_ANGLES_CLASS_STATIC_ASSERT((unsigned)BetaAxisAbs != (unsigned)GammaAxisAbs,
164 BETA_AXIS_CANT_BE_EQUAL_TO_GAMMA_AXIS);
165
166 static const int
167 // I, J, K are the pivot indexes permutation for the rotation matrix, that match this Euler system.
168 // They are used in this class converters.
169 // They are always different from each other, and their possible values are: 0, 1, or 2.
170 I_ = AlphaAxisAbs - 1,
171 J_ = (AlphaAxisAbs - 1 + 1 + IsOdd) % 3, K_ = (AlphaAxisAbs - 1 + 2 - IsOdd) % 3;
172
173 // TODO: Get @mat parameter in form that avoids double evaluation.
174 template <typename Derived>
175 static void CalcEulerAngles_imp(Matrix<typename MatrixBase<Derived>::Scalar, 3, 1>& res,
176 const MatrixBase<Derived>& mat, internal::true_type /*isTaitBryan*/) {
177 using std::atan2;
178 using std::sqrt;
179
180 typedef typename Derived::Scalar Scalar;
181
182 const Scalar plusMinus = IsEven ? 1 : -1;
183 const Scalar minusPlus = IsOdd ? 1 : -1;
184
185 const Scalar Rsum = sqrt((mat(I_, I_) * mat(I_, I_) + mat(I_, J_) * mat(I_, J_) + mat(J_, K_) * mat(J_, K_) +
186 mat(K_, K_) * mat(K_, K_)) /
187 2);
188 res[1] = atan2(plusMinus * mat(I_, K_), Rsum);
189
190 // There is a singularity when cos(beta) == 0
191 if (Rsum > 4 * NumTraits<Scalar>::epsilon()) { // cos(beta) != 0
192 res[0] = atan2(minusPlus * mat(J_, K_), mat(K_, K_));
193 res[2] = atan2(minusPlus * mat(I_, J_), mat(I_, I_));
194 } else if (plusMinus * mat(I_, K_) > 0) { // cos(beta) == 0 and sin(beta) == 1
195 Scalar spos = mat(J_, I_) + plusMinus * mat(K_, J_); // 2*sin(alpha + plusMinus * gamma
196 Scalar cpos = mat(J_, J_) + minusPlus * mat(K_, I_); // 2*cos(alpha + plusMinus * gamma)
197 Scalar alphaPlusMinusGamma = atan2(spos, cpos);
198 res[0] = alphaPlusMinusGamma;
199 res[2] = 0;
200 } else { // cos(beta) == 0 and sin(beta) == -1
201 Scalar sneg = plusMinus * (mat(K_, J_) + minusPlus * mat(J_, I_)); // 2*sin(alpha + minusPlus*gamma)
202 Scalar cneg = mat(J_, J_) + plusMinus * mat(K_, I_); // 2*cos(alpha + minusPlus*gamma)
203 Scalar alphaMinusPlusBeta = atan2(sneg, cneg);
204 res[0] = alphaMinusPlusBeta;
205 res[2] = 0;
206 }
207 }
208
209 template <typename Derived>
210 static void CalcEulerAngles_imp(Matrix<typename MatrixBase<Derived>::Scalar, 3, 1>& res,
211 const MatrixBase<Derived>& mat, internal::false_type /*isTaitBryan*/) {
212 using std::atan2;
213 using std::sqrt;
214
215 typedef typename Derived::Scalar Scalar;
216
217 const Scalar plusMinus = IsEven ? 1 : -1;
218 const Scalar minusPlus = IsOdd ? 1 : -1;
219
220 const Scalar Rsum = sqrt((mat(I_, J_) * mat(I_, J_) + mat(I_, K_) * mat(I_, K_) + mat(J_, I_) * mat(J_, I_) +
221 mat(K_, I_) * mat(K_, I_)) /
222 2);
223
224 res[1] = atan2(Rsum, mat(I_, I_));
225
226 // There is a singularity when sin(beta) == 0
227 if (Rsum > 4 * NumTraits<Scalar>::epsilon()) { // sin(beta) != 0
228 res[0] = atan2(mat(J_, I_), minusPlus * mat(K_, I_));
229 res[2] = atan2(mat(I_, J_), plusMinus * mat(I_, K_));
230 } else if (mat(I_, I_) > 0) { // sin(beta) == 0 and cos(beta) == 1
231 Scalar spos = plusMinus * mat(K_, J_) + minusPlus * mat(J_, K_); // 2*sin(alpha + gamma)
232 Scalar cpos = mat(J_, J_) + mat(K_, K_); // 2*cos(alpha + gamma)
233 res[0] = atan2(spos, cpos);
234 res[2] = 0;
235 } else { // sin(beta) == 0 and cos(beta) == -1
236 Scalar sneg = plusMinus * mat(K_, J_) + plusMinus * mat(J_, K_); // 2*sin(alpha - gamma)
237 Scalar cneg = mat(J_, J_) - mat(K_, K_); // 2*cos(alpha - gamma)
238 res[0] = atan2(sneg, cneg);
239 res[2] = 0;
240 }
241 }
242
243 template <typename Scalar>
244 static void CalcEulerAngles(EulerAngles<Scalar, EulerSystem>& res,
245 const typename EulerAngles<Scalar, EulerSystem>::Matrix3& mat) {
246 CalcEulerAngles_imp(res.angles(), mat,
247 std::conditional_t<IsTaitBryan, internal::true_type, internal::false_type>());
248
249 if (IsAlphaOpposite) res.alpha() = -res.alpha();
250
251 if (IsBetaOpposite) res.beta() = -res.beta();
252
253 if (IsGammaOpposite) res.gamma() = -res.gamma();
254 }
255
256 template <typename Scalar_, class _System>
257 friend class Eigen::EulerAngles;
258
259 template <typename System, typename Other, int OtherRows, int OtherCols>
260 friend struct internal::eulerangles_assign_impl;
261};
262
263#define EIGEN_EULER_SYSTEM_TYPEDEF(A, B, C) typedef EulerSystem<EULER_##A, EULER_##B, EULER_##C> EulerSystem##A##B##C;
264
268EIGEN_EULER_SYSTEM_TYPEDEF(X, Y, Z)
269EIGEN_EULER_SYSTEM_TYPEDEF(X, Y, X)
270EIGEN_EULER_SYSTEM_TYPEDEF(X, Z, Y)
271EIGEN_EULER_SYSTEM_TYPEDEF(X, Z, X)
272
273EIGEN_EULER_SYSTEM_TYPEDEF(Y, Z, X)
274EIGEN_EULER_SYSTEM_TYPEDEF(Y, Z, Y)
275EIGEN_EULER_SYSTEM_TYPEDEF(Y, X, Z)
276EIGEN_EULER_SYSTEM_TYPEDEF(Y, X, Y)
277
278EIGEN_EULER_SYSTEM_TYPEDEF(Z, X, Y)
279EIGEN_EULER_SYSTEM_TYPEDEF(Z, X, Z)
280EIGEN_EULER_SYSTEM_TYPEDEF(Z, Y, X)
281EIGEN_EULER_SYSTEM_TYPEDEF(Z, Y, Z)
282} // namespace Eigen
283
284#endif // EIGEN_EULERSYSTEM_H
internal::traits< Derived >::Scalar Scalar
Represents a rotation in a 3 dimensional space as three Euler angles.
Definition EulerAngles.h:103
Represents a fixed Euler rotation system.
Definition EulerSystem.h:121
static constexpr int AlphaAxis
Definition EulerSystem.h:127
static constexpr int GammaAxis
Definition EulerSystem.h:133
@ GammaAxisAbs
Definition EulerSystem.h:138
@ IsGammaOpposite
Definition EulerSystem.h:142
@ IsAlphaOpposite
Definition EulerSystem.h:140
@ AlphaAxisAbs
Definition EulerSystem.h:136
@ BetaAxisAbs
Definition EulerSystem.h:137
@ IsTaitBryan
Definition EulerSystem.h:149
@ IsBetaOpposite
Definition EulerSystem.h:141
static constexpr int BetaAxis
Definition EulerSystem.h:130
EulerAxis
Representation of a fixed signed rotation axis for EulerSystem.
Definition EulerSystem.h:57
@ EULER_X
Definition EulerSystem.h:58
@ EULER_Z
Definition EulerSystem.h:60
@ EULER_Y
Definition EulerSystem.h:59
Namespace containing all symbols from the Eigen library.
const Eigen::CwiseUnaryOp< Eigen::internal::scalar_sqrt_op< typename Derived::Scalar >, const Derived > sqrt(const Eigen::ArrayBase< Derived > &x)