GCC Code Coverage Report


Directory: ./
File: include/pinocchio/algorithm/model.hxx
Date: 2025-02-12 21:03:38
Exec Total Coverage
Lines: 359 370 97.0%
Branches: 364 672 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 #include "pinocchio/algorithm/joint-configuration.hpp"
10 #include "pinocchio/spatial/fwd.hpp"
11
12 namespace pinocchio
13 {
14 namespace details
15 {
16
17 // Retrieve the joint id in model_out, given the info of model_in.
18 // If the user change all the joint names, the universe name won't correspond to the first joint
19 // in the tree when searching by name. We thus need to retrieve it with other means, e.g.
20 // checking the index of the joints.
21 template<typename Scalar, int Options, template<typename, int> class JointCollectionTpl>
22 246 JointIndex getJointId(
23 const ModelTpl<Scalar, Options, JointCollectionTpl> & model_in,
24 const ModelTpl<Scalar, Options, JointCollectionTpl> & model_out,
25 const std::string & joint_name_in_model_in)
26 {
27 246 const JointIndex joint_id = model_in.getJointId(joint_name_in_model_in);
28
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 246 times.
246 assert(joint_id < model_in.joints.size());
29
2/6
✗ Branch 0 not taken.
✓ Branch 1 taken 246 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 246 times.
246 if (joint_id == 0 && model_in.parents[0] == 0) // This is the universe, maybe renamed.
30 return model_out.getJointId(model_out.names[0]);
31 else
32 246 return model_out.getJointId(joint_name_in_model_in);
33 }
34
35 // Retrieve the frame id in model_out, given the info of model_in.
36 // If the user change all the frame names, the universe name won't correspond to the first frame
37 // in the tree when searching by name. We thus need to retrieve it with other means, e.g.
38 // checking the fields of the frames.
39 template<typename Scalar, int Options, template<typename, int> class JointCollectionTpl>
40
1/2
✓ Branch 1 taken 748 times.
✗ Branch 2 not taken.
748 FrameIndex getFrameId(
41 const ModelTpl<Scalar, Options, JointCollectionTpl> & model_in,
42 const ModelTpl<Scalar, Options, JointCollectionTpl> & model_out,
43 const std::string & frame_name_in_model_in,
44 const FrameType & type)
45 {
46
1/2
✓ Branch 1 taken 748 times.
✗ Branch 2 not taken.
748 const FrameIndex frame_id = model_in.getFrameId(frame_name_in_model_in);
47
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 748 times.
748 assert(frame_id < model_in.frames.size());
48 748 if (
49
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 frame_id == 0 && model_in.frames[0].parentFrame == 0
50
5/6
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 744 times.
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 4 times.
✓ Branch 6 taken 744 times.
752 && model_in.frames[0].parent == 0) // This is the universe, maybe renamed.
51 4 return model_out.getFrameId(model_out.frames[0].name, type);
52 else
53 744 return model_out.getFrameId(frame_name_in_model_in, type);
54 }
55
56 template<typename Scalar, int Options, template<typename, int> class JointCollectionTpl>
57 20 void appendUniverseToModel(
58 const ModelTpl<Scalar, Options, JointCollectionTpl> & modelAB,
59 const GeometryModel & geomModelAB,
60 FrameIndex parentFrame,
61 const SE3Tpl<Scalar, Options> & pfMAB,
62 ModelTpl<Scalar, Options, JointCollectionTpl> & model,
63 GeometryModel & geomModel)
64 {
65 typedef ModelTpl<Scalar, Options, JointCollectionTpl> Model;
66 typedef typename Model::Frame Frame;
67
68
1/4
✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
20 PINOCCHIO_THROW(
69 parentFrame < model.frames.size(), std::invalid_argument,
70 "parentFrame is greater than the size of the frames vector.");
71
72 20 const Frame & pframe = model.frames[parentFrame];
73 20 JointIndex jid = pframe.parentJoint;
74
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
20 assert(jid < model.joints.size());
75
76 // If inertia is not NaN, add it.
77
1/2
✓ Branch 3 taken 20 times.
✗ Branch 4 not taken.
20 if (modelAB.inertias[0] == modelAB.inertias[0])
78
1/2
✓ Branch 3 taken 20 times.
✗ Branch 4 not taken.
20 model.appendBodyToJoint(jid, modelAB.inertias[0], pframe.placement * pfMAB);
79
80 // Add all frames whose parent is this joint.
81
2/2
✓ Branch 2 taken 647 times.
✓ Branch 3 taken 20 times.
667 for (FrameIndex fid = 1; fid < modelAB.frames.size(); ++fid)
82 {
83
1/2
✓ Branch 2 taken 647 times.
✗ Branch 3 not taken.
647 Frame frame = modelAB.frames[fid];
84
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 642 times.
647 if (frame.parentJoint == 0)
85 {
86
2/6
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
5 PINOCCHIO_CHECK_INPUT_ARGUMENT(
87 !model.existFrame(frame.name, frame.type),
88 "The two models have conflicting frame names.");
89
90 5 frame.parentJoint = jid;
91
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 times.
5 if (frame.parentFrame != 0)
92 {
93 4 frame.parentFrame = getFrameId(
94
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 modelAB, model, modelAB.frames[frame.parentFrame].name,
95 4 modelAB.frames[frame.parentFrame].type);
96 }
97 else
98 {
99 1 frame.parentFrame = parentFrame;
100 }
101
102 // Modify frame placement
103
3/6
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 5 times.
✗ Branch 8 not taken.
5 frame.placement = pframe.placement * pfMAB * frame.placement;
104 // Some frames may have some inertia attached to them. In this case, we need to remove it
105 // from the parent joint. To prevent introducing NaNs, we check if the frame inertia is
106 // not NaN and is not zero.
107
8/12
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 5 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 5 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 1 times.
✓ Branch 12 taken 4 times.
✓ Branch 13 taken 1 times.
✓ Branch 14 taken 4 times.
5 if (frame.inertia == frame.inertia && frame.inertia != Inertia::Zero())
108 {
109
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 model.inertias[frame.parentJoint] -= frame.inertia;
110 }
111
1/2
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
5 model.addFrame(frame);
112 }
113 }
114
115 // Add all geometries whose parent is this joint.
116
2/2
✓ Branch 2 taken 114 times.
✓ Branch 3 taken 20 times.
134 for (GeomIndex gid = 0; gid < geomModelAB.geometryObjects.size(); ++gid)
117 {
118
1/2
✓ Branch 2 taken 114 times.
✗ Branch 3 not taken.
114 GeometryObject go = geomModelAB.geometryObjects[gid];
119
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 113 times.
114 if (go.parentJoint == 0)
120 {
121 1 go.parentJoint = jid;
122
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (go.parentFrame != 0)
123 {
124 1 go.parentFrame = getFrameId(
125
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 modelAB, model, modelAB.frames[go.parentFrame].name,
126 1 modelAB.frames[go.parentFrame].type);
127 }
128 else
129 {
130 go.parentFrame = parentFrame;
131 }
132
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
1 go.placement = pframe.placement * pfMAB * go.placement;
133
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 geomModel.addGeometryObject(go);
134 }
135 }
136 20 }
137
138 template<typename Scalar, int Options, template<typename, int> class JointCollectionTpl>
139 struct AppendJointOfModelAlgoTpl
140 : public fusion::JointUnaryVisitorBase<
141 AppendJointOfModelAlgoTpl<Scalar, Options, JointCollectionTpl>>
142 {
143
144 typedef ModelTpl<Scalar, Options, JointCollectionTpl> Model;
145 typedef typename Model::Frame Frame;
146
147 typedef boost::fusion::vector<
148 const Model &,
149 const GeometryModel &,
150 JointIndex,
151 const typename Model::SE3 &,
152 Model &,
153 GeometryModel &>
154 ArgsType;
155
156 template<typename JointModel>
157 534 static void algo(
158 const JointModelBase<JointModel> & jmodel_in,
159 const Model & modelAB,
160 const GeometryModel & geomModelAB,
161 JointIndex parent_id,
162 const typename Model::SE3 & pMi,
163 Model & model,
164 GeometryModel & geomModel)
165 {
166 // If old parent is universe, use what's provided in the input.
167 // otherwise, get the parent from modelAB.
168 534 const JointIndex joint_id_in = jmodel_in.id();
169
2/2
✓ Branch 1 taken 246 times.
✓ Branch 2 taken 21 times.
534 if (modelAB.parents[joint_id_in] > 0)
170 492 parent_id = getJointId(modelAB, model, modelAB.names[modelAB.parents[joint_id_in]]);
171
172
1/4
✗ Branch 2 not taken.
✓ Branch 3 taken 267 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
534 PINOCCHIO_CHECK_INPUT_ARGUMENT(
173 !model.existJointName(modelAB.names[joint_id_in]),
174 "The two models have conflicting joint names.");
175
176
9/18
✓ Branch 1 taken 267 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 267 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 267 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 267 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 267 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 267 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 267 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 267 times.
✗ Branch 23 not taken.
✓ Branch 25 taken 267 times.
✗ Branch 26 not taken.
3738 JointIndex joint_id_out = model.addJoint(
177 534 parent_id, jmodel_in, pMi * modelAB.jointPlacements[joint_id_in],
178
1/2
✓ Branch 1 taken 267 times.
✗ Branch 2 not taken.
1602 modelAB.names[joint_id_in], jmodel_in.jointVelocitySelector(modelAB.effortLimit),
179
1/2
✓ Branch 1 taken 267 times.
✗ Branch 2 not taken.
1068 jmodel_in.jointVelocitySelector(modelAB.velocityLimit),
180
1/2
✓ Branch 1 taken 267 times.
✗ Branch 2 not taken.
1068 jmodel_in.jointConfigSelector(modelAB.lowerPositionLimit),
181
1/2
✓ Branch 1 taken 267 times.
✗ Branch 2 not taken.
1068 jmodel_in.jointConfigSelector(modelAB.upperPositionLimit),
182
1/2
✓ Branch 1 taken 267 times.
✗ Branch 2 not taken.
1068 jmodel_in.jointVelocitySelector(modelAB.friction),
183 534 jmodel_in.jointVelocitySelector(modelAB.damping));
184
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 267 times.
534 assert(joint_id_out < model.joints.size());
185
186
1/2
✓ Branch 3 taken 267 times.
✗ Branch 4 not taken.
534 model.appendBodyToJoint(joint_id_out, modelAB.inertias[joint_id_in]);
187
188 534 const typename Model::JointModel & jmodel_out = model.joints[joint_id_out];
189
2/4
✓ Branch 1 taken 267 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 267 times.
✗ Branch 5 not taken.
534 jmodel_out.jointVelocitySelector(model.rotorInertia) =
190 534 jmodel_in.jointVelocitySelector(modelAB.rotorInertia);
191
2/4
✓ Branch 1 taken 267 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 267 times.
✗ Branch 5 not taken.
534 jmodel_out.jointVelocitySelector(model.rotorGearRatio) =
192 534 jmodel_in.jointVelocitySelector(modelAB.rotorGearRatio);
193
194 // Add all frames whose parent is this joint.
195
2/2
✓ Branch 2 taken 15093 times.
✓ Branch 3 taken 267 times.
30720 for (FrameIndex fid = 1; fid < modelAB.frames.size(); ++fid)
196 {
197
1/2
✓ Branch 2 taken 15093 times.
✗ Branch 3 not taken.
30186 Frame frame = modelAB.frames[fid];
198
3/4
✓ Branch 1 taken 15093 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 642 times.
✓ Branch 4 taken 14451 times.
30186 if (frame.parentJoint == jmodel_in.id())
199 {
200
2/6
✓ Branch 1 taken 642 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 642 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
1284 PINOCCHIO_CHECK_INPUT_ARGUMENT(
201 !model.existFrame(frame.name, frame.type),
202 "The two models have conflicting frame names.");
203
204 1284 frame.parentJoint = joint_id_out;
205
3/4
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 622 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 20 times.
1284 assert(frame.parentFrame > 0 || frame.type == JOINT);
206
2/2
✓ Branch 0 taken 622 times.
✓ Branch 1 taken 20 times.
1284 if (frame.parentFrame != 0)
207 {
208 1244 frame.parentFrame = getFrameId(
209
1/2
✓ Branch 1 taken 622 times.
✗ Branch 2 not taken.
1244 modelAB, model, modelAB.frames[frame.parentFrame].name,
210 1244 modelAB.frames[frame.parentFrame].type);
211 }
212 // Some frames may have some inertia attached to them. In this case, we need to remove
213 // it from the parent joint. To prevent introducing NaNs, we check if the frame inertia
214 // is not NaN and is not zero.
215
8/12
✓ Branch 1 taken 642 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 642 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 642 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 642 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 1 times.
✓ Branch 12 taken 641 times.
✓ Branch 13 taken 1 times.
✓ Branch 14 taken 641 times.
1284 if (frame.inertia == frame.inertia && frame.inertia != Inertia::Zero())
216 {
217
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 model.inertias[frame.parentJoint] -= frame.inertia;
218 }
219
1/2
✓ Branch 1 taken 642 times.
✗ Branch 2 not taken.
1284 model.addFrame(frame);
220 }
221 }
222 // Add all geometries whose parent is this joint.
223
2/2
✓ Branch 2 taken 2537 times.
✓ Branch 3 taken 267 times.
5608 for (GeomIndex gid = 0; gid < geomModelAB.geometryObjects.size(); ++gid)
224 {
225
1/2
✓ Branch 2 taken 2537 times.
✗ Branch 3 not taken.
5074 GeometryObject go = geomModelAB.geometryObjects[gid];
226
2/2
✓ Branch 0 taken 113 times.
✓ Branch 1 taken 2424 times.
5074 if (go.parentJoint == joint_id_in)
227 {
228 226 go.parentJoint = joint_id_out;
229
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 113 times.
226 assert(go.parentFrame > 0);
230
5/6
✓ Branch 0 taken 113 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 111 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 111 times.
✓ Branch 6 taken 2 times.
226 if (go.parentFrame != 0 && go.parentFrame < modelAB.frames.size())
231 {
232 222 go.parentFrame = getFrameId(
233
1/2
✓ Branch 1 taken 111 times.
✗ Branch 2 not taken.
222 modelAB, model, modelAB.frames[go.parentFrame].name,
234 222 modelAB.frames[go.parentFrame].type);
235 }
236
1/2
✓ Branch 1 taken 113 times.
✗ Branch 2 not taken.
226 geomModel.addGeometryObject(go);
237 }
238 }
239 }
240 };
241
242 } // namespace details
243
244 template<typename Scalar, int Options, template<typename, int> class JointCollectionTpl>
245 5 void appendModel(
246 const ModelTpl<Scalar, Options, JointCollectionTpl> & modelA,
247 const ModelTpl<Scalar, Options, JointCollectionTpl> & modelB,
248 const FrameIndex frameInModelA,
249 const SE3Tpl<Scalar, Options> & aMb,
250 ModelTpl<Scalar, Options, JointCollectionTpl> & model)
251 {
252
3/6
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 5 times.
✗ Branch 8 not taken.
5 GeometryModel geomModelA, geomModelB, geomModel;
253
254
1/2
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
5 appendModel(modelA, modelB, geomModelA, geomModelB, frameInModelA, aMb, model, geomModel);
255 5 }
256
257 // Compute whether Joint child is a descendent of parent in a given model
258 // Joints are represented by their id in the model
259 template<typename Scalar, int Options, template<typename, int> class JointCollectionTpl>
260 158 static bool hasAncestor(
261 const ModelTpl<Scalar, Options, JointCollectionTpl> & model,
262 JointIndex child,
263 JointIndex parent)
264 {
265 typedef typename ModelTpl<Scalar, Options, JointCollectionTpl>::IndexVector IndexVector_t;
266 // Any joints has universe as an acenstor
267
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 158 times.
158 assert(model.supports[child][0] == 0);
268 158 for (typename IndexVector_t::const_iterator it = model.supports[child].begin();
269
1/2
✓ Branch 4 taken 284 times.
✗ Branch 5 not taken.
284 it != model.supports[child].end(); ++it)
270 {
271
2/2
✓ Branch 1 taken 158 times.
✓ Branch 2 taken 126 times.
284 if (*it == parent)
272 158 return true;
273 }
274 return false;
275 }
276
277 template<typename Scalar, int Options, template<typename, int> class JointCollectionTpl>
278 10 void appendModel(
279 const ModelTpl<Scalar, Options, JointCollectionTpl> & modelA,
280 const ModelTpl<Scalar, Options, JointCollectionTpl> & modelB,
281 const GeometryModel & geomModelA,
282 const GeometryModel & geomModelB,
283 const FrameIndex frameInModelA,
284 const SE3Tpl<Scalar, Options> & aMb,
285 ModelTpl<Scalar, Options, JointCollectionTpl> & model,
286 GeometryModel & geomModel)
287 {
288 typedef details::AppendJointOfModelAlgoTpl<Scalar, Options, JointCollectionTpl>
289 AppendJointOfModelAlgo;
290 typedef typename AppendJointOfModelAlgo::ArgsType ArgsType;
291
292
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
10 PINOCCHIO_CHECK_INPUT_ARGUMENT(
293 (bool)(frameInModelA < (FrameIndex)modelA.nframes),
294 "frameInModelA is an invalid Frame index, greater than the "
295 "number of frames contained in modelA.");
296
297 typedef ModelTpl<Scalar, Options, JointCollectionTpl> Model;
298 typedef typename Model::SE3 SE3;
299 typedef typename Model::Frame Frame;
300
301 10 const Frame & frame = modelA.frames[frameInModelA];
302
4/8
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
10 static const SE3 id = SE3::Identity();
303
304 10 int njoints = modelA.njoints + modelB.njoints - 1;
305
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
10 model.names.reserve((size_t)njoints);
306
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
10 model.joints.reserve((size_t)njoints);
307
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
10 model.jointPlacements.reserve((size_t)njoints);
308
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
10 model.parents.reserve((size_t)njoints);
309
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
10 model.inertias.reserve((size_t)njoints);
310 10 int nframes = modelA.nframes + modelB.nframes - 1;
311
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
10 model.frames.reserve((size_t)nframes);
312
313
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
10 geomModel.geometryObjects.reserve(geomModelA.ngeoms + geomModelB.ngeoms);
314
315
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
10 details::appendUniverseToModel(modelA, geomModelA, 0, id, model, geomModel);
316 // Compute joints of A that should be added before and after joints of B
317 10 std::vector<JointIndex> AJointsBeforeB;
318 10 std::vector<JointIndex> AJointsAfterB;
319 // All joints until the parent of frameInModelA come first
320
2/2
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 10 times.
68 for (JointIndex jid = 1; jid <= frame.parent; ++jid)
321 {
322
1/2
✓ Branch 1 taken 58 times.
✗ Branch 2 not taken.
58 AJointsBeforeB.push_back(jid);
323 }
324 // descendants of the parent of frameInModelA come also before model B
325 // TODO(jcarpent): enhancement by taking into account the compactness of the joint ordering.
326
2/2
✓ Branch 1 taken 158 times.
✓ Branch 2 taken 10 times.
168 for (JointIndex jid = frame.parent + 1; jid < modelA.joints.size(); ++jid)
327 {
328
1/2
✓ Branch 1 taken 158 times.
✗ Branch 2 not taken.
158 if (hasAncestor(modelA, jid, frame.parent))
329 {
330
1/2
✓ Branch 1 taken 158 times.
✗ Branch 2 not taken.
158 AJointsBeforeB.push_back(jid);
331 }
332 else
333 {
334 AJointsAfterB.push_back(jid);
335 }
336 }
337 // Copy modelA joints that should come before model B
338 10 for (std::vector<JointIndex>::const_iterator jid = AJointsBeforeB.begin();
339
2/2
✓ Branch 2 taken 216 times.
✓ Branch 3 taken 10 times.
226 jid != AJointsBeforeB.end(); ++jid)
340 {
341
1/2
✓ Branch 1 taken 216 times.
✗ Branch 2 not taken.
216 ArgsType args(modelA, geomModelA, 0, id, model, geomModel);
342
2/4
✓ Branch 1 taken 216 times.
✗ Branch 2 not taken.
✓ Branch 6 taken 216 times.
✗ Branch 7 not taken.
216 AppendJointOfModelAlgo::run(modelA.joints[*jid], args);
343 }
344
345 // Copy modelB joints
346
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
10 details::appendUniverseToModel(
347
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
10 modelB, geomModelB, details::getFrameId(modelA, model, frame.name, frame.type), aMb, model,
348 geomModel);
349
2/2
✓ Branch 1 taken 51 times.
✓ Branch 2 taken 10 times.
61 for (JointIndex jid = 1; jid < modelB.joints.size(); ++jid)
350 {
351
4/6
✓ Branch 1 taken 11 times.
✓ Branch 2 taken 40 times.
✓ Branch 4 taken 11 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 40 times.
✗ Branch 8 not taken.
51 SE3 pMi = (modelB.parents[jid] == 0 ? frame.placement * aMb : id);
352
1/2
✓ Branch 1 taken 51 times.
✗ Branch 2 not taken.
51 ArgsType args(modelB, geomModelB, frame.parentJoint, pMi, model, geomModel);
353
2/4
✓ Branch 1 taken 51 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 51 times.
✗ Branch 6 not taken.
51 AppendJointOfModelAlgo::run(modelB.joints[jid], args);
354 }
355
356 // Copy remaining joints of modelA
357 // Copy modelA joints that should come before model B
358 10 for (std::vector<JointIndex>::const_iterator jid = AJointsAfterB.begin();
359
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 10 times.
10 jid != AJointsAfterB.end(); ++jid)
360 {
361 ArgsType args(modelA, geomModelA, 0, id, model, geomModel);
362 AppendJointOfModelAlgo::run(modelA.joints[*jid], args);
363 }
364
365 // Retrieve and set the reference configurations
366 typedef typename Model::ConfigVectorMap ConfigVectorMap;
367
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
10 typename Model::ConfigVectorType neutral_config_vector(model.nq);
368 // Get neutral configuration
369
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
10 neutral(model, neutral_config_vector);
370
371 // Get all reference keys from ModelA
372 10 for (typename ConfigVectorMap::const_iterator config_it =
373 10 modelA.referenceConfigurations.begin();
374
2/2
✓ Branch 3 taken 16 times.
✓ Branch 4 taken 10 times.
26 config_it != modelA.referenceConfigurations.end(); ++config_it)
375 {
376 16 const std::string & config_name = config_it->first;
377 16 const typename Model::ConfigVectorType & config_vectorA = config_it->second;
378
379
1/2
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
16 typename Model::ConfigVectorType config_vector(neutral_config_vector);
380
2/2
✓ Branch 1 taken 418 times.
✓ Branch 2 taken 16 times.
434 for (JointIndex joint_idA = 1; joint_idA < modelA.joints.size(); ++joint_idA)
381 {
382
1/2
✓ Branch 2 taken 418 times.
✗ Branch 3 not taken.
418 const JointIndex joint_id = model.getJointId(modelA.names[joint_idA]);
383 418 const typename Model::JointModel & joint_model = model.joints[joint_id];
384 418 const typename Model::JointModel & joint_modelA = modelA.joints[joint_idA];
385
386
2/4
✓ Branch 1 taken 418 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 418 times.
✗ Branch 5 not taken.
418 joint_model.jointConfigSelector(config_vector) =
387
1/2
✓ Branch 1 taken 418 times.
✗ Branch 2 not taken.
836 joint_modelA.jointConfigSelector(config_vectorA);
388 }
389
390
2/4
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 16 times.
✗ Branch 5 not taken.
16 model.referenceConfigurations.insert(std::make_pair(config_name, config_vector));
391 }
392
393 // Get all reference keys from ModelB
394 10 for (typename ConfigVectorMap::const_iterator config_it =
395 10 modelB.referenceConfigurations.begin();
396
2/2
✓ Branch 3 taken 16 times.
✓ Branch 4 taken 10 times.
26 config_it != modelB.referenceConfigurations.end(); ++config_it)
397 {
398 16 const std::string & config_name = config_it->first;
399 16 const typename Model::ConfigVectorType & config_vectorB = config_it->second;
400
401
3/4
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 9 times.
✓ Branch 6 taken 7 times.
16 if (model.referenceConfigurations.find(config_name) == model.referenceConfigurations.end())
402 {
403 // not found
404
2/4
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 9 times.
✗ Branch 5 not taken.
9 model.referenceConfigurations.insert(std::make_pair(config_name, neutral_config_vector));
405 }
406
407 16 typename Model::ConfigVectorType & config_vector =
408
1/2
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
16 model.referenceConfigurations.find(config_name)->second;
409
2/2
✓ Branch 1 taken 96 times.
✓ Branch 2 taken 16 times.
112 for (JointIndex joint_idB = 1; joint_idB < modelB.joints.size(); ++joint_idB)
410 {
411
1/2
✓ Branch 2 taken 96 times.
✗ Branch 3 not taken.
96 const JointIndex joint_id = model.getJointId(modelB.names[joint_idB]);
412 96 const typename Model::JointModel & joint_model = model.joints[joint_id];
413 96 const typename Model::JointModel & joint_modelB = modelB.joints[joint_idB];
414
415
2/4
✓ Branch 1 taken 96 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 96 times.
✗ Branch 5 not taken.
96 joint_model.jointConfigSelector(config_vector) =
416
1/2
✓ Branch 1 taken 96 times.
✗ Branch 2 not taken.
192 joint_modelB.jointConfigSelector(config_vectorB);
417 }
418 }
419
420 #ifdef PINOCCHIO_WITH_HPP_FCL
421 // Add collision pairs of geomModelA and geomModelB
422 20 geomModel.collisionPairs.reserve(
423 10 geomModelA.collisionPairs.size() + geomModelB.collisionPairs.size()
424
1/2
✓ Branch 3 taken 10 times.
✗ Branch 4 not taken.
10 + geomModelA.geometryObjects.size() * geomModelB.geometryObjects.size());
425
426
2/2
✓ Branch 1 taken 1041 times.
✓ Branch 2 taken 10 times.
1051 for (std::size_t icp = 0; icp < geomModelA.collisionPairs.size(); ++icp)
427 {
428 1041 const CollisionPair & cp = geomModelA.collisionPairs[icp];
429
1/2
✓ Branch 2 taken 1041 times.
✗ Branch 3 not taken.
1041 GeomIndex go1 = geomModel.getGeometryId(geomModelA.geometryObjects[cp.first].name);
430
1/2
✓ Branch 2 taken 1041 times.
✗ Branch 3 not taken.
1041 GeomIndex go2 = geomModel.getGeometryId(geomModelA.geometryObjects[cp.second].name);
431
2/4
✓ Branch 1 taken 1041 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1041 times.
✗ Branch 5 not taken.
1041 geomModel.addCollisionPair(CollisionPair(go1, go2));
432 }
433
434
2/2
✓ Branch 1 taken 56 times.
✓ Branch 2 taken 10 times.
66 for (std::size_t icp = 0; icp < geomModelB.collisionPairs.size(); ++icp)
435 {
436 56 const CollisionPair & cp = geomModelB.collisionPairs[icp];
437
1/2
✓ Branch 2 taken 56 times.
✗ Branch 3 not taken.
56 GeomIndex go1 = geomModel.getGeometryId(geomModelB.geometryObjects[cp.first].name);
438
1/2
✓ Branch 2 taken 56 times.
✗ Branch 3 not taken.
56 GeomIndex go2 = geomModel.getGeometryId(geomModelB.geometryObjects[cp.second].name);
439
2/4
✓ Branch 1 taken 56 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 56 times.
✗ Branch 5 not taken.
56 geomModel.addCollisionPair(CollisionPair(go1, go2));
440 }
441
442 // add the collision pairs between geomModelA and geomModelB.
443
2/2
✓ Branch 1 taken 88 times.
✓ Branch 2 taken 10 times.
98 for (Index i = 0; i < geomModelA.geometryObjects.size(); ++i)
444 {
445
1/2
✓ Branch 2 taken 88 times.
✗ Branch 3 not taken.
88 GeomIndex go1 = geomModel.getGeometryId(geomModelA.geometryObjects[i].name);
446
2/2
✓ Branch 1 taken 500 times.
✓ Branch 2 taken 88 times.
588 for (Index j = 0; j < geomModelB.geometryObjects.size(); ++j)
447 {
448
1/2
✓ Branch 2 taken 500 times.
✗ Branch 3 not taken.
500 GeomIndex go2 = geomModel.getGeometryId(geomModelB.geometryObjects[j].name);
449 500 if (
450
1/2
✓ Branch 2 taken 500 times.
✗ Branch 3 not taken.
500 geomModel.geometryObjects[go1].parentJoint != geomModel.geometryObjects[go2].parentJoint)
451
2/4
✓ Branch 1 taken 500 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 500 times.
✗ Branch 5 not taken.
500 geomModel.addCollisionPair(CollisionPair(go1, go2));
452 }
453 }
454 #endif
455 10 }
456
457 template<
458 typename Scalar,
459 int Options,
460 template<typename, int> class JointCollectionTpl,
461 typename ConfigVectorType>
462 15 void buildReducedModel(
463 const ModelTpl<Scalar, Options, JointCollectionTpl> & input_model,
464 std::vector<JointIndex> list_of_joints_to_lock,
465 const Eigen::MatrixBase<ConfigVectorType> & reference_configuration,
466 ModelTpl<Scalar, Options, JointCollectionTpl> & reduced_model)
467 {
468
1/24
✗ Branch 1 not taken.
✓ Branch 2 taken 15 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
15 PINOCCHIO_CHECK_ARGUMENT_SIZE(
469 reference_configuration.size(), input_model.nq,
470 "The configuration vector is not of right size");
471
1/4
✗ Branch 1 not taken.
✓ Branch 2 taken 15 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
15 PINOCCHIO_CHECK_INPUT_ARGUMENT(
472 list_of_joints_to_lock.size() <= (size_t)input_model.njoints,
473 "The number of joints to lock is greater than the total of joints in the reduced_model");
474
475 typedef ModelTpl<Scalar, Options, JointCollectionTpl> Model;
476 typedef typename Model::JointModel JointModel;
477 typedef typename Model::JointData JointData;
478 typedef typename Model::Frame Frame;
479 typedef typename Model::SE3 SE3;
480
481 // Sort indexes
482
1/2
✓ Branch 3 taken 15 times.
✗ Branch 4 not taken.
15 std::sort(list_of_joints_to_lock.begin(), list_of_joints_to_lock.end());
483
484 15 typename Model::FrameVector::const_iterator frame_it = input_model.frames.begin();
485
486 // Check that they are not two identical elements
487
2/2
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 15 times.
31 for (size_t id = 1; id < list_of_joints_to_lock.size(); ++id)
488 {
489
1/4
✗ Branch 2 not taken.
✓ Branch 3 taken 16 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
16 PINOCCHIO_CHECK_INPUT_ARGUMENT(
490 list_of_joints_to_lock[id - 1] < list_of_joints_to_lock[id],
491 "The input list_of_joints_to_lock contains two identical indexes.");
492 }
493
494 // Reserve memory
495 15 const Eigen::DenseIndex njoints =
496 15 input_model.njoints - (Eigen::DenseIndex)list_of_joints_to_lock.size();
497
1/2
✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
15 reduced_model.names.reserve((size_t)njoints);
498
1/2
✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
15 reduced_model.joints.reserve((size_t)njoints);
499
1/2
✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
15 reduced_model.jointPlacements.reserve((size_t)njoints);
500
1/2
✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
15 reduced_model.parents.reserve((size_t)njoints);
501
1/2
✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
15 reduced_model.inertias.reserve((size_t)njoints);
502
503
1/2
✓ Branch 3 taken 15 times.
✗ Branch 4 not taken.
15 reduced_model.names[0] = input_model.names[0];
504
1/2
✓ Branch 3 taken 15 times.
✗ Branch 4 not taken.
15 reduced_model.joints[0] = input_model.joints[0];
505
1/2
✓ Branch 3 taken 15 times.
✗ Branch 4 not taken.
15 reduced_model.jointPlacements[0] = input_model.jointPlacements[0];
506 15 reduced_model.parents[0] = input_model.parents[0];
507
1/2
✓ Branch 3 taken 15 times.
✗ Branch 4 not taken.
15 reduced_model.inertias[0] = input_model.inertias[0];
508
509
1/2
✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
15 reduced_model.name = input_model.name;
510
1/2
✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
15 reduced_model.gravity = input_model.gravity;
511
512 15 size_t current_index_to_lock = 0;
513
514
2/2
✓ Branch 0 taken 297 times.
✓ Branch 1 taken 15 times.
312 for (JointIndex joint_id = 1; joint_id < (JointIndex)input_model.njoints; ++joint_id)
515 {
516
517 297 const JointIndex joint_id_to_lock = (current_index_to_lock < list_of_joints_to_lock.size())
518
2/2
✓ Branch 0 taken 151 times.
✓ Branch 1 taken 146 times.
297 ? list_of_joints_to_lock[current_index_to_lock]
519 : 0;
520
521 297 const JointIndex input_parent_joint_index = input_model.parents[joint_id];
522 297 const std::string & joint_name = input_model.names[joint_id];
523 297 const JointModel & joint_input_model = input_model.joints[joint_id];
524
525 // retrieve the closest joint parent in the new kinematic tree
526 297 const std::string & parent_joint_name = input_model.names[input_parent_joint_index];
527
1/2
✓ Branch 1 taken 297 times.
✗ Branch 2 not taken.
297 const bool exist_parent_joint = reduced_model.existJointName(parent_joint_name);
528
529
2/2
✓ Branch 0 taken 274 times.
✓ Branch 1 taken 23 times.
297 const JointIndex reduced_parent_joint_index =
530 exist_parent_joint
531
3/4
✓ Branch 0 taken 274 times.
✓ Branch 1 taken 23 times.
✓ Branch 3 taken 274 times.
✗ Branch 4 not taken.
320 ? reduced_model.getJointId(parent_joint_name)
532
1/2
✓ Branch 1 taken 23 times.
✗ Branch 2 not taken.
23 : reduced_model.frames[reduced_model.getFrameId(parent_joint_name)].parentJoint;
533
534
3/4
✓ Branch 0 taken 274 times.
✓ Branch 1 taken 23 times.
✓ Branch 3 taken 274 times.
✗ Branch 4 not taken.
297 const SE3 parent_frame_placement =
535 exist_parent_joint
536 ? SE3::Identity()
537
2/4
✓ Branch 1 taken 23 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 23 times.
✗ Branch 6 not taken.
23 : reduced_model.frames[reduced_model.getFrameId(parent_joint_name)].placement;
538
539
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 270 times.
297 const FrameIndex reduced_previous_frame_index =
540
3/4
✓ Branch 0 taken 274 times.
✓ Branch 1 taken 23 times.
✓ Branch 3 taken 23 times.
✗ Branch 4 not taken.
297 exist_parent_joint ? 0 : reduced_model.getFrameId(parent_joint_name);
541
542
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 270 times.
297 if (joint_id == joint_id_to_lock)
543 {
544 // the joint should not be added to the Model but aggragated to its parent joint
545 // Add frames up to the joint to lock
546
1/2
✓ Branch 2 taken 358 times.
✗ Branch 3 not taken.
358 while ((*frame_it).name != joint_name)
547 {
548 358 ++frame_it;
549 358 const Frame & input_frame = *frame_it;
550
2/2
✓ Branch 1 taken 27 times.
✓ Branch 2 taken 331 times.
358 if (input_frame.name == joint_name)
551 27 break;
552 331 const std::string & support_joint_name = input_model.names[input_frame.parent];
553
554
1/2
✓ Branch 2 taken 331 times.
✗ Branch 3 not taken.
331 std::vector<JointIndex>::const_iterator support_joint_it = std::find(
555 331 list_of_joints_to_lock.begin(), list_of_joints_to_lock.end(), input_frame.parent);
556
557
2/2
✓ Branch 2 taken 16 times.
✓ Branch 3 taken 315 times.
331 if (support_joint_it != list_of_joints_to_lock.end())
558 {
559
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (
560 input_frame.type == JOINT && reduced_model.existFrame(input_frame.name)
561
2/6
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 16 times.
16 && support_joint_name == input_frame.name)
562 continue; // this means that the Joint is now fixed and has been replaced by a Frame.
563 // No need to add a new one.
564
565 // The joint has been removed and replaced by a Frame
566
1/2
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
16 const FrameIndex joint_frame_id = reduced_model.getFrameId(support_joint_name);
567 16 const Frame & joint_frame = reduced_model.frames[joint_frame_id];
568
1/2
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
16 Frame reduced_frame = input_frame;
569
2/4
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 16 times.
✗ Branch 5 not taken.
16 reduced_frame.placement = joint_frame.placement * input_frame.placement;
570 16 reduced_frame.parent = joint_frame.parent;
571 32 reduced_frame.previousFrame =
572
2/4
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 16 times.
✗ Branch 6 not taken.
16 reduced_model.getFrameId(input_model.frames[input_frame.previousFrame].name);
573
1/2
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
16 reduced_model.addFrame(reduced_frame, false);
574 16 }
575 else
576 {
577
1/2
✓ Branch 1 taken 315 times.
✗ Branch 2 not taken.
315 Frame reduced_frame = input_frame;
578
1/2
✓ Branch 2 taken 315 times.
✗ Branch 3 not taken.
315 reduced_frame.parent = reduced_model.getJointId(input_model.names[input_frame.parent]);
579 630 reduced_frame.previousFrame =
580
2/4
✓ Branch 2 taken 315 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 315 times.
✗ Branch 6 not taken.
315 reduced_model.getFrameId(input_model.frames[input_frame.previousFrame].name);
581
1/2
✓ Branch 1 taken 315 times.
✗ Branch 2 not taken.
315 reduced_model.addFrame(reduced_frame, false);
582 315 }
583 }
584
585 // Compute the new placement of the joint with respect to its parent joint in the new
586 // kinematic tree.
587
1/2
✓ Branch 1 taken 27 times.
✗ Branch 2 not taken.
27 JointData joint_data = joint_input_model.createData();
588
1/2
✓ Branch 1 taken 27 times.
✗ Branch 2 not taken.
27 joint_input_model.calc(joint_data, reference_configuration);
589
3/6
✓ Branch 1 taken 27 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 27 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 27 times.
✗ Branch 8 not taken.
54 const SE3 liMi =
590 27 parent_frame_placement * input_model.jointPlacements[joint_id] * joint_data.M();
591
592
1/2
✓ Branch 1 taken 27 times.
✗ Branch 2 not taken.
27 Frame frame = Frame(
593 joint_name, reduced_parent_joint_index, reduced_previous_frame_index, liMi, FIXED_JOINT,
594 27 input_model.inertias[joint_id]);
595
596
1/2
✓ Branch 1 taken 27 times.
✗ Branch 2 not taken.
27 FrameIndex frame_id = reduced_model.addFrame(frame);
597 27 reduced_model.frames[frame_id].parentFrame =
598 frame_id; // a bit weird, but this is a solution for missing parent frame
599
600 27 current_index_to_lock++;
601 27 }
602 else
603 {
604 // the joint should be added to the Model as it is
605
8/16
✓ Branch 1 taken 270 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 270 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 270 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 270 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 270 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 270 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 270 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 270 times.
✗ Branch 23 not taken.
1890 JointIndex reduced_joint_id = reduced_model.addJoint(
606 reduced_parent_joint_index, joint_input_model,
607 270 parent_frame_placement * input_model.jointPlacements[joint_id], joint_name,
608
1/2
✓ Branch 1 taken 270 times.
✗ Branch 2 not taken.
540 joint_input_model.jointVelocitySelector(input_model.effortLimit),
609
1/2
✓ Branch 1 taken 270 times.
✗ Branch 2 not taken.
540 joint_input_model.jointVelocitySelector(input_model.velocityLimit),
610
1/2
✓ Branch 1 taken 270 times.
✗ Branch 2 not taken.
540 joint_input_model.jointConfigSelector(input_model.lowerPositionLimit),
611
1/2
✓ Branch 1 taken 270 times.
✗ Branch 2 not taken.
540 joint_input_model.jointConfigSelector(input_model.upperPositionLimit),
612
1/2
✓ Branch 1 taken 270 times.
✗ Branch 2 not taken.
540 joint_input_model.jointVelocitySelector(input_model.friction),
613
1/2
✓ Branch 1 taken 270 times.
✗ Branch 2 not taken.
270 joint_input_model.jointVelocitySelector(input_model.damping));
614 // Append inertia
615
2/4
✓ Branch 1 taken 270 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 270 times.
✗ Branch 5 not taken.
540 reduced_model.appendBodyToJoint(
616 270 reduced_joint_id, input_model.inertias[joint_id], SE3::Identity());
617
618 // Copy other kinematics and dynamics properties
619 270 const typename Model::JointModel & jmodel_out = reduced_model.joints[reduced_joint_id];
620
2/4
✓ Branch 1 taken 270 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 270 times.
✗ Branch 5 not taken.
270 jmodel_out.jointVelocitySelector(reduced_model.rotorInertia) =
621
1/2
✓ Branch 1 taken 270 times.
✗ Branch 2 not taken.
270 joint_input_model.jointVelocitySelector(input_model.rotorInertia);
622
2/4
✓ Branch 1 taken 270 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 270 times.
✗ Branch 5 not taken.
270 jmodel_out.jointVelocitySelector(reduced_model.rotorGearRatio) =
623
1/2
✓ Branch 1 taken 270 times.
✗ Branch 2 not taken.
540 joint_input_model.jointVelocitySelector(input_model.rotorGearRatio);
624 }
625 }
626
627 // Retrieve and extend the reference configurations
628 typedef typename Model::ConfigVectorMap ConfigVectorMap;
629 15 for (typename ConfigVectorMap::const_iterator config_it =
630 15 input_model.referenceConfigurations.begin();
631
2/2
✓ Branch 3 taken 5 times.
✓ Branch 4 taken 15 times.
20 config_it != input_model.referenceConfigurations.end(); ++config_it)
632 {
633 5 const std::string & config_name = config_it->first;
634 5 const typename Model::ConfigVectorType & input_config_vector = config_it->second;
635
636
1/2
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
5 typename Model::ConfigVectorType reduced_config_vector(reduced_model.nq);
637
2/2
✓ Branch 1 taken 141 times.
✓ Branch 2 taken 5 times.
146 for (JointIndex reduced_joint_id = 1; reduced_joint_id < reduced_model.joints.size();
638 ++reduced_joint_id)
639 {
640 const JointIndex input_joint_id =
641
1/2
✓ Branch 2 taken 141 times.
✗ Branch 3 not taken.
141 input_model.getJointId(reduced_model.names[reduced_joint_id]);
642 141 const JointModel & input_joint_model = input_model.joints[input_joint_id];
643 141 const JointModel & reduced_joint_model = reduced_model.joints[reduced_joint_id];
644
645
2/4
✓ Branch 1 taken 141 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 141 times.
✗ Branch 5 not taken.
141 reduced_joint_model.jointConfigSelector(reduced_config_vector) =
646
1/2
✓ Branch 1 taken 141 times.
✗ Branch 2 not taken.
282 input_joint_model.jointConfigSelector(input_config_vector);
647 }
648
649
2/4
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
5 reduced_model.referenceConfigurations.insert(
650 std::make_pair(config_name, reduced_config_vector));
651 }
652
653 // Add all the missing frames
654
2/2
✓ Branch 3 taken 404 times.
✓ Branch 4 taken 15 times.
419 for (; frame_it != input_model.frames.end(); ++frame_it)
655 {
656 404 const Frame & input_frame = *frame_it;
657 404 const std::string & support_joint_name = input_model.names[input_frame.parentJoint];
658
659
1/2
✓ Branch 2 taken 404 times.
✗ Branch 3 not taken.
404 std::vector<JointIndex>::const_iterator support_joint_it = std::find(
660 404 list_of_joints_to_lock.begin(), list_of_joints_to_lock.end(), input_frame.parentJoint);
661
662
2/2
✓ Branch 2 taken 46 times.
✓ Branch 3 taken 358 times.
404 if (support_joint_it != list_of_joints_to_lock.end())
663 {
664
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 35 times.
46 if (
665
2/4
✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 11 times.
✗ Branch 4 not taken.
11 input_frame.type == JOINT && reduced_model.existFrame(input_frame.name)
666
5/6
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 35 times.
✓ Branch 3 taken 11 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 11 times.
✓ Branch 6 taken 35 times.
57 && support_joint_name == input_frame.name)
667 11 continue; // this means that the Joint is now fixed and has been replaced by a Frame. No
668 // need to add a new one.
669
670 // The joint has been removed and replaced by a Frame
671
1/2
✓ Branch 1 taken 35 times.
✗ Branch 2 not taken.
35 const FrameIndex joint_frame_id = reduced_model.getFrameId(support_joint_name);
672 35 const Frame & joint_frame = reduced_model.frames[joint_frame_id];
673
1/2
✓ Branch 1 taken 35 times.
✗ Branch 2 not taken.
35 Frame reduced_frame = input_frame;
674
2/4
✓ Branch 1 taken 35 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 35 times.
✗ Branch 5 not taken.
35 reduced_frame.placement = joint_frame.placement * input_frame.placement;
675 35 reduced_frame.parentJoint = joint_frame.parentJoint;
676 35 reduced_frame.parentFrame =
677
2/4
✓ Branch 2 taken 35 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 35 times.
✗ Branch 6 not taken.
35 reduced_model.getFrameId(input_model.frames[input_frame.parentFrame].name);
678
1/2
✓ Branch 1 taken 35 times.
✗ Branch 2 not taken.
35 reduced_model.addFrame(reduced_frame, false);
679 35 }
680 else
681 {
682
1/2
✓ Branch 1 taken 358 times.
✗ Branch 2 not taken.
358 Frame reduced_frame = input_frame;
683 358 reduced_frame.parentJoint =
684
1/2
✓ Branch 2 taken 358 times.
✗ Branch 3 not taken.
358 reduced_model.getJointId(input_model.names[input_frame.parentJoint]);
685 358 reduced_frame.parentFrame =
686
2/4
✓ Branch 2 taken 358 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 358 times.
✗ Branch 6 not taken.
358 reduced_model.getFrameId(input_model.frames[input_frame.parentFrame].name);
687
1/2
✓ Branch 1 taken 358 times.
✗ Branch 2 not taken.
358 reduced_model.addFrame(reduced_frame, false);
688 358 }
689 }
690 15 }
691
692 template<
693 typename Scalar,
694 int Options,
695 template<typename, int> class JointCollectionTpl,
696 typename ConfigVectorType>
697 3 void buildReducedModel(
698 const ModelTpl<Scalar, Options, JointCollectionTpl> & input_model,
699 const GeometryModel & input_geom_model,
700 const std::vector<JointIndex> & list_of_joints_to_lock,
701 const Eigen::MatrixBase<ConfigVectorType> & reference_configuration,
702 ModelTpl<Scalar, Options, JointCollectionTpl> & reduced_model,
703 GeometryModel & reduced_geom_model)
704 {
705
706
1/2
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
3 const std::vector<GeometryModel> temp_input_geoms(1, input_geom_model);
707 3 std::vector<GeometryModel> temp_reduced_geom_models;
708
709
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 buildReducedModel(
710 input_model, temp_input_geoms, list_of_joints_to_lock, reference_configuration, reduced_model,
711 temp_reduced_geom_models);
712
1/2
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
3 reduced_geom_model = temp_reduced_geom_models.front();
713 3 }
714
715 template<
716 typename Scalar,
717 int Options,
718 template<typename, int> class JointCollectionTpl,
719 typename GeometryModelAllocator,
720 typename ConfigVectorType>
721 11 void buildReducedModel(
722 const ModelTpl<Scalar, Options, JointCollectionTpl> & input_model,
723 const std::vector<GeometryModel, GeometryModelAllocator> & list_of_geom_models,
724 const std::vector<JointIndex> & list_of_joints_to_lock,
725 const Eigen::MatrixBase<ConfigVectorType> & reference_configuration,
726 ModelTpl<Scalar, Options, JointCollectionTpl> & reduced_model,
727 std::vector<GeometryModel, GeometryModelAllocator> & list_of_reduced_geom_models)
728 {
729
730 typedef ModelTpl<Scalar, Options, JointCollectionTpl> Model;
731
1/2
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
11 buildReducedModel(input_model, list_of_joints_to_lock, reference_configuration, reduced_model);
732
733 // for all GeometryModels
734
2/2
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 6 times.
28 for (size_t gmi = 0; gmi < list_of_geom_models.size(); ++gmi)
735 {
736 17 const GeometryModel & input_geom_model = list_of_geom_models[gmi];
737
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
17 GeometryModel reduced_geom_model;
738
739 // Add all the geometries
740 typedef GeometryModel::GeometryObject GeometryObject;
741 typedef GeometryModel::GeometryObjectVector GeometryObjectVector;
742 280 for (GeometryObjectVector::const_iterator it = input_geom_model.geometryObjects.begin();
743
2/2
✓ Branch 3 taken 172 times.
✓ Branch 4 taken 10 times.
280 it != input_geom_model.geometryObjects.end(); ++it)
744 {
745 263 const GeometryModel::GeometryObject & geom = *it;
746
747 263 const JointIndex joint_id_in_input_model = geom.parentJoint;
748
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 172 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
263 _PINOCCHIO_CHECK_INPUT_ARGUMENT_2(
749 (joint_id_in_input_model < (JointIndex)input_model.njoints),
750 "Invalid joint parent index for the geometry with name " + geom.name);
751 263 const std::string & parent_joint_name = input_model.names[joint_id_in_input_model];
752
753 263 JointIndex reduced_joint_id = (JointIndex)-1;
754 typedef typename Model::SE3 SE3;
755
1/2
✓ Branch 1 taken 172 times.
✗ Branch 2 not taken.
263 SE3 relative_placement = SE3::Identity();
756
3/4
✓ Branch 1 taken 172 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 155 times.
✓ Branch 4 taken 17 times.
263 if (reduced_model.existJointName(parent_joint_name))
757 {
758
1/2
✓ Branch 1 taken 155 times.
✗ Branch 2 not taken.
229 reduced_joint_id = reduced_model.getJointId(parent_joint_name);
759 }
760 else // The joint is now a frame
761 {
762
1/2
✓ Branch 1 taken 17 times.
✗ Branch 2 not taken.
34 const FrameIndex reduced_frame_id = reduced_model.getFrameId(parent_joint_name);
763 34 reduced_joint_id = reduced_model.frames[reduced_frame_id].parentJoint;
764
1/2
✓ Branch 2 taken 17 times.
✗ Branch 3 not taken.
34 relative_placement = reduced_model.frames[reduced_frame_id].placement;
765 }
766
767
1/2
✓ Branch 1 taken 172 times.
✗ Branch 2 not taken.
263 GeometryObject reduced_geom(geom);
768 263 reduced_geom.parentJoint = reduced_joint_id;
769 263 reduced_geom.parentFrame =
770
1/2
✓ Branch 2 taken 172 times.
✗ Branch 3 not taken.
263 reduced_model.getBodyId(input_model.frames[geom.parentFrame].name);
771
2/4
✓ Branch 1 taken 172 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 172 times.
✗ Branch 5 not taken.
263 reduced_geom.placement = relative_placement * geom.placement;
772
1/2
✓ Branch 1 taken 172 times.
✗ Branch 2 not taken.
263 reduced_geom_model.addGeometryObject(reduced_geom);
773 }
774
775 #ifdef PINOCCHIO_WITH_HPP_FCL
776 // Add all the collision pairs - the index of the geometry objects should have not changed
777
778 typedef GeometryModel::CollisionPairVector CollisionPairVector;
779 17 for (CollisionPairVector::const_iterator it = input_geom_model.collisionPairs.begin();
780
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 10 times.
17 it != input_geom_model.collisionPairs.end(); ++it)
781 {
782 const CollisionPair & cp = *it;
783 reduced_geom_model.addCollisionPair(cp);
784 }
785 #endif
786
787
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
17 list_of_reduced_geom_models.push_back(reduced_geom_model);
788 }
789 11 }
790
791 template<typename Scalar, int Options, template<typename, int> class JointCollectionTpl>
792 4 JointIndex findCommonAncestor(
793 const ModelTpl<Scalar, Options, JointCollectionTpl> & model,
794 JointIndex joint1_id,
795 JointIndex joint2_id,
796 size_t & index_ancestor_in_support1,
797 size_t & index_ancestor_in_support2)
798 {
799
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
4 PINOCCHIO_CHECK_INPUT_ARGUMENT(
800 joint1_id < (JointIndex)model.njoints, "joint1_id is not valid.");
801
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
4 PINOCCHIO_CHECK_INPUT_ARGUMENT(
802 joint2_id < (JointIndex)model.njoints, "joint2_id is not valid.");
803
804 typedef ModelTpl<Scalar, Options, JointCollectionTpl> Model;
805 typedef typename Model::IndexVector IndexVector;
806
807
4/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1 times.
4 if (joint1_id == 0 || joint2_id == 0)
808 {
809 3 index_ancestor_in_support1 = index_ancestor_in_support2 = 0;
810 3 return 0;
811 }
812
813 1 const IndexVector & support1 = model.supports[joint1_id];
814 1 const IndexVector & support2 = model.supports[joint2_id];
815
816 1 index_ancestor_in_support1 = support1.size() - 1;
817 1 index_ancestor_in_support2 = support2.size() - 1;
818
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 1 times.
9 while (joint1_id != joint2_id)
819 {
820
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 if (joint1_id > joint2_id)
821 8 joint1_id = support1[--index_ancestor_in_support1];
822 else
823 joint2_id = support2[--index_ancestor_in_support2];
824 }
825
826 1 return joint1_id;
827 }
828
829 } // namespace pinocchio
830
831 #endif // ifndef __pinocchio_algorithm_model_hxx__
832