GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: include/pinocchio/algorithm/aba.hxx Lines: 163 163 100.0 %
Date: 2024-01-23 21:41:47 Branches: 271 671 40.4 %

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

10936
      data.a_gf[i] = jdata.c() + (data.v[i] ^ jdata.v());
50
51
10936
      data.Yaba[i] = model.inertias[i].matrix();
52
10936
      data.f[i] = model.inertias[i].vxiv(data.v[i]); // -f_ext
53
    }
54
55
  };
56
57
  namespace internal
58
  {
59
60
    template<typename Scalar>
61
    struct SE3actOn
62
    {
63
      template<int Options, typename Matrix6Type>
64
      static typename PINOCCHIO_EIGEN_PLAIN_TYPE(Matrix6Type)
65
6609
      run(const SE3Tpl<Scalar,Options> & M,
66
          const Eigen::MatrixBase<Matrix6Type> & I)
67
      {
68
        typedef SE3Tpl<Scalar,Options> SE3;
69
        typedef typename SE3::Matrix3 Matrix3;
70
        typedef typename SE3::Vector3 Vector3;
71
72
        typedef const Eigen::Block<Matrix6Type,3,3> constBlock3;
73
74
        typedef typename PINOCCHIO_EIGEN_PLAIN_TYPE(Matrix6Type) ReturnType;
75
        typedef Eigen::Block<ReturnType,3,3> Block3;
76
77
6609
        Matrix6Type & I_ = PINOCCHIO_EIGEN_CONST_CAST(Matrix6Type,I);
78
6609
        const constBlock3 & Ai = I_.template block<3,3>(Inertia::LINEAR, Inertia::LINEAR);
79
6609
        const constBlock3 & Bi = I_.template block<3,3>(Inertia::LINEAR, Inertia::ANGULAR);
80
6609
        const constBlock3 & Di = I_.template block<3,3>(Inertia::ANGULAR, Inertia::ANGULAR);
81
82
6609
        const Matrix3 & R = M.rotation();
83
6609
        const Vector3 & t = M.translation();
84
85
6609
        ReturnType res;
86
6609
        Block3 Ao = res.template block<3,3>(Inertia::LINEAR, Inertia::LINEAR);
87
6609
        Block3 Bo = res.template block<3,3>(Inertia::LINEAR, Inertia::ANGULAR);
88
6609
        Block3 Co = res.template block<3,3>(Inertia::ANGULAR, Inertia::LINEAR);
89
6609
        Block3 Do = res.template block<3,3>(Inertia::ANGULAR, Inertia::ANGULAR);
90
91

6609
        Do.noalias() = R*Ai; // tmp variable
92


6609
        Ao.noalias() = Do*R.transpose();
93
94

6609
        Do.noalias() = R*Bi; // tmp variable
95


6609
        Bo.noalias() = Do*R.transpose();
96
97

6609
        Co.noalias() = R*Di; // tmp variable
98


6609
        Do.noalias() = Co*R.transpose();
99
100


6609
        Do.row(0) += t.cross(Bo.col(0));
101


6609
        Do.row(1) += t.cross(Bo.col(1));
102


6609
        Do.row(2) += t.cross(Bo.col(2));
103
104


6609
        Co.col(0) = t.cross(Ao.col(0));
105


6609
        Co.col(1) = t.cross(Ao.col(1));
106


6609
        Co.col(2) = t.cross(Ao.col(2));
107

6609
        Co += Bo.transpose();
108
109

6609
        Bo = Co.transpose();
110


6609
        Do.col(0) += t.cross(Bo.col(0));
111


6609
        Do.col(1) += t.cross(Bo.col(1));
112


6609
        Do.col(2) += t.cross(Bo.col(2));
113
114
13218
        return res;
115
      }
116
    };
117
118
  }
119
120
  template<typename Scalar, int Options, template<typename,int> class JointCollectionTpl>
121
  struct AbaBackwardStep
122
  : public fusion::JointUnaryVisitorBase< AbaBackwardStep<Scalar,Options,JointCollectionTpl> >
123
  {
124
    typedef ModelTpl<Scalar,Options,JointCollectionTpl> Model;
125
    typedef DataTpl<Scalar,Options,JointCollectionTpl> Data;
126
127
    typedef boost::fusion::vector<const Model &,
128
                                  Data &> ArgsType;
129
130
    template<typename JointModel>
131
10936
    static void algo(const JointModelBase<JointModel> & jmodel,
132
                     JointDataBase<typename JointModel::JointDataDerived> & jdata,
133
                     const Model & model,
134
                     Data & data)
135
    {
136
      typedef typename Model::JointIndex JointIndex;
137
      typedef typename Data::Inertia Inertia;
138
      typedef typename Data::Force Force;
139
140
10936
      const JointIndex & i = jmodel.id();
141
10936
      const JointIndex & parent  = model.parents[i];
142
10936
      typename Inertia::Matrix6 & Ia = data.Yaba[i];
143
144

10936
      jmodel.jointVelocitySelector(data.u) -= jdata.S().transpose()*data.f[i];
145
10936
      jmodel.calc_aba(jdata.derived(), Ia, parent > 0);
146
147
10936
      if (parent > 0)
148
      {
149
10504
        Force & pa = data.f[i];
150



10504
        pa.toVector() += Ia * data.a_gf[i].toVector() + jdata.UDinv() * jmodel.jointVelocitySelector(data.u);
151
10504
        data.Yaba[parent] += internal::SE3actOn<Scalar>::run(data.liMi[i], Ia);
152
10504
        data.f[parent] += data.liMi[i].act(pa);
153
      }
154
    }
155
156
  };
157
158
159
160
  template<typename Scalar, int Options, template<typename,int> class JointCollectionTpl>
161
  struct AbaForwardStep2
162
  : public fusion::JointUnaryVisitorBase< AbaForwardStep2<Scalar,Options,JointCollectionTpl> >
163
  {
164
    typedef ModelTpl<Scalar,Options,JointCollectionTpl> Model;
165
    typedef DataTpl<Scalar,Options,JointCollectionTpl> Data;
166
167
    typedef boost::fusion::vector<const Model &,
168
                                  Data &> ArgsType;
169
170
    template<typename JointModel>
171
10936
    static void algo(const pinocchio::JointModelBase<JointModel> & jmodel,
172
                     pinocchio::JointDataBase<typename JointModel::JointDataDerived> & jdata,
173
                     const Model & model,
174
                     Data & data)
175
    {
176
      typedef typename Model::JointIndex JointIndex;
177
178
10936
      const JointIndex & i = jmodel.id();
179
10936
      const JointIndex & parent = model.parents[i];
180
181
10936
      data.a_gf[i] += data.liMi[i].actInv(data.a_gf[parent]);
182


10936
      jmodel.jointVelocitySelector(data.ddq).noalias() =
183


10936
      jdata.Dinv() * jmodel.jointVelocitySelector(data.u) - jdata.UDinv().transpose() * data.a_gf[i].toVector();
184

10936
      data.a_gf[i] += jdata.S() * jmodel.jointVelocitySelector(data.ddq);
185
    }
186
187
  };
188
189
  template<typename Scalar, int Options, template<typename,int> class JointCollectionTpl, typename ConfigVectorType, typename TangentVectorType1, typename TangentVectorType2>
190
  inline const typename DataTpl<Scalar,Options,JointCollectionTpl>::TangentVectorType &
191
117
  aba(const ModelTpl<Scalar,Options,JointCollectionTpl> & model,
192
      DataTpl<Scalar,Options,JointCollectionTpl> & data,
193
      const Eigen::MatrixBase<ConfigVectorType> & q,
194
      const Eigen::MatrixBase<TangentVectorType1> & v,
195
      const Eigen::MatrixBase<TangentVectorType2> & tau)
196
  {
197
117
    assert(model.check(data) && "data is not consistent with model.");
198






117
    PINOCCHIO_CHECK_ARGUMENT_SIZE(q.size(), model.nq, "The joint configuration vector is not of right size");
199






117
    PINOCCHIO_CHECK_ARGUMENT_SIZE(v.size(), model.nv, "The joint velocity vector is not of right size");
200






117
    PINOCCHIO_CHECK_ARGUMENT_SIZE(tau.size(), model.nv, "The joint torque vector is not of right size");
201
202
    typedef typename ModelTpl<Scalar,Options,JointCollectionTpl>::JointIndex JointIndex;
203
204
117
    data.v[0].setZero();
205
117
    data.a_gf[0] = -model.gravity;
206
117
    data.u = tau;
207
208
    typedef AbaForwardStep1<Scalar,Options,JointCollectionTpl,ConfigVectorType,TangentVectorType1> Pass1;
209
2912
    for(JointIndex i=1; i<(JointIndex)model.njoints; ++i)
210
    {
211
2795
      Pass1::run(model.joints[i],data.joints[i],
212
                 typename Pass1::ArgsType(model,data,q.derived(),v.derived()));
213
    }
214
215
    typedef AbaBackwardStep<Scalar,Options,JointCollectionTpl> Pass2;
216
2912
    for(JointIndex i=(JointIndex)model.njoints-1;i>0; --i)
217
    {
218
2795
      Pass2::run(model.joints[i],data.joints[i],
219
                 typename Pass2::ArgsType(model,data));
220
    }
221
222
    typedef AbaForwardStep2<Scalar,Options,JointCollectionTpl> Pass3;
223
2912
    for(JointIndex i=1; i<(JointIndex)model.njoints; ++i)
224
    {
225
2795
      Pass3::run(model.joints[i],data.joints[i],
226
                 typename Pass3::ArgsType(model,data));
227
    }
228
229
117
    return data.ddq;
230
  }
231
232
  template<typename Scalar, int Options, template<typename,int> class JointCollectionTpl, typename ConfigVectorType, typename TangentVectorType1, typename TangentVectorType2, typename ForceDerived>
233
  inline const typename DataTpl<Scalar,Options,JointCollectionTpl>::TangentVectorType &
234
99
  aba(const ModelTpl<Scalar,Options,JointCollectionTpl> & model,
235
      DataTpl<Scalar,Options,JointCollectionTpl> & data,
236
      const Eigen::MatrixBase<ConfigVectorType> & q,
237
      const Eigen::MatrixBase<TangentVectorType1> & v,
238
      const Eigen::MatrixBase<TangentVectorType2> & tau,
239
      const container::aligned_vector<ForceDerived> & fext)
240
241
  {
242
99
    assert(model.check(data) && "data is not consistent with model.");
243






99
    PINOCCHIO_CHECK_ARGUMENT_SIZE(q.size(), model.nq, "The joint configuration vector is not of right size");
244






99
    PINOCCHIO_CHECK_ARGUMENT_SIZE(v.size(), model.nv, "The joint velocity vector is not of right size");
245






99
    PINOCCHIO_CHECK_ARGUMENT_SIZE(tau.size(), model.nv, "The joint torque vector is not of right size");
246
247
    typedef typename ModelTpl<Scalar,Options,JointCollectionTpl>::JointIndex JointIndex;
248
249
99
    data.v[0].setZero();
250
99
    data.a_gf[0] = -model.gravity;
251
99
    data.u = tau;
252
253
    typedef AbaForwardStep1<Scalar,Options,JointCollectionTpl,ConfigVectorType,TangentVectorType1> Pass1;
254
2772
    for(JointIndex i=1;i<(JointIndex)model.njoints;++i)
255
    {
256
2673
      Pass1::run(model.joints[i],data.joints[i],
257
                 typename Pass1::ArgsType(model,data,q.derived(),v.derived()));
258
2673
      data.f[i] -= fext[i];
259
    }
260
261
    typedef AbaBackwardStep<Scalar,Options,JointCollectionTpl> Pass2;
262
2772
    for(JointIndex i=(JointIndex)model.njoints-1;i>0; --i)
263
    {
264
2673
      Pass2::run(model.joints[i],data.joints[i],
265
                 typename Pass2::ArgsType(model,data));
266
    }
267
268
    typedef AbaForwardStep2<Scalar,Options,JointCollectionTpl> Pass3;
269
2772
    for(JointIndex i=1; i<(JointIndex)model.njoints; ++i)
270
    {
271
2673
      Pass3::run(model.joints[i],data.joints[i],
272
                 typename Pass3::ArgsType(model,data));
273
    }
274
275
99
    return data.ddq;
276
  }
277
278
  template<typename Scalar, int Options, template<typename,int> class JointCollectionTpl, typename ConfigVectorType>
279
  struct ComputeMinverseForwardStep1
280
  : public fusion::JointUnaryVisitorBase< ComputeMinverseForwardStep1<Scalar,Options,JointCollectionTpl,ConfigVectorType> >
281
  {
282
    typedef ModelTpl<Scalar,Options,JointCollectionTpl> Model;
283
    typedef DataTpl<Scalar,Options,JointCollectionTpl> Data;
284
285
    typedef boost::fusion::vector<const Model &,
286
                                  Data &,
287
                                  const ConfigVectorType &
288
                                  > ArgsType;
289
290
    template<typename JointModel>
291
1242
    static void algo(const pinocchio::JointModelBase<JointModel> & jmodel,
292
                     pinocchio::JointDataBase<typename JointModel::JointDataDerived> & jdata,
293
                     const Model & model,
294
                     Data & data,
295
                     const Eigen::MatrixBase<ConfigVectorType> & q)
296
    {
297
      typedef typename Model::JointIndex JointIndex;
298
299
1242
      const JointIndex & i = jmodel.id();
300
1242
      jmodel.calc(jdata.derived(),q.derived());
301
302
1242
      const JointIndex & parent = model.parents[i];
303

1242
      data.liMi[i] = model.jointPlacements[i] * jdata.M();
304
305
1242
      if (parent>0)
306
1196
        data.oMi[i] = data.oMi[parent] * data.liMi[i];
307
      else
308
46
        data.oMi[i] = data.liMi[i];
309
310
      typedef typename SizeDepType<JointModel::NV>::template ColsReturn<typename Data::Matrix6x>::Type ColsBlock;
311
1242
      ColsBlock J_cols = jmodel.jointCols(data.J);
312

1242
      J_cols = data.oMi[i].act(jdata.S());
313
314
1242
      data.Yaba[i] = model.inertias[i].matrix();
315
    }
316
317
  };
318
319
  template<typename Scalar, int Options, template<typename,int> class JointCollectionTpl>
320
  struct ComputeMinverseBackwardStep
321
  : public fusion::JointUnaryVisitorBase< ComputeMinverseBackwardStep<Scalar,Options,JointCollectionTpl> >
322
  {
323
    typedef ModelTpl<Scalar,Options,JointCollectionTpl> Model;
324
    typedef DataTpl<Scalar,Options,JointCollectionTpl> Data;
325
326
    typedef boost::fusion::vector<const Model &,
327
                                  Data &> ArgsType;
328
329
    template<typename JointModel>
330
1242
    static void algo(const JointModelBase<JointModel> & jmodel,
331
                     JointDataBase<typename JointModel::JointDataDerived> & jdata,
332
                     const Model & model,
333
                     Data & data)
334
    {
335
      typedef typename Model::JointIndex JointIndex;
336
      typedef typename Data::Inertia Inertia;
337
338
1242
      const JointIndex & i = jmodel.id();
339
1242
      const JointIndex & parent  = model.parents[i];
340
341
1242
      typename Inertia::Matrix6 & Ia = data.Yaba[i];
342
1242
      typename Data::RowMatrixXs & Minv = data.Minv;
343
1242
      typename Data::Matrix6x & Fcrb = data.Fcrb[0];
344
1242
      typename Data::Matrix6x & FcrbTmp = data.Fcrb.back();
345
346
1242
      jmodel.calc_aba(jdata.derived(), Ia, parent > 0);
347
348
      typedef typename SizeDepType<JointModel::NV>::template ColsReturn<typename Data::Matrix6x>::Type ColsBlock;
349
350
1242
      ColsBlock U_cols = jmodel.jointCols(data.IS);
351

1242
      forceSet::se3Action(data.oMi[i],jdata.U(),U_cols); // expressed in the world frame
352
353



1242
      Minv.block(jmodel.idx_v(),jmodel.idx_v(),jmodel.nv(),jmodel.nv()) = jdata.Dinv();
354
1242
      const int nv_children = data.nvSubtree[i] - jmodel.nv();
355
1242
      if(nv_children > 0)
356
      {
357
1058
        ColsBlock J_cols = jmodel.jointCols(data.J);
358
1058
        ColsBlock SDinv_cols = jmodel.jointCols(data.SDinv);
359


1058
        SDinv_cols.noalias() = J_cols * jdata.Dinv();
360
361


1058
        Minv.block(jmodel.idx_v(),jmodel.idx_v()+jmodel.nv(),jmodel.nv(),nv_children).noalias()
362




2116
        = -SDinv_cols.transpose() * Fcrb.middleCols(jmodel.idx_v()+jmodel.nv(),nv_children);
363
364
1058
        if(parent > 0)
365
        {
366
1012
          FcrbTmp.leftCols(data.nvSubtree[i]).noalias()
367




2024
          = U_cols * Minv.block(jmodel.idx_v(),jmodel.idx_v(),jmodel.nv(),data.nvSubtree[i]);
368


1012
          Fcrb.middleCols(jmodel.idx_v(),data.nvSubtree[i]) += FcrbTmp.leftCols(data.nvSubtree[i]);
369
        }
370
      }
371
      else
372
      {
373
184
        Fcrb.middleCols(jmodel.idx_v(),data.nvSubtree[i]).noalias()
374




368
        = U_cols * Minv.block(jmodel.idx_v(),jmodel.idx_v(),jmodel.nv(),data.nvSubtree[i]);
375
      }
376
377
1242
      if(parent > 0)
378

1196
        data.Yaba[parent] += internal::SE3actOn<Scalar>::run(data.liMi[i], Ia);
379
    }
380
  };
381
382
  template<typename Scalar, int Options, template<typename,int> class JointCollectionTpl>
383
  struct ComputeMinverseForwardStep2
384
  : public fusion::JointUnaryVisitorBase< ComputeMinverseForwardStep2<Scalar,Options,JointCollectionTpl> >
385
  {
386
    typedef ModelTpl<Scalar,Options,JointCollectionTpl> Model;
387
    typedef DataTpl<Scalar,Options,JointCollectionTpl> Data;
388
389
    typedef boost::fusion::vector<const Model &,
390
                                  Data &> ArgsType;
391
392
    template<typename JointModel>
393
1242
    static void algo(const pinocchio::JointModelBase<JointModel> & jmodel,
394
                     pinocchio::JointDataBase<typename JointModel::JointDataDerived> & jdata,
395
                     const Model & model,
396
                     Data & data)
397
    {
398
      typedef typename Model::JointIndex JointIndex;
399
400
1242
      const JointIndex & i = jmodel.id();
401
1242
      const JointIndex & parent = model.parents[i];
402
1242
      typename Data::RowMatrixXs & Minv = data.Minv;
403
1242
      typename Data::Matrix6x & FcrbTmp = data.Fcrb.back();
404
405
      typedef typename SizeDepType<JointModel::NV>::template ColsReturn<typename Data::Matrix6x>::Type ColsBlock;
406
1242
      ColsBlock UDinv_cols = jmodel.jointCols(data.UDinv);
407

1242
      forceSet::se3Action(data.oMi[i],jdata.UDinv(),UDinv_cols); // expressed in the world frame
408
1242
      ColsBlock J_cols = jmodel.jointCols(data.J);
409
410
1242
      if(parent > 0)
411
      {
412


1196
        FcrbTmp.topRows(jmodel.nv()).rightCols(model.nv - jmodel.idx_v()).noalias()
413



2392
        = UDinv_cols.transpose() * data.Fcrb[parent].rightCols(model.nv - jmodel.idx_v());
414


1196
        Minv.middleRows(jmodel.idx_v(),jmodel.nv()).rightCols(model.nv - jmodel.idx_v())
415



2392
        -= FcrbTmp.topRows(jmodel.nv()).rightCols(model.nv - jmodel.idx_v());
416
      }
417
418





1242
      data.Fcrb[i].rightCols(model.nv - jmodel.idx_v()).noalias() = J_cols * Minv.middleRows(jmodel.idx_v(),jmodel.nv()).rightCols(model.nv - jmodel.idx_v());
419
1242
      if(parent > 0)
420


1196
        data.Fcrb[i].rightCols(model.nv - jmodel.idx_v()) += data.Fcrb[parent].rightCols(model.nv - jmodel.idx_v());
421
    }
422
423
  };
424
425
  template<typename Scalar, int Options, template<typename,int> class JointCollectionTpl, typename ConfigVectorType>
426
  inline const typename DataTpl<Scalar,Options,JointCollectionTpl>::RowMatrixXs &
427
23
  computeMinverse(const ModelTpl<Scalar,Options,JointCollectionTpl> & model,
428
                  DataTpl<Scalar,Options,JointCollectionTpl> & data,
429
                  const Eigen::MatrixBase<ConfigVectorType> & q)
430
  {
431
23
    assert(model.check(data) && "data is not consistent with model.");
432






23
    PINOCCHIO_CHECK_ARGUMENT_SIZE(q.size(), model.nq, "The joint configuration vector is not of right size");
433
434
    typedef typename ModelTpl<Scalar,Options,JointCollectionTpl>::JointIndex JointIndex;
435
23
    data.Minv.template triangularView<Eigen::Upper>().setZero();
436
437
    typedef ComputeMinverseForwardStep1<Scalar,Options,JointCollectionTpl,ConfigVectorType> Pass1;
438
644
    for(JointIndex i=1; i<(JointIndex)model.njoints; ++i)
439
    {
440
621
      Pass1::run(model.joints[i],data.joints[i],
441
                 typename Pass1::ArgsType(model,data,q.derived()));
442
    }
443
444
23
    data.Fcrb[0].setZero();
445
    typedef ComputeMinverseBackwardStep<Scalar,Options,JointCollectionTpl> Pass2;
446
644
    for(JointIndex i=(JointIndex)model.njoints-1; i>0; --i)
447
    {
448
621
      Pass2::run(model.joints[i],data.joints[i],
449
                 typename Pass2::ArgsType(model,data));
450
    }
451
452
    typedef ComputeMinverseForwardStep2<Scalar,Options,JointCollectionTpl> Pass3;
453
644
    for(JointIndex i=1; i<(JointIndex)model.njoints; ++i)
454
    {
455
621
      Pass3::run(model.joints[i],data.joints[i],
456
                 typename Pass3::ArgsType(model,data));
457
    }
458
459
23
    return data.Minv;
460
  }
461
462
463
  // --- CHECKER ---------------------------------------------------------------
464
  // --- CHECKER ---------------------------------------------------------------
465
  // --- CHECKER ---------------------------------------------------------------
466
467
  // Check whether all masses are nonzero and diagonal of inertia is nonzero
468
  // The second test is overconstraining.
469
  template<typename Scalar, int Options, template<typename,int> class JointCollectionTpl>
470
3
  inline bool ABAChecker::checkModel_impl(const ModelTpl<Scalar,Options,JointCollectionTpl> & model) const
471
  {
472
    typedef ModelTpl<Scalar,Options,JointCollectionTpl> Model;
473
    typedef typename Model::JointIndex JointIndex;
474
475
57
    for(JointIndex j=1;j<(JointIndex)model.njoints;j++)
476
55
      if(    (model.inertias[j].mass   ()           < 1e-5)
477
55
          || (model.inertias[j].inertia().data()[0] < 1e-5)
478
54
          || (model.inertias[j].inertia().data()[2] < 1e-5)
479

110
          || (model.inertias[j].inertia().data()[5] < 1e-5) )
480
1
        return false;
481
2
    return true;
482
  }
483
484
} // namespace pinocchio
485
486
/// @endcond
487
488
#endif // ifndef __pinocchio_aba_hxx__