GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: include/pinocchio/algorithm/model.hxx Lines: 252 256 98.4 %
Date: 2024-01-23 21:41:47 Branches: 258 476 54.2 %

Line Branch Exec Source
1
//
2
// Copyright (c) 2019-2022 CNRS INRIA
3
//
4
5
#ifndef __pinocchio_algorithm_model_hxx__
6
#define __pinocchio_algorithm_model_hxx__
7
8
#include <algorithm>
9
10
namespace pinocchio
11
{
12
  namespace details
13
  {
14
15
    // Retrieve the joint id in model_out, given the info of model_in.
16
    // If the user change all the joint names, the universe name won't correspond to the first joint in the tree when searching by name.
17
    // We thus need to retrieve it with other means, e.g. checking the index of the joints.
18
    template<typename Scalar, int Options, template<typename,int> class JointCollectionTpl>
19
203
    JointIndex getJointId(const ModelTpl<Scalar,Options,JointCollectionTpl> & model_in,
20
                          const ModelTpl<Scalar,Options,JointCollectionTpl> & model_out,
21
                          const std::string & joint_name_in_model_in)
22
    {
23
203
      const JointIndex joint_id = model_in.getJointId(joint_name_in_model_in);
24
203
      assert(joint_id < model_in.joints.size());
25

203
      if(joint_id == 0 && model_in.parents[0] == 0) // This is the universe, maybe renamed.
26
        return model_out.getJointId(model_out.names[0]);
27
      else
28
203
        return model_out.getJointId(joint_name_in_model_in);
29
    }
30
31
    // Retrieve the frame id in model_out, given the info of model_in.
32
    // If the user change all the frame names, the universe name won't correspond to the first frame in the tree when searching by name.
33
    // We thus need to retrieve it with other means, e.g. checking the fields of the frames.
34
    template<typename Scalar, int Options, template<typename,int> class JointCollectionTpl>
35
536
    FrameIndex getFrameId(const ModelTpl<Scalar,Options,JointCollectionTpl> & model_in,
36
                          const ModelTpl<Scalar,Options,JointCollectionTpl> & model_out,
37
                          const std::string & frame_name_in_model_in,
38
                          const FrameType & type)
39
    {
40
536
      const FrameIndex frame_id = model_in.getFrameId(frame_name_in_model_in);
41
536
      assert(frame_id < model_in.frames.size());
42


536
      if(frame_id == 0 && model_in.frames[0].previousFrame == 0 && model_in.frames[0].parent == 0) // This is the universe, maybe renamed.
43
3
        return model_out.getFrameId(model_out.frames[0].name,type);
44
      else
45
533
        return model_out.getFrameId(frame_name_in_model_in,type);
46
    }
47
48
    template<typename Scalar, int Options, template<typename,int> class JointCollectionTpl>
49
14
    void appendUniverseToModel(const ModelTpl<Scalar,Options,JointCollectionTpl> & modelAB,
50
                               const GeometryModel & geomModelAB,
51
                               FrameIndex parentFrame,
52
                               const SE3Tpl<Scalar, Options> & pfMAB,
53
                               ModelTpl<Scalar,Options,JointCollectionTpl> & model,
54
                               GeometryModel & geomModel)
55
    {
56
      typedef ModelTpl<Scalar,Options,JointCollectionTpl> Model;
57
      typedef typename Model::Frame Frame;
58
59

14
      PINOCCHIO_THROW(parentFrame < model.frames.size(),
60
                      std::invalid_argument,
61
                      "parentFrame is greater than the size of the frames vector.");
62
63
14
      const Frame & pframe = model.frames[parentFrame];
64
14
      JointIndex jid = pframe.parent;
65
14
      assert(jid < model.joints.size());
66
67
      // If inertia is not NaN, add it.
68
14
      if (modelAB.inertias[0] == modelAB.inertias[0])
69
14
        model.appendBodyToJoint (jid, modelAB.inertias[0], pframe.placement * pfMAB);
70
71
      // Add all frames whose parent is this joint.
72
483
      for (FrameIndex fid = 1; fid < modelAB.frames.size(); ++fid)
73
      {
74
938
        Frame frame = modelAB.frames[fid];
75
469
        if (frame.parent == 0)
76
        {
77

6
          PINOCCHIO_CHECK_INPUT_ARGUMENT(!model.existFrame(frame.name, frame.type),
78
                                         "The two models have conflicting frame names.");
79
80
6
          frame.parent = jid;
81
6
          if (frame.previousFrame != 0)
82
          {
83
5
            frame.previousFrame = getFrameId(modelAB,model,modelAB.frames[frame.previousFrame].name,
84
5
                                             modelAB.frames[frame.previousFrame].type);
85
          }
86
          else
87
          {
88
1
            frame.previousFrame = parentFrame;
89
          }
90
91
          // Modify frame placement
92

6
          frame.placement = pframe.placement * pfMAB * frame.placement;
93
6
          model.addFrame (frame);
94
        }
95
      }
96
97
      // Add all geometries whose parent is this joint.
98
89
      for (GeomIndex gid = 0; gid < geomModelAB.geometryObjects.size(); ++gid)
99
      {
100
150
        GeometryObject go = geomModelAB.geometryObjects[gid];
101
75
        if (go.parentJoint == 0)
102
        {
103
1
          go.parentJoint = jid;
104
1
          if (go.parentFrame != 0)
105
          {
106
1
            go.parentFrame = getFrameId(modelAB,model,modelAB.frames[go.parentFrame].name,
107
1
                                        modelAB.frames[go.parentFrame].type);
108
          }
109
          else
110
          {
111
            go.parentFrame = parentFrame;
112
          }
113

1
          go.placement = pframe.placement * pfMAB * go.placement;
114
1
          geomModel.addGeometryObject (go);
115
        }
116
      }
117
14
    }
118
119
    template<typename Scalar, int Options, template<typename,int> class JointCollectionTpl>
120
    struct AppendJointOfModelAlgoTpl
121
    : public fusion::JointUnaryVisitorBase< AppendJointOfModelAlgoTpl<Scalar,Options,JointCollectionTpl> >
122
    {
123
124
      typedef ModelTpl<Scalar,Options,JointCollectionTpl> Model;
125
      typedef typename Model::Frame Frame;
126
127
      typedef boost::fusion::vector<
128
      const Model &,
129
      const GeometryModel&,
130
      JointIndex,
131
      const typename Model::SE3 &,
132
      Model &,
133
      GeometryModel& > ArgsType;
134
135
      template <typename JointModel>
136
434
      static void algo (const JointModelBase<JointModel> & jmodel_in,
137
                        const Model & modelAB,
138
                        const GeometryModel & geomModelAB,
139
                        JointIndex parent_id,
140
                        const typename Model::SE3 & pMi,
141
                        Model & model,
142
                        GeometryModel & geomModel)
143
      {
144
        // If old parent is universe, use what's provided in the input.
145
        // otherwise, get the parent from modelAB.
146
434
        const JointIndex joint_id_in = jmodel_in.id();
147
434
        if (modelAB.parents[joint_id_in] > 0)
148
406
          parent_id = getJointId(modelAB,model,modelAB.names[modelAB.parents[joint_id_in]]);
149
150

434
        PINOCCHIO_CHECK_INPUT_ARGUMENT(!model.existJointName(modelAB.names[joint_id_in]),
151
                                       "The two models have conflicting joint names.");
152
153




3038
        JointIndex joint_id_out = model.addJoint(parent_id,
154
                                                 jmodel_in,
155
434
                                                 pMi * modelAB.jointPlacements[joint_id_in],
156
434
                                                 modelAB.names[joint_id_in],
157
434
                                                 jmodel_in.jointVelocitySelector(modelAB.effortLimit),
158
434
                                                 jmodel_in.jointVelocitySelector(modelAB.velocityLimit),
159
434
                                                 jmodel_in.jointConfigSelector(modelAB.lowerPositionLimit),
160
434
                                                 jmodel_in.jointConfigSelector(modelAB.upperPositionLimit),
161
434
                                                 jmodel_in.jointVelocitySelector(modelAB.friction),
162
434
                                                 jmodel_in.jointVelocitySelector(modelAB.damping));
163
434
        assert(joint_id_out < model.joints.size());
164
165
434
        model.appendBodyToJoint(joint_id_out, modelAB.inertias[joint_id_in]);
166
167
434
        const typename Model::JointModel & jmodel_out = model.joints[joint_id_out];
168

434
        jmodel_out.jointVelocitySelector(model.rotorInertia) = jmodel_in.jointVelocitySelector(modelAB.rotorInertia);
169

434
        jmodel_out.jointVelocitySelector(model.rotorGearRatio) = jmodel_in.jointVelocitySelector(modelAB.rotorGearRatio);
170
171
        // Add all frames whose parent is this joint.
172
23036
        for (FrameIndex fid = 1; fid < modelAB.frames.size(); ++fid)
173
        {
174
45204
          Frame frame = modelAB.frames[fid];
175

22602
          if (frame.parent == jmodel_in.id())
176
          {
177

926
            PINOCCHIO_CHECK_INPUT_ARGUMENT(!model.existFrame(frame.name, frame.type),
178
                                           "The two models have conflicting frame names.");
179
180
926
            frame.parent = joint_id_out;
181

926
            assert (frame.previousFrame > 0 || frame.type == JOINT);
182
926
            if (frame.previousFrame != 0)
183
            {
184
902
              frame.previousFrame = getFrameId(modelAB,model,modelAB.frames[frame.previousFrame].name,modelAB.frames[frame.previousFrame].type);
185
            }
186
187
926
            model.addFrame(frame);
188
          }
189
        }
190
        // Add all geometries whose parent is this joint.
191
3798
        for(GeomIndex gid = 0; gid < geomModelAB.geometryObjects.size(); ++gid)
192
        {
193
6728
          GeometryObject go = geomModelAB.geometryObjects[gid];
194
3364
          if(go.parentJoint == joint_id_in)
195
          {
196
148
            go.parentJoint = joint_id_out;
197
148
            assert(go.parentFrame > 0);
198

148
            if(go.parentFrame != 0 && go.parentFrame < modelAB.frames.size())
199
            {
200
144
              go.parentFrame = getFrameId(modelAB,model,modelAB.frames[go.parentFrame].name,modelAB.frames[go.parentFrame].type);
201
            }
202
148
            geomModel.addGeometryObject(go);
203
          }
204
        }
205
      }
206
    };
207
208
  } // namespace details
209
210
  template<typename Scalar, int Options, template<typename,int> class JointCollectionTpl>
211
  void
212
4
  appendModel(const ModelTpl<Scalar,Options,JointCollectionTpl> & modelA,
213
              const ModelTpl<Scalar,Options,JointCollectionTpl> & modelB,
214
              const FrameIndex frameInModelA,
215
              const SE3Tpl<Scalar, Options> & aMb,
216
              ModelTpl<Scalar,Options,JointCollectionTpl> & model)
217
  {
218

8
    GeometryModel geomModelA, geomModelB, geomModel;
219
220
4
    appendModel(modelA, modelB, geomModelA, geomModelB, frameInModelA, aMb,
221
         model, geomModel);
222
4
  }
223
224
  template<typename Scalar, int Options, template<typename,int> class JointCollectionTpl>
225
  void
226
7
  appendModel(const ModelTpl<Scalar,Options,JointCollectionTpl> & modelA,
227
              const ModelTpl<Scalar,Options,JointCollectionTpl> & modelB,
228
              const GeometryModel& geomModelA,
229
              const GeometryModel& geomModelB,
230
              const FrameIndex frameInModelA,
231
              const SE3Tpl<Scalar, Options>& aMb,
232
              ModelTpl<Scalar,Options,JointCollectionTpl>& model,
233
              GeometryModel& geomModel)
234
  {
235
    typedef details::AppendJointOfModelAlgoTpl<Scalar, Options, JointCollectionTpl> AppendJointOfModelAlgo;
236
    typedef typename AppendJointOfModelAlgo::ArgsType ArgsType;
237
238

7
    PINOCCHIO_CHECK_INPUT_ARGUMENT((bool)(frameInModelA < (FrameIndex) modelA.nframes),
239
                                   "frameInModelA is an invalid Frame index, greater than the number of frames contained in modelA.");
240
241
    typedef ModelTpl<Scalar,Options,JointCollectionTpl> Model;
242
    typedef typename Model::SE3 SE3;
243
    typedef typename Model::Frame Frame;
244
245
7
    const Frame & frame = modelA.frames[frameInModelA];
246


7
    static const SE3 id = SE3::Identity();
247
248
7
    int njoints = modelA.njoints + modelB.njoints - 1;
249
7
    model.names                 .reserve ((size_t)njoints);
250
7
    model.joints                .reserve ((size_t)njoints);
251
7
    model.jointPlacements       .reserve ((size_t)njoints);
252
7
    model.parents               .reserve ((size_t)njoints);
253
7
    model.inertias              .reserve ((size_t)njoints);
254
7
    int nframes = modelA.nframes + modelB.nframes - 1;
255
7
    model.frames                .reserve ((size_t)nframes);
256
257
7
    geomModel.geometryObjects.reserve (geomModelA.ngeoms + geomModelB.ngeoms);
258
259
    // Copy modelA joints until frame.parentJoint
260
7
    details::appendUniverseToModel (modelA, geomModelA, 0, id, model, geomModel);
261
58
    for (JointIndex jid = 1; jid <= frame.parent; ++jid)
262
    {
263
51
      ArgsType args (modelA, geomModelA, 0, id, model, geomModel);
264

51
      AppendJointOfModelAlgo::run (modelA.joints[jid], args);
265
    }
266
267
    // Copy modelB joints
268
7
    details::appendUniverseToModel (modelB, geomModelB,
269
7
                                    details::getFrameId(modelA,model,frame.name,frame.type), aMb, model, geomModel);
270
44
    for (JointIndex jid = 1; jid < modelB.joints.size(); ++jid)
271
    {
272

37
      SE3 pMi = (jid == 1 ? frame.placement * aMb : id);
273
37
      ArgsType args (modelB, geomModelB, frame.parent, pMi, model, geomModel);
274

37
      AppendJointOfModelAlgo::run (modelB.joints[jid], args);
275
    }
276
277
    // Copy remaining joints of modelA
278
136
    for (JointIndex jid = frame.parent+1; jid < modelA.joints.size(); ++jid)
279
    {
280
129
      ArgsType args (modelA, geomModelA, 0, id, model, geomModel);
281

129
      AppendJointOfModelAlgo::run (modelA.joints[jid], args);
282
    }
283
284
#ifdef PINOCCHIO_WITH_HPP_FCL
285
    // Add collision pairs of geomModelA and geomModelB
286
7
    geomModel.collisionPairs.reserve(geomModelA.collisionPairs.size()
287
7
       + geomModelB.collisionPairs.size()
288
7
       + geomModelA.geometryObjects.size() * geomModelB.geometryObjects.size());
289
290
701
    for (std::size_t icp = 0; icp < geomModelA.collisionPairs.size(); ++icp)
291
    {
292
694
      const CollisionPair& cp = geomModelA.collisionPairs[icp];
293
694
      GeomIndex go1 = geomModel.getGeometryId(geomModelA.geometryObjects[cp.first ].name);
294
694
      GeomIndex go2 = geomModel.getGeometryId(geomModelA.geometryObjects[cp.second].name);
295
694
      geomModel.addCollisionPair (CollisionPair (go1, go2));
296
    }
297
298
35
    for (std::size_t icp = 0; icp < geomModelB.collisionPairs.size(); ++icp)
299
    {
300
28
      const CollisionPair & cp = geomModelB.collisionPairs[icp];
301
28
      GeomIndex go1 = geomModel.getGeometryId(geomModelB.geometryObjects[cp.first ].name);
302
28
      GeomIndex go2 = geomModel.getGeometryId(geomModelB.geometryObjects[cp.second].name);
303
28
      geomModel.addCollisionPair (CollisionPair (go1, go2));
304
    }
305
306
    // add the collision pairs between geomModelA and geomModelB.
307
68
    for (Index i = 0; i < geomModelA.geometryObjects.size(); ++i)
308
    {
309
61
      GeomIndex go1 = geomModel.getGeometryId(geomModelA.geometryObjects[i].name);
310
399
      for (Index j = 0; j < geomModelB.geometryObjects.size(); ++j)
311
      {
312
338
        GeomIndex go2 = geomModel.getGeometryId(geomModelB.geometryObjects[j].name);
313
338
        if (   geomModel.geometryObjects[go1].parentJoint
314
338
            != geomModel.geometryObjects[go2].parentJoint)
315
338
          geomModel.addCollisionPair(CollisionPair(go1, go2));
316
      }
317
    }
318
#endif
319
7
  }
320
321
  template<typename Scalar, int Options, template<typename,int> class JointCollectionTpl, typename ConfigVectorType>
322
  void
323
15
  buildReducedModel(const ModelTpl<Scalar,Options,JointCollectionTpl> & input_model,
324
                    std::vector<JointIndex> list_of_joints_to_lock,
325
                    const Eigen::MatrixBase<ConfigVectorType> & reference_configuration,
326
                    ModelTpl<Scalar,Options,JointCollectionTpl> & reduced_model)
327
  {
328







15
    PINOCCHIO_CHECK_ARGUMENT_SIZE(reference_configuration.size(), input_model.nq,
329
                                   "The configuration vector is not of right size");
330

15
    PINOCCHIO_CHECK_INPUT_ARGUMENT(list_of_joints_to_lock.size() <= (size_t)input_model.njoints,
331
                                   "The number of joints to lock is greater than the total of joints in the reduced_model");
332
333
    typedef ModelTpl<Scalar,Options,JointCollectionTpl> Model;
334
    typedef typename Model::JointModel JointModel;
335
    typedef typename Model::JointData JointData;
336
    typedef typename Model::Frame Frame;
337
    typedef typename Model::SE3 SE3;
338
339
    // Sort indexes
340
15
    std::sort(list_of_joints_to_lock.begin(),list_of_joints_to_lock.end());
341
342
    // Check that they are not two identical elements
343
31
    for(size_t id = 1; id < list_of_joints_to_lock.size(); ++id)
344
    {
345

16
      PINOCCHIO_CHECK_INPUT_ARGUMENT(list_of_joints_to_lock[id-1] < list_of_joints_to_lock[id],
346
                                     "The input list_of_joints_to_lock contains two identical indexes.");
347
    }
348
349
    // Reserve memory
350
15
    const Eigen::DenseIndex njoints = input_model.njoints - (Eigen::DenseIndex)list_of_joints_to_lock.size();
351
15
    reduced_model.names                 .reserve((size_t)njoints);
352
15
    reduced_model.joints                .reserve((size_t)njoints);
353
15
    reduced_model.jointPlacements       .reserve((size_t)njoints);
354
15
    reduced_model.parents               .reserve((size_t)njoints);
355
356
15
    reduced_model.names[0] = input_model.names[0];
357
15
    reduced_model.joints[0] = input_model.joints[0];
358
15
    reduced_model.jointPlacements[0] = input_model.jointPlacements[0];
359
15
    reduced_model.parents[0] = input_model.parents[0];
360
15
    reduced_model.inertias[0] = input_model.inertias[0];
361
362
15
    reduced_model.name = input_model.name;
363
15
    reduced_model.gravity = input_model.gravity;
364
365
15
    size_t current_index_to_lock = 0;
366
367
312
    for(JointIndex joint_id = 1; joint_id < (JointIndex)input_model.njoints; ++joint_id)
368
    {
369
297
      const JointIndex joint_id_to_lock = (current_index_to_lock < list_of_joints_to_lock.size()) ? list_of_joints_to_lock[current_index_to_lock] : 0;
370
371
297
      const JointIndex input_parent_joint_index = input_model.parents[joint_id];
372
297
      const std::string & joint_name = input_model.names[joint_id];
373
297
      const JointModel & joint_input_model = input_model.joints[joint_id];
374
375
      // retrieve the closest joint parent in the new kinematic tree
376
297
      const std::string & parent_joint_name = input_model.names[input_parent_joint_index];
377
297
      const bool exist_parent_joint = reduced_model.existJointName(parent_joint_name);
378
379
297
      const JointIndex reduced_parent_joint_index
380
      = exist_parent_joint
381

320
      ? reduced_model.getJointId(parent_joint_name)
382
23
      : reduced_model.frames[reduced_model.getFrameId(parent_joint_name)].parent;
383
384

297
      const SE3 parent_frame_placement
385
      = exist_parent_joint
386
      ? SE3::Identity()
387

23
      : reduced_model.frames[reduced_model.getFrameId(parent_joint_name)].placement;
388
389
297
      const FrameIndex reduced_previous_frame_index
390
      = exist_parent_joint
391

297
      ? 0
392
      : reduced_model.getFrameId(parent_joint_name);
393
394
297
      if(joint_id == joint_id_to_lock)
395
      {
396
        // the joint should not be added to the Model but aggragated to its parent joint
397
398
        // Compute the new placement of the joint with respect to its parent joint in the new kinematic tree.
399
54
        JointData joint_data = joint_input_model.createData();
400
27
        joint_input_model.calc(joint_data,reference_configuration);
401

27
        const SE3 liMi = parent_frame_placement * input_model.jointPlacements[joint_id] * joint_data.M();
402
403
27
        Frame frame = Frame(joint_name,
404
                            reduced_parent_joint_index, reduced_previous_frame_index,
405
                            liMi,
406
                            FIXED_JOINT,
407
27
                            input_model.inertias[joint_id]);
408
409
27
        FrameIndex frame_id = reduced_model.addFrame(frame);
410
27
        reduced_model.frames[frame_id].previousFrame = frame_id; // a bit weird, but this is a solution for missing parent frame
411
412
27
        current_index_to_lock++;
413
      }
414
      else
415
      {
416
        // the joint should be added to the Model as it is
417




1890
        JointIndex reduced_joint_id = reduced_model.addJoint(reduced_parent_joint_index,
418
                                                             joint_input_model,
419
270
                                                             parent_frame_placement * input_model.jointPlacements[joint_id],
420
                                                             joint_name,
421
270
                                                             joint_input_model.jointVelocitySelector(input_model.effortLimit),
422
270
                                                             joint_input_model.jointVelocitySelector(input_model.velocityLimit),
423
270
                                                             joint_input_model.jointConfigSelector(input_model.lowerPositionLimit),
424
270
                                                             joint_input_model.jointConfigSelector(input_model.upperPositionLimit),
425
270
                                                             joint_input_model.jointVelocitySelector(input_model.friction),
426
270
                                                             joint_input_model.jointVelocitySelector(input_model.damping));
427
        // Append inertia
428

540
        reduced_model.appendBodyToJoint(reduced_joint_id,
429
270
                                        input_model.inertias[joint_id],
430
                                        SE3::Identity());
431
432
        // Copy other kinematics and dynamics properties
433
270
        const typename Model::JointModel & jmodel_out = reduced_model.joints[reduced_joint_id];
434
270
        jmodel_out.jointVelocitySelector(reduced_model.rotorInertia)
435

270
        = joint_input_model.jointVelocitySelector(input_model.rotorInertia);
436
270
        jmodel_out.jointVelocitySelector(reduced_model.rotorGearRatio)
437

270
        = joint_input_model.jointVelocitySelector(input_model.rotorGearRatio);
438
      }
439
    }
440
441
    // Retrieve and extend the reference configurations
442
    typedef typename Model::ConfigVectorMap ConfigVectorMap;
443
20
    for(typename ConfigVectorMap::const_iterator config_it = input_model.referenceConfigurations.begin();
444
25
        config_it != input_model.referenceConfigurations.end(); ++config_it)
445
    {
446
5
      const std::string & config_name = config_it->first;
447
5
      const typename Model::ConfigVectorType & input_config_vector = config_it->second;
448
449
5
      typename Model::ConfigVectorType reduced_config_vector(reduced_model.nq);
450
5
      for(JointIndex reduced_joint_id = 1;
451
146
          reduced_joint_id < reduced_model.joints.size();
452
          ++reduced_joint_id)
453
      {
454
141
        const JointIndex input_joint_id = input_model.getJointId(reduced_model.names[reduced_joint_id]);
455
141
        const JointModel & input_joint_model = input_model.joints[input_joint_id];
456
141
        const JointModel & reduced_joint_model = reduced_model.joints[reduced_joint_id];
457
458

141
        reduced_joint_model.jointConfigSelector(reduced_config_vector) = input_joint_model.jointConfigSelector(input_config_vector);
459
      }
460
461

5
      reduced_model.referenceConfigurations.insert(std::make_pair(config_name, reduced_config_vector));
462
    }
463
464
    // Add all frames
465
15
    typename Model::FrameVector::const_iterator frame_it = input_model.frames.begin();
466
696
    for(++frame_it;frame_it != input_model.frames.end(); ++frame_it)
467
    {
468
681
      const Frame & input_frame = *frame_it;
469
681
      const std::string & support_joint_name = input_model.names[input_frame.parent];
470
471
681
      std::vector<JointIndex>::const_iterator support_joint_it = std::find(list_of_joints_to_lock.begin(),
472
                                                                           list_of_joints_to_lock.end(),
473
681
                                                                           input_frame.parent);
474
475
681
      if(support_joint_it != list_of_joints_to_lock.end())
476
      {
477
78
        if(   input_frame.type == JOINT
478

27
           && reduced_model.existFrame(input_frame.name)
479

105
           && support_joint_name == input_frame.name)
480
27
          continue; // this means that the Joint is now fixed and has been replaced by a Frame. No need to add a new one.
481
482
        // The joint has been removed and replaced by a Frame
483
51
        const FrameIndex joint_frame_id = reduced_model.getFrameId(support_joint_name);
484
51
        const Frame & joint_frame = reduced_model.frames[joint_frame_id];
485
102
        Frame reduced_frame = input_frame;
486
51
        reduced_frame.placement = joint_frame.placement * input_frame.placement;
487
51
        reduced_frame.parent = joint_frame.parent;
488

51
        reduced_frame.previousFrame = reduced_model.getFrameId(input_model.frames[input_frame.previousFrame].name);
489
51
        reduced_model.addFrame(reduced_frame, false);
490
      }
491
      else
492
      {
493
1206
        Frame reduced_frame = input_frame;
494
603
        reduced_frame.parent = reduced_model.getJointId(input_model.names[input_frame.parent]);
495

603
        reduced_frame.previousFrame = reduced_model.getFrameId(input_model.frames[input_frame.previousFrame].name);
496
603
        reduced_model.addFrame(reduced_frame, false);
497
      }
498
    }
499
15
  }
500
501
  template<typename Scalar, int Options, template<typename,int> class JointCollectionTpl, typename ConfigVectorType>
502
  void
503
3
  buildReducedModel(const ModelTpl<Scalar,Options,JointCollectionTpl> & input_model,
504
                    const GeometryModel & input_geom_model,
505
                    const std::vector<JointIndex> & list_of_joints_to_lock,
506
                    const Eigen::MatrixBase<ConfigVectorType> & reference_configuration,
507
                    ModelTpl<Scalar,Options,JointCollectionTpl> & reduced_model,
508
                    GeometryModel & reduced_geom_model)
509
  {
510
511
6
    const std::vector<GeometryModel> temp_input_geoms(1,input_geom_model);
512
6
    std::vector<GeometryModel> temp_reduced_geom_models;
513
514
3
    buildReducedModel(input_model, temp_input_geoms, list_of_joints_to_lock,
515
                      reference_configuration, reduced_model,
516
                      temp_reduced_geom_models);
517
3
    reduced_geom_model = temp_reduced_geom_models.front();
518
3
  }
519
520
  template <typename Scalar, int Options,
521
            template <typename, int> class JointCollectionTpl,
522
            typename GeometryModelAllocator,
523
            typename ConfigVectorType>
524
9
  void buildReducedModel(
525
      const ModelTpl<Scalar, Options, JointCollectionTpl> &input_model,
526
      const std::vector<GeometryModel,GeometryModelAllocator> &list_of_geom_models,
527
      const std::vector<JointIndex> &list_of_joints_to_lock,
528
      const Eigen::MatrixBase<ConfigVectorType> &reference_configuration,
529
      ModelTpl<Scalar, Options, JointCollectionTpl> &reduced_model,
530
      std::vector<GeometryModel,GeometryModelAllocator> &list_of_reduced_geom_models) {
531
532
    typedef ModelTpl<Scalar, Options, JointCollectionTpl> Model;
533
9
    buildReducedModel(input_model, list_of_joints_to_lock, reference_configuration, reduced_model);
534
535
    // for all GeometryModels
536
24
    for (size_t gmi = 0; gmi < list_of_geom_models.size(); ++gmi) {
537
15
      const GeometryModel &input_geom_model = list_of_geom_models[gmi];
538
30
      GeometryModel reduced_geom_model;
539
540
      // Add all the geometries
541
      typedef GeometryModel::GeometryObject GeometryObject;
542
      typedef GeometryModel::GeometryObjectVector GeometryObjectVector;
543
224
      for(GeometryObjectVector::const_iterator it = input_geom_model.geometryObjects.begin();
544
433
          it != input_geom_model.geometryObjects.end(); ++it)
545
      {
546
209
        const GeometryModel::GeometryObject & geom = *it;
547
548
209
        const JointIndex joint_id_in_input_model = geom.parentJoint;
549

209
        _PINOCCHIO_CHECK_INPUT_ARGUMENT_2((joint_id_in_input_model < (JointIndex)input_model.njoints),
550
                                          "Invalid joint parent index for the geometry with name " + geom.name);
551
209
        const std::string & parent_joint_name = input_model.names[joint_id_in_input_model];
552
553
209
        JointIndex reduced_joint_id = (JointIndex)-1;
554
        typedef typename Model::SE3 SE3;
555
209
        SE3 relative_placement = SE3::Identity();
556

209
        if(reduced_model.existJointName(parent_joint_name))
557
        {
558
175
          reduced_joint_id = reduced_model.getJointId(parent_joint_name);
559
        }
560
        else // The joint is now a frame
561
        {
562
34
          const FrameIndex reduced_frame_id = reduced_model.getFrameId(parent_joint_name);
563
34
          reduced_joint_id = reduced_model.frames[reduced_frame_id].parent;
564
34
          relative_placement = reduced_model.frames[reduced_frame_id].placement;
565
        }
566
567
418
        GeometryObject reduced_geom(geom);
568
209
        reduced_geom.parentJoint = reduced_joint_id;
569
418
        reduced_geom.parentFrame = reduced_model.getBodyId(
570
209
            input_model.frames[geom.parentFrame].name);
571
209
        reduced_geom.placement = relative_placement * geom.placement;
572
209
        reduced_geom_model.addGeometryObject(reduced_geom);
573
      }
574
575
  #ifdef PINOCCHIO_WITH_HPP_FCL
576
      // Add all the collision pairs - the index of the geometry objects should have not changed
577
578
      typedef GeometryModel::CollisionPairVector CollisionPairVector;
579
15
      for(CollisionPairVector::const_iterator it = input_geom_model.collisionPairs.begin();
580
15
          it != input_geom_model.collisionPairs.end(); ++it)
581
      {
582
        const CollisionPair & cp = *it;
583
        reduced_geom_model.addCollisionPair(cp);
584
      }
585
  #endif
586
587
15
    list_of_reduced_geom_models.push_back(reduced_geom_model);
588
    }
589
9
  }
590
591
} // namespace pinocchio
592
593
#endif // ifndef __pinocchio_algorithm_model_hxx__