GCC Code Coverage Report


Directory: ./
File: unittest/joint-spherical.cpp
Date: 2024-08-27 18:20:05
Exec Total Coverage
Lines: 0 158 0.0%
Branches: 0 1350 0.0%

Line Branch Exec Source
1 //
2 // Copyright (c) 2015-2020 CNRS INRIA
3 // Copyright (c) 2015 Wandercraft, 86 rue de Paris 91400 Orsay, France.
4 //
5
6 #include "pinocchio/math/fwd.hpp"
7 #include "pinocchio/multibody/joint/joints.hpp"
8 #include "pinocchio/algorithm/rnea.hpp"
9 #include "pinocchio/algorithm/aba.hpp"
10 #include "pinocchio/algorithm/crba.hpp"
11 #include "pinocchio/algorithm/jacobian.hpp"
12 #include "pinocchio/algorithm/compute-all-terms.hpp"
13
14 #include <boost/test/unit_test.hpp>
15 #include <iostream>
16
17 using namespace pinocchio;
18
19 template<typename D>
20 void addJointAndBody(
21 Model & model,
22 const JointModelBase<D> & jmodel,
23 const Model::JointIndex parent_id,
24 const SE3 & joint_placement,
25 const std::string & joint_name,
26 const Inertia & Y)
27 {
28 Model::JointIndex idx;
29
30 idx = model.addJoint(parent_id, jmodel, joint_placement, joint_name);
31 model.appendBodyToJoint(idx, Y);
32 }
33
34 BOOST_AUTO_TEST_SUITE(JointSpherical)
35
36 BOOST_AUTO_TEST_CASE(spatial)
37 {
38 SE3 M(SE3::Random());
39 Motion v(Motion::Random());
40
41 MotionSpherical mp(MotionSpherical::Vector3(1., 2., 3.));
42 Motion mp_dense(mp);
43
44 BOOST_CHECK(M.act(mp).isApprox(M.act(mp_dense)));
45 BOOST_CHECK(M.actInv(mp).isApprox(M.actInv(mp_dense)));
46
47 BOOST_CHECK(v.cross(mp).isApprox(v.cross(mp_dense)));
48 }
49
50 BOOST_AUTO_TEST_CASE(vsFreeFlyer)
51 {
52 using namespace pinocchio;
53 typedef SE3::Vector3 Vector3;
54 typedef Eigen::Matrix<double, 6, 1> Vector6;
55 typedef Eigen::Matrix<double, 7, 1> VectorFF;
56 typedef SE3::Matrix3 Matrix3;
57
58 Model modelSpherical, modelFreeflyer;
59
60 Inertia inertia(1., Vector3(0.5, 0., 0.0), Matrix3::Identity());
61 SE3 pos(1);
62 pos.translation() = SE3::LinearType(1., 0., 0.);
63
64 addJointAndBody(modelSpherical, JointModelSpherical(), 0, pos, "spherical", inertia);
65 addJointAndBody(modelFreeflyer, JointModelFreeFlyer(), 0, pos, "free-flyer", inertia);
66
67 Data dataSpherical(modelSpherical);
68 Data dataFreeFlyer(modelFreeflyer);
69
70 Eigen::VectorXd q = Eigen::VectorXd::Ones(modelSpherical.nq);
71 q.normalize();
72 VectorFF qff;
73 qff << 0, 0, 0, q[0], q[1], q[2], q[3];
74 Eigen::VectorXd v = Eigen::VectorXd::Ones(modelSpherical.nv);
75 Vector6 vff;
76 vff << 0, 0, 0, 1, 1, 1;
77 Eigen::VectorXd tauSpherical = Eigen::VectorXd::Ones(modelSpherical.nv);
78 Eigen::VectorXd tauff;
79 tauff.resize(7);
80 tauff << 0, 0, 0, 1, 1, 1, 1;
81 Eigen::VectorXd aSpherical = Eigen::VectorXd::Ones(modelSpherical.nv);
82 Eigen::VectorXd aff(vff);
83
84 forwardKinematics(modelSpherical, dataSpherical, q, v);
85 forwardKinematics(modelFreeflyer, dataFreeFlyer, qff, vff);
86
87 computeAllTerms(modelSpherical, dataSpherical, q, v);
88 computeAllTerms(modelFreeflyer, dataFreeFlyer, qff, vff);
89
90 BOOST_CHECK(dataFreeFlyer.oMi[1].isApprox(dataSpherical.oMi[1]));
91 BOOST_CHECK(dataFreeFlyer.liMi[1].isApprox(dataSpherical.liMi[1]));
92 BOOST_CHECK(dataFreeFlyer.Ycrb[1].matrix().isApprox(dataSpherical.Ycrb[1].matrix()));
93 BOOST_CHECK(dataFreeFlyer.f[1].toVector().isApprox(dataSpherical.f[1].toVector()));
94
95 Eigen::VectorXd nle_expected_ff(3);
96 nle_expected_ff << dataFreeFlyer.nle[3], dataFreeFlyer.nle[4], dataFreeFlyer.nle[5];
97 BOOST_CHECK(nle_expected_ff.isApprox(dataSpherical.nle));
98 BOOST_CHECK(dataFreeFlyer.com[0].isApprox(dataSpherical.com[0]));
99
100 // InverseDynamics == rnea
101 tauSpherical = rnea(modelSpherical, dataSpherical, q, v, aSpherical);
102 tauff = rnea(modelFreeflyer, dataFreeFlyer, qff, vff, aff);
103
104 Vector3 tau_expected;
105 tau_expected << tauff(3), tauff(4), tauff(5);
106 BOOST_CHECK(tauSpherical.isApprox(tau_expected));
107
108 // ForwardDynamics == aba
109 Eigen::VectorXd aAbaSpherical =
110 aba(modelSpherical, dataSpherical, q, v, tauSpherical, Convention::WORLD);
111 Eigen::VectorXd aAbaFreeFlyer =
112 aba(modelFreeflyer, dataFreeFlyer, qff, vff, tauff, Convention::WORLD);
113 Vector3 a_expected;
114 a_expected << aAbaFreeFlyer[3], aAbaFreeFlyer[4], aAbaFreeFlyer[5];
115 BOOST_CHECK(aAbaSpherical.isApprox(a_expected));
116
117 // crba
118 crba(modelSpherical, dataSpherical, q, Convention::WORLD);
119 crba(modelFreeflyer, dataFreeFlyer, qff, Convention::WORLD);
120
121 Eigen::Matrix<double, 3, 3> M_expected(dataFreeFlyer.M.bottomRightCorner<3, 3>());
122
123 BOOST_CHECK(dataSpherical.M.isApprox(M_expected));
124
125 // Jacobian
126 Eigen::Matrix<double, 6, Eigen::Dynamic> jacobian_planar;
127 jacobian_planar.resize(6, 3);
128 jacobian_planar.setZero();
129 Eigen::Matrix<double, 6, Eigen::Dynamic> jacobian_ff;
130 jacobian_ff.resize(6, 6);
131 jacobian_ff.setZero();
132 computeJointJacobians(modelSpherical, dataSpherical, q);
133 computeJointJacobians(modelFreeflyer, dataFreeFlyer, qff);
134 getJointJacobian(modelSpherical, dataSpherical, 1, LOCAL, jacobian_planar);
135 getJointJacobian(modelFreeflyer, dataFreeFlyer, 1, LOCAL, jacobian_ff);
136
137 Eigen::Matrix<double, 6, 3> jacobian_expected;
138 jacobian_expected << jacobian_ff.col(3), jacobian_ff.col(4), jacobian_ff.col(5);
139
140 BOOST_CHECK(jacobian_planar.isApprox(jacobian_expected));
141 }
142 BOOST_AUTO_TEST_SUITE_END()
143
144 BOOST_AUTO_TEST_SUITE(JointSphericalZYX)
145
146 BOOST_AUTO_TEST_CASE(spatial)
147 {
148 SE3 M(SE3::Random());
149 Motion v(Motion::Random());
150
151 MotionSpherical mp(MotionSpherical::Vector3(1., 2., 3.));
152 Motion mp_dense(mp);
153
154 BOOST_CHECK(M.act(mp).isApprox(M.act(mp_dense)));
155 BOOST_CHECK(M.actInv(mp).isApprox(M.actInv(mp_dense)));
156
157 BOOST_CHECK(v.cross(mp).isApprox(v.cross(mp_dense)));
158 }
159
160 BOOST_AUTO_TEST_CASE(vsFreeFlyer)
161 {
162 // WARNIG : Dynamic algorithm's results cannot be compared to FreeFlyer's ones because
163 // of the representation of the rotation and the ConstraintSubspace difference.
164 using namespace pinocchio;
165 typedef SE3::Vector3 Vector3;
166 typedef Eigen::Matrix<double, 6, 1> Vector6;
167 typedef Eigen::Matrix<double, 7, 1> VectorFF;
168 typedef SE3::Matrix3 Matrix3;
169
170 Model modelSphericalZYX, modelFreeflyer;
171
172 Inertia inertia(1., Vector3(0.5, 0., 0.0), Matrix3::Identity());
173 SE3 pos(1);
174 pos.translation() = SE3::LinearType(1., 0., 0.);
175
176 addJointAndBody(modelSphericalZYX, JointModelSphericalZYX(), 0, pos, "spherical-zyx", inertia);
177 addJointAndBody(modelFreeflyer, JointModelFreeFlyer(), 0, pos, "free-flyer", inertia);
178
179 Data dataSphericalZYX(modelSphericalZYX);
180 Data dataFreeFlyer(modelFreeflyer);
181
182 Eigen::AngleAxisd rollAngle(1, Eigen::Vector3d::UnitZ());
183 Eigen::AngleAxisd yawAngle(1, Eigen::Vector3d::UnitY());
184 Eigen::AngleAxisd pitchAngle(1, Eigen::Vector3d::UnitX());
185 Eigen::Quaterniond q_sph = rollAngle * yawAngle * pitchAngle;
186
187 Eigen::VectorXd q = Eigen::VectorXd::Ones(modelSphericalZYX.nq);
188 VectorFF qff;
189 qff << 0, 0, 0, q_sph.x(), q_sph.y(), q_sph.z(), q_sph.w();
190 Eigen::VectorXd v = Eigen::VectorXd::Ones(modelSphericalZYX.nv);
191 Vector6 vff;
192 vff << 0, 0, 0, 1, 1, 1;
193 Eigen::VectorXd tauSpherical = Eigen::VectorXd::Ones(modelSphericalZYX.nv);
194 Eigen::VectorXd tauff;
195 tauff.resize(6);
196 tauff << 0, 0, 0, 1, 1, 1;
197 Eigen::VectorXd aSpherical = Eigen::VectorXd::Ones(modelSphericalZYX.nv);
198 Eigen::VectorXd aff(vff);
199
200 forwardKinematics(modelSphericalZYX, dataSphericalZYX, q, v);
201 forwardKinematics(modelFreeflyer, dataFreeFlyer, qff, vff);
202
203 computeAllTerms(modelSphericalZYX, dataSphericalZYX, q, v);
204 computeAllTerms(modelFreeflyer, dataFreeFlyer, qff, vff);
205
206 BOOST_CHECK(dataFreeFlyer.oMi[1].isApprox(dataSphericalZYX.oMi[1]));
207 BOOST_CHECK(dataFreeFlyer.liMi[1].isApprox(dataSphericalZYX.liMi[1]));
208 BOOST_CHECK(dataFreeFlyer.Ycrb[1].matrix().isApprox(dataSphericalZYX.Ycrb[1].matrix()));
209
210 BOOST_CHECK(dataFreeFlyer.com[0].isApprox(dataSphericalZYX.com[0]));
211 }
212
213 BOOST_AUTO_TEST_CASE(test_rnea)
214 {
215 using namespace pinocchio;
216 typedef SE3::Vector3 Vector3;
217 typedef SE3::Matrix3 Matrix3;
218
219 Model model;
220 Inertia inertia(1., Vector3(0.5, 0., 0.0), Matrix3::Identity());
221
222 addJointAndBody(
223 model, JointModelSphericalZYX(), model.getJointId("universe"), SE3::Identity(), "root",
224 inertia);
225
226 Data data(model);
227
228 Eigen::VectorXd q = Eigen::VectorXd::Zero(model.nq);
229 Eigen::VectorXd v = Eigen::VectorXd::Zero(model.nv);
230 Eigen::VectorXd a = Eigen::VectorXd::Zero(model.nv);
231
232 rnea(model, data, q, v, a);
233 Vector3 tau_expected(0., -4.905, 0.);
234
235 BOOST_CHECK(tau_expected.isApprox(data.tau, 1e-14));
236
237 q = Eigen::VectorXd::Ones(model.nq);
238 v = Eigen::VectorXd::Ones(model.nv);
239 a = Eigen::VectorXd::Ones(model.nv);
240
241 rnea(model, data, q, v, a);
242 tau_expected << -0.53611600195085, -0.74621832606188, -0.38177329067604;
243
244 BOOST_CHECK(tau_expected.isApprox(data.tau, 1e-12));
245
246 q << 3, 2, 1;
247 v = Eigen::VectorXd::Ones(model.nv);
248 a = Eigen::VectorXd::Ones(model.nv);
249
250 rnea(model, data, q, v, a);
251 tau_expected << 0.73934458094049, 2.7804530848031, 0.50684940972146;
252
253 BOOST_CHECK(tau_expected.isApprox(data.tau, 1e-12));
254 }
255
256 BOOST_AUTO_TEST_CASE(test_crba)
257 {
258 using namespace pinocchio;
259 using namespace std;
260 typedef SE3::Vector3 Vector3;
261 typedef SE3::Matrix3 Matrix3;
262
263 Model model;
264 Inertia inertia(1., Vector3(0.5, 0., 0.0), Matrix3::Identity());
265
266 addJointAndBody(
267 model, JointModelSphericalZYX(), model.getJointId("universe"), SE3::Identity(), "root",
268 inertia);
269
270 Data data(model);
271
272 Eigen::VectorXd q(Eigen::VectorXd::Zero(model.nq));
273 Eigen::MatrixXd M_expected(model.nv, model.nv);
274
275 crba(model, data, q, Convention::WORLD);
276 M_expected << 1.25, 0, 0, 0, 1.25, 0, 0, 0, 1;
277
278 BOOST_CHECK(M_expected.isApprox(data.M, 1e-14));
279
280 q = Eigen::VectorXd::Ones(model.nq);
281
282 crba(model, data, q, Convention::WORLD);
283 M_expected << 1.0729816454316, -5.5511151231258e-17, -0.8414709848079, -5.5511151231258e-17, 1.25,
284 0, -0.8414709848079, 0, 1;
285
286 BOOST_CHECK(M_expected.isApprox(data.M, 1e-12));
287
288 q << 3, 2, 1;
289
290 crba(model, data, q, Convention::WORLD);
291 M_expected << 1.043294547392, 2.7755575615629e-17, -0.90929742682568, 0, 1.25, 0,
292 -0.90929742682568, 0, 1;
293
294 BOOST_CHECK(M_expected.isApprox(data.M, 1e-10));
295 }
296
297 BOOST_AUTO_TEST_SUITE_END()
298