11 #include "pinocchio/algorithm/contact-cholesky.hxx" 
   15 #include <boost/test/unit_test.hpp> 
   16 #include <boost/utility/binary.hpp> 
   22     template<
typename Scalar, 
int Options>
 
   37         return this->parents_fromRow;
 
   41         return this->last_child;
 
   45         return this->nv_subtree_fromRow;
 
   49         return this->joint1_indexes;
 
   53         return this->joint2_indexes;
 
   61 BOOST_AUTO_TEST_SUITE(BOOST_TEST_MODULE)
 
   66   using namespace Eigen;
 
   68   using namespace cholesky;
 
   72   Data humanoid_data(humanoid_model);
 
   76   Data manipulator_data(manipulator_model);
 
   90   humanoid_chol.compute(humanoid_model, humanoid_data, contact_models_empty, contact_datas_empty);
 
   91   manipulator_chol.compute(
 
   92     manipulator_model, manipulator_data, contact_models_empty, contact_datas_empty);
 
   94   BOOST_CHECK(humanoid_chol == humanoid_chol);
 
   95   BOOST_CHECK(humanoid_chol != manipulator_chol);
 
  100   using namespace Eigen;
 
  108   model.lowerPositionLimit.head<3>().
fill(-1.);
 
  109   model.upperPositionLimit.head<3>().
fill(1.);
 
  114   data_ref.
M.triangularView<Eigen::StrictlyLower>() =
 
  115     data_ref.
M.triangularView<Eigen::StrictlyUpper>().transpose();
 
  120   contact_chol_decomposition.allocate(
model, contact_models_empty);
 
  122   BOOST_CHECK(contact_chol_decomposition.D.size() == 
model.nv);
 
  123   BOOST_CHECK(contact_chol_decomposition.Dinv.size() == 
model.nv);
 
  124   BOOST_CHECK(contact_chol_decomposition.U.rows() == 
model.nv);
 
  125   BOOST_CHECK(contact_chol_decomposition.U.cols() == 
model.nv);
 
  126   BOOST_CHECK(contact_chol_decomposition.size() == 
model.nv);
 
  127   BOOST_CHECK(contact_chol_decomposition.U.diagonal().isOnes());
 
  131   data.M.triangularView<Eigen::StrictlyLower>() =
 
  132     data.M.triangularView<Eigen::StrictlyUpper>().transpose();
 
  134   contact_chol_decomposition.compute(
model, 
data, contact_models_empty, contact_datas_empty);
 
  136   data_ref.
Minv = data_ref.
M.inverse();
 
  137   Eigen::MatrixXd Minv_test(Eigen::MatrixXd::Zero(
model.nv, 
model.nv));
 
  138   contact_chol_decomposition.getInverseMassMatrix(Minv_test);
 
  140   BOOST_CHECK(
data.M.isApprox(data_ref.
M));
 
  141   BOOST_CHECK(Minv_test.isApprox(data_ref.
Minv));
 
  143   BOOST_CHECK(data_ref.
D.isApprox(contact_chol_decomposition.D.tail(
model.nv)));
 
  144   BOOST_CHECK(data_ref.
Dinv.isApprox(contact_chol_decomposition.Dinv.tail(
model.nv)));
 
  146     data_ref.
U.isApprox(contact_chol_decomposition.U.bottomRightCorner(
model.nv, 
model.nv)));
 
  149   for (Eigen::DenseIndex k = 0; k < 
model.nv; ++k)
 
  154   for (Eigen::DenseIndex k = 0; k < 
model.njoints; ++k)
 
  159   for (Eigen::DenseIndex k = 0; k < 
model.nv; ++k)
 
  165   VectorXd v_in(VectorXd::Random(
model.nv));
 
  166   MatrixXd mat_in(MatrixXd::Random(contact_chol_decomposition.size(), 20));
 
  169   VectorXd Uv_op_res(v_in), Uv_op_ref(v_in);
 
  171   contact_chol_decomposition.Uv(Uv_op_res);
 
  174   BOOST_CHECK(Uv_op_res.isApprox(Uv_op_ref));
 
  176   MatrixXd Uv_mat_op_res(mat_in), Uv_mat_op_ref(mat_in);
 
  178   contact_chol_decomposition.Uv(Uv_mat_op_res);
 
  181   BOOST_CHECK(Uv_mat_op_res.isApprox(Uv_mat_op_ref));
 
  184   VectorXd Utv_op_res(v_in), Utv_op_ref(v_in);
 
  186   contact_chol_decomposition.Utv(Utv_op_res);
 
  189   BOOST_CHECK(Utv_op_res.isApprox(Utv_op_ref));
 
  191   MatrixXd Utv_mat_op_res(mat_in), Utv_mat_op_ref(mat_in);
 
  193   contact_chol_decomposition.Utv(Utv_mat_op_res);
 
  196   BOOST_CHECK(Utv_mat_op_res.isApprox(Utv_mat_op_ref));
 
  199   VectorXd Uiv_op_res(v_in), Uiv_op_ref(v_in);
 
  201   contact_chol_decomposition.Uiv(Uiv_op_res);
 
  204   BOOST_CHECK(Uiv_op_res.isApprox(Uiv_op_ref));
 
  206   MatrixXd Uiv_mat_op_res(mat_in), Uiv_mat_op_ref(mat_in);
 
  208   contact_chol_decomposition.Uiv(Uiv_mat_op_res);
 
  211   BOOST_CHECK(Uiv_mat_op_res.isApprox(Uiv_mat_op_ref));
 
  214   VectorXd Utiv_op_res(v_in), Utiv_op_ref(v_in);
 
  216   contact_chol_decomposition.Utiv(Utiv_op_res);
 
  219   BOOST_CHECK(Utiv_op_res.isApprox(Utiv_op_ref));
 
  221   MatrixXd Utiv_mat_op_res(mat_in), Utiv_mat_op_ref(mat_in);
 
  223   contact_chol_decomposition.Utiv(Utiv_mat_op_res);
 
  226   BOOST_CHECK(Utiv_mat_op_res.isApprox(Utiv_mat_op_ref));
 
  230   contact_chol_decomposition.solveInPlace(
sol);
 
  232   VectorXd sol_ref(
data.M.inverse() * v_in);
 
  234   BOOST_CHECK(
sol.isApprox(sol_ref));
 
  236   MatrixXd sol_mat(mat_in);
 
  237   contact_chol_decomposition.solveInPlace(sol_mat);
 
  239   MatrixXd sol_mat_ref(
data.M.inverse() * mat_in);
 
  241   BOOST_CHECK(sol_mat.isApprox(sol_mat_ref));
 
  244   MatrixXd sol_copy_mat = contact_chol_decomposition.solve(mat_in);
 
  245   BOOST_CHECK(sol_copy_mat.isApprox(sol_mat));
 
  249   contact_chol_decomposition.inverse(M_inv);
 
  251   MatrixXd M_inv_ref = 
data.M.inverse();
 
  252   BOOST_CHECK(M_inv.isApprox(M_inv_ref));
 
  256     contact_chol_decomposition.getMassMatrixChoeslkyDecomposition(
model);
 
  259   MatrixXd iosim = contact_chol_decomposition.getInverseOperationalSpaceInertiaMatrix();
 
  260   MatrixXd osim = contact_chol_decomposition.getOperationalSpaceInertiaMatrix();
 
  261   BOOST_CHECK(iosim.size() == 0);
 
  262   BOOST_CHECK(osim.size() == 0);
 
  264   BOOST_CHECK(mass_matrix_chol == contact_chol_decomposition);
 
  265   BOOST_CHECK(mass_matrix_chol.U.isApprox(data_ref.
U));
 
  266   BOOST_CHECK(mass_matrix_chol.D.isApprox(data_ref.
D));
 
  267   BOOST_CHECK(mass_matrix_chol.Dinv.isApprox(data_ref.
Dinv));
 
  272   using namespace Eigen;
 
  280   model.lowerPositionLimit.head<3>().
fill(-1.);
 
  281   model.upperPositionLimit.head<3>().
fill(1.);
 
  284   const std::string RF = 
"rleg6_joint";
 
  285   const std::string LF = 
"lleg6_joint";
 
  298   data_ref.
M.triangularView<Eigen::StrictlyLower>() =
 
  299     data_ref.
M.triangularView<Eigen::StrictlyUpper>().transpose();
 
  317   H.middleRows<6>(0).rightCols(
model.nv) = J_RF;
 
  318   H.middleRows<6>(6).rightCols(
model.nv) = J_LF;
 
  320   H.triangularView<Eigen::StrictlyLower>() = 
H.triangularView<Eigen::StrictlyUpper>().transpose();
 
  328   for (Eigen::DenseIndex k = 0; k < 
model.nv; ++k)
 
  330     if (
data.parents_fromRow[(
size_t)k] == -1)
 
  340   data.M.triangularView<Eigen::StrictlyLower>() =
 
  341     data.M.triangularView<Eigen::StrictlyUpper>().transpose();
 
  343   BOOST_CHECK(data_ref.
D.isApprox(contact_chol_decomposition.D.tail(
model.nv)));
 
  344   BOOST_CHECK(data_ref.
Dinv.isApprox(contact_chol_decomposition.Dinv.tail(
model.nv)));
 
  346     data_ref.
U.isApprox(contact_chol_decomposition.U.bottomRightCorner(
model.nv, 
model.nv)));
 
  349     contact_chol_decomposition.U.bottomRightCorner(
model.nv, 
model.nv)
 
  350     * contact_chol_decomposition.D.tail(
model.nv).asDiagonal()
 
  351     * contact_chol_decomposition.U.bottomRightCorner(
model.nv, 
model.nv).transpose();
 
  352   BOOST_CHECK(M_recomposed.isApprox(
data.M));
 
  355                                 * contact_chol_decomposition.D.asDiagonal()
 
  356                                 * contact_chol_decomposition.U.transpose();
 
  358   BOOST_CHECK(H_recomposed.bottomRightCorner(
model.nv, 
model.nv).isApprox(
data.M));
 
  361   BOOST_CHECK(H_recomposed.isApprox(
H));
 
  365     MatrixXd JMinvJt = 
H.middleRows<12>(0).rightCols(
model.nv) * data_ref.
M.inverse()
 
  366                        * 
H.middleRows<12>(0).rightCols(
model.nv).transpose();
 
  367     MatrixXd iosim = contact_chol_decomposition.getInverseOperationalSpaceInertiaMatrix();
 
  368     MatrixXd osim = contact_chol_decomposition.getOperationalSpaceInertiaMatrix();
 
  370     contact_chol_decomposition.getJMinv(JMinv_test);
 
  371     MatrixXd JMinv_ref = 
H.middleRows<12>(0).rightCols(
model.nv) * data_ref.
M.inverse();
 
  372     BOOST_CHECK(JMinv_ref.isApprox(JMinv_test));
 
  374     BOOST_CHECK(iosim.isApprox(JMinvJt));
 
  375     BOOST_CHECK(osim.isApprox(JMinvJt.inverse()));
 
  377     const MatrixXd 
rhs = MatrixXd::Random(12, 12);
 
  378     const MatrixXd res_delassus = contact_chol_decomposition.getDelassusCholeskyExpression() * 
rhs;
 
  379     const MatrixXd res_delassus_ref = iosim * 
rhs;
 
  381     BOOST_CHECK(res_delassus_ref.isApprox(res_delassus));
 
  383     const MatrixXd res_delassus_inverse =
 
  384       contact_chol_decomposition.getDelassusCholeskyExpression().solve(
rhs);
 
  385     const MatrixXd res_delassus_inverse_ref = osim * 
rhs;
 
  387     BOOST_CHECK(res_delassus_inverse_ref.isApprox(res_delassus_inverse));
 
  391   data_ref.
Minv = data_ref.
M.inverse();
 
  392   Eigen::MatrixXd Minv_test(Eigen::MatrixXd::Zero(
model.nv, 
model.nv));
 
  393   contact_chol_decomposition.getInverseMassMatrix(Minv_test);
 
  395   BOOST_CHECK(Minv_test.isApprox(data_ref.
Minv));
 
  401   BOOST_CHECK(contact_chol_decomposition_mu.D.isApprox(contact_chol_decomposition.D));
 
  402   BOOST_CHECK(contact_chol_decomposition_mu.Dinv.isApprox(contact_chol_decomposition.Dinv));
 
  403   BOOST_CHECK(contact_chol_decomposition_mu.U.isApprox(contact_chol_decomposition.U));
 
  405   const double mu = 0.1;
 
  412     MatrixXd JMinvJt_mu = H_mu.middleRows<12>(0).rightCols(
model.nv) * data_ref.
M.inverse()
 
  413                             * H_mu.middleRows<12>(0).rightCols(
model.nv).transpose()
 
  414                           + 
mu * MatrixXd::Identity(12, 12);
 
  415     MatrixXd iosim_mu = contact_chol_decomposition_mu.getInverseOperationalSpaceInertiaMatrix();
 
  416     MatrixXd osim_mu = contact_chol_decomposition_mu.getOperationalSpaceInertiaMatrix();
 
  418     BOOST_CHECK(iosim_mu.isApprox(JMinvJt_mu));
 
  419     BOOST_CHECK(osim_mu.isApprox(JMinvJt_mu.inverse()));
 
  421     const MatrixXd 
rhs = MatrixXd::Random(12, 1);
 
  422     const MatrixXd 
res = contact_chol_decomposition_mu.getDelassusCholeskyExpression() * 
rhs;
 
  423     const MatrixXd res_ref = iosim_mu * 
rhs;
 
  425     BOOST_CHECK(res_ref.isApprox(
res));
 
  427     const MatrixXd res_no_mu =
 
  428       contact_chol_decomposition_mu.getDelassusCholeskyExpression() * 
rhs - 
mu * 
rhs;
 
  429     const MatrixXd res_no_mu_ref = contact_chol_decomposition.getDelassusCholeskyExpression() * 
rhs;
 
  431     BOOST_CHECK(res_no_mu.isApprox(res_no_mu_ref));
 
  435                                    * contact_chol_decomposition_mu.D.asDiagonal()
 
  436                                    * contact_chol_decomposition_mu.U.transpose();
 
  438   BOOST_CHECK(H_recomposed_mu.isApprox(H_mu));
 
  441   VectorXd v_in(VectorXd::Random(contact_chol_decomposition.size()));
 
  442   MatrixXd mat_in(MatrixXd::Random(contact_chol_decomposition.size(), 20));
 
  445   VectorXd Uv_op_res(v_in), Uv_op_ref(v_in);
 
  447   contact_chol_decomposition.Uv(Uv_op_res);
 
  448   Uv_op_ref.noalias() = contact_chol_decomposition.U * v_in;
 
  450   BOOST_CHECK(Uv_op_res.isApprox(Uv_op_ref));
 
  452   MatrixXd Uv_mat_op_res(mat_in), Uv_mat_op_ref(mat_in);
 
  454   contact_chol_decomposition.Uv(Uv_mat_op_res);
 
  455   Uv_mat_op_ref.noalias() = contact_chol_decomposition.U * mat_in;
 
  457   BOOST_CHECK(Uv_mat_op_res.isApprox(Uv_mat_op_ref));
 
  460   VectorXd Utv_op_res(v_in), Utv_op_ref(v_in);
 
  462   contact_chol_decomposition.Utv(Utv_op_res);
 
  463   Utv_op_ref.noalias() = contact_chol_decomposition.U.transpose() * v_in;
 
  465   BOOST_CHECK(Utv_op_res.isApprox(Utv_op_ref));
 
  467   MatrixXd Utv_mat_op_res(mat_in), Utv_mat_op_ref(mat_in);
 
  469   contact_chol_decomposition.Utv(Utv_mat_op_res);
 
  470   Utv_mat_op_ref.noalias() = contact_chol_decomposition.U.transpose() * mat_in;
 
  472   BOOST_CHECK(Utv_mat_op_res.isApprox(Utv_mat_op_ref));
 
  475   VectorXd Uiv_op_res(v_in), Uiv_op_ref(v_in);
 
  477   contact_chol_decomposition.Uiv(Uiv_op_res);
 
  478   Uiv_op_ref.noalias() = contact_chol_decomposition.U.inverse() * v_in;
 
  480   BOOST_CHECK(Uiv_op_res.isApprox(Uiv_op_ref));
 
  482   MatrixXd Uiv_mat_op_res(mat_in), Uiv_mat_op_ref(mat_in);
 
  484   contact_chol_decomposition.Uiv(Uiv_mat_op_res);
 
  485   Uiv_mat_op_ref.noalias() = contact_chol_decomposition.U.inverse() * mat_in;
 
  487   BOOST_CHECK(Uiv_mat_op_res.isApprox(Uiv_mat_op_ref));
 
  490   VectorXd Utiv_op_res(v_in), Utiv_op_ref(v_in);
 
  492   contact_chol_decomposition.Utiv(Utiv_op_res);
 
  493   Utiv_op_ref.noalias() = contact_chol_decomposition.U.inverse().transpose() * v_in;
 
  495   BOOST_CHECK(Utiv_op_res.isApprox(Utiv_op_ref));
 
  497   MatrixXd Utiv_mat_op_res(mat_in), Utiv_mat_op_ref(mat_in);
 
  499   contact_chol_decomposition.Utiv(Utiv_mat_op_res);
 
  500   Utiv_mat_op_ref.noalias() = contact_chol_decomposition.U.inverse().transpose() * mat_in;
 
  502   BOOST_CHECK(Utiv_mat_op_res.isApprox(Utiv_mat_op_ref));
 
  506   contact_chol_decomposition.solveInPlace(
sol);
 
  508   VectorXd sol_ref(
H.inverse() * v_in);
 
  510   BOOST_CHECK(
sol.isApprox(sol_ref));
 
  512   MatrixXd sol_mat(mat_in), sol_mat_ref(mat_in);
 
  514   contact_chol_decomposition.solveInPlace(sol_mat);
 
  515   sol_mat_ref.noalias() = 
H.inverse() * mat_in;
 
  517   BOOST_CHECK(sol_mat.isApprox(sol_mat_ref));
 
  520   MatrixXd sol_copy_mat = contact_chol_decomposition.solve(mat_in);
 
  521   BOOST_CHECK(sol_copy_mat.isApprox(sol_mat));
 
  524   MatrixXd H_inv(contact_chol_decomposition.size(), contact_chol_decomposition.size());
 
  525   contact_chol_decomposition.inverse(H_inv);
 
  527   MatrixXd H_inv_ref = 
H.inverse();
 
  528   BOOST_CHECK(H_inv.isApprox(H_inv_ref));
 
  532   contact_chol_decomposition.matrix(mat1);
 
  533   BOOST_CHECK(mat1.isApprox(
H));
 
  537   BOOST_CHECK(mat2.isApprox(
H));
 
  539   MatrixXd mat3 = contact_chol_decomposition.matrix();
 
  540   BOOST_CHECK(mat3.isApprox(
H));
 
  545   using namespace Eigen;
 
  553   model.lowerPositionLimit.head<3>().
fill(-1.);
 
  554   model.upperPositionLimit.head<3>().
fill(1.);
 
  557   const std::string RF = 
"rleg6_joint";
 
  558   const std::string LF = 
"lleg6_joint";
 
  559   const std::string RA = 
"rarm6_joint";
 
  560   const std::string LA = 
"larm6_joint";
 
  579   data_ref.
M.triangularView<Eigen::StrictlyLower>() =
 
  580     data_ref.
M.triangularView<Eigen::StrictlyUpper>().transpose();
 
  602   H.middleRows<6>(0).rightCols(
model.nv) = J_RF;
 
  603   H.middleRows<3>(6).rightCols(
model.nv) = J_LF.middleRows<3>(Motion::LINEAR);
 
  607   H.triangularView<Eigen::StrictlyLower>() = 
H.triangularView<Eigen::StrictlyUpper>().transpose();
 
  615   for (Eigen::DenseIndex k = 0; k < 
model.nv; ++k)
 
  617     if (
data.parents_fromRow[(
size_t)k] == -1)
 
  627   data.M.triangularView<Eigen::StrictlyLower>() =
 
  628     data.M.triangularView<Eigen::StrictlyUpper>().transpose();
 
  630   BOOST_CHECK(data_ref.
D.isApprox(contact_chol_decomposition.D.tail(
model.nv)));
 
  631   BOOST_CHECK(data_ref.
Dinv.isApprox(contact_chol_decomposition.Dinv.tail(
model.nv)));
 
  633     data_ref.
U.isApprox(contact_chol_decomposition.U.bottomRightCorner(
model.nv, 
model.nv)));
 
  636     contact_chol_decomposition.U.bottomRightCorner(
model.nv, 
model.nv)
 
  637     * contact_chol_decomposition.D.tail(
model.nv).asDiagonal()
 
  638     * contact_chol_decomposition.U.bottomRightCorner(
model.nv, 
model.nv).transpose();
 
  639   BOOST_CHECK(M_recomposed.isApprox(
data.M));
 
  642                                 * contact_chol_decomposition.D.asDiagonal()
 
  643                                 * contact_chol_decomposition.U.transpose();
 
  645   BOOST_CHECK(H_recomposed.bottomRightCorner(
model.nv, 
model.nv).isApprox(
data.M));
 
  648   BOOST_CHECK(H_recomposed.isApprox(
H));
 
  651   VectorXd v_in(VectorXd::Random(contact_chol_decomposition.size()));
 
  652   MatrixXd mat_in(MatrixXd::Random(contact_chol_decomposition.size(), 20));
 
  655   VectorXd Uv_op_res(v_in), Uv_op_ref(v_in);
 
  657   contact_chol_decomposition.Uv(Uv_op_res);
 
  658   Uv_op_ref.noalias() = contact_chol_decomposition.U * v_in;
 
  660   BOOST_CHECK(Uv_op_res.isApprox(Uv_op_ref));
 
  662   MatrixXd Uv_mat_op_res(mat_in), Uv_mat_op_ref(mat_in);
 
  664   contact_chol_decomposition.Uv(Uv_mat_op_res);
 
  665   Uv_mat_op_ref.noalias() = contact_chol_decomposition.U * mat_in;
 
  667   BOOST_CHECK(Uv_mat_op_res.isApprox(Uv_mat_op_ref));
 
  670   VectorXd Utv_op_res(v_in), Utv_op_ref(v_in);
 
  672   contact_chol_decomposition.Utv(Utv_op_res);
 
  673   Utv_op_ref.noalias() = contact_chol_decomposition.U.transpose() * v_in;
 
  675   BOOST_CHECK(Utv_op_res.isApprox(Utv_op_ref));
 
  677   MatrixXd Utv_mat_op_res(mat_in), Utv_mat_op_ref(mat_in);
 
  679   contact_chol_decomposition.Utv(Utv_mat_op_res);
 
  680   Utv_mat_op_ref.noalias() = contact_chol_decomposition.U.transpose() * mat_in;
 
  682   BOOST_CHECK(Utv_mat_op_res.isApprox(Utv_mat_op_ref));
 
  685   VectorXd Uiv_op_res(v_in), Uiv_op_ref(v_in);
 
  687   contact_chol_decomposition.Uiv(Uiv_op_res);
 
  688   Uiv_op_ref.noalias() = contact_chol_decomposition.U.inverse() * v_in;
 
  690   BOOST_CHECK(Uiv_op_res.isApprox(Uiv_op_ref));
 
  692   MatrixXd Uiv_mat_op_res(mat_in), Uiv_mat_op_ref(mat_in);
 
  694   contact_chol_decomposition.Uiv(Uiv_mat_op_res);
 
  695   Uiv_mat_op_ref.noalias() = contact_chol_decomposition.U.inverse() * mat_in;
 
  697   BOOST_CHECK(Uiv_mat_op_res.isApprox(Uiv_mat_op_ref));
 
  700   VectorXd Utiv_op_res(v_in), Utiv_op_ref(v_in);
 
  702   contact_chol_decomposition.Utiv(Utiv_op_res);
 
  703   Utiv_op_ref.noalias() = contact_chol_decomposition.U.inverse().transpose() * v_in;
 
  705   BOOST_CHECK(Utiv_op_res.isApprox(Utiv_op_ref));
 
  707   MatrixXd Utiv_mat_op_res(mat_in), Utiv_mat_op_ref(mat_in);
 
  709   contact_chol_decomposition.Utiv(Utiv_mat_op_res);
 
  710   Utiv_mat_op_ref.noalias() = contact_chol_decomposition.U.inverse().transpose() * mat_in;
 
  712   BOOST_CHECK(Utiv_mat_op_res.isApprox(Utiv_mat_op_ref));
 
  716   contact_chol_decomposition.solveInPlace(
sol);
 
  718   VectorXd sol_ref(
H.inverse() * v_in);
 
  720   BOOST_CHECK(
sol.isApprox(sol_ref));
 
  722   MatrixXd sol_mat(mat_in), sol_mat_ref(mat_in);
 
  724   contact_chol_decomposition.solveInPlace(sol_mat);
 
  725   sol_mat_ref.noalias() = 
H.inverse() * mat_in;
 
  727   BOOST_CHECK(sol_mat.isApprox(sol_mat_ref));
 
  730   MatrixXd sol_copy_mat = contact_chol_decomposition.solve(mat_in);
 
  731   BOOST_CHECK(sol_copy_mat.isApprox(sol_mat));
 
  734   MatrixXd H_inv(contact_chol_decomposition.size(), contact_chol_decomposition.size());
 
  735   contact_chol_decomposition.inverse(H_inv);
 
  737   MatrixXd H_inv_ref = 
H.inverse();
 
  738   BOOST_CHECK(H_inv.isApprox(H_inv_ref));
 
  742   contact_chol_decomposition.matrix(mat1);
 
  743   BOOST_CHECK(mat1.isApprox(
H));
 
  747   BOOST_CHECK(mat2.isApprox(
H));
 
  749   MatrixXd mat3 = contact_chol_decomposition.matrix();
 
  750   BOOST_CHECK(mat3.isApprox(
H));
 
  753   MatrixXd JMinvJt = 
H.middleRows<9>(0).rightCols(
model.nv) * data_ref.
M.inverse()
 
  754                      * 
H.middleRows<9>(0).rightCols(
model.nv).transpose();
 
  755   MatrixXd iosim = contact_chol_decomposition.getInverseOperationalSpaceInertiaMatrix();
 
  756   MatrixXd osim = contact_chol_decomposition.getOperationalSpaceInertiaMatrix();
 
  758   BOOST_CHECK(iosim.isApprox(JMinvJt));
 
  759   BOOST_CHECK(osim.isApprox(JMinvJt.inverse()));
 
  762   data_ref.
Minv = data_ref.
M.inverse();
 
  763   Eigen::MatrixXd Minv_test(Eigen::MatrixXd::Zero(
model.nv, 
model.nv));
 
  764   contact_chol_decomposition.getInverseMassMatrix(Minv_test);
 
  766   Eigen::MatrixXd JMinv_test(Eigen::MatrixXd::Zero(9, 
model.nv));
 
  767   contact_chol_decomposition.getJMinv(JMinv_test);
 
  768   MatrixXd JMinv_ref = 
H.middleRows<9>(0).rightCols(
model.nv) * data_ref.
M.inverse();
 
  769   BOOST_CHECK(JMinv_ref.isApprox(JMinv_test));
 
  771   BOOST_CHECK(Minv_test.isApprox(data_ref.
Minv));
 
  776   using namespace Eigen;
 
  784   model.lowerPositionLimit.head<3>().
fill(-1.);
 
  785   model.upperPositionLimit.head<3>().
fill(1.);
 
  788   const std::string RF = 
"rleg6_joint";
 
  789   const std::string LF = 
"lleg6_joint";
 
  802   data_ref.
M.triangularView<Eigen::StrictlyLower>() =
 
  803     data_ref.
M.triangularView<Eigen::StrictlyUpper>().transpose();
 
  821   H.middleRows<6>(0).rightCols(
model.nv) = J_RF;
 
  822   H.middleRows<6>(6).rightCols(
model.nv) = J_LF;
 
  824   H.triangularView<Eigen::StrictlyLower>() = 
H.triangularView<Eigen::StrictlyUpper>().transpose();
 
  832   data.M.triangularView<Eigen::StrictlyLower>() =
 
  833     data.M.triangularView<Eigen::StrictlyUpper>().transpose();
 
  835   Data::MatrixXs H_recomposed = contact_chol_decomposition.matrix();
 
  837   BOOST_CHECK(H_recomposed.bottomRightCorner(
model.nv, 
model.nv).isApprox(
data.M));
 
  840   BOOST_CHECK(H_recomposed.isApprox(
H));
 
  843   MatrixXd H_inv(contact_chol_decomposition.size(), contact_chol_decomposition.size());
 
  844   contact_chol_decomposition.inverse(H_inv);
 
  846   MatrixXd H_inv_ref = H_recomposed.inverse();
 
  847   BOOST_CHECK(H_inv.isApprox(H_inv_ref));
 
  850   MatrixXd JMinvJt = 
H.middleRows<12>(0).rightCols(
model.nv) * data_ref.
M.inverse()
 
  851                      * 
H.middleRows<12>(0).rightCols(
model.nv).transpose();
 
  852   MatrixXd iosim = contact_chol_decomposition.getInverseOperationalSpaceInertiaMatrix();
 
  853   MatrixXd osim = contact_chol_decomposition.getOperationalSpaceInertiaMatrix();
 
  855   BOOST_CHECK(iosim.isApprox(JMinvJt));
 
  856   BOOST_CHECK(osim.isApprox(JMinvJt.inverse()));
 
  859   data_ref.
Minv = data_ref.
M.inverse();
 
  860   Eigen::MatrixXd Minv_test(Eigen::MatrixXd::Zero(
model.nv, 
model.nv));
 
  861   contact_chol_decomposition.getInverseMassMatrix(Minv_test);
 
  863   Eigen::MatrixXd JMinv_test(Eigen::MatrixXd::Zero(12, 
model.nv));
 
  864   contact_chol_decomposition.getJMinv(JMinv_test);
 
  865   MatrixXd JMinv_ref = 
H.middleRows<12>(0).rightCols(
model.nv) * data_ref.
M.inverse();
 
  866   BOOST_CHECK(JMinv_ref.isApprox(JMinv_test));
 
  868   BOOST_CHECK(Minv_test.isApprox(data_ref.
Minv));
 
  873   using namespace Eigen;
 
  881   model.lowerPositionLimit.head<3>().
fill(-1.);
 
  882   model.upperPositionLimit.head<3>().
fill(1.);
 
  885   const std::string RF = 
"rleg6_joint";
 
  886   const std::string LF = 
"lleg6_joint";
 
  887   const std::string RA = 
"rarm6_joint";
 
  888   const std::string LA = 
"larm6_joint";
 
  907   data_ref.
M.triangularView<Eigen::StrictlyLower>() =
 
  908     data_ref.
M.triangularView<Eigen::StrictlyUpper>().transpose();
 
  927   const SE3 oMRA_wla = 
SE3(SE3::Matrix3::Identity(), ci_RA.joint1_placement.translation());
 
  929   const double mu = 0.1;
 
  934   H.middleRows<6>(0).rightCols(
model.nv) = -ci_RF.joint1_placement.toActionMatrixInverse() * J_RF;
 
  935   H.middleRows<6>(6).rightCols(
model.nv) = -ci_LF.joint1_placement.toActionMatrixInverse() * J_LF;
 
  936   H.middleRows<6>(12).rightCols(
model.nv) = -oMRA_wla.toActionMatrixInverse() * J_RA;
 
  937   H.middleRows<6>(18).rightCols(
model.nv) = -ci_LA.joint1_placement.toActionMatrixInverse() * J_LA;
 
  939   H.triangularView<Eigen::StrictlyLower>() = 
H.triangularView<Eigen::StrictlyUpper>().transpose();
 
  947   data.M.triangularView<Eigen::StrictlyLower>() =
 
  948     data.M.triangularView<Eigen::StrictlyUpper>().transpose();
 
  950   Data::MatrixXs H_recomposed = contact_chol_decomposition.matrix();
 
  952   BOOST_CHECK(H_recomposed.bottomRightCorner(
model.nv, 
model.nv).isApprox(
data.M));
 
  955   BOOST_CHECK(H_recomposed.isApprox(
H));
 
  957   VectorXd v_in(VectorXd::Random(contact_chol_decomposition.size()));
 
  958   MatrixXd mat_in(MatrixXd::Random(contact_chol_decomposition.size(), 20));
 
  961   VectorXd Uv_op_res(v_in), Uv_op_ref(v_in);
 
  963   contact_chol_decomposition.Uv(Uv_op_res);
 
  964   Uv_op_ref.noalias() = contact_chol_decomposition.U * v_in;
 
  966   BOOST_CHECK(Uv_op_res.isApprox(Uv_op_ref));
 
  968   MatrixXd Uv_mat_op_res(mat_in), Uv_mat_op_ref(mat_in);
 
  970   contact_chol_decomposition.Uv(Uv_mat_op_res);
 
  971   Uv_mat_op_ref.noalias() = contact_chol_decomposition.U * mat_in;
 
  973   BOOST_CHECK(Uv_mat_op_res.isApprox(Uv_mat_op_ref));
 
  976   VectorXd Utv_op_res(v_in), Utv_op_ref(v_in);
 
  978   contact_chol_decomposition.Utv(Utv_op_res);
 
  979   Utv_op_ref.noalias() = contact_chol_decomposition.U.transpose() * v_in;
 
  981   BOOST_CHECK(Utv_op_res.isApprox(Utv_op_ref));
 
  983   MatrixXd Utv_mat_op_res(mat_in), Utv_mat_op_ref(mat_in);
 
  985   contact_chol_decomposition.Utv(Utv_mat_op_res);
 
  986   Utv_mat_op_ref.noalias() = contact_chol_decomposition.U.transpose() * mat_in;
 
  988   BOOST_CHECK(Utv_mat_op_res.isApprox(Utv_mat_op_ref));
 
  991   VectorXd Uiv_op_res(v_in), Uiv_op_ref(v_in);
 
  993   contact_chol_decomposition.Uiv(Uiv_op_res);
 
  994   Uiv_op_ref.noalias() = contact_chol_decomposition.U.inverse() * v_in;
 
  996   BOOST_CHECK(Uiv_op_res.isApprox(Uiv_op_ref));
 
  998   MatrixXd Uiv_mat_op_res(mat_in), Uiv_mat_op_ref(mat_in);
 
 1000   contact_chol_decomposition.Uiv(Uiv_mat_op_res);
 
 1001   Uiv_mat_op_ref.noalias() = contact_chol_decomposition.U.inverse() * mat_in;
 
 1003   BOOST_CHECK(Uiv_mat_op_res.isApprox(Uiv_mat_op_ref));
 
 1006   VectorXd Utiv_op_res(v_in), Utiv_op_ref(v_in);
 
 1008   contact_chol_decomposition.Utiv(Utiv_op_res);
 
 1009   Utiv_op_ref.noalias() = contact_chol_decomposition.U.inverse().transpose() * v_in;
 
 1011   BOOST_CHECK(Utiv_op_res.isApprox(Utiv_op_ref));
 
 1013   MatrixXd Utiv_mat_op_res(mat_in), Utiv_mat_op_ref(mat_in);
 
 1015   contact_chol_decomposition.Utiv(Utiv_mat_op_res);
 
 1016   Utiv_mat_op_ref.noalias() = contact_chol_decomposition.U.inverse().transpose() * mat_in;
 
 1018   BOOST_CHECK(Utiv_mat_op_res.isApprox(Utiv_mat_op_ref));
 
 1021   MatrixXd H_inv(contact_chol_decomposition.size(), contact_chol_decomposition.size());
 
 1022   contact_chol_decomposition.inverse(H_inv);
 
 1024   MatrixXd H_inv2 = contact_chol_decomposition.U.transpose().inverse()
 
 1025                     * contact_chol_decomposition.Dinv.asDiagonal()
 
 1026                     * contact_chol_decomposition.U.inverse();
 
 1029     MatrixXd::Identity(contact_chol_decomposition.size(), contact_chol_decomposition.size());
 
 1030   contact_chol_decomposition.solveInPlace(H_inv3);
 
 1032   MatrixXd H_inv_ref = H_recomposed.inverse();
 
 1035   BOOST_CHECK(H_inv.bottomRightCorner(
model.nv, 
model.nv)
 
 1036                 .isApprox(H_inv_ref.bottomRightCorner(
model.nv, 
model.nv)));
 
 1040   BOOST_CHECK(H_inv_ref.isApprox(H_inv));
 
 1041   BOOST_CHECK(H_inv_ref.isApprox(H_inv2));
 
 1042   BOOST_CHECK(H_inv_ref.isApprox(H_inv3));
 
 1043   const VectorXd ei = VectorXd::Unit(contact_chol_decomposition.size(), 
constraint_dim);
 
 1044   VectorXd ei_inv = ei;
 
 1045   contact_chol_decomposition.solveInPlace(ei_inv);
 
 1046   VectorXd ei_inv2 = ei;
 
 1047   contact_chol_decomposition.Uiv(ei_inv2);
 
 1048   ei_inv2 = contact_chol_decomposition.Dinv.asDiagonal() * ei_inv2;
 
 1049   contact_chol_decomposition.Utiv(ei_inv2);
 
 1051   BOOST_CHECK(ei_inv.isApprox(H_inv_ref * ei));
 
 1052   BOOST_CHECK(ei_inv2.isApprox(H_inv_ref * ei));
 
 1053   BOOST_CHECK(ei_inv.isApprox(H_inv * ei));
 
 1054   BOOST_CHECK(ei_inv2.isApprox(H_inv * ei));
 
 1057   MatrixXd JMinvJt = 
H.middleRows<24>(0).rightCols(
model.nv) * data_ref.
M.inverse()
 
 1058                        * 
H.middleRows<24>(0).rightCols(
model.nv).transpose()
 
 1059                      + 
mu * Eigen::MatrixXd::Identity(24, 24);
 
 1060   MatrixXd iosim = contact_chol_decomposition.getInverseOperationalSpaceInertiaMatrix();
 
 1061   MatrixXd osim = contact_chol_decomposition.getOperationalSpaceInertiaMatrix();
 
 1063   BOOST_CHECK(iosim.isApprox(JMinvJt));
 
 1064   BOOST_CHECK(osim.isApprox(JMinvJt.inverse()));
 
 1067   data_ref.
Minv = data_ref.
M.inverse();
 
 1068   Eigen::MatrixXd Minv_test(Eigen::MatrixXd::Zero(
model.nv, 
model.nv));
 
 1069   contact_chol_decomposition.getInverseMassMatrix(Minv_test);
 
 1071   BOOST_CHECK(Minv_test.isApprox(data_ref.
Minv));
 
 1072   Eigen::MatrixXd JMinv_test(Eigen::MatrixXd::Zero(24, 
model.nv));
 
 1073   contact_chol_decomposition.getJMinv(JMinv_test);
 
 1074   MatrixXd JMinv_ref = 
H.middleRows<24>(0).rightCols(
model.nv) * data_ref.
M.inverse();
 
 1075   BOOST_CHECK(JMinv_ref.isApprox(JMinv_test));
 
 1080   using namespace Eigen;
 
 1088   model.lowerPositionLimit.head<3>().
fill(-1.);
 
 1089   model.upperPositionLimit.head<3>().
fill(1.);
 
 1092   const std::string RF = 
"rleg6_joint";
 
 1093   const std::string LF = 
"lleg6_joint";
 
 1094   const std::string RA = 
"rarm6_joint";
 
 1095   const std::string LA = 
"larm6_joint";
 
 1114   data_ref.
M.triangularView<Eigen::StrictlyLower>() =
 
 1115     data_ref.
M.triangularView<Eigen::StrictlyUpper>().transpose();
 
 1137   H.middleRows<6>(0).rightCols(
model.nv) = -ci_RF.joint1_placement.toActionMatrix() * J_RF;
 
 1138   H.middleRows<3>(6).rightCols(
model.nv) =
 
 1139     -data_ref.oMi[
model.getJointId(LF)].rotation() * J_LF.middleRows<3>(Motion::LINEAR);
 
 1140   H.middleRows<3>(9).rightCols(
model.nv) =
 
 1141     -data_ref.oMi[
model.getJointId(RA)].rotation() * J_RA.middleRows<3>(Motion::LINEAR);
 
 1142   H.middleRows<3>(12).rightCols(
model.nv) = -J_LA.middleRows<3>(Motion::LINEAR);
 
 1144   H.triangularView<Eigen::StrictlyLower>() = 
H.triangularView<Eigen::StrictlyUpper>().transpose();
 
 1153   data.M.triangularView<Eigen::StrictlyLower>() =
 
 1154     data.M.triangularView<Eigen::StrictlyUpper>().transpose();
 
 1156   BOOST_CHECK(data_ref.
D.isApprox(contact_chol_decomposition.D.tail(
model.nv)));
 
 1157   BOOST_CHECK(data_ref.
Dinv.isApprox(contact_chol_decomposition.Dinv.tail(
model.nv)));
 
 1159     data_ref.
U.isApprox(contact_chol_decomposition.U.bottomRightCorner(
model.nv, 
model.nv)));
 
 1162     contact_chol_decomposition.U.bottomRightCorner(
model.nv, 
model.nv)
 
 1163     * contact_chol_decomposition.D.tail(
model.nv).asDiagonal()
 
 1164     * contact_chol_decomposition.U.bottomRightCorner(
model.nv, 
model.nv).transpose();
 
 1165   BOOST_CHECK(M_recomposed.isApprox(
data.M));
 
 1168                                 * contact_chol_decomposition.D.asDiagonal()
 
 1169                                 * contact_chol_decomposition.U.transpose();
 
 1171   BOOST_CHECK(H_recomposed.bottomRightCorner(
model.nv, 
model.nv).isApprox(
data.M));
 
 1174   BOOST_CHECK(H_recomposed.isApprox(
H));
 
 1177   MatrixXd JMinvJt = 
H.middleRows<15>(0).rightCols(
model.nv) * data_ref.
M.inverse()
 
 1178                      * 
H.middleRows<15>(0).rightCols(
model.nv).transpose();
 
 1179   MatrixXd iosim = contact_chol_decomposition.getInverseOperationalSpaceInertiaMatrix();
 
 1180   MatrixXd osim = contact_chol_decomposition.getOperationalSpaceInertiaMatrix();
 
 1182   BOOST_CHECK(iosim.isApprox(JMinvJt));
 
 1183   BOOST_CHECK(osim.isApprox(JMinvJt.inverse()));
 
 1186   data_ref.
Minv = data_ref.
M.inverse();
 
 1187   Eigen::MatrixXd Minv_test(Eigen::MatrixXd::Zero(
model.nv, 
model.nv));
 
 1188   contact_chol_decomposition.getInverseMassMatrix(Minv_test);
 
 1190   BOOST_CHECK(Minv_test.isApprox(data_ref.
Minv));
 
 1191   Eigen::MatrixXd JMinv_test(Eigen::MatrixXd::Zero(15, 
model.nv));
 
 1192   contact_chol_decomposition.getJMinv(JMinv_test);
 
 1193   MatrixXd JMinv_ref = 
H.middleRows<15>(0).rightCols(
model.nv) * data_ref.
M.inverse();
 
 1194   BOOST_CHECK(JMinv_ref.isApprox(JMinv_test));
 
 1199   using namespace Eigen;
 
 1207   model.lowerPositionLimit.head<3>().
fill(-1.);
 
 1208   model.upperPositionLimit.head<3>().
fill(1.);
 
 1211   const std::string RF = 
"rleg6_joint";
 
 1212   const std::string LF = 
"lleg6_joint";
 
 1213   const std::string RA = 
"rarm6_joint";
 
 1214   const std::string LA = 
"larm6_joint";
 
 1223   loop_RF_LF_local.joint1_placement.setRandom();
 
 1224   loop_RF_LF_local.joint2_placement.setRandom();
 
 1226   loop_RA_LA_lwa.joint1_placement.setRandom();
 
 1227   loop_RA_LA_lwa.joint2_placement.setRandom();
 
 1237   data_ref.
M.triangularView<Eigen::StrictlyLower>() =
 
 1238     data_ref.
M.triangularView<Eigen::StrictlyUpper>().transpose();
 
 1241   const double mu = 0.1;
 
 1246     J_LA_local(6, 
model.nv);
 
 1249   Data::Matrix6x J_RF_local = loop_RF_LF_local.joint1_placement.toActionMatrixInverse() * J_RF;
 
 1252   Data::Matrix6x J_LF_local = loop_RF_LF_local.joint2_placement.toActionMatrixInverse() * J_LF;
 
 1253   J_RA_local.setZero();
 
 1255   J_RA_local = loop_RA_LA_lwa.joint1_placement.toActionMatrixInverse() * J_RA_local;
 
 1256   J_LA_local.setZero();
 
 1258   J_LA_local = loop_RA_LA_lwa.joint2_placement.toActionMatrixInverse() * J_LA_local;
 
 1261   J_RF_world.setZero();
 
 1263   J_LF_world.setZero();
 
 1267   const SE3 oM1_loop1 =
 
 1268     data_ref.oMi[loop_RF_LF_local.joint1_id] * loop_RF_LF_local.joint1_placement;
 
 1269   const SE3 oM2_loop1 =
 
 1270     data_ref.oMi[loop_RF_LF_local.joint2_id] * loop_RF_LF_local.joint2_placement;
 
 1271   const SE3 _1M2_loop1 = oM1_loop1.inverse() * oM2_loop1;
 
 1272   const SE3 oM1_loop2 = data_ref.oMi[loop_RA_LA_lwa.joint1_id] * loop_RA_LA_lwa.joint1_placement;
 
 1273   const SE3 oM2_loop2 = data_ref.oMi[loop_RA_LA_lwa.joint2_id] * loop_RA_LA_lwa.joint2_placement;
 
 1274   const SE3 _1M2_loop2 = oM1_loop2.inverse() * oM2_loop2;
 
 1283   H.middleRows<6>(0).rightCols(
model.nv) = J_RF_local - _1M2_loop1.toActionMatrix() * J_LF_local;
 
 1284   const SE3 oM1_loop2_lwa = 
SE3(oM1_loop2.rotation(), SE3::Vector3::Zero());
 
 1285   H.middleRows<6>(6).rightCols(
model.nv) =
 
 1286     oM1_loop2_lwa.toActionMatrix() * J_RA_local
 
 1287     - (oM1_loop2_lwa.toActionMatrix() * _1M2_loop2.toActionMatrix()) * J_LA_local;
 
 1289   H.triangularView<Eigen::StrictlyLower>() = 
H.triangularView<Eigen::StrictlyUpper>().transpose();
 
 1297   Data::MatrixXs H_recomposed = contact_chol_decomposition.matrix();
 
 1299   data.M.triangularView<Eigen::StrictlyLower>() =
 
 1300     data.M.triangularView<Eigen::StrictlyUpper>().transpose();
 
 1301   BOOST_CHECK(H_recomposed.bottomRightCorner(
model.nv, 
model.nv).isApprox(
data.M));
 
 1304   BOOST_CHECK(H_recomposed.isApprox(
H));
 
 1307   MatrixXd H_inv(contact_chol_decomposition.size(), contact_chol_decomposition.size());
 
 1308   contact_chol_decomposition.inverse(H_inv);
 
 1310   MatrixXd H_inv_ref = H_recomposed.inverse();
 
 1312   BOOST_CHECK(H_inv_ref.isApprox(H_inv));
 
 1315   MatrixXd JMinvJt = 
H.middleRows<12>(0).rightCols(
model.nv) * data_ref.
M.inverse()
 
 1316                        * 
H.middleRows<12>(0).rightCols(
model.nv).transpose()
 
 1317                      + 
mu * Eigen::MatrixXd::Identity(12, 12);
 
 1318   MatrixXd iosim = contact_chol_decomposition.getInverseOperationalSpaceInertiaMatrix();
 
 1319   MatrixXd osim = contact_chol_decomposition.getOperationalSpaceInertiaMatrix();
 
 1321   BOOST_CHECK(iosim.isApprox(JMinvJt));
 
 1322   BOOST_CHECK(osim.isApprox(JMinvJt.inverse()));
 
 1325   data_ref.
Minv = data_ref.
M.inverse();
 
 1326   Eigen::MatrixXd Minv_test(Eigen::MatrixXd::Zero(
model.nv, 
model.nv));
 
 1327   contact_chol_decomposition.getInverseMassMatrix(Minv_test);
 
 1329   BOOST_CHECK(Minv_test.isApprox(data_ref.
Minv));
 
 1330   Eigen::MatrixXd JMinv_test(Eigen::MatrixXd::Zero(12, 
model.nv));
 
 1331   contact_chol_decomposition.getJMinv(JMinv_test);
 
 1332   MatrixXd JMinv_ref = 
H.middleRows<12>(0).rightCols(
model.nv) * data_ref.
M.inverse();
 
 1333   BOOST_CHECK(JMinv_ref.isApprox(JMinv_test));
 
 1338   using namespace Eigen;
 
 1346   model.lowerPositionLimit.head<3>().
fill(-1.);
 
 1347   model.upperPositionLimit.head<3>().
fill(1.);
 
 1350   const std::string RF = 
"rleg6_joint";
 
 1351   const std::string LF = 
"lleg6_joint";
 
 1352   const std::string RA = 
"rarm6_joint";
 
 1353   const std::string LA = 
"larm6_joint";
 
 1362   loop_RF_LF_local.joint1_placement.setRandom();
 
 1363   loop_RF_LF_local.joint2_placement.setRandom();
 
 1365   loop_RA_LA_lwa.joint1_placement.setRandom();
 
 1366   loop_RA_LA_lwa.joint2_placement.setRandom();
 
 1376   data_ref.
M.triangularView<Eigen::StrictlyLower>() =
 
 1377     data_ref.
M.triangularView<Eigen::StrictlyUpper>().transpose();
 
 1380   const double mu = 0.1;
 
 1385     J_LA_local(6, 
model.nv);
 
 1389     loop_RF_LF_local.joint1_placement.toActionMatrixInverse() * J_RF;
 
 1393     loop_RF_LF_local.joint2_placement.toActionMatrixInverse() * J_LF;
 
 1394   J_RA_local.setZero();
 
 1396   J_RA_local = loop_RA_LA_lwa.joint1_placement.toActionMatrixInverse() * J_RA_local;
 
 1397   J_LA_local.setZero();
 
 1399   J_LA_local = loop_RA_LA_lwa.joint2_placement.toActionMatrixInverse() * J_LA_local;
 
 1402   J_RF_world.setZero();
 
 1404   J_LF_world.setZero();
 
 1408   const SE3 oM1_loop1 =
 
 1409     data_ref.oMi[loop_RF_LF_local.joint1_id] * loop_RF_LF_local.joint1_placement;
 
 1410   const SE3 oM2_loop1 =
 
 1411     data_ref.oMi[loop_RF_LF_local.joint2_id] * loop_RF_LF_local.joint2_placement;
 
 1412   const SE3 _1M2_loop1 = oM1_loop1.inverse() * oM2_loop1;
 
 1413   const SE3 oM1_loop2 = data_ref.oMi[loop_RA_LA_lwa.joint1_id] * loop_RA_LA_lwa.joint1_placement;
 
 1414   const SE3 oM2_loop2 = data_ref.oMi[loop_RA_LA_lwa.joint2_id] * loop_RA_LA_lwa.joint2_placement;
 
 1415   const SE3 _1M2_loop2 = oM1_loop2.inverse() * oM2_loop2;
 
 1424   H.middleRows<3>(0).rightCols(
model.nv) =
 
 1425     J_RF_local.middleRows<3>(Motion::LINEAR)
 
 1426     - _1M2_loop1.rotation() * J_LF_local.middleRows<3>(Motion::LINEAR);
 
 1427   const SE3 oM1_loop2_lwa = 
SE3(oM1_loop2.rotation(), SE3::Vector3::Zero());
 
 1428   const SE3 oM2_loop2_lwa = 
SE3(oM2_loop2.rotation(), SE3::Vector3::Zero());
 
 1429   H.middleRows<3>(3).rightCols(
model.nv) =
 
 1430     (oM1_loop2_lwa.toActionMatrix() * J_RA_local - (oM2_loop2_lwa.toActionMatrix()) * J_LA_local)
 
 1431       .middleRows<3>(Motion::LINEAR);
 
 1433   H.triangularView<Eigen::StrictlyLower>() = 
H.triangularView<Eigen::StrictlyUpper>().transpose();
 
 1443   Data::MatrixXs H_recomposed = contact_chol_decomposition.matrix();
 
 1445   data.M.triangularView<Eigen::StrictlyLower>() =
 
 1446     data.M.triangularView<Eigen::StrictlyUpper>().transpose();
 
 1447   BOOST_CHECK(H_recomposed.bottomRightCorner(
model.nv, 
model.nv).isApprox(
data.M));
 
 1450   BOOST_CHECK(H_recomposed.isApprox(
H));
 
 1458   MatrixXd H_inv(contact_chol_decomposition.size(), contact_chol_decomposition.size());
 
 1459   contact_chol_decomposition.inverse(H_inv);
 
 1461   MatrixXd H_inv_ref = H_recomposed.inverse();
 
 1463   BOOST_CHECK(H_inv_ref.isApprox(H_inv));
 
 1466   MatrixXd JMinvJt = 
H.middleRows<6>(0).rightCols(
model.nv) * data_ref.
M.inverse()
 
 1467                        * 
H.middleRows<6>(0).rightCols(
model.nv).transpose()
 
 1468                      + 
mu * Eigen::MatrixXd::Identity(6, 6);
 
 1469   MatrixXd iosim = contact_chol_decomposition.getInverseOperationalSpaceInertiaMatrix();
 
 1470   MatrixXd osim = contact_chol_decomposition.getOperationalSpaceInertiaMatrix();
 
 1472   BOOST_CHECK(iosim.isApprox(JMinvJt));
 
 1473   BOOST_CHECK(osim.isApprox(JMinvJt.inverse()));
 
 1476   data_ref.
Minv = data_ref.
M.inverse();
 
 1477   Eigen::MatrixXd Minv_test(Eigen::MatrixXd::Zero(
model.nv, 
model.nv));
 
 1478   contact_chol_decomposition.getInverseMassMatrix(Minv_test);
 
 1480   Eigen::MatrixXd JMinv_test(Eigen::MatrixXd::Zero(6, 
model.nv));
 
 1481   contact_chol_decomposition.getJMinv(JMinv_test);
 
 1482   MatrixXd JMinv_ref = 
H.middleRows<6>(0).rightCols(
model.nv) * data_ref.
M.inverse();
 
 1483   BOOST_CHECK(JMinv_ref.isApprox(JMinv_test));
 
 1484   BOOST_CHECK(Minv_test.isApprox(data_ref.
Minv));
 
 1489   using namespace Eigen;
 
 1497   model.lowerPositionLimit.head<3>().
fill(-1.);
 
 1498   model.upperPositionLimit.head<3>().
fill(1.);
 
 1501   const std::string RF = 
"rleg6_joint";
 
 1502   const std::string LF = 
"lleg6_joint";
 
 1516   const double mu1 = 1e-2, mu2 = 1e-10;
 
 1522     contact_chol_decomposition.updateDamping(mu2);
 
 1528     BOOST_CHECK(contact_chol_decomposition.D.isApprox(contact_chol_decomposition_ref.D));
 
 1529     BOOST_CHECK(contact_chol_decomposition.Dinv.isApprox(contact_chol_decomposition_ref.Dinv));
 
 1530     BOOST_CHECK(contact_chol_decomposition.U.isApprox(contact_chol_decomposition_ref.U));
 
 1537     contact_chol_decomposition.getDelassusCholeskyExpression().updateDamping(mu2);
 
 1543     BOOST_CHECK(contact_chol_decomposition.D.isApprox(contact_chol_decomposition_ref.D));
 
 1544     BOOST_CHECK(contact_chol_decomposition.Dinv.isApprox(contact_chol_decomposition_ref.Dinv));
 
 1545     BOOST_CHECK(contact_chol_decomposition.U.isApprox(contact_chol_decomposition_ref.U));
 
 1549 BOOST_AUTO_TEST_SUITE_END()