Rigid Body Dynamics Library
Model.cc
Go to the documentation of this file.
1/*
2 * RBDL - Rigid Body Dynamics Library
3 * Copyright (c) 2011-2018 Martin Felis <martin@fysx.org>
4 *
5 * Licensed under the zlib license. See LICENSE for more details.
6 */
7
8#include <iostream>
9#include <limits>
10#include <assert.h>
11
12#include "rbdl/rbdl_mathutils.h"
13
14#include "rbdl/Logging.h"
15
16#include "rbdl/Model.h"
17#include "rbdl/Body.h"
18#include "rbdl/Joint.h"
19
20using namespace RigidBodyDynamics;
21using namespace RigidBodyDynamics::Math;
22
23Model::Model()
24{
25 Body root_body;
26 Joint root_joint;
27
28 Vector3d zero_position (0., 0., 0.);
29 SpatialVector zero_spatial (0., 0., 0., 0., 0., 0.);
30
31 // structural information
32 lambda.push_back(0);
33 lambda_q.push_back(0);
34 mu.push_back(std::vector<unsigned int>());
35 dof_count = 0;
36 q_size = 0;
37 qdot_size = 0;
38 previously_added_body_id = 0;
39
40 gravity = Vector3d (0., -9.81, 0.);
41
42 // state information
43 v.push_back(zero_spatial);
44 a.push_back(zero_spatial);
45
46 // Joints
47 mJoints.push_back(root_joint);
48 S.push_back (zero_spatial);
49 X_T.push_back(SpatialTransform());
50
51 v_J.push_back (zero_spatial);
52 c_J.push_back (zero_spatial);
53
54 // Spherical joints
55 multdof3_S.push_back (Matrix63::Zero());
56 multdof3_U.push_back (Matrix63::Zero());
57 multdof3_Dinv.push_back (Matrix3d::Zero());
58 multdof3_u.push_back (Vector3d::Zero());
59 multdof3_w_index.push_back (0);
60
61 // Dynamic variables
62 c.push_back(zero_spatial);
63 IA.push_back(SpatialMatrix::Identity());
64 pA.push_back(zero_spatial);
65 U.push_back(zero_spatial);
66
67 u = VectorNd::Zero(1);
68 d = VectorNd::Zero(1);
69
70 f.push_back (zero_spatial);
72 Vector3d (0., 0., 0.),
73 Matrix3d::Zero());
74 Ic.push_back (rbi);
75 I.push_back(rbi);
76 hc.push_back (zero_spatial);
77 hdotc.push_back (zero_spatial);
78
79 // Bodies
80 X_lambda.push_back(SpatialTransform());
81 X_base.push_back(SpatialTransform());
82
83 mBodies.push_back(root_body);
84 mBodyNameMap["ROOT"] = 0;
85
86 fixed_body_discriminator = std::numeric_limits<unsigned int>::max() / 2;
87}
88
89unsigned int AddBodyFixedJoint (
90 Model &model,
91 const unsigned int parent_id,
92 const SpatialTransform &joint_frame,
93 const Joint &joint,
94 const Body &body,
95 std::string body_name)
96{
97 FixedBody fbody = FixedBody::CreateFromBody (body);
98 fbody.mMovableParent = parent_id;
99 fbody.mParentTransform = joint_frame;
100
101 if (model.IsFixedBodyId(parent_id)) {
102 FixedBody fixed_parent =
103 model.mFixedBodies[parent_id - model.fixed_body_discriminator];
104
105 fbody.mMovableParent = fixed_parent.mMovableParent;
106 fbody.mParentTransform = joint_frame * fixed_parent.mParentTransform;
107 }
108
109 // merge the two bodies
110 Body parent_body = model.mBodies[fbody.mMovableParent];
111 parent_body.Join (fbody.mParentTransform, body);
112 model.mBodies[fbody.mMovableParent] = parent_body;
113 model.I[fbody.mMovableParent] =
114 SpatialRigidBodyInertia::createFromMassComInertiaC (
115 parent_body.mMass,
116 parent_body.mCenterOfMass,
117 parent_body.mInertia);
118
119 model.mFixedBodies.push_back (fbody);
120
121 if (model.mFixedBodies.size() > std::numeric_limits<unsigned int>::max() -
122 model.fixed_body_discriminator) {
123 std::ostringstream errormsg;
124 errormsg << "Error: cannot add more than "
125 << std::numeric_limits<unsigned int>::max() - model.mFixedBodies.size()
126 << " fixed bodies. You need to modify "
127 << "Model::fixed_body_discriminator for this."
128 << std::endl;
129 throw Errors::RBDLError(errormsg.str());
130 }
131
132 if (body_name.size() != 0) {
133 if (model.mBodyNameMap.find(body_name) != model.mBodyNameMap.end()) {
134 std::ostringstream errormsg;
135 errormsg << "Error: Body with name '"
136 << body_name
137 << "' already exists!"
138 << std::endl;
139 throw Errors::RBDLError(errormsg.str());
140 }
141 model.mBodyNameMap[body_name] = model.mFixedBodies.size()
142 + model.fixed_body_discriminator - 1;
143 }
144
145 return model.mFixedBodies.size() + model.fixed_body_discriminator - 1;
146}
147
149 Model &model,
150 const unsigned int parent_id,
151 const SpatialTransform &joint_frame,
152 const Joint &joint,
153 const Body &body,
154 std::string body_name)
155{
156 // Here we emulate multi DoF joints by simply adding nullbodies. This
157 // allows us to use fixed size elements for S,v,a, etc. which is very
158 // fast in Eigen.
159 unsigned int joint_count = 0;
160 if (joint.mJointType == JointType1DoF) {
161 joint_count = 1;
162 } else if (joint.mJointType == JointType2DoF) {
163 joint_count = 2;
164 } else if (joint.mJointType == JointType3DoF) {
165 joint_count = 3;
166 } else if (joint.mJointType == JointType4DoF) {
167 joint_count = 4;
168 } else if (joint.mJointType == JointType5DoF) {
169 joint_count = 5;
170 } else if (joint.mJointType == JointType6DoF) {
171 joint_count = 6;
172 } else if (joint.mJointType == JointTypeFloatingBase)
173 // no action required
174 {}
175 else {
176 std::ostringstream errormsg;
177 errormsg << "Error: Invalid joint type: "
178 << joint.mJointType
179 << std::endl;
180 throw Errors::RBDLError(errormsg.str());
181 }
182
183 Body null_body (0., Vector3d (0., 0., 0.), Vector3d (0., 0., 0.));
184 null_body.mIsVirtual = true;
185
186 unsigned int null_parent = parent_id;
187 SpatialTransform joint_frame_transform;
188
189 if (joint.mJointType == JointTypeFloatingBase) {
190 null_parent = model.AddBody (parent_id,
191 joint_frame,
192 JointTypeTranslationXYZ,
193 null_body);
194
195 return model.AddBody (null_parent,
197 JointTypeSpherical,
198 body,
199 body_name);
200 }
201
202 Joint single_dof_joint;
203 unsigned int j;
204
205 // Here we add multiple virtual bodies that have no mass or inertia for
206 // which each is attached to the model with a single degree of freedom
207 // joint.
208 for (j = 0; j < joint_count; j++) {
209 single_dof_joint = Joint (joint.mJointAxes[j]);
210
211 if (single_dof_joint.mJointType == JointType1DoF) {
212 Vector3d rotation (
213 joint.mJointAxes[j][0],
214 joint.mJointAxes[j][1],
215 joint.mJointAxes[j][2]);
216 Vector3d translation (
217 joint.mJointAxes[j][3],
218 joint.mJointAxes[j][4],
219 joint.mJointAxes[j][5]);
220
221#ifdef RBDL_USE_CASADI_MATH
222 if (rotation.is_zero()) {
223#else
224 if (rotation == Vector3d (0., 0., 0.)) {
225#endif
226 single_dof_joint = Joint (JointTypePrismatic, translation);
227 }
228#ifdef RBDL_USE_CASADI_MATH
229 if (translation.is_zero()) {
230#else
231 else if (translation == Vector3d (0., 0., 0.)) {
232#endif
233 single_dof_joint = Joint (JointTypeRevolute, rotation);
234 }
235 }
236
237 // the first joint has to be transformed by joint_frame, all the
238 // others must have a null transformation
239 if (j == 0) {
240 joint_frame_transform = joint_frame;
241 } else {
242 joint_frame_transform = SpatialTransform();
243 }
244
245 if (j == joint_count - 1)
246 // if we are at the last we must add the real body
247 {
248 break;
249 } else {
250 // otherwise we just add an intermediate body
251 null_parent = model.AddBody (null_parent,
252 joint_frame_transform,
253 single_dof_joint,
254 null_body);
255 }
256 }
257
258 return model.AddBody (null_parent,
259 joint_frame_transform,
260 single_dof_joint,
261 body,
262 body_name);
263}
264
265unsigned int Model::AddBody(
266 const unsigned int parent_id,
267 const SpatialTransform &joint_frame,
268 const Joint &joint,
269 const Body &body,
270 std::string body_name)
271{
272 assert (lambda.size() > 0);
273 assert (joint.mJointType != JointTypeUndefined);
274
275 if (joint.mJointType == JointTypeFixed) {
276 previously_added_body_id = AddBodyFixedJoint (*this,
277 parent_id,
278 joint_frame,
279 joint,
280 body,
281 body_name);
282
283 return previously_added_body_id;
284 } else if ( (joint.mJointType == JointTypeSpherical)
285 || (joint.mJointType == JointTypeEulerZYX)
286 || (joint.mJointType == JointTypeEulerXYZ)
287 || (joint.mJointType == JointTypeEulerYXZ)
288 || (joint.mJointType == JointTypeEulerZXY)
289 || (joint.mJointType == JointTypeTranslationXYZ)
290 || (joint.mJointType == JointTypeCustom)
291 ) {
292 // no action required
293 } else if (joint.mJointType != JointTypePrismatic
294 && joint.mJointType != JointTypeRevolute
295 && joint.mJointType != JointTypeRevoluteX
296 && joint.mJointType != JointTypeRevoluteY
297 && joint.mJointType != JointTypeRevoluteZ
298 && joint.mJointType != JointTypeHelical
299 ) {
300 previously_added_body_id = AddBodyMultiDofJoint (*this,
301 parent_id,
302 joint_frame,
303 joint,
304 body,
305 body_name);
306 return previously_added_body_id;
307 }
308
309 // If we add the body to a fixed body we have to make sure that we
310 // actually add it to its movable parent.
311 unsigned int movable_parent_id = parent_id;
312 SpatialTransform movable_parent_transform;
313
314 if (IsFixedBodyId(parent_id)) {
315 unsigned int fbody_id = parent_id - fixed_body_discriminator;
316 movable_parent_id = mFixedBodies[fbody_id].mMovableParent;
317 movable_parent_transform = mFixedBodies[fbody_id].mParentTransform;
318 }
319
320 // structural information
321 lambda.push_back(movable_parent_id);
322 unsigned int lambda_q_last = mJoints[mJoints.size() - 1].q_index;
323
324 if (mJoints[mJoints.size() - 1].mDoFCount > 0
325 && mJoints[mJoints.size() - 1].mJointType != JointTypeCustom) {
326 lambda_q_last = lambda_q_last + mJoints[mJoints.size() - 1].mDoFCount;
327 } else if (mJoints[mJoints.size() - 1].mJointType == JointTypeCustom) {
328 unsigned int custom_index = mJoints[mJoints.size() - 1].custom_joint_index;
329 lambda_q_last = lambda_q_last
330 + mCustomJoints[mCustomJoints.size() - 1]->mDoFCount;
331 }
332
333 for (unsigned int i = 0; i < joint.mDoFCount; i++) {
334 lambda_q.push_back(lambda_q_last + i);
335 }
336 mu.push_back(std::vector<unsigned int>());
337 mu.at(movable_parent_id).push_back(mBodies.size());
338
339 // Bodies
340 X_lambda.push_back(SpatialTransform());
341 X_base.push_back(SpatialTransform());
342 mBodies.push_back(body);
343
344 if (body_name.size() != 0) {
345 if (mBodyNameMap.find(body_name) != mBodyNameMap.end()) {
346 std::ostringstream errormsg;
347 errormsg << "Error: Body with name '"
348 << body_name
349 << "' already exists!"
350 << std::endl;
351 throw Errors::RBDLError(errormsg.str());
352 }
353 mBodyNameMap[body_name] = mBodies.size() - 1;
354 }
355
356 // state information
357 v.push_back(SpatialVector(0., 0., 0., 0., 0., 0.));
358 a.push_back(SpatialVector(0., 0., 0., 0., 0., 0.));
359
360 // Joints
361 unsigned int prev_joint_index = mJoints.size() - 1;
362 mJoints.push_back(joint);
363
364 if (mJoints[prev_joint_index].mJointType != JointTypeCustom) {
365 mJoints[mJoints.size() - 1].q_index =
366 mJoints[prev_joint_index].q_index + mJoints[prev_joint_index].mDoFCount;
367 } else {
368 mJoints[mJoints.size() - 1].q_index =
369 mJoints[prev_joint_index].q_index + mJoints[prev_joint_index].mDoFCount;
370 }
371
372 S.push_back (joint.mJointAxes[0]);
373
374 // Joint state variables
375 v_J.push_back (joint.mJointAxes[0]);
376 c_J.push_back (SpatialVector(0., 0., 0., 0., 0., 0.));
377
378 // workspace for joints with 3 dof
379 multdof3_S.push_back (Matrix63::Zero());
380 multdof3_U.push_back (Matrix63::Zero());
381 multdof3_Dinv.push_back (Matrix3d::Zero());
382 multdof3_u.push_back (Vector3d::Zero());
383 multdof3_w_index.push_back (0);
384
385 dof_count = dof_count + joint.mDoFCount;
386
387 // update the w components of the Quaternions. They are stored at the end
388 // of the q vector
389 int multdof3_joint_counter = 0;
390 int mCustomJoint_joint_counter = 0;
391 for (unsigned int i = 1; i < mJoints.size(); i++) {
392 if (mJoints[i].mJointType == JointTypeSpherical) {
393 multdof3_w_index[i] = dof_count + multdof3_joint_counter;
394 multdof3_joint_counter++;
395 }
396 }
397
398 q_size = dof_count
399 + multdof3_joint_counter;
400
401 qdot_size = qdot_size + joint.mDoFCount;
402
403 // we have to invert the transformation as it is later always used from the
404 // child bodies perspective.
405 X_T.push_back(joint_frame * movable_parent_transform);
406
407 // Dynamic variables
408 c.push_back(SpatialVector(0., 0., 0., 0., 0., 0.));
409 IA.push_back(SpatialMatrix::Zero());
410 pA.push_back(SpatialVector(0., 0., 0., 0., 0., 0.));
411 U.push_back(SpatialVector(0., 0., 0., 0., 0., 0.));
412
413 d = VectorNd::Zero (mBodies.size());
414 u = VectorNd::Zero (mBodies.size());
415
416 f.push_back (SpatialVector (0., 0., 0., 0., 0., 0.));
417
419 SpatialRigidBodyInertia::createFromMassComInertiaC (body.mMass,
420 body.mCenterOfMass,
421 body.mInertia);
422
423 Ic.push_back (rbi);
424 I.push_back (rbi);
425 hc.push_back (SpatialVector(0., 0., 0., 0., 0., 0.));
426 hdotc.push_back (SpatialVector(0., 0., 0., 0., 0., 0.));
427
428 if (mBodies.size() == fixed_body_discriminator) {
429 std::ostringstream errormsg;
430 errormsg << "Error: cannot add more than "
431 << fixed_body_discriminator
432 << " movable bodies. You need to modify Model::fixed_body_discriminator for this."
433 << std::endl;
434 throw Errors::RBDLError(errormsg.str());
435 }
436
437 previously_added_body_id = mBodies.size() - 1;
438
439 mJointUpdateOrder.clear();
440
441 // update the joint order computation
442 std::vector<std::pair<JointType, unsigned int> > joint_types;
443 for (unsigned int i = 0; i < mJoints.size(); i++) {
444 joint_types.push_back(
445 std::pair<JointType, unsigned int> (mJoints[i].mJointType,i));
446 mJointUpdateOrder.push_back (mJoints[i].mJointType);
447 }
448
449 mJointUpdateOrder.clear();
450 JointType current_joint_type = JointTypeUndefined;
451 while (joint_types.size() != 0) {
452 current_joint_type = joint_types[0].first;
453
454 std::vector<std::pair<JointType, unsigned int> >::iterator type_iter =
455 joint_types.begin();
456
457 while (type_iter != joint_types.end()) {
458 if (type_iter->first == current_joint_type) {
459 mJointUpdateOrder.push_back (type_iter->second);
460 type_iter = joint_types.erase (type_iter);
461 } else {
462 ++type_iter;
463 }
464 }
465 }
466
467 // for (unsigned int i = 0; i < mJointUpdateOrder.size(); i++) {
468 // std::cout << "i = " << i << ": joint_id = " << mJointUpdateOrder[i]
469 // << " joint_type = " << mJoints[mJointUpdateOrder[i]].mJointType << std::endl;
470 // }
471
472 return previously_added_body_id;
473}
474
475unsigned int Model::AppendBody (
476 const Math::SpatialTransform &joint_frame,
477 const Joint &joint,
478 const Body &body,
479 std::string body_name)
480{
481 return Model::AddBody (previously_added_body_id,
482 joint_frame,
483 joint,
484 body,
485 body_name);
486}
487
488unsigned int Model::AddBodyCustomJoint (
489 const unsigned int parent_id,
490 const Math::SpatialTransform &joint_frame,
491 CustomJoint *custom_joint,
492 const Body &body,
493 std::string body_name)
494{
495 Joint proxy_joint (JointTypeCustom, custom_joint->mDoFCount);
496 proxy_joint.custom_joint_index = mCustomJoints.size();
497 //proxy_joint.mDoFCount = custom_joint->mDoFCount; //MM added. Otherwise
498 //model.q_size = 0, which is not good.
499
500 mCustomJoints.push_back (custom_joint);
501
502 unsigned int body_id = AddBody (parent_id,
503 joint_frame,
504 proxy_joint,
505 body,
506 body_name);
507
508 return body_id;
509}
510
unsigned int AddBodyMultiDofJoint(Model &model, const unsigned int parent_id, const SpatialTransform &joint_frame, const Joint &joint, const Body &body, std::string body_name)
Definition: Model.cc:148
unsigned int AddBodyFixedJoint(Model &model, const unsigned int parent_id, const SpatialTransform &joint_frame, const Joint &joint, const Body &body, std::string body_name)
Definition: Model.cc:89
Base class for all RBDL exceptions.
Definition: rbdl_errors.h:35
Math types such as vectors and matrices and utility functions.
SpatialVector_t SpatialVector
Definition: rbdl_math.h:61
Describes all properties of a single body.
Definition: Body.h:28
Math::Matrix3d mInertia
Inertia matrix at the center of mass.
Definition: Body.h:197
void Join(const Math::SpatialTransform &transform, const Body &other_body)
Joins inertial parameters of two bodies to create a composite body.
Definition: Body.h:108
Math::Vector3d mCenterOfMass
The position of the center of mass in body coordinates.
Definition: Body.h:195
Math::Scalar mMass
The mass of the body.
Definition: Body.h:190
Keeps the information of a body and how it is attached to another body.
Definition: Body.h:208
unsigned int mMovableParent
Id of the movable body that this fixed body is attached to.
Definition: Body.h:217
Math::SpatialTransform mParentTransform
Transforms spatial quantities expressed for the parent to the.
Definition: Body.h:220
Compact representation for Spatial Inertia.
Compact representation of spatial transformations.