pinocchio  UNKNOWN
rnea-derivatives.hxx
1 //
2 // Copyright (c) 2017-2018 CNRS
3 //
4 // This file is part of Pinocchio
5 // Pinocchio is free software: you can redistribute it
6 // and/or modify it under the terms of the GNU Lesser General Public
7 // License as published by the Free Software Foundation, either version
8 // 3 of the License, or (at your option) any later version.
9 //
10 // Pinocchio is distributed in the hope that it will be
11 // useful, but WITHOUT ANY WARRANTY; without even the implied warranty
12 // of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // General Lesser Public License for more details. You should have
14 // received a copy of the GNU Lesser General Public License along with
15 // Pinocchio If not, see
16 // <http://www.gnu.org/licenses/>.
17 
18 #ifndef __se3_rnea_derivatives_hxx__
19 #define __se3_rnea_derivatives_hxx__
20 
21 #include "pinocchio/multibody/visitor.hpp"
22 #include "pinocchio/algorithm/check.hpp"
23 
24 namespace se3
25 {
26 
27  struct computeGeneralizedGravityDerivativeForwardStep : public fusion::JointVisitor<computeGeneralizedGravityDerivativeForwardStep>
28  {
29  typedef boost::fusion::vector< const se3::Model &,
30  se3::Data &,
31  const Eigen::VectorXd &
32  > ArgsType;
33 
35 
36  template<typename JointModel>
37  static void algo(const se3::JointModelBase<JointModel> & jmodel,
39  const se3::Model & model,
40  se3::Data & data,
41  const Eigen::VectorXd & q)
42  {
43  const Model::JointIndex & i = jmodel.id();
44  const Model::JointIndex & parent = model.parents[i];
45  Motion & oa = data.a_gf[0];
46 
47  jmodel.calc(jdata.derived(),q);
48 
49  data.liMi[i] = model.jointPlacements[i]*jdata.M();
50 
51  if(parent > 0)
52  data.oMi[i] = data.oMi[parent] * data.liMi[i];
53  else
54  data.oMi[i] = data.liMi[i];
55 
56  data.oYcrb[i] = data.oMi[i].act(model.inertias[i]);
57  data.of[i].setZero();
58 
59  typedef typename SizeDepType<JointModel::NV>::template ColsReturn<Data::Matrix6x>::Type ColsBlock;
60  ColsBlock J_cols = jmodel.jointCols(data.J);
61  ColsBlock dAdq_cols = jmodel.jointCols(data.dAdq);
62  J_cols = data.oMi[i].act(jdata.S());
63  motionSet::motionAction(oa,J_cols,dAdq_cols);
64 
65  }
66 
67  };
68 
69  struct computeGeneralizedGravityDerivativeBackwardStep : public fusion::JointModelVisitor<computeGeneralizedGravityDerivativeBackwardStep>
70  {
71  typedef boost::fusion::vector<const Model &,
72  Data &,
73  Eigen::MatrixXd &
74  > ArgsType;
75 
76  JOINT_MODEL_VISITOR_INIT(computeGeneralizedGravityDerivativeBackwardStep);
77 
78  template<typename JointModel>
79  static void algo(const JointModelBase<JointModel> & jmodel,
80  const Model & model,
81  Data & data,
82  Eigen::MatrixXd & gravity_partial_dq)
83  {
84  const Model::JointIndex & i = jmodel.id();
85  const Model::JointIndex & parent = model.parents[i];
86  Data::RowMatrix6 & M6tmpR = data.M6tmpR;
87  Motion & oa = data.a_gf[0];
88 
89  typedef typename SizeDepType<JointModel::NV>::template ColsReturn<Data::Matrix6x>::Type ColsBlock;
90 
91  ColsBlock J_cols = jmodel.jointCols(data.J);
92  ColsBlock dAdq_cols = jmodel.jointCols(data.dAdq);
93  ColsBlock dFdq_cols = jmodel.jointCols(data.dFdq);
94 
95  motionSet::inertiaAction(data.oYcrb[i],dAdq_cols,dFdq_cols);
96 
97  gravity_partial_dq.block(jmodel.idx_v(),jmodel.idx_v(),jmodel.nv(),data.nvSubtree[i]).noalias()
98  = J_cols.transpose()*data.dFdq.middleCols(jmodel.idx_v(),data.nvSubtree[i]);
99 
100  data.of[i] = data.oYcrb[i] * oa;
101  motionSet::act<ADDTO>(J_cols,data.of[i],dFdq_cols);
102 
103  lhsInertiaMult(data.oYcrb[i],J_cols.transpose(),M6tmpR.topRows(jmodel.nv()));
104  for(int j = data.parents_fromRow[(Model::Index)jmodel.idx_v()];j >= 0; j = data.parents_fromRow[(Model::Index)j])
105  gravity_partial_dq.middleRows(jmodel.idx_v(),jmodel.nv()).col(j).noalias() = M6tmpR.topRows(jmodel.nv()) * data.dAdq.col(j);
106 
107  jmodel.jointVelocitySelector(data.g).noalias() = J_cols.transpose()*data.of[i].toVector();
108  if(parent>0)
109  {
110  data.oYcrb[parent] += data.oYcrb[i];
111  }
112  }
113 
114  template<typename Min, typename Mout>
115  static void lhsInertiaMult(const Inertia & Y,
116  const Eigen::MatrixBase<Min> & J,
117  const Eigen::MatrixBase<Mout> & F)
118  {
119  Mout & F_ = const_cast<Mout &>(F.derived());
120  motionSet::inertiaAction(Y,J.derived().transpose(),F_.transpose());
121  }
122  };
123 
124  inline void
126  const Eigen::VectorXd & q,
127  Eigen::MatrixXd & gravity_partial_dq)
128  {
129  assert(q.size() == model.nq && "The configuration vector is not of right size");
130  assert(gravity_partial_dq.cols() == model.nv);
131  assert(gravity_partial_dq.rows() == model.nv);
132  assert(model.check(data) && "data is not consistent with model.");
133 
134  data.a_gf[0] = -model.gravity;
135 
136  for(Model::JointIndex i=1; i<(Model::JointIndex) model.njoints; ++i)
137  {
138  computeGeneralizedGravityDerivativeForwardStep::run(model.joints[i],data.joints[i],
139  computeGeneralizedGravityDerivativeForwardStep::ArgsType(model,data,q));
140  }
141 
142  for(size_t i=(size_t) (model.njoints-1);i>0;--i)
143  {
144  computeGeneralizedGravityDerivativeBackwardStep::run(model.joints[i],
145  computeGeneralizedGravityDerivativeBackwardStep::ArgsType(model,data,gravity_partial_dq));
146  }
147  }
148 
149  struct computeRNEADerivativesForwardStep : public fusion::JointVisitor<computeRNEADerivativesForwardStep>
150  {
151  typedef boost::fusion::vector< const se3::Model &,
152  se3::Data &,
153  const Eigen::VectorXd &,
154  const Eigen::VectorXd &,
155  const Eigen::VectorXd &
156  > ArgsType;
157 
158  JOINT_VISITOR_INIT(computeRNEADerivativesForwardStep);
159 
160  template<typename JointModel>
161  static void algo(const se3::JointModelBase<JointModel> & jmodel,
163  const se3::Model & model,
164  se3::Data & data,
165  const Eigen::VectorXd & q,
166  const Eigen::VectorXd & v,
167  const Eigen::VectorXd & a)
168  {
169  const Model::JointIndex & i = jmodel.id();
170  const Model::JointIndex & parent = model.parents[i];
171  Motion & ov = data.ov[i];
172  Motion & oa = data.oa[i];
173 
174  jmodel.calc(jdata.derived(),q,v);
175 
176  data.liMi[i] = model.jointPlacements[i]*jdata.M();
177 
178  data.v[i] = jdata.v();
179 
180  if(parent > 0)
181  {
182  data.oMi[i] = data.oMi[parent] * data.liMi[i];
183  data.v[i] += data.liMi[i].actInv(data.v[parent]);
184  }
185  else
186  data.oMi[i] = data.liMi[i];
187 
188  data.a[i] = jdata.S() * jmodel.jointVelocitySelector(a) + jdata.c() + (data.v[i] ^ jdata.v());
189  if(parent > 0)
190  {
191  data.a[i] += data.liMi[i].actInv(data.a[parent]);
192  }
193 
194  data.oYcrb[i] = data.oMi[i].act(model.inertias[i]);
195  ov = data.oMi[i].act(data.v[i]);
196  oa = data.oMi[i].act(data.a[i]) + data.oa[0]; // add gravity contribution
197 
198  data.oh[i] = data.oYcrb[i] * ov;
199  data.of[i] = data.oYcrb[i] * oa + ov.cross(data.oh[i]);
200 
201  typedef typename SizeDepType<JointModel::NV>::template ColsReturn<Data::Matrix6x>::Type ColsBlock;
202  ColsBlock J_cols = jmodel.jointCols(data.J);
203  ColsBlock dJ_cols = jmodel.jointCols(data.dJ);
204  ColsBlock dVdq_cols = jmodel.jointCols(data.dVdq);
205  ColsBlock dAdq_cols = jmodel.jointCols(data.dAdq);
206  ColsBlock dAdv_cols = jmodel.jointCols(data.dAdv);
207 
208  J_cols = data.oMi[i].act(jdata.S());
209  motionSet::motionAction(ov,J_cols,dJ_cols);
210  motionSet::motionAction(data.oa[parent],J_cols,dAdq_cols);
211  dAdv_cols = dJ_cols;
212  if(parent > 0)
213  {
214  motionSet::motionAction(data.ov[parent],J_cols,dVdq_cols);
215  motionSet::motionAction<ADDTO>(data.ov[parent],dVdq_cols,dAdq_cols);
216  dAdv_cols += dVdq_cols;
217  }
218  else
219  dVdq_cols.setZero();
220 
221  // computes variation of inertias
222  data.doYcrb[i] = data.oYcrb[i].variation(ov);
223 
224  addForceCrossMatrix(data.oh[i],data.doYcrb[i]);
225  }
226 
227  template<typename ForceDerived, typename M6>
228  static void addForceCrossMatrix(const ForceDense<ForceDerived> & f, const Eigen::MatrixBase<M6> & mout)
229  {
230  M6 & mout_ = const_cast<Eigen::MatrixBase<M6> &>(mout).derived();
231  typedef Eigen::Matrix<typename M6::Scalar,3,3,EIGEN_PLAIN_TYPE(M6)::Options> M3;
232  const M3 fx(skew(f.linear()));
233  mout_.template block<3,3>(Force::LINEAR,Force::ANGULAR) -= fx;
234  mout_.template block<3,3>(Force::ANGULAR,Force::LINEAR) -= fx;
235  mout_.template block<3,3>(Force::ANGULAR,Force::ANGULAR) -= skew(f.angular());
236  }
237 
238  };
239 
240  struct computeRNEADerivativesBackwardStep : public fusion::JointModelVisitor<computeRNEADerivativesBackwardStep>
241  {
242  typedef boost::fusion::vector<const Model &,
243  Data &,
244  Eigen::MatrixXd &,
245  Eigen::MatrixXd &,
246  Eigen::MatrixXd &
247  > ArgsType;
248 
249  JOINT_MODEL_VISITOR_INIT(computeRNEADerivativesBackwardStep);
250 
251  template<typename JointModel>
252  static void algo(const JointModelBase<JointModel> & jmodel,
253  const Model & model,
254  Data & data,
255  Eigen::MatrixXd & rnea_partial_dq,
256  Eigen::MatrixXd & rnea_partial_dv,
257  Eigen::MatrixXd & rnea_partial_da)
258  {
259  const Model::JointIndex & i = jmodel.id();
260  const Model::JointIndex & parent = model.parents[i];
261  Data::RowMatrix6 & M6tmpR = data.M6tmpR;
262 
263  typedef typename SizeDepType<JointModel::NV>::template ColsReturn<Data::Matrix6x>::Type ColsBlock;
264 
265  ColsBlock J_cols = jmodel.jointCols(data.J);
266  ColsBlock dVdq_cols = jmodel.jointCols(data.dVdq);
267  ColsBlock dAdq_cols = jmodel.jointCols(data.dAdq);
268  ColsBlock dAdv_cols = jmodel.jointCols(data.dAdv);
269  ColsBlock dFdq_cols = jmodel.jointCols(data.dFdq);
270  ColsBlock dFdv_cols = jmodel.jointCols(data.dFdv);
271  ColsBlock dFda_cols = jmodel.jointCols(data.dFda);
272 
273  // tau
274  jmodel.jointVelocitySelector(data.tau).noalias() = J_cols.transpose()*data.of[i].toVector();
275 
276  // dtau/da similar to data.M
277  motionSet::inertiaAction(data.oYcrb[i],J_cols,dFda_cols);
278  rnea_partial_da.block(jmodel.idx_v(),jmodel.idx_v(),jmodel.nv(),data.nvSubtree[i]).noalias()
279  = J_cols.transpose()*data.dFda.middleCols(jmodel.idx_v(),data.nvSubtree[i]);
280 
281  // dtau/dv
282  motionSet::inertiaAction(data.oYcrb[i],dAdv_cols,dFdv_cols);
283  dFdv_cols += data.doYcrb[i] * J_cols;
284 
285  rnea_partial_dv.block(jmodel.idx_v(),jmodel.idx_v(),jmodel.nv(),data.nvSubtree[i]).noalias()
286  = J_cols.transpose()*data.dFdv.middleCols(jmodel.idx_v(),data.nvSubtree[i]);
287 
288  // dtau/dq
289  motionSet::inertiaAction(data.oYcrb[i],dAdq_cols,dFdq_cols);
290  if(parent>0)
291  dFdq_cols += data.doYcrb[i] * dVdq_cols;
292 
293  rnea_partial_dq.block(jmodel.idx_v(),jmodel.idx_v(),jmodel.nv(),data.nvSubtree[i]).noalias()
294  = J_cols.transpose()*data.dFdq.middleCols(jmodel.idx_v(),data.nvSubtree[i]);
295 
296  motionSet::act<ADDTO>(J_cols,data.of[i],dFdq_cols);
297 
298  if(parent > 0)
299  {
300  lhsInertiaMult(data.oYcrb[i],J_cols.transpose(),M6tmpR.topRows(jmodel.nv()));
301  for(int j = data.parents_fromRow[(Model::Index)jmodel.idx_v()];j >= 0; j = data.parents_fromRow[(Model::Index)j])
302  rnea_partial_dq.middleRows(jmodel.idx_v(),jmodel.nv()).col(j).noalias() = M6tmpR.topRows(jmodel.nv()) * data.dAdq.col(j);
303  for(int j = data.parents_fromRow[(Model::Index)jmodel.idx_v()];j >= 0; j = data.parents_fromRow[(Model::Index)j])
304  rnea_partial_dv.middleRows(jmodel.idx_v(),jmodel.nv()).col(j).noalias() = M6tmpR.topRows(jmodel.nv()) * data.dAdv.col(j);
305 
306  M6tmpR.topRows(jmodel.nv()).noalias() = J_cols.transpose() * data.doYcrb[i];
307  for(int j = data.parents_fromRow[(Model::Index)jmodel.idx_v()];j >= 0; j = data.parents_fromRow[(Model::Index)j])
308  rnea_partial_dq.middleRows(jmodel.idx_v(),jmodel.nv()).col(j) += M6tmpR.topRows(jmodel.nv()) * data.dVdq.col(j);
309  for(int j = data.parents_fromRow[(Model::Index)jmodel.idx_v()];j >= 0; j = data.parents_fromRow[(Model::Index)j])
310  rnea_partial_dv.middleRows(jmodel.idx_v(),jmodel.nv()).col(j) += M6tmpR.topRows(jmodel.nv()) * data.J.col(j);
311  }
312 
313  if(parent>0)
314  {
315  data.oYcrb[parent] += data.oYcrb[i];
316  data.doYcrb[parent] += data.doYcrb[i];
317  data.of[parent] += data.of[i];
318  }
319  }
320 
321  template<typename Min, typename Mout>
322  static void lhsInertiaMult(const Inertia & Y,
323  const Eigen::MatrixBase<Min> & J,
324  const Eigen::MatrixBase<Mout> & F)
325  {
326  Mout & F_ = const_cast<Mout &>(F.derived());
327  motionSet::inertiaAction(Y,J.derived().transpose(),F_.transpose());
328  }
329  };
330 
331  inline void
332  computeRNEADerivatives(const Model & model, Data & data,
333  const Eigen::VectorXd & q,
334  const Eigen::VectorXd & v,
335  const Eigen::VectorXd & a,
336  Eigen::MatrixXd & rnea_partial_dq,
337  Eigen::MatrixXd & rnea_partial_dv,
338  Eigen::MatrixXd & rnea_partial_da)
339  {
340  assert(q.size() == model.nq && "The joint configuration vector is not of right size");
341  assert(v.size() == model.nv && "The joint velocity vector is not of right size");
342  assert(a.size() == model.nv && "The joint acceleration vector is not of right size");
343  assert(rnea_partial_dq.cols() == model.nv);
344  assert(rnea_partial_dq.rows() == model.nv);
345  assert(rnea_partial_dv.cols() == model.nv);
346  assert(rnea_partial_dv.rows() == model.nv);
347  assert(rnea_partial_da.cols() == model.nv);
348  assert(rnea_partial_da.rows() == model.nv);
349  assert(model.check(data) && "data is not consistent with model.");
350 
351  data.oa[0] = -model.gravity;
352 
353  for(Model::JointIndex i=1; i<(Model::JointIndex) model.njoints; ++i)
354  {
355  computeRNEADerivativesForwardStep::run(model.joints[i],data.joints[i],
356  computeRNEADerivativesForwardStep::ArgsType(model,data,q,v,a));
357  }
358 
359  for(size_t i=(size_t) (model.njoints-1);i>0;--i)
360  {
361  computeRNEADerivativesBackwardStep::run(model.joints[i],
362  computeRNEADerivativesBackwardStep::ArgsType(model,data,rnea_partial_dq,rnea_partial_dv,rnea_partial_da));
363  }
364  }
365 
366 
367 } // namespace se3
368 
369 #endif // ifndef __se3_rnea_derivatives_hxx__
370 
Eigen::VectorXd tau
Vector of joint torques (dim model.nv).
Definition: data.hpp:93
container::aligned_vector< Force > oh
Vector of spatial momenta expressed in the world frame.
Definition: data.hpp:84
container::aligned_vector< Motion > a
Vector of joint accelerations expressed at the centers of the joints.
Definition: data.hpp:58
int nq
Dimension of the configuration vector representation.
Definition: model.hpp:49
int nv
Dimension of the velocity vector space.
Definition: model.hpp:52
container::aligned_vector< SE3 > jointPlacements
Placement (SE3) of the input of joint i regarding to the parent joint output li.
Definition: model.hpp:67
std::vector< int > nvSubtree
Dimension of the subtree motion space (for CRBA)
Definition: data.hpp:195
container::aligned_vector< Inertia > oYcrb
Inertia quantities expressed in the world frame.
Definition: data.hpp:149
Eigen::VectorXd g
Vector of generalized gravity (dim model.nv).
Definition: data.hpp:103
Matrix6x dAdq
Variation of the spatial acceleration set with respect to the joint configuration.
Definition: data.hpp:226
JointModelVector joints
Model of joint i, encapsulated in a JointModelAccessor.
Definition: model.hpp:70
ConstAngularType angular() const
Return the angular part of the force vector.
Definition: force-base.hpp:53
void skew(const Eigen::MatrixBase< Vector3 > &v, const Eigen::MatrixBase< Matrix3 > &M)
Computes the skew representation of a given 3d vector, i.e. the antisymmetric matrix representation o...
Definition: skew.hpp:34
Matrix6x J
Jacobian of joint placements.
Definition: data.hpp:217
container::aligned_vector< Motion > oa
Vector of joint accelerations expressed at the origin.
Definition: data.hpp:61
container::aligned_vector< Inertia::Matrix6 > doYcrb
Time variation of the inertia quantities expressed in the world frame.
Definition: data.hpp:152
Matrix6x dVdq
Variation of the spatial velocity set with respect to the joint configuration.
Definition: data.hpp:223
Matrix6x dFdv
Variation of the forceset with respect to the joint velocity.
Definition: data.hpp:128
void computeGeneralizedGravityDerivatives(const Model &model, Data &data, const Eigen::VectorXd &q, Eigen::MatrixXd &gravity_partial_dq)
Computes the derivative of the generalized gravity contribution with respect to the joint configurati...
ConstLinearType linear() const
Return the linear part of the force vector.
Definition: force-base.hpp:60
container::aligned_vector< Force > of
Vector of body forces expressed in the world frame. For each body, the force represents the sum of al...
Definition: data.hpp:78
std::vector< JointIndex > parents
Joint parent of joint i, denoted li (li==parents[i]).
Definition: model.hpp:73
Matrix6x dAdv
Variation of the spatial acceleration set with respect to the joint velocity.
Definition: data.hpp:229
Matrix6x dFdq
Variation of the forceset with respect to the joint configuration.
Definition: data.hpp:125
container::aligned_vector< Motion > ov
Vector of joint velocities expressed at the origin.
Definition: data.hpp:70
Matrix6x dJ
Derivative of the Jacobian with respect to the time.
Definition: data.hpp:220
container::aligned_vector< Motion > a_gf
Vector of joint accelerations due to the gravity field.
Definition: data.hpp:64
JointDataVector joints
Vector of se3::JointData associated to the se3::JointModel stored in model, encapsulated in JointData...
Definition: data.hpp:55
Motion gravity
Spatial gravity of the model.
Definition: model.hpp:106
container::aligned_vector< SE3 > liMi
Vector of relative joint placements (wrt the body parent).
Definition: data.hpp:90
container::aligned_vector< SE3 > oMi
Vector of absolute joint placements (wrt the world).
Definition: data.hpp:87
bool check(const AlgorithmCheckerBase< D > &checker=AlgorithmCheckerBase< D >()) const
Definition: model.hpp:331
container::aligned_vector< Inertia > inertias
Spatial inertias of the body i expressed in the supporting joint frame i.
Definition: model.hpp:64
RowMatrix6 M6tmpR
Temporary for derivative algorithms.
Definition: data.hpp:158
std::vector< int > parents_fromRow
First previous non-zero row in M (used in Cholesky Decomposition).
Definition: data.hpp:210
container::aligned_vector< Motion > v
Vector of joint velocities expressed at the centers of the joints.
Definition: data.hpp:67
int njoints
Number of joints.
Definition: model.hpp:55
Matrix6x dFda
Variation of the forceset with respect to the joint acceleration.
Definition: data.hpp:131
void computeRNEADerivatives(const Model &model, Data &data, const Eigen::VectorXd &q, const Eigen::VectorXd &v, const Eigen::VectorXd &a, Eigen::MatrixXd &rnea_partial_dq, Eigen::MatrixXd &rnea_partial_dv, Eigen::MatrixXd &rnea_partial_da)
Computes the derivatives of the Recursive Newton Euler Algorithms with respect to the joint configura...