GCC Code Coverage Report


Directory: ./
File: unittest/joint-motion-subspace.cpp
Date: 2024-08-27 18:20:05
Exec Total Coverage
Lines: 0 160 0.0%
Branches: 0 965 0.0%

Line Branch Exec Source
1 //
2 // Copyright (c) 2015-2019 CNRS INRIA
3 //
4
5 #include "pinocchio/spatial/se3.hpp"
6 #include "pinocchio/spatial/inertia.hpp"
7 #include "pinocchio/multibody/force-set.hpp"
8 #include "pinocchio/multibody/model.hpp"
9 #include "pinocchio/algorithm/joint-configuration.hpp"
10
11 #include "utils/macros.hpp"
12
13 #include <iostream>
14
15 #include <boost/test/unit_test.hpp>
16 #include <boost/utility/binary.hpp>
17
18 using namespace pinocchio;
19
20 BOOST_AUTO_TEST_SUITE(BOOST_TEST_MODULE)
21
22 BOOST_AUTO_TEST_CASE(test_ForceSet)
23 {
24 using namespace pinocchio;
25
26 SE3 amb = SE3::Random();
27 SE3 bmc = SE3::Random();
28 SE3 amc = amb * bmc;
29
30 ForceSet F(12);
31 ForceSet F2(Eigen::Matrix<double, 3, 2>::Zero(), Eigen::Matrix<double, 3, 2>::Zero());
32 F.block(10, 2) = F2;
33 BOOST_CHECK_EQUAL(F.matrix().col(10).norm(), 0.0);
34 BOOST_CHECK(std::isnan(F.matrix()(0, 9)));
35
36 ForceSet F3(Eigen::Matrix<double, 3, 12>::Random(), Eigen::Matrix<double, 3, 12>::Random());
37 ForceSet F4 = amb.act(F3);
38 SE3::Matrix6 aXb = amb;
39 BOOST_CHECK((aXb.transpose().inverse() * F3.matrix()).isApprox(F4.matrix(), 1e-12));
40
41 ForceSet bF = bmc.act(F3);
42 ForceSet aF = amb.act(bF);
43 ForceSet aF2 = amc.act(F3);
44 BOOST_CHECK(aF.matrix().isApprox(aF2.matrix(), 1e-12));
45
46 ForceSet F36 = amb.act(F3.block(3, 6));
47 BOOST_CHECK(
48 (aXb.transpose().inverse() * F3.matrix().block(0, 3, 6, 6)).isApprox(F36.matrix(), 1e-12));
49
50 ForceSet F36full(12);
51 F36full.block(3, 6) = amb.act(F3.block(3, 6));
52 BOOST_CHECK((aXb.transpose().inverse() * F3.matrix().block(0, 3, 6, 6))
53 .isApprox(F36full.matrix().block(0, 3, 6, 6), 1e-12));
54 }
55
56 BOOST_AUTO_TEST_CASE(test_ConstraintRX)
57 {
58 using namespace pinocchio;
59
60 Inertia Y = Inertia::Random();
61 JointDataRX::Constraint_t S;
62
63 ForceSet F1(1);
64 F1.block(0, 1) = Y * S;
65 BOOST_CHECK(F1.matrix().isApprox(Y.matrix().col(3), 1e-12));
66
67 ForceSet F2(Eigen::Matrix<double, 3, 9>::Random(), Eigen::Matrix<double, 3, 9>::Random());
68 Eigen::MatrixXd StF2 = S.transpose() * F2.block(5, 3).matrix();
69 BOOST_CHECK(StF2.isApprox(S.matrix().transpose() * F2.matrix().block(0, 5, 6, 3), 1e-12));
70 }
71
72 template<typename JointModel>
73 void test_jmodel_nq_against_nq_ref(const JointModelBase<JointModel> & jmodel, const int & nq_ref)
74 {
75 BOOST_CHECK(jmodel.nq() == nq_ref);
76 }
77
78 template<typename JointModel>
79 void test_jmodel_nq_against_nq_ref(const JointModelMimic<JointModel> & jmodel, const int & nq_ref)
80 {
81 BOOST_CHECK(jmodel.jmodel().nq() == nq_ref);
82 }
83
84 template<typename JointModel, typename ConstraintDerived>
85 void test_nv_against_jmodel(
86 const JointModelBase<JointModel> & jmodel,
87 const JointMotionSubspaceBase<ConstraintDerived> & constraint)
88 {
89 BOOST_CHECK(constraint.nv() == jmodel.nv());
90 }
91
92 template<typename JointModel, typename ConstraintDerived>
93 void test_nv_against_jmodel(
94 const JointModelMimic<JointModel> & jmodel,
95 const JointMotionSubspaceBase<ConstraintDerived> & constraint)
96 {
97 BOOST_CHECK(constraint.nv() == jmodel.jmodel().nv());
98 }
99
100 template<class JointModel>
101 struct buildModel
102 {
103 static Model run(const JointModelBase<JointModel> & jmodel)
104 {
105 Model model;
106 model.addJoint(0, jmodel, SE3::Identity(), "joint");
107
108 return model;
109 }
110 };
111
112 template<class JointModel>
113 struct buildModel<JointModelMimic<JointModel>>
114 {
115 typedef JointModelMimic<JointModel> JointModel_;
116
117 static Model run(const JointModel_ & jmodel)
118 {
119 Model model;
120 model.addJoint(0, jmodel.jmodel(), SE3::Identity(), "joint");
121 model.addJoint(0, jmodel, SE3::Identity(), "joint_mimic");
122
123 return model;
124 }
125 };
126
127 template<typename JointModel>
128 void test_constraint_operations(const JointModelBase<JointModel> & jmodel)
129 {
130 typedef typename traits<JointModel>::JointDerived Joint;
131 typedef typename traits<Joint>::Constraint_t ConstraintType;
132 typedef typename traits<Joint>::JointDataDerived JointData;
133 typedef Eigen::Matrix<typename JointModel::Scalar, 6, Eigen::Dynamic> Matrix6x;
134
135 JointData jdata = jmodel.createData();
136 typedef typename JointModel::ConfigVector_t ConfigVector_t;
137 ConfigVector_t q;
138
139 // We need to use a model here in order to call the randomConfiguration to init q.
140 Model model = buildModel<JointModel>::run(jmodel.derived());
141
142 test_jmodel_nq_against_nq_ref(jmodel.derived(), model.nq);
143
144 q = randomConfiguration(
145 model, ConfigVector_t::Constant(model.nq, -1.), ConfigVector_t::Constant(model.nq, 1.));
146
147 // By calling jmodel.calc, we then have jdata.S which is initialized with non NaN quantities
148 jmodel.calc(jdata, q);
149
150 ConstraintType constraint(jdata.S);
151
152 test_nv_against_jmodel(jmodel.derived(), constraint);
153 BOOST_CHECK(constraint.cols() == constraint.nv());
154 BOOST_CHECK(constraint.rows() == 6);
155
156 typedef typename JointModel::TangentVector_t TangentVector_t;
157 TangentVector_t v = TangentVector_t::Random(constraint.nv());
158
159 typename ConstraintType::DenseBase constraint_mat = constraint.matrix();
160 Motion m = constraint * v;
161 Motion m_ref = Motion(constraint_mat * v);
162
163 BOOST_CHECK(m.isApprox(m_ref));
164
165 // Test SE3 action
166 {
167 SE3 M = SE3::Random();
168 typename ConstraintType::DenseBase S = M.act(constraint);
169 typename ConstraintType::DenseBase S_ref(6, constraint.nv());
170
171 for (Eigen::DenseIndex k = 0; k < constraint.nv(); ++k)
172 {
173 typedef typename ConstraintType::DenseBase::ColXpr Vector6Like;
174 MotionRef<Vector6Like> m_in(constraint_mat.col(k)), m_out(S_ref.col(k));
175
176 m_out = M.act(m_in);
177 }
178
179 BOOST_CHECK(S.isApprox(S_ref));
180 }
181
182 // Test SE3 action inverse
183 {
184 SE3 M = SE3::Random();
185 typename ConstraintType::DenseBase S = M.actInv(constraint);
186 typename ConstraintType::DenseBase S_ref(6, constraint.nv());
187
188 for (Eigen::DenseIndex k = 0; k < constraint.nv(); ++k)
189 {
190 typedef typename ConstraintType::DenseBase::ColXpr Vector6Like;
191 MotionRef<Vector6Like> m_in(constraint_mat.col(k)), m_out(S_ref.col(k));
192
193 m_out = M.actInv(m_in);
194 }
195
196 BOOST_CHECK(S.isApprox(S_ref));
197 }
198
199 // Test SE3 action and SE3 action inverse
200 {
201 const SE3 M = SE3::Random();
202 const SE3 Minv = M.inverse();
203
204 typename ConstraintType::DenseBase S1_vice = M.actInv(constraint);
205 typename ConstraintType::DenseBase S2_vice = Minv.act(constraint);
206
207 BOOST_CHECK(S1_vice.isApprox(S2_vice));
208
209 typename ConstraintType::DenseBase S1_versa = M.act(constraint);
210 typename ConstraintType::DenseBase S2_versa = Minv.actInv(constraint);
211
212 BOOST_CHECK(S1_versa.isApprox(S2_versa));
213 }
214
215 // Test Motion action
216 {
217 Motion v = Motion::Random();
218
219 typename ConstraintType::DenseBase S = v.cross(constraint);
220 typename ConstraintType::DenseBase S_ref(6, constraint.nv());
221
222 for (Eigen::DenseIndex k = 0; k < constraint.nv(); ++k)
223 {
224 typedef typename ConstraintType::DenseBase::ColXpr Vector6Like;
225 MotionRef<Vector6Like> m_in(constraint_mat.col(k)), m_out(S_ref.col(k));
226
227 m_out = v.cross(m_in);
228 }
229 BOOST_CHECK(S.isApprox(S_ref));
230 }
231
232 // Test transpose operations
233 {
234 const Eigen::DenseIndex dim = 20;
235 const Matrix6x Fin = Matrix6x::Random(6, dim);
236 Eigen::MatrixXd Fout = constraint.transpose() * Fin;
237 Eigen::MatrixXd Fout_ref = constraint_mat.transpose() * Fin;
238 BOOST_CHECK(Fout.isApprox(Fout_ref));
239
240 Force force_in(Force::Random());
241 Eigen::MatrixXd Stf = (constraint.transpose() * force_in);
242 Eigen::MatrixXd Stf_ref = constraint_mat.transpose() * force_in.toVector();
243 BOOST_CHECK(Stf_ref.isApprox(Stf));
244 }
245
246 // CRBA operations
247 {
248 const Inertia Y = Inertia::Random();
249 Eigen::MatrixXd YS = Y * constraint;
250 Eigen::MatrixXd YS_ref = Y.matrix() * constraint_mat;
251 BOOST_CHECK(YS.isApprox(YS_ref));
252 }
253
254 // ABA operations
255 {
256 const Inertia Y = Inertia::Random();
257 const Inertia::Matrix6 Y_mat = Y.matrix();
258 Eigen::MatrixXd YS = Y_mat * constraint;
259 Eigen::MatrixXd YS_ref = Y_mat * constraint_mat;
260 BOOST_CHECK(YS.isApprox(YS_ref));
261 }
262
263 // Test constrainst operations
264 {
265 Eigen::MatrixXd StS = constraint.transpose() * constraint;
266 Eigen::MatrixXd StS_ref = constraint_mat.transpose() * constraint_mat;
267 BOOST_CHECK(StS.isApprox(StS_ref));
268 }
269 }
270
271 template<typename JointModel_>
272 struct init;
273
274 template<typename JointModel_>
275 struct init
276 {
277 static JointModel_ run()
278 {
279 JointModel_ jmodel;
280 jmodel.setIndexes(0, 0, 0);
281 return jmodel;
282 }
283 };
284
285 template<typename Scalar, int Options>
286 struct init<pinocchio::JointModelRevoluteUnalignedTpl<Scalar, Options>>
287 {
288 typedef pinocchio::JointModelRevoluteUnalignedTpl<Scalar, Options> JointModel;
289
290 static JointModel run()
291 {
292 typedef typename JointModel::Vector3 Vector3;
293 JointModel jmodel(Vector3::Random().normalized());
294
295 jmodel.setIndexes(0, 0, 0);
296 return jmodel;
297 }
298 };
299
300 template<typename Scalar, int Options>
301 struct init<pinocchio::JointModelRevoluteUnboundedUnalignedTpl<Scalar, Options>>
302 {
303 typedef pinocchio::JointModelRevoluteUnboundedUnalignedTpl<Scalar, Options> JointModel;
304
305 static JointModel run()
306 {
307 typedef typename JointModel::Vector3 Vector3;
308 JointModel jmodel(Vector3::Random().normalized());
309
310 jmodel.setIndexes(0, 0, 0);
311 return jmodel;
312 }
313 };
314
315 template<typename Scalar, int Options>
316 struct init<pinocchio::JointModelPrismaticUnalignedTpl<Scalar, Options>>
317 {
318 typedef pinocchio::JointModelPrismaticUnalignedTpl<Scalar, Options> JointModel;
319
320 static JointModel run()
321 {
322 typedef typename JointModel::Vector3 Vector3;
323 JointModel jmodel(Vector3::Random().normalized());
324
325 jmodel.setIndexes(0, 0, 0);
326 return jmodel;
327 }
328 };
329
330 template<typename Scalar, int Options, template<typename, int> class JointCollection>
331 struct init<pinocchio::JointModelTpl<Scalar, Options, JointCollection>>
332 {
333 typedef pinocchio::JointModelTpl<Scalar, Options, JointCollection> JointModel;
334
335 static JointModel run()
336 {
337 typedef pinocchio::JointModelRevoluteTpl<Scalar, Options, 0> JointModelRX;
338 JointModel jmodel((JointModelRX()));
339
340 jmodel.setIndexes(0, 0, 0);
341 return jmodel;
342 }
343 };
344
345 template<typename Scalar, int Options>
346 struct init<pinocchio::JointModelUniversalTpl<Scalar, Options>>
347 {
348 typedef pinocchio::JointModelUniversalTpl<Scalar, Options> JointModel;
349
350 static JointModel run()
351 {
352 JointModel jmodel(XAxis::vector(), YAxis::vector());
353
354 jmodel.setIndexes(0, 0, 0);
355 return jmodel;
356 }
357 };
358
359 template<typename Scalar, int Options, template<typename, int> class JointCollection>
360 struct init<pinocchio::JointModelCompositeTpl<Scalar, Options, JointCollection>>
361 {
362 typedef pinocchio::JointModelCompositeTpl<Scalar, Options, JointCollection> JointModel;
363
364 static JointModel run()
365 {
366 typedef pinocchio::JointModelRevoluteTpl<Scalar, Options, 0> JointModelRX;
367 typedef pinocchio::JointModelRevoluteTpl<Scalar, Options, 1> JointModelRY;
368 typedef pinocchio::JointModelRevoluteTpl<Scalar, Options, 2> JointModelRZ;
369
370 JointModel jmodel(JointModelRX(), SE3::Random());
371 jmodel.addJoint(JointModelRY(), SE3::Random());
372 jmodel.addJoint(JointModelRZ(), SE3::Random());
373
374 jmodel.setIndexes(0, 0, 0);
375
376 return jmodel;
377 }
378 };
379
380 template<typename JointModel_>
381 struct init<pinocchio::JointModelMimic<JointModel_>>
382 {
383 typedef pinocchio::JointModelMimic<JointModel_> JointModel;
384
385 static JointModel run()
386 {
387 JointModel_ jmodel_ref = init<JointModel_>::run();
388
389 JointModel jmodel(jmodel_ref, 1., 0.);
390 jmodel.setIndexes(0, 0, 0);
391
392 return jmodel;
393 }
394 };
395
396 template<typename Scalar, int Options, int axis>
397 struct init<pinocchio::JointModelHelicalTpl<Scalar, Options, axis>>
398 {
399 typedef pinocchio::JointModelHelicalTpl<Scalar, Options, axis> JointModel;
400
401 static JointModel run()
402 {
403 JointModel jmodel(static_cast<Scalar>(0.5));
404
405 jmodel.setIndexes(0, 0, 0);
406 return jmodel;
407 }
408 };
409
410 template<typename Scalar, int Options>
411 struct init<pinocchio::JointModelHelicalUnalignedTpl<Scalar, Options>>
412 {
413 typedef pinocchio::JointModelHelicalUnalignedTpl<Scalar, Options> JointModel;
414
415 static JointModel run()
416 {
417 typedef typename JointModel::Vector3 Vector3;
418 JointModel jmodel(Vector3::Random().normalized());
419
420 jmodel.setIndexes(0, 0, 0);
421 return jmodel;
422 }
423 };
424
425 struct TestJointConstraint
426 {
427
428 template<typename JointModel>
429 void operator()(const JointModelBase<JointModel> &) const
430 {
431 JointModel jmodel = init<JointModel>::run();
432 jmodel.setIndexes(0, 0, 0);
433
434 test_constraint_operations(jmodel);
435 }
436 };
437
438 BOOST_AUTO_TEST_CASE(test_joint_constraint_operations)
439 {
440 typedef JointCollectionDefault::JointModelVariant Variant;
441 boost::mpl::for_each<Variant::types>(TestJointConstraint());
442 }
443
444 BOOST_AUTO_TEST_SUITE_END()
445