unittest/rnea.cpp
Go to the documentation of this file.
1 //
2 // Copyright (c) 2015-2020 CNRS INRIA
3 //
4 
5 /*
6  * Unittest of the RNE algorithm. The code simply test that the algorithm does
7  * not cause any serious errors. The numerical values are not cross validated
8  * in any way.
9  *
10  */
11 
12 #include "pinocchio/spatial/fwd.hpp"
13 #include "pinocchio/multibody/model.hpp"
14 #include "pinocchio/multibody/data.hpp"
15 #include "pinocchio/algorithm/rnea.hpp"
16 #include "pinocchio/algorithm/jacobian.hpp"
17 #include "pinocchio/algorithm/center-of-mass.hpp"
18 #include "pinocchio/algorithm/joint-configuration.hpp"
19 #include "pinocchio/algorithm/crba.hpp"
20 #include "pinocchio/algorithm/centroidal.hpp"
21 #include "pinocchio/parsers/sample-models.hpp"
22 #include "pinocchio/utils/timer.hpp"
23 
24 #include <iostream>
25 
26 //#define __SSE3__
27 #include <fenv.h>
28 
29 #ifdef __SSE3__
30 #include <pmmintrin.h>
31 #endif
32 
33 #include <boost/test/unit_test.hpp>
34 #include <boost/utility/binary.hpp>
35 
36 BOOST_AUTO_TEST_SUITE ( BOOST_TEST_MODULE )
37 
38 BOOST_AUTO_TEST_CASE ( test_rnea )
39 {
40  #ifdef __SSE3__
41  _MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON);
42  #endif
43  using namespace Eigen;
44  using namespace pinocchio;
45 
47 
48  model.lowerPositionLimit.head<3>().fill(-1.);
49  model.upperPositionLimit.head<3>().fill( 1.);
50 
51  pinocchio::Data data(model);
52  data.v[0] = Motion::Zero();
53  data.a[0] = -model.gravity;
54 
56  VectorXd v = VectorXd::Random(model.nv);
57  VectorXd a = VectorXd::Random(model.nv);
58 
59  #ifdef NDEBUG
60  const size_t NBT = 10000;
61  #else
62  const size_t NBT = 1;
63  std::cout << "(the time score in debug mode is not relevant) " ;
64  #endif
65 
66  PinocchioTicToc timer(PinocchioTicToc::US); timer.tic();
67  SMOOTH(NBT)
68  {
69  rnea(model,data,q,v,a);
70  }
71  timer.toc(std::cout,NBT);
72 
73 }
74 
75 BOOST_AUTO_TEST_CASE ( test_nle_vs_rnea )
76 {
77  using namespace Eigen;
78  using namespace pinocchio;
79 
81 
82  model.lowerPositionLimit.head<3>().fill(-1.);
83  model.upperPositionLimit.head<3>().fill( 1.);
84 
85  pinocchio::Data data_nle(model);
86  pinocchio::Data data_rnea(model);
87 
89  VectorXd v = VectorXd::Random(model.nv);
90 
91  VectorXd tau_nle (VectorXd::Zero (model.nv));
92  VectorXd tau_rnea (VectorXd::Zero (model.nv));
93 
94  // -------
95  q.tail(model.nq-7).setZero();
96  v.setZero();
97 
98  tau_nle = nonLinearEffects(model,data_nle,q,v);
99  tau_rnea = rnea(model,data_rnea,q,v,VectorXd::Zero (model.nv));
100 
101  BOOST_CHECK(tau_nle.isApprox(tau_rnea, 1e-12));
102 
103  // -------
104  q.tail(model.nq-7).setZero();
105  v.setOnes();
106 
107  tau_nle = nonLinearEffects(model,data_nle,q,v);
108  tau_rnea = rnea(model,data_rnea,q,v,VectorXd::Zero (model.nv));
109 
110  BOOST_CHECK(tau_nle.isApprox(tau_rnea, 1e-12));
111 
112  // -------
113  q.tail(model.nq-7).setOnes();
114  v.setOnes();
115 
116  tau_nle = nonLinearEffects(model,data_nle,q,v);
117  tau_rnea = rnea(model,data_rnea,q,v,VectorXd::Zero (model.nv));
118 
119  BOOST_CHECK(tau_nle.isApprox(tau_rnea, 1e-12));
120 
121  // -------
122  q = randomConfiguration(model);
123  v.setRandom();
124 
125  tau_nle = nonLinearEffects(model,data_nle,q,v);
126  tau_rnea = rnea(model,data_rnea,q,v,VectorXd::Zero (model.nv));
127 
128  BOOST_CHECK(tau_nle.isApprox(tau_rnea, 1e-12));
129 }
130 
131 BOOST_AUTO_TEST_CASE (test_rnea_with_fext)
132 {
133  using namespace Eigen;
134  using namespace pinocchio;
135 
136  Model model;
138 
139  model.lowerPositionLimit.head<3>().fill(-1.);
140  model.upperPositionLimit.head<3>().fill( 1.);
141 
142  Data data_rnea_fext(model);
143  Data data_rnea(model);
144 
145  VectorXd q = randomConfiguration(model);
146 
147  VectorXd v (VectorXd::Random(model.nv));
148  VectorXd a (VectorXd::Random(model.nv));
149 
150  PINOCCHIO_ALIGNED_STD_VECTOR(Force) fext(model.joints.size(), Force::Zero());
151 
152  JointIndex rf = model.getJointId("rleg6_joint"); Force Frf = Force::Random();
153  fext[rf] = Frf;
154  JointIndex lf = model.getJointId("lleg6_joint"); Force Flf = Force::Random();
155  fext[lf] = Flf;
156 
157  rnea(model,data_rnea,q,v,a);
158  VectorXd tau_ref(data_rnea.tau);
159  Data::Matrix6x Jrf(Data::Matrix6x::Zero(6,model.nv));
160  computeJointJacobian(model,data_rnea,q,rf,Jrf);
161  tau_ref -= Jrf.transpose() * Frf.toVector();
162 
163  Data::Matrix6x Jlf(Data::Matrix6x::Zero(6,model.nv));
164  computeJointJacobian(model,data_rnea,q,lf,Jlf);
165  tau_ref -= Jlf.transpose() * Flf.toVector();
166 
167  rnea(model,data_rnea_fext,q,v,a,fext);
168 
169  BOOST_CHECK(tau_ref.isApprox(data_rnea_fext.tau));
170 }
171 
172 BOOST_AUTO_TEST_CASE(test_compute_gravity)
173 {
174  using namespace Eigen;
175  using namespace pinocchio;
176 
177  Model model;
179 
180  model.lowerPositionLimit.head<3>().fill(-1.);
181  model.upperPositionLimit.head<3>().fill( 1.);
182 
183  Data data_rnea(model);
184  Data data(model);
185 
186  VectorXd q = randomConfiguration(model);
187 
188  rnea(model,data_rnea,q,VectorXd::Zero(model.nv),VectorXd::Zero(model.nv));
189  computeGeneralizedGravity(model,data,q);
190 
191  BOOST_CHECK(data_rnea.tau.isApprox(data.g));
192 
193  // Compare with Jcom
194  crba(model,data_rnea,q);
195  Data::Matrix3x Jcom = getJacobianComFromCrba(model,data_rnea);
196 
197  VectorXd g_ref(-data_rnea.mass[0]*Jcom.transpose()*Model::gravity981);
198 
199  BOOST_CHECK(g_ref.isApprox(data.g));
200 }
201 
202 BOOST_AUTO_TEST_CASE(test_compute_static_torque)
203 {
204  using namespace Eigen;
205  using namespace pinocchio;
206 
207  Model model;
209 
210  model.lowerPositionLimit.head<3>().fill(-1.);
211  model.upperPositionLimit.head<3>().fill( 1.);
212 
213  Data data_rnea(model);
214  Data data(model);
215 
216  VectorXd q = randomConfiguration(model);
217 
218  typedef PINOCCHIO_ALIGNED_STD_VECTOR(Force) ForceVector;
219  ForceVector fext((size_t)model.njoints);
220  for(ForceVector::iterator it = fext.begin(); it != fext.end(); ++it)
221  (*it).setRandom();
222 
223  rnea(model,data_rnea,q,VectorXd::Zero(model.nv),VectorXd::Zero(model.nv),fext);
224  computeStaticTorque(model,data,q,fext);
225 
226  BOOST_CHECK(data_rnea.tau.isApprox(data.tau));
227 
228  // Compare with Jcom + Jacobian of joint
229  crba(model,data_rnea,q);
230  Data::Matrix3x Jcom = getJacobianComFromCrba(model,data_rnea);
231 
232  VectorXd static_torque_ref = -data_rnea.mass[0]*Jcom.transpose()*Model::gravity981;
233  computeJointJacobians(model,data_rnea,q);
234 
235  Data::Matrix6x J_local(6,model.nv);
236  for(JointIndex joint_id = 1; joint_id < (JointIndex)(model.njoints); ++joint_id)
237  {
238  J_local.setZero();
239  getJointJacobian(model, data_rnea, joint_id, LOCAL, J_local);
240  static_torque_ref -= J_local.transpose() * fext[joint_id].toVector();
241  }
242 
243  BOOST_CHECK(static_torque_ref.isApprox(data.tau));
244 }
245 
246 BOOST_AUTO_TEST_CASE(test_compute_coriolis)
247 {
248  using namespace Eigen;
249  using namespace pinocchio;
250 
251  const double prec = Eigen::NumTraits<double>::dummy_precision();
252 
253  Model model;
255 
256  model.lowerPositionLimit.head<3>().fill(-1.);
257  model.upperPositionLimit.head<3>().fill( 1.);
258 
259  Data data_ref(model);
260  Data data(model);
261 
262  VectorXd q = randomConfiguration(model);
263 
264  VectorXd v (VectorXd::Random(model.nv));
265  computeCoriolisMatrix(model,data,q,Eigen::VectorXd::Zero(model.nv));
266  BOOST_CHECK(data.C.isZero(prec));
267 
268 
269  model.gravity.setZero();
270  rnea(model,data_ref,q,v,VectorXd::Zero(model.nv));
271  computeJointJacobiansTimeVariation(model,data_ref,q,v);
272  computeCoriolisMatrix(model,data,q,v);
273 
274  BOOST_CHECK(data.dJ.isApprox(data_ref.dJ));
275  BOOST_CHECK(data.J.isApprox(data_ref.J));
276 
277  VectorXd tau = data.C * v;
278  BOOST_CHECK(tau.isApprox(data_ref.tau,prec));
279 
280  dccrba(model,data_ref,q,v);
281  crba(model,data_ref,q);
282 
283  const Data::Vector3 & com = data_ref.com[0];
284  Motion vcom(data_ref.vcom[0],Data::Vector3::Zero());
285  SE3 cM1(data.oMi[1]); cM1.translation() -= com;
286 
287  BOOST_CHECK((cM1.toDualActionMatrix()*data_ref.M.topRows<6>()).isApprox(data_ref.Ag,prec));
288 
289  Force dh_ref = cM1.act(Force(data_ref.tau.head<6>()));
290  Force dh(data_ref.dAg * v);
291  BOOST_CHECK(dh.isApprox(dh_ref,prec));
292 
293  {
294  Data data_ref(model), data_ref_plus(model);
295  Eigen::MatrixXd dM(data.C + data.C.transpose());
296 
297  const double alpha = 1e-8;
298  Eigen::VectorXd q_plus(model.nq);
299  q_plus = integrate(model,q,alpha*v);
300 
301  crba(model,data_ref,q);
302  data_ref.M.triangularView<Eigen::StrictlyLower>() = data_ref.M.transpose().triangularView<Eigen::StrictlyLower>();
303  crba(model,data_ref_plus,q_plus);
304  data_ref_plus.M.triangularView<Eigen::StrictlyLower>() = data_ref_plus.M.transpose().triangularView<Eigen::StrictlyLower>();
305 
306  Eigen::MatrixXd dM_ref = (data_ref_plus.M - data_ref.M)/alpha;
307  BOOST_CHECK(dM.isApprox(dM_ref,sqrt(alpha)));
308  }
309 
310 }
311 
312 BOOST_AUTO_TEST_SUITE_END()
Matrix6x dJ
Derivative of the Jacobian with respect to the time.
BOOST_AUTO_TEST_CASE(test_rnea)
const DataTpl< Scalar, Options, JointCollectionTpl >::Matrix3x & getJacobianComFromCrba(const ModelTpl< Scalar, Options, JointCollectionTpl > &model, DataTpl< Scalar, Options, JointCollectionTpl > &data)
Extracts both the jacobian of the center of mass (CoM), the total mass of the system and the CoM posi...
TangentVectorType tau
Vector of joint torques (dim model.nv).
double toc()
Definition: timer.hpp:68
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).
q
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.
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...
bool isApprox(const ForceDense< M2 > &f, const Scalar &prec=Eigen::NumTraits< Scalar >::dummy_precision()) const
int njoints
Number of joints.
ConfigVectorType lowerPositionLimit
Lower joint configuration limit.
ToVectorConstReturnType toVector() const
Return the force as an Eigen vector.
Definition: force-base.hpp:81
dM
Definition: dcrba.py:383
v
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.
void getJointJacobian(const ModelTpl< Scalar, Options, JointCollectionTpl > &model, const DataTpl< Scalar, Options, JointCollectionTpl > &data, const typename ModelTpl< Scalar, Options, JointCollectionTpl >::JointIndex jointId, const ReferenceFrame rf, const Eigen::MatrixBase< Matrix6Like > &J)
Computes the Jacobian of a specific joint frame expressed either in the world (rf = WORLD) frame or i...
data
void tic()
Definition: timer.hpp:63
const DataTpl< Scalar, Options, JointCollectionTpl >::Matrix6x & dccrba(const ModelTpl< Scalar, Options, JointCollectionTpl > &model, DataTpl< Scalar, Options, JointCollectionTpl > &data, const Eigen::MatrixBase< ConfigVectorType > &q, const Eigen::MatrixBase< TangentVectorType > &v)
Computes the time derivative of the Centroidal Momentum Matrix according to the current configuration...
ActionMatrixType toDualActionMatrix() const
Definition: se3-base.hpp:75
The LOCAL frame convention corresponds to the frame directly attached to the moving part (Joint...
MatrixXs M
The joint space inertia matrix (a square matrix of dim model.nv).
MatrixXs C
The Coriolis matrix (a square matrix of dim model.nv).
#define PINOCCHIO_ALIGNED_STD_VECTOR(Type)
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...
Matrix6x dAg
Centroidal Momentum Matrix Time Variation.
#define SMOOTH(s)
Definition: timer.hpp:38
Motion gravity
Spatial gravity of the model.
ConstLinearRef translation() const
Definition: se3-base.hpp:38
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:
SE3GroupAction< D >::ReturnType act(const D &d) const
ay = aXb.act(by)
Definition: se3-base.hpp:90
Main pinocchio namespace.
Definition: timings.cpp:30
const DataTpl< Scalar, Options, JointCollectionTpl >::Matrix6x & computeJointJacobians(const ModelTpl< Scalar, Options, JointCollectionTpl > &model, DataTpl< Scalar, Options, JointCollectionTpl > &data, const Eigen::MatrixBase< ConfigVectorType > &q)
Computes the full model Jacobian, i.e. the stack of all motion subspace expressed in the world frame...
Matrix6x Ag
Centroidal Momentum Matrix.
int nv
Dimension of the velocity vector space.
Eigen::Matrix< Scalar, 3, Eigen::Dynamic, Options > Matrix3x
The 3d jacobian type (temporary)
JointIndex getJointId(const std::string &name) const
Return the index of a joint given by its name.
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:
list a
ConfigVectorType upperPositionLimit
Upper joint configuration limit.
void computeJointJacobian(const ModelTpl< Scalar, Options, JointCollectionTpl > &model, DataTpl< Scalar, Options, JointCollectionTpl > &data, const Eigen::MatrixBase< ConfigVectorType > &q, const JointIndex jointId, const Eigen::MatrixBase< Matrix6Like > &J)
Computes the Jacobian of a specific joint frame expressed in the local frame of the joint and store t...
const DataTpl< Scalar, Options, JointCollectionTpl >::TangentVectorType & nonLinearEffects(const ModelTpl< Scalar, Options, JointCollectionTpl > &model, DataTpl< Scalar, Options, JointCollectionTpl > &data, const Eigen::MatrixBase< ConfigVectorType > &q, const Eigen::MatrixBase< TangentVectorType > &v)
Computes the non-linear effects (Corriolis, centrifual and gravitationnal effects), also called the bias terms of the Lagrangian dynamics:
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
Definition: conversions.cpp:14
Eigen::Matrix< Scalar, 6, Eigen::Dynamic, Options > Matrix6x
The 6d jacobian type (temporary)
int nq
Dimension of the configuration vector representation.
Eigen::Matrix< Scalar, 3, 1, Options > Vector3
std::vector< Scalar > mass
Vector of subtree mass. In other words, mass[j] is the mass of the subtree supported by joint ...
void fill(Eigen::Ref< MatType > mat, const typename MatType::Scalar &value)


pinocchio
Author(s):
autogenerated on Tue Jun 1 2021 02:45:04