GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: include/pinocchio/algorithm/rnea.hxx Lines: 191 191 100.0 %
Date: 2024-01-23 21:41:47 Branches: 276 831 33.2 %

Line Branch Exec Source
1
//
2
// Copyright (c) 2015-2022 CNRS INRIA
3
//
4
5
#ifndef __pinocchio_algorithm_rnea_hxx__
6
#define __pinocchio_algorithm_rnea_hxx__
7
8
/// @cond DEV
9
10
#include "pinocchio/multibody/visitor.hpp"
11
#include "pinocchio/algorithm/check.hpp"
12
13
namespace pinocchio
14
{
15
  template<typename Scalar, int Options, template<typename,int> class JointCollectionTpl, typename ConfigVectorType, typename TangentVectorType1, typename TangentVectorType2>
16
  struct RneaForwardStep
17
  : public fusion::JointUnaryVisitorBase< RneaForwardStep<Scalar,Options,JointCollectionTpl,ConfigVectorType,TangentVectorType1,TangentVectorType2> >
18
  {
19
    typedef ModelTpl<Scalar,Options,JointCollectionTpl> Model;
20
    typedef DataTpl<Scalar,Options,JointCollectionTpl> Data;
21
22
    typedef boost::fusion::vector<const Model &,
23
                                  Data &,
24
                                  const ConfigVectorType &,
25
                                  const TangentVectorType1 &,
26
                                  const TangentVectorType2 &
27
                                  > ArgsType;
28
29
    template<typename JointModel>
30
19406
    static void algo(const JointModelBase<JointModel> & jmodel,
31
                     JointDataBase<typename JointModel::JointDataDerived> & jdata,
32
                     const Model & model,
33
                     Data & data,
34
                     const Eigen::MatrixBase<ConfigVectorType> & q,
35
                     const Eigen::MatrixBase<TangentVectorType1> & v,
36
                     const Eigen::MatrixBase<TangentVectorType2> & a)
37
    {
38
      typedef typename Model::JointIndex JointIndex;
39
40
19406
      const JointIndex i = jmodel.id();
41
19406
      const JointIndex parent = model.parents[i];
42
43
19406
      jmodel.calc(jdata.derived(),q.derived(),v.derived());
44
45
19406
      data.liMi[i] = model.jointPlacements[i]*jdata.M();
46
//      data.liMi[i].setIdentity();
47
48
19406
      data.v[i] = jdata.v();
49
19406
      if(parent>0)
50
18642
        data.v[i] += data.liMi[i].actInv(data.v[parent]);
51
52

19406
      data.a_gf[i] = jdata.c() + (data.v[i] ^ jdata.v());
53

19406
      data.a_gf[i] += jdata.S() * jmodel.jointVelocitySelector(a);
54
19406
      data.a_gf[i] += data.liMi[i].actInv(data.a_gf[parent]);
55
//
56
//      data.f[i] = model.inertias[i]*data.a_gf[i];// + model.inertias[i].vxiv(data.v[i]); // -f_ext
57
//      data.h[i] = model.inertias[i]*data.v[i];
58
19406
      model.inertias[i].__mult__(data.v[i],data.h[i]);
59
19406
      model.inertias[i].__mult__(data.a_gf[i],data.f[i]);
60
19406
      data.f[i] += data.v[i].cross(data.h[i]);
61
//      data.h[i].motionAction(data.v[i],data.f[i]);
62
//      data.f[i] = model.inertias[i].vxiv(data.v[i]);
63
//      data.f[i].setZero();
64
    }
65
66
  };
67
68
  template<typename Scalar, int Options, template<typename,int> class JointCollectionTpl>
69
  struct RneaBackwardStep
70
  : public fusion::JointUnaryVisitorBase< RneaBackwardStep<Scalar,Options,JointCollectionTpl> >
71
  {
72
    typedef ModelTpl<Scalar,Options,JointCollectionTpl> Model;
73
    typedef DataTpl<Scalar,Options,JointCollectionTpl> Data;
74
75
    typedef boost::fusion::vector<const Model &,
76
                                  Data &
77
                                  > ArgsType;
78
79
    template<typename JointModel>
80
19406
    static void algo(const JointModelBase<JointModel> & jmodel,
81
                     JointDataBase<typename JointModel::JointDataDerived> & jdata,
82
                     const Model & model,
83
                     Data & data)
84
    {
85
      typedef typename Model::JointIndex JointIndex;
86
87
19406
      const JointIndex i = jmodel.id();
88
19406
      const JointIndex parent = model.parents[i];
89
90

19406
      jmodel.jointVelocitySelector(data.tau) = jdata.S().transpose()*data.f[i];
91

19406
      if(parent>0) data.f[parent] += data.liMi[i].act(data.f[i]);
92
    }
93
  };
94
95
  template<typename Scalar, int Options, template<typename,int> class JointCollectionTpl, typename ConfigVectorType, typename TangentVectorType1, typename TangentVectorType2>
96
  inline const typename DataTpl<Scalar,Options,JointCollectionTpl>::TangentVectorType &
97
484
  rnea(const ModelTpl<Scalar,Options,JointCollectionTpl> & model,
98
       DataTpl<Scalar,Options,JointCollectionTpl> & data,
99
       const Eigen::MatrixBase<ConfigVectorType> & q,
100
       const Eigen::MatrixBase<TangentVectorType1> & v,
101
       const Eigen::MatrixBase<TangentVectorType2> & a)
102
  {
103

484
    assert(model.check(data) && "data is not consistent with model.");
104







484
    PINOCCHIO_CHECK_ARGUMENT_SIZE(q.size(), model.nq, "The configuration vector is not of right size");
105







484
    PINOCCHIO_CHECK_ARGUMENT_SIZE(v.size(), model.nv, "The velocity vector is not of right size");
106







484
    PINOCCHIO_CHECK_ARGUMENT_SIZE(a.size(), model.nv, "The acceleration vector is not of right size");
107
108
    typedef ModelTpl<Scalar,Options,JointCollectionTpl> Model;
109
    typedef typename Model::JointIndex JointIndex;
110
111
484
    data.v[0].setZero();
112
484
    data.a_gf[0] = -model.gravity;
113
114
    typedef RneaForwardStep<Scalar,Options,JointCollectionTpl,ConfigVectorType,TangentVectorType1,TangentVectorType2> Pass1;
115
484
    typename Pass1::ArgsType arg1(model,data,q.derived(),v.derived(),a.derived());
116
12955
    for(JointIndex i=1; i<(JointIndex)model.njoints; ++i)
117
    {
118

12471
      Pass1::run(model.joints[i],data.joints[i],
119
                 arg1);
120
    }
121
122
    typedef RneaBackwardStep<Scalar,Options,JointCollectionTpl> Pass2;
123
484
    typename Pass2::ArgsType arg2(model,data);
124
12955
    for(JointIndex i=(JointIndex)model.njoints-1; i>0; --i)
125
    {
126

12471
      Pass2::run(model.joints[i],data.joints[i],
127
                 arg2);
128
    }
129
130
484
    return data.tau;
131
  }
132
133
  template<typename Scalar, int Options, template<typename,int> class JointCollectionTpl, typename ConfigVectorType, typename TangentVectorType1, typename TangentVectorType2, typename ForceDerived>
134
  inline const typename DataTpl<Scalar,Options,JointCollectionTpl>::TangentVectorType &
135
105
  rnea(const ModelTpl<Scalar,Options,JointCollectionTpl> & model,
136
       DataTpl<Scalar,Options,JointCollectionTpl> & data,
137
       const Eigen::MatrixBase<ConfigVectorType> & q,
138
       const Eigen::MatrixBase<TangentVectorType1> & v,
139
       const Eigen::MatrixBase<TangentVectorType2> & a,
140
       const container::aligned_vector<ForceDerived> & fext)
141
  {
142






105
    PINOCCHIO_CHECK_ARGUMENT_SIZE(fext.size(), model.joints.size());
143
105
    assert(model.check(data) && "data is not consistent with model.");
144






105
    PINOCCHIO_CHECK_ARGUMENT_SIZE(q.size(), model.nq, "The configuration vector is not of right size");
145






105
    PINOCCHIO_CHECK_ARGUMENT_SIZE(v.size(), model.nv, "The velocity vector is not of right size");
146






105
    PINOCCHIO_CHECK_ARGUMENT_SIZE(a.size(), model.nv, "The acceleration vector is not of right size");
147
148
    typedef ModelTpl<Scalar,Options,JointCollectionTpl> Model;
149
    typedef typename Model::JointIndex JointIndex;
150
151
105
    data.v[0].setZero();
152
105
    data.a_gf[0] = -model.gravity;
153
154
    typedef RneaForwardStep<Scalar,Options,JointCollectionTpl,ConfigVectorType,TangentVectorType1,TangentVectorType2> Pass1;
155
2926
    for(JointIndex i=1; i<(JointIndex)model.njoints; ++i)
156
    {
157
2821
      Pass1::run(model.joints[i],data.joints[i],
158
                 typename Pass1::ArgsType(model,data,q.derived(),v.derived(),a.derived()));
159
2821
      data.f[i] -= fext[i];
160
    }
161
162
    typedef RneaBackwardStep<Scalar,Options,JointCollectionTpl> Pass2;
163
2926
    for(JointIndex i=(JointIndex)model.njoints-1; i>0; --i)
164
    {
165
2821
      Pass2::run(model.joints[i],data.joints[i],
166
                 typename Pass2::ArgsType(model,data));
167
    }
168
169
170
105
    return data.tau;
171
  }
172
173
  template<typename Scalar, int Options, template<typename,int> class JointCollectionTpl, typename ConfigVectorType, typename TangentVectorType>
174
  struct NLEForwardStep
175
  : public fusion::JointUnaryVisitorBase< NLEForwardStep<Scalar,Options,JointCollectionTpl,ConfigVectorType,TangentVectorType> >
176
  {
177
    typedef ModelTpl<Scalar,Options,JointCollectionTpl> Model;
178
    typedef DataTpl<Scalar,Options,JointCollectionTpl> Data;
179
180
    typedef boost::fusion::vector<const Model &,
181
                                  Data &,
182
                                  const ConfigVectorType &,
183
                                  const TangentVectorType &
184
                                  > ArgsType;
185
186
    template<typename JointModel>
187
594
    static void algo(const pinocchio::JointModelBase<JointModel> & jmodel,
188
                     pinocchio::JointDataBase<typename JointModel::JointDataDerived> & jdata,
189
                     const Model & model,
190
                     Data & data,
191
                     const Eigen::MatrixBase<ConfigVectorType> & q,
192
                     const Eigen::MatrixBase<TangentVectorType> & v)
193
    {
194
      typedef typename Model::JointIndex JointIndex;
195
196
594
      const JointIndex & i = jmodel.id();
197
594
      const JointIndex & parent = model.parents[i];
198
199
594
      jmodel.calc(jdata.derived(),q.derived(),v.derived());
200
201
594
      data.liMi[i] = model.jointPlacements[i]*jdata.M();
202
203
594
      data.v[i] = jdata.v();
204

594
      if(parent>0) data.v[i] += data.liMi[i].actInv(data.v[parent]);
205
206

594
      data.a_gf[i]  = jdata.c() + (data.v[i] ^ jdata.v());
207
594
      data.a_gf[i] += data.liMi[i].actInv(data.a_gf[parent]);
208
209

594
      data.f[i] = model.inertias[i]*data.a_gf[i] + model.inertias[i].vxiv(data.v[i]); // -f_ext
210
    }
211
212
  };
213
214
  template<typename Scalar, int Options, template<typename,int> class JointCollectionTpl>
215
  struct NLEBackwardStep
216
  : public fusion::JointUnaryVisitorBase< NLEBackwardStep<Scalar,Options,JointCollectionTpl> >
217
  {
218
    typedef ModelTpl<Scalar,Options,JointCollectionTpl> Model;
219
    typedef DataTpl<Scalar,Options,JointCollectionTpl> Data;
220
221
    typedef boost::fusion::vector<const Model &,
222
                                  Data &
223
                                  >  ArgsType;
224
225
    template<typename JointModel>
226
594
    static void algo(const JointModelBase<JointModel> & jmodel,
227
                     JointDataBase<typename JointModel::JointDataDerived> & jdata,
228
                     const Model & model,
229
                     Data & data)
230
    {
231
      typedef typename Model::JointIndex JointIndex;
232
233
594
      const JointIndex & i = jmodel.id();
234
594
      const JointIndex & parent  = model.parents[i];
235
236

594
      jmodel.jointVelocitySelector(data.nle) = jdata.S().transpose()*data.f[i];
237

594
      if(parent>0) data.f[parent] += data.liMi[i].act(data.f[i]);
238
    }
239
  };
240
241
  template<typename Scalar, int Options, template<typename,int> class JointCollectionTpl, typename ConfigVectorType, typename TangentVectorType>
242
  inline const typename DataTpl<Scalar,Options,JointCollectionTpl>::TangentVectorType &
243
11
  nonLinearEffects(const ModelTpl<Scalar,Options,JointCollectionTpl> & model,
244
                   DataTpl<Scalar,Options,JointCollectionTpl> & data,
245
                   const Eigen::MatrixBase<ConfigVectorType> & q,
246
                   const Eigen::MatrixBase<TangentVectorType> & v)
247
  {
248
11
    assert(model.check(data) && "data is not consistent with model.");
249






11
    PINOCCHIO_CHECK_ARGUMENT_SIZE(q.size(), model.nq, "The configuration vector is not of right size");
250






11
    PINOCCHIO_CHECK_ARGUMENT_SIZE(v.size(), model.nv, "The velocity vector is not of right size");
251
252
    typedef ModelTpl<Scalar,Options,JointCollectionTpl> Model;
253
    typedef typename Model::JointIndex JointIndex;
254
255
11
    data.v[0].setZero ();
256
11
    data.a_gf[0] = -model.gravity;
257
258
    typedef NLEForwardStep<Scalar,Options,JointCollectionTpl,ConfigVectorType,TangentVectorType> Pass1;
259
308
    for(JointIndex i=1; i<(JointIndex)model.njoints; ++i)
260
    {
261
297
      Pass1::run(model.joints[i],data.joints[i],
262
                 typename Pass1::ArgsType(model,data,q.derived(),v.derived()));
263
    }
264
265
    typedef NLEBackwardStep<Scalar,Options,JointCollectionTpl> Pass2;
266
308
    for(JointIndex i=(JointIndex)(model.njoints-1); i>0; --i)
267
    {
268
297
      Pass2::run(model.joints[i],data.joints[i],
269
                 typename Pass2::ArgsType(model,data));
270
    }
271
272
11
    return data.nle;
273
  }
274
275
  template<typename Scalar, int Options, template<typename,int> class JointCollectionTpl, typename ConfigVectorType>
276
  struct ComputeGeneralizedGravityForwardStep
277
  : public fusion::JointUnaryVisitorBase< ComputeGeneralizedGravityForwardStep<Scalar,Options,JointCollectionTpl,ConfigVectorType> >
278
  {
279
    typedef ModelTpl<Scalar,Options,JointCollectionTpl> Model;
280
    typedef DataTpl<Scalar,Options,JointCollectionTpl> Data;
281
282
    typedef boost::fusion::vector<const Model &,
283
                                  Data &,
284
                                  const ConfigVectorType &
285
                                  > ArgsType;
286
287
    template<typename JointModel>
288
3888
    static void algo(const pinocchio::JointModelBase<JointModel> & jmodel,
289
                     pinocchio::JointDataBase<typename JointModel::JointDataDerived> & jdata,
290
                     const Model & model,
291
                     Data & data,
292
                     const Eigen::MatrixBase<ConfigVectorType> & q)
293
    {
294
      typedef typename Model::JointIndex JointIndex;
295
296
3888
      const JointIndex & i = jmodel.id();
297
3888
      const JointIndex & parent = model.parents[i];
298
299
3888
      jmodel.calc(jdata.derived(),q.derived());
300
301
3888
      data.liMi[i] = model.jointPlacements[i]*jdata.M();
302
303
3888
      data.a_gf[i] = data.liMi[i].actInv(data.a_gf[(size_t) parent]);
304
3888
      data.f[i] = model.inertias[i]*data.a_gf[i];
305
    }
306
307
  };
308
309
  template<typename Scalar, int Options, template<typename,int> class JointCollectionTpl>
310
  struct ComputeGeneralizedGravityBackwardStep
311
  : public fusion::JointUnaryVisitorBase< ComputeGeneralizedGravityBackwardStep<Scalar,Options,JointCollectionTpl> >
312
  {
313
    typedef ModelTpl<Scalar,Options,JointCollectionTpl> Model;
314
    typedef DataTpl<Scalar,Options,JointCollectionTpl> Data;
315
316
    typedef boost::fusion::vector<const Model &,
317
                                  Data &,
318
                                  typename Data::VectorXs &
319
                                  > ArgsType;
320
321
    template<typename JointModel>
322
3888
    static void algo(const JointModelBase<JointModel> & jmodel,
323
                     JointDataBase<typename JointModel::JointDataDerived> & jdata,
324
                     const Model & model,
325
                     Data & data,
326
                     typename Data::VectorXs & g)
327
    {
328
      typedef typename Model::JointIndex JointIndex;
329
330
3888
      const JointIndex & i = jmodel.id();
331
3888
      const JointIndex & parent = model.parents[i];
332
333

3888
      jmodel.jointVelocitySelector(g) = jdata.S().transpose()*data.f[i];
334

3888
      if(parent>0) data.f[(size_t) parent] += data.liMi[i].act(data.f[i]);
335
    }
336
  };
337
338
  template<typename Scalar, int Options, template<typename,int> class JointCollectionTpl, typename ConfigVectorType>
339
  inline const typename DataTpl<Scalar,Options,JointCollectionTpl>::TangentVectorType &
340
38
  computeGeneralizedGravity(const ModelTpl<Scalar,Options,JointCollectionTpl> & model,
341
                            DataTpl<Scalar,Options,JointCollectionTpl> & data,
342
                            const Eigen::MatrixBase<ConfigVectorType> & q)
343
  {
344
38
    assert(model.check(data) && "data is not consistent with model.");
345






38
    PINOCCHIO_CHECK_ARGUMENT_SIZE(q.size(), model.nq, "The configuration vector is not of right size");
346
347
    typedef ModelTpl<Scalar,Options,JointCollectionTpl> Model;
348
    typedef typename Model::JointIndex JointIndex;
349
350
38
    data.a_gf[0] = -model.gravity;
351
352
    typedef ComputeGeneralizedGravityForwardStep<Scalar,Options,JointCollectionTpl,ConfigVectorType> Pass1;
353
1064
    for(JointIndex i=1; i<(JointIndex)model.njoints; ++i)
354
    {
355
1026
      Pass1::run(model.joints[i],data.joints[i],
356
                 typename Pass1::ArgsType(model,data,q.derived()));
357
    }
358
359
    typedef ComputeGeneralizedGravityBackwardStep<Scalar,Options,JointCollectionTpl> Pass2;
360
1064
    for(JointIndex i=(JointIndex)(model.njoints-1); i>0; --i)
361
    {
362
1026
      Pass2::run(model.joints[i],data.joints[i],
363
1026
                 typename Pass2::ArgsType(model,data,data.g));
364
    }
365
366
38
    return data.g;
367
  }
368
369
  template<typename Scalar, int Options, template<typename,int> class JointCollectionTpl, typename ConfigVectorType>
370
  inline const typename DataTpl<Scalar,Options,JointCollectionTpl>::TangentVectorType &
371
34
  computeStaticTorque(const ModelTpl<Scalar,Options,JointCollectionTpl> & model,
372
                                 DataTpl<Scalar,Options,JointCollectionTpl> & data,
373
                                 const Eigen::MatrixBase<ConfigVectorType> & q,
374
                                 const container::aligned_vector< ForceTpl<Scalar,Options> > & fext)
375
  {
376
34
    assert(model.check(data) && "data is not consistent with model.");
377






34
    PINOCCHIO_CHECK_ARGUMENT_SIZE(q.size(), model.nq, "The configuration vector is not of right size");
378






34
    PINOCCHIO_CHECK_ARGUMENT_SIZE(fext.size(), (size_t)model.njoints, "The size of the external forces is not of right size");
379
380
    typedef ModelTpl<Scalar,Options,JointCollectionTpl> Model;
381
    typedef typename Model::JointIndex JointIndex;
382
383
34
    data.a_gf[0] = -model.gravity;
384
385
    typedef ComputeGeneralizedGravityForwardStep<Scalar,Options,JointCollectionTpl,ConfigVectorType> Pass1;
386
952
    for(JointIndex i=1; i<(JointIndex)model.njoints; ++i)
387
    {
388
918
      Pass1::run(model.joints[i],data.joints[i],
389
                 typename Pass1::ArgsType(model,data,q.derived()));
390
918
      data.f[i] -= fext[i];
391
    }
392
393
    typedef ComputeGeneralizedGravityBackwardStep<Scalar,Options,JointCollectionTpl> Pass2;
394
952
    for(JointIndex i=(JointIndex)(model.njoints-1); i>0; --i)
395
    {
396
918
      Pass2::run(model.joints[i],data.joints[i],
397
918
                 typename Pass2::ArgsType(model,data,data.tau));
398
    }
399
400
34
    return data.tau;
401
  }
402
403
  template<typename Scalar, int Options, template<typename,int> class JointCollectionTpl, typename ConfigVectorType, typename TangentVectorType>
404
  struct CoriolisMatrixForwardStep
405
  : public fusion::JointUnaryVisitorBase< CoriolisMatrixForwardStep<Scalar,Options,JointCollectionTpl,ConfigVectorType,TangentVectorType> >
406
  {
407
    typedef ModelTpl<Scalar,Options,JointCollectionTpl> Model;
408
    typedef DataTpl<Scalar,Options,JointCollectionTpl> Data;
409
410
    typedef boost::fusion::vector<const Model &,
411
                                  Data &,
412
                                  const ConfigVectorType &,
413
                                  const TangentVectorType &
414
                                  > ArgsType;
415
416
    template<typename JointModel>
417
162
    static void algo(const pinocchio::JointModelBase<JointModel> & jmodel,
418
                     pinocchio::JointDataBase<typename JointModel::JointDataDerived> & jdata,
419
                     const Model & model,
420
                     Data & data,
421
                     const Eigen::MatrixBase<ConfigVectorType> & q,
422
                     const Eigen::MatrixBase<TangentVectorType> & v)
423
    {
424
      typedef typename Model::JointIndex JointIndex;
425
426
162
      const JointIndex & i = jmodel.id();
427
162
      const JointIndex & parent = model.parents[i];
428
429
162
      jmodel.calc(jdata.derived(),q.derived(),v.derived());
430
431

162
      data.liMi[i] = model.jointPlacements[i]*jdata.M();
432

162
      if(parent>0) data.oMi[i] = data.oMi[parent] * data.liMi[i];
433
6
      else data.oMi[i] = data.liMi[i];
434
435
      // express quantities in the world frame
436

162
      data.oYcrb[i] = data.oMi[i].act(model.inertias[i]);
437
438

162
      data.v[i] = jdata.v();
439

162
      if(parent>0) data.v[i] += data.liMi[i].actInv(data.v[parent]);
440
162
      data.ov[i] = data.oMi[i].act(data.v[i]);
441

162
      data.oh[i] = data.oYcrb[i] * data.ov[i];
442
443
      // computes S expressed at the world frame
444
      typedef typename SizeDepType<JointModel::NV>::template ColsReturn<typename Data::Matrix6x>::Type ColsBlock;
445
162
      ColsBlock Jcols = jmodel.jointCols(data.J);
446

162
      Jcols = data.oMi[i].act(jdata.S()); // collection of S expressed at the world frame
447
448
      // computes vxS expressed at the world frame
449
162
      ColsBlock dJcols = jmodel.jointCols(data.dJ);
450
162
      motionSet::motionAction(data.ov[i],Jcols,dJcols);
451
452

162
      data.B[i] = data.oYcrb[i].variation(0.5*data.ov[i]);
453

162
      addForceCrossMatrix(0.5*data.oh[i],data.B[i]);
454
    }
455
456
    template<typename ForceDerived, typename M6>
457
162
    static void addForceCrossMatrix(const ForceDense<ForceDerived> & f,
458
                                    const Eigen::MatrixBase<M6> & mout)
459
    {
460
162
      M6 & mout_ = PINOCCHIO_EIGEN_CONST_CAST(M6,mout);
461

162
      addSkew(-f.linear(),mout_.template block<3,3>(ForceDerived::LINEAR,ForceDerived::ANGULAR));
462

162
      addSkew(-f.linear(),mout_.template block<3,3>(ForceDerived::ANGULAR,ForceDerived::LINEAR));
463

162
      addSkew(-f.angular(),mout_.template block<3,3>(ForceDerived::ANGULAR,ForceDerived::ANGULAR));
464
162
    }
465
466
  };
467
468
  template<typename Scalar, int Options, template<typename,int> class JointCollectionTpl>
469
  struct CoriolisMatrixBackwardStep
470
  : public fusion::JointUnaryVisitorBase< CoriolisMatrixBackwardStep<Scalar,Options,JointCollectionTpl> >
471
  {
472
    typedef ModelTpl<Scalar,Options,JointCollectionTpl> Model;
473
    typedef DataTpl<Scalar,Options,JointCollectionTpl> Data;
474
475
    typedef boost::fusion::vector<const Model &,
476
                                  Data &
477
                                  > ArgsType;
478
479
    template<typename JointModel>
480
162
    static void algo(const JointModelBase<JointModel> & jmodel,
481
                     const Model & model,
482
                     Data & data)
483
    {
484
      typedef typename Model::JointIndex JointIndex;
485
486
162
      const JointIndex i = jmodel.id();
487
162
      const JointIndex parent = model.parents[i];
488
162
      typename Data::RowMatrix6 & M6tmpR = data.M6tmpR;
489
490
      typedef typename SizeDepType<JointModel::NV>::template ColsReturn<typename Data::Matrix6x>::Type ColsBlock;
491
162
      ColsBlock dJcols = jmodel.jointCols(data.dJ);
492
162
      ColsBlock Jcols = jmodel.jointCols(data.J);
493
494

162
      motionSet::inertiaAction(data.oYcrb[i],dJcols,jmodel.jointCols(data.dFdv));
495

162
      jmodel.jointCols(data.dFdv) += data.B[i] * Jcols;
496
497


162
      data.C.block(jmodel.idx_v(),jmodel.idx_v(),jmodel.nv(),data.nvSubtree[i]).noalias()
498



324
      = Jcols.transpose()*data.dFdv.middleCols(jmodel.idx_v(),data.nvSubtree[i]);
499
500


162
      lhsInertiaMult(data.oYcrb[i],Jcols.transpose(),M6tmpR.topRows(jmodel.nv()));
501

1608
      for(int j = data.parents_fromRow[(JointIndex)jmodel.idx_v()];j >= 0; j = data.parents_fromRow[(JointIndex)j])
502





1446
        data.C.middleRows(jmodel.idx_v(),jmodel.nv()).col(j).noalias() = M6tmpR.topRows(jmodel.nv()) * data.dJ.col(j);
503
504



162
      M6tmpR.topRows(jmodel.nv()).noalias() = Jcols.transpose() * data.B[i];
505

1608
      for(int j = data.parents_fromRow[(JointIndex)jmodel.idx_v()];j >= 0; j = data.parents_fromRow[(JointIndex)j])
506





1446
        data.C.middleRows(jmodel.idx_v(),jmodel.nv()).col(j).noalias() += M6tmpR.topRows(jmodel.nv()) * data.J.col(j);
507
508
162
      if(parent>0)
509
      {
510
156
        data.oYcrb[parent] += data.oYcrb[i];
511
156
        data.B[parent] += data.B[i];
512
      }
513
514
    }
515
516
    template<typename Min, typename Mout>
517
216
    static void lhsInertiaMult(const typename Data::Inertia & Y,
518
                               const Eigen::MatrixBase<Min> & J,
519
                               const Eigen::MatrixBase<Mout> & F)
520
    {
521
216
      Mout & F_ = PINOCCHIO_EIGEN_CONST_CAST(Mout,F);
522

216
      motionSet::inertiaAction(Y,J.derived().transpose(),F_.transpose());
523
    }
524
  };
525
526
  template<typename Scalar, int Options, template<typename,int> class JointCollectionTpl, typename ConfigVectorType, typename TangentVectorType>
527
  inline const typename DataTpl<Scalar,Options,JointCollectionTpl>::MatrixXs &
528
3
  computeCoriolisMatrix(const ModelTpl<Scalar,Options,JointCollectionTpl> & model,
529
                        DataTpl<Scalar,Options,JointCollectionTpl> & data,
530
                        const Eigen::MatrixBase<ConfigVectorType> & q,
531
                        const Eigen::MatrixBase<TangentVectorType> & v)
532
  {
533
3
    assert(model.check(data) && "data is not consistent with model.");
534






3
    PINOCCHIO_CHECK_ARGUMENT_SIZE(q.size(), model.nq);
535






3
    PINOCCHIO_CHECK_ARGUMENT_SIZE(v.size(), model.nv);
536
537
    typedef ModelTpl<Scalar,Options,JointCollectionTpl> Model;
538
    typedef typename Model::JointIndex JointIndex;
539
540
    typedef CoriolisMatrixForwardStep<Scalar,Options,JointCollectionTpl,ConfigVectorType,TangentVectorType> Pass1;
541
84
    for(JointIndex i=1; i<(JointIndex)model.njoints; ++i)
542
    {
543
81
      Pass1::run(model.joints[i],data.joints[i],
544
                 typename Pass1::ArgsType(model,data,q.derived(),v.derived()));
545
    }
546
547
    typedef CoriolisMatrixBackwardStep<Scalar,Options,JointCollectionTpl> Pass2;
548
84
    for(JointIndex i=(JointIndex)(model.njoints-1); i>0; --i)
549
    {
550
81
      Pass2::run(model.joints[i],
551
                 typename Pass2::ArgsType(model,data));
552
    }
553
554
3
    return data.C;
555
  }
556
557
  template<typename Scalar, int Options, template<typename,int> class JointCollectionTpl>
558
  struct GetCoriolisMatrixBackwardStep
559
  : public fusion::JointUnaryVisitorBase< GetCoriolisMatrixBackwardStep<Scalar,Options,JointCollectionTpl> >
560
  {
561
    typedef ModelTpl<Scalar,Options,JointCollectionTpl> Model;
562
    typedef DataTpl<Scalar,Options,JointCollectionTpl> Data;
563
564
    typedef boost::fusion::vector<const Model &,
565
                                  Data &
566
                                  > ArgsType;
567
568
    template<typename JointModel>
569
54
    static void algo(const JointModelBase<JointModel> & jmodel,
570
                     const Model & model,
571
                     Data & data)
572
    {
573
      typedef typename Model::JointIndex JointIndex;
574
      typedef CoriolisMatrixBackwardStep<Scalar,Options,JointCollectionTpl> EquivalentPass;
575
576
54
      const JointIndex i = jmodel.id();
577
54
      const JointIndex parent = model.parents[i];
578
54
      typename Data::RowMatrix6 & M6tmpR = data.M6tmpR;
579
580
      typedef typename SizeDepType<JointModel::NV>::template ColsReturn<typename Data::Matrix6x>::Type ColsBlock;
581
54
      ColsBlock dJ_cols = jmodel.jointCols(data.dJ);
582
54
      ColsBlock J_cols = jmodel.jointCols(data.J);
583
54
      typename Data::Matrix6x & dFdv = data.Fcrb[0];
584
54
      ColsBlock dFdv_cols = jmodel.jointCols(dFdv);
585
586
54
      motionSet::inertiaAction(data.oYcrb[i],dJ_cols,dFdv_cols);
587

54
      dFdv_cols.noalias() += data.B[i] * J_cols;
588
589


54
      data.C.block(jmodel.idx_v(),jmodel.idx_v(),jmodel.nv(),data.nvSubtree[i]).noalias()
590



108
      = J_cols.transpose() * dFdv.middleCols(jmodel.idx_v(),data.nvSubtree[i]);
591
592


54
      EquivalentPass::lhsInertiaMult(data.oYcrb[i],J_cols.transpose(),M6tmpR.topRows(jmodel.nv()));
593

536
      for(int j = data.parents_fromRow[(JointIndex)jmodel.idx_v()];j >= 0; j = data.parents_fromRow[(JointIndex)j])
594





482
        data.C.middleRows(jmodel.idx_v(),jmodel.nv()).col(j).noalias() = M6tmpR.topRows(jmodel.nv()) * data.dJ.col(j);
595
596



54
      M6tmpR.topRows(jmodel.nv()).noalias() = J_cols.transpose() * data.B[i];
597

536
      for(int j = data.parents_fromRow[(JointIndex)jmodel.idx_v()];j >= 0; j = data.parents_fromRow[(JointIndex)j])
598





482
        data.C.middleRows(jmodel.idx_v(),jmodel.nv()).col(j).noalias() += M6tmpR.topRows(jmodel.nv()) * data.J.col(j);
599
600
54
      if(parent>0)
601
52
        data.B[parent] += data.B[i];
602
603
    }
604
  };
605
606
  template<typename Scalar, int Options, template<typename,int> class JointCollectionTpl>
607
  inline const typename DataTpl<Scalar,Options,JointCollectionTpl>::MatrixXs &
608
1
  getCoriolisMatrix(const ModelTpl<Scalar,Options,JointCollectionTpl> & model,
609
                    DataTpl<Scalar,Options,JointCollectionTpl> & data)
610
  {
611
1
    assert(model.check(data) && "data is not consistent with model.");
612
613
    typedef ModelTpl<Scalar,Options,JointCollectionTpl> Model;
614
    typedef typename Model::JointIndex JointIndex;
615
    typedef typename Model::ConfigVectorType ConfigVectorType;
616
    typedef typename Model::TangentVectorType TangentVectorType;
617
618
    typedef CoriolisMatrixForwardStep<Scalar,Options,JointCollectionTpl,ConfigVectorType,TangentVectorType> Pass1;
619
28
    for(JointIndex i=1; i<(JointIndex)model.njoints; ++i)
620
    {
621
      typedef typename Data::Inertia Inertia;
622
27
      const Inertia oY = data.oMi[i].act(model.inertias[i]);
623

27
      data.B[i] = oY.variation(0.5*data.ov[i]);
624

27
      Pass1::addForceCrossMatrix(0.5*data.oh[i],data.B[i]);
625
    }
626
627
    typedef GetCoriolisMatrixBackwardStep<Scalar,Options,JointCollectionTpl> Pass2;
628
28
    for(JointIndex i=(JointIndex)(model.njoints-1); i>0; --i)
629
    {
630
27
      Pass2::run(model.joints[i],typename Pass2::ArgsType(model,data));
631
    }
632
633
1
    return data.C;
634
  }
635
636
} // namespace pinocchio
637
638
/// @endcond
639
640
#endif // ifndef __pinocchio_algorithm_rnea_hxx__