Ion
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
rotation.cc
Go to the documentation of this file.
1 
18 #include "ion/math/rotation.h"
19 
20 #include <algorithm>
21 #include <cmath>
22 #include <limits>
23 
24 #include "ion/base/logging.h"
25 #include "ion/math/angleutils.h"
26 #include "ion/math/utils.h"
27 #include "ion/math/vectorutils.h"
28 
29 namespace ion {
30 namespace math {
31 
33 
36 
37 
38 template <typename T>
40  const AngleType& angle) {
41  VectorType unit_axis = axis;
42  if (!Normalize(&unit_axis)) {
43  *this = Identity();
44  } else {
45  AngleType a = angle / 2;
46  const T s = static_cast<T>(Sine(a));
47  SetQuaternion(QuaternionType(unit_axis * s, static_cast<T>(Cosine(a))));
48  }
49 }
50 
51 template <typename T>
53  static const T kOne = static_cast<T>(1.0);
54  static const T kFour = static_cast<T>(4.0);
55 
56  const T d0 = mat(0, 0), d1 = mat(1, 1), d2 = mat(2, 2);
57  const T ww = kOne + d0 + d1 + d2;
58  const T xx = kOne + d0 - d1 - d2;
59  const T yy = kOne - d0 + d1 - d2;
60  const T zz = kOne - d0 - d1 + d2;
61 
62  const T max = std::max(ww, std::max(xx, std::max(yy, zz)));
63  if (ww == max) {
64  const T w4 = Sqrt(ww * kFour);
66  (mat(2, 1) - mat(1, 2)) / w4,
67  (mat(0, 2) - mat(2, 0)) / w4,
68  (mat(1, 0) - mat(0, 1)) / w4,
69  w4 / kFour));
70  }
71 
72  if (xx == max) {
73  const T x4 = Sqrt(xx * kFour);
75  x4 / kFour,
76  (mat(0, 1) + mat(1, 0)) / x4,
77  (mat(0, 2) + mat(2, 0)) / x4,
78  (mat(2, 1) - mat(1, 2)) / x4));
79  }
80 
81  if (yy == max) {
82  const T y4 = Sqrt(yy * kFour);
84  (mat(0, 1) + mat(1, 0)) / y4,
85  y4 / kFour,
86  (mat(1, 2) + mat(2, 1)) / y4,
87  (mat(0, 2) - mat(2, 0)) / y4));
88  }
89 
91  const T z4 = Sqrt(zz * kFour);
93  (mat(0, 2) + mat(2, 0)) / z4,
94  (mat(1, 2) + mat(2, 1)) / z4,
95  z4 / kFour,
96  (mat(1, 0) - mat(0, 1)) / z4));
97 }
98 
99 template <typename T>
101  DCHECK(axis);
102  DCHECK(angle);
103  if (IsIdentity()) {
104  *axis = VectorType(1, 0, 0);
105  *angle = AngleType();
106  } else {
107  DCHECK_NE(quat_[3], static_cast<T>(1));
108  *angle = 2 * ArcCosine(quat_[3]);
109  const T s = static_cast<T>(1) / Sqrt(static_cast<T>(1) - Square(quat_[3]));
110  *axis = VectorType(quat_[0], quat_[1], quat_[2]) * s;
111  }
112 }
113 
114 template <typename T>
116  AngleType* yaw, AngleType* pitch, AngleType* roll) const {
117  DCHECK(yaw);
118  DCHECK(pitch);
119  DCHECK(roll);
120  const T& qx = quat_[0];
121  const T& qy = quat_[1];
122  const T& qz = quat_[2];
123  const T& qw = quat_[3];
124 
125  const T test = qz * qy + qx * qw;
126  if (test > static_cast<T>(0.4999f)) {
129  *yaw = AngleType::FromRadians(static_cast<T>(2. * atan2(qz, qw)));
130  *pitch = AngleType::FromRadians(static_cast<T>(M_PI_2));
131  *roll = AngleType::FromRadians(static_cast<T>(0.));
132  } else if (test < static_cast<T>(-0.4999f)) {
135  *yaw = AngleType::FromRadians(static_cast<T>(-2. * atan2(qz, qw)));
136  *pitch = AngleType::FromRadians(static_cast<T>(-M_PI_2));
137  *roll = AngleType::FromRadians(static_cast<T>(0.));
138  } else {
140  *yaw = AngleType::FromRadians(static_cast<T>(atan2(
141  2. * qy * qw - 2. * qz * qx, 1. - 2. * qy * qy - 2. * qx * qx)));
142  *pitch = AngleType::FromRadians(static_cast<T>(asin(
143  2. * test)));
144  *roll = AngleType::FromRadians(static_cast<T>(atan2(
145  2. * qz * qw - 2. * qy * qx , 1. - 2. * qz * qz - 2. * qx * qx)));
146  }
147 }
148 
149 template <typename T>
151  const VectorType& to) {
152  static const T kTolerance = std::numeric_limits<T>::epsilon() * 100;
153 
156  const T norm_u_norm_v = Sqrt(LengthSquared(from) * LengthSquared(to));
157  T real_part = norm_u_norm_v + Dot(from, to);
158  VectorType w;
159  if (real_part < kTolerance * norm_u_norm_v) {
163  real_part = 0.0;
164  w = (Abs(from[0]) > Abs(from[2])) ?
165  VectorType(-from[1], from[0], 0) :
166  VectorType(0, -from[2], from[1]);
167  } else {
169  w = Cross(from, to);
170  }
171 
174  return Rotation::FromQuaternion(QuaternionType(w[0], w[1], w[2], real_part));
175 }
176 
177 template <typename T>
179  const Rotation& r1, T t) {
180  const QuaternionType& q0 = r0.GetQuaternion();
181  QuaternionType q1 = r1.GetQuaternion();
182  QuaternionType q_result;
183 
186  T dot = Clamp(Dot(q0, q1), static_cast<T>(-1), static_cast<T>(1));
187 
190  if (dot < static_cast<T>(0.0)) {
191  dot = -dot;
192  q1 = -q1;
193  }
194 
196  static const T kMinDotForSlerp = static_cast<T>(1.0 - 1e-5);
197  if (dot > kMinDotForSlerp) {
198  q_result = q0 + t * (q1 - q0);
199  } else {
201  const Angle<T> theta = t * ArcCosine(dot);
202  const QuaternionType q2 = Normalized(q1 - q0 * dot);
203 
205  q_result = q0 * Cosine(theta) + q2 * Sine(theta);
206  }
207  Rotation<T> result;
208  result.SetQuaternion(q_result);
209  return result;
210 }
211 
213 
216 
217 
218 #define ION_INSTANTIATE_ROTATION_FUNCTIONS(type) \
219 template void ION_API Rotation<type>::SetAxisAndAngle( \
220  const Vector<3, type>& axis, const Angle<type>& angle); \
221 template void ION_API Rotation<type>::GetAxisAndAngle( \
222  Vector<3, type>* axis, Angle<type>* angle) const; \
223 template void ION_API Rotation<type>::GetEulerAngles( \
224  Angle<type>* yaw, Angle<type>* pitch, Angle<type>* roll) const; \
225 template Rotation<type> ION_API Rotation<type>::RotateInto( \
226  const Vector<3, type>& from, const Vector<3, type>& to); \
227 template Rotation<type> ION_API Rotation<type>::Slerp( \
228  const Rotation& r0, const Rotation& r1, type t); \
229 template Rotation<type> ION_API Rotation<type>::FromRotationMatrix( \
230  const Matrix<3, type>& mat)
231 
232 ION_INSTANTIATE_ROTATION_FUNCTIONS(double); // NOLINT; thinks it's a function.
233 ION_INSTANTIATE_ROTATION_FUNCTIONS(float); // NOLINT; thinks it's a function.
234 
235 #undef ION_INSTANTIATE_ROTATION_FUNCTIONS
236 
237 } // namespace math
238 } // namespace ion
static Rotation Slerp(const Rotation &r0, const Rotation &r1, T t)
Performs spherical linear interpolation between two Rotation instances.
Definition: rotation.cc:178
bool Normalize(Vector< Dimension, T > *v)
Normalizes a Vector to unit length.
Definition: vectorutils.h:90
ION_INSTANTIATE_ROTATION_FUNCTIONS(double)
#define DCHECK(expr)
Definition: logging.h:331
T Cosine(const ion::math::Angle< T > &angle)
ion::math::Angle specialization of Cosine.
Definition: angleutils.h:80
T Dot(const Vector< Dimension, T > &v0, const Vector< Dimension, T > &v1)
Returns the dot (inner) product of two Vectors.
Definition: vectorutils.h:38
void GetEulerAngles(AngleType *yaw, AngleType *pitch, AngleType *roll) const
Returns the Euler angles which would result in this rotation if done in the order of rotate-Y by yaw...
Definition: rotation.cc:115
T Sqrt(const T &val)
Returns the square root of a value.
Definition: utils.h:59
A simple class to represent angles.
Definition: angle.h:33
static Rotation FromQuaternion(const QuaternionType &quat)
Convienance function that constructs and returns a Rotation given a quaternion.
Definition: rotation.h:94
#define DCHECK_NE(val1, val2)
Definition: logging.h:333
The Matrix class defines a square N-dimensional matrix.
Definition: matrix.h:35
const QuaternionType & GetQuaternion() const
Returns the Rotation as a normalized quaternion (4D vector).
Definition: rotation.h:67
void SetQuaternion(const QuaternionType &quaternion)
Sets the Rotation from a quaternion (4D vector), which is first normalized.
Definition: rotation.h:62
const T Clamp(const T &val, const T &min_val, const T &max_val)
Clamps a value to lie between a minimum and maximum, inclusive.
Definition: utils.h:204
const Vector< Dimension, T > Normalized(const Vector< Dimension, T > &v)
Returns a unit-length version of a Vector.
Definition: vectorutils.h:104
static Rotation FromRotationMatrix(const Matrix< 3, T > &mat)
Convienance function that constructs and returns a Rotation given a rotation matrix R with $R^ R = I ...
Definition: rotation.cc:52
Copyright 2016 Google Inc.
Vector.
Definition: vector.h:180
The Rotation class represents a rotation around a 3-dimensional axis.
Definition: rotation.h:37
Angle< T > ArcCosine(T v)
Returns the inverse cosine of the given value.
Definition: angleutils.h:36
void GetAxisAndAngle(VectorType *axis, AngleType *angle) const
Returns the right-hand rule axis and angle corresponding to the Rotation.
Definition: rotation.cc:100
static Rotation RotateInto(const VectorType &from, const VectorType &to)
Constructs and returns a Rotation that rotates one vector to another along the shortest arc...
Definition: rotation.cc:150
T Sine(const ion::math::Angle< T > &angle)
ion::math::Angle specialization of Sine.
Definition: angleutils.h:86
const T Square(const T &val)
Squares a value.
Definition: utils.h:48
void SetAxisAndAngle(const VectorType &axis, const AngleType &angle)
Sets the Rotation to rotate by the given angle around the given axis, following the right-hand rule...
Definition: rotation.cc:39
Angle< T > AngleType
Convenience typedefs for Angle and 3D vector of the correct type.
Definition: rotation.h:40
const T Abs(const T &val)
Returns the absolute value of a number in a type-safe way.
Definition: utils.h:42
Vector< 3, T > Cross(const Vector< 3, T > &v0, const Vector< 3, T > &v1)
Returns the 3-dimensional cross product of 2 Vectors.
Definition: vectorutils.h:48
T LengthSquared(const Vector< Dimension, T > &v)
Returns the square of the length of a Vector.
Definition: vectorutils.h:64