GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: include/pinocchio/multibody/model.hpp Lines: 109 127 85.8 %
Date: 2024-04-26 13:14:21 Branches: 207 383 54.0 %

Line Branch Exec Source
1
//
2
// Copyright (c) 2015-2020 CNRS INRIA
3
// Copyright (c) 2015 Wandercraft, 86 rue de Paris 91400 Orsay, France.
4
//
5
6
#ifndef __pinocchio_multibody_model_hpp__
7
#define __pinocchio_multibody_model_hpp__
8
9
#include "pinocchio/spatial/fwd.hpp"
10
#include "pinocchio/spatial/se3.hpp"
11
#include "pinocchio/spatial/force.hpp"
12
#include "pinocchio/spatial/motion.hpp"
13
#include "pinocchio/spatial/inertia.hpp"
14
15
#include "pinocchio/multibody/fwd.hpp"
16
#include "pinocchio/multibody/frame.hpp"
17
#include "pinocchio/multibody/joint/joint-generic.hpp"
18
19
#include "pinocchio/container/aligned-vector.hpp"
20
21
#include "pinocchio/serialization/serializable.hpp"
22
23
#include <iostream>
24
#include <map>
25
#include <iterator>
26
27
namespace pinocchio
28
{
29
30
  template<typename _Scalar, int _Options, template<typename,int> class JointCollectionTpl>
31
  struct ModelTpl
32
  : serialization::Serializable< ModelTpl<_Scalar,_Options,JointCollectionTpl> >
33
  {
34
    EIGEN_MAKE_ALIGNED_OPERATOR_NEW
35
36
    typedef _Scalar Scalar;
37
    enum { Options = _Options };
38
39
    typedef JointCollectionTpl<Scalar,Options> JointCollection;
40
    typedef DataTpl<Scalar,Options,JointCollectionTpl> Data;
41
42
    typedef SE3Tpl<Scalar,Options> SE3;
43
    typedef MotionTpl<Scalar,Options> Motion;
44
    typedef ForceTpl<Scalar,Options> Force;
45
    typedef InertiaTpl<Scalar,Options> Inertia;
46
    typedef FrameTpl<Scalar,Options> Frame;
47
48
    typedef pinocchio::Index Index;
49
    typedef pinocchio::JointIndex JointIndex;
50
    typedef pinocchio::GeomIndex GeomIndex;
51
    typedef pinocchio::FrameIndex FrameIndex;
52
    typedef std::vector<Index> IndexVector;
53
54
    typedef JointModelTpl<Scalar,Options,JointCollectionTpl> JointModel;
55
    typedef JointDataTpl<Scalar,Options,JointCollectionTpl> JointData;
56
57
    typedef PINOCCHIO_ALIGNED_STD_VECTOR(JointModel) JointModelVector;
58
    typedef PINOCCHIO_ALIGNED_STD_VECTOR(JointData) JointDataVector;
59
60
    typedef PINOCCHIO_ALIGNED_STD_VECTOR(Frame) FrameVector;
61
62
    typedef Eigen::Matrix<Scalar,Eigen::Dynamic,1,Options> VectorXs;
63
    typedef Eigen::Matrix<Scalar,3,1,Options> Vector3;
64
65
    /// \brief Dense vectorized version of a joint configuration vector.
66
    typedef VectorXs ConfigVectorType;
67
68
    /// \brief Map between a string (key) and a configuration vector
69
    typedef std::map<std::string, ConfigVectorType>  ConfigVectorMap;
70
71
    /// \brief Dense vectorized version of a joint tangent vector (e.g. velocity, acceleration, etc).
72
    ///        It also handles the notion of co-tangent vector (e.g. torque, etc).
73
    typedef VectorXs TangentVectorType;
74
75
    /// \brief Dimension of the configuration vector representation.
76
    int nq;
77
78
    /// \brief Dimension of the velocity vector space.
79
    int nv;
80
81
    /// \brief Number of joints.
82
    int njoints;
83
84
    /// \brief Number of bodies.
85
    int nbodies;
86
87
    /// \brief Number of operational frames.
88
    int nframes;
89
90
    /// \brief Spatial inertias of the body *i* expressed in the supporting joint frame *i*.
91
    PINOCCHIO_ALIGNED_STD_VECTOR(Inertia) inertias;
92
93
    /// \brief Placement (SE3) of the input of joint *i* regarding to the parent joint output *li*.
94
    PINOCCHIO_ALIGNED_STD_VECTOR(SE3) jointPlacements;
95
96
    /// \brief Model of joint *i*, encapsulated in a JointModelAccessor.
97
    JointModelVector joints;
98
99
    /// \brief Starting index of the joint *i* in the configuration space
100
    std::vector<int> idx_qs;
101
102
    /// \brief Dimension of the joint *i* configuration subspace
103
    std::vector<int> nqs;
104
105
    /// \brief Starting index of the joint *i* in the tangent configuration space
106
    std::vector<int> idx_vs;
107
108
    /// \brief Dimension of the joint *i* tangent subspace
109
    std::vector<int> nvs;
110
111
    /// \brief Joint parent of joint *i*, denoted *li* (li==parents[i]).
112
    std::vector<JointIndex> parents;
113
114
    /// \brief Name of joint *i*
115
    std::vector<std::string> names;
116
117
    /// \brief Map of reference configurations, indexed by user given names.
118
    ConfigVectorMap referenceConfigurations;
119
120
    /// \brief Vector of rotor inertia parameters
121
    TangentVectorType rotorInertia;
122
123
    /// \brief Vector of rotor gear ratio parameters
124
    TangentVectorType rotorGearRatio;
125
126
    /// \brief Vector of joint friction parameters
127
    TangentVectorType friction;
128
129
    /// \brief Vector of joint damping parameters
130
    TangentVectorType damping;
131
132
    /// \brief Vector of maximal joint torques
133
    TangentVectorType effortLimit;
134
135
    /// \brief Vector of maximal joint velocities
136
    TangentVectorType velocityLimit;
137
138
    /// \brief Lower joint configuration limit
139
    ConfigVectorType lowerPositionLimit;
140
141
    /// \brief Upper joint configuration limit
142
    ConfigVectorType upperPositionLimit;
143
144
    /// \brief Vector of operational frames registered on the model.
145
    FrameVector frames;
146
147
    /// \brief Vector of joint supports.
148
    /// supports[j] corresponds to the vector of indices of the joints located on the path between
149
    /// joint *j*  and "universe".
150
    /// The first element of supports[j] is "universe", the last one is the index of joint *j*
151
    /// itself.
152
    std::vector<IndexVector> supports;
153
154
    /// \brief Vector of joint subtrees.
155
    /// subtree[j] corresponds to the subtree supported by the joint *j*.
156
    /// The first element of subtree[j] is the index of the joint *j* itself.
157
    std::vector<IndexVector> subtrees;
158
159
    /// \brief Spatial gravity of the model.
160
    Motion gravity;
161
162
    /// \brief Default 3D gravity vector (=(0,0,-9.81)).
163
    static const Vector3 gravity981;
164
165
    /// \brief Model name;
166
    std::string name;
167
168
    /// \brief Default constructor. Builds an empty model with no joints.
169
605
    ModelTpl()
170
    : nq(0)
171
    , nv(0)
172
    , njoints(1)
173
    , nbodies(1)
174
    , nframes(0)
175
    , inertias(1, Inertia::Zero())
176
    , jointPlacements(1, SE3::Identity())
177
    , joints(1)
178
    , idx_qs(1,0)
179
    , nqs(1,0)
180
    , idx_vs(1,0)
181
    , nvs(1,0)
182
    , parents(1, 0)
183
    , names(1)
184
    , supports(1,IndexVector(1,0))
185
    , subtrees(1)
186











605
    , gravity(gravity981,Vector3::Zero())
187
    {
188
605
      names[0]     = "universe";     // Should be "universe joint (trivial)"
189
      // FIXME Should the universe joint be a FIXED_JOINT even if it is
190
      // in the list of joints ? See comment in definition of
191
      // Model::addJointFrame and Model::addBodyFrame
192


605
      addFrame(Frame("universe", 0, 0, SE3::Identity(), FIXED_JOINT));
193
605
    }
194
836
    ~ModelTpl() {} // std::cout << "Destroy model" << std::endl; }
195
196
    /// \returns An expression of *this with the Scalar type casted to NewScalar.
197
    template<typename NewScalar>
198
10
    ModelTpl<NewScalar,Options,JointCollectionTpl> cast() const
199
    {
200
      typedef ModelTpl<NewScalar,Options,JointCollectionTpl> ReturnType;
201
10
      ReturnType res;
202
10
      res.nq = nq; res.nv = nv;
203
10
      res.njoints = njoints;
204
10
      res.nbodies = nbodies;
205
10
      res.nframes = nframes;
206
10
      res.parents = parents;
207
10
      res.names = names;
208
10
      res.supports = supports;
209
10
      res.subtrees = subtrees;
210
10
      res.gravity = gravity.template cast<NewScalar>();
211
10
      res.name = name;
212
213
10
      res.idx_qs = idx_qs;
214
10
      res.nqs = nqs;
215
10
      res.idx_vs = idx_vs;
216
10
      res.nvs = nvs;
217
218
      // Eigen Vectors
219

10
      res.rotorInertia = rotorInertia.template cast<NewScalar>();
220

10
      res.rotorGearRatio = rotorGearRatio.template cast<NewScalar>();
221

10
      res.friction = friction.template cast<NewScalar>();
222

10
      res.damping = damping.template cast<NewScalar>();
223

10
      res.effortLimit = effortLimit.template cast<NewScalar>();
224

10
      res.velocityLimit = velocityLimit.template cast<NewScalar>();
225

10
      res.lowerPositionLimit = lowerPositionLimit.template cast<NewScalar>();
226

10
      res.upperPositionLimit = upperPositionLimit.template cast<NewScalar>();
227
228
10
      typename ConfigVectorMap::const_iterator it;
229
10
      for (it = referenceConfigurations.begin();
230
10
           it != referenceConfigurations.end(); it++ )
231
      {
232
        res.referenceConfigurations.insert(std::make_pair(it->first, it->second.template cast<NewScalar>()));
233
      }
234
235
      // reserve vectors
236
10
      res.inertias.resize(inertias.size());
237
10
      res.jointPlacements.resize(jointPlacements.size());
238
10
      res.joints.resize(joints.size());
239
10
      res.frames.resize(frames.size());
240
241
      /// copy into vectors
242
290
      for(size_t k = 0; k < joints.size(); ++k)
243
      {
244

280
        res.inertias[k] = inertias[k].template cast<NewScalar>();
245
280
        res.jointPlacements[k] = jointPlacements[k].template cast<NewScalar>();
246

280
        res.joints[k] = joints[k].template cast<NewScalar>();
247
      }
248
249
560
      for(size_t k = 0; k < frames.size(); ++k)
250
      {
251

550
        res.frames[k] = frames[k].template cast<NewScalar>();
252
      }
253
254
20
      return res;
255
    }
256
257
    ///
258
    /// \brief Equality comparison operator.
259
    ///
260
    /// \returns true if *this is equal to other.
261
    ///
262
75
    bool operator==(const ModelTpl & other) const
263
    {
264
75
      bool res =
265
75
         other.nq == nq
266
73
      && other.nv == nv
267
73
      && other.njoints == njoints
268
73
      && other.nbodies == nbodies
269
73
      && other.nframes == nframes
270

73
      && other.parents == parents
271

73
      && other.names == names
272

73
      && other.subtrees == subtrees
273

73
      && other.gravity == gravity
274

148
      && other.name == name;
275
276
75
      res &=
277
75
         other.idx_qs == idx_qs
278

73
      && other.nqs == nqs
279

73
      && other.idx_vs == idx_vs
280

148
      && other.nvs == nvs;
281
282
75
      if(other.referenceConfigurations.size() != referenceConfigurations.size())
283
        return false;
284
285
75
      typename ConfigVectorMap::const_iterator it = referenceConfigurations.begin();
286
75
      typename ConfigVectorMap::const_iterator it_other = other.referenceConfigurations.begin();
287
81
      for(long k = 0; k < (long)referenceConfigurations.size(); ++k)
288
      {
289

8
        std::advance(it,k); std::advance(it_other,k);
290
291

8
        if(it->second.size() != it_other->second.size())
292
2
          return false;
293

6
        if(it->second != it_other->second)
294
          return false;
295
      }
296
297

73
      if(other.rotorInertia.size() != rotorInertia.size())
298
        return false;
299
73
      res &= other.rotorInertia == rotorInertia;
300
73
      if(!res) return res;
301
302

73
      if(other.friction.size() != friction.size())
303
        return false;
304
73
      res &= other.friction == friction;
305
73
      if(!res) return res;
306
307

73
      if(other.damping.size() != damping.size())
308
        return false;
309
73
      res &= other.damping == damping;
310
73
      if(!res) return res;
311
312

73
      if(other.rotorGearRatio.size() != rotorGearRatio.size())
313
        return false;
314
73
      res &= other.rotorGearRatio == rotorGearRatio;
315
73
      if(!res) return res;
316
317

73
      if(other.effortLimit.size() != effortLimit.size())
318
        return false;
319
73
      res &= other.effortLimit == effortLimit;
320
73
      if(!res) return res;
321
322

73
      if(other.velocityLimit.size() != velocityLimit.size())
323
        return false;
324
73
      res &= other.velocityLimit == velocityLimit;
325
73
      if(!res) return res;
326
327

73
      if(other.lowerPositionLimit.size() != lowerPositionLimit.size())
328
        return false;
329
73
      res &= other.lowerPositionLimit == lowerPositionLimit;
330
73
      if(!res) return res;
331
332

73
      if(other.upperPositionLimit.size() != upperPositionLimit.size())
333
        return false;
334
73
      res &= other.upperPositionLimit == upperPositionLimit;
335
73
      if(!res) return res;
336
337
2232
      for(size_t k = 1; k < inertias.size(); ++k)
338
      {
339
2159
        res &= other.inertias[k] == inertias[k];
340
2159
        if(!res) return res;
341
      }
342
343
2232
      for(size_t k = 1; k < other.jointPlacements.size(); ++k)
344
      {
345
2159
        res &= other.jointPlacements[k] == jointPlacements[k];
346
2159
        if(!res) return res;
347
      }
348
349
73
      res &=
350
73
         other.joints == joints
351

73
      && other.frames == frames;
352
353
73
      return res;
354
    }
355
356
    ///
357
    /// \returns true if *this is NOT equal to other.
358
    ///
359
1
    bool operator!=(const ModelTpl & other) const
360
1
    { return !(*this == other); }
361
362
    ///
363
    /// \brief Add a joint to the kinematic tree with infinite bounds.
364
    ///
365
    /// \remark This method also adds a Frame of same name to the vector of frames.
366
    /// \remark The inertia supported by the joint is set to Zero.
367
    /// \remark Joints need to be added to the tree in a depth-first order.
368
    ///
369
    /// \tparam JointModelDerived The type of the joint model.
370
    ///
371
    /// \param[in] parent Index of the parent joint.
372
    /// \param[in] joint_model The joint model.
373
    /// \param[in] joint_placement Placement of the joint inside its parent joint.
374
    /// \param[in] joint_name Name of the joint. If empty, the name is random.
375
    ///
376
    /// \return The index of the new joint.
377
    ///
378
    /// \sa Model::appendBodyToJoint
379
    ///
380
    JointIndex addJoint(const JointIndex parent,
381
                        const JointModel & joint_model,
382
                        const SE3 & joint_placement,
383
                        const std::string & joint_name);
384
385
    ///
386
    /// \copydoc ModelTpl::addJoint(const JointIndex,const JointModel &,const SE3 &,const std::string &)
387
    ///
388
    /// \param[in] max_effort Maximal joint torque.
389
    /// \param[in] max_velocity Maximal joint velocity.
390
    /// \param[in] min_config Lower joint configuration.
391
    /// \param[in] max_config Upper joint configuration.
392
    ///
393
    JointIndex addJoint(const JointIndex parent,
394
                        const JointModel & joint_model,
395
                        const SE3 & joint_placement,
396
                        const std::string & joint_name,
397
                        const VectorXs & max_effort,
398
                        const VectorXs & max_velocity,
399
                        const VectorXs & min_config,
400
                        const VectorXs & max_config);
401
402
    ///
403
    /// \copydoc ModelTpl::addJoint(const JointIndex,const JointModel &,const SE3 &,const std::string &,const VectorXs &,const VectorXs &,const VectorXs &,const VectorXs &)
404
    ///
405
    /// \param[in] friction Joint friction parameters.
406
    /// \param[in] damping Joint damping parameters.
407
    ///
408
    JointIndex addJoint(const JointIndex parent,
409
                        const JointModel & joint_model,
410
                        const SE3 & joint_placement,
411
                        const std::string & joint_name,
412
                        const VectorXs & max_effort,
413
                        const VectorXs & max_velocity,
414
                        const VectorXs & min_config,
415
                        const VectorXs & max_config,
416
                        const VectorXs & friction,
417
                        const VectorXs & damping);
418
419
    ///
420
    /// \brief Add a joint to the frame tree.
421
    ///
422
    /// \param[in] jointIndex Index of the joint.
423
    /// \param[in] frameIndex Index of the parent frame. If negative,
424
    ///            the parent frame is the frame of the parent joint.
425
    ///
426
    /// \return The index of the new frame
427
    ///
428
    FrameIndex addJointFrame(const JointIndex & joint_index,
429
                             int previous_frame_index = -1);
430
431
    ///
432
    /// \brief Append a body to a given joint of the kinematic tree.
433
    ///
434
    /// \param[in] joint_index Index of the supporting joint.
435
    /// \param[in] Y Spatial inertia of the body.
436
    /// \param[in] body_placement The relative placement of the body regarding to the parent joint. Set default to the Identity placement.
437
    ///
438
    /// \sa Model::addJoint
439
    ///
440
    void appendBodyToJoint(const JointIndex joint_index, const Inertia & Y,
441
                           const SE3 & body_placement = SE3::Identity());
442
443
    ///
444
    /// \brief Add a body to the frame tree.
445
    ///
446
    /// \param[in] body_name Name of the body.
447
    /// \param[in] parentJoint Index of the parent joint.
448
    /// \param[in] body_placement The relative placement of the body regarding to the parent joint. Set default to the Identity placement.
449
    /// \param[in] previousFrame Index of the parent frame. If negative,
450
    ///            the parent frame is the frame of the parent joint.
451
    ///
452
    /// \return The index of the new frame
453
    ///
454
    FrameIndex addBodyFrame(const std::string & body_name,
455
                            const JointIndex  & parentJoint,
456
                            const SE3         & body_placement = SE3::Identity(),
457
                            int                 previousFrame  = -1);
458
459
    ///
460
    /// \brief Return the index of a body given by its name.
461
    ///
462
    /// \warning If no body is found, return the number of elements at time T.
463
    /// This can lead to errors if the model is expanded after this method is called
464
    /// (for example to get the id of a parent body)
465
    ///
466
    /// \param[in] name Name of the body.
467
    ///
468
    /// \return Index of the body.
469
    ///
470
    FrameIndex getBodyId(const std::string & name) const;
471
472
    ///
473
    /// \brief Check if a body given by its name exists.
474
    ///
475
    /// \param[in] name Name of the body.
476
    ///
477
    /// \return True if the body exists in the kinematic tree.
478
    ///
479
    bool existBodyName(const std::string & name) const;
480
481
482
    ///
483
    /// \brief Return the index of a joint given by its name.
484
    ///
485
    /// \warning If no joint is found, return the number of elements at time T.
486
    /// This can lead to errors if the model is expanded after this method is called
487
    /// (for example to get the id of a parent joint)
488
    /// \param[in] name Name of the joint.
489
    ///
490
    /// \return Index of the joint.
491
    ///
492
    JointIndex getJointId(const std::string & name) const;
493
494
    ///
495
    /// \brief Check if a joint given by its name exists.
496
    ///
497
    /// \param[in] name Name of the joint.
498
    ///
499
    /// \return True if the joint exists in the kinematic tree.
500
    ///
501
    bool existJointName(const std::string & name) const;
502
503
    ///
504
    /// \brief Returns the index of a frame given by its name.
505
    ///        \sa Model::existFrame to check if the frame exists or not.
506
    ///
507
    /// \warning If no frame is found, returns the size of the vector of Model::frames.
508
    /// This can lead to errors if the model is expanded after this method is called
509
    /// (for example to get the id of a parent frame).
510
    ///
511
    /// \param[in] name Name of the frame.
512
    /// \param[in] type Type of the frame.
513
    ///
514
    /// \return Index of the frame.
515
    ///
516
    FrameIndex getFrameId(const std::string & name,
517













3037
                          const FrameType & type = (FrameType) (JOINT | FIXED_JOINT | BODY | OP_FRAME | SENSOR )) const;
518
519
    ///
520
    /// \brief Checks if a frame given by its name exists.
521
    ///
522
    /// \param[in] name Name of the frame.
523
    /// \param[in] type Type of the frame.
524
    ///
525
    /// \return Returns true if the frame exists.
526
    ///
527
    bool existFrame(const std::string & name,
528





207
                    const FrameType& type = (FrameType) (JOINT | FIXED_JOINT | BODY | OP_FRAME | SENSOR )) const;
529
530
    ///
531
    /// \brief Adds a frame to the kinematic tree.
532
    ///        The inertia stored within the frame will be happened to the inertia supported by the joint (frame.parent).
533
    ///
534
    /// \param[in] frame The frame to add to the kinematic tree.
535
    /// \param[in] append_inertia Append the inertia contained in the Frame to the inertia supported by the joint.
536
    ///
537
    /// \return Returns the index of the frame if it has been successfully added or if it already exists in the kinematic tree.
538
    ///
539
    FrameIndex addFrame(const Frame & frame,
540
                        const bool append_inertia = true);
541
542
    ///
543
    /// \brief Check the validity of the attributes of Model with respect to the specification of some
544
    /// algorithms.
545
    ///
546
    /// The method is a template so that the checkers can be defined in each algorithms.
547
    /// \param[in] checker a class, typically defined in the algorithm module, that
548
    /// validates the attributes of model.
549
    ///
550
    /// \return true if the Model is valid, false otherwise.
551
    ///
552
    template<typename D>
553
12
    inline bool check(const AlgorithmCheckerBase<D> & checker = AlgorithmCheckerBase<D>()) const
554
12
    { return checker.checkModel(*this); }
555
556
    ///
557
    /// \brief Check if joints have configuration limits
558
    ///
559
    /// \return Returns list of boolean of size model.nq.
560
    ///
561
    std::vector<bool> hasConfigurationLimit();
562
563
    ///
564
    /// \brief Check if joints have configuration limits
565
    ///
566
    /// \return Returns list of boolean of size model.nq.
567
    ///
568
    std::vector<bool> hasConfigurationLimitInTangent();
569
570
    /// Run check(fusion::list) with DEFAULT_CHECKERS as argument.
571
    inline bool check() const;
572
573
    ///
574
    /// \brief Run checkData on data and current model.
575
    ///
576
    /// \param[in] data to be checked wrt *this.
577
    ///
578
    /// \return true if the data is valid, false otherwise.
579
    ///
580
    inline bool check(const Data & data) const;
581
582
  protected:
583
584
    ///
585
    /// \brief Add the joint_id to its parent subtrees.
586
    ///
587
    /// \param[in] joint_id The id of the joint to add to the subtrees
588
    ///
589
    void addJointIndexToParentSubtrees(const JointIndex joint_id);
590
  };
591
592
} // namespace pinocchio
593
594
/* --- Details -------------------------------------------------------------- */
595
/* --- Details -------------------------------------------------------------- */
596
/* --- Details -------------------------------------------------------------- */
597
#include "pinocchio/multibody/model.hxx"
598
599
#endif // ifndef __pinocchio_multibody_model_hpp__