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