22 #include <boost/test/unit_test.hpp>
23 #include <boost/utility/binary.hpp>
28 BOOST_AUTO_TEST_SUITE(BOOST_TEST_MODULE)
86 switch (reference_frame)
92 res.linear() = oa.linear();
93 res.angular() = oa.angular();
107 res.angular() = iMc.rotation().transpose() *
data.a[
joint_id].angular();
118 using namespace Eigen;
125 model.lowerPositionLimit.head<3>().
fill(-1.);
126 model.upperPositionLimit.head<3>().
fill(1.);
129 VectorXd
v = VectorXd::Random(
model.nv);
130 VectorXd
tau = VectorXd::Random(
model.nv);
132 const std::string RF =
"rleg6_joint";
134 const std::string LF =
"lleg6_joint";
141 const double mu0 = 0.;
145 data_ref.
M.triangularView<Eigen::StrictlyLower>() =
146 data_ref.
M.transpose().triangularView<Eigen::StrictlyLower>();
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;
155 data.M.triangularView<Eigen::StrictlyLower>() =
156 data.M.transpose().triangularView<Eigen::StrictlyLower>();
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));
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])));
172 const Motion motion_tmp = data_ref.oMi[k].act(data_ref.a_gf[k]);
173 if (
data.oa_gf[k].angular().isZero())
175 BOOST_CHECK(
data.oa_gf[k].linear().isApprox(motion_tmp.linear()));
176 BOOST_CHECK(motion_tmp.angular().isZero());
180 BOOST_CHECK(
data.oa_gf[k].isApprox(motion_tmp));
186 Eigen::MatrixXd KKT_matrix = contact_chol.matrix();
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));
194 BOOST_CHECK(
data.ddq.isApprox(data_ref.
ddq));
199 using namespace Eigen;
206 model.lowerPositionLimit.head<3>().
fill(-1.);
207 model.upperPositionLimit.head<3>().
fill(1.);
210 VectorXd
v = VectorXd::Random(
model.nv);
211 VectorXd
tau = VectorXd::Random(
model.nv);
213 const std::string RF =
"rleg6_joint";
215 const std::string LF =
"lleg6_joint";
228 contact_models_6D.push_back(ci_RF);
230 contact_models_6D6D.push_back(ci_RF);
233 contact_models_6D6D.push_back(ci_LF);
236 const double mu0 = 0.;
240 BOOST_CHECK(data1.contact_chol.size() == (
model.nv + 0));
243 BOOST_CHECK(!
hasNaN(data1.ddq));
246 BOOST_CHECK(data1.contact_chol.size() == (
model.nv + 1 * 6));
248 BOOST_CHECK(!
hasNaN(data1.ddq));
251 BOOST_CHECK(data1.contact_chol.size() == (
model.nv + 2 * 6));
254 BOOST_CHECK(!
hasNaN(data1.ddq));
263 using namespace Eigen;
270 model.lowerPositionLimit.head<3>().
fill(-1.);
271 model.upperPositionLimit.head<3>().
fill(1.);
274 VectorXd
v = VectorXd::Random(
model.nv);
275 VectorXd
tau = VectorXd::Random(
model.nv);
277 const std::string RF =
"rleg6_joint";
279 const std::string LF =
"lleg6_joint";
286 ci_RF.joint1_placement.setRandom();
290 ci_LF.joint1_placement.setRandom();
298 const double mu0 = 0.;
301 data_ref.
M.triangularView<Eigen::StrictlyLower>() =
302 data_ref.
M.transpose().triangularView<Eigen::StrictlyLower>();
309 J_ref.middleRows<6>(0) = ci_RF.joint1_placement.inverse().toActionMatrix() * Jtmp;
313 J_ref.middleRows<6>(6) = ci_LF.joint1_placement.inverse().toActionMatrix() * Jtmp;
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)
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)
325 Eigen::MatrixXd KKT_matrix_ref =
327 KKT_matrix_ref.bottomRightCorner(
model.nv,
model.nv) = data_ref.
M;
338 BOOST_CHECK((J_ref * data_ref.
ddq + rhs_ref).isZero());
343 BOOST_CHECK((J_ref *
data.ddq + rhs_ref).isZero());
345 BOOST_CHECK((J_ref *
data.ddq + rhs_ref).isZero());
349 Eigen::MatrixXd KKT_matrix = contact_chol.matrix();
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));
356 BOOST_CHECK(
data.ddq.isApprox(data_ref.
ddq));
358 Eigen::DenseIndex constraint_id = 0;
367 BOOST_CHECK(cdata.contact_force.linear().isApprox(
374 data_ref.
lambda_c.segment<6>(constraint_id));
375 BOOST_CHECK(cdata.contact_force.isApprox(f_ref));
383 constraint_id +=
cmodel.size();
389 using namespace Eigen;
396 model.lowerPositionLimit.head<3>().
fill(-1.);
397 model.upperPositionLimit.head<3>().
fill(1.);
400 VectorXd
v = VectorXd::Random(
model.nv);
401 VectorXd
tau = VectorXd::Random(
model.nv);
403 const std::string RF =
"rleg6_joint";
404 const std::string LF =
"lleg6_joint";
405 const std::string RA =
"rarm6_joint";
424 const double mu0 = 0.;
430 data_ref.
M.triangularView<Eigen::StrictlyLower>() =
431 data_ref.
M.transpose().triangularView<Eigen::StrictlyLower>();
437 J_ref.middleRows<3>(6) = J_LF.middleRows<3>(Motion::LINEAR);
441 J_ref.middleRows<3>(9) = J_RA.middleRows<3>(Motion::LINEAR);
445 rhs_ref.segment<6>(0) =
448 rhs_ref.segment<3>(6) =
451 rhs_ref.segment<3>(9) =
455 Eigen::MatrixXd KKT_matrix_ref =
457 KKT_matrix_ref.bottomRightCorner(
model.nv,
model.nv) = data_ref.
M;
474 Eigen::MatrixXd KKT_matrix = contact_chol.matrix();
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));
481 BOOST_CHECK(
data.ddq.isApprox(data_ref.
ddq));
483 Eigen::DenseIndex constraint_id = 0;
492 BOOST_CHECK(cdata.contact_force.linear().isApprox(
499 data_ref.
lambda_c.segment<6>(constraint_id));
500 BOOST_CHECK(cdata.contact_force.isApprox(f_ref));
508 constraint_id +=
cmodel.size();
514 using namespace Eigen;
521 model.lowerPositionLimit.head<3>().
fill(-1.);
522 model.upperPositionLimit.head<3>().
fill(1.);
525 VectorXd
v = VectorXd::Random(
model.nv);
526 VectorXd
tau = VectorXd::Random(
model.nv);
528 const std::string RF =
"rleg6_joint";
529 const std::string LF =
"lleg6_joint";
536 const std::string RA =
"rarm5_joint";
538 const std::string LA =
"larm5_joint";
544 ci_closure.corrector.Kp.array() =
KP;
545 ci_closure.corrector.Kd.array() =
KD;
555 const double mu0 = 0.;
559 const VectorXd ddq_ref =
561 const VectorXd lambda_ref =
data.lambda_c;
567 const VectorXd lambda =
data.lambda_c;
568 BOOST_CHECK(ddq_ref == ddq);
569 BOOST_CHECK(lambda_ref == lambda_ref);
575 using namespace Eigen;
582 model.lowerPositionLimit.head<3>().
fill(-1.);
583 model.upperPositionLimit.head<3>().
fill(1.);
586 VectorXd
v = VectorXd::Random(
model.nv);
587 VectorXd
tau = VectorXd::Random(
model.nv);
589 const std::string RF =
"rleg6_joint";
591 const std::string LF =
"lleg6_joint";
608 const double mu0 = 0.;
614 data_ref.
M.triangularView<Eigen::StrictlyLower>() =
615 data_ref.
M.transpose().triangularView<Eigen::StrictlyLower>();
623 rhs_ref.segment<6>(0) =
626 rhs_ref.segment<6>(6) =
630 Eigen::MatrixXd KKT_matrix_ref =
632 KKT_matrix_ref.bottomRightCorner(
model.nv,
model.nv) = data_ref.
M;
649 Eigen::MatrixXd KKT_matrix = contact_chol.matrix();
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));
656 BOOST_CHECK(
data.ddq.isApprox(data_ref.
ddq));
657 BOOST_CHECK((J_ref *
data.ddq + rhs_ref).isZero());
659 Eigen::DenseIndex constraint_id = 0;
668 BOOST_CHECK(cdata.contact_force.linear().isApprox(
675 data_ref.
lambda_c.segment<6>(constraint_id));
676 BOOST_CHECK(cdata.contact_force.isApprox(f_ref));
684 constraint_id +=
cmodel.size();
690 using namespace Eigen;
697 model.lowerPositionLimit.head<3>().
fill(-1.);
698 model.upperPositionLimit.head<3>().
fill(1.);
701 VectorXd
v = VectorXd::Random(
model.nv);
702 VectorXd
tau = VectorXd::Random(
model.nv);
704 const std::string RF =
"rleg6_joint";
705 const std::string LF =
"lleg6_joint";
706 const std::string RA =
"rarm6_joint";
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;
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;
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;
743 const double mu0 = 0.;
749 data_ref.
M.triangularView<Eigen::StrictlyLower>() =
750 data_ref.
M.transpose().triangularView<Eigen::StrictlyLower>();
758 J_RF_local.setZero();
759 J_LF_local.setZero();
760 J_RA_local.setZero();
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;
776 J_ref.middleRows<6>(6) =
777 -(data_ref.oMi[ci_LF.joint1_id] * ci_LF.joint1_placement).toActionMatrixInverse() * J_LF;
781 J_ref.middleRows<6>(12) =
782 -(data_ref.oMi[ci_RA.joint1_id] * ci_RA.joint1_placement).toActionMatrixInverse() * J_RA;
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);
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]);
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]));
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]));
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();
808 Eigen::MatrixXd KKT_matrix_ref =
811 KKT_matrix_ref.bottomRightCorner(
model.nv,
model.nv) = data_ref.
M;
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));
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));
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));
840 const SE3 c1Mc2_1_LWA(
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));
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])));
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])));
867 Eigen::MatrixXd KKT_matrix = contact_chol.matrix();
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));
875 BOOST_CHECK(
data.ddq.isApprox(data_ref.
ddq));
876 BOOST_CHECK((J_ref *
data.ddq + rhs_ref).isZero());
878 Motion acc_1_final = c1Mc2_1_W.act(
data.a[ci_RF.joint2_id]);
879 BOOST_CHECK(acc_1_final.isZero());
881 std::cout <<
"acc_1_final:\n" << acc_1_final << std::endl;
883 Motion acc_2_final = c1Mc2_2.act(
data.a[ci_LF.joint2_id]);
884 BOOST_CHECK(acc_2_final.isZero());
886 std::cout <<
"acc_2_final:\n" << acc_2_final << std::endl;
888 Motion acc_3_final = c1Mc2_3.act(
data.a[ci_RA.joint2_id]);
889 BOOST_CHECK(acc_3_final.isZero());
891 std::cout <<
"acc_3_final:\n" << acc_3_final << std::endl;
893 Eigen::DenseIndex constraint_id = 0;
902 BOOST_CHECK(cdata.contact_force.linear().isApprox(
909 data_ref.
lambda_c.segment<6>(constraint_id));
910 BOOST_CHECK(cdata.contact_force.isApprox(f_ref));
918 constraint_id +=
cmodel.size();
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);
930 contact_models_bis.begin();
931 it != contact_models_bis.end(); ++
it)
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;
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()));
958 std::cout <<
"cdata.c1Mc2:\n" << cdata.c1Mc2 << std::endl;
959 Force contact_force, contact_force_bis;
960 switch (
cmodel.reference_frame)
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)));
968 contact_force = c1Mc2_LWA.actInv(cdata.contact_force);
969 BOOST_CHECK(contact_force.isApprox(-contact_force_bis));
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)));
977 contact_force = cdata.c1Mc2.actInv(cdata.contact_force);
978 BOOST_CHECK(contact_force.isApprox(-contact_force_bis));
986 std::cout <<
"contact_force: " << contact_force.toVector().transpose() << std::endl;
987 std::cout <<
"contact_force_bis: " << contact_force_bis.toVector().transpose() << std::endl;
1004 using namespace Eigen;
1010 const Inertia box_inertia = Inertia::FromBox(100., 1., 1., 1.);
1014 model.lowerPositionLimit.head<3>().
fill(-1.);
1015 model.upperPositionLimit.head<3>().
fill(1.);
1018 VectorXd
v = VectorXd::Random(
model.nv);
1019 VectorXd
tau = VectorXd::Random(
model.nv);
1021 const std::string RF =
"root";
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();
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));
1045 const double dt = 1e-8;
1054 const Motion contact_RF_velocity_error_fd =
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;
1064 const double dt = 1e-3;
1065 const double mu = 1e-12;
1074 const SE3 M0 = SE3::Random();
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);
1080 Eigen::VectorXd
q(
q0),
v(
v0);
1087 contact_data_sim_prev(contact_data_sim);
1089 for (
int it = 0;
it <=
N;
it++)
1104 cdata.contact_placement_error.toVector().norm()
1105 <= cdata_prev.contact_placement_error.toVector().norm());
1109 contact_data_sim_prev = contact_data_sim;
1116 using namespace Eigen;
1122 const Inertia box_inertia = Inertia::FromBox(100., 1., 1., 1.);
1126 model.lowerPositionLimit.head<3>().
fill(-1.);
1127 model.upperPositionLimit.head<3>().
fill(1.);
1130 VectorXd
v = VectorXd::Random(
model.nv);
1131 VectorXd
tau = VectorXd::Random(
model.nv);
1133 const double mu = 1e-8;
1134 const std::string RF =
"root";
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();
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();
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();
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();
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();
1182 const double dt = 1e-3;
1191 const SE3 M0 = SE3::Random();
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);
1197 Eigen::VectorXd
q(
q0),
v(
v0);
1202 contact_data_sim_prev(contact_data_sim);
1204 for (
int it = 0;
it <=
N;
it++)
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();
1222 BOOST_CHECK(contact_placement_error.norm() <= contact_placement_error_prev.norm());
1224 contact_data_sim_prev = contact_data_sim;
1231 using namespace Eigen;
1238 model.lowerPositionLimit.head<3>().
fill(-1.);
1239 model.upperPositionLimit.head<3>().
fill(1.);
1242 VectorXd
v = VectorXd::Random(
model.nv);
1243 VectorXd
tau = VectorXd::Random(
model.nv);
1245 const std::string RF =
"rleg6_joint";
1246 const std::string LF =
"lleg6_joint";
1247 const std::string RA =
"rarm6_joint";
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;
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;
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;
1284 const double mu0 = 0.;
1290 data_ref.
M.triangularView<Eigen::StrictlyLower>() =
1291 data_ref.
M.transpose().triangularView<Eigen::StrictlyLower>();
1298 J_RF_local.setZero();
1299 J_LF_local.setZero();
1300 J_RA_local.setZero();
1303 J_RF_local = ci_RF.joint2_placement.toActionMatrixInverse() * J_RF_local;
1306 J_LF_local = ci_LF.joint2_placement.toActionMatrixInverse() * J_LF_local;
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);
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);
1323 J_ref.middleRows<6>(6) =
1324 -(data_ref.oMi[ci_RA.joint1_id] * ci_RA.joint1_placement).toActionMatrixInverse() * J_RA;
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()));
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()));
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]));
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();
1356 Eigen::MatrixXd KKT_matrix_ref =
1359 KKT_matrix_ref.bottomRightCorner(
model.nv,
model.nv) = data_ref.
M;
1375 Eigen::MatrixXd KKT_matrix = contact_chol.matrix();
1377 BOOST_CHECK(KKT_matrix.bottomRightCorner(
model.nv,
model.nv)
1378 .isApprox(KKT_matrix_ref.bottomRightCorner(
model.nv,
model.nv)));
1380 BOOST_CHECK(KKT_matrix.isApprox(KKT_matrix_ref));
1382 std::cout <<
"KKT_matrix.topRightCorner(constraint_dim,model.nv):\n"
1384 std::cout <<
"KKT_matrix_ref.topRightCorner(constraint_dim,model.nv):\n"
1389 BOOST_CHECK(
data.ddq.isApprox(data_ref.
ddq));
1390 BOOST_CHECK((J_ref *
data.ddq + rhs_ref).isZero());
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;
1397 const Motion vel_1_final = ci_RF.joint2_placement.actInv(
data.v[ci_RF.joint2_id]);
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());
1403 std::cout <<
"acc_1_final:" << acc_1_final.transpose() << std::endl;
1405 const Motion vel_2_final = ci_LF.joint2_placement.actInv(
data.v[ci_LF.joint2_id]);
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());
1411 std::cout <<
"acc_2_final:" << acc_2_final.transpose() << std::endl;
1413 Motion acc_3_final = c1Mc2_3.act(
data.a[ci_RA.joint2_id]);
1414 BOOST_CHECK(acc_3_final.isZero());
1416 std::cout <<
"acc_3_final:\n" << acc_3_final << std::endl;
1418 Eigen::DenseIndex constraint_id = 0;
1427 BOOST_CHECK(cdata.contact_force.linear().isApprox(
1434 data_ref.
lambda_c.segment<6>(constraint_id));
1435 BOOST_CHECK(cdata.contact_force.isApprox(f_ref));
1443 constraint_id +=
cmodel.size();
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);
1455 contact_models_bis.begin();
1456 it != contact_models_bis.end(); ++
it)
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;
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()));
1482 std::cout <<
"cdata.c1Mc2:\n" << cdata.c1Mc2 << std::endl;
1483 Force contact_force, contact_force_bis;
1484 switch (
cmodel.reference_frame)
1487 SE3 c1Mc2_LWA(SE3::Matrix3::Identity(), cdata.oMc1.rotation() * cdata.c1Mc2.translation());
1488 contact_force_bis = cdata_bis.contact_force;
1491 contact_force = cdata.contact_force;
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)));
1498 BOOST_CHECK(contact_force.isApprox(-contact_force_bis));
1502 contact_force_bis = cdata_bis.contact_force;
1505 contact_force.linear() = cdata.c1Mc2.actInv(cdata.contact_force).linear();
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)));
1512 BOOST_CHECK(contact_force.isApprox(-contact_force_bis));
1520 std::cout <<
"contact_force: " << contact_force.toVector().transpose() << std::endl;
1521 std::cout <<
"contact_force_bis: " << contact_force_bis.toVector().transpose() << std::endl;
1528 using namespace Eigen;
1532 model.rotorInertia =
1533 100. * (Model::VectorXs::Random(
model.nv) + Model::VectorXs::Constant(
model.nv, 1.));
1534 model.rotorGearRatio.fill(100);
1538 model.lowerPositionLimit.head<3>().
fill(-1.);
1539 model.upperPositionLimit.head<3>().
fill(1.);
1542 VectorXd
v = VectorXd::Random(
model.nv);
1543 VectorXd
tau = VectorXd::Random(
model.nv);
1546 RigidConstraintModelVector;
1548 const RigidConstraintModelVector empty_rigid_contact_models;
1549 RigidConstraintDataVector empty_rigid_contact_data;
1555 BOOST_CHECK(
tau.isApprox(tau_ref));
1562 const double mu = 1e2;
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());
1568 const SE3 M = SE3::Random();
1570 const Inertia::Matrix3 RtRmu =
mu * Inertia::Matrix3::Identity();
1573 const Inertia I6_ref =
M.act(diagonal6_inertia);
1574 BOOST_CHECK(I6_translate.isApprox(I6_ref));
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());
1584 const Inertia I3_ref =
M.act(diagonal3_inertia);
1585 BOOST_CHECK(I3_translate.isApprox(I3_ref));
1590 using namespace Eigen;
1597 model.lowerPositionLimit.head<3>().
fill(-1.);
1598 model.upperPositionLimit.head<3>().
fill(1.);
1601 VectorXd
v = VectorXd::Random(
model.nv);
1602 VectorXd
tau = VectorXd::Random(
model.nv);
1604 const std::string RF =
"rleg6_joint";
1611 const std::string LF =
"lleg6_joint";
1621 RigidConstraintModelVector;
1624 const RigidConstraintModelVector empty_contact_models;
1625 RigidConstraintDataVector empty_contact_data;
1646 BOOST_CHECK(
data.J.isApprox(data_ref.
J));
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 =
1656 BOOST_CHECK(
data.joints[
joint_id].StU().isApprox(StYS_ref));
1658 oMi.toDualActionMatrix() * data_ref.Yaba[
joint_id] * oMi.
inverse().toActionMatrix();
1664 BOOST_CHECK(
data.ddq.isApprox(data_ref.
ddq));
1668 BOOST_CHECK(
data.ddq.isApprox(data_ref.
ddq));
1673 ci_RF.joint1_placement.setRandom();
1677 ci_LF.joint1_placement.setRandom();
1687 const double mu0 = 0.;
1703 J_ref.middleRows<6>(0) = ci_RF.joint1_placement.inverse().toActionMatrix() * Jtmp;
1707 J_ref.middleRows<6>(6) = ci_LF.joint1_placement.inverse().toActionMatrix() * Jtmp;
1711 gamma.segment<6>(0) =
1713 model, data_ref, ci_RF.joint1_id, ci_RF.reference_frame, ci_RF.type, ci_RF.joint1_placement)
1715 gamma.segment<6>(6) =
1717 model, data_ref, ci_LF.joint1_id, ci_LF.reference_frame, ci_LF.type, ci_LF.joint1_placement)
1720 BOOST_CHECK((J_ref * data_ref.
ddq + gamma).isZero());
1729 BOOST_CHECK((J_ref * data_constrained_dyn.
ddq + gamma).isZero());
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());
1756 for (
size_t contact_id = 0; contact_id <
contact_models.size(); ++contact_id)
1764 const SE3 & iMc =
cmodel.joint1_placement;
1766 BOOST_CHECK(cdata.oMc1.isApprox(oMc));
1769 const Motion contact1_velocity_ref = iMc.actInv(data_ref.v[
joint1_id]);
1770 BOOST_CHECK(cdata.contact1_velocity.isApprox(contact1_velocity_ref));
1775 S.setDiagonal(Symmetric3::Vector3::Constant(
mu));
1779 Inertia::Matrix6 contact_inertia_ref = Inertia::Matrix6::Zero();
1782 contact_inertia_ref.diagonal().fill(
mu);
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()));
1789 Inertia::Matrix6 Yaba_ref = data_ref.oMi[
joint1_id].toDualActionMatrix()
1791 * data_ref.oMi[
joint1_id].toActionMatrixInverse()
1792 + contact_inertia_ref;
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));
1807 Yaba_ref -= UDinv_ref * U_ref.transpose();
1817 BOOST_CHECK(prox_settings2.
iter == 0);
1822 using namespace Eigen;
1829 model.lowerPositionLimit.head<3>().
fill(-1.);
1830 model.upperPositionLimit.head<3>().
fill(1.);
1833 VectorXd
v = VectorXd::Random(
model.nv);
1834 VectorXd
tau = VectorXd::Random(
model.nv);
1836 const std::string RF =
"rleg6_joint";
1838 const std::string LF =
"lleg6_joint";
1843 RigidConstraintModelVector;
1872 J_ref.middleRows<3>(0) = Jtmp.middleRows<3>(Motion::LINEAR);
1875 J_ref.middleRows<3>(3) = Jtmp.middleRows<3>(Motion::LINEAR);
1879 gamma.segment<3>(0) =
1882 gamma.segment<3>(3) =
1886 BOOST_CHECK((J_ref * data_ref.
ddq + gamma).isZero());
1895 BOOST_CHECK((J_ref * data_constrained_dyn.
ddq + gamma).isZero());
1902 BOOST_CHECK((J_ref *
data.ddq + gamma).isZero());
1909 BOOST_CHECK(prox_settings2.
iter == 0);
1912 BOOST_AUTO_TEST_SUITE_END()