Rigid Body Dynamics Library
Quaternion.h
Go to the documentation of this file.
1/*
2 * RBDL - Rigid Body Dynamics Library
3 * Copyright (c) 2011-2018 Martin Felis <martin@fysx.org>
4 *
5 * Licensed under the zlib license. See LICENSE for more details.
6 */
7
8#ifndef RBDL_QUATERNION_H
9#define RBDL_QUATERNION_H
10
11//#include <cmath>
12#include <assert.h>
13
14namespace RigidBodyDynamics {
15
16namespace Math {
17
22class Quaternion : public Vector4d {
23 public:
25 Vector4d (0., 0., 0., 1.)
26 {}
27 Quaternion (const Vector4d &vec4) :
28 Vector4d (vec4)
29 {}
31 Vector4d (x, y, z, w)
32 {}
33 Quaternion operator* (const double &s) const {
34 return Quaternion (
35 (*this)[0] * s,
36 (*this)[1] * s,
37 (*this)[2] * s,
38 (*this)[3] * s
39 );
40 }
43 return Quaternion (
44 (*this)[3] * q[0] + (*this)[0] * q[3] + (*this)[1] * q[2] - (*this)[2] * q[1],
45 (*this)[3] * q[1] + (*this)[1] * q[3] + (*this)[2] * q[0] - (*this)[0] * q[2],
46 (*this)[3] * q[2] + (*this)[2] * q[3] + (*this)[0] * q[1] - (*this)[1] * q[0],
47 (*this)[3] * q[3] - (*this)[0] * q[0] - (*this)[1] * q[1] - (*this)[2] * q[2]
48 );
49 }
51 set (
52 (*this)[3] * q[0] + (*this)[0] * q[3] + (*this)[1] * q[2] - (*this)[2] * q[1],
53 (*this)[3] * q[1] + (*this)[1] * q[3] + (*this)[2] * q[0] - (*this)[0] * q[2],
54 (*this)[3] * q[2] + (*this)[2] * q[3] + (*this)[0] * q[1] - (*this)[1] * q[0],
55 (*this)[3] * q[3] - (*this)[0] * q[0] - (*this)[1] * q[1] - (*this)[2] * q[2]
56 );
57 return *this;
58 }
59
60 static Quaternion fromGLRotate (double angle, double x, double y, double z) {
61 double st = std::sin (angle * M_PI / 360.);
62 return Quaternion (
63 st * x,
64 st * y,
65 st * z,
66 std::cos (angle * M_PI / 360.)
67 );
68 }
69
70 Quaternion slerp (double alpha, const Quaternion &quat) const {
71 // check whether one of the two has 0 length
72 Scalar s = std::sqrt (squaredNorm() * quat.squaredNorm());
73
74 // division by 0.f is unhealthy
75 #ifndef RBDL_USE_CASADI_MATH
76 assert (s != 0.);
77 #endif
78
79 Scalar angle = acos (dot(quat) / s);
80#ifndef RBDL_USE_CASADI_MATH
81 if (angle == 0. || std::isnan(angle)) {
82 return *this;
83 }
84 assert(!std::isnan(angle));
85#endif
86
87 Scalar d = 1. / std::sin (angle);
88 Scalar p0 = std::sin ((1. - alpha) * angle);
89 Scalar p1 = std::sin (alpha * angle);
90
91#ifdef RBDL_USE_CASADI_MATH
92 return Quaternion (casadi::MX::if_else(casadi::MX::lt(dot (quat), 0.),
93 Quaternion( ((*this) * p0 - quat * p1) * d),
94 Quaternion( ((*this) * p0 + quat * p1) * d)) );
95#else
96 if (dot (quat) < 0.) {
97 return Quaternion( ((*this) * p0 - quat * p1) * d);
98 } else {
99 return Quaternion( ((*this) * p0 + quat * p1) * d);
100 }
101#endif
102 }
103
104 static Quaternion fromAxisAngle (const Vector3d &axis, Scalar angle_rad) {
105 Scalar d = axis.norm();
106 Scalar s2 = std::sin (angle_rad * 0.5) / d;
107 return Quaternion (
108 axis[0] * s2,
109 axis[1] * s2,
110 axis[2] * s2,
111 std::cos(angle_rad * 0.5)
112 );
113 }
114
115 static Quaternion fromMatrix (const Matrix3d &mat) {
116 Scalar w = std::sqrt (1. + mat(0,0) + mat(1,1) + mat(2,2)) * 0.5;
117 return Quaternion (
118 (mat(1,2) - mat(2,1)) / (w * 4.),
119 (mat(2,0) - mat(0,2)) / (w * 4.),
120 (mat(0,1) - mat(1,0)) / (w * 4.),
121 w);
122 }
123
124 static Quaternion fromZYXAngles (const Vector3d &zyx_angles) {
125 return Quaternion::fromAxisAngle (Vector3d (0., 0., 1.), zyx_angles[0])
126 * Quaternion::fromAxisAngle (Vector3d (0., 1., 0.), zyx_angles[1])
127 * Quaternion::fromAxisAngle (Vector3d (1., 0., 0.), zyx_angles[2]);
128 }
129
130 static Quaternion fromYXZAngles (const Vector3d &yxz_angles) {
131 return Quaternion::fromAxisAngle (Vector3d (0., 1., 0.), yxz_angles[0])
132 * Quaternion::fromAxisAngle (Vector3d (1., 0., 0.), yxz_angles[1])
133 * Quaternion::fromAxisAngle (Vector3d (0., 0., 1.), yxz_angles[2]);
134 }
135
136 static Quaternion fromXYZAngles (const Vector3d &xyz_angles) {
137 return Quaternion::fromAxisAngle (Vector3d (0., 0., 01.), xyz_angles[2])
138 * Quaternion::fromAxisAngle (Vector3d (0., 1., 0.), xyz_angles[1])
139 * Quaternion::fromAxisAngle (Vector3d (1., 0., 0.), xyz_angles[0]);
140 }
141
143 Scalar x = (*this)[0];
144 Scalar y = (*this)[1];
145 Scalar z = (*this)[2];
146 Scalar w = (*this)[3];
147 return Matrix3d (
148 1 - 2*y*y - 2*z*z,
149 2*x*y + 2*w*z,
150 2*x*z - 2*w*y,
151
152 2*x*y - 2*w*z,
153 1 - 2*x*x - 2*z*z,
154 2*y*z + 2*w*x,
155
156 2*x*z + 2*w*y,
157 2*y*z - 2*w*x,
158 1 - 2*x*x - 2*y*y
159
160 /*
161 1 - 2*y*y - 2*z*z,
162 2*x*y - 2*w*z,
163 2*x*z + 2*w*y,
164
165 2*x*y + 2*w*z,
166 1 - 2*x*x - 2*z*z,
167 2*y*z - 2*w*x,
168
169 2*x*z - 2*w*y,
170 2*y*z + 2*w*x,
171 1 - 2*x*x - 2*y*y
172 */
173 );
174 }
175
177 return Quaternion (
178 -(*this)[0],
179 -(*this)[1],
180 -(*this)[2],
181 (*this)[3]);
182 }
183
184 Quaternion timeStep (const Vector3d &omega, double dt) {
185 Scalar omega_norm = omega.norm();
186 return Quaternion::fromAxisAngle (omega / omega_norm, dt * omega_norm) * (*this);
187 }
188
189 Vector3d rotate (const Vector3d &vec) const {
190 Vector3d vn (vec);
191 Quaternion vec_quat (vn[0], vn[1], vn[2], 0.f), res_quat;
192
193 res_quat = vec_quat * (*this);
194 res_quat = conjugate() * res_quat;
195
196 return Vector3d (res_quat[0], res_quat[1], res_quat[2]);
197 }
198
208 Vector4d omegaToQDot(const Vector3d& omega) const {
210 m(0, 0) = (*this)[3]; m(0, 1) = -(*this)[2]; m(0, 2) = (*this)[1];
211 m(1, 0) = (*this)[2]; m(1, 1) = (*this)[3]; m(1, 2) = -(*this)[0];
212 m(2, 0) = -(*this)[1]; m(2, 1) = (*this)[0]; m(2, 2) = (*this)[3];
213 m(3, 0) = -(*this)[0]; m(3, 1) = -(*this)[1]; m(3, 2) = -(*this)[2];
214 return Quaternion(0.5 * m * omega);
215 }
216};
217
218}
219
220}
221
222/* RBDL_QUATERNION_H */
223#endif
Quaternion that are used for singularity free joints.
Definition: Quaternion.h:22
Vector4d omegaToQDot(const Vector3d &omega) const
Converts a 3d angular velocity vector into a 4d derivative of the components of the quaternion.
Definition: Quaternion.h:208
Quaternion timeStep(const Vector3d &omega, double dt)
Definition: Quaternion.h:184
static Quaternion fromYXZAngles(const Vector3d &yxz_angles)
Definition: Quaternion.h:130
Quaternion(Scalar x, Scalar y, Scalar z, Scalar w)
Definition: Quaternion.h:30
static Quaternion fromAxisAngle(const Vector3d &axis, Scalar angle_rad)
Definition: Quaternion.h:104
static Quaternion fromXYZAngles(const Vector3d &xyz_angles)
Definition: Quaternion.h:136
Quaternion & operator*=(const Quaternion &q)
Definition: Quaternion.h:50
static Quaternion fromMatrix(const Matrix3d &mat)
Definition: Quaternion.h:115
Vector3d rotate(const Vector3d &vec) const
Definition: Quaternion.h:189
static Quaternion fromZYXAngles(const Vector3d &zyx_angles)
Definition: Quaternion.h:124
Quaternion operator*(const double &s) const
Definition: Quaternion.h:33
Quaternion slerp(double alpha, const Quaternion &quat) const
Definition: Quaternion.h:70
Quaternion(const Vector4d &vec4)
Definition: Quaternion.h:27
static Quaternion fromGLRotate(double angle, double x, double y, double z)
Definition: Quaternion.h:60
void set(const double &v0, const double &v1, const double &v2, const double &v3)
bool isnan(const casadi::MX &x)
Definition: MX_Xd_utils.h:366
MX_Xd_scalar sqrt(const MX_Xd_scalar &x)
Definition: MX_Xd_utils.h:342
MX_Xd_scalar acos(const MX_Xd_scalar &x)
Definition: MX_Xd_utils.h:354
MX_Xd_scalar cos(const MX_Xd_scalar &x)
Definition: MX_Xd_utils.h:351
MX_Xd_scalar sin(const MX_Xd_scalar &x)
Definition: MX_Xd_utils.h:345