1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
|
#ifndef MULTIBODYTREE_HPP_
#define MULTIBODYTREE_HPP_
#include "IDConfig.hpp"
#include "IDMath.hpp"
namespace btInverseDynamics {
/// Enumeration of supported joint types
enum JointType {
/// no degree of freedom, moves with parent
FIXED = 0,
/// one rotational degree of freedom relative to parent
REVOLUTE,
/// one translational degree of freedom relative to parent
PRISMATIC,
/// six degrees of freedom relative to parent
FLOATING
};
/// Interface class for calculating inverse dynamics for tree structured
/// multibody systems
///
/// Note on degrees of freedom
/// The q vector contains the generalized coordinate set defining the tree's configuration.
/// Every joint adds elements that define the corresponding link's frame pose relative to
/// its parent. For the joint types that is:
/// - FIXED: none
/// - REVOLUTE: angle of rotation [rad]
/// - PRISMATIC: displacement [m]
/// - FLOATING: Euler x-y-z angles [rad] and displacement in body-fixed frame of parent [m]
/// (in that order)
/// The u vector contains the generalized speeds, which are
/// - FIXED: none
/// - REVOLUTE: time derivative of angle of rotation [rad/s]
/// - PRISMATIC: time derivative of displacement [m/s]
/// - FLOATING: angular velocity [rad/s] (*not* time derivative of rpy angles)
/// and time derivative of displacement in parent frame [m/s]
///
/// The q and u vectors are obtained by stacking contributions of all bodies in one
/// vector in the order of body indices.
///
/// Note on generalized forces: analogous to u, i.e.,
/// - FIXED: none
/// - REVOLUTE: moment [Nm], about joint axis
/// - PRISMATIC: force [N], along joint axis
/// - FLOATING: moment vector [Nm] and force vector [N], both in body-fixed frame
/// (in that order)
///
/// TODO - force element interface (friction, springs, dampers, etc)
/// - gears and motor inertia
class MultiBodyTree {
public:
ID_DECLARE_ALIGNED_ALLOCATOR();
/// The contructor.
/// Initialization & allocation is via addBody and buildSystem calls.
MultiBodyTree();
/// the destructor. This also deallocates all memory
~MultiBodyTree();
/// Add body to the system. this allocates memory and not real-time safe.
/// This only adds the data to an initial cache. After all bodies have been
/// added,
/// the system is setup using the buildSystem call
/// @param body_index index of the body to be added. Must >=0, <number of bodies,
/// and index of parent must be < index of body
/// @param parent_index index of the parent body
/// The root of the tree has index 0 and its parent (the world frame)
/// is assigned index -1
/// the rotation and translation relative to the parent are taken as
/// pose of the root body relative to the world frame. Other parameters
/// are ignored
/// @param JointType type of joint connecting the body to the parent
/// @param mass the mass of the body
/// @param body_r_body_com the center of mass of the body relative to and
/// described in
/// the body fixed frame, which is located in the joint axis connecting
/// the body to its parent
/// @param body_I_body the moment of inertia of the body w.r.t the body-fixed
/// frame
/// (ie, the reference point is the origin of the body-fixed frame and
/// the matrix is written
/// w.r.t. those unit vectors)
/// @param parent_r_parent_body_ref position of joint relative to the parent
/// body's reference frame
/// for q=0, written in the parent bodies reference frame
/// @param body_axis_of_motion translation/rotation axis in body-fixed frame.
/// Ignored for joints that are not revolute or prismatic.
/// must be a unit vector.
/// @param body_T_parent_ref transform matrix from parent to body reference
/// frame for q=0.
/// This is the matrix transforming a vector represented in the
/// parent's reference frame into one represented
/// in this body's reference frame.
/// ie, if parent_vec is a vector in R^3 whose components are w.r.t to
/// the parent's reference frame,
/// then the same vector written w.r.t. this body's frame (for q=0) is
/// given by
/// body_vec = parent_R_body_ref * parent_vec
/// @param user_ptr pointer to user data
/// @param user_int pointer to user integer
/// @return 0 on success, -1 on error
int addBody(int body_index, int parent_index, JointType joint_type,
const vec3& parent_r_parent_body_ref, const mat33& body_T_parent_ref,
const vec3& body_axis_of_motion, idScalar mass, const vec3& body_r_body_com,
const mat33& body_I_body, const int user_int, void* user_ptr);
/// set policy for invalid mass properties
/// @param flag if true, invalid mass properties are accepted,
/// the default is false
void setAcceptInvalidMassParameters(bool flag);
/// @return the mass properties policy flag
bool getAcceptInvalidMassProperties() const;
/// build internal data structures
/// call this after all bodies have been added via addBody
/// @return 0 on success, -1 on error
int finalize();
/// pretty print ascii description of tree to stdout
void printTree();
/// print tree data to stdout
void printTreeData();
/// Calculate joint forces for given generalized state & derivatives.
/// This also updates kinematic terms computed in calculateKinematics.
/// If gravity is not set to zero, acceleration terms will contain
/// gravitational acceleration.
/// @param q generalized coordinates
/// @param u generalized velocities. In the general case, u=T(q)*dot(q) and dim(q)>=dim(u)
/// @param dot_u time derivative of u
/// @param joint_forces this is where the resulting joint forces will be
/// stored. dim(joint_forces) = dim(u)
/// @return 0 on success, -1 on error
int calculateInverseDynamics(const vecx& q, const vecx& u, const vecx& dot_u,
vecx* joint_forces);
/// Calculate joint space mass matrix
/// @param q generalized coordinates
/// @param initialize_matrix if true, initialize mass matrix with zero.
/// If mass_matrix is initialized to zero externally and only used
/// for mass matrix computations for the same system, it is safe to
/// set this to false.
/// @param set_lower_triangular_matrix if true, the lower triangular section of mass_matrix
/// is also populated, otherwise not.
/// @param mass_matrix matrix for storing the output (should be dim(q)xdim(q))
/// @return -1 on error, 0 on success
int calculateMassMatrix(const vecx& q, const bool update_kinematics,
const bool initialize_matrix, const bool set_lower_triangular_matrix,
matxx* mass_matrix);
/// Calculate joint space mass matrix.
/// This version will update kinematics, initialize all mass_matrix elements to zero and
/// populate all mass matrix entries.
/// @param q generalized coordinates
/// @param mass_matrix matrix for storing the output (should be dim(q)xdim(q))
/// @return -1 on error, 0 on success
int calculateMassMatrix(const vecx& q, matxx* mass_matrix);
/// Calculates kinematics also calculated in calculateInverseDynamics,
/// but not dynamics.
/// This function ensures that correct accelerations are computed that do not
/// contain gravitational acceleration terms.
/// Does not calculate Jacobians, but only vector quantities (positions, velocities & accelerations)
int calculateKinematics(const vecx& q, const vecx& u, const vecx& dot_u);
/// Calculate position kinematics
int calculatePositionKinematics(const vecx& q);
/// Calculate position and velocity kinematics
int calculatePositionAndVelocityKinematics(const vecx& q, const vecx& u);
#if (defined BT_ID_HAVE_MAT3X) && (defined BT_ID_WITH_JACOBIANS)
/// Calculate Jacobians (dvel/du), as well as velocity-dependent accelearation components
/// d(Jacobian)/dt*u
/// This function assumes that calculateInverseDynamics was called, or calculateKinematics,
/// or calculatePositionAndVelocityKinematics
int calculateJacobians(const vecx& q, const vecx& u);
/// Calculate Jacobians (dvel/du)
/// This function assumes that calculateInverseDynamics was called, or
/// one of the calculateKineamtics functions
int calculateJacobians(const vecx& q);
#endif // BT_ID_HAVE_MAT3X
/// set gravitational acceleration
/// the default is [0;0;-9.8] in the world frame
/// @param gravity the gravitational acceleration in world frame
/// @return 0 on success, -1 on error
int setGravityInWorldFrame(const vec3& gravity);
/// returns number of bodies in tree
int numBodies() const;
/// returns number of mechanical degrees of freedom (dimension of q-vector)
int numDoFs() const;
/// get origin of a body-fixed frame, represented in world frame
/// @param body_index index for frame/body
/// @param world_origin pointer for return data
/// @return 0 on success, -1 on error
int getBodyOrigin(const int body_index, vec3* world_origin) const;
/// get center of mass of a body, represented in world frame
/// @param body_index index for frame/body
/// @param world_com pointer for return data
/// @return 0 on success, -1 on error
int getBodyCoM(const int body_index, vec3* world_com) const;
/// get transform from of a body-fixed frame to the world frame
/// @param body_index index for frame/body
/// @param world_T_body pointer for return data
/// @return 0 on success, -1 on error
int getBodyTransform(const int body_index, mat33* world_T_body) const;
/// get absolute angular velocity for a body, represented in the world frame
/// @param body_index index for frame/body
/// @param world_omega pointer for return data
/// @return 0 on success, -1 on error
int getBodyAngularVelocity(const int body_index, vec3* world_omega) const;
/// get linear velocity of a body, represented in world frame
/// @param body_index index for frame/body
/// @param world_velocity pointer for return data
/// @return 0 on success, -1 on error
int getBodyLinearVelocity(const int body_index, vec3* world_velocity) const;
/// get linear velocity of a body's CoM, represented in world frame
/// (not required for inverse dynamics, provided for convenience)
/// @param body_index index for frame/body
/// @param world_vel_com pointer for return data
/// @return 0 on success, -1 on error
int getBodyLinearVelocityCoM(const int body_index, vec3* world_velocity) const;
/// get origin of a body-fixed frame, represented in world frame
/// @param body_index index for frame/body
/// @param world_origin pointer for return data
/// @return 0 on success, -1 on error
int getBodyAngularAcceleration(const int body_index, vec3* world_dot_omega) const;
/// get origin of a body-fixed frame, represented in world frame
/// NOTE: this will include the gravitational acceleration, so the actual acceleration is
/// obtainened by setting gravitational acceleration to zero, or subtracting it.
/// @param body_index index for frame/body
/// @param world_origin pointer for return data
/// @return 0 on success, -1 on error
int getBodyLinearAcceleration(const int body_index, vec3* world_acceleration) const;
#if (defined BT_ID_HAVE_MAT3X) && (defined BT_ID_WITH_JACOBIANS)
// get translational jacobian, in world frame (dworld_velocity/du)
int getBodyJacobianTrans(const int body_index, mat3x* world_jac_trans) const;
// get rotational jacobian, in world frame (dworld_omega/du)
int getBodyJacobianRot(const int body_index, mat3x* world_jac_rot) const;
// get product of translational jacobian derivative * generatlized velocities
int getBodyDotJacobianTransU(const int body_index, vec3* world_dot_jac_trans_u) const;
// get product of rotational jacobian derivative * generatlized velocities
int getBodyDotJacobianRotU(const int body_index, vec3* world_dot_jac_rot_u) const;
#endif // BT_ID_HAVE_MAT3X
/// returns the (internal) index of body
/// @param body_index is the index of a body
/// @param parent_index pointer to where parent index will be stored
/// @return 0 on success, -1 on error
int getParentIndex(const int body_index, int* parent_index) const;
/// get joint type
/// @param body_index index of the body
/// @param joint_type the corresponding joint type
/// @return 0 on success, -1 on failure
int getJointType(const int body_index, JointType* joint_type) const;
/// get joint type as string
/// @param body_index index of the body
/// @param joint_type string naming the corresponding joint type
/// @return 0 on success, -1 on failure
int getJointTypeStr(const int body_index, const char** joint_type) const;
/// get offset translation to parent body (see addBody)
/// @param body_index index of the body
/// @param r the offset translation (see above)
/// @return 0 on success, -1 on failure
int getParentRParentBodyRef(const int body_index, vec3* r) const;
/// get offset rotation to parent body (see addBody)
/// @param body_index index of the body
/// @param T the transform (see above)
/// @return 0 on success, -1 on failure
int getBodyTParentRef(const int body_index, mat33* T) const;
/// get axis of motion (see addBody)
/// @param body_index index of the body
/// @param axis the axis (see above)
/// @return 0 on success, -1 on failure
int getBodyAxisOfMotion(const int body_index, vec3* axis) const;
/// get offset for degrees of freedom of this body into the q-vector
/// @param body_index index of the body
/// @param q_offset offset the q vector
/// @return -1 on error, 0 on success
int getDoFOffset(const int body_index, int* q_offset) const;
/// get user integer. not used by the library.
/// @param body_index index of the body
/// @param user_int the user integer
/// @return 0 on success, -1 on error
int getUserInt(const int body_index, int* user_int) const;
/// get user pointer. not used by the library.
/// @param body_index index of the body
/// @param user_ptr the user pointer
/// @return 0 on success, -1 on error
int getUserPtr(const int body_index, void** user_ptr) const;
/// set user integer. not used by the library.
/// @param body_index index of the body
/// @param user_int the user integer
/// @return 0 on success, -1 on error
int setUserInt(const int body_index, const int user_int);
/// set user pointer. not used by the library.
/// @param body_index index of the body
/// @param user_ptr the user pointer
/// @return 0 on success, -1 on error
int setUserPtr(const int body_index, void* const user_ptr);
/// set mass for a body
/// @param body_index index of the body
/// @param mass the mass to set
/// @return 0 on success, -1 on failure
int setBodyMass(const int body_index, const idScalar mass);
/// set first moment of mass for a body
/// (mass * center of mass, in body fixed frame, relative to joint)
/// @param body_index index of the body
/// @param first_mass_moment the vector to set
/// @return 0 on success, -1 on failure
int setBodyFirstMassMoment(const int body_index, const vec3& first_mass_moment);
/// set second moment of mass for a body
/// (moment of inertia, in body fixed frame, relative to joint)
/// @param body_index index of the body
/// @param second_mass_moment the inertia matrix
/// @return 0 on success, -1 on failure
int setBodySecondMassMoment(const int body_index, const mat33& second_mass_moment);
/// get mass for a body
/// @param body_index index of the body
/// @param mass the mass
/// @return 0 on success, -1 on failure
int getBodyMass(const int body_index, idScalar* mass) const;
/// get first moment of mass for a body
/// (mass * center of mass, in body fixed frame, relative to joint)
/// @param body_index index of the body
/// @param first_moment the vector
/// @return 0 on success, -1 on failure
int getBodyFirstMassMoment(const int body_index, vec3* first_mass_moment) const;
/// get second moment of mass for a body
/// (moment of inertia, in body fixed frame, relative to joint)
/// @param body_index index of the body
/// @param second_mass_moment the inertia matrix
/// @return 0 on success, -1 on failure
int getBodySecondMassMoment(const int body_index, mat33* second_mass_moment) const;
/// set all user forces and moments to zero
void clearAllUserForcesAndMoments();
/// Add an external force to a body, acting at the origin of the body-fixed frame.
/// Calls to addUserForce are cumulative. Set the user force and moment to zero
/// via clearAllUserForcesAndMoments()
/// @param body_force the force represented in the body-fixed frame of reference
/// @return 0 on success, -1 on error
int addUserForce(const int body_index, const vec3& body_force);
/// Add an external moment to a body.
/// Calls to addUserMoment are cumulative. Set the user force and moment to zero
/// via clearAllUserForcesAndMoments()
/// @param body_moment the moment represented in the body-fixed frame of reference
/// @return 0 on success, -1 on error
int addUserMoment(const int body_index, const vec3& body_moment);
private:
// flag indicating if system has been initialized
bool m_is_finalized;
// flag indicating if mass properties are physically valid
bool m_mass_parameters_are_valid;
// flag defining if unphysical mass parameters are accepted
bool m_accept_invalid_mass_parameters;
// This struct implements the inverse dynamics calculations
class MultiBodyImpl;
MultiBodyImpl* m_impl;
// cache data structure for initialization
class InitCache;
InitCache* m_init_cache;
};
} // namespace btInverseDynamics
#endif // MULTIBODYTREE_HPP_
|