15 #include <boost/test/unit_test.hpp>
16 #include <boost/utility/binary.hpp>
17 #include <boost/algorithm/string.hpp>
18 #include <boost/mpl/vector.hpp>
20 #define EIGEN_VECTOR_IS_APPROX(Va, Vb, precision) \
21 BOOST_CHECK_MESSAGE( \
22 (Va).isApprox(Vb, precision), "check " #Va ".isApprox(" #Vb ") failed " \
24 << (Va).transpose() << "\n!=\n" \
25 << (Vb).transpose() << "\n]")
26 #define EIGEN_MATRIX_IS_APPROX(Va, Vb, precision) \
27 BOOST_CHECK_MESSAGE( \
28 (Va).isApprox(Vb, precision), "check " #Va ".isApprox(" #Vb ") failed " \
36 #define IFVERBOSE if (VERBOSE)
40 template<
typename Derived>
43 return os << lg.
name();
45 template<
typename LieGroupCollection>
48 return os << lg.
name();
58 const Scalar prec = Eigen::NumTraits<Scalar>::dummy_precision();
59 BOOST_TEST_MESSAGE(
"Testing Joint over " << jmodel.shortname());
60 typedef typename T::ConfigVector_t ConfigVector_t;
61 typedef typename T::TangentVector_t TangentVector_t;
63 ConfigVector_t
q1(ConfigVector_t::Random(jmodel.nq()));
64 TangentVector_t q1_dot(TangentVector_t::Random(jmodel.nv()));
65 ConfigVector_t
q2(ConfigVector_t::Random(jmodel.nq()));
67 static ConfigVector_t Ones(ConfigVector_t::Ones(jmodel.nq()));
72 q1 = LieGroupType().randomConfiguration(-Ones, Ones);
75 typename T::JointDataDerived jdata = jmodel.createData();
78 jmodel.calc(jdata,
q1, q1_dot);
82 q2 = LieGroupType().integrate(
q1, q1_dot);
84 jmodel.calc(jdata,
q2);
87 double tol_test = 1e2;
88 if (jmodel.shortname() ==
"JointModelPlanar")
91 const SE3 M2_exp = M1 *
exp6(v1);
93 if (jmodel.shortname() !=
"JointModelSphericalZYX")
96 M2.isApprox(M2_exp), std::string(
"Error when integrating1 " + jmodel.shortname()));
100 ConfigVector_t qTest(ConfigVector_t::Random(jmodel.nq()));
101 TangentVector_t qTest_dot(TangentVector_t::Random(jmodel.nv()));
102 ConfigVector_t qResult(ConfigVector_t::Random(jmodel.nq()));
103 qTest = LieGroupType().randomConfiguration(-Ones, Ones);
104 qResult = LieGroupType().integrate(qTest, qTest_dot);
105 LieGroupType().integrate(qTest, qTest_dot, qTest);
109 "Normalization error when integrating with same input and output " + jmodel.shortname()));
112 typename T::JointDataDerived jdata = jmodel.createData();
113 jmodel.calc(jdata, qTest);
117 typename T::JointDataDerived jdata = jmodel.createData();
118 jmodel.calc(jdata, qResult);
122 MTest.isApprox(MResult),
124 "Inconsistent value when integrating with same input and output " + jmodel.shortname()));
127 qTest.isApprox(qResult, prec),
129 "Inconsistent value when integrating with same input and output " + jmodel.shortname()));
132 ConfigVector_t q3 = LieGroupType().integrate(
q2, -q1_dot);
133 jmodel.calc(jdata, q3);
137 M3.isApprox(M1), std::string(
"Error when integrating back " + jmodel.shortname()));
140 ConfigVector_t q_interpolate = LieGroupType().interpolate(
q1,
q2, 0.);
142 q_interpolate.isApprox(
q1), std::string(
"Error when interpolating " + jmodel.shortname()));
144 q_interpolate = LieGroupType().interpolate(
q1,
q2, 1.);
145 if (jmodel.shortname() ==
"JointModelPlanar")
148 q_interpolate.isApprox(
q2, 1e-8),
149 std::string(
"Error when interpolating " + jmodel.shortname()));
152 q_interpolate.isApprox(
q2, 1e0 * prec),
153 std::string(
"Error when interpolating " + jmodel.shortname()));
155 if (jmodel.shortname() !=
"JointModelSphericalZYX")
157 q_interpolate = LieGroupType().interpolate(
q1,
q2,
u);
158 jmodel.calc(jdata, q_interpolate);
159 SE3 M_interpolate = jdata.M;
161 SE3 M_interpolate_expected = M1 *
exp6(
u * v1);
163 M_interpolate_expected.isApprox(M_interpolate, 1e4 * prec),
164 std::string(
"Error when interpolating " + jmodel.shortname()));
168 TangentVector_t
zero = LieGroupType().difference(
q1,
q1);
170 zero.isZero(), std::string(
"Error: difference between two equal configurations is not 0."));
171 zero = LieGroupType().difference(
q2,
q2);
173 zero.isZero(), std::string(
"Error: difference between two equal configurations is not 0."));
178 TangentVector_t vdiff = LieGroupType().difference(
q1,
q2);
180 vdiff.isApprox(q1_dot, tol_test * prec),
181 std::string(
"Error when differentiating " + jmodel.shortname()));
185 BOOST_CHECK_MESSAGE(
dist > 0.,
"distance - wrong results");
186 BOOST_CHECK_SMALL(math::fabs(
dist - q1_dot.norm()), tol_test * prec);
188 std::string error_prefix(
"LieGroup");
189 error_prefix +=
" on joint " + jmodel.shortname();
191 BOOST_CHECK_MESSAGE(jmodel.nq() ==
LieGroupType::NQ, std::string(error_prefix +
" - nq "));
192 BOOST_CHECK_MESSAGE(jmodel.nv() ==
LieGroupType::NV, std::string(error_prefix +
" - nv "));
196 std::string(error_prefix +
" - RandomConfiguration dimensions "));
198 ConfigVector_t q_normalize(ConfigVector_t::Random());
199 Eigen::VectorXd q_normalize_ref(q_normalize);
200 if (jmodel.shortname() ==
"JointModelSpherical")
204 std::string(error_prefix +
" - !isNormalized "));
205 q_normalize_ref /= q_normalize_ref.norm();
207 else if (jmodel.shortname() ==
"JointModelFreeFlyer")
211 std::string(error_prefix +
" - !isNormalized "));
212 q_normalize_ref.template tail<4>() /= q_normalize_ref.template tail<4>().norm();
214 else if (boost::algorithm::istarts_with(jmodel.shortname(),
"JointModelRUB"))
218 std::string(error_prefix +
" - !isNormalized "));
219 q_normalize_ref /= q_normalize_ref.norm();
221 else if (jmodel.shortname() ==
"JointModelPlanar")
225 std::string(error_prefix +
" - !isNormalized "));
226 q_normalize_ref.template tail<2>() /= q_normalize_ref.template tail<2>().norm();
229 LieGroupType().
isNormalized(q_normalize_ref), std::string(error_prefix +
" - isNormalized "));
230 LieGroupType().normalize(q_normalize);
232 q_normalize.isApprox(q_normalize_ref), std::string(error_prefix +
" - normalize "));
238 template<
typename Jo
intModel,
typename Jo
intData>
241 for (
int i = 0;
i <= 50; ++
i)
251 jmodel.setIndexes(0, 0, 0);
252 typename T::JointDataDerived jdata = jmodel.createData();
254 run_tests(jmodel, jdata);
261 pinocchio::JointModelRevoluteUnaligned::JointDataDerived jdata = jmodel.
createData();
263 run_tests(jmodel, jdata);
270 pinocchio::JointModelPrismaticUnaligned::JointDataDerived jdata = jmodel.
createData();
272 run_tests(jmodel, jdata);
281 typedef typename T::ConfigVector_t ConfigVector_t;
282 typedef typename T::TangentVector_t TangentVector_t;
283 typedef typename T::JacobianMatrix_t JacobianMatrix_t;
287 BOOST_TEST_MESSAGE(lg.name());
288 ConfigVector_t
q[2], q_dv[2];
293 TangentVector_t va, vb,
dv;
294 JacobianMatrix_t
J[2];
297 lg.difference(
q[0],
q[1], va);
298 lg.template dDifference<ARG0>(
q[0],
q[1],
J[0]);
299 lg.template dDifference<ARG1>(
q[0],
q[1],
J[1]);
302 for (
int k = 0; k < 2; ++k)
304 BOOST_TEST_MESSAGE(
"Checking J" << k <<
'\n' <<
J[k]);
308 for (
int i = 0;
i <
dv.size(); ++
i)
311 lg.integrate(
q[k],
dv, q_dv[k]);
312 lg.difference(q_dv[0], q_dv[1], vb);
315 TangentVector_t J_dv =
J[k].col(
i);
316 TangentVector_t vb_va = (vb - va) /
eps;
331 template<
typename Scalar,
int Options>
335 const Scalar prec = Eigen::NumTraits<Scalar>::dummy_precision();
338 typedef typename LG_t::ConfigVector_t ConfigVector_t;
339 typedef typename LG_t::JacobianMatrix_t JacobianMatrix_t;
340 typedef typename LG_t::ConstQuaternionMap_t ConstQuaternionMap_t;
348 ConstQuaternionMap_t quat0(
q[0].
template tail<4>().
data()),
349 quat1(
q[1].
template tail<4>().
data());
350 JacobianMatrix_t
J[2];
352 lg.template dDifference<ARG0>(
q[0],
q[1],
J[0]);
353 lg.template dDifference<ARG1>(
q[0],
q[1],
J[1]);
356 om1(
typename SE3::Quaternion(
q[1].
template tail<4>()).matrix(),
q[1].
template head<3>()),
357 _1m2(om1.actInv(om0));
362 ConfigVector_t q_interp = lg.interpolate(
q[0],
q[1],
u);
363 ConstQuaternionMap_t quat_interp(q_interp.template tail<4>().data());
365 SE3 M0(quat0,
q[0].
template head<3>());
366 SE3 M1(quat1,
q[1].
template head<3>());
369 SE3 M_interp(quat_interp, q_interp.template head<3>());
370 BOOST_CHECK(M_u.isApprox(M_interp, prec));
373 template<
typename Scalar,
int Options>
383 typedef typename LG_t::ConfigVector_t ConfigVector_t;
384 typedef typename LG_t::JacobianMatrix_t JacobianMatrix_t;
391 JacobianMatrix_t
J[2];
393 lg.template dDifference<ARG0>(
q[0],
q[1],
J[0]);
394 lg.template dDifference<ARG1>(
q[0],
q[1],
J[1]);
398 JacobianMatrix_t
X(JacobianMatrix_t::Identity());
399 X.template bottomRightCorner<3, 3>() = oR1.transpose() * oR0;
404 template<
bool around_
identity>
410 typedef typename T::ConfigVector_t ConfigVector_t;
411 typedef typename T::TangentVector_t TangentVector_t;
412 typedef typename T::JacobianMatrix_t JacobianMatrix_t;
416 ConfigVector_t
q = lg.random();
417 TangentVector_t
v,
dq,
dv;
426 ConfigVector_t q_v = lg.integrate(
q,
v);
430 JacobianMatrix_t Jq, Jv;
431 lg.dIntegrate_dq(
q,
v, Jq);
432 lg.dIntegrate_dv(
q,
v, Jv);
436 for (
int i = 0;
i <
v.size(); ++
i)
439 ConfigVector_t q_dq = lg.integrate(
q,
dq);
441 ConfigVector_t q_dq_v = lg.integrate(q_dq,
v);
442 TangentVector_t Jq_dq = Jq.col(
i);
444 TangentVector_t dI_dq = lg.difference(q_v, q_dq_v) /
eps;
447 ConfigVector_t q_v_dv = lg.integrate(
q, (
v +
dv).eval());
448 TangentVector_t Jv_dv = Jv.col(
i);
450 TangentVector_t dI_dv = lg.difference(q_v, q_v_dv) /
eps;
463 typedef typename T::ConfigVector_t ConfigVector_t;
464 typedef typename T::TangentVector_t TangentVector_t;
465 typedef typename T::JacobianMatrix_t JacobianMatrix_t;
470 BOOST_TEST_MESSAGE(lg.name());
471 ConfigVector_t qa, qb(lg.nq());
473 TangentVector_t
v(lg.nv());
475 lg.integrate(qa,
v, qb);
477 JacobianMatrix_t Jd_qb, Ji_v;
479 lg.template dDifference<ARG1>(qa, qb, Jd_qb);
480 lg.template dIntegrate<ARG1>(qa,
v, Ji_v);
484 (Jd_qb * Ji_v).isIdentity(),
"Jd_qb\n"
489 << Jd_qb * Ji_v <<
'\n');
498 typedef typename T::ConfigVector_t ConfigVector_t;
499 typedef typename T::TangentVector_t TangentVector_t;
500 typedef typename T::JacobianMatrix_t JacobianMatrix_t;
505 BOOST_TEST_MESSAGE(lg.name());
506 ConfigVector_t qa, qb(lg.nq());
508 TangentVector_t
v(lg.nv()), tvec_at_qb(lg.nv()), tvec_at_qa(lg.nv()), tvec_at_qa_r(lg.nv());
510 lg.integrate(qa,
v, qb);
513 tvec_at_qb.setRandom();
514 lg.dIntegrateTransport(qa,
v, tvec_at_qb, tvec_at_qa,
ARG0);
517 TangentVector_t v_r = -
v;
518 ConfigVector_t qa_r = lg.integrate(qb, v_r);
519 lg.dIntegrateTransport(qa_r, v_r, tvec_at_qa, tvec_at_qa_r,
ARG0);
521 BOOST_CHECK_SMALL((qa - qa_r).norm(), 1e-6);
522 BOOST_CHECK_SMALL((tvec_at_qb - tvec_at_qa_r).norm(), 1e-6);
525 JacobianMatrix_t J_at_qa(lg.nv(), lg.nv());
527 JacobianMatrix_t J_at_qb(lg.nv(), lg.nv());
528 lg.dIntegrateTransport(qa,
v, J_at_qa, J_at_qb,
ARG0);
529 JacobianMatrix_t J_at_qa_r(lg.nv(), lg.nv());
530 lg.dIntegrateTransport(qa_r, v_r, J_at_qb, J_at_qa_r,
ARG0);
532 BOOST_CHECK_SMALL((J_at_qa - J_at_qa_r).norm(), 1e-6);
541 typedef typename T::ConfigVector_t ConfigVector_t;
542 typedef typename T::TangentVector_t TangentVector_t;
546 ConfigVector_t
q = lg.random();
547 TangentVector_t
dv(TangentVector_t::Zero(lg.nv()));
549 BOOST_TEST_MESSAGE(lg.name());
550 typedef Eigen::Matrix<Scalar, T::NQ, T::NV> JacobianCoeffs;
551 JacobianCoeffs Jintegrate(JacobianCoeffs::Zero(lg.nq(), lg.nv()));
552 lg.integrateCoeffWiseJacobian(
q, Jintegrate);
553 JacobianCoeffs Jintegrate_fd(JacobianCoeffs::Zero(lg.nq(), lg.nv()));
556 for (
int i = 0;
i < lg.nv(); ++
i)
559 ConfigVector_t
q_next(ConfigVector_t::Zero(lg.nq()));
570 BOOST_AUTO_TEST_SUITE(BOOST_TEST_MODULE)
574 typedef boost::variant<
580 for (
int i = 0;
i < 20; ++
i)
581 boost::mpl::for_each<Variant::types>(
TestJoint());
595 typedef boost::mpl::vector<
608 for (
int i = 0;
i < 20; ++
i)
620 typedef boost::mpl::vector<
633 for (
int i = 0;
i < 20; ++
i)
645 typedef boost::mpl::vector<
658 for (
int i = 0;
i < 20; ++
i)
673 typedef boost::mpl::vector<
686 for (
int i = 0;
i < 20; ++
i)
698 typedef boost::mpl::vector<
711 for (
int i = 0;
i < 20; ++
i)
716 typedef LieGroup::ConfigVector_t ConfigVector_t;
719 ConfigVector_t
q = lg.random();
722 typedef Eigen::Matrix<Scalar, LieGroup::NQ, LieGroup::NV> JacobianCoeffs;
723 JacobianCoeffs Jintegrate(JacobianCoeffs::Zero(lg.nq(), lg.nv()));
724 lg.integrateCoeffWiseJacobian(
q, Jintegrate);
731 VSO_t::ConfigVector_t
q,
732 lo(VSO_t::ConfigVector_t::Constant(-std::numeric_limits<double>::infinity())),
735 up(VSO_t::ConfigVector_t::Constant(0));
740 VSO_t().randomConfiguration(lo, up,
q);
742 catch (
const std::runtime_error &)
746 BOOST_CHECK_MESSAGE(error,
"Random configuration between infinite bounds should return an error");
756 BOOST_CHECK(vs1.
nq() == 1);
757 BOOST_CHECK(vs1.
nv() == 1);
758 BOOST_CHECK(vs1.
name() ==
"R^1");
764 BOOST_CHECK(vs2.
nq() == 2);
765 BOOST_CHECK(vs2.
nv() == 2);
766 BOOST_CHECK(vs2.
name() ==
"R^2");
772 BOOST_CHECK(vs3.
nq() == 3);
773 BOOST_CHECK(vs3.
nv() == 3);
774 BOOST_CHECK(vs3.
name() ==
"R^3");
781 BOOST_CHECK(so2.nq() == 2);
782 BOOST_CHECK(so2.nv() == 1);
783 BOOST_CHECK(so2.name() ==
"SO(2)");
784 BOOST_CHECK(so2.neutral() ==
neutral);
790 BOOST_CHECK(so3.nq() == 4);
791 BOOST_CHECK(so3.nv() == 3);
792 BOOST_CHECK(so3.name() ==
"SO(3)");
793 BOOST_CHECK(so3.neutral() ==
neutral);
799 BOOST_CHECK(se2.nq() == 4);
800 BOOST_CHECK(se2.nv() == 3);
801 BOOST_CHECK(se2.name() ==
"SE(2)");
802 BOOST_CHECK(se2.neutral() ==
neutral);
808 BOOST_CHECK(se3.nq() == 7);
809 BOOST_CHECK(se3.nv() == 6);
810 BOOST_CHECK(se3.name() ==
"SE(3)");
811 BOOST_CHECK(se3.neutral() ==
neutral);
819 BOOST_CHECK(r2xso2.nq() == 4);
820 BOOST_CHECK(r2xso2.nv() == 3);
821 BOOST_CHECK(r2xso2.name() ==
"R^2*SO(2)");
822 BOOST_CHECK(r2xso2.neutral() ==
neutral);
830 BOOST_CHECK(r3xso3.nq() == 7);
831 BOOST_CHECK(r3xso3.nv() == 6);
832 BOOST_CHECK(r3xso3.name() ==
"R^3*SO(3)");
833 BOOST_CHECK(r3xso3.neutral() ==
neutral);
839 BOOST_CHECK(
dim == 2);
849 Eigen::VectorXd
q1(so3.nq());
850 Eigen::VectorXd
q2(so3.nq());
851 q1 << 0, 0, -0.1953711450011105244, 0.9807293794421349169;
852 q2 << 0, 0, -0.19537114500111049664, 0.98072937944213492244;
854 BOOST_CHECK_MESSAGE(so3.distance(
q1,
q2) > 0.,
"SO3 small distance - wrong results");
857 template<
typename LieGroupCollection>
865 template<
typename Derived>
869 test(lg, lg_generic);
872 template<
typename Derived>
876 BOOST_CHECK(lg.
nq() ==
nq(lg_generic));
877 BOOST_CHECK(lg.
nv() ==
nv(lg_generic));
879 BOOST_CHECK(lg.
name() ==
name(lg_generic));
883 typedef typename LieGroupGeneric::ConfigVector_t ConfigVectorGeneric;
884 typedef typename LieGroupGeneric::TangentVector_t TangentVectorGeneric;
891 ConfigVectorGeneric
qout(lg.
nq());
892 integrate(lg_generic, ConfigVectorGeneric(
q0), TangentVectorGeneric(
v),
qout);
893 BOOST_CHECK(
qout.isApprox(qout_ref));
909 boost::mpl::for_each<LieGroupCollectionDefault::LieGroupVariant::types>(
913 template<
typename Lg1,
typename Lg2>
917 BOOST_CHECK_EQUAL(LieGroupGeneric(lg1), LieGroupGeneric(lg2));
920 template<
typename Lg1,
typename Lg2>
924 BOOST_CHECK_PREDICATE(
925 std::not_equal_to<LieGroupGeneric>(), (LieGroupGeneric(lg1))(LieGroupGeneric(lg2)));
936 BOOST_AUTO_TEST_SUITE_END()