unittest/frames.cpp
Go to the documentation of this file.
1 //
2 // Copyright (c) 2016-2024 CNRS INRIA
3 //
4 
16 
17 #include <iostream>
18 
19 #include <boost/test/unit_test.hpp>
20 #include <boost/utility/binary.hpp>
21 
23 
24 template<typename Derived>
25 inline bool isFinite(const Eigen::MatrixBase<Derived> & x)
26 {
27  return ((x - x).array() == (x - x).array()).all();
28 }
29 
30 BOOST_AUTO_TEST_SUITE(BOOST_TEST_MODULE)
31 
33 {
34  using namespace pinocchio;
35  Model model;
37 
38  BOOST_CHECK(model.frames.size() >= size_t(model.njoints));
39  for (Model::FrameVector::const_iterator it = model.frames.begin(); it != model.frames.end(); ++it)
40  {
41  const Frame & frame = *it;
42  BOOST_CHECK(frame == frame);
43  Frame frame_copy(frame);
44  BOOST_CHECK(frame_copy == frame);
45  }
46 
47  Frame frame1("toto", 0, 0, SE3::Random(), OP_FRAME);
48  std::ostringstream os;
49  os << frame1 << std::endl;
50  BOOST_CHECK(!os.str().empty());
51 
52  // Check other signature
53  Frame frame2("toto", 0, frame1.placement, OP_FRAME);
54  BOOST_CHECK(frame1 == frame2);
55 }
56 
58 {
59  using namespace pinocchio;
60  Frame frame("toto", 0, 0, SE3::Random(), OP_FRAME);
61 
62  BOOST_CHECK(frame.cast<double>() == frame);
63  BOOST_CHECK(frame.cast<double>().cast<long double>() == frame.cast<long double>());
64 
65  typedef FrameTpl<long double> Frameld;
66  Frameld frame2(frame);
67 
68  BOOST_CHECK(frame2 == frame.cast<long double>());
69 }
70 
71 BOOST_AUTO_TEST_CASE(test_kinematics)
72 {
73  using namespace Eigen;
74  using namespace pinocchio;
75 
78  Model::Index parent_idx = model.existJointName("rarm2_joint") ? model.getJointId("rarm2_joint")
79  : (Model::Index)(model.njoints - 1);
80  const std::string & frame_name = std::string(model.names[parent_idx] + "_frame");
81  const SE3 & framePlacement = SE3::Random();
82  model.addFrame(Frame(frame_name, parent_idx, 0, framePlacement, OP_FRAME));
84 
85  VectorXd q = VectorXd::Ones(model.nq);
86  q.middleRows<4>(3).normalize();
88 
89  BOOST_CHECK(
90  data.oMf[model.getFrameId(frame_name)].isApprox(data.oMi[parent_idx] * framePlacement));
91 }
92 
93 BOOST_AUTO_TEST_CASE(test_update_placements)
94 {
95  using namespace Eigen;
96  using namespace pinocchio;
97 
100  Model::Index parent_idx = model.existJointName("rarm2_joint") ? model.getJointId("rarm2_joint")
101  : (Model::Index)(model.njoints - 1);
102  const std::string & frame_name = std::string(model.names[parent_idx] + "_frame");
103  const SE3 & framePlacement = SE3::Random();
104  Model::FrameIndex frame_idx =
105  model.addFrame(Frame(frame_name, parent_idx, 0, framePlacement, OP_FRAME));
107  pinocchio::Data data_ref(model);
108 
109  VectorXd q = VectorXd::Ones(model.nq);
110  q.middleRows<4>(3).normalize();
111 
114 
115  framesForwardKinematics(model, data_ref, q);
116 
117  BOOST_CHECK(data.oMf[frame_idx].isApprox(data_ref.oMf[frame_idx]));
118 }
119 
120 BOOST_AUTO_TEST_CASE(test_update_single_placement)
121 {
122  using namespace Eigen;
123  using namespace pinocchio;
124 
127  Model::Index parent_idx = model.existJointName("rarm2_joint") ? model.getJointId("rarm2_joint")
128  : (Model::Index)(model.njoints - 1);
129  const std::string & frame_name = std::string(model.names[parent_idx] + "_frame");
130  const SE3 & framePlacement = SE3::Random();
131  Model::FrameIndex frame_idx =
132  model.addFrame(Frame(frame_name, parent_idx, 0, framePlacement, OP_FRAME));
134  pinocchio::Data data_ref(model);
135 
136  VectorXd q = VectorXd::Ones(model.nq);
137  q.middleRows<4>(3).normalize();
138 
140  updateFramePlacement(model, data, frame_idx);
141 
142  framesForwardKinematics(model, data_ref, q);
143 
144  BOOST_CHECK(data.oMf[frame_idx].isApprox(data_ref.oMf[frame_idx]));
145 }
146 
147 BOOST_AUTO_TEST_CASE(test_velocity)
148 {
149  using namespace Eigen;
150  using namespace pinocchio;
151 
154  Model::Index parent_idx = model.existJointName("rarm2_joint") ? model.getJointId("rarm2_joint")
155  : (Model::Index)(model.njoints - 1);
156  const std::string & frame_name = std::string(model.names[parent_idx] + "_frame");
157  const SE3 & framePlacement = SE3::Random();
158  Model::FrameIndex frame_idx =
159  model.addFrame(Frame(frame_name, parent_idx, 0, framePlacement, OP_FRAME));
161 
162  VectorXd q = VectorXd::Ones(model.nq);
163  q.middleRows<4>(3).normalize();
164  VectorXd v = VectorXd::Ones(model.nv);
166 
167  Motion vf = getFrameVelocity(model, data, frame_idx);
168 
169  BOOST_CHECK(vf.isApprox(framePlacement.actInv(data.v[parent_idx])));
170 
171  pinocchio::Data data_ref(model);
172  forwardKinematics(model, data_ref, q, v);
173  updateFramePlacements(model, data_ref);
174  Motion v_ref = getFrameVelocity(model, data_ref, frame_idx);
175 
176  BOOST_CHECK(v_ref.isApprox(getFrameVelocity(model, data, frame_idx)));
177  BOOST_CHECK(v_ref.isApprox(getFrameVelocity(model, data, frame_idx, LOCAL)));
178  BOOST_CHECK(
179  data_ref.oMf[frame_idx].act(v_ref).isApprox(getFrameVelocity(model, data, frame_idx, WORLD)));
180  BOOST_CHECK(SE3(data_ref.oMf[frame_idx].rotation(), Eigen::Vector3d::Zero())
181  .act(v_ref)
182  .isApprox(getFrameVelocity(model, data, frame_idx, LOCAL_WORLD_ALIGNED)));
183 }
184 
185 BOOST_AUTO_TEST_CASE(test_acceleration)
186 {
187  using namespace Eigen;
188  using namespace pinocchio;
189 
192  Model::Index parent_idx = model.existJointName("rarm2_joint") ? model.getJointId("rarm2_joint")
193  : (Model::Index)(model.njoints - 1);
194  const std::string & frame_name = std::string(model.names[parent_idx] + "_frame");
195  const SE3 & framePlacement = SE3::Random();
196  Model::FrameIndex frame_idx =
197  model.addFrame(Frame(frame_name, parent_idx, 0, framePlacement, OP_FRAME));
199 
200  VectorXd q = VectorXd::Ones(model.nq);
201  q.middleRows<4>(3).normalize();
202  VectorXd v = VectorXd::Ones(model.nv);
203  VectorXd a = VectorXd::Ones(model.nv);
205 
206  Motion af = getFrameAcceleration(model, data, frame_idx);
207 
208  BOOST_CHECK(af.isApprox(framePlacement.actInv(data.a[parent_idx])));
209 
210  pinocchio::Data data_ref(model);
211  forwardKinematics(model, data_ref, q, v, a);
212  updateFramePlacements(model, data_ref);
213  Motion a_ref = getFrameAcceleration(model, data_ref, frame_idx);
214 
215  BOOST_CHECK(a_ref.isApprox(getFrameAcceleration(model, data, frame_idx)));
216  BOOST_CHECK(a_ref.isApprox(getFrameAcceleration(model, data, frame_idx, LOCAL)));
217  BOOST_CHECK(data_ref.oMf[frame_idx].act(a_ref).isApprox(
218  getFrameAcceleration(model, data, frame_idx, WORLD)));
219  BOOST_CHECK(SE3(data_ref.oMf[frame_idx].rotation(), Eigen::Vector3d::Zero())
220  .act(a_ref)
221  .isApprox(getFrameAcceleration(model, data, frame_idx, LOCAL_WORLD_ALIGNED)));
222 }
223 
224 BOOST_AUTO_TEST_CASE(test_classic_acceleration)
225 {
226  using namespace Eigen;
227  using namespace pinocchio;
228 
231  Model::Index parent_idx = model.existJointName("rarm2_joint") ? model.getJointId("rarm2_joint")
232  : (Model::Index)(model.njoints - 1);
233  const std::string & frame_name = std::string(model.names[parent_idx] + "_frame");
234  const SE3 & framePlacement = SE3::Random();
235  Model::FrameIndex frame_idx =
236  model.addFrame(Frame(frame_name, parent_idx, 0, framePlacement, OP_FRAME));
238 
239  VectorXd q = VectorXd::Ones(model.nq);
240  q.middleRows<4>(3).normalize();
241  VectorXd v = VectorXd::Ones(model.nv);
242  VectorXd a = VectorXd::Ones(model.nv);
244 
245  Motion vel = framePlacement.actInv(data.v[parent_idx]);
246  Motion acc = framePlacement.actInv(data.a[parent_idx]);
247  Vector3d linear;
248 
249  Motion acc_classical_local = acc;
250  linear = acc.linear() + vel.angular().cross(vel.linear());
251  acc_classical_local.linear() = linear;
252 
254 
255  BOOST_CHECK(af.isApprox(acc_classical_local));
256 
257  pinocchio::Data data_ref(model);
258  forwardKinematics(model, data_ref, q, v, a);
259  updateFramePlacements(model, data_ref);
260 
261  SE3 T_ref = data_ref.oMf[frame_idx];
262  Motion v_ref = getFrameVelocity(model, data_ref, frame_idx);
263  Motion a_ref = getFrameAcceleration(model, data_ref, frame_idx);
264 
265  Motion acc_classical_local_ref = a_ref;
266  linear = a_ref.linear() + v_ref.angular().cross(v_ref.linear());
267  acc_classical_local_ref.linear() = linear;
268 
269  BOOST_CHECK(
270  acc_classical_local_ref.isApprox(getFrameClassicalAcceleration(model, data, frame_idx)));
271  BOOST_CHECK(
272  acc_classical_local_ref.isApprox(getFrameClassicalAcceleration(model, data, frame_idx, LOCAL)));
273 
274  Motion vel_world_ref = T_ref.act(v_ref);
275  Motion acc_classical_world_ref = T_ref.act(a_ref);
276  linear = acc_classical_world_ref.linear() + vel_world_ref.angular().cross(vel_world_ref.linear());
277  acc_classical_world_ref.linear() = linear;
278 
279  BOOST_CHECK(
280  acc_classical_world_ref.isApprox(getFrameClassicalAcceleration(model, data, frame_idx, WORLD)));
281 
282  Motion vel_aligned_ref = SE3(T_ref.rotation(), Eigen::Vector3d::Zero()).act(v_ref);
283  Motion acc_classical_aligned_ref = SE3(T_ref.rotation(), Eigen::Vector3d::Zero()).act(a_ref);
284  linear =
285  acc_classical_aligned_ref.linear() + vel_aligned_ref.angular().cross(vel_aligned_ref.linear());
286  acc_classical_aligned_ref.linear() = linear;
287 
288  BOOST_CHECK(acc_classical_aligned_ref.isApprox(
290 }
291 
292 BOOST_AUTO_TEST_CASE(test_frame_getters)
293 {
294  using namespace Eigen;
295  using namespace pinocchio;
296 
297  // Build a simple 1R planar model
298  Model model;
299  JointIndex parentId = model.addJoint(0, JointModelRZ(), SE3::Identity(), "Joint1");
300  FrameIndex frameId = model.addFrame(
301  Frame("Frame1", parentId, 0, SE3(Matrix3d::Identity(), Vector3d(1.0, 0.0, 0.0)), OP_FRAME));
302 
303  Data data(model);
304 
305  // Predetermined configuration values
306  VectorXd q(model.nq);
307  q << M_PI / 2;
308 
309  VectorXd v(model.nv);
310  v << 1.0;
311 
312  VectorXd a(model.nv);
313  a << 0.0;
314 
315  // Expected velocity
316  Motion v_local;
317  v_local.linear() = Vector3d(0.0, 1.0, 0.0);
318  v_local.angular() = Vector3d(0.0, 0.0, 1.0);
319 
320  Motion v_world;
321  v_world.linear() = Vector3d::Zero();
322  v_world.angular() = Vector3d(0.0, 0.0, 1.0);
323 
324  Motion v_align;
325  v_align.linear() = Vector3d(-1.0, 0.0, 0.0);
326  v_align.angular() = Vector3d(0.0, 0.0, 1.0);
327 
328  // Expected classical acceleration
329  Motion ac_local;
330  ac_local.linear() = Vector3d(-1.0, 0.0, 0.0);
331  ac_local.angular() = Vector3d::Zero();
332 
333  Motion ac_world = Motion::Zero();
334 
335  Motion ac_align;
336  ac_align.linear() = Vector3d(0.0, -1.0, 0.0);
337  ac_align.angular() = Vector3d::Zero();
338 
339  // Perform kinematics
341 
342  // Check output velocity
343  BOOST_CHECK(v_local.isApprox(getFrameVelocity(model, data, frameId)));
344  BOOST_CHECK(v_local.isApprox(getFrameVelocity(model, data, frameId, LOCAL)));
345  BOOST_CHECK(v_world.isApprox(getFrameVelocity(model, data, frameId, WORLD)));
346  BOOST_CHECK(v_align.isApprox(getFrameVelocity(model, data, frameId, LOCAL_WORLD_ALIGNED)));
347 
348  // Check output acceleration (all zero)
349  BOOST_CHECK(getFrameAcceleration(model, data, frameId).isZero());
350  BOOST_CHECK(getFrameAcceleration(model, data, frameId, LOCAL).isZero());
351  BOOST_CHECK(getFrameAcceleration(model, data, frameId, WORLD).isZero());
352  BOOST_CHECK(getFrameAcceleration(model, data, frameId, LOCAL_WORLD_ALIGNED).isZero());
353 
354  // Check output classical acceleration
355  BOOST_CHECK(ac_local.isApprox(getFrameClassicalAcceleration(model, data, frameId)));
356  BOOST_CHECK(ac_local.isApprox(getFrameClassicalAcceleration(model, data, frameId, LOCAL)));
357  BOOST_CHECK(ac_world.isApprox(getFrameClassicalAcceleration(model, data, frameId, WORLD)));
358  BOOST_CHECK(
359  ac_align.isApprox(getFrameClassicalAcceleration(model, data, frameId, LOCAL_WORLD_ALIGNED)));
360 }
361 
362 // Test getFrameJacobian
363 // Jacobian is calculated in LOCAL, WORLD and LOCAL_WORLD_ALIGNED and tested against velocity.
365  const pinocchio::Model & input_model, pinocchio::JointIndex joint_idx)
366 {
367  using namespace Eigen;
368  using namespace pinocchio;
369 
370  Model model(input_model);
371  const std::string & frame_name = std::string(model.names[joint_idx] + "_frame");
372  const SE3 & framePlacement = SE3::Random();
373  auto frame_idx = model.addFrame(Frame(frame_name, joint_idx, 0, framePlacement, OP_FRAME));
374 
376  // data_ref is used to compute the frame velocity
377  pinocchio::Data data_ref(model);
378 
379  model.lowerPositionLimit.head<7>().fill(-1.);
380  model.upperPositionLimit.head<7>().fill(1.);
381  VectorXd q = randomConfiguration(model);
382  VectorXd v = VectorXd::Random(model.nv);
383 
385  updateFramePlacement(model, data, frame_idx);
386 
387  forwardKinematics(model, data_ref, q, v);
388  updateFramePlacement(model, data_ref, frame_idx);
389 
390  // In LOCAL frame
391  Data::Matrix6x J_local(Data::Matrix6x::Zero(6, model.nv));
392  getFrameJacobian(model, data, frame_idx, LOCAL, J_local);
393  auto frame_velocity_local = getFrameVelocity(model, data_ref, frame_idx, LOCAL);
394  BOOST_CHECK((J_local * v).isApprox(frame_velocity_local.toVector()));
395 
396  // In WORLD frame
397  Data::Matrix6x J_world(Data::Matrix6x::Zero(6, model.nv));
398  getFrameJacobian(model, data, frame_idx, WORLD, J_world);
399  auto frame_velocity_world = getFrameVelocity(model, data_ref, frame_idx, WORLD);
400  BOOST_CHECK((J_world * v).isApprox(frame_velocity_world.toVector()));
401 
402  // In LOCAL_WORLD_ALIGNED frame
403  Data::Matrix6x J_local_world_aligned(Data::Matrix6x::Zero(6, model.nv));
404  getFrameJacobian(model, data, frame_idx, LOCAL_WORLD_ALIGNED, J_local_world_aligned);
405  auto frame_velocity_local_world_aligned =
406  getFrameVelocity(model, data_ref, frame_idx, LOCAL_WORLD_ALIGNED);
407  BOOST_CHECK((J_local_world_aligned * v).isApprox(frame_velocity_local_world_aligned.toVector()));
408 }
409 
410 // Test getFrameJacobian on normal models
411 BOOST_AUTO_TEST_CASE(test_get_frame_jacobian)
412 {
413  using namespace Eigen;
414  using namespace pinocchio;
415 
416  Model model;
418  for (int j = 1; j < model.njoints; j++)
419  {
421  }
422 }
423 
424 // Test getFrameJacobian on model with mimic joint
425 BOOST_AUTO_TEST_CASE(test_get_frame_jacobian_mimic)
426 {
427  using namespace Eigen;
428  using namespace pinocchio;
429 
430  for (int i = 0; i < pinocchio::MimicTestCases::N_CASES; i++)
431  {
432  const pinocchio::MimicTestCases mimic_test_case(i);
433  const pinocchio::Model & model_mimic = mimic_test_case.model_mimic;
434  for (int j = 1; j < model_mimic.njoints; j++)
435  {
437  }
438  }
439 }
440 
441 // Test computeFrameJacobian
442 // Jacobian is calculated in LOCAL, WORLD and LOCAL_WORLD_ALIGNED and tested against velocity.
444  const pinocchio::Model & input_model, pinocchio::JointIndex joint_idx)
445 {
446  using namespace Eigen;
447  using namespace pinocchio;
448 
449  Model model(input_model);
450  const std::string & frame_name = std::string(model.names[joint_idx] + "_frame");
451  const SE3 & framePlacement = SE3::Random();
452  auto frame_idx = model.addFrame(Frame(frame_name, joint_idx, 0, framePlacement, OP_FRAME));
453 
455  // data_ref is used to compute the frame velocity
456  pinocchio::Data data_ref(model);
457 
458  model.lowerPositionLimit.head<7>().fill(-1.);
459  model.upperPositionLimit.head<7>().fill(1.);
460  VectorXd q = randomConfiguration(model);
461  VectorXd v = VectorXd::Random(model.nv);
462 
463  forwardKinematics(model, data_ref, q, v);
464  updateFramePlacement(model, data_ref, frame_idx);
465 
466  // In LOCAL frame
467  Data::Matrix6x J_local(Data::Matrix6x::Zero(6, model.nv));
468  computeFrameJacobian(model, data, q, frame_idx, LOCAL, J_local);
469  auto frame_velocity_local = getFrameVelocity(model, data_ref, frame_idx, LOCAL);
470  BOOST_CHECK((J_local * v).isApprox(frame_velocity_local.toVector()));
471 
472  // In WORLD frame
473  Data::Matrix6x J_world(Data::Matrix6x::Zero(6, model.nv));
474  computeFrameJacobian(model, data, q, frame_idx, WORLD, J_world);
475  auto frame_velocity_world = getFrameVelocity(model, data_ref, frame_idx, WORLD);
476  BOOST_CHECK((J_world * v).isApprox(frame_velocity_world.toVector()));
477 
478  // In LOCAL_WORLD_ALIGNED frame
479  Data::Matrix6x J_local_world_aligned(Data::Matrix6x::Zero(6, model.nv));
480  computeFrameJacobian(model, data, q, frame_idx, LOCAL_WORLD_ALIGNED, J_local_world_aligned);
481  auto frame_velocity_local_world_aligned =
482  getFrameVelocity(model, data_ref, frame_idx, LOCAL_WORLD_ALIGNED);
483  BOOST_CHECK((J_local_world_aligned * v).isApprox(frame_velocity_local_world_aligned.toVector()));
484 }
485 
486 // Test computeFrameJacobian on normal models
487 BOOST_AUTO_TEST_CASE(test_compute_frame_jacobian)
488 {
489  using namespace Eigen;
490  using namespace pinocchio;
491 
492  Model model;
494  for (int j = 1; j < model.njoints; j++)
495  {
497  }
498 }
499 
500 // Test computeFrameJacobian on model with mimic joint
501 BOOST_AUTO_TEST_CASE(test_compute_frame_jacobian_mimic)
502 {
503  using namespace Eigen;
504  using namespace pinocchio;
505 
506  for (int i = 0; i < pinocchio::MimicTestCases::N_CASES; i++)
507  {
508  const pinocchio::MimicTestCases mimic_test_case(i, true);
509  const pinocchio::Model & model_mimic = mimic_test_case.model_mimic;
510  for (int j = 1; j < model_mimic.njoints; j++)
511  {
513  }
514  }
515 }
516 
517 BOOST_AUTO_TEST_CASE(test_frame_jacobian_time_variation)
518 {
519  using namespace Eigen;
520  using namespace pinocchio;
521 
524  Model::Index parent_idx = model.existJointName("rarm2_joint") ? model.getJointId("rarm2_joint")
525  : (Model::Index)(model.njoints - 1);
526  const std::string & frame_name = std::string(model.names[parent_idx] + "_frame");
527  const SE3 & framePlacement = SE3::Random();
528  model.addFrame(Frame(frame_name, parent_idx, 0, framePlacement, OP_FRAME));
530  pinocchio::Data data_ref(model);
531 
532  VectorXd q = randomConfiguration(
533  model, -1 * Eigen::VectorXd::Ones(model.nq), Eigen::VectorXd::Ones(model.nq));
534  VectorXd v = VectorXd::Random(model.nv);
535  VectorXd a = VectorXd::Random(model.nv);
536 
539 
540  forwardKinematics(model, data_ref, q, v, a);
541  updateFramePlacements(model, data_ref);
542 
543  BOOST_CHECK(isFinite(data.dJ));
544 
545  Model::Index idx = model.getFrameId(frame_name);
546  const Frame & frame = model.frames[idx];
547  BOOST_CHECK(frame.placement.isApprox_impl(framePlacement));
548 
549  Data::Matrix6x J(6, model.nv);
550  J.fill(0.);
551  Data::Matrix6x dJ(6, model.nv);
552  dJ.fill(0.);
553 
554  // Regarding to the WORLD origin
555  getFrameJacobian(model, data, idx, WORLD, J);
557 
558  Motion v_idx(J * v);
559  const Motion & v_ref_local = frame.placement.actInv(data_ref.v[parent_idx]);
560  const Motion & v_ref = data_ref.oMf[idx].act(v_ref_local);
561 
562  const SE3 wMf = SE3(data_ref.oMf[idx].rotation(), SE3::Vector3::Zero());
563  const Motion v_ref_local_world_aligned = wMf.act(v_ref_local);
564  BOOST_CHECK(v_idx.isApprox(v_ref));
565 
566  Motion a_idx(J * a + dJ * v);
567  const Motion a_ref_local = frame.placement.actInv(data_ref.a[parent_idx]);
568  const Motion a_ref = data_ref.oMf[idx].act(a_ref_local);
569  const Motion a_ref_local_world_aligned = wMf.act(a_ref_local);
570  BOOST_CHECK(a_idx.isApprox(a_ref));
571 
572  J.fill(0.);
573  dJ.fill(0.);
574  // Regarding to the LOCAL frame
575  getFrameJacobian(model, data, idx, LOCAL, J);
577 
578  v_idx = (Motion::Vector6)(J * v);
579  BOOST_CHECK(v_idx.isApprox(v_ref_local));
580 
581  a_idx = (Motion::Vector6)(J * a + dJ * v);
582  BOOST_CHECK(a_idx.isApprox(a_ref_local));
583 
584  // Regarding to the LOCAL_WORLD_ALIGNED frame
587  Data::Motion world_v_frame = data.ov[parent_idx];
588  world_v_frame.linear().setZero();
589 
590  v_idx = (Motion::Vector6)(J * v);
591  BOOST_CHECK(v_idx.isApprox(v_ref_local_world_aligned));
592 
593  a_idx = (Motion::Vector6)(J * a + dJ * v);
594  BOOST_CHECK(
595  a_idx.isApprox(world_v_frame.cross(wMf.act(v_ref_local)) + a_ref_local_world_aligned));
596 
597  // compare to finite differencies
598  {
599  Data data_ref(model), data_ref_plus(model);
600 
601  const double alpha = 1e-8;
602  Eigen::VectorXd q_plus(model.nq);
603  q_plus = integrate(model, q, alpha * v);
604 
605  // data_ref
606  Data::Matrix6x J_ref_world(6, model.nv), J_ref_local(6, model.nv),
607  J_ref_local_world_aligned(6, model.nv);
608  J_ref_world.fill(0.);
609  J_ref_local.fill(0.);
610  J_ref_local_world_aligned.fill(0.);
611  computeJointJacobians(model, data_ref, q);
612  updateFramePlacements(model, data_ref);
613  getFrameJacobian(model, data_ref, idx, WORLD, J_ref_world);
614  getFrameJacobian(model, data_ref, idx, LOCAL, J_ref_local);
615  getFrameJacobian(model, data_ref, idx, LOCAL_WORLD_ALIGNED, J_ref_local_world_aligned);
616 
617  // data_ref_plus
618  Data::Matrix6x J_ref_plus_world(6, model.nv), J_ref_plus_local(6, model.nv),
619  J_ref_plus_local_world_aligned(6, model.nv);
620  J_ref_plus_world.fill(0.);
621  J_ref_plus_local.fill(0.);
622  J_ref_plus_local_world_aligned.fill(0.);
623  computeJointJacobians(model, data_ref_plus, q_plus);
624  updateFramePlacements(model, data_ref_plus);
625  getFrameJacobian(model, data_ref_plus, idx, WORLD, J_ref_plus_world);
626  getFrameJacobian(model, data_ref_plus, idx, LOCAL, J_ref_plus_local);
628  model, data_ref_plus, idx, LOCAL_WORLD_ALIGNED, J_ref_plus_local_world_aligned);
629 
630  Data::Matrix6x dJ_ref_world(6, model.nv), dJ_ref_local(6, model.nv),
631  dJ_ref_local_world_aligned(6, model.nv);
632  dJ_ref_world.fill(0.);
633  dJ_ref_local.fill(0.);
634  dJ_ref_local_world_aligned.fill(0.);
635  dJ_ref_world = (J_ref_plus_world - J_ref_world) / alpha;
636  dJ_ref_local = (J_ref_plus_local - J_ref_local) / alpha;
637  dJ_ref_local_world_aligned =
638  (J_ref_plus_local_world_aligned - J_ref_local_world_aligned) / alpha;
639 
640  // data
644  Data::Matrix6x dJ_world(6, model.nv), dJ_local(6, model.nv),
645  dJ_local_world_aligned(6, model.nv);
646  dJ_world.fill(0.);
647  dJ_local.fill(0.);
648  dJ_local_world_aligned.fill(0.);
649  getFrameJacobianTimeVariation(model, data, idx, WORLD, dJ_world);
650  getFrameJacobianTimeVariation(model, data, idx, LOCAL, dJ_local);
651  getFrameJacobianTimeVariation(model, data, idx, LOCAL_WORLD_ALIGNED, dJ_local_world_aligned);
652 
653  BOOST_CHECK(dJ_world.isApprox(dJ_ref_world, sqrt(alpha)));
654  BOOST_CHECK(dJ_local.isApprox(dJ_ref_local, sqrt(alpha)));
655  BOOST_CHECK(dJ_local_world_aligned.isApprox(dJ_ref_local_world_aligned, sqrt(alpha)));
656  }
657 }
658 
659 BOOST_AUTO_TEST_CASE(test_supported_inertia_and_force)
660 {
661  using namespace Eigen;
662  using namespace pinocchio;
663 
664  // Create a humanoid robot
665  Model model_free;
666  pinocchio::buildModels::humanoid(model_free, true);
667  Data data_free(model_free);
668 
669  // Set freeflyer limits to allow for randomConfiguration
670  model_free.lowerPositionLimit.segment(0, 3) << Vector3d::Constant(-1);
671  model_free.upperPositionLimit.segment(0, 3) << Vector3d::Constant(1);
672 
673  // Joint of interest (that will be converted to frame)
674  const std::string joint_name = "chest2_joint";
675  const JointIndex joint_id = model_free.getJointId(joint_name);
676 
677  // Duplicate of the model with the joint of interest fixed (to make a frame)
678  pinocchio::Model model_fix = buildReducedModel(model_free, {joint_id}, neutral(model_free));
679  Data data_fix(model_fix);
680  const FrameIndex frame_id = model_fix.getFrameId(joint_name);
681 
682  // Const variable to help convert q, v, a from one model to another
683  const int joint_idx_q(model_free.joints[joint_id].idx_q());
684  const int joint_idx_v(model_free.joints[joint_id].idx_v());
685 
686  // Pick random q, v, a
687  VectorXd q_free = randomConfiguration(model_free);
688  VectorXd v_free(VectorXd::Random(model_free.nv));
689  VectorXd a_free(VectorXd::Random(model_free.nv));
690 
691  // Set joint of interest to q, v, a = 0 to mimic the fixed joint
692  q_free[joint_idx_q] = 0;
693  v_free[joint_idx_v] = 0;
694  a_free[joint_idx_v] = 0;
695 
696  // Adapt configuration for fixed joint model
697  VectorXd q_fix(model_fix.nq);
698  q_fix << q_free.head(joint_idx_q), q_free.tail(model_free.nq - joint_idx_q - 1);
699  VectorXd v_fix(model_fix.nv);
700  v_fix << v_free.head(joint_idx_v), v_free.tail(model_free.nv - joint_idx_v - 1);
701  VectorXd a_fix(model_fix.nv);
702  a_fix << a_free.head(joint_idx_v), a_free.tail(model_free.nv - joint_idx_v - 1);
703 
704  // Compute inertia/force for both models differently
705  forwardKinematics(model_fix, data_fix, q_fix, v_fix, a_fix);
706  crba(model_free, data_free, q_free, Convention::WORLD);
707 
708  Inertia inertia_fix = computeSupportedInertiaByFrame(model_fix, data_fix, frame_id, false);
709  Inertia inertia_free(model_free.inertias[joint_id]);
710  BOOST_CHECK(inertia_fix.isApprox(inertia_free));
711 
712  inertia_fix = computeSupportedInertiaByFrame(model_fix, data_fix, frame_id, true);
713  inertia_free = data_free.oMi[joint_id].actInv(data_free.oYcrb[joint_id]);
714  BOOST_CHECK(inertia_fix.isApprox(inertia_free));
715 
716  rnea(model_fix, data_fix, q_fix, v_fix, a_fix);
717  rnea(model_free, data_free, q_free, v_free, a_free);
718 
719  Force force_fix = computeSupportedForceByFrame(model_fix, data_fix, frame_id);
720  Force force_free(data_free.f[joint_id]);
721  BOOST_CHECK(force_fix.isApprox(force_free));
722 }
723 BOOST_AUTO_TEST_SUITE_END()
pinocchio::WORLD
@ WORLD
Definition: multibody/fwd.hpp:48
act-on-set.hpp
pinocchio::FrameIndex
Index FrameIndex
Definition: multibody/fwd.hpp:28
frames.hpp
Eigen
pinocchio::DataTpl
Definition: context/generic.hpp:25
pinocchio::forwardKinematics
void forwardKinematics(const ModelTpl< Scalar, Options, JointCollectionTpl > &model, DataTpl< Scalar, Options, JointCollectionTpl > &data, const Eigen::MatrixBase< ConfigVectorType > &q)
Update the joint placements according to the current joint configuration.
model.hpp
pinocchio::getFrameJacobian
void getFrameJacobian(const ModelTpl< Scalar, Options, JointCollectionTpl > &model, DataTpl< Scalar, Options, JointCollectionTpl > &data, const JointIndex joint_id, const SE3Tpl< Scalar, Options > &placement, const ReferenceFrame reference_frame, const Eigen::MatrixBase< Matrix6xLike > &J)
Returns the jacobian of the frame given by its relative placement w.r.t. a joint frame,...
pinocchio::isZero
bool isZero(const Eigen::MatrixBase< MatrixLike > &m, const typename MatrixLike::RealScalar &prec=Eigen::NumTraits< typename MatrixLike::Scalar >::dummy_precision())
Definition: math/matrix.hpp:59
BOOST_AUTO_TEST_CASE
BOOST_AUTO_TEST_CASE(frame_basic)
Definition: unittest/frames.cpp:32
pinocchio::ModelTpl::lowerPositionLimit
ConfigVectorType lowerPositionLimit
Lower joint configuration limit.
Definition: multibody/model.hpp:187
pinocchio::python::context::Frame
FrameTpl< Scalar, Options > Frame
Definition: bindings/python/context/generic.hpp:62
pinocchio::SE3
context::SE3 SE3
Definition: spatial/fwd.hpp:59
inverse-kinematics.i
int i
Definition: inverse-kinematics.py:17
pinocchio::getFrameVelocity
MotionTpl< Scalar, Options > getFrameVelocity(const ModelTpl< Scalar, Options, JointCollectionTpl > &model, const DataTpl< Scalar, Options, JointCollectionTpl > &data, const JointIndex joint_id, const SE3Tpl< Scalar, Options > &placement, const ReferenceFrame rf=LOCAL)
Returns the spatial velocity of the Frame expressed in the desired reference frame....
model.hpp
setup.data
data
Definition: cmake/cython/setup.in.py:48
pinocchio::getFrameClassicalAcceleration
MotionTpl< Scalar, Options > getFrameClassicalAcceleration(const ModelTpl< Scalar, Options, JointCollectionTpl > &model, const DataTpl< Scalar, Options, JointCollectionTpl > &data, const JointIndex joint_id, const SE3Tpl< Scalar, Options > &placement, const ReferenceFrame rf=LOCAL)
Returns the "classical" acceleration of the Frame expressed in the desired reference frame....
pinocchio::python::context::JointModelRZ
JointModelRevoluteTpl< Scalar, Options, 2 > JointModelRZ
Definition: bindings/python/context/generic.hpp:79
inverse-kinematics-3d.J
J
Definition: inverse-kinematics-3d.py:28
pinocchio::ModelTpl::joints
JointModelVector joints
Vector of joint models.
Definition: multibody/model.hpp:122
pinocchio::FrameTpl::placement
SE3 placement
Position of kinematic element in parent joint frame.
Definition: model-item.hpp:39
pinocchio::crba
const DataTpl< Scalar, Options, JointCollectionTpl >::MatrixXs & crba(const ModelTpl< Scalar, Options, JointCollectionTpl > &model, DataTpl< Scalar, Options, JointCollectionTpl > &data, const Eigen::MatrixBase< ConfigVectorType > &q, const Convention convention=Convention::LOCAL)
Computes the upper triangular part of the joint space inertia matrix M by using the Composite Rigid B...
pinocchio::computeJointJacobiansTimeVariation
const DataTpl< Scalar, Options, JointCollectionTpl >::Matrix6x & computeJointJacobiansTimeVariation(const ModelTpl< Scalar, Options, JointCollectionTpl > &model, DataTpl< Scalar, Options, JointCollectionTpl > &data, const Eigen::MatrixBase< ConfigVectorType > &q, const Eigen::MatrixBase< TangentVectorType > &v)
Computes the full model Jacobian variations with respect to time. It corresponds to dJ/dt which depen...
pinocchio::computeJointJacobians
const DataTpl< Scalar, Options, JointCollectionTpl >::Matrix6x & computeJointJacobians(const ModelTpl< Scalar, Options, JointCollectionTpl > &model, DataTpl< Scalar, Options, JointCollectionTpl > &data, const Eigen::MatrixBase< ConfigVectorType > &q)
Computes the full model Jacobian, i.e. the stack of all motion subspace expressed in the world frame....
pinocchio::MimicTestCases::N_CASES
static const int N_CASES
Definition: model-generator.hpp:128
pinocchio::buildModels::humanoidRandom
void humanoidRandom(ModelTpl< Scalar, Options, JointCollectionTpl > &model, bool usingFF=true, bool mimic=false)
Create a humanoid kinematic tree with 6-DOF limbs and random joint placements.
pinocchio::computeSupportedForceByFrame
ForceTpl< Scalar, Options > computeSupportedForceByFrame(const ModelTpl< Scalar, Options, JointCollectionTpl > &model, const DataTpl< Scalar, Options, JointCollectionTpl > &data, const FrameIndex frame_id)
Computes the force supported by a specific frame (given by frame_id) expressed in the LOCAL frame....
pinocchio::randomConfiguration
void randomConfiguration(const ModelTpl< Scalar, Options, JointCollectionTpl > &model, const Eigen::MatrixBase< ConfigVectorIn1 > &lowerLimits, const Eigen::MatrixBase< ConfigVectorIn2 > &upperLimits, const Eigen::MatrixBase< ReturnType > &qout)
Generate a configuration vector uniformly sampled among provided limits.
Definition: joint-configuration.hpp:315
model-generator.hpp
isFinite
bool isFinite(const Eigen::MatrixBase< Derived > &x)
Definition: unittest/frames.cpp:25
rnea.hpp
timer.hpp
static-contact-dynamics.acc
acc
Definition: static-contact-dynamics.py:187
pinocchio::computeFrameJacobian
void computeFrameJacobian(const ModelTpl< Scalar, Options, JointCollectionTpl > &model, DataTpl< Scalar, Options, JointCollectionTpl > &data, const Eigen::MatrixBase< ConfigVectorType > &q, const FrameIndex frameId, const ReferenceFrame reference_frame, const Eigen::MatrixBase< Matrix6xLike > &J)
Computes the Jacobian of a specific Frame expressed in the desired reference_frame given as argument.
pinocchio::FrameTpl
A Plucker coordinate frame attached to a parent joint inside a kinematic tree.
Definition: multibody/frame.hpp:55
anymal-simulation.model
model
Definition: anymal-simulation.py:8
pinocchio::ModelTpl::inertias
InertiaVector inertias
Vector of spatial inertias supported by each joint.
Definition: multibody/model.hpp:116
pinocchio::LOCAL_WORLD_ALIGNED
@ LOCAL_WORLD_ALIGNED
Definition: multibody/fwd.hpp:52
test_compute_frame_jacobian_impl
void test_compute_frame_jacobian_impl(const pinocchio::Model &input_model, pinocchio::JointIndex joint_idx)
Definition: unittest/frames.cpp:443
joint-configuration.hpp
pinocchio::Force
context::Force Force
Definition: spatial/fwd.hpp:63
reachable-workspace-with-collisions.alpha
float alpha
Definition: reachable-workspace-with-collisions.py:162
pinocchio::updateFramePlacements
void updateFramePlacements(const ModelTpl< Scalar, Options, JointCollectionTpl > &model, DataTpl< Scalar, Options, JointCollectionTpl > &data)
Updates the position of each frame contained in the model.
pinocchio::integrate
void integrate(const ModelTpl< Scalar, Options, JointCollectionTpl > &model, const Eigen::MatrixBase< ConfigVectorType > &q, const Eigen::MatrixBase< TangentVectorType > &v, const Eigen::MatrixBase< ReturnType > &qout)
Integrate a configuration vector for the specified model for a tangent vector during one unit time.
Definition: joint-configuration.hpp:70
pinocchio::ModelTpl::getFrameId
FrameIndex getFrameId(const std::string &name, const FrameType &type=(FrameType)(JOINT|FIXED_JOINT|BODY|OP_FRAME|SENSOR)) const
Returns the index of a frame given by its name.
cartpole.v
v
Definition: cartpole.py:153
data.hpp
pinocchio::ModelTpl< Scalar >::FrameIndex
pinocchio::FrameIndex FrameIndex
Definition: multibody/model.hpp:69
x
x
pinocchio::MimicTestCases::model_mimic
pinocchio::Model model_mimic
Definition: model-generator.hpp:130
pinocchio::Inertia
context::Inertia Inertia
Definition: spatial/fwd.hpp:64
pinocchio::computeSupportedInertiaByFrame
InertiaTpl< Scalar, Options > computeSupportedInertiaByFrame(const ModelTpl< Scalar, Options, JointCollectionTpl > &model, const DataTpl< Scalar, Options, JointCollectionTpl > &data, const FrameIndex frame_id, bool with_subtree)
Compute the inertia supported by a specific frame (given by frame_id) expressed in the LOCAL frame....
mimic_dynamics.model_mimic
model_mimic
Definition: mimic_dynamics.py:19
q
q
pinocchio::framesForwardKinematics
void framesForwardKinematics(const ModelTpl< Scalar, Options, JointCollectionTpl > &model, DataTpl< Scalar, Options, JointCollectionTpl > &data, const Eigen::MatrixBase< ConfigVectorType > &q)
First calls the forwardKinematics on the model, then computes the placement of each frame....
contact-cholesky.frame
frame
Definition: contact-cholesky.py:24
inverse-kinematics-3d.it
int it
Definition: inverse-kinematics-3d.py:17
a
Vec3f a
contact-cholesky.frame_id
frame_id
Definition: contact-cholesky.py:19
pinocchio::ModelTpl::getJointId
JointIndex getJointId(const std::string &name) const
Return the index of a joint given by its name.
pinocchio::buildModels::humanoid
void humanoid(ModelTpl< Scalar, Options, JointCollectionTpl > &model, bool usingFF=true)
Create a 28-DOF kinematic chain of a floating humanoid robot.
pinocchio::ModelTpl< Scalar >::Index
pinocchio::Index Index
Definition: multibody/model.hpp:66
pinocchio::python::buildReducedModel
bp::tuple buildReducedModel(const ModelTpl< Scalar, Options, JointCollectionTpl > &model, const GeometryModel &geom_model, const std::vector< JointIndex > &list_of_joints_to_lock, const Eigen::MatrixBase< ConfigVectorType > &reference_configuration)
Definition: algorithm/expose-model.cpp:39
pinocchio::OP_FRAME
@ OP_FRAME
operational frame: user-defined frames that are defined at runtime
Definition: multibody/frame.hpp:33
append-urdf-model-with-another-model.joint_name
string joint_name
Definition: append-urdf-model-with-another-model.py:33
fill
fill
pinocchio::rnea
const DataTpl< Scalar, Options, JointCollectionTpl >::TangentVectorType & rnea(const ModelTpl< Scalar, Options, JointCollectionTpl > &model, DataTpl< Scalar, Options, JointCollectionTpl > &data, const Eigen::MatrixBase< ConfigVectorType > &q, const Eigen::MatrixBase< TangentVectorType1 > &v, const Eigen::MatrixBase< TangentVectorType2 > &a)
The Recursive Newton-Euler algorithm. It computes the inverse dynamics, aka the joint torques accordi...
pinocchio::MimicTestCases
Definition: model-generator.hpp:125
pinocchio::getFrameAcceleration
MotionTpl< Scalar, Options > getFrameAcceleration(const ModelTpl< Scalar, Options, JointCollectionTpl > &model, const DataTpl< Scalar, Options, JointCollectionTpl > &data, const JointIndex joint_id, const SE3Tpl< Scalar, Options > &placement, const ReferenceFrame rf=LOCAL)
Returns the spatial acceleration of the Frame expressed in the desired reference frame....
pinocchio::ModelTpl::nv
int nv
Dimension of the velocity vector space.
Definition: multibody/model.hpp:101
pinocchio::getFrameJacobianTimeVariation
void getFrameJacobianTimeVariation(const ModelTpl< Scalar, Options, JointCollectionTpl > &model, DataTpl< Scalar, Options, JointCollectionTpl > &data, const FrameIndex frame_id, const ReferenceFrame rf, const Eigen::MatrixBase< Matrix6xLike > &dJ)
Computes the Jacobian time variation of a specific frame (given by frame_id) expressed either in the ...
simulation-contact-dynamics.v_ref
v_ref
Definition: simulation-contact-dynamics.py:55
pinocchio::JointIndex
Index JointIndex
Definition: multibody/fwd.hpp:26
pinocchio::DataTpl::Matrix6x
Eigen::Matrix< Scalar, 6, Eigen::Dynamic, Options > Matrix6x
The 6d jacobian type (temporary)
Definition: multibody/data.hpp:92
pinocchio::neutral
void neutral(const ModelTpl< Scalar, Options, JointCollectionTpl > &model, const Eigen::MatrixBase< ReturnType > &qout)
Return the neutral configuration element related to the model configuration space.
Definition: joint-configuration.hpp:363
pinocchio::updateFramePlacement
const DataTpl< Scalar, Options, JointCollectionTpl >::SE3 & updateFramePlacement(const ModelTpl< Scalar, Options, JointCollectionTpl > &model, DataTpl< Scalar, Options, JointCollectionTpl > &data, const FrameIndex frame_id)
Updates the placement of the given frame.
pinocchio::python::context::SE3
SE3Tpl< Scalar, Options > SE3
Definition: bindings/python/context/generic.hpp:53
sample-models.hpp
pinocchio::MotionTpl
Definition: context/casadi.hpp:28
append-urdf-model-with-another-model.joint_id
joint_id
Definition: append-urdf-model-with-another-model.py:34
jacobian.hpp
pinocchio::ModelTpl< Scalar >
crba.hpp
pinocchio::ModelTpl::upperPositionLimit
ConfigVectorType upperPositionLimit
Upper joint configuration limit.
Definition: multibody/model.hpp:190
test_get_frame_jacobian_impl
void test_get_frame_jacobian_impl(const pinocchio::Model &input_model, pinocchio::JointIndex joint_idx)
Definition: unittest/frames.cpp:364
pinocchio::ModelTpl::nq
int nq
Dimension of the configuration vector representation.
Definition: multibody/model.hpp:98
pinocchio::normalize
void normalize(const ModelTpl< Scalar, Options, JointCollectionTpl > &model, const Eigen::MatrixBase< ConfigVectorType > &qout)
Normalize a configuration vector.
Definition: joint-configuration.hpp:887
pinocchio::model
JointCollectionTpl & model
Definition: joint-configuration.hpp:1082
pinocchio
Main pinocchio namespace.
Definition: timings.cpp:33
isApprox
bool isApprox(const Box &s1, const Box &s2, const FCL_REAL tol)
pinocchio::LOCAL
@ LOCAL
Definition: multibody/fwd.hpp:50


pinocchio
Author(s):
autogenerated on Thu Apr 10 2025 02:42:18