GCC Code Coverage Report


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

Line Branch Exec Source
1 //
2 // Copyright (c) 2016 CNRS
3 //
4
5 #include "pinocchio/multibody/joint/joint-composite.hpp"
6 #include "pinocchio/algorithm/joint-configuration.hpp"
7 #include "pinocchio/algorithm/kinematics.hpp"
8
9 #include <iostream>
10 #include <boost/test/unit_test.hpp>
11 #include <boost/utility/binary.hpp>
12
13 using namespace pinocchio;
14 using namespace Eigen;
15
16 template<typename JointModel>
17 void test_joint_methods(
18 const JointModelBase<JointModel> & jmodel, JointModelComposite & jmodel_composite);
19
20 template<typename JointModel>
21 void test_joint_methods(const JointModelBase<JointModel> & jmodel)
22 {
23 JointModelComposite jmodel_composite(jmodel);
24 test_joint_methods(jmodel, jmodel_composite);
25 }
26
27 template<typename JointModel>
28 void test_joint_methods(
29 const JointModelBase<JointModel> & jmodel, JointModelComposite & jmodel_composite)
30 {
31 typedef typename JointModelBase<JointModel>::JointDataDerived JointData;
32
33 JointData jdata = jmodel.createData();
34 JointDataComposite jdata_composite = jmodel_composite.createData();
35
36 jmodel_composite.setIndexes(jmodel.id(), jmodel.idx_q(), jmodel.idx_v());
37
38 typedef typename JointModel::ConfigVector_t ConfigVector_t;
39 typedef typename JointModel::TangentVector_t TangentVector_t;
40 typedef typename LieGroup<JointModel>::type LieGroupType;
41
42 typedef Eigen::Matrix<typename ConfigVector_t::Scalar, Eigen::Dynamic, 1, ConfigVector_t::Options>
43 DynConfigVectorType;
44 typedef DynConfigVectorType DynTangentVectorType;
45
46 ConfigVector_t ql(ConfigVector_t::Constant(jmodel.nq(), -M_PI));
47 ConfigVector_t qu(ConfigVector_t::Constant(jmodel.nq(), M_PI));
48 DynConfigVectorType q = LieGroupType().randomConfiguration(ql, qu);
49
50 BOOST_CHECK(jmodel.nv() == jmodel_composite.nv());
51 BOOST_CHECK(jmodel.nq() == jmodel_composite.nq());
52
53 jmodel.calc(jdata, q);
54 jmodel_composite.calc(jdata_composite, q);
55
56 BOOST_CHECK(jdata_composite.M.isApprox((SE3)jdata.M));
57 BOOST_CHECK(jdata_composite.S.matrix().isApprox(jdata.S.matrix()));
58
59 q = LieGroupType().randomConfiguration(ql, qu);
60 DynTangentVectorType v = TangentVector_t::Random(jmodel.nv());
61 jmodel.calc(jdata, q, v);
62 jmodel_composite.calc(jdata_composite, q, v);
63
64 BOOST_CHECK(jdata_composite.M.isApprox((SE3)jdata.M));
65 BOOST_CHECK(jdata_composite.S.matrix().isApprox(jdata.S.matrix()));
66 BOOST_CHECK(jdata_composite.v.isApprox((Motion)jdata.v));
67 BOOST_CHECK(jdata_composite.c.isApprox((Motion)jdata.c));
68
69 // TODO: Not yet checked
70 // {
71 // VectorXd q1(jmodel.random());
72 // jmodel.normalize(q1);
73 // VectorXd q2(jmodel.random());
74 // jmodel.normalize(q2);
75 // VectorXd v(VectorXd::Random(jmodel.nv()));
76 //
77 // BOOST_CHECK(jmodel_composite.integrate(q1,v).isApprox(jmodel.integrate(q1,v)));
78 //
79 // TangentVector_t v1 = jmodel_composite.difference(q1,q2);
80 // TangentVector_t v2 = jmodel.difference(q1,q2);
81 //
82 // BOOST_CHECK(v1.isApprox(v2));
83 //
84 // const double alpha = 0.2;
85 // BOOST_CHECK(jmodel_composite.interpolate(q1,q2,alpha).isApprox(jmodel.interpolate(q1,q2,alpha)));
86 // BOOST_CHECK(math::fabs(jmodel_composite.distance(q1,q2)-jmodel.distance(q1,q2))<=
87 // NumTraits<double>::dummy_precision());
88 // }
89
90 Inertia::Matrix6 I0(Inertia::Random().matrix());
91
92 Inertia::Matrix6 I1 = I0;
93 Inertia::Matrix6 I2 = I0;
94
95 const Eigen::VectorXd armature =
96 Eigen::VectorXd::Random(jmodel.nv()) + Eigen::VectorXd::Ones(jmodel.nv());
97 jmodel.calc_aba(jdata, armature, I1, true);
98 jmodel_composite.calc_aba(jdata_composite, armature, I2, true);
99
100 double prec = 1e-10; // higher tolerance to errors due to possible numerical imprecisions
101
102 BOOST_CHECK(jdata.U.isApprox(jdata_composite.U, prec));
103 BOOST_CHECK(jdata.Dinv.isApprox(jdata_composite.Dinv, prec));
104 BOOST_CHECK(jdata.UDinv.isApprox(jdata_composite.UDinv, prec));
105
106 // Checking the inertia was correctly updated
107 // We use isApprox as usual, except for the freeflyer,
108 // where the correct result is exacly zero and isApprox would fail.
109 // Only for this single case, we use the infinity norm of the difference
110 if (jmodel.shortname() == "JointModelFreeFlyer")
111 BOOST_CHECK((I1 - I2).lpNorm<Eigen::Infinity>() < prec);
112 else
113 BOOST_CHECK(I1.isApprox(I2, prec));
114
115 // Test operator=
116 JointModelComposite jmodel_composite2 = jmodel_composite;
117 JointDataComposite jdata_composite2 = jmodel_composite2.createData();
118
119 jmodel_composite2.calc(jdata_composite2, q, v);
120
121 Inertia::Matrix6 I3 = I0;
122 jmodel_composite2.calc_aba(jdata_composite2, armature, I3, true);
123
124 if (jmodel.shortname() == "JointModelFreeFlyer")
125 BOOST_CHECK((I3 - I2).lpNorm<Eigen::Infinity>() < prec);
126 else
127 BOOST_CHECK(I3.isApprox(I2, prec));
128
129 BOOST_CHECK(jmodel_composite2 == jmodel_composite);
130
131 BOOST_CHECK(jdata_composite2.U.isApprox(jdata_composite.U, prec));
132 BOOST_CHECK(jdata_composite2.Dinv.isApprox(jdata_composite.Dinv, prec));
133 BOOST_CHECK(jdata_composite2.UDinv.isApprox(jdata_composite.UDinv, prec));
134
135 // Test operator <<
136 std::cout << "JointModelComposite operator<<:\n" << jmodel_composite << std::endl;
137
138 // Test block operators
139 const int m = 100;
140 Data::Matrix6x mat(Data::Matrix6x::Ones(6, m));
141 const Data::Matrix6x mat_const(Data::Matrix6x::Ones(6, m));
142 Model::ConfigVectorType vec(Model::ConfigVectorType::Ones(m));
143 const Model::ConfigVectorType vec_const(Model::ConfigVectorType::Ones(m));
144
145 BOOST_CHECK(jmodel.jointConfigSelector(vec) == jmodel_composite.jointConfigSelector(vec));
146 BOOST_CHECK(
147 jmodel.jointConfigSelector(vec_const) == jmodel_composite.jointConfigSelector(vec_const));
148
149 BOOST_CHECK(jmodel.jointVelocitySelector(vec) == jmodel_composite.jointVelocitySelector(vec));
150 BOOST_CHECK(
151 jmodel.jointVelocitySelector(vec_const) == jmodel_composite.jointVelocitySelector(vec_const));
152
153 BOOST_CHECK(jmodel.jointCols(mat) == jmodel_composite.jointCols(mat));
154 BOOST_CHECK(jmodel.jointCols(mat_const) == jmodel_composite.jointCols(mat_const));
155 }
156
157 struct TestJointComposite
158 {
159
160 template<typename JointModel>
161 void operator()(const JointModelBase<JointModel> &) const
162 {
163 JointModel jmodel;
164 jmodel.setIndexes(0, 0, 0);
165
166 test_joint_methods(jmodel);
167 }
168
169 // void operator()(const JointModelBase<JointModelComposite> &) const
170 // {
171 // JointModelComposite jmodel_composite;
172 // jmodel_composite.addJoint(pinocchio::JointModelRX());
173 // jmodel_composite.addJoint(pinocchio::JointModelRY());
174 // jmodel_composite.setIndexes(0,0,0);
175 //
176 // test_joint_methods(jmodel_composite);
177 // }
178
179 void operator()(const JointModelBase<JointModelRevoluteUnaligned> &) const
180 {
181 JointModelRevoluteUnaligned jmodel(1.5, 1., 0.);
182 jmodel.setIndexes(0, 0, 0);
183
184 test_joint_methods(jmodel);
185 }
186
187 void operator()(const JointModelBase<JointModelPrismaticUnaligned> &) const
188 {
189 JointModelPrismaticUnaligned jmodel(1.5, 1., 0.);
190 jmodel.setIndexes(0, 0, 0);
191 test_joint_methods(jmodel);
192 }
193 };
194
195 BOOST_AUTO_TEST_SUITE(BOOST_TEST_MODULE)
196
197 BOOST_AUTO_TEST_CASE(test_basic)
198 {
199 typedef boost::variant<
200 JointModelRX, JointModelRY, JointModelRZ, JointModelRevoluteUnaligned, JointModelSpherical,
201 JointModelSphericalZYX, JointModelPX, JointModelPY, JointModelPZ, JointModelPrismaticUnaligned,
202 JointModelFreeFlyer, JointModelPlanar, JointModelTranslation, JointModelRUBX, JointModelRUBY,
203 JointModelRUBZ>
204 Variant;
205
206 boost::mpl::for_each<Variant::types>(TestJointComposite());
207 }
208
209 BOOST_AUTO_TEST_CASE(chain)
210 {
211 JointModelComposite jmodel_composite;
212 jmodel_composite.addJoint(JointModelRZ())
213 .addJoint(JointModelRY(), SE3::Random())
214 .addJoint(JointModelRX());
215 BOOST_CHECK_MESSAGE(jmodel_composite.nq() == 3, "Chain did not work");
216 BOOST_CHECK_MESSAGE(jmodel_composite.nv() == 3, "Chain did not work");
217 BOOST_CHECK_MESSAGE(jmodel_composite.njoints == 3, "Chain did not work");
218 }
219
220 BOOST_AUTO_TEST_CASE(vsZYX)
221 {
222 JointModelSphericalZYX jmodel_spherical;
223 jmodel_spherical.setIndexes(0, 0, 0);
224
225 JointModelComposite jmodel_composite((JointModelRZ()));
226 jmodel_composite.addJoint(JointModelRY());
227 jmodel_composite.addJoint(JointModelRX());
228
229 test_joint_methods(jmodel_spherical, jmodel_composite);
230 }
231
232 BOOST_AUTO_TEST_CASE(vsTranslation)
233 {
234 JointModelTranslation jmodel_translation;
235 jmodel_translation.setIndexes(0, 0, 0);
236
237 JointModelComposite jmodel_composite((JointModelPX()));
238 jmodel_composite.addJoint(JointModelPY());
239 jmodel_composite.addJoint(JointModelPZ());
240
241 test_joint_methods(jmodel_translation, jmodel_composite);
242 }
243
244 BOOST_AUTO_TEST_CASE(test_recursive_variant)
245 {
246 /// Create joint composite with two joints,
247 JointModelComposite jmodel_composite_two_rx((JointModelRX()));
248 jmodel_composite_two_rx.addJoint(JointModelRY());
249
250 /// Create Joint composite with three joints, and add a composite in it, to test the
251 /// recursive_wrapper
252 JointModelComposite jmodel_composite_recursive((JointModelFreeFlyer()));
253 jmodel_composite_recursive.addJoint(JointModelPlanar());
254 jmodel_composite_recursive.addJoint(jmodel_composite_two_rx);
255 }
256
257 BOOST_AUTO_TEST_CASE(test_copy)
258 {
259 JointModelComposite jmodel_composite_planar((JointModelPX()));
260 jmodel_composite_planar.addJoint(JointModelPY());
261 jmodel_composite_planar.addJoint(JointModelRZ());
262 jmodel_composite_planar.setIndexes(0, 0, 0);
263
264 JointDataComposite jdata_composite_planar = jmodel_composite_planar.createData();
265
266 VectorXd q1(VectorXd::Random(3));
267 VectorXd q1_dot(VectorXd::Random(3));
268
269 JointModelComposite model_copy = jmodel_composite_planar;
270 JointDataComposite data_copy = model_copy.createData();
271
272 BOOST_CHECK_MESSAGE(
273 model_copy.nq() == jmodel_composite_planar.nq(), "Test Copy Composite, nq are differents");
274 BOOST_CHECK_MESSAGE(
275 model_copy.nv() == jmodel_composite_planar.nv(), "Test Copy Composite, nv are differents");
276
277 jmodel_composite_planar.calc(jdata_composite_planar, q1, q1_dot);
278 model_copy.calc(data_copy, q1, q1_dot);
279 }
280
281 BOOST_AUTO_TEST_CASE(test_kinematics)
282 {
283 Model model;
284 JointModelComposite jmodel_composite;
285
286 SE3 config = SE3::Random();
287 JointIndex parent = 0;
288
289 for (int i = 0; i < 10; i++)
290 {
291 parent = model.addJoint(parent, JointModelRX(), config, "joint");
292 jmodel_composite.addJoint(JointModelRX(), config);
293
294 config.setRandom();
295 }
296
297 Data data(model);
298
299 Model model_c;
300 model_c.addJoint(0, jmodel_composite, SE3::Identity(), "joint");
301
302 Data data_c(model_c);
303
304 BOOST_CHECK(model.nv == model_c.nv);
305 BOOST_CHECK(model.nq == model_c.nq);
306
307 VectorXd q(VectorXd::Random(model.nv));
308 forwardKinematics(model, data, q);
309 forwardKinematics(model_c, data_c, q);
310
311 BOOST_CHECK(data.oMi.back().isApprox(data_c.oMi.back()));
312
313 q.setRandom(model.nq);
314 VectorXd v(VectorXd::Random(model.nv));
315 forwardKinematics(model, data, q, v);
316 forwardKinematics(model_c, data_c, q, v);
317
318 BOOST_CHECK(data.oMi.back().isApprox(data_c.oMi.back()));
319 BOOST_CHECK(data.v.back().isApprox(data_c.v.back()));
320
321 q.setRandom(model.nq);
322 v.setRandom(model.nv);
323 VectorXd a(VectorXd::Random(model.nv));
324 forwardKinematics(model, data, q, v, a);
325 forwardKinematics(model_c, data_c, q, v, a);
326
327 BOOST_CHECK(data.oMi.back().isApprox(data_c.oMi.back()));
328 BOOST_CHECK(data.v.back().isApprox(data_c.v.back()));
329 BOOST_CHECK(data.a.back().isApprox(data_c.a.back()));
330 }
331
332 BOOST_AUTO_TEST_SUITE_END()
333