Quaternion.h
Go to the documentation of this file.
1 /*
2  * Original Copyright (c) 2011-2016 Martin Felis <martin.felis@iwr.uni-heidelberg.de>
3  *
4  *
5  * RDL - Robot Dynamics Library
6  * Modifications Copyright (c) 2017 Jordan Lack <jlack1987@gmail.com>
7  *
8  * Licensed under the zlib license. See LICENSE for more details.
9  */
10 
11 #ifndef __RDL_QUATERNION_H__
12 #define __RDL_QUATERNION_H__
13 
14 #include <cmath>
16 
17 namespace RobotDynamics
18 {
19 namespace Math
20 {
26 {
27  public:
31  Quaternion() : Vector4d(0., 0., 0., 1.)
32  {
33  }
34 
35  // cppcheck-suppress noExplicitConstructor
36  Quaternion(const Eigen::Quaterniond& q) : Quaternion(q.x(), q.y(), q.z(), q.w())
37  {
38  }
39 
40  // cppcheck-suppress noExplicitConstructor
41  Quaternion(const RobotDynamics::Math::Quaternion& q) : Vector4d(q.x(), q.y(), q.z(), q.w())
42  {
43  }
44 
45  // cppcheck-suppress noExplicitConstructor
47  {
48  }
49 
50  // cppcheck-suppress noExplicitConstructor
51  Quaternion(const Vector4d& q) : Vector4d(q)
52  {
53  }
54 
55  // cppcheck-suppress noExplicitConstructor
56  Quaternion(const AxisAngle& axis_angle) : Quaternion(axis_angle.axis(), axis_angle.angle())
57  {
58  }
59 
60  Quaternion(const Vector3d& axis, double angle)
61  {
62  set(axis, angle);
63  }
64 
72  Quaternion(double x, double y, double z, double w) : Vector4d(x, y, z, w)
73  {
74  }
75 
76  EIGEN_STRONG_INLINE double& x()
77  {
78  return this->data()[0];
79  }
80 
81  EIGEN_STRONG_INLINE double x() const
82  {
83  return this->data()[0];
84  }
85 
86  EIGEN_STRONG_INLINE double& y()
87  {
88  return this->data()[1];
89  }
90 
91  EIGEN_STRONG_INLINE double y() const
92  {
93  return this->data()[1];
94  }
95 
96  EIGEN_STRONG_INLINE double& z()
97  {
98  return this->data()[2];
99  }
100 
101  EIGEN_STRONG_INLINE double z() const
102  {
103  return this->data()[2];
104  }
105 
106  EIGEN_STRONG_INLINE double& w()
107  {
108  return this->data()[3];
109  }
110 
111  EIGEN_STRONG_INLINE double w() const
112  {
113  return this->data()[3];
114  }
115 
116  void set(double x, double y, double z, double w)
117  {
118  this->data()[0] = x;
119  this->data()[1] = y;
120  this->data()[2] = z;
121  this->data()[3] = w;
122  }
123 
128  EIGEN_STRONG_INLINE Vector3d vec() const
129  {
130  return Vector3d(this->data()[0], this->data()[1], this->data()[2]);
131  }
132 
138  [[deprecated("Use Quaternion::w() instead")]] EIGEN_STRONG_INLINE double getScalarPart() const { return this->data()[3]; }
139 
140  Quaternion&
141  operator=(const Eigen::Quaterniond& q)
142  {
143  set(q.x(), q.y(), q.z(), q.w());
144  return *this;
145  }
146 
150  void sanitize()
151  {
152  if (!std::signbit(w()))
153  {
154  return;
155  }
156 
157  x() *= -1.0;
158  y() *= -1.0;
159  z() *= -1.0;
160  w() *= -1.0;
161  }
162 
164  {
165  set(q.x(), q.y(), q.z(), q.w());
166  return *this;
167  }
168 
170  {
171  set(q[0], q[1], q[2], q[3]);
172  return *this;
173  }
174 
176  {
177  set(E);
178  return *this;
179  }
180 
181  Quaternion& operator=(const AxisAngle& axis_angle)
182  {
183  set(axis_angle);
184  return *this;
185  }
186 
192  Quaternion operator*(const double& s) const
193  {
194  return Quaternion((*this)[0] * s, (*this)[1] * s, (*this)[2] * s, (*this)[3] * s);
195  }
196 
203  {
204  return Quaternion(
205  (*this)[3] * q[0] + (*this)[0] * q[3] + (*this)[1] * q[2] - (*this)[2] * q[1], (*this)[3] * q[1] + (*this)[1] * q[3] + (*this)[2] * q[0] - (*this)[0] * q[2],
206  (*this)[3] * q[2] + (*this)[2] * q[3] + (*this)[0] * q[1] - (*this)[1] * q[0], (*this)[3] * q[3] - (*this)[0] * q[0] - (*this)[1] * q[1] - (*this)[2] * q[2]);
207  }
208 
215  {
216  set((*this)[3] * q[0] + (*this)[0] * q[3] + (*this)[1] * q[2] - (*this)[2] * q[1], (*this)[3] * q[1] + (*this)[1] * q[3] + (*this)[2] * q[0] - (*this)[0] * q[2],
217  (*this)[3] * q[2] + (*this)[2] * q[3] + (*this)[0] * q[1] - (*this)[1] * q[0], (*this)[3] * q[3] - (*this)[0] * q[0] - (*this)[1] * q[1] - (*this)[2] * q[2]);
218  return *this;
219  }
220 
221  void set(const Matrix3d& E)
222  {
223  *this = toQuaternion(E);
224  }
225 
226  void set(const Quaternion& q)
227  {
228  *this = q;
229  }
230 
231  void set(const AxisAngle& axis_angle)
232  {
233  set(axis_angle.axis(), axis_angle.angle());
234  }
235 
236  void set(Vector3d axis, double angle)
237  {
238  double d = axis.norm();
239  double s2 = std::sin(angle * 0.5) / d;
240  set(axis[0] * s2, axis[1] * s2, axis[2] * s2, std::cos(angle * 0.5));
241  }
242 
244  {
245  *this = toQuaternion(X.E.transpose()) * (*this);
246  }
247 
258  Quaternion slerp(double alpha, const Quaternion& quat) const
259  {
260  // check whether one of the two has 0 length
261  double s = std::sqrt(squaredNorm() * quat.squaredNorm());
262 
263  // division by 0.f is unhealthy!
264  assert(s != 0.);
265 
266  double angle = acos(dot(quat) / s);
267 
268  if ((angle == 0.) || std::isnan(angle))
269  {
270  return *this;
271  }
272  assert(!std::isnan(angle));
273 
274  double d = 1. / std::sin(angle);
275  double p0 = std::sin((1. - alpha) * angle);
276  double p1 = std::sin(alpha * angle);
277 
278  if (dot(quat) < 0.)
279  {
280  return Quaternion(Vector4d(((*this) * p0 - quat * p1) * d));
281  }
282  return Quaternion(Vector4d(((*this) * p0 + quat * p1) * d));
283  }
284 
286  {
287  return Quaternion(-(*this)[0], -(*this)[1], -(*this)[2], (*this)[3]);
288  }
289 
290  Quaternion timeStep(const Vector3d& omega, double dt)
291  {
292  double omega_norm = omega.norm();
293 
294  return fromAxisAngle(omega / omega_norm, dt * omega_norm) * (*this);
295  }
296 
297  Vector3d rotate(const Vector3d& vec) const
298  {
299  Vector3d vn(vec);
300  Quaternion vec_quat(vn[0], vn[1], vn[2], 0.f), res_quat;
301 
302  res_quat = vec_quat * (*this);
303  res_quat = conjugate() * res_quat;
304 
305  return Vector3d(res_quat[0], res_quat[1], res_quat[2]);
306  }
307 
316  void swingTwistDecomposition(const Vector3d& twist_axis, Quaternion& swing, Quaternion& twist)
317  {
318  double u = twist_axis.dot(vec());
319  double n = twist_axis.squaredNorm();
320  double m = w() * n;
321  double l = std::sqrt(std::pow(m, 2) + std::pow(u, 2) * n);
322  twist.set(twist_axis.x() * (u / l), twist_axis.y() * (u / l), twist_axis.z() * (u / l), m / l);
323  swing.set(*this * twist.conjugate());
324  }
325 
326  private:
328  {
329  double trace = mat.trace();
330 
331  if (trace > 0.)
332  {
333  double s = 2. * std::sqrt(trace + 1.);
334  return Quaternion((mat(1, 2) - mat(2, 1)) / s, (mat(2, 0) - mat(0, 2)) / s, (mat(0, 1) - mat(1, 0)) / s, 0.25 * s);
335  }
336  else if ((mat(0, 0) > mat(1, 1)) && (mat(0, 0) > mat(2, 2)))
337  {
338  double s = 2. * std::sqrt(1. + mat(0, 0) - mat(1, 1) - mat(2, 2));
339  return Quaternion(-0.25 * s, (-mat(0, 1) - mat(1, 0)) / s, (-mat(0, 2) - mat(2, 0)) / s, (mat(2, 1) - mat(1, 2)) / s);
340  }
341  else if (mat(1, 1) > mat(2, 2))
342  {
343  double s = 2. * std::sqrt(1. + mat(1, 1) - mat(0, 0) - mat(2, 2));
344  return Quaternion((-mat(0, 1) - mat(1, 0)) / s, -0.25 * s, (-mat(1, 2) - mat(2, 1)) / s, (mat(0, 2) - mat(2, 0)) / s);
345  }
346  else
347  {
348  double s = 2. * std::sqrt(1. + mat(2, 2) - mat(0, 0) - mat(1, 1));
349  return Quaternion((-mat(0, 2) - mat(2, 0)) / s, (-mat(1, 2) - mat(2, 1)) / s, -0.25 * s, (mat(1, 0) - mat(0, 1)) / s);
350  }
351  }
352 
353  Quaternion fromAxisAngle(const Vector3d& axis, double angle_rad)
354  {
355  double d = axis.norm();
356  double s2 = std::sin(angle_rad * 0.5) / d;
357 
358  return Quaternion(axis[0] * s2, axis[1] * s2, axis[2] * s2, std::cos(angle_rad * 0.5));
359  }
360 };
361 } // namespace Math
362 } // namespace RobotDynamics
363 
365 
366 /* __RDL_QUATERNION_H__ */
367 #endif // ifndef __RDL_QUATERNION_H__
EIGEN_STRONG_INLINE double & w()
Definition: Quaternion.h:106
Quaternion timeStep(const Vector3d &omega, double dt)
Definition: Quaternion.h:290
EIGEN_DEFINE_STL_VECTOR_SPECIALIZATION(RobotDynamics::Joint)
Quaternion & operator=(const Matrix3d &E)
Definition: Quaternion.h:175
void swingTwistDecomposition(const Vector3d &twist_axis, Quaternion &swing, Quaternion &twist)
Decompose a quaternion into a swing then twist quaternion where the twist is about the given axis...
Definition: Quaternion.h:316
EIGEN_STRONG_INLINE double y() const
Definition: Quaternion.h:91
Quaternion & operator=(const Eigen::Quaterniond &q)
Definition: Quaternion.h:141
Quaternion(const Eigen::Quaterniond &q)
Definition: Quaternion.h:36
EIGEN_STRONG_INLINE double w() const
Definition: Quaternion.h:111
Quaternion(const Vector4d &q)
Definition: Quaternion.h:51
EIGEN_STRONG_INLINE Vector3d vec() const
Get vector part.
Definition: Quaternion.h:128
void transform(const RobotDynamics::Math::SpatialTransform &X)
Pure virtual object. This object forces objects that inherit from it to have a method that tells how ...
Definition: Quaternion.h:243
Quaternion & operator=(const RobotDynamics::Math::Quaternion &q)
Definition: Quaternion.h:163
EIGEN_STRONG_INLINE double z() const
Definition: Quaternion.h:101
Quaternion toQuaternion(const Matrix3d &mat)
Definition: Quaternion.h:327
The TransformableGeometricObject class is an essential interface because it forces all geometric obje...
Definition: rdl_eigenmath.h:43
Vector3d rotate(const Vector3d &vec) const
Definition: Quaternion.h:297
Compact representation of spatial transformations.
EIGEN_STRONG_INLINE double & y()
Definition: Quaternion.h:86
void sanitize()
sanitize the quaternion by negating each element if the w element is less than zero ...
Definition: Quaternion.h:150
Quaternion that are used for singularity free joints.
Definition: Quaternion.h:25
Quaternion(const Vector3d &axis, double angle)
Definition: Quaternion.h:60
EIGEN_STRONG_INLINE double getScalarPart() const
Get scalar part.
Definition: Quaternion.h:138
Quaternion(double x, double y, double z, double w)
Constructor.
Definition: Quaternion.h:72
EIGEN_STRONG_INLINE double & x()
Definition: Quaternion.h:76
EIGEN_STRONG_INLINE double x() const
Definition: Quaternion.h:81
Quaternion(const RobotDynamics::Math::Matrix3d &E)
Definition: Quaternion.h:46
Quaternion operator*(const double &s) const
Method to scale the elements of a quaternion by a constant. Normalization is NOT performed.
Definition: Quaternion.h:192
EIGEN_STRONG_INLINE Vector4d()
Quaternion slerp(double alpha, const Quaternion &quat) const
From Wikipedia: In computer graphics, Slerp is shorthand for spherical linear interpolation, introduced by Ken Shoemake in the context of quaternion interpolation for the purpose of animating 3D rotation. It refers to constant-speed motion along a unit-radius great circle arc, given the ends and an interpolation parameter between 0 and 1.
Definition: Quaternion.h:258
Quaternion(const AxisAngle &axis_angle)
Definition: Quaternion.h:56
EIGEN_STRONG_INLINE double & z()
Definition: Quaternion.h:96
Quaternion operator*(const Quaternion &q) const
Quaternion multiplication.
Definition: Quaternion.h:202
Quaternion conjugate() const
Definition: Quaternion.h:285
void set(double x, double y, double z, double w)
Definition: Quaternion.h:116
Quaternion & operator=(const Vector4d &q)
Definition: Quaternion.h:169
Eigen::AngleAxisd AxisAngle
Definition: rdl_eigenmath.h:27
Quaternion & operator=(const AxisAngle &axis_angle)
Definition: Quaternion.h:181
Namespace for all structures of the RobotDynamics library.
Definition: Body.h:21
Quaternion fromAxisAngle(const Vector3d &axis, double angle_rad)
Definition: Quaternion.h:353
Quaternion(const RobotDynamics::Math::Quaternion &q)
Definition: Quaternion.h:41
Quaternion & operator*=(const Quaternion &q)
Overloaded *= operator for quaternion multiplication.
Definition: Quaternion.h:214


rdl_dynamics
Author(s):
autogenerated on Tue Apr 20 2021 02:25:27