Ocean
Loading...
Searching...
No Matches
Euler.h
Go to the documentation of this file.
1/*
2 * Copyright (c) Meta Platforms, Inc. and affiliates.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 */
7
8#ifndef META_OCEAN_MATH_EULER_H
9#define META_OCEAN_MATH_EULER_H
10
11#include "ocean/math/Math.h"
12#include "ocean/math/Numeric.h"
13#include "ocean/math/Rotation.h"
15
16#include "ocean/base/String.h"
17
18namespace Ocean
19{
20
21// Forward declaration
22template <typename T> class HomogenousMatrixT4;
23// Forward declaration
24template <typename T> class QuaternionT;
25// Forward declaration
26template <typename T> class RotationT;
27// Forward declaration
28template <typename T> class SquareMatrixT3;
29
30// Forward declaration.
31template <typename T> class EulerT;
32
33/**
34 * Definition of the Euler object, depending on the OCEAN_MATH_USE_SINGLE_PRECISION either with single or double precision float data type.
35 * @see EulerT
36 * @ingroup math
37 */
39
40/**
41 * Instantiation of the EulerT template class using a double precision float data type.
42 * @see EulerT
43 * @ingroup math
44 */
46
47/**
48 * Instantiation of the EulerT template class using a single precision float data type.
49 * @see EulerT
50 * @ingroup math
51 */
53
54/**
55 * Definition of a typename alias for vectors with EulerT objects.
56 * @see EulerT
57 * @ingroup math
58 */
59template <typename T>
60using EulersT = std::vector<EulerT<T>>;
61
62/**
63 * Definition of a vector holding euler objects.
64 * @see Euler
65 * @ingroup math
66 */
67using Eulers = std::vector<Euler>;
68
69/**
70 * This class implements an euler rotation with angles: yaw, pitch and roll.
71 * The yaw angle is defined about the positive y-axis with range [-Pi, Pi].<br>
72 * The pitch angle is defined about the positive x-axis with range [-Pi/2, Pi/2].<br>
73 * The roll angle is defined about the positive z-axis with range [-Pi, Pi].<br>
74 * The entire rotation can be written as matrix product: Ry(yaw) * Rx(pitch) * Rz(roll).<br>
75 * All angles are defined in radian.
76 * @tparam T Data type of angle values_
77 * @see Euler, EulerF, EulerD, Rotation, Quaternion, SquareMatrix3, ExponentialMap.
78 * @ingroup math
79 */
80template <typename T>
81class EulerT
82{
83 public:
84
85 /**
86 * Definition of the used data type.
87 */
88 using Type = T;
89
90 public:
91
92 /**
93 * Creates a new Euler rotation with all angles zero.
94 */
95 EulerT();
96
97 /**
98 * Creates a new euler rotation by given angles.
99 * @param yaw The yaw angle with range [-Pi, Pi]
100 * @param pitch The pitch angle with range [-Pi/2, Pi/2]
101 * @param roll The roll angle with range [-Pi, Pi]
102 */
103 EulerT(const T yaw, const T pitch, const T roll);
104
105 /**
106 * Creates a new euler rotation by an array of angles.
107 * @param arrayValue Array with three angles, with order yaw, pitch, roll, must be valid
108 */
109 explicit EulerT(const T* arrayValue);
110
111 /**
112 * Creates a new euler rotation by a given homogeneous transformation.
113 * @param transformation The homogeneous transformation to create a euler rotation from
114 */
115 explicit EulerT(const HomogenousMatrixT4<T>& transformation);
116
117 /**
118 * Creates a new euler rotation by a given angle-axis rotation.
119 * @param rotation Angle-axis rotation to create a euler rotation from
120 */
121 explicit EulerT(const RotationT<T>& rotation);
122
123 /**
124 * Creates a new euler rotation by a given quaternion rotation.
125 * @param quaternion The quaternion rotation to create a euler rotation from
126 */
127 explicit EulerT(const QuaternionT<T>& quaternion);
128
129 /**
130 * Creates a new euler rotation by a given 3x3 matrix rotation.
131 * @param matrix The rotation matrix to create a euler rotation from
132 */
133 explicit EulerT(const SquareMatrixT3<T>& matrix);
134
135 /**
136 * Returns the yaw angle.
137 * @return Yaw angle in radian
138 */
139 inline const T& yaw() const;
140
141 /**
142 * Returns the yaw angle.
143 * @return Yaw angle in radian
144 */
145 inline T& yaw();
146
147 /**
148 * Returns the pitch angle.
149 * @return Pitch angle in radian
150 */
151 inline const T& pitch() const;
152
153 /**
154 * Returns the pitch angle.
155 * @return Pitch angle in radian
156 */
157 inline T& pitch();
158
159 /**
160 * Returns the roll angle.
161 * @return Roll angle in radian
162 */
163 inline const T& roll() const;
164
165 /**
166 * Returns the roll angle.
167 * @return Roll angle in radian
168 */
169 inline T& roll();
170
171 /**
172 * Returns whether the euler rotation holds valid parameters.
173 * @return True, if so
174 */
175 bool isValid() const;
176
177 /**
178 * Returns the euler rotation as string.
179 * @param inDegree True, to output the angles in degree; False, to output the angles in radian
180 * @return Euler rotation as string
181 */
182 std::string toString(const bool inDegree = false) const;
183
184 /**
185 * Returns whether two euler rotations are identical up to a small epsilon.
186 * @param euler Right euler rotation
187 * @return True, if so
188 */
189 bool operator==(const EulerT<T>& euler) const;
190
191 /**
192 * Returns whether two euler rotations are not identical up to a small epsilon.
193 * @param euler Right euler rotation
194 * @return True, if so
195 */
196 inline bool operator!=(const EulerT<T>& euler) const;
197
198 /**
199 * Element access operator.
200 * @param index The index of the element to access, with range [0, 2]
201 * @return Element of the euler rotation
202 */
203 inline const T& operator[](const unsigned int index) const;
204
205 /**
206 * Element access operator.
207 * @param index The index of the element to access, with range [0, 2]
208 * @return Element of the euler rotation
209 */
210 inline T& operator[](const unsigned int index);
211
212 /**
213 * Element access operator.
214 * @param index The index of the element to access, with range [0, 2]
215 * @return Element of the euler rotation
216 */
217 inline const T& operator()(const unsigned int index) const;
218
219 /**
220 * Element access operator.
221 * @param index The index of the element to access, with range [0, 2]
222 * @return Element of the euler rotation
223 */
224 inline T& operator()(const unsigned int index);
225
226 /**
227 * Access operator.
228 * @return Pointer to the elements
229 */
230 inline const T* operator()() const;
231
232 /**
233 * Access operator.
234 * @return Pointer to the elements
235 */
236 inline T* operator()();
237
238 /**
239 * Decomposes a 3x3 rotation matrix to the corresponding yaw, pitch and roll angles as defined by the euler class.
240 * The provided rotation matrix can be recreated by the matrix product: Ry(yAngle) * Rx(xAngle) * Rz(zAngle).
241 * @param matrix The 3x3 square matrix to decompose, must be an orthonormal rotation matrix
242 * @param yAngle The resulting (yaw) angle (rotation around the y-axis), with range [-PI, PI]
243 * @param xAngle The resulting (pitch) angle (rotation around the x-axis), with range [-PI/2, PI/2]
244 * @param zAngle The resulting (roll) angle (rotation around the z-axis), with range [-PI, PI]
245 */
246 static void decomposeRotationMatrixToYXZ(const SquareMatrixT3<T>& matrix, T& yAngle, T& xAngle, T& zAngle);
247
248 /**
249 * Decomposes a 3x3 rotation matrix to the corresponding x, y and z angles.
250 * The provided rotation matrix can be recreated by the matrix product: Rx(xAngle) * Ry(yAngle) * Rz(zAngle).
251 * @param matrix The 3x3 square matrix to decompose, must be an orthonormal rotation matrix
252 * @param xAngle The resulting x angle (rotation around the x-axis), with range [-PI, PI]
253 * @param yAngle The resulting y angle (rotation around the y-axis), with range [-PI/2, PI/2]
254 * @param zAngle The resulting z angle (rotation around the z-axis), with range [-PI, PI]
255 */
256 static void decomposeRotationMatrixToXYZ(const SquareMatrixT3<T>& matrix, T& xAngle, T& yAngle, T& zAngle);
257
258 /**
259 * Adjusts euler angles with arbitrary value (e.g., outside the valid value range) to euler angles within the value range of a valid Euler object.
260 * @param yaw The yaw angle to be adjusted, in radian, afterwards will be in the value range of [-PI, PI], with range (-infinity, infinity)
261 * @param pitch The pitch angle to be adjusted, in radian, afterwards will be in the value range of [-PI/2, PI/2], with range (-infinity, infinity)
262 * @param roll The roll angle to be adjusted, in radian, afterwards will be in the value range of [-PI, PI], with range (-infinity, infinity)
263 */
264 static void adjustAngles(T& yaw, T& pitch, T& roll);
265
266 protected:
267
268 /// The three angles of the euler rotation.
270};
271
272template <typename T>
274{
275 values_[0] = T(0);
276 values_[1] = T(0);
277 values_[2] = T(0);
278}
279
280template <typename T>
281EulerT<T>::EulerT(const T yaw, const T pitch, const T roll)
282{
283 values_[0] = yaw;
284 values_[1] = pitch;
285 values_[2] = roll;
286}
287
288template <typename T>
289EulerT<T>::EulerT(const T* arrayValue)
290{
291 ocean_assert(arrayValue);
292 memcpy(values_, arrayValue, sizeof(T) * 3);
293}
294
295template <typename T>
297{
298 decomposeRotationMatrixToYXZ(transformation.orthonormalRotationMatrix(), values_[0], values_[1], values_[2]);
299 ocean_assert(isValid());
300}
301
302template <typename T>
304{
305 decomposeRotationMatrixToYXZ(SquareMatrixT3<T>(rotation), values_[0], values_[1], values_[2]);
306 ocean_assert(isValid());
307}
308
309template <typename T>
311{
312 decomposeRotationMatrixToYXZ(SquareMatrixT3<T>(quaternion), values_[0], values_[1], values_[2]);
313 ocean_assert(isValid());
314}
315
316template <typename T>
318{
319 decomposeRotationMatrixToYXZ(matrix, values_[0], values_[1], values_[2]);
320 ocean_assert(isValid());
321}
322
323template <typename T>
324inline const T& EulerT<T>::yaw() const
325{
326 return values_[0];
327}
328
329template <typename T>
330inline T& EulerT<T>::yaw()
331{
332 return values_[0];
333}
334
335template <typename T>
336inline const T& EulerT<T>::pitch() const
337{
338 return values_[1];
339}
340
341template <typename T>
343{
344 return values_[1];
345}
346
347template <typename T>
348inline const T& EulerT<T>::roll() const
349{
350 return values_[2];
351}
352
353template <typename T>
355{
356 return values_[2];
357}
358
359template <typename T>
366
367template <typename T>
368std::string EulerT<T>::toString(const bool inDegree) const
369{
370 if (inDegree)
371 {
372 const T yaw = NumericT<T>::rad2deg(values_[0]);
373 const T pitch = NumericT<T>::rad2deg(values_[1]);
374 const T roll = NumericT<T>::rad2deg(values_[2]);
375
376 return String::toAString(yaw, 1u) + ", " + String::toAString(pitch, 1u) + ", " + String::toAString(roll, 1u);
377 }
378 else
379 {
380 return String::toAString(values_[0], 4u) + ", " + String::toAString(values_[1], 4u) + ", " + String::toAString(values_[2], 4u);
381 }
382}
383
384template <typename T>
385bool EulerT<T>::operator==(const EulerT<T>& euler) const
386{
387 return NumericT<T>::isEqual(values_[0], euler.values_[0]) && NumericT<T>::isEqual(values_[1], euler.values_[1]) && NumericT<T>::isEqual(values_[2], euler.values_[2]);
388}
389
390template <typename T>
391inline bool EulerT<T>::operator!=(const EulerT<T>& euler) const
392{
393 return !(*this == euler);
394}
395
396template <typename T>
397inline const T& EulerT<T>::operator[](const unsigned int index) const
398{
399 ocean_assert(index < 3u);
400 return values_[index];
401}
402
403template <typename T>
404inline T& EulerT<T>::operator[](const unsigned int index)
405{
406 ocean_assert(index < 3u);
407 return values_[index];
408}
409
410template <typename T>
411inline const T& EulerT<T>::operator()(const unsigned int index) const
412{
413 ocean_assert(index < 3u);
414 return values_[index];
415}
416
417template <typename T>
418inline T& EulerT<T>::operator()(const unsigned int index)
419{
420 ocean_assert(index < 3u);
421 return values_[index];
422}
423
424template <typename T>
425inline const T* EulerT<T>::operator()() const
426{
427 return values_;
428}
429
430template <typename T>
432{
433 return values_;
434}
435
436template <typename T>
437void EulerT<T>::decomposeRotationMatrixToYXZ(const SquareMatrixT3<T>& matrix, T& yAngle, T& xAngle, T& zAngle)
438{
439 ocean_assert(matrix.isOrthonormal());
440
441 /**
442 * Combined rotation matrix for R(y)R(x)R(z)
443 * [ cy cz + sx sy sz cz sx sy - cy sz cx sy ]
444 * [ cx sz cx cz -sx ]
445 * [ -cz sy + cy sx sz cy cz sx + sy sz cx cy ]
446 */
447
448 if (matrix(1, 2) > T(-1) + NumericT<T>::eps())
449 {
450 if (matrix(1, 2) < T(1) - NumericT<T>::eps())
451 {
452 // we have the normal case without any extreme angles
453
454 xAngle = NumericT<T>::asin(-matrix(1, 2));
455
456 ocean_assert(NumericT<T>::isNotEqualEps(matrix(0, 2)) || NumericT<T>::isNotEqualEps(matrix(2, 2)));
457 yAngle = NumericT<T>::atan2(matrix(0, 2), matrix(2, 2));
458
459 ocean_assert(NumericT<T>::isNotEqualEps(matrix(1, 0)) || NumericT<T>::isNotEqualEps(matrix(1, 1)));
460 zAngle = NumericT<T>::atan2(matrix(1, 0), matrix(1, 1));
461 }
462 else
463 {
464 // we have a special case where sx == -1
465 ocean_assert((std::is_same<float, T>::value) ? NumericT<T>::isWeakEqual(matrix(1, 2), 1) : NumericT<T>::isEqual(matrix(1, 2), 1));
466
467 /**
468 * Combined rotation matrix for R(y)R(x)R(z), with sx == -1 and cx == 0
469 * [ cy cz - sy sz - cz sy - cy sz 0 ] [ cos(y + z) -sin(y + z) 0 ]
470 * [ 0 0 -1 ] = [ 0 0 -1 ]
471 * [ -cz sy - cy sz - cy cz + sy sz 0 ] [ -sin(y + z) -cos(y + z) 0 ]
472 */
473
474 // tan(y + z) = sin(y + z) / cos(y + z), z == 0
475
476 yAngle = NumericT<T>::atan2(-matrix(0, 1), -matrix(2, 1));
477 xAngle = -NumericT<T>::pi_2();
478 zAngle = T(0.0);
479 }
480 }
481 else
482 {
483 // we have a special case where sx == 1
484 ocean_assert((std::is_same<float, T>::value) ? NumericT<T>::isWeakEqual(matrix(1, 2), -1) : NumericT<T>::isEqual(matrix(1, 2), -1));
485
486 /**
487 * Combined rotation matrix for R(y)R(x)R(z), with sx == 1 and cx == 0
488 * [ cy cz + sy sz cz sy - cy sz 0 ] [ cos(y - z) sin(y - z) 0 ]
489 * [ 0 0 -1 ] = [ 0 0 -1 ]
490 * [ -cz sy + cy sz cy cz + sy sz 0 ] [ sin(z - y) cos(y - z) 0 ]
491 */
492
493 // tan(y - z) = sin(y - z) / cos(y - z), z == 0
494
495 yAngle = NumericT<T>::atan2(matrix(0, 1), matrix(2, 1));
496 xAngle = NumericT<T>::pi_2();
497 zAngle = T(0.0);
498 }
499
503}
504
505template <typename T>
506void EulerT<T>::decomposeRotationMatrixToXYZ(const SquareMatrixT3<T>& matrix, T& xAngle, T& yAngle, T& zAngle)
507{
508 ocean_assert(matrix.isOrthonormal());
509
510 /**
511 * Combined rotation matrix for R(x)R(y)R(z)
512 * [ cy cz -cy sz sy ]
513 * [ cx sz + sx sy cz cx cz - sx sy sz -sx cy ]
514 * [ sx sz - cx sy cz sx cz + cx sy sz cx cy ]
515 */
516
517 if (matrix(0, 2) < T(1) - NumericT<T>::eps())
518 {
519 if (matrix(0, 2) > T(-1) + NumericT<T>::eps())
520 {
521 // we have the normal case without any extreme angles
522
523 ocean_assert(NumericT<T>::isNotEqualEps(matrix(1, 2)) || NumericT<T>::isNotEqualEps(matrix(2, 2)));
524 xAngle = NumericT<T>::atan2(-matrix(1, 2), matrix(2, 2));
525
526 yAngle = NumericT<T>::asin(matrix(0, 2));
527
528 ocean_assert(NumericT<T>::isNotEqualEps(matrix(0, 1)) || NumericT<T>::isNotEqualEps(matrix(0, 0)));
529 zAngle = NumericT<T>::atan2(-matrix(0, 1), matrix(0, 0));
530 }
531 else
532 {
533 // we have a special case where sx == -1
534 ocean_assert((std::is_same<float, T>::value) ? NumericT<T>::isWeakEqual(matrix(0, 2), -1) : NumericT<T>::isEqual(matrix(0, 2), -1));
535
536 /**
537 * Combined rotation matrix for R(x)R(y)R(z), with sy == -1 and cy == 0
538 * [ 0 0 1 ] [ 0 0 1 ]
539 * [ cx sz - sx cz cx cz + sx sz 0 ] = [ -sin(x - z) cos(x - z) 0 ]
540 * [ sx sz + cx cz sx cz - cx sz 0 ] [ cos(x - z) sin(x - z) 0 ]
541 */
542
543 // tan(x - z) = sin(x - z) / cos(x - z), z == 0
544
545 xAngle = NumericT<T>::atan2(matrix(2, 1), matrix(1, 1));
546 yAngle = -NumericT<T>::pi_2();
547 zAngle = T(0.0);
548 }
549 }
550 else
551 {
552 // we have a special case where sy == 1
553 ocean_assert((std::is_same<float, T>::value) ? NumericT<T>::isWeakEqual(matrix(0, 2), 1) : NumericT<T>::isEqual(matrix(0, 2), 1));
554
555 /**
556 * Combined rotation matrix for R(x)R(y)R(z), with sy == 1 and cy == 0
557 * [ 0 0 1 ] [ 0 0 1 ]
558 * [ cx sz + sx cz cx cz - sx sz 0 ] = [ sin(x + z) cos(x + z) 0 ]
559 * [ sx sz - cx cz sx cz + cx sz 0 ] [ -cos(x + z) sin(x + z) 0 ]
560 */
561
562 // tan(x + z) = sin(x + z) / cos(x + z), z == 0
563
564 xAngle = NumericT<T>::atan2(matrix(1, 0), matrix(1, 1));
565 yAngle = NumericT<T>::pi_2();
566 zAngle = T(0.0);
567 }
568
572}
573
574template <typename T>
575void EulerT<T>::adjustAngles(T& yaw, T& pitch, T& roll)
576{
577 pitch = NumericT<T>::angleAdjustNull(pitch);
578
579 if (NumericT<T>::abs(pitch) > NumericT<T>::pi_2())
580 {
581 pitch = NumericT<T>::copySign(NumericT<T>::pi(), pitch) - pitch;
582 yaw += NumericT<T>::pi();
583 roll += NumericT<T>::pi();
584 }
585
587 roll = NumericT<T>::angleAdjustNull(roll);
588
589 ocean_assert(Euler(yaw, pitch, roll).isValid());
590}
591
592}
593
594#endif // META_OCEAN_MATH_EULER_H
This class implements an euler rotation with angles: yaw, pitch and roll.
Definition Euler.h:82
EulerT()
Creates a new Euler rotation with all angles zero.
Definition Euler.h:273
static void decomposeRotationMatrixToXYZ(const SquareMatrixT3< T > &matrix, T &xAngle, T &yAngle, T &zAngle)
Decomposes a 3x3 rotation matrix to the corresponding x, y and z angles.
Definition Euler.h:506
const T & yaw() const
Returns the yaw angle.
Definition Euler.h:324
const T * operator()() const
Access operator.
Definition Euler.h:425
T values_[3]
The three angles of the euler rotation.
Definition Euler.h:269
const T & operator[](const unsigned int index) const
Element access operator.
Definition Euler.h:397
const T & roll() const
Returns the roll angle.
Definition Euler.h:348
bool operator!=(const EulerT< T > &euler) const
Returns whether two euler rotations are not identical up to a small epsilon.
Definition Euler.h:391
static void decomposeRotationMatrixToYXZ(const SquareMatrixT3< T > &matrix, T &yAngle, T &xAngle, T &zAngle)
Decomposes a 3x3 rotation matrix to the corresponding yaw, pitch and roll angles as defined by the eu...
Definition Euler.h:437
bool isValid() const
Returns whether the euler rotation holds valid parameters.
Definition Euler.h:360
std::string toString(const bool inDegree=false) const
Returns the euler rotation as string.
Definition Euler.h:368
T Type
Definition of the used data type.
Definition Euler.h:88
const T & pitch() const
Returns the pitch angle.
Definition Euler.h:336
static void adjustAngles(T &yaw, T &pitch, T &roll)
Adjusts euler angles with arbitrary value (e.g., outside the valid value range) to euler angles withi...
Definition Euler.h:575
bool operator==(const EulerT< T > &euler) const
Returns whether two euler rotations are identical up to a small epsilon.
Definition Euler.h:385
This class implements a 4x4 homogeneous transformation matrix using floating point values with the pr...
Definition HomogenousMatrix4.h:110
SquareMatrixT3< T > orthonormalRotationMatrix() const
Returns the 3x3 orthonormal rotation matrix of the 4x4 transformation (by forcing a orthogonal and no...
Definition HomogenousMatrix4.h:1538
This class provides basic numeric functionalities.
Definition Numeric.h:57
static constexpr bool isInsideRange(const T lower, const T value, const T upper, const T epsilon=NumericT< T >::eps())
Returns whether a value lies between a given range up to a provided epsilon border.
Definition Numeric.h:2881
static constexpr T pi_2()
Returns PI/2 which is equivalent to 90 degree.
Definition Numeric.h:938
static T atan2(const T y, const T x)
Returns the arctangent of a given value in radian.
Definition Numeric.h:1636
static constexpr T pi()
Returns PI which is equivalent to 180 degree.
Definition Numeric.h:926
static T angleAdjustNull(const T angle)
Adjusts an arbitrary angle into the range of (-PI, PI].
Definition Numeric.h:1800
static bool isEqual(const T first, const T second)
Returns whether two values are equal up to a small epsilon.
Definition Numeric.h:2395
static constexpr T copySign(const T signReceiver, const T signProvider)
Copies the sign of a given value to another one.
Definition Numeric.h:3273
static constexpr T rad2deg(const T rad)
Converts rad to deg.
Definition Numeric.h:3247
static T asin(const T value)
Returns the arcsine of a given value.
Definition Numeric.h:2896
This class implements a unit quaternion rotation.
Definition Quaternion.h:100
This class implements a axis-angle rotation using floating point values.
Definition Rotation.h:73
This class implements a 3x3 square matrix.
Definition SquareMatrix3.h:89
bool isOrthonormal(const T epsilon=NumericT< T >::eps()) const
Returns whether this matrix is an orthonormal matrix.
Definition SquareMatrix3.h:1366
static std::string toAString(const char value)
Converts a value to a string with 8bit character.
std::vector< EulerT< T > > EulersT
Definition of a typename alias for vectors with EulerT objects.
Definition Euler.h:60
EulerT< Scalar > Euler
Definition of the Euler object, depending on the OCEAN_MATH_USE_SINGLE_PRECISION either with single o...
Definition Euler.h:38
std::vector< Euler > Eulers
Definition of a vector holding euler objects.
Definition Euler.h:67
The namespace covering the entire Ocean framework.
Definition Accessor.h:15