unittest/constrained-dynamics.cpp
Go to the documentation of this file.
1 //
2 // Copyright (c) 2019-2023 INRIA
3 //
4 
19 
20 #include <iostream>
21 
22 #include <boost/test/unit_test.hpp>
23 #include <boost/utility/binary.hpp>
24 
25 #define KP 10
26 #define KD 10
27 
28 BOOST_AUTO_TEST_SUITE(BOOST_TEST_MODULE)
29 
30 // BOOST_AUTO_TEST_CASE(contact_models)
31 // {
32 // using namespace pinocchio;
33 
34 // // Check default constructor
35 // RigidConstraintModel cmodel1;
36 // BOOST_CHECK(cmodel1.type == CONTACT_UNDEFINED);
37 // BOOST_CHECK(cmodel1.size() == 0);
38 
39 // // Check complete constructor
40 // const SE3 M(SE3::Random());
41 // RigidConstraintModel cmodel2(CONTACT_3D,0,M);
42 // BOOST_CHECK(cmodel2.type == CONTACT_3D);
43 // BOOST_CHECK(cmodel2.joint1_id == 0);
44 // BOOST_CHECK(cmodel2.joint1_placement.isApprox(M));
45 // BOOST_CHECK(cmodel2.size() == 3);
46 
47 // // Check contructor with two arguments
48 // RigidConstraintModel cmodel2prime(CONTACT_3D,0);
49 // BOOST_CHECK(cmodel2prime.type == CONTACT_3D);
50 // BOOST_CHECK(cmodel2prime.joint1_id == 0);
51 // BOOST_CHECK(cmodel2prime.joint1_placement.isIdentity());
52 // BOOST_CHECK(cmodel2prime.size() == 3);
53 
54 // // Check default copy constructor
55 // RigidConstraintModel cmodel3(cmodel2);
56 // BOOST_CHECK(cmodel3 == cmodel2);
57 
58 // // Check complete constructor 6D
59 // RigidConstraintModel cmodel4(CONTACT_6D,0);
60 // BOOST_CHECK(cmodel4.type == CONTACT_6D);
61 // BOOST_CHECK(cmodel4.joint1_id == 0);
62 // BOOST_CHECK(cmodel4.joint1_placement.isIdentity());
63 // BOOST_CHECK(cmodel4.size() == 6);
64 // }
65 
68  const pinocchio::Model & model,
71  pinocchio::ReferenceFrame reference_frame,
74 {
76  using namespace pinocchio;
78 
79  const Data::SE3 & oMi = data.oMi[joint_id];
80  const Data::SE3 & iMc = placement;
81  const Data::SE3 oMc = oMi * iMc;
82 
83  const Motion ov = oMi.act(data.v[joint_id]);
84  const Motion oa = oMi.act(data.a[joint_id]);
85 
86  switch (reference_frame)
87  {
88  case WORLD:
89  if (type == CONTACT_3D)
90  classicAcceleration(ov, oa, res.linear());
91  else
92  res.linear() = oa.linear();
93  res.angular() = oa.angular();
94  break;
96  if (type == CONTACT_3D)
97  res.linear() = oMc.rotation() * classicAcceleration(data.v[joint_id], data.a[joint_id], iMc);
98  else
99  res.linear() = oMc.rotation() * (iMc.actInv(data.a[joint_id])).linear();
100  res.angular() = oMi.rotation() * data.a[joint_id].angular();
101  break;
102  case LOCAL:
103  if (type == CONTACT_3D)
104  classicAcceleration(data.v[joint_id], data.a[joint_id], iMc, res.linear());
105  else
106  res.linear() = (iMc.actInv(data.a[joint_id])).linear();
107  res.angular() = iMc.rotation().transpose() * data.a[joint_id].angular();
108  break;
109  default:
110  break;
111  }
112 
113  return res;
114 }
115 
116 BOOST_AUTO_TEST_CASE(test_sparse_forward_dynamics_empty)
117 {
118  using namespace Eigen;
119  using namespace pinocchio;
120 
123  pinocchio::Data data(model), data_ref(model);
124 
125  model.lowerPositionLimit.head<3>().fill(-1.);
126  model.upperPositionLimit.head<3>().fill(1.);
127  VectorXd q = randomConfiguration(model);
128 
129  VectorXd v = VectorXd::Random(model.nv);
130  VectorXd tau = VectorXd::Random(model.nv);
131 
132  const std::string RF = "rleg6_joint";
133  // const Model::JointIndex RF_id = model.getJointId(RF);
134  const std::string LF = "lleg6_joint";
135  // const Model::JointIndex LF_id = model.getJointId(LF);
136 
137  // Contact models and data
140 
141  const double mu0 = 0.;
142  ProximalSettings prox_settings(1e-12, mu0, 1);
143 
144  computeAllTerms(model, data_ref, q, v);
145  data_ref.M.triangularView<Eigen::StrictlyLower>() =
146  data_ref.M.transpose().triangularView<Eigen::StrictlyLower>();
147 
148  Eigen::MatrixXd KKT_matrix_ref = Eigen::MatrixXd::Zero(model.nv, model.nv);
149  KKT_matrix_ref.bottomRightCorner(model.nv, model.nv) = data_ref.M;
150 
151  initConstraintDynamics(model, data, empty_contact_models);
153  model, data, q, v, tau, empty_contact_models, empty_contact_datas, prox_settings);
154 
155  data.M.triangularView<Eigen::StrictlyLower>() =
156  data.M.transpose().triangularView<Eigen::StrictlyLower>();
157 
158  Data data_ag(model);
159  ccrba(model, data_ag, q, v);
160 
161  BOOST_CHECK(data.J.isApprox(data_ref.J));
162  BOOST_CHECK(data.M.isApprox(data_ref.M));
163  BOOST_CHECK(data.Ag.isApprox(data_ag.Ag));
164  BOOST_CHECK(data.nle.isApprox(data_ref.nle));
165 
166  for (Model::JointIndex k = 1; k < model.joints.size(); ++k)
167  {
168  BOOST_CHECK(data.oMi[k].isApprox(data_ref.oMi[k]));
169  BOOST_CHECK(data.liMi[k].isApprox(data_ref.liMi[k]));
170  BOOST_CHECK(data.ov[k].isApprox(data_ref.oMi[k].act(data_ref.v[k])));
171  // Since it's gravity, we know linear can't be zero. Angular might be though.
172  const Motion motion_tmp = data_ref.oMi[k].act(data_ref.a_gf[k]);
173  if (data.oa_gf[k].angular().isZero())
174  {
175  BOOST_CHECK(data.oa_gf[k].linear().isApprox(motion_tmp.linear()));
176  BOOST_CHECK(motion_tmp.angular().isZero());
177  }
178  else
179  {
180  BOOST_CHECK(data.oa_gf[k].isApprox(motion_tmp));
181  }
182  }
183 
184  // Check that the decomposition is correct
185  const Data::ContactCholeskyDecomposition & contact_chol = data.contact_chol;
186  Eigen::MatrixXd KKT_matrix = contact_chol.matrix();
187 
188  BOOST_CHECK(KKT_matrix.bottomRightCorner(model.nv, model.nv)
189  .isApprox(KKT_matrix_ref.bottomRightCorner(model.nv, model.nv)));
190  BOOST_CHECK(KKT_matrix.isApprox(KKT_matrix_ref));
191 
192  // Check solutions
193  aba(model, data_ref, q, v, tau, Convention::WORLD);
194  BOOST_CHECK(data.ddq.isApprox(data_ref.ddq));
195 }
196 
197 BOOST_AUTO_TEST_CASE(test_sparse_forward_dynamics_double_init)
198 {
199  using namespace Eigen;
200  using namespace pinocchio;
201 
204  pinocchio::Data data1(model), data2(model);
205 
206  model.lowerPositionLimit.head<3>().fill(-1.);
207  model.upperPositionLimit.head<3>().fill(1.);
208  VectorXd q = randomConfiguration(model);
209 
210  VectorXd v = VectorXd::Random(model.nv);
211  VectorXd tau = VectorXd::Random(model.nv);
212 
213  const std::string RF = "rleg6_joint";
214  // const Model::JointIndex RF_id = model.getJointId(RF);
215  const std::string LF = "lleg6_joint";
216 
217  // Contact models and data
220 
223 
226 
227  RigidConstraintModel ci_RF(CONTACT_6D, model, model.getJointId(RF), LOCAL);
228  contact_models_6D.push_back(ci_RF);
229  contact_datas_6D.push_back(RigidConstraintData(ci_RF));
230  contact_models_6D6D.push_back(ci_RF);
231  contact_datas_6D6D.push_back(RigidConstraintData(ci_RF));
232  RigidConstraintModel ci_LF(CONTACT_6D, model, model.getJointId(LF), LOCAL);
233  contact_models_6D6D.push_back(ci_LF);
234  contact_datas_6D6D.push_back(RigidConstraintData(ci_LF));
235 
236  const double mu0 = 0.;
237  ProximalSettings prox_settings(1e-12, mu0, 1);
238 
239  initConstraintDynamics(model, data1, contact_models_empty);
240  BOOST_CHECK(data1.contact_chol.size() == (model.nv + 0));
242  model, data1, q, v, tau, contact_models_empty, contact_datas_empty, prox_settings);
243  BOOST_CHECK(!hasNaN(data1.ddq));
244 
245  initConstraintDynamics(model, data1, contact_models_6D);
246  BOOST_CHECK(data1.contact_chol.size() == (model.nv + 1 * 6));
247  constraintDynamics(model, data1, q, v, tau, contact_models_6D, contact_datas_6D, prox_settings);
248  BOOST_CHECK(!hasNaN(data1.ddq));
249 
250  initConstraintDynamics(model, data1, contact_models_6D6D);
251  BOOST_CHECK(data1.contact_chol.size() == (model.nv + 2 * 6));
253  model, data1, q, v, tau, contact_models_6D6D, contact_datas_6D6D, prox_settings);
254  BOOST_CHECK(!hasNaN(data1.ddq));
255 
256  initConstraintDynamics(model, data2, contact_models_6D6D);
257  initConstraintDynamics(model, data2, contact_models_6D);
258  initConstraintDynamics(model, data2, contact_models_empty);
259 }
260 
261 BOOST_AUTO_TEST_CASE(test_sparse_forward_dynamics_in_contact_6D_LOCAL)
262 {
263  using namespace Eigen;
264  using namespace pinocchio;
265 
268  pinocchio::Data data(model), data_ref(model);
269 
270  model.lowerPositionLimit.head<3>().fill(-1.);
271  model.upperPositionLimit.head<3>().fill(1.);
272  VectorXd q = randomConfiguration(model);
273 
274  VectorXd v = VectorXd::Random(model.nv);
275  VectorXd tau = VectorXd::Random(model.nv);
276 
277  const std::string RF = "rleg6_joint";
278  // const Model::JointIndex RF_id = model.getJointId(RF);
279  const std::string LF = "lleg6_joint";
280  // const Model::JointIndex LF_id = model.getJointId(LF);
281 
282  // Contact models and data
285  RigidConstraintModel ci_RF(CONTACT_6D, model, model.getJointId(RF), LOCAL);
286  ci_RF.joint1_placement.setRandom();
287  contact_models.push_back(ci_RF);
288  contact_datas.push_back(RigidConstraintData(ci_RF));
289  RigidConstraintModel ci_LF(CONTACT_6D, model, model.getJointId(LF), LOCAL);
290  ci_LF.joint1_placement.setRandom();
291  contact_models.push_back(ci_LF);
292  contact_datas.push_back(RigidConstraintData(ci_LF));
293 
294  Eigen::DenseIndex constraint_dim = 0;
295  for (size_t k = 0; k < contact_models.size(); ++k)
297 
298  const double mu0 = 0.;
299 
300  computeAllTerms(model, data_ref, q, v);
301  data_ref.M.triangularView<Eigen::StrictlyLower>() =
302  data_ref.M.transpose().triangularView<Eigen::StrictlyLower>();
303 
304  Eigen::MatrixXd J_ref(constraint_dim, model.nv);
305  J_ref.setZero();
306  Data::Matrix6x Jtmp = Data::Matrix6x::Zero(6, model.nv);
307 
308  getJointJacobian(model, data_ref, ci_RF.joint1_id, ci_RF.reference_frame, Jtmp);
309  J_ref.middleRows<6>(0) = ci_RF.joint1_placement.inverse().toActionMatrix() * Jtmp;
310 
311  Jtmp.setZero();
312  getJointJacobian(model, data_ref, ci_LF.joint1_id, ci_LF.reference_frame, Jtmp);
313  J_ref.middleRows<6>(6) = ci_LF.joint1_placement.inverse().toActionMatrix() * Jtmp;
314 
315  Eigen::VectorXd rhs_ref(constraint_dim);
316  rhs_ref.segment<6>(0) =
318  model, data_ref, ci_RF.joint1_id, ci_RF.reference_frame, ci_RF.type, ci_RF.joint1_placement)
319  .toVector();
320  rhs_ref.segment<6>(6) =
322  model, data_ref, ci_LF.joint1_id, ci_LF.reference_frame, ci_LF.type, ci_LF.joint1_placement)
323  .toVector();
324 
325  Eigen::MatrixXd KKT_matrix_ref =
326  Eigen::MatrixXd::Zero(model.nv + constraint_dim, model.nv + constraint_dim);
327  KKT_matrix_ref.bottomRightCorner(model.nv, model.nv) = data_ref.M;
328  KKT_matrix_ref.topRightCorner(constraint_dim, model.nv) = J_ref;
329  KKT_matrix_ref.bottomLeftCorner(model.nv, constraint_dim) = J_ref.transpose();
330 
333  forwardDynamics(model, data_ref, q, v, tau, J_ref, rhs_ref, mu0);
335 
336  forwardKinematics(model, data_ref, q, v, data_ref.ddq);
337 
338  BOOST_CHECK((J_ref * data_ref.ddq + rhs_ref).isZero());
339 
340  ProximalSettings prox_settings(1e-12, mu0, 1);
343  BOOST_CHECK((J_ref * data.ddq + rhs_ref).isZero());
344 
345  BOOST_CHECK((J_ref * data.ddq + rhs_ref).isZero());
346 
347  // Check that the decomposition is correct
348  const Data::ContactCholeskyDecomposition & contact_chol = data.contact_chol;
349  Eigen::MatrixXd KKT_matrix = contact_chol.matrix();
350 
351  BOOST_CHECK(KKT_matrix.bottomRightCorner(model.nv, model.nv)
352  .isApprox(KKT_matrix_ref.bottomRightCorner(model.nv, model.nv)));
353  BOOST_CHECK(KKT_matrix.isApprox(KKT_matrix_ref));
354 
355  // Check solutions
356  BOOST_CHECK(data.ddq.isApprox(data_ref.ddq));
357 
358  Eigen::DenseIndex constraint_id = 0;
359  for (size_t k = 0; k < contact_models.size(); ++k)
360  {
362  const RigidConstraintData & cdata = contact_datas[k];
363 
364  switch (cmodel.type)
365  {
366  case pinocchio::CONTACT_3D: {
367  BOOST_CHECK(cdata.contact_force.linear().isApprox(
368  data_ref.lambda_c.segment(constraint_id, cmodel.size())));
369  break;
370  }
371 
372  case pinocchio::CONTACT_6D: {
374  data_ref.lambda_c.segment<6>(constraint_id));
375  BOOST_CHECK(cdata.contact_force.isApprox(f_ref));
376  break;
377  }
378 
379  default:
380  break;
381  }
382 
383  constraint_id += cmodel.size();
384  }
385 }
386 
387 BOOST_AUTO_TEST_CASE(test_sparse_forward_dynamics_in_contact_6D_3D)
388 {
389  using namespace Eigen;
390  using namespace pinocchio;
391 
394  pinocchio::Data data(model), data_ref(model);
395 
396  model.lowerPositionLimit.head<3>().fill(-1.);
397  model.upperPositionLimit.head<3>().fill(1.);
398  VectorXd q = randomConfiguration(model);
399 
400  VectorXd v = VectorXd::Random(model.nv);
401  VectorXd tau = VectorXd::Random(model.nv);
402 
403  const std::string RF = "rleg6_joint";
404  const std::string LF = "lleg6_joint";
405  const std::string RA = "rarm6_joint";
406 
407  // Contact models and data
410  RigidConstraintModel ci_RF(CONTACT_6D, model, model.getJointId(RF), LOCAL);
411  contact_models.push_back(ci_RF);
412  contact_datas.push_back(RigidConstraintData(ci_RF));
414  contact_models.push_back(ci_LF);
415  contact_datas.push_back(RigidConstraintData(ci_LF));
416  RigidConstraintModel ci_RA(CONTACT_3D, model, model.getJointId(RA), LOCAL);
417  contact_models.push_back(ci_RA);
418  contact_datas.push_back(RigidConstraintData(ci_RA));
419 
420  Eigen::DenseIndex constraint_dim = 0;
421  for (size_t k = 0; k < contact_models.size(); ++k)
423 
424  const double mu0 = 0.;
425 
426  Eigen::MatrixXd J_ref(constraint_dim, model.nv);
427  J_ref.setZero();
428 
429  computeAllTerms(model, data_ref, q, v);
430  data_ref.M.triangularView<Eigen::StrictlyLower>() =
431  data_ref.M.transpose().triangularView<Eigen::StrictlyLower>();
432 
433  getJointJacobian(model, data_ref, model.getJointId(RF), LOCAL, J_ref.middleRows<6>(0));
434  Data::Matrix6x J_LF(6, model.nv);
435  J_LF.setZero();
436  getJointJacobian(model, data_ref, model.getJointId(LF), LOCAL_WORLD_ALIGNED, J_LF);
437  J_ref.middleRows<3>(6) = J_LF.middleRows<3>(Motion::LINEAR);
438  Data::Matrix6x J_RA(6, model.nv);
439  J_RA.setZero();
440  getJointJacobian(model, data_ref, model.getJointId(RA), LOCAL, J_RA);
441  J_ref.middleRows<3>(9) = J_RA.middleRows<3>(Motion::LINEAR);
442 
443  Eigen::VectorXd rhs_ref(constraint_dim);
444 
445  rhs_ref.segment<6>(0) =
446  computeAcceleration(model, data_ref, model.getJointId(RF), ci_RF.reference_frame, ci_RF.type)
447  .toVector();
448  rhs_ref.segment<3>(6) =
449  computeAcceleration(model, data_ref, model.getJointId(LF), ci_LF.reference_frame, ci_LF.type)
450  .linear();
451  rhs_ref.segment<3>(9) =
452  computeAcceleration(model, data_ref, model.getJointId(RA), ci_RA.reference_frame, ci_RA.type)
453  .linear();
454 
455  Eigen::MatrixXd KKT_matrix_ref =
456  Eigen::MatrixXd::Zero(model.nv + constraint_dim, model.nv + constraint_dim);
457  KKT_matrix_ref.bottomRightCorner(model.nv, model.nv) = data_ref.M;
458  KKT_matrix_ref.topRightCorner(constraint_dim, model.nv) = J_ref;
459  KKT_matrix_ref.bottomLeftCorner(model.nv, constraint_dim) = J_ref.transpose();
460 
463  forwardDynamics(model, data_ref, q, v, tau, J_ref, rhs_ref, mu0);
465 
466  forwardKinematics(model, data_ref, q, v, data_ref.ddq);
467 
468  ProximalSettings prox_settings(1e-12, mu0, 1);
471 
472  // Check that the decomposition is correct
473  const Data::ContactCholeskyDecomposition & contact_chol = data.contact_chol;
474  Eigen::MatrixXd KKT_matrix = contact_chol.matrix();
475 
476  BOOST_CHECK(KKT_matrix.bottomRightCorner(model.nv, model.nv)
477  .isApprox(KKT_matrix_ref.bottomRightCorner(model.nv, model.nv)));
478  BOOST_CHECK(KKT_matrix.isApprox(KKT_matrix_ref));
479 
480  // Check solutions
481  BOOST_CHECK(data.ddq.isApprox(data_ref.ddq));
482 
483  Eigen::DenseIndex constraint_id = 0;
484  for (size_t k = 0; k < contact_models.size(); ++k)
485  {
487  const RigidConstraintData & cdata = contact_datas[k];
488 
489  switch (cmodel.type)
490  {
491  case pinocchio::CONTACT_3D: {
492  BOOST_CHECK(cdata.contact_force.linear().isApprox(
493  data_ref.lambda_c.segment(constraint_id, cmodel.size())));
494  break;
495  }
496 
497  case pinocchio::CONTACT_6D: {
499  data_ref.lambda_c.segment<6>(constraint_id));
500  BOOST_CHECK(cdata.contact_force.isApprox(f_ref));
501  break;
502  }
503 
504  default:
505  break;
506  }
507 
508  constraint_id += cmodel.size();
509  }
510 }
511 
512 BOOST_AUTO_TEST_CASE(test_constraint_dynamics_LOCAL_6D_loop_closure_j1j2)
513 {
514  using namespace Eigen;
515  using namespace pinocchio;
516 
517  Model model;
519  Data data(model), data_fd(model);
520 
521  model.lowerPositionLimit.head<3>().fill(-1.);
522  model.upperPositionLimit.head<3>().fill(1.);
523  VectorXd q = randomConfiguration(model);
524 
525  VectorXd v = VectorXd::Random(model.nv);
526  VectorXd tau = VectorXd::Random(model.nv);
527 
528  const std::string RF = "rleg6_joint";
529  const std::string LF = "lleg6_joint";
530 
531  // Contact models and data
534  constraint_data, constraint_data_fd;
535 
536  const std::string RA = "rarm5_joint";
537  const Model::JointIndex RA_id = model.getJointId(RA);
538  const std::string LA = "larm5_joint";
539  const Model::JointIndex LA_id = model.getJointId(LA);
540 
541  // Add loop closure constraint
542  RigidConstraintModel ci_closure(
543  CONTACT_6D, model, LA_id, SE3::Random(), RA_id, SE3::Random(), LOCAL);
544  ci_closure.corrector.Kp.array() = KP;
545  ci_closure.corrector.Kd.array() = KD;
546 
547  constraint_models.push_back(ci_closure);
548  constraint_data.push_back(RigidConstraintData(ci_closure));
549  constraint_data_fd.push_back(RigidConstraintData(ci_closure));
550 
551  Eigen::DenseIndex constraint_dim = 0;
552  for (size_t k = 0; k < constraint_models.size(); ++k)
554 
555  const double mu0 = 0.;
556  ProximalSettings prox_settings(1e-12, mu0, 100);
557 
559  const VectorXd ddq_ref =
561  const VectorXd lambda_ref = data.lambda_c;
562 
563  // test multiple call
564  {
565  const VectorXd ddq =
567  const VectorXd lambda = data.lambda_c;
568  BOOST_CHECK(ddq_ref == ddq);
569  BOOST_CHECK(lambda_ref == lambda_ref);
570  }
571 }
572 
573 BOOST_AUTO_TEST_CASE(test_sparse_forward_dynamics_in_contact_6D_LOCAL_WORLD_ALIGNED)
574 {
575  using namespace Eigen;
576  using namespace pinocchio;
577 
580  pinocchio::Data data(model), data_ref(model);
581 
582  model.lowerPositionLimit.head<3>().fill(-1.);
583  model.upperPositionLimit.head<3>().fill(1.);
584  VectorXd q = randomConfiguration(model);
585 
586  VectorXd v = VectorXd::Random(model.nv);
587  VectorXd tau = VectorXd::Random(model.nv);
588 
589  const std::string RF = "rleg6_joint";
590  // const Model::JointIndex RF_id = model.getJointId(RF);
591  const std::string LF = "lleg6_joint";
592  // const Model::JointIndex LF_id = model.getJointId(LF);
593 
594  // Contact models and data
598  contact_models.push_back(ci_RF);
599  contact_datas.push_back(RigidConstraintData(ci_RF));
600  RigidConstraintModel ci_LF(CONTACT_6D, model, model.getJointId(LF), LOCAL);
601  contact_models.push_back(ci_LF);
602  contact_datas.push_back(RigidConstraintData(ci_LF));
603 
604  Eigen::DenseIndex constraint_dim = 0;
605  for (size_t k = 0; k < contact_models.size(); ++k)
607 
608  const double mu0 = 0.;
609 
610  Eigen::MatrixXd J_ref(constraint_dim, model.nv);
611  J_ref.setZero();
612 
613  computeAllTerms(model, data_ref, q, v);
614  data_ref.M.triangularView<Eigen::StrictlyLower>() =
615  data_ref.M.transpose().triangularView<Eigen::StrictlyLower>();
616 
617  updateFramePlacements(model, data_ref);
618  getJointJacobian(model, data_ref, ci_RF.joint1_id, ci_RF.reference_frame, J_ref.middleRows<6>(0));
619  getJointJacobian(model, data_ref, ci_LF.joint1_id, ci_LF.reference_frame, J_ref.middleRows<6>(6));
620 
621  Eigen::VectorXd rhs_ref(constraint_dim);
622 
623  rhs_ref.segment<6>(0) =
624  computeAcceleration(model, data_ref, ci_RF.joint1_id, ci_RF.reference_frame, ci_RF.type)
625  .toVector();
626  rhs_ref.segment<6>(6) =
627  computeAcceleration(model, data_ref, ci_LF.joint1_id, ci_LF.reference_frame, ci_LF.type)
628  .toVector();
629 
630  Eigen::MatrixXd KKT_matrix_ref =
631  Eigen::MatrixXd::Zero(model.nv + constraint_dim, model.nv + constraint_dim);
632  KKT_matrix_ref.bottomRightCorner(model.nv, model.nv) = data_ref.M;
633  KKT_matrix_ref.topRightCorner(constraint_dim, model.nv) = J_ref;
634  KKT_matrix_ref.bottomLeftCorner(model.nv, constraint_dim) = J_ref.transpose();
635 
638  forwardDynamics(model, data_ref, q, v, tau, J_ref, rhs_ref, mu0);
640 
641  forwardKinematics(model, data_ref, q, v, data_ref.ddq);
642 
643  ProximalSettings prox_settings(1e-12, mu0, 1);
646 
647  // Check that the decomposition is correct
648  const Data::ContactCholeskyDecomposition & contact_chol = data.contact_chol;
649  Eigen::MatrixXd KKT_matrix = contact_chol.matrix();
650 
651  BOOST_CHECK(KKT_matrix.bottomRightCorner(model.nv, model.nv)
652  .isApprox(KKT_matrix_ref.bottomRightCorner(model.nv, model.nv)));
653  BOOST_CHECK(KKT_matrix.isApprox(KKT_matrix_ref));
654 
655  // Check solutions
656  BOOST_CHECK(data.ddq.isApprox(data_ref.ddq));
657  BOOST_CHECK((J_ref * data.ddq + rhs_ref).isZero());
658 
659  Eigen::DenseIndex constraint_id = 0;
660  for (size_t k = 0; k < contact_models.size(); ++k)
661  {
663  const RigidConstraintData & cdata = contact_datas[k];
664 
665  switch (cmodel.type)
666  {
667  case pinocchio::CONTACT_3D: {
668  BOOST_CHECK(cdata.contact_force.linear().isApprox(
669  data_ref.lambda_c.segment(constraint_id, cmodel.size())));
670  break;
671  }
672 
673  case pinocchio::CONTACT_6D: {
675  data_ref.lambda_c.segment<6>(constraint_id));
676  BOOST_CHECK(cdata.contact_force.isApprox(f_ref));
677  break;
678  }
679 
680  default:
681  break;
682  }
683 
684  constraint_id += cmodel.size();
685  }
686 }
687 
688 BOOST_AUTO_TEST_CASE(test_sparse_forward_dynamics_in_contact_specifying_joint2id)
689 {
690  using namespace Eigen;
691  using namespace pinocchio;
692 
695  pinocchio::Data data(model), data_ref(model);
696 
697  model.lowerPositionLimit.head<3>().fill(-1.);
698  model.upperPositionLimit.head<3>().fill(1.);
699  VectorXd q = randomConfiguration(model);
700 
701  VectorXd v = VectorXd::Random(model.nv);
702  VectorXd tau = VectorXd::Random(model.nv);
703 
704  const std::string RF = "rleg6_joint";
705  const std::string LF = "lleg6_joint";
706  const std::string RA = "rarm6_joint";
707 
708  // Contact models and data
711 
712  RigidConstraintModel ci_RF(CONTACT_6D, model, 0, model.getJointId(RF), LOCAL_WORLD_ALIGNED);
713  RigidConstraintModel ci_RF_bis(CONTACT_6D, model, model.getJointId(RF), LOCAL_WORLD_ALIGNED);
714  ci_RF.joint1_placement.setRandom();
715  ci_RF.joint2_placement.setRandom();
716  ci_RF_bis.joint1_placement = ci_RF.joint2_placement;
717  ci_RF_bis.joint2_placement = ci_RF.joint1_placement;
718  contact_models.push_back(ci_RF);
719  contact_datas.push_back(RigidConstraintData(ci_RF));
720 
721  RigidConstraintModel ci_LF(CONTACT_6D, model, 0, model.getJointId(LF), LOCAL);
722  RigidConstraintModel ci_LF_bis(CONTACT_6D, model, model.getJointId(LF), LOCAL);
723  ci_LF.joint1_placement.setRandom();
724  ci_LF.joint2_placement.setRandom();
725  ci_LF_bis.joint1_placement = ci_LF.joint2_placement;
726  ci_LF_bis.joint2_placement = ci_LF.joint1_placement;
727  contact_models.push_back(ci_LF);
728  contact_datas.push_back(RigidConstraintData(ci_LF));
729 
730  RigidConstraintModel ci_RA(CONTACT_6D, model, 0, model.getJointId(RA), LOCAL);
731  RigidConstraintModel ci_RA_bis(CONTACT_6D, model, model.getJointId(RA), LOCAL);
732  ci_RA.joint1_placement.setRandom();
733  ci_RA.joint2_placement.setRandom();
734  ci_RA_bis.joint1_placement = ci_RA.joint2_placement;
735  ci_RA_bis.joint2_placement = ci_RA.joint1_placement;
736  contact_models.push_back(ci_RA);
737  contact_datas.push_back(RigidConstraintData(ci_RA));
738 
739  Eigen::DenseIndex constraint_dim = 0;
740  for (size_t k = 0; k < contact_models.size(); ++k)
742 
743  const double mu0 = 0.;
744 
745  Eigen::MatrixXd J_ref(constraint_dim, model.nv);
746  J_ref.setZero();
747 
748  computeAllTerms(model, data_ref, q, v);
749  data_ref.M.triangularView<Eigen::StrictlyLower>() =
750  data_ref.M.transpose().triangularView<Eigen::StrictlyLower>();
751 
752  updateFramePlacements(model, data_ref);
753  Data::Matrix6x J_RF(6, model.nv), J_LF(6, model.nv), J_RA(6, model.nv);
754  J_RF.setZero();
755  J_LF.setZero();
756  J_RA.setZero();
757  Data::Matrix6x J_RF_local(6, model.nv), J_LF_local(6, model.nv), J_RA_local(6, model.nv);
758  J_RF_local.setZero();
759  J_LF_local.setZero();
760  J_RA_local.setZero();
761  getJointJacobian(model, data_ref, ci_RF.joint2_id, WORLD, J_RF);
762  getJointJacobian(model, data_ref, ci_RF.joint2_id, LOCAL, J_RF_local);
763  getJointJacobian(model, data_ref, ci_LF.joint2_id, WORLD, J_LF);
764  getJointJacobian(model, data_ref, ci_LF.joint2_id, LOCAL, J_LF_local);
765  getJointJacobian(model, data_ref, ci_RA.joint2_id, WORLD, J_RA);
766  getJointJacobian(model, data_ref, ci_RA.joint2_id, LOCAL, J_RA_local);
767 
768  {
769  const SE3 oMc(
770  SE3::Matrix3::Identity(),
771  (data_ref.oMi[ci_RF.joint1_id] * ci_RF.joint1_placement).translation());
772  J_ref.middleRows<6>(0) = -oMc.toActionMatrixInverse() * J_RF;
773  }
774 
775  {
776  J_ref.middleRows<6>(6) =
777  -(data_ref.oMi[ci_LF.joint1_id] * ci_LF.joint1_placement).toActionMatrixInverse() * J_LF;
778  }
779 
780  {
781  J_ref.middleRows<6>(12) =
782  -(data_ref.oMi[ci_RA.joint1_id] * ci_RA.joint1_placement).toActionMatrixInverse() * J_RA;
783  }
784 
785  Eigen::VectorXd rhs_ref(constraint_dim);
786 
787  forwardKinematics(model, data_ref, q, v, 0 * v);
788  const SE3 c1Mc2_1 = (data.oMi[ci_RF.joint1_id] * ci_RF.joint1_placement)
789  .actInv(data_ref.oMi[ci_RF.joint2_id] * ci_RF.joint2_placement);
790  SE3 c1Mc2_1_W(
791  (data_ref.oMi[ci_RF.joint2_id]).rotation(),
792  -(data_ref.oMi[ci_RF.joint1_id] * ci_RF.joint1_placement).translation()
793  + data_ref.oMi[ci_RF.joint2_id].translation());
794  Motion acc_1 = c1Mc2_1_W.act(data_ref.a[ci_RF.joint2_id]);
795 
796  const SE3 c1Mc2_2 = (data_ref.oMi[ci_LF.joint1_id] * ci_LF.joint1_placement)
797  .actInv(data_ref.oMi[ci_LF.joint2_id] * ci_LF.joint2_placement);
798  Motion acc_2 = c1Mc2_2.act(ci_LF.joint2_placement.actInv(data_ref.a[ci_LF.joint2_id]));
799 
800  const SE3 c1Mc2_3 = (data_ref.oMi[ci_RA.joint1_id] * ci_RA.joint1_placement)
801  .actInv(data_ref.oMi[ci_RA.joint2_id] * ci_RA.joint2_placement);
802  Motion acc_3 = c1Mc2_3.act(ci_RA.joint2_placement.actInv(data_ref.a[ci_RA.joint2_id]));
803 
804  rhs_ref.segment<6>(0) = -acc_1.toVector();
805  rhs_ref.segment<6>(6) = -acc_2.toVector();
806  rhs_ref.segment<6>(12) = -acc_3.toVector();
807 
808  Eigen::MatrixXd KKT_matrix_ref =
809  Eigen::MatrixXd::Zero(model.nv + constraint_dim, model.nv + constraint_dim);
810  KKT_matrix_ref.topLeftCorner(constraint_dim, constraint_dim).diagonal().fill(-mu0);
811  KKT_matrix_ref.bottomRightCorner(model.nv, model.nv) = data_ref.M;
812  KKT_matrix_ref.topRightCorner(constraint_dim, model.nv) = J_ref;
813  KKT_matrix_ref.bottomLeftCorner(model.nv, constraint_dim) = J_ref.transpose();
814 
817  forwardDynamics(model, data_ref, q, v, tau, J_ref, rhs_ref, mu0);
819 
820  forwardKinematics(model, data_ref, q, v, 0 * data_ref.ddq);
821 
822  ProximalSettings prox_settings(1e-12, mu0, 1);
825 
826  std::cout << "acc_1 ref:\n" << acc_1 << std::endl;
827  std::cout << "acc_1:\n" << contact_datas[0].contact2_acceleration_drift << std::endl;
828  BOOST_CHECK(acc_1.isApprox(contact_datas[0].contact2_acceleration_drift));
829 
830  std::cout << "acc_2 ref:\n" << acc_2 << std::endl;
831  std::cout << "acc_2:\n" << contact_datas[1].contact2_acceleration_drift << std::endl;
832  BOOST_CHECK(acc_2.isApprox(contact_datas[1].contact2_acceleration_drift));
833 
834  std::cout << "acc_3 ref:\n" << acc_3 << std::endl;
835  std::cout << "acc_3:\n" << contact_datas[2].contact2_acceleration_drift << std::endl;
836  BOOST_CHECK(acc_3.isApprox(contact_datas[2].contact2_acceleration_drift));
837 
838  BOOST_CHECK(contact_datas[0].c1Mc2.isApprox(c1Mc2_1));
839 
840  const SE3 c1Mc2_1_LWA(
841  contact_datas[0].oMc2.rotation(), contact_datas[0].oMc1.rotation() * c1Mc2_1.translation());
842  BOOST_CHECK(
843  (c1Mc2_1_LWA.toActionMatrix() * (ci_RF.joint2_placement.toActionMatrixInverse() * J_RF_local))
844  .isApprox(-J_ref.middleRows<6>(0)));
845  BOOST_CHECK(contact_datas[0].oMc1.isApprox(ci_RF.joint1_placement));
846 
847  BOOST_CHECK(contact_datas[1].c1Mc2.isApprox(c1Mc2_2));
848  BOOST_CHECK(
849  (contact_datas[1].oMc1.toActionMatrixInverse() * J_LF).isApprox(-J_ref.middleRows<6>(6)));
850  BOOST_CHECK((data_ref.oMi[ci_LF.joint2_id].toActionMatrix() * J_LF_local).isApprox(J_LF));
851  BOOST_CHECK(contact_datas[1].oMc1.isApprox(ci_LF.joint1_placement));
852  BOOST_CHECK(data.oa[ci_LF.joint2_id].isApprox(
853  data_ref.oMi[ci_LF.joint2_id].act(data_ref.a[ci_LF.joint2_id])));
854 
855  BOOST_CHECK(contact_datas[2].c1Mc2.isApprox(c1Mc2_3));
856  BOOST_CHECK(
857  (c1Mc2_3.toActionMatrix() * (ci_RA.joint2_placement.toActionMatrixInverse() * J_RA_local))
858  .isApprox(-J_ref.middleRows<6>(12)));
859  BOOST_CHECK(contact_datas[2].oMc1.isApprox(ci_RA.joint1_placement));
860  BOOST_CHECK(data.oa[ci_RA.joint2_id].isApprox(
861  data_ref.oMi[ci_RA.joint2_id].act(data_ref.a[ci_RA.joint2_id])));
862 
863  // Check that the decomposition is correct
864 
865  forwardKinematics(model, data_ref, q, v, 0 * data_ref.ddq);
866  const Data::ContactCholeskyDecomposition & contact_chol = data.contact_chol;
867  Eigen::MatrixXd KKT_matrix = contact_chol.matrix();
868 
869  BOOST_CHECK(KKT_matrix.bottomRightCorner(model.nv, model.nv)
870  .isApprox(KKT_matrix_ref.bottomRightCorner(model.nv, model.nv)));
871  BOOST_CHECK(KKT_matrix.isApprox(KKT_matrix_ref));
872 
873  // Check solutions
874  forwardKinematics(model, data, q, v, data.ddq);
875  BOOST_CHECK(data.ddq.isApprox(data_ref.ddq));
876  BOOST_CHECK((J_ref * data.ddq + rhs_ref).isZero());
877 
878  Motion acc_1_final = c1Mc2_1_W.act(data.a[ci_RF.joint2_id]);
879  BOOST_CHECK(acc_1_final.isZero());
880 
881  std::cout << "acc_1_final:\n" << acc_1_final << std::endl;
882 
883  Motion acc_2_final = c1Mc2_2.act(data.a[ci_LF.joint2_id]);
884  BOOST_CHECK(acc_2_final.isZero());
885 
886  std::cout << "acc_2_final:\n" << acc_2_final << std::endl;
887 
888  Motion acc_3_final = c1Mc2_3.act(data.a[ci_RA.joint2_id]);
889  BOOST_CHECK(acc_3_final.isZero());
890 
891  std::cout << "acc_3_final:\n" << acc_3_final << std::endl;
892 
893  Eigen::DenseIndex constraint_id = 0;
894  for (size_t k = 0; k < contact_models.size(); ++k)
895  {
897  const RigidConstraintData & cdata = contact_datas[k];
898 
899  switch (cmodel.type)
900  {
901  case pinocchio::CONTACT_3D: {
902  BOOST_CHECK(cdata.contact_force.linear().isApprox(
903  data_ref.lambda_c.segment(constraint_id, cmodel.size())));
904  break;
905  }
906 
907  case pinocchio::CONTACT_6D: {
909  data_ref.lambda_c.segment<6>(constraint_id));
910  BOOST_CHECK(cdata.contact_force.isApprox(f_ref));
911  break;
912  }
913 
914  default:
915  break;
916  }
917 
918  constraint_id += cmodel.size();
919  }
920 
921  // Contact models and data
924 
925  contact_models_bis.push_back(ci_RF_bis);
926  contact_models_bis.push_back(ci_LF_bis);
927  contact_models_bis.push_back(ci_RA_bis);
928 
930  contact_models_bis.begin();
931  it != contact_models_bis.end(); ++it)
932  contact_datas_bis.push_back(RigidConstraintData(*it));
933 
934  Data data_bis(model);
935  initConstraintDynamics(model, data_bis, contact_models_bis);
937  model, data_bis, q, v, tau, contact_models_bis, contact_datas_bis, prox_settings);
938 
939  BOOST_CHECK(data_bis.ddq.isApprox(data.ddq));
940  std::cout << "ddq: " << data_bis.ddq.transpose() << std::endl;
941  std::cout << "ddq: " << data.ddq.transpose() << std::endl;
942 
943  // Eigen::DenseIndex constraint_id = 0;
944  for (size_t k = 0; k < contact_models.size(); ++k)
945  {
947  const RigidConstraintData & cdata = contact_datas[k];
948  const RigidConstraintModel & cmodel_bis = contact_models_bis[k];
949  const RigidConstraintData & cdata_bis = contact_datas_bis[k];
950 
951  BOOST_CHECK(cmodel_bis.reference_frame == cmodel.reference_frame);
952  BOOST_CHECK(cmodel_bis.joint1_id == cmodel.joint2_id);
953  BOOST_CHECK(cmodel_bis.joint2_id == cmodel.joint1_id);
954  BOOST_CHECK(cdata.oMc1.isApprox(cdata_bis.oMc2));
955  BOOST_CHECK(cdata.oMc2.isApprox(cdata_bis.oMc1));
956  BOOST_CHECK(cdata.c1Mc2.isApprox(cdata_bis.c1Mc2.inverse()));
957 
958  std::cout << "cdata.c1Mc2:\n" << cdata.c1Mc2 << std::endl;
959  Force contact_force, contact_force_bis;
960  switch (cmodel.reference_frame)
961  {
962  case LOCAL_WORLD_ALIGNED: {
963  SE3 c1Mc2_LWA(SE3::Matrix3::Identity(), cdata.oMc1.rotation() * cdata.c1Mc2.translation());
964  contact_force_bis = cdata_bis.contact_force;
965  BOOST_CHECK(cdata_bis.contact1_acceleration_drift.isApprox(
966  c1Mc2_LWA.actInv(cdata.contact2_acceleration_drift)));
967 
968  contact_force = c1Mc2_LWA.actInv(cdata.contact_force);
969  BOOST_CHECK(contact_force.isApprox(-contact_force_bis));
970  break;
971  }
972  case LOCAL: {
973  contact_force_bis = cdata_bis.contact_force;
974  BOOST_CHECK(cdata_bis.contact1_acceleration_drift.isApprox(
975  cdata.c1Mc2.actInv(cdata.contact2_acceleration_drift)));
976 
977  contact_force = cdata.c1Mc2.actInv(cdata.contact_force);
978  BOOST_CHECK(contact_force.isApprox(-contact_force_bis));
979  break;
980  }
981  case WORLD:
982  BOOST_CHECK(false);
983  break;
984  }
985 
986  std::cout << "contact_force: " << contact_force.toVector().transpose() << std::endl;
987  std::cout << "contact_force_bis: " << contact_force_bis.toVector().transpose() << std::endl;
988  }
989 }
990 
994 {
996  for (size_t k = 0; k < contact_models.size(); ++k)
998 
999  return contact_datas;
1000 }
1001 
1002 BOOST_AUTO_TEST_CASE(test_correction_CONTACT_6D)
1003 {
1004  using namespace Eigen;
1005  using namespace pinocchio;
1006 
1008  // pinocchio::buildModels::humanoidRandom(model,true);
1009  const JointIndex joint_id = model.addJoint(0, JointModelFreeFlyer(), SE3::Identity(), "root");
1010  const Inertia box_inertia = Inertia::FromBox(100., 1., 1., 1.);
1011  model.appendBodyToJoint(joint_id, box_inertia);
1012  pinocchio::Data data(model), data_ref(model);
1013 
1014  model.lowerPositionLimit.head<3>().fill(-1.);
1015  model.upperPositionLimit.head<3>().fill(1.);
1016  VectorXd q = randomConfiguration(model);
1017 
1018  VectorXd v = VectorXd::Random(model.nv);
1019  VectorXd tau = VectorXd::Random(model.nv);
1020 
1021  const std::string RF = "root";
1022  const JointIndex RF_id = model.getJointId(RF);
1023 
1024  // Contact models and data
1026 
1027  RigidConstraintModel ci_RF(CONTACT_6D, model, RF_id, LOCAL);
1028  ci_RF.joint1_placement.setIdentity();
1029  ci_RF.joint2_placement.setIdentity();
1030  ci_RF.corrector.Kp.setConstant(10.);
1031  ci_RF.corrector.Kd = 2. * ci_RF.corrector.Kp.cwiseSqrt();
1032  contact_models.push_back(ci_RF);
1033 
1038 
1039  BOOST_CHECK(contact_datas[0].oMc1.isApprox(data.oMi[ci_RF.joint1_id] * ci_RF.joint1_placement));
1040  BOOST_CHECK(contact_datas[0].oMc2.isApprox(data.oMi[ci_RF.joint2_id] * ci_RF.joint2_placement));
1041  BOOST_CHECK(contact_datas[0].contact1_velocity.isApprox(
1042  contact_datas[0].oMc1.actInv(data.ov[ci_RF.joint1_id])));
1043  BOOST_CHECK(contact_datas[0].contact2_velocity.isZero());
1044 
1045  const double dt = 1e-8;
1046  const VectorXd q_plus = integrate(model, q, v * dt);
1047 
1048  Data data_plus(model);
1050  contact_datas_plus = createData(contact_models);
1052  constraintDynamics(model, data_plus, q_plus, v, tau, contact_models, contact_datas_plus);
1053 
1054  const Motion contact_RF_velocity_error_fd =
1055  log6(contact_datas[0].c1Mc2.act(contact_datas_plus[0].c1Mc2.inverse())) / dt;
1056  BOOST_CHECK(
1057  contact_RF_velocity_error_fd.isApprox(contact_datas[0].contact_velocity_error, sqrt(dt)));
1058  std::cout << "contact_RF_velocity_error_fd:\n" << contact_RF_velocity_error_fd << std::endl;
1059  std::cout << "contact_velocity_error:\n" << contact_datas[0].contact_velocity_error << std::endl;
1060 
1061  // Simulation loop
1062  {
1063  const int N = 200;
1064  const double dt = 1e-3;
1065  const double mu = 1e-12;
1066 
1067  // model.gravity.setZero();
1068  Data data_sim(model);
1070  contact_data_sim = createData(contact_models);
1072 
1073  Eigen::VectorXd q0(model.nq);
1074  const SE3 M0 = SE3::Random();
1075  q0 << M0.translation(), SE3::Quaternion(M0.rotation()).coeffs();
1076  const Eigen::VectorXd v0 = Eigen::VectorXd::Zero(model.nv);
1077  Eigen::VectorXd a = Eigen::VectorXd(model.nv);
1078  Eigen::VectorXd tau = Eigen::VectorXd::Zero(model.nv);
1079 
1080  Eigen::VectorXd q(q0), v(v0);
1081 
1082  tau = rnea(model, data_sim, q, v, Eigen::VectorXd::Zero(model.nv));
1083  ProximalSettings prox_settings(1e-12, mu, 1);
1085  model, data_sim, q0, v0, tau, contact_models, contact_data_sim, prox_settings);
1087  contact_data_sim_prev(contact_data_sim);
1088 
1089  for (int it = 0; it <= N; it++)
1090  {
1092  model, data_sim, q, v, tau, contact_models, contact_data_sim, prox_settings);
1093  v += a * dt;
1094  q = integrate(model, q, v * dt);
1095 
1096  if (it > 1)
1097  {
1098  for (size_t k = 0; k < contact_models.size(); ++k)
1099  {
1100  const RigidConstraintData & cdata = contact_data_sim[k];
1101  const RigidConstraintData & cdata_prev = contact_data_sim_prev[k];
1102 
1103  BOOST_CHECK(
1104  cdata.contact_placement_error.toVector().norm()
1105  <= cdata_prev.contact_placement_error.toVector().norm());
1106  }
1107  }
1108 
1109  contact_data_sim_prev = contact_data_sim;
1110  }
1111  }
1112 }
1113 
1114 BOOST_AUTO_TEST_CASE(test_correction_CONTACT_3D)
1115 {
1116  using namespace Eigen;
1117  using namespace pinocchio;
1118 
1120  // pinocchio::buildModels::humanoidRandom(model,true);
1121  const JointIndex joint_id = model.addJoint(0, JointModelFreeFlyer(), SE3::Identity(), "root");
1122  const Inertia box_inertia = Inertia::FromBox(100., 1., 1., 1.);
1123  model.appendBodyToJoint(joint_id, box_inertia);
1124  pinocchio::Data data(model), data_ref(model);
1125 
1126  model.lowerPositionLimit.head<3>().fill(-1.);
1127  model.upperPositionLimit.head<3>().fill(1.);
1128  VectorXd q = randomConfiguration(model);
1129 
1130  VectorXd v = VectorXd::Random(model.nv);
1131  VectorXd tau = VectorXd::Random(model.nv);
1132 
1133  const double mu = 1e-8;
1134  const std::string RF = "root";
1135  const JointIndex RF_id = model.getJointId(RF);
1136 
1137  // Contact models and data
1139 
1140  RigidConstraintModel ci_RF1(CONTACT_3D, model, RF_id, LOCAL);
1141  ci_RF1.joint1_placement.translation() = SE3::Vector3(0.5, 0.5, -0.5);
1142  ci_RF1.joint2_placement.setRandom();
1143  ci_RF1.corrector.Kp.setConstant(10.);
1144  ci_RF1.corrector.Kd = 2. * ci_RF1.corrector.Kp.cwiseSqrt();
1145  contact_models.push_back(ci_RF1);
1146 
1147  RigidConstraintModel ci_RF2(CONTACT_3D, model, RF_id, LOCAL);
1148  ci_RF2.joint1_placement.translation() = SE3::Vector3(-0.5, 0.5, -0.5);
1149  ci_RF2.joint2_placement.setRandom();
1150  ci_RF2.corrector.Kp.setConstant(10.);
1151  ci_RF2.corrector.Kd = 2. * ci_RF2.corrector.Kp.cwiseSqrt();
1152  contact_models.push_back(ci_RF2);
1153 
1154  RigidConstraintModel ci_RF3(CONTACT_3D, model, RF_id, LOCAL);
1155  ci_RF3.joint1_placement.translation() = SE3::Vector3(-0.5, -0.5, -0.5);
1156  ci_RF3.joint2_placement.setRandom();
1157  ci_RF3.corrector.Kp.setConstant(10.);
1158  ci_RF3.corrector.Kd = 2. * ci_RF3.corrector.Kp.cwiseSqrt();
1159  contact_models.push_back(ci_RF3);
1160 
1161  RigidConstraintModel ci_RF4(CONTACT_3D, model, RF_id, LOCAL);
1162  ci_RF4.joint1_placement.translation() = SE3::Vector3(0.5, -0.5, -0.5);
1163  ci_RF4.joint2_placement.setRandom();
1164  ci_RF4.corrector.Kp.setConstant(10.);
1165  ci_RF4.corrector.Kd = 2. * ci_RF4.corrector.Kp.cwiseSqrt();
1166  contact_models.push_back(ci_RF4);
1167 
1170  ProximalSettings prox_settings(1e-12, mu, 1);
1173 
1174  Eigen::VectorXd contact_placement_error_prev(contact_models.size() * 6);
1175  Eigen::VectorXd contact_placement_error(contact_models.size() * 6);
1176  contact_placement_error_prev.setZero();
1177  contact_placement_error.setZero();
1178 
1179  // Simulation loop
1180  {
1181  const int N = 200;
1182  const double dt = 1e-3;
1183 
1184  // model.gravity.setZero();
1185  Data data_sim(model);
1187  contact_data_sim = createData(contact_models);
1189 
1190  Eigen::VectorXd q0(model.nq);
1191  const SE3 M0 = SE3::Random();
1192  q0 << M0.translation(), SE3::Quaternion(M0.rotation()).coeffs();
1193  const Eigen::VectorXd v0 = Eigen::VectorXd::Zero(model.nv);
1194  Eigen::VectorXd a = Eigen::VectorXd(model.nv);
1195  Eigen::VectorXd tau = Eigen::VectorXd::Zero(model.nv);
1196 
1197  Eigen::VectorXd q(q0), v(v0);
1198 
1200  model, data_sim, q0, v0, tau, contact_models, contact_data_sim, prox_settings);
1202  contact_data_sim_prev(contact_data_sim);
1203 
1204  for (int it = 0; it <= N; it++)
1205  {
1207  model, data_sim, q, v, tau, contact_models, contact_data_sim, prox_settings);
1208  v += a * dt;
1209  q = integrate(model, q, v * dt);
1210 
1211  if (it > 1)
1212  {
1213  for (size_t k = 0; k < contact_models.size(); ++k)
1214  {
1215  const RigidConstraintData & cdata = contact_data_sim[k];
1216  const RigidConstraintData & cdata_prev = contact_data_sim_prev[k];
1217  contact_placement_error.segment<6>(6 * (Eigen::Index)k) =
1218  cdata.contact_placement_error.toVector();
1219  contact_placement_error_prev.segment<6>(6 * (Eigen::Index)k) =
1220  cdata_prev.contact_placement_error.toVector();
1221  }
1222  BOOST_CHECK(contact_placement_error.norm() <= contact_placement_error_prev.norm());
1223  }
1224  contact_data_sim_prev = contact_data_sim;
1225  }
1226  }
1227 }
1228 
1229 BOOST_AUTO_TEST_CASE(test_sparse_forward_dynamics_in_contact_specifying_joint2id_case3D)
1230 {
1231  using namespace Eigen;
1232  using namespace pinocchio;
1233 
1236  pinocchio::Data data(model), data_ref(model);
1237 
1238  model.lowerPositionLimit.head<3>().fill(-1.);
1239  model.upperPositionLimit.head<3>().fill(1.);
1240  VectorXd q = randomConfiguration(model);
1241 
1242  VectorXd v = VectorXd::Random(model.nv);
1243  VectorXd tau = VectorXd::Random(model.nv);
1244 
1245  const std::string RF = "rleg6_joint";
1246  const std::string LF = "lleg6_joint";
1247  const std::string RA = "rarm6_joint";
1248 
1249  // Contact models and data
1252 
1253  RigidConstraintModel ci_RF(CONTACT_3D, model, 0, model.getJointId(RF), LOCAL_WORLD_ALIGNED);
1254  RigidConstraintModel ci_RF_bis(CONTACT_3D, model, model.getJointId(RF), LOCAL_WORLD_ALIGNED);
1255  ci_RF.joint1_placement.setRandom();
1256  ci_RF.joint2_placement.setRandom();
1257  ci_RF_bis.joint1_placement = ci_RF.joint2_placement;
1258  ci_RF_bis.joint2_placement = ci_RF.joint1_placement;
1259  contact_models.push_back(ci_RF);
1260  contact_datas.push_back(RigidConstraintData(ci_RF));
1261 
1262  RigidConstraintModel ci_LF(CONTACT_3D, model, 0, model.getJointId(LF), LOCAL);
1263  RigidConstraintModel ci_LF_bis(CONTACT_3D, model, model.getJointId(LF), LOCAL);
1264  ci_LF.joint1_placement.setRandom();
1265  ci_LF.joint2_placement.setRandom();
1266  ci_LF_bis.joint1_placement = ci_LF.joint2_placement;
1267  ci_LF_bis.joint2_placement = ci_LF.joint1_placement;
1268  contact_models.push_back(ci_LF);
1269  contact_datas.push_back(RigidConstraintData(ci_LF));
1270 
1271  RigidConstraintModel ci_RA(CONTACT_6D, model, 0, model.getJointId(RA), LOCAL);
1272  RigidConstraintModel ci_RA_bis(CONTACT_6D, model, model.getJointId(RA), LOCAL);
1273  ci_RA.joint1_placement.setRandom();
1274  ci_RA.joint2_placement.setRandom();
1275  ci_RA_bis.joint1_placement = ci_RA.joint2_placement;
1276  ci_RA_bis.joint2_placement = ci_RA.joint1_placement;
1277  contact_models.push_back(ci_RA);
1278  contact_datas.push_back(RigidConstraintData(ci_RA));
1279 
1280  Eigen::DenseIndex constraint_dim = 0;
1281  for (size_t k = 0; k < contact_models.size(); ++k)
1283 
1284  const double mu0 = 0.;
1285 
1286  Eigen::MatrixXd J_ref(constraint_dim, model.nv);
1287  J_ref.setZero();
1288 
1289  computeAllTerms(model, data_ref, q, v);
1290  data_ref.M.triangularView<Eigen::StrictlyLower>() =
1291  data_ref.M.transpose().triangularView<Eigen::StrictlyLower>();
1292 
1293  Data::Matrix6x J_RF(6, model.nv), J_LF(6, model.nv), J_RA(6, model.nv);
1294  J_RF.setZero();
1295  J_LF.setZero();
1296  J_RA.setZero();
1297  Data::Matrix6x J_RF_local(6, model.nv), J_LF_local(6, model.nv), J_RA_local(6, model.nv);
1298  J_RF_local.setZero();
1299  J_LF_local.setZero();
1300  J_RA_local.setZero();
1301  getJointJacobian(model, data_ref, ci_RF.joint2_id, WORLD, J_RF);
1302  getJointJacobian(model, data_ref, ci_RF.joint2_id, LOCAL, J_RF_local);
1303  J_RF_local = ci_RF.joint2_placement.toActionMatrixInverse() * J_RF_local;
1304  getJointJacobian(model, data_ref, ci_LF.joint2_id, WORLD, J_LF);
1305  getJointJacobian(model, data_ref, ci_LF.joint2_id, LOCAL, J_LF_local);
1306  J_LF_local = ci_LF.joint2_placement.toActionMatrixInverse() * J_LF_local;
1307  getJointJacobian(model, data_ref, ci_RA.joint2_id, WORLD, J_RA);
1308  getJointJacobian(model, data_ref, ci_RA.joint2_id, LOCAL, J_RA_local);
1309 
1310  {
1311  const SE3 oMc2 = data_ref.oMi[ci_RF.joint2_id] * ci_RF.joint2_placement;
1312  J_ref.middleRows<3>(0) = -oMc2.rotation() * J_RF_local.middleRows<3>(Motion::LINEAR);
1313  }
1314 
1315  {
1316  const SE3 oMc1 = data_ref.oMi[ci_LF.joint1_id] * ci_LF.joint1_placement;
1317  const SE3 oMc2 = data_ref.oMi[ci_LF.joint2_id] * ci_LF.joint2_placement;
1318  const SE3 c1Mc2 = oMc1.actInv(oMc2);
1319  J_ref.middleRows<3>(3) = -c1Mc2.rotation() * J_LF_local.middleRows<3>(SE3::LINEAR);
1320  }
1321 
1322  {
1323  J_ref.middleRows<6>(6) =
1324  -(data_ref.oMi[ci_RA.joint1_id] * ci_RA.joint1_placement).toActionMatrixInverse() * J_RA;
1325  }
1326 
1327  Eigen::VectorXd rhs_ref(constraint_dim);
1328 
1329  forwardKinematics(model, data_ref, q, v, 0 * v);
1330  Motion::Vector3 acc_1;
1331  {
1332  const SE3 oMc2 = data_ref.oMi[ci_RF.joint2_id] * ci_RF.joint2_placement;
1333  const Motion v2 = ci_RF.joint2_placement.actInv(data_ref.v[ci_RF.joint2_id]);
1334  const Motion a2 = ci_RF.joint2_placement.actInv(data_ref.a[ci_RF.joint2_id]);
1335  acc_1 = oMc2.rotation() * (a2.linear() + v2.angular().cross(v2.linear()));
1336  }
1337 
1338  Motion::Vector3 acc_2;
1339  {
1340  const SE3 oMc1 = data_ref.oMi[ci_LF.joint1_id] * ci_LF.joint1_placement;
1341  const SE3 oMc2 = data_ref.oMi[ci_LF.joint2_id] * ci_LF.joint2_placement;
1342  const SE3 c1Mc2 = oMc1.actInv(oMc2);
1343  const Motion v2 = ci_LF.joint2_placement.actInv(data_ref.v[ci_LF.joint2_id]);
1344  const Motion a2 = ci_LF.joint2_placement.actInv(data_ref.a[ci_LF.joint2_id]);
1345  acc_2 = c1Mc2.rotation() * (a2.linear() + v2.angular().cross(v2.linear()));
1346  }
1347 
1348  const SE3 c1Mc2_3 = (data_ref.oMi[ci_RA.joint1_id] * ci_RA.joint1_placement)
1349  .actInv(data_ref.oMi[ci_RA.joint2_id] * ci_RA.joint2_placement);
1350  Motion acc_3 = c1Mc2_3.act(ci_RA.joint2_placement.actInv(data_ref.a[ci_RA.joint2_id]));
1351 
1352  rhs_ref.segment<3>(0) = -acc_1;
1353  rhs_ref.segment<3>(3) = -acc_2;
1354  rhs_ref.segment<6>(6) = -acc_3.toVector();
1355 
1356  Eigen::MatrixXd KKT_matrix_ref =
1357  Eigen::MatrixXd::Zero(model.nv + constraint_dim, model.nv + constraint_dim);
1358  KKT_matrix_ref.topLeftCorner(constraint_dim, constraint_dim).diagonal().fill(-mu0);
1359  KKT_matrix_ref.bottomRightCorner(model.nv, model.nv) = data_ref.M;
1360  KKT_matrix_ref.topRightCorner(constraint_dim, model.nv) = J_ref;
1361  KKT_matrix_ref.bottomLeftCorner(model.nv, constraint_dim) = J_ref.transpose();
1362 
1365  forwardDynamics(model, data_ref, q, v, tau, J_ref, rhs_ref, mu0);
1367 
1368  forwardKinematics(model, data_ref, q, v, 0 * data_ref.ddq);
1369 
1370  ProximalSettings prox_settings(1e-12, 0, 1);
1373 
1374  const Data::ContactCholeskyDecomposition & contact_chol = data.contact_chol;
1375  Eigen::MatrixXd KKT_matrix = contact_chol.matrix();
1376 
1377  BOOST_CHECK(KKT_matrix.bottomRightCorner(model.nv, model.nv)
1378  .isApprox(KKT_matrix_ref.bottomRightCorner(model.nv, model.nv)));
1379  BOOST_CHECK(KKT_matrix.topRightCorner(constraint_dim, model.nv).isApprox(J_ref));
1380  BOOST_CHECK(KKT_matrix.isApprox(KKT_matrix_ref));
1381 
1382  std::cout << "KKT_matrix.topRightCorner(constraint_dim,model.nv):\n"
1383  << KKT_matrix.topRightCorner(constraint_dim, model.nv) << std::endl;
1384  std::cout << "KKT_matrix_ref.topRightCorner(constraint_dim,model.nv):\n"
1385  << KKT_matrix_ref.topRightCorner(constraint_dim, model.nv) << std::endl;
1386 
1387  // Check solutions
1388  forwardKinematics(model, data, q, v, data.ddq);
1389  BOOST_CHECK(data.ddq.isApprox(data_ref.ddq));
1390  BOOST_CHECK((J_ref * data.ddq + rhs_ref).isZero());
1391 
1392  std::cout << "data_ref.ddq: " << data_ref.ddq.transpose() << std::endl;
1393  std::cout << "data.ddq: " << data.ddq.transpose() << std::endl;
1394  std::cout << "res: " << (J_ref * data.ddq + rhs_ref).transpose() << std::endl;
1395  std::cout << "res_ref: " << (J_ref * data_ref.ddq + rhs_ref).transpose() << std::endl;
1396 
1397  const Motion vel_1_final = ci_RF.joint2_placement.actInv(data.v[ci_RF.joint2_id]);
1398  const Motion::Vector3 acc_1_final =
1399  ci_RF.joint2_placement.actInv(data.a[ci_RF.joint2_id]).linear()
1400  + vel_1_final.angular().cross(vel_1_final.linear());
1401  BOOST_CHECK(acc_1_final.isZero());
1402 
1403  std::cout << "acc_1_final:" << acc_1_final.transpose() << std::endl;
1404 
1405  const Motion vel_2_final = ci_LF.joint2_placement.actInv(data.v[ci_LF.joint2_id]);
1406  const Motion::Vector3 acc_2_final =
1407  ci_LF.joint2_placement.actInv(data.a[ci_LF.joint2_id]).linear()
1408  + vel_2_final.angular().cross(vel_2_final.linear());
1409  BOOST_CHECK(acc_2_final.isZero());
1410 
1411  std::cout << "acc_2_final:" << acc_2_final.transpose() << std::endl;
1412 
1413  Motion acc_3_final = c1Mc2_3.act(data.a[ci_RA.joint2_id]);
1414  BOOST_CHECK(acc_3_final.isZero());
1415 
1416  std::cout << "acc_3_final:\n" << acc_3_final << std::endl;
1417 
1418  Eigen::DenseIndex constraint_id = 0;
1419  for (size_t k = 0; k < contact_models.size(); ++k)
1420  {
1422  const RigidConstraintData & cdata = contact_datas[k];
1423 
1424  switch (cmodel.type)
1425  {
1426  case pinocchio::CONTACT_3D: {
1427  BOOST_CHECK(cdata.contact_force.linear().isApprox(
1428  data_ref.lambda_c.segment(constraint_id, cmodel.size())));
1429  break;
1430  }
1431 
1432  case pinocchio::CONTACT_6D: {
1434  data_ref.lambda_c.segment<6>(constraint_id));
1435  BOOST_CHECK(cdata.contact_force.isApprox(f_ref));
1436  break;
1437  }
1438 
1439  default:
1440  break;
1441  }
1442 
1443  constraint_id += cmodel.size();
1444  }
1445 
1446  // Contact models and data
1449 
1450  contact_models_bis.push_back(ci_RF_bis);
1451  contact_models_bis.push_back(ci_LF_bis);
1452  contact_models_bis.push_back(ci_RA_bis);
1453 
1455  contact_models_bis.begin();
1456  it != contact_models_bis.end(); ++it)
1457  contact_datas_bis.push_back(RigidConstraintData(*it));
1458 
1459  Data data_bis(model);
1460  initConstraintDynamics(model, data_bis, contact_models_bis);
1462  model, data_bis, q, v, tau, contact_models_bis, contact_datas_bis, prox_settings);
1463 
1464  BOOST_CHECK(data_bis.ddq.isApprox(data.ddq));
1465  std::cout << "ddq: " << data_bis.ddq.transpose() << std::endl;
1466  std::cout << "ddq: " << data.ddq.transpose() << std::endl;
1467 
1468  for (size_t k = 0; k < contact_models.size(); ++k)
1469  {
1471  const RigidConstraintData & cdata = contact_datas[k];
1472  const RigidConstraintModel & cmodel_bis = contact_models_bis[k];
1473  const RigidConstraintData & cdata_bis = contact_datas_bis[k];
1474 
1475  BOOST_CHECK(cmodel_bis.reference_frame == cmodel.reference_frame);
1476  BOOST_CHECK(cmodel_bis.joint1_id == cmodel.joint2_id);
1477  BOOST_CHECK(cmodel_bis.joint2_id == cmodel.joint1_id);
1478  BOOST_CHECK(cdata.oMc1.isApprox(cdata_bis.oMc2));
1479  BOOST_CHECK(cdata.oMc2.isApprox(cdata_bis.oMc1));
1480  BOOST_CHECK(cdata.c1Mc2.isApprox(cdata_bis.c1Mc2.inverse()));
1481 
1482  std::cout << "cdata.c1Mc2:\n" << cdata.c1Mc2 << std::endl;
1483  Force contact_force, contact_force_bis;
1484  switch (cmodel.reference_frame)
1485  {
1486  case LOCAL_WORLD_ALIGNED: {
1487  SE3 c1Mc2_LWA(SE3::Matrix3::Identity(), cdata.oMc1.rotation() * cdata.c1Mc2.translation());
1488  contact_force_bis = cdata_bis.contact_force;
1489 
1490  if (cmodel.type == CONTACT_3D)
1491  contact_force = cdata.contact_force;
1492  else
1493  {
1494  contact_force = c1Mc2_LWA.actInv(cdata.contact_force);
1495  BOOST_CHECK(cdata_bis.contact1_acceleration_drift.isApprox(
1496  c1Mc2_LWA.actInv(cdata.contact2_acceleration_drift)));
1497  }
1498  BOOST_CHECK(contact_force.isApprox(-contact_force_bis));
1499  break;
1500  }
1501  case LOCAL: {
1502  contact_force_bis = cdata_bis.contact_force;
1503 
1504  if (cmodel.type == CONTACT_3D)
1505  contact_force.linear() = cdata.c1Mc2.actInv(cdata.contact_force).linear();
1506  else
1507  {
1508  contact_force = cdata.c1Mc2.actInv(cdata.contact_force);
1509  BOOST_CHECK(cdata_bis.contact1_acceleration_drift.isApprox(
1510  cdata.c1Mc2.actInv(cdata.contact2_acceleration_drift)));
1511  }
1512  BOOST_CHECK(contact_force.isApprox(-contact_force_bis));
1513  break;
1514  }
1515  case WORLD:
1516  BOOST_CHECK(false);
1517  break;
1518  }
1519 
1520  std::cout << "contact_force: " << contact_force.toVector().transpose() << std::endl;
1521  std::cout << "contact_force_bis: " << contact_force_bis.toVector().transpose() << std::endl;
1522  }
1523 }
1524 
1525 BOOST_AUTO_TEST_CASE(test_contact_ABA_with_armature)
1526 {
1527  using namespace pinocchio;
1528  using namespace Eigen;
1529 
1532  model.rotorInertia =
1533  100. * (Model::VectorXs::Random(model.nv) + Model::VectorXs::Constant(model.nv, 1.));
1534  model.rotorGearRatio.fill(100);
1535 
1536  pinocchio::Data data(model), data_ref(model);
1537 
1538  model.lowerPositionLimit.head<3>().fill(-1.);
1539  model.upperPositionLimit.head<3>().fill(1.);
1540  VectorXd q = randomConfiguration(model);
1541 
1542  VectorXd v = VectorXd::Random(model.nv);
1543  VectorXd tau = VectorXd::Random(model.nv);
1544 
1546  RigidConstraintModelVector;
1547  typedef PINOCCHIO_STD_VECTOR_WITH_EIGEN_ALLOCATOR(RigidConstraintData) RigidConstraintDataVector;
1548  const RigidConstraintModelVector empty_rigid_contact_models;
1549  RigidConstraintDataVector empty_rigid_contact_data;
1550 
1551  const Data::VectorXs a =
1552  contactABA(model, data, q, v, tau, empty_rigid_contact_models, empty_rigid_contact_data);
1553  const Data::VectorXs tau_ref = rnea(model, data_ref, q, v, a);
1554 
1555  BOOST_CHECK(tau.isApprox(tau_ref));
1556 }
1557 
1558 BOOST_AUTO_TEST_CASE(test_diagonal_inertia)
1559 {
1560  using namespace pinocchio;
1561 
1562  const double mu = 1e2;
1563  const Inertia diagonal6_inertia(mu, Inertia::Vector3::Zero(), Symmetric3(mu, 0, mu, 0, 0, mu));
1564  const Inertia::Matrix6 diagonal6_inertia_mat = diagonal6_inertia.matrix();
1565  BOOST_CHECK(diagonal6_inertia_mat.block(Inertia::LINEAR, Inertia::ANGULAR, 3, 3).isZero());
1566  BOOST_CHECK(diagonal6_inertia_mat.block(Inertia::ANGULAR, Inertia::LINEAR, 3, 3).isZero());
1567 
1568  const SE3 M = SE3::Random();
1569  // const Inertia::Matrix3 RtRmu = mu * M.rotation().transpose()*M.rotation();
1570  const Inertia::Matrix3 RtRmu = mu * Inertia::Matrix3::Identity();
1571  Inertia I6_translate(mu, M.translation(), Symmetric3(RtRmu));
1572 
1573  const Inertia I6_ref = M.act(diagonal6_inertia);
1574  BOOST_CHECK(I6_translate.isApprox(I6_ref));
1575 
1576  const Inertia diagonal3_inertia(mu, Inertia::Vector3::Zero(), Symmetric3(0, 0, 0, 0, 0, 0));
1577  const Inertia::Matrix6 diagonal3_inertia_mat = diagonal3_inertia.matrix();
1578  BOOST_CHECK(diagonal3_inertia_mat.block(Inertia::LINEAR, Inertia::ANGULAR, 3, 3).isZero());
1579  BOOST_CHECK(diagonal3_inertia_mat.block(Inertia::ANGULAR, Inertia::LINEAR, 3, 3).isZero());
1580  BOOST_CHECK(diagonal3_inertia_mat.block(Inertia::ANGULAR, Inertia::ANGULAR, 3, 3).isZero());
1581 
1582  Inertia I3_translate(mu, M.translation(), Symmetric3(0, 0, 0, 0, 0, 0));
1583 
1584  const Inertia I3_ref = M.act(diagonal3_inertia);
1585  BOOST_CHECK(I3_translate.isApprox(I3_ref));
1586 }
1587 
1588 BOOST_AUTO_TEST_CASE(test_contact_ABA_6D)
1589 {
1590  using namespace Eigen;
1591  using namespace pinocchio;
1592 
1595  pinocchio::Data data(model), data_ref(model);
1596 
1597  model.lowerPositionLimit.head<3>().fill(-1.);
1598  model.upperPositionLimit.head<3>().fill(1.);
1599  VectorXd q = randomConfiguration(model);
1600 
1601  VectorXd v = VectorXd::Random(model.nv);
1602  VectorXd tau = VectorXd::Random(model.nv);
1603 
1604  const std::string RF = "rleg6_joint";
1605  // const Frame & RF_frame = model.frames[model.getJointId(RF)];
1606  // Frame RF_contact_frame("RF_contact_frame",
1607  // RF_frame.parent,model.getJointId(RF),
1608  // SE3::Random(),OP_FRAME);
1609  // model.addFrame(RF_contact_frame);
1610 
1611  const std::string LF = "lleg6_joint";
1612  // const Frame & LF_frame = model.frames[model.getJointId(LF)];
1613  // Frame LF_contact_frame("LF_contact_frame",
1614  // LF_frame.parent,model.getJointId(RF),
1615  // SE3::Random(),OP_FRAME);
1616  // model.addFrame(LF_contact_frame);
1617  // const Model::JointIndex LF_id = model.getJointId(LF);
1618 
1619  // Contact models and data
1621  RigidConstraintModelVector;
1622  typedef PINOCCHIO_STD_VECTOR_WITH_EIGEN_ALLOCATOR(RigidConstraintData) RigidConstraintDataVector;
1623 
1624  const RigidConstraintModelVector empty_contact_models;
1625  RigidConstraintDataVector empty_contact_data;
1626 
1627  contactABA(model, data, q, v, tau, empty_contact_models, empty_contact_data);
1628  forwardKinematics(model, data_ref, q, v, 0 * v);
1629  for (JointIndex joint_id = 1; joint_id < (JointIndex)model.njoints; ++joint_id)
1630  {
1631  BOOST_CHECK(data.liMi[joint_id].isApprox(data_ref.liMi[joint_id]));
1632  BOOST_CHECK(data.oMi[joint_id].isApprox(data_ref.oMi[joint_id]));
1633  BOOST_CHECK(data.ov[joint_id].isApprox(data_ref.oMi[joint_id].act(data_ref.v[joint_id])));
1634  if (data.oa_drift[joint_id].isZero())
1635  {
1636  BOOST_CHECK((data_ref.oMi[joint_id].act(data_ref.a[joint_id])).isZero());
1637  }
1638  else
1639  {
1640  BOOST_CHECK(
1641  data.oa_drift[joint_id].isApprox(data_ref.oMi[joint_id].act(data_ref.a[joint_id])));
1642  }
1643  }
1644 
1645  computeJointJacobians(model, data_ref, q);
1646  BOOST_CHECK(data.J.isApprox(data_ref.J));
1647  aba(model, data_ref, q, v, tau, Convention::LOCAL);
1648 
1649  for (JointIndex joint_id = 1; joint_id < (JointIndex)model.njoints; ++joint_id)
1650  {
1651  const Data::SE3 & oMi = data.oMi[joint_id];
1652  Eigen::MatrixXd U_ref = oMi.toDualActionMatrix() * data_ref.joints[joint_id].U();
1653  BOOST_CHECK(data.joints[joint_id].U().isApprox(U_ref));
1654  Eigen::MatrixXd StYS_ref =
1655  data_ref.joints[joint_id].S().matrix().transpose() * data_ref.joints[joint_id].U();
1656  BOOST_CHECK(data.joints[joint_id].StU().isApprox(StYS_ref));
1657  const Data::Matrix6 oYaba_ref =
1658  oMi.toDualActionMatrix() * data_ref.Yaba[joint_id] * oMi.inverse().toActionMatrix();
1659  BOOST_CHECK(data.oYaba[joint_id].isApprox(oYaba_ref));
1660  BOOST_CHECK(data.oa_augmented[joint_id].isApprox(
1661  model.gravity + data_ref.oMi[joint_id].act(data_ref.a_gf[joint_id])));
1662  }
1663 
1664  BOOST_CHECK(data.ddq.isApprox(data_ref.ddq));
1665 
1666  // Test second call
1667  contactABA(model, data, q, v, tau, empty_contact_models, empty_contact_data);
1668  BOOST_CHECK(data.ddq.isApprox(data_ref.ddq));
1669 
1670  RigidConstraintModelVector contact_models;
1671  RigidConstraintDataVector contact_datas;
1672  RigidConstraintModel ci_RF(CONTACT_6D, model, model.getJointId(RF), LOCAL);
1673  ci_RF.joint1_placement.setRandom();
1674  contact_models.push_back(ci_RF);
1675  contact_datas.push_back(RigidConstraintData(ci_RF));
1676  RigidConstraintModel ci_LF(CONTACT_6D, model, model.getJointId(LF), LOCAL);
1677  ci_LF.joint1_placement.setRandom();
1678  contact_models.push_back(ci_LF);
1679  contact_datas.push_back(RigidConstraintData(ci_LF));
1680 
1681  RigidConstraintDataVector contact_datas_ref(contact_datas);
1682 
1683  Eigen::DenseIndex constraint_dim = 0;
1684  for (size_t k = 0; k < contact_models.size(); ++k)
1686 
1687  const double mu0 = 0.;
1688 
1689  Eigen::MatrixXd J_ref(constraint_dim, model.nv);
1690  J_ref.setZero();
1691 
1692  ProximalSettings prox_settings_cd(1e-12, mu0, 1);
1695  model, data_ref, q, v, tau, contact_models, contact_datas_ref, prox_settings_cd);
1696  forwardKinematics(model, data_ref, q, v, v * 0);
1697 
1698  updateFramePlacements(model, data_ref);
1699  Data::Matrix6x Jtmp(6, model.nv);
1700 
1701  Jtmp.setZero();
1702  getJointJacobian(model, data_ref, ci_RF.joint1_id, ci_RF.reference_frame, Jtmp);
1703  J_ref.middleRows<6>(0) = ci_RF.joint1_placement.inverse().toActionMatrix() * Jtmp;
1704 
1705  Jtmp.setZero();
1706  getJointJacobian(model, data_ref, ci_LF.joint1_id, ci_LF.reference_frame, Jtmp);
1707  J_ref.middleRows<6>(6) = ci_LF.joint1_placement.inverse().toActionMatrix() * Jtmp;
1708 
1709  Eigen::VectorXd gamma(constraint_dim);
1710 
1711  gamma.segment<6>(0) =
1713  model, data_ref, ci_RF.joint1_id, ci_RF.reference_frame, ci_RF.type, ci_RF.joint1_placement)
1714  .toVector();
1715  gamma.segment<6>(6) =
1717  model, data_ref, ci_LF.joint1_id, ci_LF.reference_frame, ci_LF.type, ci_LF.joint1_placement)
1718  .toVector();
1719 
1720  BOOST_CHECK((J_ref * data_ref.ddq + gamma).isZero());
1721 
1722  Data data_constrained_dyn(model);
1723 
1726  forwardDynamics(model, data_constrained_dyn, q, v, tau, J_ref, gamma, mu0);
1728 
1729  BOOST_CHECK((J_ref * data_constrained_dyn.ddq + gamma).isZero());
1730 
1732  prox_settings.max_iter = 10;
1733  prox_settings.mu = 1e8;
1734  const double mu = prox_settings.mu;
1736 
1737  std::cout << "data.ddq: " << data.ddq.transpose() << std::endl;
1738  std::cout << "data_ref.ddq: " << data_ref.ddq.transpose() << std::endl;
1739  BOOST_CHECK((J_ref * data.ddq + gamma).isZero());
1740 
1741  forwardKinematics(model, data_ref, q, v, 0 * v);
1742  for (JointIndex joint_id = 1; joint_id < (JointIndex)model.njoints; ++joint_id)
1743  {
1744  if (data.oa_drift[joint_id].isZero())
1745  {
1746  BOOST_CHECK((data_ref.oMi[joint_id].act(data_ref.a[joint_id])).isZero());
1747  }
1748  else
1749  {
1750  BOOST_CHECK(
1751  data.oa_drift[joint_id].isApprox(data_ref.oMi[joint_id].act(data_ref.a[joint_id])));
1752  }
1753  }
1754 
1755  aba(model, data_ref, q, v, 0 * v, Convention::WORLD);
1756  for (size_t contact_id = 0; contact_id < contact_models.size(); ++contact_id)
1757  {
1758  const RigidConstraintModel & cmodel = contact_models[contact_id];
1759  const RigidConstraintData & cdata = contact_datas[contact_id];
1760 
1761  const JointIndex & joint1_id = cmodel.joint1_id;
1762 
1763  // Check contact placement
1764  const SE3 & iMc = cmodel.joint1_placement;
1765  const SE3 oMc = data_ref.oMi[joint1_id] * iMc;
1766  BOOST_CHECK(cdata.oMc1.isApprox(oMc));
1767 
1768  // Check contact velocity
1769  const Motion contact1_velocity_ref = iMc.actInv(data_ref.v[joint1_id]);
1770  BOOST_CHECK(cdata.contact1_velocity.isApprox(contact1_velocity_ref));
1771 
1772  // Check contact inertia
1773  Symmetric3 S(Symmetric3::Zero());
1774  if (cmodel.type == CONTACT_6D)
1775  S.setDiagonal(Symmetric3::Vector3::Constant(mu));
1776 
1777  const Inertia contact_inertia(mu, oMc.translation(), S);
1778 
1779  Inertia::Matrix6 contact_inertia_ref = Inertia::Matrix6::Zero();
1780 
1781  if (cmodel.type == CONTACT_6D)
1782  contact_inertia_ref.diagonal().fill(mu);
1783  else
1784  contact_inertia_ref.diagonal().head<3>().fill(mu);
1785  contact_inertia_ref =
1786  oMc.toDualActionMatrix() * contact_inertia_ref * oMc.toActionMatrixInverse();
1787  BOOST_CHECK(contact_inertia_ref.isApprox(contact_inertia.matrix()));
1788 
1789  Inertia::Matrix6 Yaba_ref = data_ref.oMi[joint1_id].toDualActionMatrix()
1790  * model.inertias[joint1_id].matrix()
1791  * data_ref.oMi[joint1_id].toActionMatrixInverse()
1792  + contact_inertia_ref;
1793 
1794  const JointModel & jmodel = model.joints[joint1_id];
1795  const JointData & jdata = data.joints[joint1_id];
1796  // const JointData & jdata_ref = data_ref.joints[joint_id];
1797 
1798  const MatrixXd U_ref = Yaba_ref * data_ref.J.middleCols(jmodel.idx_v(), jmodel.nv());
1799  const MatrixXd D_ref = data_ref.J.middleCols(jmodel.idx_v(), jmodel.nv()).transpose() * U_ref;
1800  const MatrixXd Dinv_ref = D_ref.inverse();
1801  const MatrixXd UDinv_ref = U_ref * Dinv_ref;
1802  BOOST_CHECK(jdata.U().isApprox(U_ref));
1803  BOOST_CHECK(jdata.StU().isApprox(D_ref));
1804  BOOST_CHECK(jdata.Dinv().isApprox(Dinv_ref));
1805  BOOST_CHECK(jdata.UDinv().isApprox(UDinv_ref));
1806 
1807  Yaba_ref -= UDinv_ref * U_ref.transpose();
1808 
1809  BOOST_CHECK(data.oYaba[joint1_id].isApprox(Yaba_ref));
1810  }
1811 
1812  // Call the algorithm a second time
1813  Data data2(model);
1814  ProximalSettings prox_settings2;
1815  contactABA(model, data2, q, v, tau, contact_models, contact_datas, prox_settings2);
1816 
1817  BOOST_CHECK(prox_settings2.iter == 0);
1818 }
1819 
1820 BOOST_AUTO_TEST_CASE(test_contact_ABA_3D)
1821 {
1822  using namespace Eigen;
1823  using namespace pinocchio;
1824 
1827  pinocchio::Data data(model), data_ref(model);
1828 
1829  model.lowerPositionLimit.head<3>().fill(-1.);
1830  model.upperPositionLimit.head<3>().fill(1.);
1831  VectorXd q = randomConfiguration(model);
1832 
1833  VectorXd v = VectorXd::Random(model.nv);
1834  VectorXd tau = VectorXd::Random(model.nv);
1835 
1836  const std::string RF = "rleg6_joint";
1837  // const Model::JointIndex RF_id = model.getJointId(RF);
1838  const std::string LF = "lleg6_joint";
1839  // const Model::JointIndex LF_id = model.getJointId(LF);
1840 
1841  // Contact models and data
1843  RigidConstraintModelVector;
1844  typedef PINOCCHIO_STD_VECTOR_WITH_EIGEN_ALLOCATOR(RigidConstraintData) RigidConstraintDataVector;
1845 
1846  RigidConstraintModelVector contact_models;
1847  RigidConstraintDataVector contact_datas;
1848  RigidConstraintModel ci_RF(CONTACT_3D, model, model.getJointId(RF), LOCAL);
1849  contact_models.push_back(ci_RF);
1850  contact_datas.push_back(RigidConstraintData(ci_RF));
1851  RigidConstraintModel ci_LF(CONTACT_3D, model, model.getJointId(LF), LOCAL);
1852  contact_models.push_back(ci_LF);
1853  contact_datas.push_back(RigidConstraintData(ci_LF));
1854 
1855  RigidConstraintDataVector contact_datas_ref(contact_datas);
1856 
1857  Eigen::DenseIndex constraint_dim = 0;
1858  for (size_t k = 0; k < contact_models.size(); ++k)
1860 
1861  Eigen::MatrixXd J_ref(constraint_dim, model.nv);
1862  J_ref.setZero();
1863 
1864  ProximalSettings prox_settings_cd(1e-12, 0, 1);
1867  model, data_ref, q, v, tau, contact_models, contact_datas_ref, prox_settings_cd);
1868  forwardKinematics(model, data_ref, q, v, v * 0);
1869 
1870  Data::Matrix6x Jtmp = Data::Matrix6x::Zero(6, model.nv);
1871  getJointJacobian(model, data_ref, ci_RF.joint1_id, ci_RF.reference_frame, Jtmp);
1872  J_ref.middleRows<3>(0) = Jtmp.middleRows<3>(Motion::LINEAR);
1873  Jtmp.setZero();
1874  getJointJacobian(model, data_ref, ci_LF.joint1_id, ci_LF.reference_frame, Jtmp);
1875  J_ref.middleRows<3>(3) = Jtmp.middleRows<3>(Motion::LINEAR);
1876 
1877  Eigen::VectorXd gamma(constraint_dim);
1878 
1879  gamma.segment<3>(0) =
1880  computeAcceleration(model, data_ref, ci_RF.joint1_id, ci_RF.reference_frame, ci_RF.type)
1881  .linear();
1882  gamma.segment<3>(3) =
1883  computeAcceleration(model, data_ref, ci_LF.joint1_id, ci_LF.reference_frame, ci_LF.type)
1884  .linear();
1885 
1886  BOOST_CHECK((J_ref * data_ref.ddq + gamma).isZero());
1887 
1888  Data data_constrained_dyn(model);
1889 
1892  forwardDynamics(model, data_constrained_dyn, q, v, tau, J_ref, gamma, 0.);
1894 
1895  BOOST_CHECK((J_ref * data_constrained_dyn.ddq + gamma).isZero());
1896 
1898  prox_settings.max_iter = 10;
1899  prox_settings.mu = 1e8;
1901 
1902  BOOST_CHECK((J_ref * data.ddq + gamma).isZero());
1903 
1904  // Call the algorithm a second time
1905  Data data2(model);
1906  ProximalSettings prox_settings2;
1907  contactABA(model, data2, q, v, tau, contact_models, contact_datas, prox_settings2);
1908 
1909  BOOST_CHECK(prox_settings2.iter == 0);
1910 }
1911 
1912 BOOST_AUTO_TEST_SUITE_END()
pinocchio::RigidConstraintData
RigidConstraintDataTpl< context::Scalar, context::Options > RigidConstraintData
Definition: algorithm/fwd.hpp:27
pinocchio::InertiaTpl< context::Scalar, context::Options >
pinocchio::DataTpl::M
MatrixXs M
The joint space inertia matrix (a square matrix of dim model.nv).
Definition: multibody/data.hpp:199
pinocchio::WORLD
@ WORLD
Definition: multibody/fwd.hpp:48
display-shapes-meshcat.placement
placement
Definition: display-shapes-meshcat.py:24
pinocchio::DataTpl::ddq
TangentVectorType ddq
The joint accelerations computed from ABA.
Definition: multibody/data.hpp:256
frames.hpp
Eigen
pinocchio::python::ContactCholeskyDecomposition
ContactCholeskyDecompositionTpl< context::Scalar, context::Options > ContactCholeskyDecomposition
Definition: admm-solver.cpp:33
pinocchio::DataTpl
Definition: context/generic.hpp:25
pinocchio::SE3Tpl::inverse
SE3Tpl inverse() const
aXb = bXa.inverse()
Definition: spatial/se3-tpl.hpp:149
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.
compute-all-terms.hpp
meshcat-viewer.v0
int v0
Definition: meshcat-viewer.py:88
pinocchio::ReferenceFrame
ReferenceFrame
Various conventions to express the velocity of a moving frame.
Definition: multibody/fwd.hpp:46
pinocchio::JointDataTpl::StU
D_t StU() const
Definition: joint-generic.hpp:153
pinocchio::SE3Tpl
Definition: context/casadi.hpp:29
kinematics.hpp
computeAcceleration
pinocchio::Motion computeAcceleration(const pinocchio::Model &model, pinocchio::Data &data, const pinocchio::JointIndex &joint_id, pinocchio::ReferenceFrame reference_frame, const pinocchio::ContactType type, const pinocchio::SE3 &placement=pinocchio::SE3::Identity())
Computes motions in the world frame.
Definition: unittest/constrained-dynamics.cpp:67
setup.data
data
Definition: cmake/cython/setup.in.py:48
PINOCCHIO_COMPILER_DIAGNOSTIC_POP
#define PINOCCHIO_COMPILER_DIAGNOSTIC_POP
Definition: include/pinocchio/macros.hpp:130
pinocchio::classicAcceleration
void classicAcceleration(const MotionDense< Motion1 > &spatial_velocity, const MotionDense< Motion2 > &spatial_acceleration, const Eigen::MatrixBase< Vector3Like > &res)
Computes the classic acceleration from a given spatial velocity and spatial acceleration.
Definition: spatial/classic-acceleration.hpp:29
pinocchio::buildModels::humanoidRandom
void humanoidRandom(ModelTpl< Scalar, Options, JointCollectionTpl > &model, bool usingFF=true)
Create a humanoid kinematic tree with 6-DOF limbs and random joint placements.
pinocchio::DataTpl::lambda_c
VectorXs lambda_c
Lagrange Multipliers corresponding to the contact forces in pinocchio::forwardDynamics.
Definition: multibody/data.hpp:471
pinocchio::JointDataTpl< context::Scalar >
pinocchio::python::context::JointModelFreeFlyer
JointModelFreeFlyerTpl< Scalar > JointModelFreeFlyer
Definition: bindings/python/context/generic.hpp:126
contact-cholesky.cmodel
cmodel
Definition: contact-cholesky.py:25
simulation-closed-kinematic-chains.constraint_data
constraint_data
Definition: simulation-closed-kinematic-chains.py:106
pinocchio::res
ReturnType res
Definition: spatial/classic-acceleration.hpp:57
pinocchio::aba
const DataTpl< Scalar, Options, JointCollectionTpl >::TangentVectorType & aba(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 > &tau, const Convention convention=Convention::LOCAL)
The Articulated-Body algorithm. It computes the forward dynamics, aka the joint accelerations given t...
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::DataTpl::joints
PINOCCHIO_COMPILER_DIAGNOSTIC_POP JointDataVector joints
Vector of pinocchio::JointData associated to the pinocchio::JointModel stored in model,...
Definition: multibody/data.hpp:115
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
pinocchio::CONTACT_6D
@ CONTACT_6D
Point contact model.
Definition: algorithm/contact-info.hpp:22
rnea.hpp
timer.hpp
aba.hpp
simulation-pendulum.type
type
Definition: simulation-pendulum.py:19
pinocchio::Index
PINOCCHIO_COMPILER_DIAGNOSTIC_POP typedef std::size_t Index
Definition: multibody/fwd.hpp:22
anymal-simulation.model
model
Definition: anymal-simulation.py:8
pinocchio::python::context::Quaternion
Eigen::Quaternion< Scalar, Options > Quaternion
Definition: bindings/python/context/generic.hpp:49
pinocchio::SE3Tpl::translation
ConstLinearRef translation() const
Definition: se3-base.hpp:52
pinocchio::ModelTpl::JointIndex
pinocchio::JointIndex JointIndex
Definition: multibody/model.hpp:67
pinocchio::LOCAL_WORLD_ALIGNED
@ LOCAL_WORLD_ALIGNED
Definition: multibody/fwd.hpp:52
simulation-contact-dynamics.contact_datas
list contact_datas
Definition: simulation-contact-dynamics.py:60
pinocchio::python::context::Symmetric3
Symmetric3Tpl< Scalar, Options > Symmetric3
Definition: bindings/python/context/generic.hpp:59
forward-dynamics-derivatives.tau
tau
Definition: forward-dynamics-derivatives.py:25
pinocchio::DataTpl::VectorXs
Eigen::Matrix< Scalar, Eigen::Dynamic, 1, Options > VectorXs
Definition: multibody/data.hpp:75
joint-configuration.hpp
simulation-contact-dynamics.S
S
Definition: simulation-contact-dynamics.py:80
pinocchio::ProximalSettingsTpl
Structure containing all the settings parameters for the proximal algorithms.
Definition: algorithm/fwd.hpp:13
pinocchio::placement
const MotionDense< Motion2 > const SE3Tpl< SE3Scalar, SE3Options > & placement
Definition: spatial/classic-acceleration.hpp:122
KD
#define KD
Definition: unittest/constrained-dynamics.cpp:26
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::RigidConstraintModelTpl
Definition: algorithm/constraints/fwd.hpp:14
pinocchio::getJointJacobian
void getJointJacobian(const ModelTpl< Scalar, Options, JointCollectionTpl > &model, const DataTpl< Scalar, Options, JointCollectionTpl > &data, const JointIndex joint_id, const ReferenceFrame reference_frame, const Eigen::MatrixBase< Matrix6Like > &J)
Computes the Jacobian of a specific joint frame expressed in one of the pinocchio::ReferenceFrame opt...
pinocchio::forwardDynamics
const PINOCCHIO_DEPRECATED DataTpl< Scalar, Options, JointCollectionTpl >::TangentVectorType & forwardDynamics(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 > &tau, const Eigen::MatrixBase< ConstraintMatrixType > &J, const Eigen::MatrixBase< DriftVectorType > &gamma, const Scalar inv_damping=0.)
Compute the forward dynamics with contact constraints. Internally, pinocchio::computeAllTerms is call...
anymal-simulation.N
int N
Definition: anymal-simulation.py:53
pinocchio::JointModelTpl< context::Scalar >
pinocchio::RigidConstraintDataTpl
Definition: algorithm/constraints/fwd.hpp:16
cartpole.v
v
Definition: cartpole.py:153
pinocchio::initConstraintDynamics
void initConstraintDynamics(const ModelTpl< Scalar, Options, JointCollectionTpl > &model, DataTpl< Scalar, Options, JointCollectionTpl > &data, const std::vector< RigidConstraintModelTpl< Scalar, Options >, Allocator > &contact_models)
Init the forward dynamics data according to the contact information contained in contact_models.
pinocchio::SE3Tpl::rotation
ConstAngularRef rotation() const
Definition: se3-base.hpp:48
pinocchio::ForceTpl
Definition: context/casadi.hpp:25
pinocchio::ccrba
const DataTpl< Scalar, Options, JointCollectionTpl >::Matrix6x & ccrba(const ModelTpl< Scalar, Options, JointCollectionTpl > &model, DataTpl< Scalar, Options, JointCollectionTpl > &data, const Eigen::MatrixBase< ConfigVectorType > &q, const Eigen::MatrixBase< TangentVectorType > &v)
Computes the Centroidal Momentum Matrix, the Composite Ridig Body Inertia as well as the centroidal m...
size
FCL_REAL size() const
pinocchio::JointDataTpl::U
U_t U() const
Definition: joint-generic.hpp:141
PINOCCHIO_COMPILER_DIAGNOSTIC_IGNORED_DEPRECECATED_DECLARATIONS
#define PINOCCHIO_COMPILER_DIAGNOSTIC_IGNORED_DEPRECECATED_DECLARATIONS
Definition: include/pinocchio/macros.hpp:131
PINOCCHIO_COMPILER_DIAGNOSTIC_PUSH
#define PINOCCHIO_COMPILER_DIAGNOSTIC_PUSH
macros for pragma push/pop/ignore deprecated warnings
Definition: include/pinocchio/macros.hpp:129
M
M
simulation-contact-dynamics.data_sim
data_sim
Definition: simulation-contact-dynamics.py:56
pinocchio::context::Vector3
Eigen::Matrix< Scalar, 3, 1, Options > Vector3
Definition: context/generic.hpp:53
q
q
pinocchio::JointDataTpl::UDinv
UD_t UDinv() const
Definition: joint-generic.hpp:149
createData
createData(const PINOCCHIO_STD_VECTOR_WITH_EIGEN_ALLOCATOR(pinocchio::RigidConstraintModel) &contact_models)
Definition: unittest/constrained-dynamics.cpp:992
constraintDynamics
VectorXd constraintDynamics(const Model &model, Data &data, const Eigen::MatrixBase< ConfigVectorType > &q, const Eigen::MatrixBase< TangentVectorType1 > &v, const Eigen::MatrixBase< TangentVectorType2 > &tau, const Model::JointIndex id)
Definition: unittest/constrained-dynamics-derivatives.cpp:185
PINOCCHIO_STD_VECTOR_WITH_EIGEN_ALLOCATOR
#define PINOCCHIO_STD_VECTOR_WITH_EIGEN_ALLOCATOR(T)
Definition: container/aligned-vector.hpp:13
inverse-kinematics-3d.it
int it
Definition: inverse-kinematics-3d.py:17
a
Vec3f a
simulation-closed-kinematic-chains.joint1_id
joint1_id
Definition: simulation-closed-kinematic-chains.py:56
pinocchio::hasNaN
bool hasNaN(const Eigen::DenseBase< Derived > &m)
Definition: math/matrix.hpp:19
pinocchio::DataTpl::J
Matrix6x J
Jacobian of joint placements.
Definition: multibody/data.hpp:360
pinocchio::ProximalSettingsTpl::iter
int iter
Total number of iterations of the algorithm when it has converged or reached the maximal number of al...
Definition: algorithm/proximal.hpp:110
mu
double mu
Definition: delassus.cpp:58
pinocchio::ForceRef
Definition: force-ref.hpp:53
pinocchio::Symmetric3Tpl< context::Scalar, context::Options >
pinocchio::contactABA
const DataTpl< Scalar, Options, JointCollectionTpl >::TangentVectorType & contactABA(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 > &tau, const std::vector< RigidConstraintModelTpl< Scalar, Options >, ModelAllocator > &contact_models, std::vector< RigidConstraintDataTpl< Scalar, Options >, DataAllocator > &contact_data)
Definition: constrained-dynamics.hpp:172
fill
fill
pinocchio::log6
MotionTpl< Scalar, Options > log6(const SE3Tpl< Scalar, Options > &M)
Log: SE3 -> se3.
Definition: spatial/explog.hpp:435
centroidal.hpp
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::JointDataTpl::Dinv
D_t Dinv() const
Definition: joint-generic.hpp:145
pinocchio::MotionTpl::Zero
static MotionTpl Zero()
Definition: motion-tpl.hpp:136
pinocchio::ContactType
ContactType
&#160;
Definition: algorithm/contact-info.hpp:19
pinocchio::SE3Tpl::Identity
static SE3Tpl Identity()
Definition: spatial/se3-tpl.hpp:136
pinocchio::DataTpl::Matrix6
Eigen::Matrix< Scalar, 6, 6, Options > Matrix6
Definition: multibody/data.hpp:96
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
contact-cholesky.contact_models
list contact_models
Definition: contact-cholesky.py:22
anymal-simulation.constraint_models
list constraint_models
Definition: anymal-simulation.py:28
contact-info.hpp
contact-dynamics.hpp
anymal-simulation.constraint_dim
constraint_dim
Definition: anymal-simulation.py:52
sample-models.hpp
pinocchio::MotionTpl
Definition: context/casadi.hpp:27
append-urdf-model-with-another-model.joint_id
joint_id
Definition: append-urdf-model-with-another-model.py:33
KP
#define KP
Definition: unittest/constrained-dynamics.cpp:25
jacobian.hpp
pinocchio::ModelTpl
Definition: context/generic.hpp:20
constrained-dynamics.hpp
ur5x4.q0
q0
Definition: ur5x4.py:44
simulation-closed-kinematic-chains.prox_settings
prox_settings
Definition: simulation-closed-kinematic-chains.py:163
classic-acceleration.hpp
pinocchio::CONTACT_3D
@ CONTACT_3D
Definition: algorithm/contact-info.hpp:21
pinocchio::computeAllTerms
void computeAllTerms(const ModelTpl< Scalar, Options, JointCollectionTpl > &model, DataTpl< Scalar, Options, JointCollectionTpl > &data, const Eigen::MatrixBase< ConfigVectorType > &q, const Eigen::MatrixBase< TangentVectorType > &v)
Computes efficiently all the terms needed for dynamic simulation. It is equivalent to the call at the...
cartpole.dt
float dt
Definition: cartpole.py:145
BOOST_AUTO_TEST_CASE
BOOST_AUTO_TEST_CASE(test_sparse_forward_dynamics_empty)
Definition: unittest/constrained-dynamics.cpp:116
pinocchio
Main pinocchio namespace.
Definition: timings.cpp:27
pinocchio::DataTpl::nle
VectorXs nle
Vector of Non Linear Effects (dim model.nv). It corresponds to concatenation of the Coriolis,...
Definition: multibody/data.hpp:179
PINOCCHIO_UNUSED_VARIABLE
#define PINOCCHIO_UNUSED_VARIABLE(var)
Helper to declare that a parameter is unused.
Definition: include/pinocchio/macros.hpp:72
pinocchio::LOCAL
@ LOCAL
Definition: multibody/fwd.hpp:50


pinocchio
Author(s):
autogenerated on Fri Nov 1 2024 02:41:42