3
* Class representing an articulated rigid body. Stores the body's
4
* current state, allows forces and torques to be set, handles
5
* timestepping and implements Featherstone's algorithm.
8
* Copyright (C) Stephen Thompson, <stephen@solarflare.org.uk>, 2011-2013
9
* Portions written By Erwin Coumans: replacing Eigen math library by Bullet LinearMath and a dedicated 6x6 matrix inverse (solveImatrix)
11
This software is provided 'as-is', without any express or implied warranty.
12
In no event will the authors be held liable for any damages arising from the use of this software.
13
Permission is granted to anyone to use this software for any purpose,
14
including commercial applications, and to alter it and redistribute it freely,
15
subject to the following restrictions:
17
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
18
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
19
3. This notice may not be removed or altered from any source distribution.
24
#ifndef BT_MULTIBODY_H
25
#define BT_MULTIBODY_H
27
#include "LinearMath/btScalar.h"
28
#include "LinearMath/btVector3.h"
29
#include "LinearMath/btQuaternion.h"
30
#include "LinearMath/btMatrix3x3.h"
31
#include "LinearMath/btAlignedObjectArray.h"
34
#include "btMultiBodyLink.h"
35
class btMultiBodyLinkCollider;
42
BT_DECLARE_ALIGNED_ALLOCATOR();
48
btMultiBody(int n_links, // NOT including the base
49
btScalar mass, // mass of base
50
const btVector3 &inertia, // inertia of base, in base frame; assumed diagonal
51
bool fixed_base_, // whether the base is fixed (true) or can move (false)
56
void setupPrismatic(int i, // 0 to num_links-1
58
const btVector3 &inertia, // in my frame; assumed diagonal
60
const btQuaternion &rot_parent_to_this, // rotate points in parent frame to my frame.
61
const btVector3 &joint_axis, // in my frame
62
const btVector3 &r_vector_when_q_zero, // vector from parent COM to my COM, in my frame, when q = 0.
63
bool disableParentCollision=false
66
void setupRevolute(int i, // 0 to num_links-1
68
const btVector3 &inertia,
70
const btQuaternion &zero_rot_parent_to_this, // rotate points in parent frame to this frame, when q = 0
71
const btVector3 &joint_axis, // in my frame
72
const btVector3 &parent_axis_position, // vector from parent COM to joint axis, in PARENT frame
73
const btVector3 &my_axis_position, // vector from joint axis to my COM, in MY frame
74
bool disableParentCollision=false);
76
const btMultibodyLink& getLink(int index) const
81
btMultibodyLink& getLink(int index)
87
void setBaseCollider(btMultiBodyLinkCollider* collider)//collider can be NULL to disable collision for the base
89
m_baseCollider = collider;
91
const btMultiBodyLinkCollider* getBaseCollider() const
93
return m_baseCollider;
95
btMultiBodyLinkCollider* getBaseCollider()
97
return m_baseCollider;
102
// input: link num from 0 to num_links-1
103
// output: link num from 0 to num_links-1, OR -1 to mean the base.
105
int getParent(int link_num) const;
109
// get number of links, masses, moments of inertia
112
int getNumLinks() const { return links.size(); }
113
btScalar getBaseMass() const { return base_mass; }
114
const btVector3 & getBaseInertia() const { return base_inertia; }
115
btScalar getLinkMass(int i) const;
116
const btVector3 & getLinkInertia(int i) const;
120
// change mass (incomplete: can only change base mass and inertia at present)
123
void setBaseMass(btScalar mass) { base_mass = mass; }
124
void setBaseInertia(const btVector3 &inertia) { base_inertia = inertia; }
128
// get/set pos/vel/rot/omega for the base link
131
const btVector3 & getBasePos() const { return base_pos; } // in world frame
132
const btVector3 getBaseVel() const
134
return btVector3(m_real_buf[3],m_real_buf[4],m_real_buf[5]);
136
const btQuaternion & getWorldToBaseRot() const
139
} // rotates world vectors into base frame
140
btVector3 getBaseOmega() const { return btVector3(m_real_buf[0],m_real_buf[1],m_real_buf[2]); } // in world frame
142
void setBasePos(const btVector3 &pos)
146
void setBaseVel(const btVector3 &vel)
149
m_real_buf[3]=vel[0]; m_real_buf[4]=vel[1]; m_real_buf[5]=vel[2];
151
void setWorldToBaseRot(const btQuaternion &rot)
155
void setBaseOmega(const btVector3 &omega)
157
m_real_buf[0]=omega[0];
158
m_real_buf[1]=omega[1];
159
m_real_buf[2]=omega[2];
164
// get/set pos/vel for child links (i = 0 to num_links-1)
167
btScalar getJointPos(int i) const;
168
btScalar getJointVel(int i) const;
170
void setJointPos(int i, btScalar q);
171
void setJointVel(int i, btScalar qdot);
174
// direct access to velocities as a vector of 6 + num_links elements.
175
// (omega first, then v, then joint velocities.)
177
const btScalar * getVelocityVector() const
179
return &m_real_buf[0];
181
/* btScalar * getVelocityVector()
188
// get the frames of reference (positions and orientations) of the child links
189
// (i = 0 to num_links-1)
192
const btVector3 & getRVector(int i) const; // vector from COM(parent(i)) to COM(i), in frame i's coords
193
const btQuaternion & getParentToLocalRot(int i) const; // rotates vectors in frame parent(i) to vectors in frame i.
197
// transform vectors in local frame of link i to world frame (or vice versa)
199
btVector3 localPosToWorld(int i, const btVector3 &vec) const;
200
btVector3 localDirToWorld(int i, const btVector3 &vec) const;
201
btVector3 worldPosToLocal(int i, const btVector3 &vec) const;
202
btVector3 worldDirToLocal(int i, const btVector3 &vec) const;
206
// calculate kinetic energy and angular momentum
207
// useful for debugging.
210
btScalar getKineticEnergy() const;
211
btVector3 getAngularMomentum() const;
215
// set external forces and torques. Note all external forces/torques are given in the WORLD frame.
218
void clearForcesAndTorques();
219
void clearVelocities();
221
void addBaseForce(const btVector3 &f)
225
void addBaseTorque(const btVector3 &t) { base_torque += t; }
226
void addLinkForce(int i, const btVector3 &f);
227
void addLinkTorque(int i, const btVector3 &t);
228
void addJointTorque(int i, btScalar Q);
230
const btVector3 & getBaseForce() const { return base_force; }
231
const btVector3 & getBaseTorque() const { return base_torque; }
232
const btVector3 & getLinkForce(int i) const;
233
const btVector3 & getLinkTorque(int i) const;
234
btScalar getJointTorque(int i) const;
238
// dynamics routines.
241
// timestep the velocities (given the external forces/torques set using addBaseForce etc).
242
// also sets up caches for calcAccelerationDeltas.
244
// Note: the caller must provide three vectors which are used as
245
// temporary scratch space. The idea here is to reduce dynamic
246
// memory allocation: the same scratch vectors can be re-used
247
// again and again for different Multibodies, instead of each
248
// btMultiBody allocating (and then deallocating) their own
249
// individual scratch buffers. This gives a considerable speed
250
// improvement, at least on Windows (where dynamic memory
251
// allocation appears to be fairly slow).
253
void stepVelocities(btScalar dt,
254
btAlignedObjectArray<btScalar> &scratch_r,
255
btAlignedObjectArray<btVector3> &scratch_v,
256
btAlignedObjectArray<btMatrix3x3> &scratch_m);
258
// calcAccelerationDeltas
259
// input: force vector (in same format as jacobian, i.e.:
260
// 3 torque values, 3 force values, num_links joint torque values)
261
// output: 3 omegadot values, 3 vdot values, num_links q_double_dot values
262
// (existing contents of output array are replaced)
263
// stepVelocities must have been called first.
264
void calcAccelerationDeltas(const btScalar *force, btScalar *output,
265
btAlignedObjectArray<btScalar> &scratch_r,
266
btAlignedObjectArray<btVector3> &scratch_v) const;
268
// apply a delta-vee directly. used in sequential impulses code.
269
void applyDeltaVee(const btScalar * delta_vee)
272
for (int i = 0; i < 6 + getNumLinks(); ++i)
274
m_real_buf[i] += delta_vee[i];
278
void applyDeltaVee(const btScalar * delta_vee, btScalar multiplier)
281
for (int i = 0; i < 6 + getNumLinks(); ++i)
283
sum += delta_vee[i]*multiplier*delta_vee[i]*multiplier;
285
btScalar l = btSqrt(sum);
287
static btScalar maxl = -1e30f;
291
// printf("maxl=%f\n",maxl);
294
if (l>m_maxAppliedImpulse)
296
// printf("exceeds 100: l=%f\n",maxl);
297
multiplier *= m_maxAppliedImpulse/l;
300
for (int i = 0; i < 6 + getNumLinks(); ++i)
302
sum += delta_vee[i]*multiplier*delta_vee[i]*multiplier;
303
m_real_buf[i] += delta_vee[i] * multiplier;
307
// timestep the positions (given current velocities).
308
void stepPositions(btScalar dt);
315
// This routine fills out a contact constraint jacobian for this body.
316
// the 'normal' supplied must be -n for body1 or +n for body2 of the contact.
317
// 'normal' & 'contact_point' are both given in world coordinates.
318
void fillContactJacobian(int link,
319
const btVector3 &contact_point,
320
const btVector3 &normal,
322
btAlignedObjectArray<btScalar> &scratch_r,
323
btAlignedObjectArray<btVector3> &scratch_v,
324
btAlignedObjectArray<btMatrix3x3> &scratch_m) const;
330
void setCanSleep(bool canSleep)
332
can_sleep = canSleep;
335
bool isAwake() const { return awake; }
338
void checkMotionAndSleepIfRequired(btScalar timestep);
340
bool hasFixedBase() const
345
int getCompanionId() const
347
return m_companionId;
349
void setCompanionId(int id)
351
//printf("for %p setCompanionId(%d)\n",this, id);
355
void setNumLinks(int numLinks)//careful: when changing the number of links, make sure to re-initialize or update existing links
357
links.resize(numLinks);
360
btScalar getLinearDamping() const
362
return m_linearDamping;
364
void setLinearDamping( btScalar damp)
366
m_linearDamping = damp;
368
btScalar getAngularDamping() const
370
return m_angularDamping;
373
bool getUseGyroTerm() const
375
return m_useGyroTerm;
377
void setUseGyroTerm(bool useGyro)
379
m_useGyroTerm = useGyro;
381
btScalar getMaxAppliedImpulse() const
383
return m_maxAppliedImpulse;
385
void setMaxAppliedImpulse(btScalar maxImp)
387
m_maxAppliedImpulse = maxImp;
390
void setHasSelfCollision(bool hasSelfCollision)
392
m_hasSelfCollision = hasSelfCollision;
394
bool hasSelfCollision() const
396
return m_hasSelfCollision;
400
btMultiBody(const btMultiBody &); // not implemented
401
void operator=(const btMultiBody &); // not implemented
403
void compTreeLinkVelocities(btVector3 *omega, btVector3 *vel) const;
405
void solveImatrix(const btVector3& rhs_top, const btVector3& rhs_bot, float result[6]) const;
410
btMultiBodyLinkCollider* m_baseCollider;//can be NULL
412
btVector3 base_pos; // position of COM of base (world frame)
413
btQuaternion base_quat; // rotates world points into base frame
415
btScalar base_mass; // mass of the base
416
btVector3 base_inertia; // inertia of the base (in local frame; diagonal)
418
btVector3 base_force; // external force applied to base. World frame.
419
btVector3 base_torque; // external torque applied to base. World frame.
421
btAlignedObjectArray<btMultibodyLink> links; // array of links, excluding the base. index from 0 to num_links-1.
422
btAlignedObjectArray<btMultiBodyLinkCollider*> m_colliders;
427
// 0 6 + num_links v (base_omega; base_vel; joint_vels)
428
// 6+num_links num_links D
433
// num_links num_links h_bottom
437
// 0 num_links+1 rot_from_parent
440
btAlignedObjectArray<btScalar> m_real_buf;
441
btAlignedObjectArray<btVector3> vector_buf;
442
btAlignedObjectArray<btMatrix3x3> matrix_buf;
444
//std::auto_ptr<Eigen::LU<Eigen::Matrix<btScalar, 6, 6> > > cached_imatrix_lu;
446
btMatrix3x3 cached_inertia_top_left;
447
btMatrix3x3 cached_inertia_top_right;
448
btMatrix3x3 cached_inertia_lower_left;
449
btMatrix3x3 cached_inertia_lower_right;
456
btScalar sleep_timer;
459
btScalar m_linearDamping;
460
btScalar m_angularDamping;
462
btScalar m_maxAppliedImpulse;
463
bool m_hasSelfCollision;