Bullet Collision Detection & Physics Library
btMultiBody.h
Go to the documentation of this file.
1 /*
2  * PURPOSE:
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.
6  *
7  * COPYRIGHT:
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)
10 
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:
16 
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.
20 
21  */
22 
23 
24 #ifndef BT_MULTIBODY_H
25 #define BT_MULTIBODY_H
26 
27 #include "LinearMath/btScalar.h"
28 #include "LinearMath/btVector3.h"
30 #include "LinearMath/btMatrix3x3.h"
32 
33 
34 #include "btMultiBodyLink.h"
36 
38 {
39 public:
40 
41 
43 
44  //
45  // initialization
46  //
47 
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)
52  bool can_sleep_);
53 
54  ~btMultiBody();
55 
56  void setupPrismatic(int i, // 0 to num_links-1
57  btScalar mass,
58  const btVector3 &inertia, // in my frame; assumed diagonal
59  int parent,
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
64  );
65 
66  void setupRevolute(int i, // 0 to num_links-1
67  btScalar mass,
68  const btVector3 &inertia,
69  int parent,
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);
75 
76  const btMultibodyLink& getLink(int index) const
77  {
78  return links[index];
79  }
80 
82  {
83  return links[index];
84  }
85 
86 
87  void setBaseCollider(btMultiBodyLinkCollider* collider)//collider can be NULL to disable collision for the base
88  {
89  m_baseCollider = collider;
90  }
92  {
93  return m_baseCollider;
94  }
96  {
97  return m_baseCollider;
98  }
99 
100  //
101  // get parent
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.
104  //
105  int getParent(int link_num) const;
106 
107 
108  //
109  // get number of links, masses, moments of inertia
110  //
111 
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;
117 
118 
119  //
120  // change mass (incomplete: can only change base mass and inertia at present)
121  //
122 
123  void setBaseMass(btScalar mass) { base_mass = mass; }
124  void setBaseInertia(const btVector3 &inertia) { base_inertia = inertia; }
125 
126 
127  //
128  // get/set pos/vel/rot/omega for the base link
129  //
130 
131  const btVector3 & getBasePos() const { return base_pos; } // in world frame
132  const btVector3 getBaseVel() const
133  {
134  return btVector3(m_real_buf[3],m_real_buf[4],m_real_buf[5]);
135  } // in world frame
137  {
138  return base_quat;
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
141 
142  void setBasePos(const btVector3 &pos)
143  {
144  base_pos = pos;
145  }
146  void setBaseVel(const btVector3 &vel)
147  {
148 
149  m_real_buf[3]=vel[0]; m_real_buf[4]=vel[1]; m_real_buf[5]=vel[2];
150  }
151  void setWorldToBaseRot(const btQuaternion &rot)
152  {
153  base_quat = rot;
154  }
155  void setBaseOmega(const btVector3 &omega)
156  {
157  m_real_buf[0]=omega[0];
158  m_real_buf[1]=omega[1];
159  m_real_buf[2]=omega[2];
160  }
161 
162 
163  //
164  // get/set pos/vel for child links (i = 0 to num_links-1)
165  //
166 
167  btScalar getJointPos(int i) const;
168  btScalar getJointVel(int i) const;
169 
170  void setJointPos(int i, btScalar q);
171  void setJointVel(int i, btScalar qdot);
172 
173  //
174  // direct access to velocities as a vector of 6 + num_links elements.
175  // (omega first, then v, then joint velocities.)
176  //
177  const btScalar * getVelocityVector() const
178  {
179  return &m_real_buf[0];
180  }
181 /* btScalar * getVelocityVector()
182  {
183  return &real_buf[0];
184  }
185  */
186 
187  //
188  // get the frames of reference (positions and orientations) of the child links
189  // (i = 0 to num_links-1)
190  //
191 
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.
194 
195 
196  //
197  // transform vectors in local frame of link i to world frame (or vice versa)
198  //
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;
203 
204 
205  //
206  // calculate kinetic energy and angular momentum
207  // useful for debugging.
208  //
209 
210  btScalar getKineticEnergy() const;
212 
213 
214  //
215  // set external forces and torques. Note all external forces/torques are given in the WORLD frame.
216  //
217 
218  void clearForcesAndTorques();
219  void clearVelocities();
220 
221  void addBaseForce(const btVector3 &f)
222  {
223  base_force += f;
224  }
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);
229 
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;
235 
236 
237  //
238  // dynamics routines.
239  //
240 
241  // timestep the velocities (given the external forces/torques set using addBaseForce etc).
242  // also sets up caches for calcAccelerationDeltas.
243  //
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).
252  //
253  void stepVelocities(btScalar dt,
257 
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,
266  btAlignedObjectArray<btVector3> &scratch_v) const;
267 
268  // apply a delta-vee directly. used in sequential impulses code.
269  void applyDeltaVee(const btScalar * delta_vee)
270  {
271 
272  for (int i = 0; i < 6 + getNumLinks(); ++i)
273  {
274  m_real_buf[i] += delta_vee[i];
275  }
276 
277  }
278  void applyDeltaVee(const btScalar * delta_vee, btScalar multiplier)
279  {
280  btScalar sum = 0;
281  for (int i = 0; i < 6 + getNumLinks(); ++i)
282  {
283  sum += delta_vee[i]*multiplier*delta_vee[i]*multiplier;
284  }
285  btScalar l = btSqrt(sum);
286  /*
287  static btScalar maxl = -1e30f;
288  if (l>maxl)
289  {
290  maxl=l;
291  // printf("maxl=%f\n",maxl);
292  }
293  */
294  if (l>m_maxAppliedImpulse)
295  {
296 // printf("exceeds 100: l=%f\n",maxl);
297  multiplier *= m_maxAppliedImpulse/l;
298  }
299 
300  for (int i = 0; i < 6 + getNumLinks(); ++i)
301  {
302  sum += delta_vee[i]*multiplier*delta_vee[i]*multiplier;
303  m_real_buf[i] += delta_vee[i] * multiplier;
304  }
305  }
306 
307  // timestep the positions (given current velocities).
308  void stepPositions(btScalar dt);
309 
310 
311  //
312  // contacts
313  //
314 
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,
321  btScalar *jac,
324  btAlignedObjectArray<btMatrix3x3> &scratch_m) const;
325 
326 
327  //
328  // sleeping
329  //
330  void setCanSleep(bool canSleep)
331  {
332  can_sleep = canSleep;
333  }
334 
335  bool isAwake() const { return awake; }
336  void wakeUp();
337  void goToSleep();
339 
340  bool hasFixedBase() const
341  {
342  return fixed_base;
343  }
344 
345  int getCompanionId() const
346  {
347  return m_companionId;
348  }
349  void setCompanionId(int id)
350  {
351  //printf("for %p setCompanionId(%d)\n",this, id);
352  m_companionId = id;
353  }
354 
355  void setNumLinks(int numLinks)//careful: when changing the number of links, make sure to re-initialize or update existing links
356  {
357  links.resize(numLinks);
358  }
359 
361  {
362  return m_linearDamping;
363  }
365  {
366  m_linearDamping = damp;
367  }
369  {
370  return m_angularDamping;
371  }
372 
373  bool getUseGyroTerm() const
374  {
375  return m_useGyroTerm;
376  }
377  void setUseGyroTerm(bool useGyro)
378  {
379  m_useGyroTerm = useGyro;
380  }
382  {
383  return m_maxAppliedImpulse;
384  }
386  {
387  m_maxAppliedImpulse = maxImp;
388  }
389 
391  {
393  }
394  bool hasSelfCollision() const
395  {
396  return m_hasSelfCollision;
397  }
398 
399 private:
400  btMultiBody(const btMultiBody &); // not implemented
401  void operator=(const btMultiBody &); // not implemented
402 
403  void compTreeLinkVelocities(btVector3 *omega, btVector3 *vel) const;
404 
405  void solveImatrix(const btVector3& rhs_top, const btVector3& rhs_bot, float result[6]) const;
406 
407 
408 private:
409 
411 
412  btVector3 base_pos; // position of COM of base (world frame)
413  btQuaternion base_quat; // rotates world points into base frame
414 
415  btScalar base_mass; // mass of the base
416  btVector3 base_inertia; // inertia of the base (in local frame; diagonal)
417 
418  btVector3 base_force; // external force applied to base. World frame.
419  btVector3 base_torque; // external torque applied to base. World frame.
420 
421  btAlignedObjectArray<btMultibodyLink> links; // array of links, excluding the base. index from 0 to num_links-1.
423 
424  //
425  // real_buf:
426  // offset size array
427  // 0 6 + num_links v (base_omega; base_vel; joint_vels)
428  // 6+num_links num_links D
429  //
430  // vector_buf:
431  // offset size array
432  // 0 num_links h_top
433  // num_links num_links h_bottom
434  //
435  // matrix_buf:
436  // offset size array
437  // 0 num_links+1 rot_from_parent
438  //
439 
443 
444  //std::auto_ptr<Eigen::LU<Eigen::Matrix<btScalar, 6, 6> > > cached_imatrix_lu;
445 
450 
452 
453  // Sleep parameters.
454  bool awake;
455  bool can_sleep;
457 
464 };
465 
466 #endif
void calcAccelerationDeltas(const btScalar *force, btScalar *output, btAlignedObjectArray< btScalar > &scratch_r, btAlignedObjectArray< btVector3 > &scratch_v) const
static T sum(const btAlignedObjectArray< T > &items)
void setCanSleep(bool canSleep)
Definition: btMultiBody.h:330
btAlignedObjectArray< btMultiBodyLinkCollider * > m_colliders
Definition: btMultiBody.h:422
bool m_useGyroTerm
Definition: btMultiBody.h:461
const btMultibodyLink & getLink(int index) const
Definition: btMultiBody.h:76
BT_DECLARE_ALIGNED_ALLOCATOR()
const btVector3 getBaseVel() const
Definition: btMultiBody.h:132
btMultiBodyLinkCollider * getBaseCollider()
Definition: btMultiBody.h:95
void setNumLinks(int numLinks)
Definition: btMultiBody.h:355
btMultiBodyLinkCollider * m_baseCollider
Definition: btMultiBody.h:410
bool isAwake() const
Definition: btMultiBody.h:335
int getNumLinks() const
Definition: btMultiBody.h:112
btVector3 base_pos
Definition: btMultiBody.h:412
void addBaseTorque(const btVector3 &t)
Definition: btMultiBody.h:225
btVector3 base_torque
Definition: btMultiBody.h:419
const btVector3 & getLinkForce(int i) const
btScalar getBaseMass() const
Definition: btMultiBody.h:113
btScalar btSqrt(btScalar y)
Definition: btScalar.h:387
btVector3 localDirToWorld(int i, const btVector3 &vec) const
btAlignedObjectArray< btScalar > m_real_buf
Definition: btMultiBody.h:440
void addLinkForce(int i, const btVector3 &f)
void setBaseCollider(btMultiBodyLinkCollider *collider)
Definition: btMultiBody.h:87
btScalar getJointPos(int i) const
btMatrix3x3 cached_inertia_top_right
Definition: btMultiBody.h:447
const btVector3 & getBaseTorque() const
Definition: btMultiBody.h:231
btMatrix3x3 cached_inertia_lower_left
Definition: btMultiBody.h:448
void setWorldToBaseRot(const btQuaternion &rot)
Definition: btMultiBody.h:151
btScalar m_maxAppliedImpulse
Definition: btMultiBody.h:462
btAlignedObjectArray< btVector3 > vector_buf
Definition: btMultiBody.h:441
btScalar getMaxAppliedImpulse() const
Definition: btMultiBody.h:381
void applyDeltaVee(const btScalar *delta_vee)
Definition: btMultiBody.h:269
void clearForcesAndTorques()
btVector3 getAngularMomentum() const
void setBaseVel(const btVector3 &vel)
Definition: btMultiBody.h:146
btAlignedObjectArray< btMatrix3x3 > matrix_buf
Definition: btMultiBody.h:442
int m_companionId
Definition: btMultiBody.h:458
const btVector3 & getBaseInertia() const
Definition: btMultiBody.h:114
void setHasSelfCollision(bool hasSelfCollision)
Definition: btMultiBody.h:390
int size() const
return the number of elements in the array
void setUseGyroTerm(bool useGyro)
Definition: btMultiBody.h:377
const btVector3 & getLinkTorque(int i) const
void addLinkTorque(int i, const btVector3 &t)
void setCompanionId(int id)
Definition: btMultiBody.h:349
void setBaseOmega(const btVector3 &omega)
Definition: btMultiBody.h:155
bool m_hasSelfCollision
Definition: btMultiBody.h:463
void compTreeLinkVelocities(btVector3 *omega, btVector3 *vel) const
bool hasFixedBase() const
Definition: btMultiBody.h:340
btMultibodyLink & getLink(int index)
Definition: btMultiBody.h:81
void addJointTorque(int i, btScalar Q)
btScalar getLinearDamping() const
Definition: btMultiBody.h:360
void solveImatrix(const btVector3 &rhs_top, const btVector3 &rhs_bot, float result[6]) const
const btVector3 & getRVector(int i) const
bool hasSelfCollision() const
Definition: btMultiBody.h:394
void setJointVel(int i, btScalar qdot)
void operator=(const btMultiBody &)
void setJointPos(int i, btScalar q)
bool can_sleep
Definition: btMultiBody.h:455
btScalar sleep_timer
Definition: btMultiBody.h:456
void clearVelocities()
void checkMotionAndSleepIfRequired(btScalar timestep)
btVector3 can be used to represent 3D points and vectors.
Definition: btVector3.h:83
void setLinearDamping(btScalar damp)
Definition: btMultiBody.h:364
btScalar getLinkMass(int i) const
void addBaseForce(const btVector3 &f)
Definition: btMultiBody.h:221
btQuaternion base_quat
Definition: btMultiBody.h:413
btVector3 base_inertia
Definition: btMultiBody.h:416
void setMaxAppliedImpulse(btScalar maxImp)
Definition: btMultiBody.h:385
bool fixed_base
Definition: btMultiBody.h:451
btVector3 getBaseOmega() const
Definition: btMultiBody.h:140
int getCompanionId() const
Definition: btMultiBody.h:345
btAlignedObjectArray< btMultibodyLink > links
Definition: btMultiBody.h:421
btScalar m_linearDamping
Definition: btMultiBody.h:459
btScalar getAngularDamping() const
Definition: btMultiBody.h:368
void resize(int newsize, const T &fillData=T())
btMatrix3x3 cached_inertia_top_left
Definition: btMultiBody.h:446
void setupPrismatic(int i, btScalar mass, const btVector3 &inertia, int parent, const btQuaternion &rot_parent_to_this, const btVector3 &joint_axis, const btVector3 &r_vector_when_q_zero, bool disableParentCollision=false)
void goToSleep()
void applyDeltaVee(const btScalar *delta_vee, btScalar multiplier)
Definition: btMultiBody.h:278
void setBaseInertia(const btVector3 &inertia)
Definition: btMultiBody.h:124
btMultiBody(int n_links, btScalar mass, const btVector3 &inertia, bool fixed_base_, bool can_sleep_)
Definition: btMultiBody.cpp:79
btVector3 worldPosToLocal(int i, const btVector3 &vec) const
const btQuaternion & getParentToLocalRot(int i) const
void fillContactJacobian(int link, const btVector3 &contact_point, const btVector3 &normal, btScalar *jac, btAlignedObjectArray< btScalar > &scratch_r, btAlignedObjectArray< btVector3 > &scratch_v, btAlignedObjectArray< btMatrix3x3 > &scratch_m) const
The btMatrix3x3 class implements a 3x3 rotation matrix, to perform linear algebra in combination with...
Definition: btMatrix3x3.h:48
const btMultiBodyLinkCollider * getBaseCollider() const
Definition: btMultiBody.h:91
btVector3 worldDirToLocal(int i, const btVector3 &vec) const
const btVector3 & getLinkInertia(int i) const
void setupRevolute(int i, btScalar mass, const btVector3 &inertia, int parent, const btQuaternion &zero_rot_parent_to_this, const btVector3 &joint_axis, const btVector3 &parent_axis_position, const btVector3 &my_axis_position, bool disableParentCollision=false)
The btQuaternion implements quaternion to perform linear algebra rotations in combination with btMatr...
Definition: btQuaternion.h:48
btScalar getJointTorque(int i) const
const btQuaternion & getWorldToBaseRot() const
Definition: btMultiBody.h:136
void setBaseMass(btScalar mass)
Definition: btMultiBody.h:123
void stepPositions(btScalar dt)
int getParent(int link_num) const
const btVector3 & getBasePos() const
Definition: btMultiBody.h:131
btVector3 localPosToWorld(int i, const btVector3 &vec) const
const btVector3 & getBaseForce() const
Definition: btMultiBody.h:230
void setBasePos(const btVector3 &pos)
Definition: btMultiBody.h:142
btVector3 base_force
Definition: btMultiBody.h:418
btScalar base_mass
Definition: btMultiBody.h:415
const btScalar * getVelocityVector() const
Definition: btMultiBody.h:177
float btScalar
The btScalar type abstracts floating point numbers, to easily switch between double and single floati...
Definition: btScalar.h:266
btScalar m_angularDamping
Definition: btMultiBody.h:460
bool getUseGyroTerm() const
Definition: btMultiBody.h:373
void stepVelocities(btScalar dt, btAlignedObjectArray< btScalar > &scratch_r, btAlignedObjectArray< btVector3 > &scratch_v, btAlignedObjectArray< btMatrix3x3 > &scratch_m)
btScalar getJointVel(int i) const
btScalar getKineticEnergy() const
btMatrix3x3 cached_inertia_lower_right
Definition: btMultiBody.h:449