btMultiBody.h 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627
  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, <[email protected]>, 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 "LinearMath/btScalar.h"
  22. #include "LinearMath/btVector3.h"
  23. #include "LinearMath/btQuaternion.h"
  24. #include "LinearMath/btMatrix3x3.h"
  25. #include "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 fixedBase, // whether the base is fixed (true) or can move (false)
  39. bool canSleep,
  40. bool multiDof = false
  41. );
  42. ~btMultiBody();
  43. void setupFixed(int linkIndex,
  44. btScalar mass,
  45. const btVector3 &inertia,
  46. int parent,
  47. const btQuaternion &rotParentToThis,
  48. const btVector3 &parentComToThisPivotOffset,
  49. const btVector3 &thisPivotToThisComOffset,
  50. bool disableParentCollision);
  51. void setupPrismatic(int i,
  52. btScalar mass,
  53. const btVector3 &inertia,
  54. int parent,
  55. const btQuaternion &rotParentToThis,
  56. const btVector3 &jointAxis,
  57. const btVector3 &parentComToThisComOffset,
  58. const btVector3 &thisPivotToThisComOffset,
  59. bool disableParentCollision);
  60. void setupRevolute(int linkIndex, // 0 to num_links-1
  61. btScalar mass,
  62. const btVector3 &inertia,
  63. int parentIndex,
  64. const btQuaternion &rotParentToThis, // rotate points in parent frame to this frame, when q = 0
  65. const btVector3 &jointAxis, // in my frame
  66. const btVector3 &parentComToThisPivotOffset, // vector from parent COM to joint axis, in PARENT frame
  67. const btVector3 &thisPivotToThisComOffset, // vector from joint axis to my COM, in MY frame
  68. bool disableParentCollision=false);
  69. void setupSpherical(int linkIndex, // 0 to num_links-1
  70. btScalar mass,
  71. const btVector3 &inertia,
  72. int parent,
  73. const btQuaternion &rotParentToThis, // rotate points in parent frame to this frame, when q = 0
  74. const btVector3 &parentComToThisPivotOffset, // vector from parent COM to joint axis, in PARENT frame
  75. const btVector3 &thisPivotToThisComOffset, // vector from joint axis to my COM, in MY frame
  76. bool disableParentCollision=false);
  77. #ifdef BT_MULTIBODYLINK_INCLUDE_PLANAR_JOINTS
  78. void setupPlanar(int i, // 0 to num_links-1
  79. btScalar mass,
  80. const btVector3 &inertia,
  81. int parent,
  82. const btQuaternion &rotParentToThis, // rotate points in parent frame to this frame, when q = 0
  83. const btVector3 &rotationAxis,
  84. const btVector3 &parentComToThisComOffset, // vector from parent COM to this COM, in PARENT frame
  85. bool disableParentCollision=false);
  86. #endif
  87. const btMultibodyLink& getLink(int index) const
  88. {
  89. return m_links[index];
  90. }
  91. btMultibodyLink& getLink(int index)
  92. {
  93. return m_links[index];
  94. }
  95. void setBaseCollider(btMultiBodyLinkCollider* collider)//collider can be NULL to disable collision for the base
  96. {
  97. m_baseCollider = collider;
  98. }
  99. const btMultiBodyLinkCollider* getBaseCollider() const
  100. {
  101. return m_baseCollider;
  102. }
  103. btMultiBodyLinkCollider* getBaseCollider()
  104. {
  105. return m_baseCollider;
  106. }
  107. //
  108. // get parent
  109. // input: link num from 0 to num_links-1
  110. // output: link num from 0 to num_links-1, OR -1 to mean the base.
  111. //
  112. int getParent(int link_num) const;
  113. //
  114. // get number of m_links, masses, moments of inertia
  115. //
  116. int getNumLinks() const { return m_links.size(); }
  117. int getNumDofs() const { return m_dofCount; }
  118. int getNumPosVars() const { return m_posVarCnt; }
  119. btScalar getBaseMass() const { return m_baseMass; }
  120. const btVector3 & getBaseInertia() const { return m_baseInertia; }
  121. btScalar getLinkMass(int i) const;
  122. const btVector3 & getLinkInertia(int i) const;
  123. //
  124. // change mass (incomplete: can only change base mass and inertia at present)
  125. //
  126. void setBaseMass(btScalar mass) { m_baseMass = mass; }
  127. void setBaseInertia(const btVector3 &inertia) { m_baseInertia = inertia; }
  128. //
  129. // get/set pos/vel/rot/omega for the base link
  130. //
  131. const btVector3 & getBasePos() const { return m_basePos; } // in world frame
  132. const btVector3 getBaseVel() const
  133. {
  134. return btVector3(m_realBuf[3],m_realBuf[4],m_realBuf[5]);
  135. } // in world frame
  136. const btQuaternion & getWorldToBaseRot() const
  137. {
  138. return m_baseQuat;
  139. } // rotates world vectors into base frame
  140. btVector3 getBaseOmega() const { return btVector3(m_realBuf[0],m_realBuf[1],m_realBuf[2]); } // in world frame
  141. void setBasePos(const btVector3 &pos)
  142. {
  143. m_basePos = pos;
  144. }
  145. void setBaseWorldTransform(const btTransform& tr)
  146. {
  147. setBasePos(tr.getOrigin());
  148. setWorldToBaseRot(tr.getRotation().inverse());
  149. }
  150. void setBaseVel(const btVector3 &vel)
  151. {
  152. m_realBuf[3]=vel[0]; m_realBuf[4]=vel[1]; m_realBuf[5]=vel[2];
  153. }
  154. void setWorldToBaseRot(const btQuaternion &rot)
  155. {
  156. m_baseQuat = rot; //m_baseQuat asumed to ba alias!?
  157. }
  158. void setBaseOmega(const btVector3 &omega)
  159. {
  160. m_realBuf[0]=omega[0];
  161. m_realBuf[1]=omega[1];
  162. m_realBuf[2]=omega[2];
  163. }
  164. //
  165. // get/set pos/vel for child m_links (i = 0 to num_links-1)
  166. //
  167. btScalar getJointPos(int i) const;
  168. btScalar getJointVel(int i) const;
  169. btScalar * getJointVelMultiDof(int i);
  170. btScalar * getJointPosMultiDof(int i);
  171. void setJointPos(int i, btScalar q);
  172. void setJointVel(int i, btScalar qdot);
  173. void setJointPosMultiDof(int i, btScalar *q);
  174. void setJointVelMultiDof(int i, btScalar *qdot);
  175. //
  176. // direct access to velocities as a vector of 6 + num_links elements.
  177. // (omega first, then v, then joint velocities.)
  178. //
  179. const btScalar * getVelocityVector() const
  180. {
  181. return &m_realBuf[0];
  182. }
  183. /* btScalar * getVelocityVector()
  184. {
  185. return &real_buf[0];
  186. }
  187. */
  188. //
  189. // get the frames of reference (positions and orientations) of the child m_links
  190. // (i = 0 to num_links-1)
  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. // transform vectors in local frame of link i to world frame (or vice versa)
  196. //
  197. btVector3 localPosToWorld(int i, const btVector3 &vec) const;
  198. btVector3 localDirToWorld(int i, const btVector3 &vec) const;
  199. btVector3 worldPosToLocal(int i, const btVector3 &vec) const;
  200. btVector3 worldDirToLocal(int i, const btVector3 &vec) const;
  201. //
  202. // calculate kinetic energy and angular momentum
  203. // useful for debugging.
  204. //
  205. btScalar getKineticEnergy() const;
  206. btVector3 getAngularMomentum() const;
  207. //
  208. // set external forces and torques. Note all external forces/torques are given in the WORLD frame.
  209. //
  210. void clearForcesAndTorques();
  211. void clearVelocities();
  212. void addBaseForce(const btVector3 &f)
  213. {
  214. m_baseForce += f;
  215. }
  216. void addBaseTorque(const btVector3 &t) { m_baseTorque += t; }
  217. void addLinkForce(int i, const btVector3 &f);
  218. void addLinkTorque(int i, const btVector3 &t);
  219. void addJointTorque(int i, btScalar Q);
  220. void addJointTorqueMultiDof(int i, int dof, btScalar Q);
  221. void addJointTorqueMultiDof(int i, const btScalar *Q);
  222. const btVector3 & getBaseForce() const { return m_baseForce; }
  223. const btVector3 & getBaseTorque() const { return m_baseTorque; }
  224. const btVector3 & getLinkForce(int i) const;
  225. const btVector3 & getLinkTorque(int i) const;
  226. btScalar getJointTorque(int i) const;
  227. btScalar * getJointTorqueMultiDof(int i);
  228. //
  229. // dynamics routines.
  230. //
  231. // timestep the velocities (given the external forces/torques set using addBaseForce etc).
  232. // also sets up caches for calcAccelerationDeltas.
  233. //
  234. // Note: the caller must provide three vectors which are used as
  235. // temporary scratch space. The idea here is to reduce dynamic
  236. // memory allocation: the same scratch vectors can be re-used
  237. // again and again for different Multibodies, instead of each
  238. // btMultiBody allocating (and then deallocating) their own
  239. // individual scratch buffers. This gives a considerable speed
  240. // improvement, at least on Windows (where dynamic memory
  241. // allocation appears to be fairly slow).
  242. //
  243. void stepVelocities(btScalar dt,
  244. btAlignedObjectArray<btScalar> &scratch_r,
  245. btAlignedObjectArray<btVector3> &scratch_v,
  246. btAlignedObjectArray<btMatrix3x3> &scratch_m);
  247. void stepVelocitiesMultiDof(btScalar dt,
  248. btAlignedObjectArray<btScalar> &scratch_r,
  249. btAlignedObjectArray<btVector3> &scratch_v,
  250. btAlignedObjectArray<btMatrix3x3> &scratch_m);
  251. // calcAccelerationDeltas
  252. // input: force vector (in same format as jacobian, i.e.:
  253. // 3 torque values, 3 force values, num_links joint torque values)
  254. // output: 3 omegadot values, 3 vdot values, num_links q_double_dot values
  255. // (existing contents of output array are replaced)
  256. // stepVelocities must have been called first.
  257. void calcAccelerationDeltas(const btScalar *force, btScalar *output,
  258. btAlignedObjectArray<btScalar> &scratch_r,
  259. btAlignedObjectArray<btVector3> &scratch_v) const;
  260. void calcAccelerationDeltasMultiDof(const btScalar *force, btScalar *output,
  261. btAlignedObjectArray<btScalar> &scratch_r,
  262. btAlignedObjectArray<btVector3> &scratch_v) const;
  263. // apply a delta-vee directly. used in sequential impulses code.
  264. void applyDeltaVee(const btScalar * delta_vee)
  265. {
  266. for (int i = 0; i < 6 + getNumLinks(); ++i)
  267. {
  268. m_realBuf[i] += delta_vee[i];
  269. }
  270. }
  271. void applyDeltaVee(const btScalar * delta_vee, btScalar multiplier)
  272. {
  273. btScalar sum = 0;
  274. for (int i = 0; i < 6 + getNumLinks(); ++i)
  275. {
  276. sum += delta_vee[i]*multiplier*delta_vee[i]*multiplier;
  277. }
  278. btScalar l = btSqrt(sum);
  279. /*
  280. static btScalar maxl = -1e30f;
  281. if (l>maxl)
  282. {
  283. maxl=l;
  284. // printf("maxl=%f\n",maxl);
  285. }
  286. */
  287. if (l>m_maxAppliedImpulse)
  288. {
  289. // printf("exceeds 100: l=%f\n",maxl);
  290. multiplier *= m_maxAppliedImpulse/l;
  291. }
  292. for (int i = 0; i < 6 + getNumLinks(); ++i)
  293. {
  294. sum += delta_vee[i]*multiplier*delta_vee[i]*multiplier;
  295. m_realBuf[i] += delta_vee[i] * multiplier;
  296. btClamp(m_realBuf[i],-m_maxCoordinateVelocity,m_maxCoordinateVelocity);
  297. }
  298. }
  299. void applyDeltaVeeMultiDof(const btScalar * delta_vee, btScalar multiplier)
  300. {
  301. //for (int dof = 0; dof < 6 + getNumDofs(); ++dof)
  302. // printf("%.4f ", delta_vee[dof]*multiplier);
  303. //printf("\n");
  304. //btScalar sum = 0;
  305. //for (int dof = 0; dof < 6 + getNumDofs(); ++dof)
  306. //{
  307. // sum += delta_vee[dof]*multiplier*delta_vee[dof]*multiplier;
  308. //}
  309. //btScalar l = btSqrt(sum);
  310. //if (l>m_maxAppliedImpulse)
  311. //{
  312. // multiplier *= m_maxAppliedImpulse/l;
  313. //}
  314. for (int dof = 0; dof < 6 + getNumDofs(); ++dof)
  315. {
  316. m_realBuf[dof] += delta_vee[dof] * multiplier;
  317. btClamp(m_realBuf[dof],-m_maxCoordinateVelocity,m_maxCoordinateVelocity);
  318. }
  319. }
  320. // timestep the positions (given current velocities).
  321. void stepPositions(btScalar dt);
  322. void stepPositionsMultiDof(btScalar dt, btScalar *pq = 0, btScalar *pqd = 0);
  323. //
  324. // contacts
  325. //
  326. // This routine fills out a contact constraint jacobian for this body.
  327. // the 'normal' supplied must be -n for body1 or +n for body2 of the contact.
  328. // 'normal' & 'contact_point' are both given in world coordinates.
  329. void fillContactJacobian(int link,
  330. const btVector3 &contact_point,
  331. const btVector3 &normal,
  332. btScalar *jac,
  333. btAlignedObjectArray<btScalar> &scratch_r,
  334. btAlignedObjectArray<btVector3> &scratch_v,
  335. btAlignedObjectArray<btMatrix3x3> &scratch_m) const;
  336. //multidof version of fillContactJacobian
  337. void fillContactJacobianMultiDof(int link,
  338. const btVector3 &contact_point,
  339. const btVector3 &normal,
  340. btScalar *jac,
  341. btAlignedObjectArray<btScalar> &scratch_r,
  342. btAlignedObjectArray<btVector3> &scratch_v,
  343. btAlignedObjectArray<btMatrix3x3> &scratch_m) const { filConstraintJacobianMultiDof(link, contact_point, btVector3(0, 0, 0), normal, jac, scratch_r, scratch_v, scratch_m); }
  344. //a more general version of fillContactJacobianMultiDof which does not assume..
  345. //.. that the constraint in question is contact or, to be more precise, constrains linear velocity only
  346. void filConstraintJacobianMultiDof(int link,
  347. const btVector3 &contact_point,
  348. const btVector3 &normal_ang,
  349. const btVector3 &normal_lin,
  350. btScalar *jac,
  351. btAlignedObjectArray<btScalar> &scratch_r,
  352. btAlignedObjectArray<btVector3> &scratch_v,
  353. btAlignedObjectArray<btMatrix3x3> &scratch_m) const;
  354. //
  355. // sleeping
  356. //
  357. void setCanSleep(bool canSleep)
  358. {
  359. m_canSleep = canSleep;
  360. }
  361. bool getCanSleep()const
  362. {
  363. return m_canSleep;
  364. }
  365. bool isAwake() const { return m_awake; }
  366. void wakeUp();
  367. void goToSleep();
  368. void checkMotionAndSleepIfRequired(btScalar timestep);
  369. bool hasFixedBase() const
  370. {
  371. return m_fixedBase;
  372. }
  373. int getCompanionId() const
  374. {
  375. return m_companionId;
  376. }
  377. void setCompanionId(int id)
  378. {
  379. //printf("for %p setCompanionId(%d)\n",this, id);
  380. m_companionId = id;
  381. }
  382. void setNumLinks(int numLinks)//careful: when changing the number of m_links, make sure to re-initialize or update existing m_links
  383. {
  384. m_links.resize(numLinks);
  385. }
  386. btScalar getLinearDamping() const
  387. {
  388. return m_linearDamping;
  389. }
  390. void setLinearDamping( btScalar damp)
  391. {
  392. m_linearDamping = damp;
  393. }
  394. btScalar getAngularDamping() const
  395. {
  396. return m_angularDamping;
  397. }
  398. void setAngularDamping( btScalar damp)
  399. {
  400. m_angularDamping = damp;
  401. }
  402. bool getUseGyroTerm() const
  403. {
  404. return m_useGyroTerm;
  405. }
  406. void setUseGyroTerm(bool useGyro)
  407. {
  408. m_useGyroTerm = useGyro;
  409. }
  410. btScalar getMaxCoordinateVelocity() const
  411. {
  412. return m_maxCoordinateVelocity ;
  413. }
  414. void setMaxCoordinateVelocity(btScalar maxVel)
  415. {
  416. m_maxCoordinateVelocity = maxVel;
  417. }
  418. btScalar getMaxAppliedImpulse() const
  419. {
  420. return m_maxAppliedImpulse;
  421. }
  422. void setMaxAppliedImpulse(btScalar maxImp)
  423. {
  424. m_maxAppliedImpulse = maxImp;
  425. }
  426. void setHasSelfCollision(bool hasSelfCollision)
  427. {
  428. m_hasSelfCollision = hasSelfCollision;
  429. }
  430. bool hasSelfCollision() const
  431. {
  432. return m_hasSelfCollision;
  433. }
  434. bool isMultiDof() { return m_isMultiDof; }
  435. void finalizeMultiDof();
  436. void useRK4Integration(bool use) { m_useRK4 = use; }
  437. bool isUsingRK4Integration() const { return m_useRK4; }
  438. void useGlobalVelocities(bool use) { m_useGlobalVelocities = use; }
  439. bool isUsingGlobalVelocities() const { return m_useGlobalVelocities; }
  440. bool isPosUpdated() const
  441. {
  442. return __posUpdated;
  443. }
  444. void setPosUpdated(bool updated)
  445. {
  446. __posUpdated = updated;
  447. }
  448. private:
  449. btMultiBody(const btMultiBody &); // not implemented
  450. void operator=(const btMultiBody &); // not implemented
  451. void compTreeLinkVelocities(btVector3 *omega, btVector3 *vel) const;
  452. void solveImatrix(const btVector3& rhs_top, const btVector3& rhs_bot, float result[6]) const;
  453. #ifdef TEST_SPATIAL_ALGEBRA_LAYER
  454. void solveImatrix(const btSpatialForceVector &rhs, btSpatialMotionVector &result) const;
  455. #endif
  456. void updateLinksDofOffsets()
  457. {
  458. int dofOffset = 0, cfgOffset = 0;
  459. for(int bidx = 0; bidx < m_links.size(); ++bidx)
  460. {
  461. m_links[bidx].m_dofOffset = dofOffset; m_links[bidx].m_cfgOffset = cfgOffset;
  462. dofOffset += m_links[bidx].m_dofCount; cfgOffset += m_links[bidx].m_posVarCount;
  463. }
  464. }
  465. void mulMatrix(btScalar *pA, btScalar *pB, int rowsA, int colsA, int rowsB, int colsB, btScalar *pC) const;
  466. private:
  467. btMultiBodyLinkCollider* m_baseCollider;//can be NULL
  468. btVector3 m_basePos; // position of COM of base (world frame)
  469. btQuaternion m_baseQuat; // rotates world points into base frame
  470. btScalar m_baseMass; // mass of the base
  471. btVector3 m_baseInertia; // inertia of the base (in local frame; diagonal)
  472. btVector3 m_baseForce; // external force applied to base. World frame.
  473. btVector3 m_baseTorque; // external torque applied to base. World frame.
  474. btAlignedObjectArray<btMultibodyLink> m_links; // array of m_links, excluding the base. index from 0 to num_links-1.
  475. btAlignedObjectArray<btMultiBodyLinkCollider*> m_colliders;
  476. //
  477. // realBuf:
  478. // offset size array
  479. // 0 6 + num_links v (base_omega; base_vel; joint_vels) MULTIDOF [sysdof x sysdof for D matrices (TOO MUCH!) + pos_delta which is sys-cfg sized]
  480. // 6+num_links num_links D
  481. //
  482. // vectorBuf:
  483. // offset size array
  484. // 0 num_links h_top
  485. // num_links num_links h_bottom
  486. //
  487. // matrixBuf:
  488. // offset size array
  489. // 0 num_links+1 rot_from_parent
  490. //
  491. btAlignedObjectArray<btScalar> m_realBuf;
  492. btAlignedObjectArray<btVector3> m_vectorBuf;
  493. btAlignedObjectArray<btMatrix3x3> m_matrixBuf;
  494. //std::auto_ptr<Eigen::LU<Eigen::Matrix<btScalar, 6, 6> > > cached_imatrix_lu;
  495. btMatrix3x3 m_cachedInertiaTopLeft;
  496. btMatrix3x3 m_cachedInertiaTopRight;
  497. btMatrix3x3 m_cachedInertiaLowerLeft;
  498. btMatrix3x3 m_cachedInertiaLowerRight;
  499. bool m_fixedBase;
  500. // Sleep parameters.
  501. bool m_awake;
  502. bool m_canSleep;
  503. btScalar m_sleepTimer;
  504. int m_companionId;
  505. btScalar m_linearDamping;
  506. btScalar m_angularDamping;
  507. bool m_useGyroTerm;
  508. btScalar m_maxAppliedImpulse;
  509. btScalar m_maxCoordinateVelocity;
  510. bool m_hasSelfCollision;
  511. bool m_isMultiDof;
  512. bool __posUpdated;
  513. int m_dofCount, m_posVarCnt;
  514. bool m_useRK4, m_useGlobalVelocities;
  515. };
  516. #endif