1
0

btMultiBody.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466
  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. This software is provided 'as-is', without any express or implied warranty.
  11. In no event will the authors be held liable for any damages arising from the use of this software.
  12. Permission is granted to anyone to use this software for any purpose,
  13. including commercial applications, and to alter it and redistribute it freely,
  14. subject to the following restrictions:
  15. 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.
  16. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
  17. 3. This notice may not be removed or altered from any source distribution.
  18. */
  19. #ifndef BT_MULTIBODY_H
  20. #define BT_MULTIBODY_H
  21. #include "bullet/LinearMath/btScalar.h"
  22. #include "bullet/LinearMath/btVector3.h"
  23. #include "bullet/LinearMath/btQuaternion.h"
  24. #include "bullet/LinearMath/btMatrix3x3.h"
  25. #include "bullet/LinearMath/btAlignedObjectArray.h"
  26. #include "btMultiBodyLink.h"
  27. class btMultiBodyLinkCollider;
  28. class btMultiBody
  29. {
  30. public:
  31. BT_DECLARE_ALIGNED_ALLOCATOR();
  32. //
  33. // initialization
  34. //
  35. btMultiBody(int n_links, // NOT including the base
  36. btScalar mass, // mass of base
  37. const btVector3 &inertia, // inertia of base, in base frame; assumed diagonal
  38. bool fixed_base_, // whether the base is fixed (true) or can move (false)
  39. bool can_sleep_);
  40. ~btMultiBody();
  41. void setupPrismatic(int i, // 0 to num_links-1
  42. btScalar mass,
  43. const btVector3 &inertia, // in my frame; assumed diagonal
  44. int parent,
  45. const btQuaternion &rot_parent_to_this, // rotate points in parent frame to my frame.
  46. const btVector3 &joint_axis, // in my frame
  47. const btVector3 &r_vector_when_q_zero, // vector from parent COM to my COM, in my frame, when q = 0.
  48. bool disableParentCollision=false
  49. );
  50. void setupRevolute(int i, // 0 to num_links-1
  51. btScalar mass,
  52. const btVector3 &inertia,
  53. int parent,
  54. const btQuaternion &zero_rot_parent_to_this, // rotate points in parent frame to this frame, when q = 0
  55. const btVector3 &joint_axis, // in my frame
  56. const btVector3 &parent_axis_position, // vector from parent COM to joint axis, in PARENT frame
  57. const btVector3 &my_axis_position, // vector from joint axis to my COM, in MY frame
  58. bool disableParentCollision=false);
  59. const btMultibodyLink& getLink(int index) const
  60. {
  61. return links[index];
  62. }
  63. btMultibodyLink& getLink(int index)
  64. {
  65. return links[index];
  66. }
  67. void setBaseCollider(btMultiBodyLinkCollider* collider)//collider can be NULL to disable collision for the base
  68. {
  69. m_baseCollider = collider;
  70. }
  71. const btMultiBodyLinkCollider* getBaseCollider() const
  72. {
  73. return m_baseCollider;
  74. }
  75. btMultiBodyLinkCollider* getBaseCollider()
  76. {
  77. return m_baseCollider;
  78. }
  79. //
  80. // get parent
  81. // input: link num from 0 to num_links-1
  82. // output: link num from 0 to num_links-1, OR -1 to mean the base.
  83. //
  84. int getParent(int link_num) const;
  85. //
  86. // get number of links, masses, moments of inertia
  87. //
  88. int getNumLinks() const { return links.size(); }
  89. btScalar getBaseMass() const { return base_mass; }
  90. const btVector3 & getBaseInertia() const { return base_inertia; }
  91. btScalar getLinkMass(int i) const;
  92. const btVector3 & getLinkInertia(int i) const;
  93. //
  94. // change mass (incomplete: can only change base mass and inertia at present)
  95. //
  96. void setBaseMass(btScalar mass) { base_mass = mass; }
  97. void setBaseInertia(const btVector3 &inertia) { base_inertia = inertia; }
  98. //
  99. // get/set pos/vel/rot/omega for the base link
  100. //
  101. const btVector3 & getBasePos() const { return base_pos; } // in world frame
  102. const btVector3 getBaseVel() const
  103. {
  104. return btVector3(m_real_buf[3],m_real_buf[4],m_real_buf[5]);
  105. } // in world frame
  106. const btQuaternion & getWorldToBaseRot() const
  107. {
  108. return base_quat;
  109. } // rotates world vectors into base frame
  110. btVector3 getBaseOmega() const { return btVector3(m_real_buf[0],m_real_buf[1],m_real_buf[2]); } // in world frame
  111. void setBasePos(const btVector3 &pos)
  112. {
  113. base_pos = pos;
  114. }
  115. void setBaseVel(const btVector3 &vel)
  116. {
  117. m_real_buf[3]=vel[0]; m_real_buf[4]=vel[1]; m_real_buf[5]=vel[2];
  118. }
  119. void setWorldToBaseRot(const btQuaternion &rot)
  120. {
  121. base_quat = rot;
  122. }
  123. void setBaseOmega(const btVector3 &omega)
  124. {
  125. m_real_buf[0]=omega[0];
  126. m_real_buf[1]=omega[1];
  127. m_real_buf[2]=omega[2];
  128. }
  129. //
  130. // get/set pos/vel for child links (i = 0 to num_links-1)
  131. //
  132. btScalar getJointPos(int i) const;
  133. btScalar getJointVel(int i) const;
  134. void setJointPos(int i, btScalar q);
  135. void setJointVel(int i, btScalar qdot);
  136. //
  137. // direct access to velocities as a vector of 6 + num_links elements.
  138. // (omega first, then v, then joint velocities.)
  139. //
  140. const btScalar * getVelocityVector() const
  141. {
  142. return &m_real_buf[0];
  143. }
  144. /* btScalar * getVelocityVector()
  145. {
  146. return &real_buf[0];
  147. }
  148. */
  149. //
  150. // get the frames of reference (positions and orientations) of the child links
  151. // (i = 0 to num_links-1)
  152. //
  153. const btVector3 & getRVector(int i) const; // vector from COM(parent(i)) to COM(i), in frame i's coords
  154. const btQuaternion & getParentToLocalRot(int i) const; // rotates vectors in frame parent(i) to vectors in frame i.
  155. //
  156. // transform vectors in local frame of link i to world frame (or vice versa)
  157. //
  158. btVector3 localPosToWorld(int i, const btVector3 &vec) const;
  159. btVector3 localDirToWorld(int i, const btVector3 &vec) const;
  160. btVector3 worldPosToLocal(int i, const btVector3 &vec) const;
  161. btVector3 worldDirToLocal(int i, const btVector3 &vec) const;
  162. //
  163. // calculate kinetic energy and angular momentum
  164. // useful for debugging.
  165. //
  166. btScalar getKineticEnergy() const;
  167. btVector3 getAngularMomentum() const;
  168. //
  169. // set external forces and torques. Note all external forces/torques are given in the WORLD frame.
  170. //
  171. void clearForcesAndTorques();
  172. void clearVelocities();
  173. void addBaseForce(const btVector3 &f)
  174. {
  175. base_force += f;
  176. }
  177. void addBaseTorque(const btVector3 &t) { base_torque += t; }
  178. void addLinkForce(int i, const btVector3 &f);
  179. void addLinkTorque(int i, const btVector3 &t);
  180. void addJointTorque(int i, btScalar Q);
  181. const btVector3 & getBaseForce() const { return base_force; }
  182. const btVector3 & getBaseTorque() const { return base_torque; }
  183. const btVector3 & getLinkForce(int i) const;
  184. const btVector3 & getLinkTorque(int i) const;
  185. btScalar getJointTorque(int i) const;
  186. //
  187. // dynamics routines.
  188. //
  189. // timestep the velocities (given the external forces/torques set using addBaseForce etc).
  190. // also sets up caches for calcAccelerationDeltas.
  191. //
  192. // Note: the caller must provide three vectors which are used as
  193. // temporary scratch space. The idea here is to reduce dynamic
  194. // memory allocation: the same scratch vectors can be re-used
  195. // again and again for different Multibodies, instead of each
  196. // btMultiBody allocating (and then deallocating) their own
  197. // individual scratch buffers. This gives a considerable speed
  198. // improvement, at least on Windows (where dynamic memory
  199. // allocation appears to be fairly slow).
  200. //
  201. void stepVelocities(btScalar dt,
  202. btAlignedObjectArray<btScalar> &scratch_r,
  203. btAlignedObjectArray<btVector3> &scratch_v,
  204. btAlignedObjectArray<btMatrix3x3> &scratch_m);
  205. // calcAccelerationDeltas
  206. // input: force vector (in same format as jacobian, i.e.:
  207. // 3 torque values, 3 force values, num_links joint torque values)
  208. // output: 3 omegadot values, 3 vdot values, num_links q_double_dot values
  209. // (existing contents of output array are replaced)
  210. // stepVelocities must have been called first.
  211. void calcAccelerationDeltas(const btScalar *force, btScalar *output,
  212. btAlignedObjectArray<btScalar> &scratch_r,
  213. btAlignedObjectArray<btVector3> &scratch_v) const;
  214. // apply a delta-vee directly. used in sequential impulses code.
  215. void applyDeltaVee(const btScalar * delta_vee)
  216. {
  217. for (int i = 0; i < 6 + getNumLinks(); ++i)
  218. {
  219. m_real_buf[i] += delta_vee[i];
  220. }
  221. }
  222. void applyDeltaVee(const btScalar * delta_vee, btScalar multiplier)
  223. {
  224. btScalar sum = 0;
  225. for (int i = 0; i < 6 + getNumLinks(); ++i)
  226. {
  227. sum += delta_vee[i]*multiplier*delta_vee[i]*multiplier;
  228. }
  229. btScalar l = btSqrt(sum);
  230. /*
  231. static btScalar maxl = -1e30f;
  232. if (l>maxl)
  233. {
  234. maxl=l;
  235. // printf("maxl=%f\n",maxl);
  236. }
  237. */
  238. if (l>m_maxAppliedImpulse)
  239. {
  240. // printf("exceeds 100: l=%f\n",maxl);
  241. multiplier *= m_maxAppliedImpulse/l;
  242. }
  243. for (int i = 0; i < 6 + getNumLinks(); ++i)
  244. {
  245. sum += delta_vee[i]*multiplier*delta_vee[i]*multiplier;
  246. m_real_buf[i] += delta_vee[i] * multiplier;
  247. }
  248. }
  249. // timestep the positions (given current velocities).
  250. void stepPositions(btScalar dt);
  251. //
  252. // contacts
  253. //
  254. // This routine fills out a contact constraint jacobian for this body.
  255. // the 'normal' supplied must be -n for body1 or +n for body2 of the contact.
  256. // 'normal' & 'contact_point' are both given in world coordinates.
  257. void fillContactJacobian(int link,
  258. const btVector3 &contact_point,
  259. const btVector3 &normal,
  260. btScalar *jac,
  261. btAlignedObjectArray<btScalar> &scratch_r,
  262. btAlignedObjectArray<btVector3> &scratch_v,
  263. btAlignedObjectArray<btMatrix3x3> &scratch_m) const;
  264. //
  265. // sleeping
  266. //
  267. void setCanSleep(bool canSleep)
  268. {
  269. can_sleep = canSleep;
  270. }
  271. bool isAwake() const { return awake; }
  272. void wakeUp();
  273. void goToSleep();
  274. void checkMotionAndSleepIfRequired(btScalar timestep);
  275. bool hasFixedBase() const
  276. {
  277. return fixed_base;
  278. }
  279. int getCompanionId() const
  280. {
  281. return m_companionId;
  282. }
  283. void setCompanionId(int id)
  284. {
  285. //printf("for %p setCompanionId(%d)\n",this, id);
  286. m_companionId = id;
  287. }
  288. void setNumLinks(int numLinks)//careful: when changing the number of links, make sure to re-initialize or update existing links
  289. {
  290. links.resize(numLinks);
  291. }
  292. btScalar getLinearDamping() const
  293. {
  294. return m_linearDamping;
  295. }
  296. void setLinearDamping( btScalar damp)
  297. {
  298. m_linearDamping = damp;
  299. }
  300. btScalar getAngularDamping() const
  301. {
  302. return m_angularDamping;
  303. }
  304. bool getUseGyroTerm() const
  305. {
  306. return m_useGyroTerm;
  307. }
  308. void setUseGyroTerm(bool useGyro)
  309. {
  310. m_useGyroTerm = useGyro;
  311. }
  312. btScalar getMaxAppliedImpulse() const
  313. {
  314. return m_maxAppliedImpulse;
  315. }
  316. void setMaxAppliedImpulse(btScalar maxImp)
  317. {
  318. m_maxAppliedImpulse = maxImp;
  319. }
  320. void setHasSelfCollision(bool hasSelfCollision)
  321. {
  322. m_hasSelfCollision = hasSelfCollision;
  323. }
  324. bool hasSelfCollision() const
  325. {
  326. return m_hasSelfCollision;
  327. }
  328. private:
  329. btMultiBody(const btMultiBody &); // not implemented
  330. void operator=(const btMultiBody &); // not implemented
  331. void compTreeLinkVelocities(btVector3 *omega, btVector3 *vel) const;
  332. void solveImatrix(const btVector3& rhs_top, const btVector3& rhs_bot, float result[6]) const;
  333. private:
  334. btMultiBodyLinkCollider* m_baseCollider;//can be NULL
  335. btVector3 base_pos; // position of COM of base (world frame)
  336. btQuaternion base_quat; // rotates world points into base frame
  337. btScalar base_mass; // mass of the base
  338. btVector3 base_inertia; // inertia of the base (in local frame; diagonal)
  339. btVector3 base_force; // external force applied to base. World frame.
  340. btVector3 base_torque; // external torque applied to base. World frame.
  341. btAlignedObjectArray<btMultibodyLink> links; // array of links, excluding the base. index from 0 to num_links-1.
  342. btAlignedObjectArray<btMultiBodyLinkCollider*> m_colliders;
  343. //
  344. // real_buf:
  345. // offset size array
  346. // 0 6 + num_links v (base_omega; base_vel; joint_vels)
  347. // 6+num_links num_links D
  348. //
  349. // vector_buf:
  350. // offset size array
  351. // 0 num_links h_top
  352. // num_links num_links h_bottom
  353. //
  354. // matrix_buf:
  355. // offset size array
  356. // 0 num_links+1 rot_from_parent
  357. //
  358. btAlignedObjectArray<btScalar> m_real_buf;
  359. btAlignedObjectArray<btVector3> vector_buf;
  360. btAlignedObjectArray<btMatrix3x3> matrix_buf;
  361. //std::auto_ptr<Eigen::LU<Eigen::Matrix<btScalar, 6, 6> > > cached_imatrix_lu;
  362. btMatrix3x3 cached_inertia_top_left;
  363. btMatrix3x3 cached_inertia_top_right;
  364. btMatrix3x3 cached_inertia_lower_left;
  365. btMatrix3x3 cached_inertia_lower_right;
  366. bool fixed_base;
  367. // Sleep parameters.
  368. bool awake;
  369. bool can_sleep;
  370. btScalar sleep_timer;
  371. int m_companionId;
  372. btScalar m_linearDamping;
  373. btScalar m_angularDamping;
  374. bool m_useGyroTerm;
  375. btScalar m_maxAppliedImpulse;
  376. bool m_hasSelfCollision;
  377. };
  378. #endif