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