5 #include "pinocchio/multibody/model.hpp" 6 #include "pinocchio/multibody/data.hpp" 7 #include "pinocchio/algorithm/jacobian.hpp" 8 #include "pinocchio/algorithm/joint-configuration.hpp" 9 #include "pinocchio/algorithm/kinematics.hpp" 10 #include "pinocchio/algorithm/kinematics-derivatives.hpp" 11 #include "pinocchio/algorithm/rnea.hpp" 12 #include "pinocchio/algorithm/rnea-derivatives.hpp" 13 #include "pinocchio/algorithm/crba.hpp" 14 #include "pinocchio/parsers/sample-models.hpp" 18 #include <boost/test/unit_test.hpp> 19 #include <boost/utility/binary.hpp> 21 BOOST_AUTO_TEST_SUITE(BOOST_TEST_MODULE)
25 using namespace Eigen;
40 MatrixXd g_partial_dq(model.
nv,model.
nv); g_partial_dq.setZero();
44 BOOST_CHECK(
data.g.isApprox(g0));
46 MatrixXd g_partial_dq_fd(model.
nv,model.
nv); g_partial_dq_fd.setZero();
48 VectorXd v_eps(Eigen::VectorXd::Zero(model.
nv));
51 const double alpha = 1e-8;
52 for(
int k = 0; k < model.
nv; ++k)
58 g_partial_dq_fd.col(k) = (g_plus - g0)/alpha;
62 BOOST_CHECK(g_partial_dq.isApprox(g_partial_dq_fd,sqrt(alpha)));
67 using namespace Eigen;
80 ForceVector fext((
size_t)model.
njoints);
81 for(ForceVector::iterator it = fext.begin(); it != fext.end(); ++it)
85 MatrixXd static_vec_partial_dq(model.
nv,model.
nv); static_vec_partial_dq.setZero();
89 BOOST_CHECK(
data.tau.isApprox(tau0));
91 std::cout <<
"data.tau: " <<
data.tau.transpose() << std::endl;
92 std::cout <<
"tau0: " << tau0.transpose() << std::endl;
94 MatrixXd static_vec_partial_dq_fd(model.
nv,model.
nv);
96 VectorXd v_eps(Eigen::VectorXd::Zero(model.
nv));
99 const double alpha = 1e-8;
100 for(
int k = 0; k < model.
nv; ++k)
106 static_vec_partial_dq_fd.col(k) = (tau_plus - tau0)/alpha;
110 BOOST_CHECK(static_vec_partial_dq.isApprox(static_vec_partial_dq_fd,sqrt(alpha)));
115 using namespace Eigen;
121 Data data(model), data_fd(model), data_ref(model);
130 MatrixXd rnea_partial_dq(model.
nv,model.
nv); rnea_partial_dq.setZero();
131 MatrixXd rnea_partial_dv(model.
nv,model.
nv); rnea_partial_dv.setZero();
132 MatrixXd rnea_partial_da(model.
nv,model.
nv); rnea_partial_da.setZero();
134 rnea(model,data_ref,q,VectorXd::Zero(model.
nv),VectorXd::Zero(model.
nv));
137 BOOST_CHECK(
data.of[k].isApprox(
data.oMi[k].act(data_ref.f[k])));
140 MatrixXd g_partial_dq(model.
nv,model.
nv); g_partial_dq.setZero();
143 BOOST_CHECK(
data.dFdq.isApprox(data_ref.
dFdq));
144 BOOST_CHECK(rnea_partial_dq.isApprox(g_partial_dq));
145 BOOST_CHECK(
data.tau.isApprox(data_ref.
g));
147 VectorXd tau0 =
rnea(model,data_fd,q,VectorXd::Zero(model.
nv),VectorXd::Zero(model.
nv));
148 MatrixXd rnea_partial_dq_fd(model.
nv,model.
nv); rnea_partial_dq_fd.setZero();
153 const double alpha = 1e-8;
154 for(
int k = 0; k < model.
nv; ++k)
158 tau_plus =
rnea(model,data_fd,q_plus,VectorXd::Zero(model.
nv),VectorXd::Zero(model.
nv));
160 rnea_partial_dq_fd.col(k) = (tau_plus - tau0)/alpha;
163 BOOST_CHECK(rnea_partial_dq.isApprox(rnea_partial_dq_fd,sqrt(alpha)));
166 tau0 =
rnea(model,data_fd,q,0*v,a);
167 rnea_partial_dq_fd.setZero();
169 for(
int k = 0; k < model.
nv; ++k)
173 tau_plus =
rnea(model,data_fd,q_plus,VectorXd::Zero(model.
nv),a);
175 rnea_partial_dq_fd.col(k) = (tau_plus - tau0)/alpha;
179 rnea_partial_dq.setZero();
185 BOOST_CHECK(
data.a[k].isApprox(data_ref.a[k]));
186 BOOST_CHECK(
data.v[k].isApprox(data_ref.v[k]));
187 BOOST_CHECK(
data.oMi[k].isApprox(data_ref.oMi[k]));
188 BOOST_CHECK(
data.oh[k].isApprox(Force::Zero()));
191 BOOST_CHECK(
data.tau.isApprox(tau0));
192 BOOST_CHECK(rnea_partial_dq.isApprox(rnea_partial_dq_fd,sqrt(alpha)));
197 tau0 =
rnea(model,data_fd,q,v,VectorXd::Zero(model.
nv));
198 rnea_partial_dq_fd.setZero();
200 for(
int k = 0; k < model.
nv; ++k)
204 tau_plus =
rnea(model,data_fd,q_plus,v,VectorXd::Zero(model.
nv));
206 rnea_partial_dq_fd.col(k) = (tau_plus - tau0)/alpha;
211 MatrixXd rnea_partial_dv_fd(model.
nv,model.
nv); rnea_partial_dv_fd.setZero();
213 for(
int k = 0; k < model.
nv; ++k)
216 tau_plus =
rnea(model,data_fd,q,v_plus,VectorXd::Zero(model.
nv));
218 rnea_partial_dv_fd.col(k) = (tau_plus - tau0)/alpha;
222 rnea_partial_dq.setZero();
223 rnea_partial_dv.setZero();
229 BOOST_CHECK(
data.a[k].isApprox(data_ref.a[k]));
230 BOOST_CHECK(
data.v[k].isApprox(data_ref.v[k]));
231 BOOST_CHECK(
data.oMi[k].isApprox(data_ref.oMi[k]));
234 BOOST_CHECK(
data.tau.isApprox(tau0));
235 BOOST_CHECK(rnea_partial_dq.isApprox(rnea_partial_dq_fd,sqrt(alpha)));
236 BOOST_CHECK(rnea_partial_dv.isApprox(rnea_partial_dv_fd,sqrt(alpha)));
245 tau0 =
rnea(model,data_fd,q,v,a);
246 rnea_partial_dq_fd.setZero();
248 for(
int k = 0; k < model.
nv; ++k)
252 tau_plus =
rnea(model,data_fd,q_plus,v,a);
254 rnea_partial_dq_fd.col(k) = (tau_plus - tau0)/alpha;
258 rnea_partial_dv_fd.setZero();
259 for(
int k = 0; k < model.
nv; ++k)
262 tau_plus =
rnea(model,data_fd,q,v_plus,a);
264 rnea_partial_dv_fd.col(k) = (tau_plus - tau0)/alpha;
268 rnea_partial_dq.setZero();
269 rnea_partial_dv.setZero();
275 BOOST_CHECK(
data.a[k].isApprox(data_ref.a[k]));
276 BOOST_CHECK(
data.v[k].isApprox(data_ref.v[k]));
277 BOOST_CHECK(
data.oMi[k].isApprox(data_ref.oMi[k]));
281 BOOST_CHECK(
data.dJ.isApprox(data_ref.
dJ));
282 crba(model,data_ref,q);
284 rnea_partial_da.triangularView<Eigen::StrictlyLower>()
285 = rnea_partial_da.transpose().triangularView<Eigen::StrictlyLower>();
286 data_ref.
M.triangularView<Eigen::StrictlyLower>()
287 = data_ref.
M.transpose().triangularView<Eigen::StrictlyLower>();
288 BOOST_CHECK(rnea_partial_da.isApprox(data_ref.
M));
290 BOOST_CHECK(
data.tau.isApprox(tau0));
291 BOOST_CHECK(rnea_partial_dq.isApprox(rnea_partial_dq_fd,sqrt(alpha)));
292 BOOST_CHECK(rnea_partial_dv.isApprox(rnea_partial_dv_fd,sqrt(alpha)));
296 data2.M.triangularView<Eigen::StrictlyLower>()
297 = data2.M.transpose().triangularView<Eigen::StrictlyLower>();
299 BOOST_CHECK(rnea_partial_dq.isApprox(data2.dtau_dq));
300 BOOST_CHECK(rnea_partial_dv.isApprox(data2.dtau_dv));
301 BOOST_CHECK(rnea_partial_da.isApprox(data2.M));
307 using namespace Eigen;
314 Data data(model), data_fd(model), data_ref(model);
323 ForceVector fext((
size_t)model.
njoints);
324 for(ForceVector::iterator it = fext.begin(); it != fext.end(); ++it)
328 MatrixXd rnea_partial_dq(model.
nv,model.
nv); rnea_partial_dq.setZero();
329 MatrixXd rnea_partial_dv(model.
nv,model.
nv); rnea_partial_dv.setZero();
330 MatrixXd rnea_partial_da(model.
nv,model.
nv); rnea_partial_da.setZero();
333 rnea(model,data_ref,q,v,a,fext);
335 BOOST_CHECK(
data.tau.isApprox(data_ref.
tau));
338 BOOST_CHECK(rnea_partial_dv.isApprox(data_ref.
dtau_dv));
339 BOOST_CHECK(rnea_partial_da.isApprox(data_ref.
M));
341 MatrixXd rnea_partial_dq_fd(model.
nv,model.
nv); rnea_partial_dq_fd.setZero();
342 MatrixXd rnea_partial_dv_fd(model.
nv,model.
nv); rnea_partial_dv_fd.setZero();
343 MatrixXd rnea_partial_da_fd(model.
nv,model.
nv); rnea_partial_da_fd.setZero();
348 const double eps = 1e-8;
350 const VectorXd tau_ref =
rnea(model,data_ref,q,v,a,fext);
351 for(
int k = 0; k < model.
nv; ++k)
355 tau_plus =
rnea(model,data_fd,q_plus,v,a,fext);
357 rnea_partial_dq_fd.col(k) = (tau_plus - tau_ref) / eps;
361 BOOST_CHECK(rnea_partial_dq.isApprox(rnea_partial_dq_fd,sqrt(eps)));
364 for(
int k = 0; k < model.
nv; ++k)
368 tau_plus =
rnea(model,data_fd,q,v_plus,a,fext);
370 rnea_partial_dv_fd.col(k) = (tau_plus - tau_ref) / eps;
374 BOOST_CHECK(rnea_partial_dv.isApprox(rnea_partial_dv_fd,sqrt(eps)));
377 for(
int k = 0; k < model.
nv; ++k)
381 tau_plus =
rnea(model,data_fd,q,v,a_plus,fext);
383 rnea_partial_da_fd.col(k) = (tau_plus - tau_ref) / eps;
388 rnea_partial_da.triangularView<Eigen::Lower>() = rnea_partial_da.transpose().triangularView<Eigen::Lower>();
389 BOOST_CHECK(rnea_partial_da.isApprox(rnea_partial_da_fd,sqrt(eps)));
392 Data data_shortcut(model);
394 BOOST_CHECK(data_shortcut.dtau_dq.isApprox(rnea_partial_dq));
395 BOOST_CHECK(data_shortcut.dtau_dv.isApprox(rnea_partial_dv));
396 data_shortcut.M.triangularView<Eigen::Lower>() = data_shortcut.M.transpose().triangularView<Eigen::Lower>();
397 BOOST_CHECK(data_shortcut.M.isApprox(rnea_partial_da));
402 using namespace Eigen;
417 MatrixXd rnea_partial_dq(model.
nv,model.
nv); rnea_partial_dq.setZero();
418 MatrixXd rnea_partial_dv(model.
nv,model.
nv); rnea_partial_dv.setZero();
419 MatrixXd rnea_partial_da(model.
nv,model.
nv); rnea_partial_da.setZero();
424 BOOST_CHECK(
data.J.isApprox(data_ref.
J));
425 BOOST_CHECK(
data.dJ.isApprox(data_ref.
dJ));
427 for(
size_t k = 1; k < (size_t)model.
njoints; ++k)
429 BOOST_CHECK(
data.oMi[k].isApprox(data_ref.oMi[k]));
430 BOOST_CHECK(
data.ov[k].isApprox(data_ref.ov[k]));
431 BOOST_CHECK(
data.oa[k].isApprox(data_ref.oa[k]));
437 using namespace Eigen;
443 Data data1(model), data2(model);
454 for(
int k = 0; k < 20; ++k)
459 BOOST_CHECK(data1.J.isApprox(data2.
J));
460 BOOST_CHECK(data1.dJ.isApprox(data2.
dJ));
461 BOOST_CHECK(data1.dVdq.isApprox(data2.
dVdq));
462 BOOST_CHECK(data1.dAdq.isApprox(data2.
dAdq));
463 BOOST_CHECK(data1.dAdv.isApprox(data2.
dAdv));
465 BOOST_CHECK(data1.dFdq.isApprox(data2.
dFdq));
466 BOOST_CHECK(data1.dFdv.isApprox(data2.
dFdv));
467 BOOST_CHECK(data1.dFda.isApprox(data2.
dFda));
469 BOOST_CHECK(data1.dtau_dq.isApprox(data2.
dtau_dq));
470 BOOST_CHECK(data1.dtau_dv.isApprox(data2.
dtau_dv));
471 BOOST_CHECK(data1.M.isApprox(data2.
M));
476 using namespace Eigen;
485 Data data_ref(model);
497 BOOST_CHECK(data.
J.isApprox(data_ref.
J));
498 BOOST_CHECK(data.
dJ.isApprox(data_ref.
dJ));
499 BOOST_CHECK(data.Fcrb[0].isApprox(data_ref.
dFdv));
502 BOOST_CHECK(data.vxI[k].isApprox(data_ref.vxI[k]));
503 BOOST_CHECK(data.oYcrb[k].isApprox(data_ref.oYcrb[k]));
506 BOOST_CHECK(data.
C.isApprox(data_ref.
C));
509 BOOST_AUTO_TEST_SUITE_END()
Matrix6x dJ
Derivative of the Jacobian with respect to the time.
const DataTpl< Scalar, Options, JointCollectionTpl >::MatrixXs & getCoriolisMatrix(const ModelTpl< Scalar, Options, JointCollectionTpl > &model, DataTpl< Scalar, Options, JointCollectionTpl > &data)
Retrives the Coriolis Matrix of the Lagrangian dynamics: after a call to the dynamics derivativ...
TangentVectorType tau
Vector of joint torques (dim model.nv).
JointModelVector joints
Model of joint i, encapsulated in a JointModelAccessor.
const DataTpl< Scalar, Options, JointCollectionTpl >::MatrixXs & crba(const ModelTpl< Scalar, Options, JointCollectionTpl > &model, DataTpl< Scalar, Options, JointCollectionTpl > &data, const Eigen::MatrixBase< ConfigVectorType > &q)
Computes the upper triangular part of the joint space inertia matrix M by using the Composite Rigid B...
VectorXs g
Vector of generalized gravity (dim model.nv).
ForceTpl< double, 0 > Force
const DataTpl< Scalar, Options, JointCollectionTpl >::TangentVectorType & computeStaticTorque(const ModelTpl< Scalar, Options, JointCollectionTpl > &model, DataTpl< Scalar, Options, JointCollectionTpl > &data, const Eigen::MatrixBase< ConfigVectorType > &q, const container::aligned_vector< ForceTpl< Scalar, Options > > &fext)
Computes the generalized static torque contribution of the Lagrangian dynamics: ...
Matrix6x J
Jacobian of joint placements.
MatrixXs dtau_dv
Partial derivative of the joint torque vector with respect to the joint velocity. ...
Matrix6x dAdv
Variation of the spatial acceleration set with respect to the joint velocity.
void rnea(const int num_threads, ModelPoolTpl< Scalar, Options, JointCollectionTpl > &pool, const Eigen::MatrixBase< ConfigVectorPool > &q, const Eigen::MatrixBase< TangentVectorPool1 > &v, const Eigen::MatrixBase< TangentVectorPool2 > &a, const Eigen::MatrixBase< TangentVectorPool3 > &tau)
The Recursive Newton-Euler algorithm. It computes the inverse dynamics, aka the joint torques accordi...
void integrate(const ModelTpl< Scalar, Options, JointCollectionTpl > &model, const Eigen::MatrixBase< ConfigVectorType > &q, const Eigen::MatrixBase< TangentVectorType > &v, const Eigen::MatrixBase< ReturnType > &qout)
Integrate a configuration vector for the specified model for a tangent vector during one unit time...
BOOST_AUTO_TEST_CASE(test_generalized_gravity_derivatives)
int njoints
Number of joints.
Matrix6x dFda
Variation of the forceset with respect to the joint acceleration.
ConfigVectorType lowerPositionLimit
Lower joint configuration limit.
Data::MatrixXs computeStaticTorqueDerivatives(const Model &model, Data &data, const Eigen::VectorXd &q, const ForceAlignedVector &fext)
void randomConfiguration(const ModelTpl< Scalar, Options, JointCollectionTpl > &model, const Eigen::MatrixBase< ConfigVectorIn1 > &lowerLimits, const Eigen::MatrixBase< ConfigVectorIn2 > &upperLimits, const Eigen::MatrixBase< ReturnType > &qout)
Generate a configuration vector uniformly sampled among provided limits.
MatrixXs dtau_dq
Partial derivative of the joint torque vector with respect to the joint configuration.
void forwardKinematics(const ModelTpl< Scalar, Options, JointCollectionTpl > &model, DataTpl< Scalar, Options, JointCollectionTpl > &data, const Eigen::MatrixBase< ConfigVectorType > &q)
Update the joint placements according to the current joint configuration.
Matrix6x dFdq
Variation of the forceset with respect to the joint configuration.
Data::MatrixXs computeGeneralizedGravityDerivatives(const Model &model, Data &data, const Eigen::VectorXd &q)
Matrix6x dAdq
Variation of the spatial acceleration set with respect to the joint configuration.
MatrixXs M
The joint space inertia matrix (a square matrix of dim model.nv).
bp::tuple computeRNEADerivatives(const Model &model, Data &data, const Eigen::VectorXd &q, const Eigen::VectorXd &v, const Eigen::VectorXd &a)
MatrixXs C
The Coriolis matrix (a square matrix of dim model.nv).
#define PINOCCHIO_ALIGNED_STD_VECTOR(Type)
pinocchio::JointIndex JointIndex
void computeForwardKinematicsDerivatives(const ModelTpl< Scalar, Options, JointCollectionTpl > &model, DataTpl< Scalar, Options, JointCollectionTpl > &data, const Eigen::MatrixBase< ConfigVectorType > &q, const Eigen::MatrixBase< TangentVectorType1 > &v, const Eigen::MatrixBase< TangentVectorType2 > &a)
Computes all the terms required to compute the derivatives of the placement, spatial velocity and acc...
const DataTpl< Scalar, Options, JointCollectionTpl >::Matrix6x & computeJointJacobiansTimeVariation(const ModelTpl< Scalar, Options, JointCollectionTpl > &model, DataTpl< Scalar, Options, JointCollectionTpl > &data, const Eigen::MatrixBase< ConfigVectorType > &q, const Eigen::MatrixBase< TangentVectorType > &v)
Computes the full model Jacobian variations with respect to time. It corresponds to dJ/dt which depen...
Motion gravity
Spatial gravity of the model.
const DataTpl< Scalar, Options, JointCollectionTpl >::TangentVectorType & computeGeneralizedGravity(const ModelTpl< Scalar, Options, JointCollectionTpl > &model, DataTpl< Scalar, Options, JointCollectionTpl > &data, const Eigen::MatrixBase< ConfigVectorType > &q)
Computes the generalized gravity contribution of the Lagrangian dynamics:
Matrix6x dFdv
Variation of the forceset with respect to the joint velocity.
Main pinocchio namespace.
int nv
Dimension of the velocity vector space.
const DataTpl< Scalar, Options, JointCollectionTpl >::MatrixXs & computeCoriolisMatrix(const ModelTpl< Scalar, Options, JointCollectionTpl > &model, DataTpl< Scalar, Options, JointCollectionTpl > &data, const Eigen::MatrixBase< ConfigVectorType > &q, const Eigen::MatrixBase< TangentVectorType > &v)
Computes the Coriolis Matrix of the Lagrangian dynamics:
ConfigVectorType upperPositionLimit
Upper joint configuration limit.
void humanoidRandom(ModelTpl< Scalar, Options, JointCollectionTpl > &model, bool usingFF=true)
Create a humanoid kinematic tree with 6-DOF limbs and random joint placements.
Eigen::Matrix< Scalar, Eigen::Dynamic, 1 > VectorXd
int nq
Dimension of the configuration vector representation.
Matrix6x dVdq
Variation of the spatial velocity set with respect to the joint configuration.
void fill(Eigen::Ref< MatType > mat, const typename MatType::Scalar &value)