euler_angles.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. // Ceres Solver - A fast non-linear least squares minimizer
  2. // Copyright 2023 Google Inc. All rights reserved.
  3. // http://ceres-solver.org/
  4. //
  5. // Redistribution and use in source and binary forms, with or without
  6. // modification, are permitted provided that the following conditions are met:
  7. //
  8. // * Redistributions of source code must retain the above copyright notice,
  9. // this list of conditions and the following disclaimer.
  10. // * Redistributions in binary form must reproduce the above copyright notice,
  11. // this list of conditions and the following disclaimer in the documentation
  12. // and/or other materials provided with the distribution.
  13. // * Neither the name of Google Inc. nor the names of its contributors may be
  14. // used to endorse or promote products derived from this software without
  15. // specific prior written permission.
  16. //
  17. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  18. // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  19. // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  20. // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  21. // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  22. // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  23. // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  24. // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  25. // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  26. // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  27. // POSSIBILITY OF SUCH DAMAGE.
  28. #ifndef CERES_PUBLIC_INTERNAL_EULER_ANGLES_H_
  29. #define CERES_PUBLIC_INTERNAL_EULER_ANGLES_H_
  30. #include <type_traits>
  31. namespace ceres {
  32. namespace internal {
  33. // The EulerSystem struct represents an Euler Angle Convention in compile time.
  34. // It acts like a trait structure and is also used as a tag for dispatching
  35. // Euler angle conversion function templates
  36. //
  37. // Internally, it implements the convention laid out in "Euler angle
  38. // conversion", Ken Shoemake, Graphics Gems IV, where a choice of axis for the
  39. // first rotation (out of 3) and 3 binary choices compactly specify all 24
  40. // rotation conventions
  41. //
  42. // - InnerAxis: Axis for the first rotation. This is specified by struct tags
  43. // axis::X, axis::Y, and axis::Z
  44. //
  45. // - Parity: Defines the parity of the axis permutation. The axis sequence has
  46. // Even parity if the second axis of rotation is 'greater-than' the first axis
  47. // of rotation according to the order X<Y<Z<X, otherwise it has Odd parity.
  48. // This is specified by struct tags Even and Odd
  49. //
  50. // - AngleConvention: Defines whether Proper Euler Angles (originally defined
  51. // by Euler, which has the last axis repeated, i.e. ZYZ, ZXZ, etc), or
  52. // Tait-Bryan Angles (introduced by the nautical and aerospace fields, i.e.
  53. // using ZYX for roll-pitch-yaw) are used. This is specified by struct Tags
  54. // ProperEuler and TaitBryan.
  55. //
  56. // - FrameConvention: Defines whether the three rotations are be in a global
  57. // frame of reference (extrinsic) or in a body centred frame of reference
  58. // (intrinsic). This is specified by struct tags Extrinsic and Intrinsic
  59. namespace axis {
  60. struct X : std::integral_constant<int, 0> {};
  61. struct Y : std::integral_constant<int, 1> {};
  62. struct Z : std::integral_constant<int, 2> {};
  63. } // namespace axis
  64. struct Even;
  65. struct Odd;
  66. struct ProperEuler;
  67. struct TaitBryan;
  68. struct Extrinsic;
  69. struct Intrinsic;
  70. template <typename InnerAxisType,
  71. typename ParityType,
  72. typename AngleConventionType,
  73. typename FrameConventionType>
  74. struct EulerSystem {
  75. static constexpr bool kIsParityOdd = std::is_same_v<ParityType, Odd>;
  76. static constexpr bool kIsProperEuler =
  77. std::is_same_v<AngleConventionType, ProperEuler>;
  78. static constexpr bool kIsIntrinsic =
  79. std::is_same_v<FrameConventionType, Intrinsic>;
  80. static constexpr int kAxes[3] = {
  81. InnerAxisType::value,
  82. (InnerAxisType::value + 1 + static_cast<int>(kIsParityOdd)) % 3,
  83. (InnerAxisType::value + 2 - static_cast<int>(kIsParityOdd)) % 3};
  84. };
  85. } // namespace internal
  86. // Define human readable aliases to the type of the tags
  87. using ExtrinsicXYZ = internal::EulerSystem<internal::axis::X,
  88. internal::Even,
  89. internal::TaitBryan,
  90. internal::Extrinsic>;
  91. using ExtrinsicXYX = internal::EulerSystem<internal::axis::X,
  92. internal::Even,
  93. internal::ProperEuler,
  94. internal::Extrinsic>;
  95. using ExtrinsicXZY = internal::EulerSystem<internal::axis::X,
  96. internal::Odd,
  97. internal::TaitBryan,
  98. internal::Extrinsic>;
  99. using ExtrinsicXZX = internal::EulerSystem<internal::axis::X,
  100. internal::Odd,
  101. internal::ProperEuler,
  102. internal::Extrinsic>;
  103. using ExtrinsicYZX = internal::EulerSystem<internal::axis::Y,
  104. internal::Even,
  105. internal::TaitBryan,
  106. internal::Extrinsic>;
  107. using ExtrinsicYZY = internal::EulerSystem<internal::axis::Y,
  108. internal::Even,
  109. internal::ProperEuler,
  110. internal::Extrinsic>;
  111. using ExtrinsicYXZ = internal::EulerSystem<internal::axis::Y,
  112. internal::Odd,
  113. internal::TaitBryan,
  114. internal::Extrinsic>;
  115. using ExtrinsicYXY = internal::EulerSystem<internal::axis::Y,
  116. internal::Odd,
  117. internal::ProperEuler,
  118. internal::Extrinsic>;
  119. using ExtrinsicZXY = internal::EulerSystem<internal::axis::Z,
  120. internal::Even,
  121. internal::TaitBryan,
  122. internal::Extrinsic>;
  123. using ExtrinsicZXZ = internal::EulerSystem<internal::axis::Z,
  124. internal::Even,
  125. internal::ProperEuler,
  126. internal::Extrinsic>;
  127. using ExtrinsicZYX = internal::EulerSystem<internal::axis::Z,
  128. internal::Odd,
  129. internal::TaitBryan,
  130. internal::Extrinsic>;
  131. using ExtrinsicZYZ = internal::EulerSystem<internal::axis::Z,
  132. internal::Odd,
  133. internal::ProperEuler,
  134. internal::Extrinsic>;
  135. /* Rotating axes */
  136. using IntrinsicZYX = internal::EulerSystem<internal::axis::X,
  137. internal::Even,
  138. internal::TaitBryan,
  139. internal::Intrinsic>;
  140. using IntrinsicXYX = internal::EulerSystem<internal::axis::X,
  141. internal::Even,
  142. internal::ProperEuler,
  143. internal::Intrinsic>;
  144. using IntrinsicYZX = internal::EulerSystem<internal::axis::X,
  145. internal::Odd,
  146. internal::TaitBryan,
  147. internal::Intrinsic>;
  148. using IntrinsicXZX = internal::EulerSystem<internal::axis::X,
  149. internal::Odd,
  150. internal::ProperEuler,
  151. internal::Intrinsic>;
  152. using IntrinsicXZY = internal::EulerSystem<internal::axis::Y,
  153. internal::Even,
  154. internal::TaitBryan,
  155. internal::Intrinsic>;
  156. using IntrinsicYZY = internal::EulerSystem<internal::axis::Y,
  157. internal::Even,
  158. internal::ProperEuler,
  159. internal::Intrinsic>;
  160. using IntrinsicZXY = internal::EulerSystem<internal::axis::Y,
  161. internal::Odd,
  162. internal::TaitBryan,
  163. internal::Intrinsic>;
  164. using IntrinsicYXY = internal::EulerSystem<internal::axis::Y,
  165. internal::Odd,
  166. internal::ProperEuler,
  167. internal::Intrinsic>;
  168. using IntrinsicYXZ = internal::EulerSystem<internal::axis::Z,
  169. internal::Even,
  170. internal::TaitBryan,
  171. internal::Intrinsic>;
  172. using IntrinsicZXZ = internal::EulerSystem<internal::axis::Z,
  173. internal::Even,
  174. internal::ProperEuler,
  175. internal::Intrinsic>;
  176. using IntrinsicXYZ = internal::EulerSystem<internal::axis::Z,
  177. internal::Odd,
  178. internal::TaitBryan,
  179. internal::Intrinsic>;
  180. using IntrinsicZYZ = internal::EulerSystem<internal::axis::Z,
  181. internal::Odd,
  182. internal::ProperEuler,
  183. internal::Intrinsic>;
  184. } // namespace ceres
  185. #endif // CERES_PUBLIC_INTERNAL_EULER_ANGLES_H_