QuaternionTests.cpp
Go to the documentation of this file.
1 //
2 // Created by jordan on 4/20/17.
3 //
4 
5 #include <gtest/gtest.h>
6 #include <Eigen/Dense>
9 #include "UnitTestUtils.hpp"
10 
11 struct QuaternionFixture : public testing::Test
12 {
14  {
15  f = Eigen::IOFormat(Eigen::FullPrecision);
16  }
17 
18  Eigen::IOFormat f;
19 };
20 
22 {
23  RobotDynamics::Math::Quaternion q1(0.1, 0.2, 0.3, 0.4);
24  RobotDynamics::Math::Quaternion q2(-0.1, -0.2, -0.3, -0.4);
25  q1.normalize();
26  q2.normalize();
27  q2.sanitize();
28 
29  EXPECT_TRUE(q1.isApprox(q2, 1.e-12));
30 
31  RobotDynamics::Math::Quaternion q3(0.1, 0.2, 0.3, 0.4);
32  RobotDynamics::Math::Quaternion q4(0.1, 0.2, 0.3, 0.4);
33 
34  q3.normalize();
35  q4.normalize();
36  q4.sanitize();
37 
38  EXPECT_TRUE(q3.isApprox(q4, 1.e-12));
39 }
40 
41 TEST_F(QuaternionFixture, EigenConversion)
42 {
44  Eigen::Quaterniond q_eig(1., 2., 3., 4.);
45 
46  EXPECT_EQ(q.x(), 0.);
47  EXPECT_EQ(q.y(), 0.);
48  EXPECT_EQ(q.z(), 0.);
49  EXPECT_EQ(q.w(), 1.);
50 
51  q = q_eig;
52 
53  EXPECT_EQ(q.x(), 2.);
54  EXPECT_EQ(q.y(), 3.);
55  EXPECT_EQ(q.z(), 4.);
56  EXPECT_EQ(q.w(), 1.);
57 }
58 
60 {
61  RobotDynamics::Math::Vector3d v(-0.1, -0.2, 0.3);
62  v.normalize();
66 
67  EXPECT_NEAR(aa1.angle(), aa2.angle(), unit_test_utils::TEST_PREC);
68  EXPECT_TRUE(aa1.axis().isApprox(aa2.axis()));
69 
72  EXPECT_TRUE(o2.isApprox(o1, unit_test_utils::TEST_PREC));
73 }
74 
75 TEST_F(QuaternionFixture, element_accessors)
76 {
77  RobotDynamics::Math::Quaternion q1(0.2, 0.3, 0.4, 0.1);
78 
79  q1.x() = 1.1;
80  q1.y() = 2.1;
81  q1.z() = 3.1;
82  q1.w() = 4.1;
83 
84  EXPECT_EQ(1.1, q1.x());
85  EXPECT_EQ(2.1, q1.y());
86  EXPECT_EQ(3.1, q1.z());
87  EXPECT_EQ(4.1, q1.w());
88 
90  EXPECT_EQ(q1.w(), 4.1);
91 }
92 
93 TEST_F(QuaternionFixture, multiplication)
94 {
95  RobotDynamics::Math::Quaternion q1(0.2, 0.3, 0.4, 0.1), q2(0.2, 0.1, 0.5, 0.3);
96  q1.normalize();
97  q2.normalize();
98 
99  RobotDynamics::Math::Quaternion q_exp(0.5554700788944518, 0.2338821384818745, 0.3800584750330459, -0.7016464154456233);
100 
102 
103  q1 *= q2;
104 
106 }
107 
109 {
110  RobotDynamics::Math::Quaternion q1(0.2, 0.3, 0.4, 0.1), q2(0.2, 0.1, 0.5, 0.3);
111  q1.normalize();
112  q2.normalize();
113 
114  RobotDynamics::Math::Quaternion q_exp(0.3633161731320073, 0.4782736431579663, 0.7599826545340369, 0.2483587031060483);
115 
117 
118  q1 = q1 * -1.;
119  q2 = q2 * -1.;
120 
121  EXPECT_TRUE(unit_test_utils::checkVector4dEpsilonClose(q_exp * -1., q1.slerp(0.2, q2), unit_test_utils::TEST_PREC));
122 
123  q1 = q1 * -1.;
124  q2 = q2 * -1.;
125 
127 }
128 
130 {
131  RobotDynamics::Math::Quaternion q(0.1, 0.2, -0.3, -0.4);
133 }
134 
136 {
137  RobotDynamics::Math::Quaternion q1(0.1, 0.2, -0.3, -0.4), q2(-0.1, -0.3, -0.2, 0.);
138  RobotDynamics::Math::Vector3d v(-0.1, -0.3, -0.2);
139  q1.normalize();
140 
141  RobotDynamics::Math::Quaternion q_exp = q1.conjugate() * q2 * q1;
142  RobotDynamics::Math::Vector3d v_out = q1.rotate(v);
143 
144  EXPECT_NEAR(v_out.x(), q_exp.x(), unit_test_utils::TEST_PREC);
145  EXPECT_NEAR(v_out.y(), q_exp.y(), unit_test_utils::TEST_PREC);
146  EXPECT_NEAR(v_out.z(), q_exp.z(), unit_test_utils::TEST_PREC);
147 }
148 
149 TEST_F(QuaternionFixture, swingTwistDecomposition)
150 {
151  double thx = M_PI / 4.;
152  double thy = M_PI / 3.;
153  double thz = -M_PI / 6.;
154 
155  RobotDynamics::Math::Quaternion qx(std::sin(thx / 2.), 0., 0., std::cos(thx / 2.)), qy(0., std::sin(thy / 2.), 0., std::cos(thy / 2.)),
156  qz(0., 0., std::sin(thz / 2.), std::cos(thz / 2.));
157  RobotDynamics::Math::Quaternion q = qx * qy * qz;
158  RobotDynamics::Math::Quaternion q_twist, q_swing;
159 
160  q.swingTwistDecomposition(Vector3d(0., 0., 1.), q_swing, q_twist);
161  EXPECT_TRUE(q.isApprox(q_swing * q_twist, 1.e-10));
162 
163  q.swingTwistDecomposition(Vector3d(0., 1., 0.), q_swing, q_twist);
164  EXPECT_TRUE(q.isApprox(q_swing * q_twist, 1.e-10));
165 
166  q.swingTwistDecomposition(Vector3d(1., 0., 0.), q_swing, q_twist);
167  EXPECT_TRUE(q.isApprox(q_swing * q_twist, 1.e-10));
168 
169  q = qz * qy * qx;
170 
171  q.swingTwistDecomposition(Vector3d(0., 0., 1.), q_swing, q_twist);
172  EXPECT_TRUE(q.isApprox(q_swing * q_twist, 1.e-10));
173 
174  q.swingTwistDecomposition(Vector3d(0., 1., 0.), q_swing, q_twist);
175  EXPECT_TRUE(q.isApprox(q_swing * q_twist, 1.e-10));
176 
177  q.swingTwistDecomposition(Vector3d(1., 0., 0.), q_swing, q_twist);
178  EXPECT_TRUE(q.isApprox(q_swing * q_twist, 1.e-10));
179 }
180 
181 TEST_F(QuaternionFixture, swingTwistDecompositionEdgeCases)
182 {
183  RobotDynamics::Math::Quaternion q(0., 0., 0., 1);
184  RobotDynamics::Math::Quaternion q_twist, q_swing;
185 
186  q.swingTwistDecomposition(Vector3d(0., 0., 1.), q_swing, q_twist);
187 
188  EXPECT_TRUE(q.isApprox(q_swing * q_twist, 1.e-10));
189 
190  q.set(0., 0., 0., -1);
191  q.swingTwistDecomposition(Vector3d(0., 1., 0.), q_swing, q_twist);
192 
193  EXPECT_TRUE(q.isApprox(q_swing * q_twist, 1.e-10));
194 
195  q.set(0., 0., 0., -1);
196  q.swingTwistDecomposition(Vector3d(1., 0., 0.), q_swing, q_twist);
197 
198  EXPECT_TRUE(q.isApprox(q_swing * q_twist, 1.e-10));
199 }
200 
201 int main(int argc, char** argv)
202 {
203  ::testing::InitGoogleTest(&argc, argv);
204  return RUN_ALL_TESTS();
205 }
EIGEN_STRONG_INLINE double & w()
Definition: Quaternion.h:106
int main(int argc, char **argv)
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
const double TEST_PREC
EIGEN_STRONG_INLINE Vector3d vec() const
Get vector part.
Definition: Quaternion.h:128
static bool checkVector4dEpsilonClose(const RobotDynamics::Math::Vector4d &v1, const RobotDynamics::Math::Vector4d &v2, const double epsilon)
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
TEST_F(QuaternionFixture, Sanitize)
EIGEN_STRONG_INLINE double & x()
Definition: Quaternion.h:76
static bool checkVector3dEpsilonClose(const RobotDynamics::Math::Vector3d &v1, const RobotDynamics::Math::Vector3d &v2, const double epsilon)
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
EIGEN_STRONG_INLINE double & z()
Definition: Quaternion.h:96
Quaternion conjugate() const
Definition: Quaternion.h:285
void set(double x, double y, double z, double w)
Definition: Quaternion.h:116
Eigen::AngleAxisd AxisAngle
Definition: rdl_eigenmath.h:27
Eigen::IOFormat f
SpatialTransform Xrot(double angle_rad, const Vector3d &axis)
Get spatial transform from angle and axis.
static AxisAngle toAxisAngle(Quaternion q)
Get axis angle representation of a quaternion.


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