@@ -38,185 +38,6 @@ void addJointAndBody(
3838
3939BOOST_AUTO_TEST_SUITE (JointEllipsoid)
4040
41- BOOST_AUTO_TEST_CASE(vsFreeFlyer)
42- {
43- using namespace pinocchio ;
44- typedef SE3::Vector3 Vector3;
45- typedef Eigen::Matrix<double , 6 , 1 > Vector6;
46- typedef Eigen::Matrix<double , 7 , 1 > VectorFF;
47- typedef SE3::Matrix3 Matrix3;
48-
49- Model modelEllipsoid, modelFreeflyer;
50-
51- Inertia inertia (1 ., Vector3 (0.5 , 0 ., 0.0 ), Matrix3::Identity ());
52- SE3 pos (1 );
53- pos.translation () = SE3::LinearType (1 ., 0 ., 0 .);
54-
55- addJointAndBody (modelEllipsoid, JointModelEllipsoid (1 , 2 , 3 ), 0 , pos, " ellipsoid" , inertia);
56- addJointAndBody (modelFreeflyer, JointModelFreeFlyer (), 0 , pos, " free-flyer" , inertia);
57-
58- Data dataEllipsoid (modelEllipsoid);
59-
60- Eigen::VectorXd q = Eigen::VectorXd::Ones (modelEllipsoid.nq );
61- Eigen::VectorXd v = Eigen::VectorXd::Ones (modelEllipsoid.nv );
62-
63- forwardKinematics (modelEllipsoid, dataEllipsoid, q, v);
64-
65- Eigen::VectorXd tauEllipsoid = Eigen::VectorXd::Ones (modelEllipsoid.nv );
66-
67- Eigen::VectorXd aEllipsoid = Eigen::VectorXd::Ones (modelEllipsoid.nv );
68-
69- // ForwardDynamics == aba
70- Eigen::VectorXd aAbaEllipsoid =
71- aba (modelEllipsoid, dataEllipsoid, q, v, tauEllipsoid, Convention::WORLD);
72-
73- // Calculer jdata.S().transpose() * data.f[i]
74- }
75-
76- // BOOST_AUTO_TEST_CASE(vsSphericalZYX)
77- // {
78- // using namespace pinocchio;
79- // typedef SE3::Vector3 Vector3;
80- // typedef Eigen::Matrix<double, 6, 1> Vector6;
81- // typedef SE3::Matrix3 Matrix3;
82-
83- // // Build models using ModelGraph to enable configuration conversion
84- // graph::ModelGraph g;
85- // Inertia inertia(1., Vector3(0.5, 0., 0.0), Matrix3::Identity());
86- // SE3 pos(1);
87- // pos.translation() = SE3::LinearType(1., 0., 0.);
88-
89- // g.addBody("root_body", inertia);
90- // g.addBody("end_body", inertia);
91-
92- // // Create SphericalZYX joint (uses ZYX Euler angles)
93- // g.addJoint(
94- // "spherical_joint",
95- // graph::JointSphericalZYX(),
96- // "root_body",
97- // SE3::Identity(),
98- // "end_body",
99- // pos);
100-
101- // // Build SphericalZYX model
102- // const auto forward_build = graph::buildModelWithBuildInfo(g, "root_body", SE3::Identity());
103- // const Model & modelSphericalZYX = forward_build.model;
104- // Data dataSphericalZYX(modelSphericalZYX);
105-
106- // Eigen::VectorXd q_zyx(3);
107- // q_zyx << 0.5, 1.2, -0.8;
108- // Eigen::VectorXd v_zyx(3);
109- // v_zyx << 0.1, -0.3, 0.7;
110- // forwardKinematics(modelSphericalZYX, dataSphericalZYX, q_zyx, v_zyx);
111- // updateFramePlacements(modelSphericalZYX, dataSphericalZYX);
112-
113- // auto end_index = modelSphericalZYX.getFrameId("end_body", BODY);
114- // auto X_end = dataSphericalZYX.oMf[end_index];
115- // const auto backward_build =
116- // graph::buildModelWithBuildInfo(g, "end_body", X_end);
117-
118- // const Model & XYZlacirehpSledom = backward_build.model;
119-
120- // // Create converter from SphericalZYX to Ellipsoid
121- // auto converter = graph::createConverter(
122- // modelSphericalZYX, XYZlacirehpSledom, forward_build.build_info, backward_build.build_info);
123-
124- // // Convert to Ellipsoid configuration
125- // Eigen::VectorXd q_xyz = Eigen::VectorXd::Zero(XYZlacirehpSledom.nq);
126- // Eigen::VectorXd v_xyz = Eigen::VectorXd::Zero(XYZlacirehpSledom.nv);
127- // converter.convertConfigurationVector(q_zyx, q_xyz);
128- // converter.convertTangentVector(q_zyx, v_zyx, v_xyz);
129-
130- // std::cout << "\n=== Configuration Conversion ===" << std::endl;
131- // std::cout << "q_zyx (SphericalZYX): " << q_zyx.transpose() << std::endl;
132- // std::cout << "q_xyz (converted): " << q_xyz.transpose() << std::endl;
133- // std::cout << "v_zyx (SphericalZYX): " << v_zyx.transpose() << std::endl;
134- // std::cout << "v_xyz (converted): " << v_xyz.transpose() << std::endl;
135-
136- // Model modelEllipsoid;
137- // addJointAndBody(modelEllipsoid, JointModelEllipsoid(0, 0, 0), 0, pos, "ellipsoid", inertia);
138- // Data dataEllipsoid(modelEllipsoid);
139-
140- // // Test forward kinematics with converted configurations
141- // forwardKinematics(modelEllipsoid, dataEllipsoid, q_xyz, v_xyz);
142- // forwardKinematics(modelSphericalZYX, dataSphericalZYX, q_zyx, v_zyx);
143-
144- // // Check that the transformations are identical
145- // std::cout << "\n=== Forward Kinematics Comparison ===" << std::endl;
146- // std::cout << "oMi (Ellipsoid):\n" << dataEllipsoid.oMi[1] << std::endl;
147- // std::cout << "oMi (SphericalZYX):\n" << dataSphericalZYX.oMi[1] << std::endl;
148- // BOOST_CHECK(dataEllipsoid.oMi[1].isApprox(dataSphericalZYX.oMi[1]));
149-
150- // BOOST_CHECK(dataEllipsoid.liMi[1].isApprox(dataSphericalZYX.liMi[1]));
151-
152- // // Check that velocities match
153- // BOOST_CHECK(dataEllipsoid.v[1].toVector().isApprox(dataSphericalZYX.v[1].toVector()));
154-
155- // // Test computeAllTerms
156- // computeAllTerms(modelEllipsoid, dataEllipsoid, q_xyz, v_xyz);
157- // computeAllTerms(modelSphericalZYX, dataSphericalZYX, q_zyx, v_zyx);
158-
159- // BOOST_CHECK(dataEllipsoid.Ycrb[1].matrix().isApprox(dataSphericalZYX.Ycrb[1].matrix()));
160-
161- // BOOST_CHECK(dataEllipsoid.f[1].toVector().isApprox(dataSphericalZYX.f[1].toVector()));
162-
163- // BOOST_CHECK(dataEllipsoid.nle.isApprox(dataSphericalZYX.nle));
164-
165- // BOOST_CHECK(dataEllipsoid.com[0].isApprox(dataSphericalZYX.com[0]));
166-
167- // // Test inverse dynamics (RNEA)
168- // Eigen::VectorXd aEllipsoid = Eigen::VectorXd::Ones(modelEllipsoid.nv);
169- // Eigen::VectorXd aSphericalZYX = Eigen::VectorXd::Ones(modelSphericalZYX.nv);
170-
171- // Eigen::VectorXd tauEllipsoid = rnea(modelEllipsoid, dataEllipsoid, q_xyz, v_xyz, aEllipsoid);
172- // Eigen::VectorXd tauSphericalZYX = rnea(modelSphericalZYX, dataSphericalZYX, q_zyx, v_zyx,
173- // aSphericalZYX);
174-
175- // BOOST_CHECK(tauEllipsoid.isApprox(tauSphericalZYX));
176-
177- // // Test forward dynamics (ABA)
178- // Eigen::VectorXd tau = Eigen::VectorXd::Ones(modelEllipsoid.nv);
179-
180- // Eigen::VectorXd aAbaEllipsoid = aba(modelEllipsoid, dataEllipsoid, q_xyz, v_xyz, tau,
181- // Convention::WORLD); Eigen::VectorXd aAbaSphericalZYX = aba(modelSphericalZYX, dataSphericalZYX,
182- // q_zyx, v_zyx, tau, Convention::WORLD);
183-
184- // BOOST_CHECK(aAbaEllipsoid.isApprox(aAbaSphericalZYX));
185-
186- // // Test with LOCAL convention
187- // aAbaEllipsoid = aba(modelEllipsoid, dataEllipsoid, q_xyz, v_xyz, tau, Convention::LOCAL);
188- // aAbaSphericalZYX = aba(modelSphericalZYX, dataSphericalZYX, q_zyx, v_zyx, tau,
189- // Convention::LOCAL);
190-
191- // BOOST_CHECK(aAbaEllipsoid.isApprox(aAbaSphericalZYX));
192-
193- // // Test with different configurations
194- // q_zyx << 0.2, -0.5, 1.1;
195- // v_zyx << 0.3, 0.1, -0.2;
196-
197- // converter.convertConfigurationVector(q_zyx, q_xyz);
198- // converter.convertTangentVector(q_zyx, v_zyx, v_xyz);
199-
200- // forwardKinematics(modelEllipsoid, dataEllipsoid, q_xyz, v_xyz);
201- // forwardKinematics(modelSphericalZYX, dataSphericalZYX, q_zyx, v_zyx);
202-
203- // BOOST_CHECK(dataEllipsoid.oMi[1].isApprox(dataSphericalZYX.oMi[1]));
204-
205- // BOOST_CHECK(dataEllipsoid.v[1].toVector().isApprox(dataSphericalZYX.v[1].toVector()));
206-
207- // tauEllipsoid = rnea(modelEllipsoid, dataEllipsoid, q_xyz, v_xyz, aEllipsoid);
208- // tauSphericalZYX = rnea(modelSphericalZYX, dataSphericalZYX, q_zyx, v_zyx, aSphericalZYX);
209-
210- // BOOST_CHECK(tauEllipsoid.isApprox(tauSphericalZYX));
211-
212- // aAbaEllipsoid = aba(modelEllipsoid, dataEllipsoid, q_xyz, v_xyz, tau, Convention::WORLD);
213- // aAbaSphericalZYX = aba(modelSphericalZYX, dataSphericalZYX, q_zyx, v_zyx, tau,
214- // Convention::WORLD);
215-
216- // BOOST_CHECK(aAbaEllipsoid.isApprox(aAbaSphericalZYX));
217-
218- // }
219-
22041BOOST_AUTO_TEST_CASE(vsSphericalZYX)
22142{
22243 using namespace pinocchio ;
@@ -319,7 +140,6 @@ BOOST_AUTO_TEST_CASE(vsSphericalZYX)
319140
320141 BOOST_CHECK (jDataEllipsoidFK.S .matrix ().isApprox (jDataEllipsoidFK2.S .matrix ()));
321142 BOOST_CHECK (jDataEllipsoidFK.S .matrix ().isApprox (jDataEllipsoidFK3.S .matrix ()));
322- std::cout << " ✓ Motion subspace matrices match for the three calc(...) methods" << std::endl;
323143
324144 JointDataSphericalZYX jDataSphereFK = jmodel_s.createData ();
325145 jmodel_s.calc (jDataSphereFK, q_s, qd_s);
@@ -330,10 +150,7 @@ BOOST_AUTO_TEST_CASE(vsSphericalZYX)
330150 Eigen::Matrix<double , 6 , 1 > joint_vel_s = jDataSphereFK.S .matrix () * qd_s;
331151
332152 BOOST_CHECK (dataEllipsoid.v [1 ].toVector ().isApprox (dataSphericalZYX.v [1 ].toVector ()));
333- std::cout << " ✓ Spatial velocities match" << std::endl;
334-
335153 BOOST_CHECK (dataEllipsoid.oMi [1 ].isApprox (dataSphericalZYX.oMi [1 ]));
336- std::cout << " ✓ Full oMi[1] matches" << std::endl;
337154
338155 Matrix3 Sdot_e = jDataEllipsoidFK.Sdot .matrix ().bottomRows <3 >(); // Angular part
339156
@@ -348,31 +165,126 @@ BOOST_AUTO_TEST_CASE(vsSphericalZYX)
348165 Eigen::Vector3d wdot_s = jDataSphereFK.c .angular () + S_s * qdotdot_s;
349166 Eigen::Vector3d wdot_e = Sdot_e * qd_e + S_e * qdotdot_e;
350167 BOOST_CHECK (wdot_s.isApprox (wdot_e));
351- std::cout << " ✓ Angular accelerations from joint accelerations match" << std::endl;
352168
353169 forwardKinematics (modelEllipsoid, dataEllipsoid, q_e, qd_e, qdotdot_e);
354170 forwardKinematics (modelSphericalZYX, dataSphericalZYX, q_s, qd_s, qdotdot_s);
355171
356172 BOOST_CHECK (dataEllipsoid.a [1 ].toVector ().isApprox (dataSphericalZYX.a [1 ].toVector ()));
357173
358- // Test RNEA (Recursive Newton-Euler Algorithm)
359- std::cout << " \n === RNEA Test ===" << std::endl;
360-
174+ // Test RNEA (Recursive Newton-Euler Algorithm) - spatial forces should match
361175 rnea (modelEllipsoid, dataEllipsoid, q_e, qd_e, qdotdot_e);
362176 rnea (modelSphericalZYX, dataSphericalZYX, q_s, qd_s, qdotdot_s);
363177
364178 BOOST_CHECK (dataEllipsoid.f [1 ].isApprox (dataSphericalZYX.f [1 ]));
365- std::cout << " ✓ RNEA f match" << std::endl;
366179
367180 // Test ABA (Articulated-Body Algorithm)
368- std::cout << " \n === ABA Test ===" << std::endl;
369181 Eigen::VectorXd tau = Eigen::VectorXd::Ones (modelEllipsoid.nv );
370-
371182 Eigen::VectorXd aAbaEllipsoid =
372183 aba (modelEllipsoid, dataEllipsoid, q_e, qd_e, dataEllipsoid.tau , Convention::WORLD);
373184
374185 BOOST_CHECK (dataEllipsoid.ddq .isApprox (qdotdot_e));
375186 std::cout << " ✓ ABA computed accelerations match input accelerations" << std::endl;
376187}
377188
189+ BOOST_AUTO_TEST_CASE (vsCompositeTxTyTzRxRyRz)
190+ {
191+ using namespace pinocchio ;
192+ typedef SE3::Vector3 Vector3;
193+ typedef SE3::Matrix3 Matrix3;
194+
195+ // Ellipsoid parameters
196+ double radius_a = 2.0 ;
197+ double radius_b = 1.5 ;
198+ double radius_c = 1.0 ;
199+
200+ Inertia inertia = Inertia::Identity ();
201+ SE3 pos = SE3::Identity ();
202+
203+ // Create Ellipsoid model
204+ Model modelEllipsoid;
205+ JointModelEllipsoid jointModelEllipsoid (radius_a, radius_b, radius_c);
206+ addJointAndBody (
207+ modelEllipsoid, jointModelEllipsoid, 0 , pos, " ellipsoid" ,
208+ inertia);
209+
210+ // Create Composite model (Tx, Ty, Tz, Rx, Ry, Rz)
211+ Model modelComposite;
212+ JointModelComposite jComposite;
213+ jComposite.addJoint (JointModelPX ());
214+ jComposite.addJoint (JointModelPY ());
215+ jComposite.addJoint (JointModelPZ ());
216+ jComposite.addJoint (JointModelRX ());
217+ jComposite.addJoint (JointModelRY ());
218+ jComposite.addJoint (JointModelRZ ());
219+ addJointAndBody (modelComposite, jComposite, 0 , pos, " composite" , inertia);
220+
221+ Data dataEllipsoid (modelEllipsoid);
222+ Data dataComposite (modelComposite);
223+
224+ // Test positions of ellispoid vs composite
225+ Eigen::VectorXd q_ellipsoid (3 );
226+ q_ellipsoid << 1.0 , 2.0 , 3.0 ; // rx, ry, rz
227+ Eigen::Vector3d t = jointModelEllipsoid.computeTranslations (q_ellipsoid);
228+ Eigen::VectorXd q_composite (6 );
229+ q_composite << t, q_ellipsoid;
230+
231+ forwardKinematics (modelEllipsoid, dataEllipsoid, q_ellipsoid);
232+ forwardKinematics (modelComposite, dataComposite, q_composite);
233+
234+ BOOST_CHECK (dataEllipsoid.oMi [1 ].isApprox (dataComposite.oMi [1 ]));
235+
236+ // Velocity test
237+ Eigen::VectorXd qdot_ellipsoid (3 );
238+ qdot_ellipsoid << 0.1 , 0.2 , 0.3 ;
239+
240+ Eigen::Vector3d v_linear = jointModelEllipsoid.computeTranslationVelocities (q_ellipsoid, qdot_ellipsoid);
241+ Eigen::VectorXd qdot_composite (6 );
242+ qdot_composite << v_linear, qdot_ellipsoid;
243+
244+ forwardKinematics (modelEllipsoid, dataEllipsoid, q_ellipsoid, qdot_ellipsoid);
245+ forwardKinematics (modelComposite, dataComposite, q_composite, qdot_composite);
246+
247+ BOOST_CHECK (dataEllipsoid.v [1 ].toVector ().isApprox (dataComposite.v [1 ].toVector ()));
248+
249+ // Acceleration test
250+ Eigen::VectorXd qddot_ellipsoid (3 );
251+ qddot_ellipsoid << 0.01 , 0.02 , 0.03 ;
252+ Eigen::Vector3d a_linear = jointModelEllipsoid.computeTranslationAccelerations (
253+ q_ellipsoid, qdot_ellipsoid, qddot_ellipsoid);
254+ Eigen::VectorXd qddot_composite (6 );
255+ qddot_composite << a_linear, qddot_ellipsoid;
256+
257+ forwardKinematics (modelEllipsoid, dataEllipsoid, q_ellipsoid, qdot_ellipsoid, qddot_ellipsoid);
258+ forwardKinematics (modelComposite, dataComposite, q_composite, qdot_composite, qddot_composite);
259+
260+ BOOST_CHECK (dataEllipsoid.a [1 ].toVector ().isApprox (dataComposite.a [1 ].toVector ()));
261+
262+ // Test RNEA - spatial forces and torques should match
263+ rnea (modelEllipsoid, dataEllipsoid, q_ellipsoid, qdot_ellipsoid, qddot_ellipsoid);
264+ rnea (modelComposite, dataComposite, q_composite, qdot_composite, qddot_composite);
265+ BOOST_CHECK (dataEllipsoid.f [1 ].isApprox (dataComposite.f [1 ]));
266+
267+ // Torque doesn't match yet.
268+ std::cout << " Ellipsoid torques: " << dataEllipsoid.tau .transpose () << std::endl;
269+ std::cout << " Composite torques: " << dataComposite.tau .transpose () << std::endl;
270+ BOOST_CHECK (dataEllipsoid.tau .isApprox (dataComposite.tau ));
271+ std::cout << " ✓ RNEA torques match" << std::endl;
272+
273+
274+ // Test ABA (Articulated-Body Algorithm)
275+ Eigen::VectorXd tau = Eigen::VectorXd::Ones (modelEllipsoid.nv );
276+ Eigen::VectorXd aAbaEllipsoid =
277+ aba (modelEllipsoid, dataEllipsoid, q_ellipsoid, qdot_ellipsoid, tau, Convention::WORLD);
278+ Eigen::VectorXd tau_composite = Eigen::VectorXd::Ones (modelComposite.nv );
279+ Eigen::VectorXd aAbaComposite =
280+ aba (modelComposite, dataComposite, q_composite, qdot_composite, tau_composite, Convention::WORLD);
281+
282+ std::cout << " Ellipsoid ABA ddq: " << dataEllipsoid.ddq .transpose () << std::endl;
283+ std::cout << " Composite ABA ddq: " << dataComposite.ddq .transpose () << std::endl;
284+ std::cout << " Composite ABA linear ddq: " << aAbaComposite.head <3 >().transpose () << std::endl;
285+ std::cout << " Composite ABA angular ddq: " << aAbaComposite.tail <3 >().transpose () << std::endl;
286+
287+ BOOST_CHECK (dataEllipsoid.ddq .isApprox (aAbaComposite.tail <3 >()));
288+ }
289+
378290BOOST_AUTO_TEST_SUITE_END ()
0 commit comments