btMultiBody.cpp 79 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462
  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: connection to LCP solver, various multibody constraints, replacing Eigen math library by Bullet LinearMath and a dedicated 6x6 matrix inverse (solveImatrix)
  10. * Portions written By Jakub Stepien: support for multi-DOF constraints, introduction of spatial algebra and several other improvements
  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. 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.
  17. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
  18. 3. This notice may not be removed or altered from any source distribution.
  19. */
  20. #include "btMultiBody.h"
  21. #include "btMultiBodyLink.h"
  22. #include "btMultiBodyLinkCollider.h"
  23. #include "btMultiBodyJointFeedback.h"
  24. #include "LinearMath/btTransformUtil.h"
  25. #include "LinearMath/btSerializer.h"
  26. //#include "Bullet3Common/b3Logging.h"
  27. // #define INCLUDE_GYRO_TERM
  28. namespace
  29. {
  30. const btScalar INITIAL_SLEEP_EPSILON = btScalar(0.05); // this is a squared velocity (m^2 s^-2)
  31. const btScalar INITIAL_SLEEP_TIMEOUT = btScalar(2); // in seconds
  32. } // namespace
  33. void btMultiBody::spatialTransform(const btMatrix3x3 &rotation_matrix, // rotates vectors in 'from' frame to vectors in 'to' frame
  34. const btVector3 &displacement, // vector from origin of 'from' frame to origin of 'to' frame, in 'to' coordinates
  35. const btVector3 &top_in, // top part of input vector
  36. const btVector3 &bottom_in, // bottom part of input vector
  37. btVector3 &top_out, // top part of output vector
  38. btVector3 &bottom_out) // bottom part of output vector
  39. {
  40. top_out = rotation_matrix * top_in;
  41. bottom_out = -displacement.cross(top_out) + rotation_matrix * bottom_in;
  42. }
  43. namespace
  44. {
  45. #if 0
  46. void InverseSpatialTransform(const btMatrix3x3 &rotation_matrix,
  47. const btVector3 &displacement,
  48. const btVector3 &top_in,
  49. const btVector3 &bottom_in,
  50. btVector3 &top_out,
  51. btVector3 &bottom_out)
  52. {
  53. top_out = rotation_matrix.transpose() * top_in;
  54. bottom_out = rotation_matrix.transpose() * (bottom_in + displacement.cross(top_in));
  55. }
  56. btScalar SpatialDotProduct(const btVector3 &a_top,
  57. const btVector3 &a_bottom,
  58. const btVector3 &b_top,
  59. const btVector3 &b_bottom)
  60. {
  61. return a_bottom.dot(b_top) + a_top.dot(b_bottom);
  62. }
  63. void SpatialCrossProduct(const btVector3 &a_top,
  64. const btVector3 &a_bottom,
  65. const btVector3 &b_top,
  66. const btVector3 &b_bottom,
  67. btVector3 &top_out,
  68. btVector3 &bottom_out)
  69. {
  70. top_out = a_top.cross(b_top);
  71. bottom_out = a_bottom.cross(b_top) + a_top.cross(b_bottom);
  72. }
  73. #endif
  74. } // namespace
  75. //
  76. // Implementation of class btMultiBody
  77. //
  78. btMultiBody::btMultiBody(int n_links,
  79. btScalar mass,
  80. const btVector3 &inertia,
  81. bool fixedBase,
  82. bool canSleep,
  83. bool /*deprecatedUseMultiDof*/)
  84. : m_baseCollider(0),
  85. m_baseName(0),
  86. m_basePos(0, 0, 0),
  87. m_baseQuat(0, 0, 0, 1),
  88. m_basePos_interpolate(0, 0, 0),
  89. m_baseQuat_interpolate(0, 0, 0, 1),
  90. m_baseMass(mass),
  91. m_baseInertia(inertia),
  92. m_fixedBase(fixedBase),
  93. m_awake(true),
  94. m_canSleep(canSleep),
  95. m_canWakeup(true),
  96. m_sleepTimer(0),
  97. m_sleepEpsilon(INITIAL_SLEEP_EPSILON),
  98. m_sleepTimeout(INITIAL_SLEEP_TIMEOUT),
  99. m_userObjectPointer(0),
  100. m_userIndex2(-1),
  101. m_userIndex(-1),
  102. m_companionId(-1),
  103. m_linearDamping(0.04f),
  104. m_angularDamping(0.04f),
  105. m_useGyroTerm(true),
  106. m_maxAppliedImpulse(1000.f),
  107. m_maxCoordinateVelocity(100.f),
  108. m_hasSelfCollision(true),
  109. __posUpdated(false),
  110. m_dofCount(0),
  111. m_posVarCnt(0),
  112. m_useRK4(false),
  113. m_useGlobalVelocities(false),
  114. m_internalNeedsJointFeedback(false),
  115. m_kinematic_calculate_velocity(false)
  116. {
  117. m_cachedInertiaTopLeft.setValue(0, 0, 0, 0, 0, 0, 0, 0, 0);
  118. m_cachedInertiaTopRight.setValue(0, 0, 0, 0, 0, 0, 0, 0, 0);
  119. m_cachedInertiaLowerLeft.setValue(0, 0, 0, 0, 0, 0, 0, 0, 0);
  120. m_cachedInertiaLowerRight.setValue(0, 0, 0, 0, 0, 0, 0, 0, 0);
  121. m_cachedInertiaValid = false;
  122. m_links.resize(n_links);
  123. m_matrixBuf.resize(n_links + 1);
  124. m_baseForce.setValue(0, 0, 0);
  125. m_baseTorque.setValue(0, 0, 0);
  126. clearConstraintForces();
  127. clearForcesAndTorques();
  128. }
  129. btMultiBody::~btMultiBody()
  130. {
  131. }
  132. void btMultiBody::setupFixed(int i,
  133. btScalar mass,
  134. const btVector3 &inertia,
  135. int parent,
  136. const btQuaternion &rotParentToThis,
  137. const btVector3 &parentComToThisPivotOffset,
  138. const btVector3 &thisPivotToThisComOffset, bool /*deprecatedDisableParentCollision*/)
  139. {
  140. m_links[i].m_mass = mass;
  141. m_links[i].m_inertiaLocal = inertia;
  142. m_links[i].m_parent = parent;
  143. m_links[i].setAxisTop(0, 0., 0., 0.);
  144. m_links[i].setAxisBottom(0, btVector3(0, 0, 0));
  145. m_links[i].m_zeroRotParentToThis = rotParentToThis;
  146. m_links[i].m_dVector = thisPivotToThisComOffset;
  147. m_links[i].m_eVector = parentComToThisPivotOffset;
  148. m_links[i].m_jointType = btMultibodyLink::eFixed;
  149. m_links[i].m_dofCount = 0;
  150. m_links[i].m_posVarCount = 0;
  151. m_links[i].m_flags |= BT_MULTIBODYLINKFLAGS_DISABLE_PARENT_COLLISION;
  152. m_links[i].updateCacheMultiDof();
  153. updateLinksDofOffsets();
  154. }
  155. void btMultiBody::setupPrismatic(int i,
  156. btScalar mass,
  157. const btVector3 &inertia,
  158. int parent,
  159. const btQuaternion &rotParentToThis,
  160. const btVector3 &jointAxis,
  161. const btVector3 &parentComToThisPivotOffset,
  162. const btVector3 &thisPivotToThisComOffset,
  163. bool disableParentCollision)
  164. {
  165. m_dofCount += 1;
  166. m_posVarCnt += 1;
  167. m_links[i].m_mass = mass;
  168. m_links[i].m_inertiaLocal = inertia;
  169. m_links[i].m_parent = parent;
  170. m_links[i].m_zeroRotParentToThis = rotParentToThis;
  171. m_links[i].setAxisTop(0, 0., 0., 0.);
  172. m_links[i].setAxisBottom(0, jointAxis);
  173. m_links[i].m_eVector = parentComToThisPivotOffset;
  174. m_links[i].m_dVector = thisPivotToThisComOffset;
  175. m_links[i].m_cachedRotParentToThis = rotParentToThis;
  176. m_links[i].m_jointType = btMultibodyLink::ePrismatic;
  177. m_links[i].m_dofCount = 1;
  178. m_links[i].m_posVarCount = 1;
  179. m_links[i].m_jointPos[0] = 0.f;
  180. m_links[i].m_jointTorque[0] = 0.f;
  181. if (disableParentCollision)
  182. m_links[i].m_flags |= BT_MULTIBODYLINKFLAGS_DISABLE_PARENT_COLLISION;
  183. //
  184. m_links[i].updateCacheMultiDof();
  185. updateLinksDofOffsets();
  186. }
  187. void btMultiBody::setupRevolute(int i,
  188. btScalar mass,
  189. const btVector3 &inertia,
  190. int parent,
  191. const btQuaternion &rotParentToThis,
  192. const btVector3 &jointAxis,
  193. const btVector3 &parentComToThisPivotOffset,
  194. const btVector3 &thisPivotToThisComOffset,
  195. bool disableParentCollision)
  196. {
  197. m_dofCount += 1;
  198. m_posVarCnt += 1;
  199. m_links[i].m_mass = mass;
  200. m_links[i].m_inertiaLocal = inertia;
  201. m_links[i].m_parent = parent;
  202. m_links[i].m_zeroRotParentToThis = rotParentToThis;
  203. m_links[i].setAxisTop(0, jointAxis);
  204. m_links[i].setAxisBottom(0, jointAxis.cross(thisPivotToThisComOffset));
  205. m_links[i].m_dVector = thisPivotToThisComOffset;
  206. m_links[i].m_eVector = parentComToThisPivotOffset;
  207. m_links[i].m_jointType = btMultibodyLink::eRevolute;
  208. m_links[i].m_dofCount = 1;
  209. m_links[i].m_posVarCount = 1;
  210. m_links[i].m_jointPos[0] = 0.f;
  211. m_links[i].m_jointTorque[0] = 0.f;
  212. if (disableParentCollision)
  213. m_links[i].m_flags |= BT_MULTIBODYLINKFLAGS_DISABLE_PARENT_COLLISION;
  214. //
  215. m_links[i].updateCacheMultiDof();
  216. //
  217. updateLinksDofOffsets();
  218. }
  219. void btMultiBody::setupSpherical(int i,
  220. btScalar mass,
  221. const btVector3 &inertia,
  222. int parent,
  223. const btQuaternion &rotParentToThis,
  224. const btVector3 &parentComToThisPivotOffset,
  225. const btVector3 &thisPivotToThisComOffset,
  226. bool disableParentCollision)
  227. {
  228. m_dofCount += 3;
  229. m_posVarCnt += 4;
  230. m_links[i].m_mass = mass;
  231. m_links[i].m_inertiaLocal = inertia;
  232. m_links[i].m_parent = parent;
  233. m_links[i].m_zeroRotParentToThis = rotParentToThis;
  234. m_links[i].m_dVector = thisPivotToThisComOffset;
  235. m_links[i].m_eVector = parentComToThisPivotOffset;
  236. m_links[i].m_jointType = btMultibodyLink::eSpherical;
  237. m_links[i].m_dofCount = 3;
  238. m_links[i].m_posVarCount = 4;
  239. m_links[i].setAxisTop(0, 1.f, 0.f, 0.f);
  240. m_links[i].setAxisTop(1, 0.f, 1.f, 0.f);
  241. m_links[i].setAxisTop(2, 0.f, 0.f, 1.f);
  242. m_links[i].setAxisBottom(0, m_links[i].getAxisTop(0).cross(thisPivotToThisComOffset));
  243. m_links[i].setAxisBottom(1, m_links[i].getAxisTop(1).cross(thisPivotToThisComOffset));
  244. m_links[i].setAxisBottom(2, m_links[i].getAxisTop(2).cross(thisPivotToThisComOffset));
  245. m_links[i].m_jointPos[0] = m_links[i].m_jointPos[1] = m_links[i].m_jointPos[2] = 0.f;
  246. m_links[i].m_jointPos[3] = 1.f;
  247. m_links[i].m_jointTorque[0] = m_links[i].m_jointTorque[1] = m_links[i].m_jointTorque[2] = 0.f;
  248. if (disableParentCollision)
  249. m_links[i].m_flags |= BT_MULTIBODYLINKFLAGS_DISABLE_PARENT_COLLISION;
  250. //
  251. m_links[i].updateCacheMultiDof();
  252. //
  253. updateLinksDofOffsets();
  254. }
  255. void btMultiBody::setupPlanar(int i,
  256. btScalar mass,
  257. const btVector3 &inertia,
  258. int parent,
  259. const btQuaternion &rotParentToThis,
  260. const btVector3 &rotationAxis,
  261. const btVector3 &parentComToThisComOffset,
  262. bool disableParentCollision)
  263. {
  264. m_dofCount += 3;
  265. m_posVarCnt += 3;
  266. m_links[i].m_mass = mass;
  267. m_links[i].m_inertiaLocal = inertia;
  268. m_links[i].m_parent = parent;
  269. m_links[i].m_zeroRotParentToThis = rotParentToThis;
  270. m_links[i].m_dVector.setZero();
  271. m_links[i].m_eVector = parentComToThisComOffset;
  272. //
  273. btVector3 vecNonParallelToRotAxis(1, 0, 0);
  274. if (rotationAxis.normalized().dot(vecNonParallelToRotAxis) > 0.999)
  275. vecNonParallelToRotAxis.setValue(0, 1, 0);
  276. //
  277. m_links[i].m_jointType = btMultibodyLink::ePlanar;
  278. m_links[i].m_dofCount = 3;
  279. m_links[i].m_posVarCount = 3;
  280. btVector3 n = rotationAxis.normalized();
  281. m_links[i].setAxisTop(0, n[0], n[1], n[2]);
  282. m_links[i].setAxisTop(1, 0, 0, 0);
  283. m_links[i].setAxisTop(2, 0, 0, 0);
  284. m_links[i].setAxisBottom(0, 0, 0, 0);
  285. btVector3 cr = m_links[i].getAxisTop(0).cross(vecNonParallelToRotAxis);
  286. m_links[i].setAxisBottom(1, cr[0], cr[1], cr[2]);
  287. cr = m_links[i].getAxisBottom(1).cross(m_links[i].getAxisTop(0));
  288. m_links[i].setAxisBottom(2, cr[0], cr[1], cr[2]);
  289. m_links[i].m_jointPos[0] = m_links[i].m_jointPos[1] = m_links[i].m_jointPos[2] = 0.f;
  290. m_links[i].m_jointTorque[0] = m_links[i].m_jointTorque[1] = m_links[i].m_jointTorque[2] = 0.f;
  291. if (disableParentCollision)
  292. m_links[i].m_flags |= BT_MULTIBODYLINKFLAGS_DISABLE_PARENT_COLLISION;
  293. //
  294. m_links[i].updateCacheMultiDof();
  295. //
  296. updateLinksDofOffsets();
  297. m_links[i].setAxisBottom(1, m_links[i].getAxisBottom(1).normalized());
  298. m_links[i].setAxisBottom(2, m_links[i].getAxisBottom(2).normalized());
  299. }
  300. void btMultiBody::finalizeMultiDof()
  301. {
  302. m_deltaV.resize(0);
  303. m_deltaV.resize(6 + m_dofCount);
  304. m_splitV.resize(0);
  305. m_splitV.resize(6 + m_dofCount);
  306. m_realBuf.resize(6 + m_dofCount + m_dofCount * m_dofCount + 6 + m_dofCount); //m_dofCount for joint-space vels + m_dofCount^2 for "D" matrices + delta-pos vector (6 base "vels" + joint "vels")
  307. m_vectorBuf.resize(2 * m_dofCount); //two 3-vectors (i.e. one six-vector) for each system dof ("h" matrices)
  308. m_matrixBuf.resize(m_links.size() + 1);
  309. for (int i = 0; i < m_vectorBuf.size(); i++)
  310. {
  311. m_vectorBuf[i].setValue(0, 0, 0);
  312. }
  313. updateLinksDofOffsets();
  314. }
  315. int btMultiBody::getParent(int link_num) const
  316. {
  317. return m_links[link_num].m_parent;
  318. }
  319. btScalar btMultiBody::getLinkMass(int i) const
  320. {
  321. return m_links[i].m_mass;
  322. }
  323. const btVector3 &btMultiBody::getLinkInertia(int i) const
  324. {
  325. return m_links[i].m_inertiaLocal;
  326. }
  327. btScalar btMultiBody::getJointPos(int i) const
  328. {
  329. return m_links[i].m_jointPos[0];
  330. }
  331. btScalar btMultiBody::getJointVel(int i) const
  332. {
  333. return m_realBuf[6 + m_links[i].m_dofOffset];
  334. }
  335. btScalar *btMultiBody::getJointPosMultiDof(int i)
  336. {
  337. return &m_links[i].m_jointPos[0];
  338. }
  339. btScalar *btMultiBody::getJointVelMultiDof(int i)
  340. {
  341. return &m_realBuf[6 + m_links[i].m_dofOffset];
  342. }
  343. const btScalar *btMultiBody::getJointPosMultiDof(int i) const
  344. {
  345. return &m_links[i].m_jointPos[0];
  346. }
  347. const btScalar *btMultiBody::getJointVelMultiDof(int i) const
  348. {
  349. return &m_realBuf[6 + m_links[i].m_dofOffset];
  350. }
  351. void btMultiBody::setJointPos(int i, btScalar q)
  352. {
  353. m_links[i].m_jointPos[0] = q;
  354. m_links[i].updateCacheMultiDof();
  355. }
  356. void btMultiBody::setJointPosMultiDof(int i, const double *q)
  357. {
  358. for (int pos = 0; pos < m_links[i].m_posVarCount; ++pos)
  359. m_links[i].m_jointPos[pos] = (btScalar)q[pos];
  360. m_links[i].updateCacheMultiDof();
  361. }
  362. void btMultiBody::setJointPosMultiDof(int i, const float *q)
  363. {
  364. for (int pos = 0; pos < m_links[i].m_posVarCount; ++pos)
  365. m_links[i].m_jointPos[pos] = (btScalar)q[pos];
  366. m_links[i].updateCacheMultiDof();
  367. }
  368. void btMultiBody::setJointVel(int i, btScalar qdot)
  369. {
  370. m_realBuf[6 + m_links[i].m_dofOffset] = qdot;
  371. }
  372. void btMultiBody::setJointVelMultiDof(int i, const double *qdot)
  373. {
  374. for (int dof = 0; dof < m_links[i].m_dofCount; ++dof)
  375. m_realBuf[6 + m_links[i].m_dofOffset + dof] = (btScalar)qdot[dof];
  376. }
  377. void btMultiBody::setJointVelMultiDof(int i, const float* qdot)
  378. {
  379. for (int dof = 0; dof < m_links[i].m_dofCount; ++dof)
  380. m_realBuf[6 + m_links[i].m_dofOffset + dof] = (btScalar)qdot[dof];
  381. }
  382. const btVector3 &btMultiBody::getRVector(int i) const
  383. {
  384. return m_links[i].m_cachedRVector;
  385. }
  386. const btQuaternion &btMultiBody::getParentToLocalRot(int i) const
  387. {
  388. return m_links[i].m_cachedRotParentToThis;
  389. }
  390. const btVector3 &btMultiBody::getInterpolateRVector(int i) const
  391. {
  392. return m_links[i].m_cachedRVector_interpolate;
  393. }
  394. const btQuaternion &btMultiBody::getInterpolateParentToLocalRot(int i) const
  395. {
  396. return m_links[i].m_cachedRotParentToThis_interpolate;
  397. }
  398. btVector3 btMultiBody::localPosToWorld(int i, const btVector3 &local_pos) const
  399. {
  400. btAssert(i >= -1);
  401. btAssert(i < m_links.size());
  402. if ((i < -1) || (i >= m_links.size()))
  403. {
  404. return btVector3(SIMD_INFINITY, SIMD_INFINITY, SIMD_INFINITY);
  405. }
  406. btVector3 result = local_pos;
  407. while (i != -1)
  408. {
  409. // 'result' is in frame i. transform it to frame parent(i)
  410. result += getRVector(i);
  411. result = quatRotate(getParentToLocalRot(i).inverse(), result);
  412. i = getParent(i);
  413. }
  414. // 'result' is now in the base frame. transform it to world frame
  415. result = quatRotate(getWorldToBaseRot().inverse(), result);
  416. result += getBasePos();
  417. return result;
  418. }
  419. btVector3 btMultiBody::worldPosToLocal(int i, const btVector3 &world_pos) const
  420. {
  421. btAssert(i >= -1);
  422. btAssert(i < m_links.size());
  423. if ((i < -1) || (i >= m_links.size()))
  424. {
  425. return btVector3(SIMD_INFINITY, SIMD_INFINITY, SIMD_INFINITY);
  426. }
  427. if (i == -1)
  428. {
  429. // world to base
  430. return quatRotate(getWorldToBaseRot(), (world_pos - getBasePos()));
  431. }
  432. else
  433. {
  434. // find position in parent frame, then transform to current frame
  435. return quatRotate(getParentToLocalRot(i), worldPosToLocal(getParent(i), world_pos)) - getRVector(i);
  436. }
  437. }
  438. btVector3 btMultiBody::localDirToWorld(int i, const btVector3 &local_dir) const
  439. {
  440. btAssert(i >= -1);
  441. btAssert(i < m_links.size());
  442. if ((i < -1) || (i >= m_links.size()))
  443. {
  444. return btVector3(SIMD_INFINITY, SIMD_INFINITY, SIMD_INFINITY);
  445. }
  446. btVector3 result = local_dir;
  447. while (i != -1)
  448. {
  449. result = quatRotate(getParentToLocalRot(i).inverse(), result);
  450. i = getParent(i);
  451. }
  452. result = quatRotate(getWorldToBaseRot().inverse(), result);
  453. return result;
  454. }
  455. btVector3 btMultiBody::worldDirToLocal(int i, const btVector3 &world_dir) const
  456. {
  457. btAssert(i >= -1);
  458. btAssert(i < m_links.size());
  459. if ((i < -1) || (i >= m_links.size()))
  460. {
  461. return btVector3(SIMD_INFINITY, SIMD_INFINITY, SIMD_INFINITY);
  462. }
  463. if (i == -1)
  464. {
  465. return quatRotate(getWorldToBaseRot(), world_dir);
  466. }
  467. else
  468. {
  469. return quatRotate(getParentToLocalRot(i), worldDirToLocal(getParent(i), world_dir));
  470. }
  471. }
  472. btMatrix3x3 btMultiBody::localFrameToWorld(int i, const btMatrix3x3 &local_frame) const
  473. {
  474. btMatrix3x3 result = local_frame;
  475. btVector3 frameInWorld0 = localDirToWorld(i, local_frame.getColumn(0));
  476. btVector3 frameInWorld1 = localDirToWorld(i, local_frame.getColumn(1));
  477. btVector3 frameInWorld2 = localDirToWorld(i, local_frame.getColumn(2));
  478. result.setValue(frameInWorld0[0], frameInWorld1[0], frameInWorld2[0], frameInWorld0[1], frameInWorld1[1], frameInWorld2[1], frameInWorld0[2], frameInWorld1[2], frameInWorld2[2]);
  479. return result;
  480. }
  481. void btMultiBody::compTreeLinkVelocities(btVector3 *omega, btVector3 *vel) const
  482. {
  483. int num_links = getNumLinks();
  484. // Calculates the velocities of each link (and the base) in its local frame
  485. const btQuaternion& base_rot = getWorldToBaseRot();
  486. omega[0] = quatRotate(base_rot, getBaseOmega());
  487. vel[0] = quatRotate(base_rot, getBaseVel());
  488. for (int i = 0; i < num_links; ++i)
  489. {
  490. const btMultibodyLink& link = getLink(i);
  491. const int parent = link.m_parent;
  492. // transform parent vel into this frame, store in omega[i+1], vel[i+1]
  493. spatialTransform(btMatrix3x3(link.m_cachedRotParentToThis), link.m_cachedRVector,
  494. omega[parent + 1], vel[parent + 1],
  495. omega[i + 1], vel[i + 1]);
  496. // now add qidot * shat_i
  497. const btScalar* jointVel = getJointVelMultiDof(i);
  498. for (int dof = 0; dof < link.m_dofCount; ++dof)
  499. {
  500. omega[i + 1] += jointVel[dof] * link.getAxisTop(dof);
  501. vel[i + 1] += jointVel[dof] * link.getAxisBottom(dof);
  502. }
  503. }
  504. }
  505. void btMultiBody::clearConstraintForces()
  506. {
  507. m_baseConstraintForce.setValue(0, 0, 0);
  508. m_baseConstraintTorque.setValue(0, 0, 0);
  509. for (int i = 0; i < getNumLinks(); ++i)
  510. {
  511. m_links[i].m_appliedConstraintForce.setValue(0, 0, 0);
  512. m_links[i].m_appliedConstraintTorque.setValue(0, 0, 0);
  513. }
  514. }
  515. void btMultiBody::clearForcesAndTorques()
  516. {
  517. m_baseForce.setValue(0, 0, 0);
  518. m_baseTorque.setValue(0, 0, 0);
  519. for (int i = 0; i < getNumLinks(); ++i)
  520. {
  521. m_links[i].m_appliedForce.setValue(0, 0, 0);
  522. m_links[i].m_appliedTorque.setValue(0, 0, 0);
  523. m_links[i].m_jointTorque[0] = m_links[i].m_jointTorque[1] = m_links[i].m_jointTorque[2] = m_links[i].m_jointTorque[3] = m_links[i].m_jointTorque[4] = m_links[i].m_jointTorque[5] = 0.f;
  524. }
  525. }
  526. void btMultiBody::clearVelocities()
  527. {
  528. for (int i = 0; i < 6 + getNumDofs(); ++i)
  529. {
  530. m_realBuf[i] = 0.f;
  531. }
  532. }
  533. void btMultiBody::addLinkForce(int i, const btVector3 &f)
  534. {
  535. m_links[i].m_appliedForce += f;
  536. }
  537. void btMultiBody::addLinkTorque(int i, const btVector3 &t)
  538. {
  539. m_links[i].m_appliedTorque += t;
  540. }
  541. void btMultiBody::addLinkConstraintForce(int i, const btVector3 &f)
  542. {
  543. m_links[i].m_appliedConstraintForce += f;
  544. }
  545. void btMultiBody::addLinkConstraintTorque(int i, const btVector3 &t)
  546. {
  547. m_links[i].m_appliedConstraintTorque += t;
  548. }
  549. void btMultiBody::addJointTorque(int i, btScalar Q)
  550. {
  551. m_links[i].m_jointTorque[0] += Q;
  552. }
  553. void btMultiBody::addJointTorqueMultiDof(int i, int dof, btScalar Q)
  554. {
  555. m_links[i].m_jointTorque[dof] += Q;
  556. }
  557. void btMultiBody::addJointTorqueMultiDof(int i, const btScalar *Q)
  558. {
  559. for (int dof = 0; dof < m_links[i].m_dofCount; ++dof)
  560. m_links[i].m_jointTorque[dof] = Q[dof];
  561. }
  562. const btVector3 &btMultiBody::getLinkForce(int i) const
  563. {
  564. return m_links[i].m_appliedForce;
  565. }
  566. const btVector3 &btMultiBody::getLinkTorque(int i) const
  567. {
  568. return m_links[i].m_appliedTorque;
  569. }
  570. btScalar btMultiBody::getJointTorque(int i) const
  571. {
  572. return m_links[i].m_jointTorque[0];
  573. }
  574. btScalar *btMultiBody::getJointTorqueMultiDof(int i)
  575. {
  576. return &m_links[i].m_jointTorque[0];
  577. }
  578. bool btMultiBody::hasFixedBase() const
  579. {
  580. return m_fixedBase || (getBaseCollider() && getBaseCollider()->isStaticObject());
  581. }
  582. bool btMultiBody::isBaseStaticOrKinematic() const
  583. {
  584. return m_fixedBase || (getBaseCollider() && getBaseCollider()->isStaticOrKinematicObject());
  585. }
  586. bool btMultiBody::isBaseKinematic() const
  587. {
  588. return getBaseCollider() && getBaseCollider()->isKinematicObject();
  589. }
  590. void btMultiBody::setBaseDynamicType(int dynamicType)
  591. {
  592. if(getBaseCollider()) {
  593. int oldFlags = getBaseCollider()->getCollisionFlags();
  594. oldFlags &= ~(btCollisionObject::CF_STATIC_OBJECT | btCollisionObject::CF_KINEMATIC_OBJECT);
  595. getBaseCollider()->setCollisionFlags(oldFlags | dynamicType);
  596. }
  597. }
  598. inline btMatrix3x3 outerProduct(const btVector3 &v0, const btVector3 &v1) //renamed it from vecMulVecTranspose (http://en.wikipedia.org/wiki/Outer_product); maybe it should be moved to btVector3 like dot and cross?
  599. {
  600. btVector3 row0 = btVector3(
  601. v0.x() * v1.x(),
  602. v0.x() * v1.y(),
  603. v0.x() * v1.z());
  604. btVector3 row1 = btVector3(
  605. v0.y() * v1.x(),
  606. v0.y() * v1.y(),
  607. v0.y() * v1.z());
  608. btVector3 row2 = btVector3(
  609. v0.z() * v1.x(),
  610. v0.z() * v1.y(),
  611. v0.z() * v1.z());
  612. btMatrix3x3 m(row0[0], row0[1], row0[2],
  613. row1[0], row1[1], row1[2],
  614. row2[0], row2[1], row2[2]);
  615. return m;
  616. }
  617. #define vecMulVecTranspose(v0, v1Transposed) outerProduct(v0, v1Transposed)
  618. //
  619. void btMultiBody::computeAccelerationsArticulatedBodyAlgorithmMultiDof(btScalar dt,
  620. btAlignedObjectArray<btScalar> &scratch_r,
  621. btAlignedObjectArray<btVector3> &scratch_v,
  622. btAlignedObjectArray<btMatrix3x3> &scratch_m,
  623. bool isConstraintPass,
  624. bool jointFeedbackInWorldSpace,
  625. bool jointFeedbackInJointFrame)
  626. {
  627. // Implement Featherstone's algorithm to calculate joint accelerations (q_double_dot)
  628. // and the base linear & angular accelerations.
  629. // We apply damping forces in this routine as well as any external forces specified by the
  630. // caller (via addBaseForce etc).
  631. // output should point to an array of 6 + num_links reals.
  632. // Format is: 3 angular accelerations (in world frame), 3 linear accelerations (in world frame),
  633. // num_links joint acceleration values.
  634. // We added support for multi degree of freedom (multi dof) joints.
  635. // In addition we also can compute the joint reaction forces. This is performed in a second pass,
  636. // so that we can include the effect of the constraint solver forces (computed in the PGS LCP solver)
  637. m_internalNeedsJointFeedback = false;
  638. int num_links = getNumLinks();
  639. const btScalar DAMPING_K1_LINEAR = m_linearDamping;
  640. const btScalar DAMPING_K2_LINEAR = m_linearDamping;
  641. const btScalar DAMPING_K1_ANGULAR = m_angularDamping;
  642. const btScalar DAMPING_K2_ANGULAR = m_angularDamping;
  643. const btVector3 base_vel = getBaseVel();
  644. const btVector3 base_omega = getBaseOmega();
  645. // Temporary matrices/vectors -- use scratch space from caller
  646. // so that we don't have to keep reallocating every frame
  647. scratch_r.resize(2 * m_dofCount + 7); //multidof? ("Y"s use it and it is used to store qdd) => 2 x m_dofCount
  648. scratch_v.resize(8 * num_links + 6);
  649. scratch_m.resize(4 * num_links + 4);
  650. //btScalar * r_ptr = &scratch_r[0];
  651. btScalar *output = &scratch_r[m_dofCount]; // "output" holds the q_double_dot results
  652. btVector3 *v_ptr = &scratch_v[0];
  653. // vhat_i (top = angular, bottom = linear part)
  654. btSpatialMotionVector *spatVel = (btSpatialMotionVector *)v_ptr;
  655. v_ptr += num_links * 2 + 2;
  656. //
  657. // zhat_i^A
  658. btSpatialForceVector *zeroAccSpatFrc = (btSpatialForceVector *)v_ptr;
  659. v_ptr += num_links * 2 + 2;
  660. //
  661. // chat_i (note NOT defined for the base)
  662. btSpatialMotionVector *spatCoriolisAcc = (btSpatialMotionVector *)v_ptr;
  663. v_ptr += num_links * 2;
  664. //
  665. // Ihat_i^A.
  666. btSymmetricSpatialDyad *spatInertia = (btSymmetricSpatialDyad *)&scratch_m[num_links + 1];
  667. // Cached 3x3 rotation matrices from parent frame to this frame.
  668. btMatrix3x3 *rot_from_parent = &m_matrixBuf[0];
  669. btMatrix3x3 *rot_from_world = &scratch_m[0];
  670. // hhat_i, ahat_i
  671. // hhat is NOT stored for the base (but ahat is)
  672. btSpatialForceVector *h = (btSpatialForceVector *)(m_dofCount > 0 ? &m_vectorBuf[0] : 0);
  673. btSpatialMotionVector *spatAcc = (btSpatialMotionVector *)v_ptr;
  674. v_ptr += num_links * 2 + 2;
  675. //
  676. // Y_i, invD_i
  677. btScalar *invD = m_dofCount > 0 ? &m_realBuf[6 + m_dofCount] : 0;
  678. btScalar *Y = &scratch_r[0];
  679. //
  680. //aux variables
  681. btSpatialMotionVector spatJointVel; //spatial velocity due to the joint motion (i.e. without predecessors' influence)
  682. btScalar D[36]; //"D" matrix; it's dofxdof for each body so asingle 6x6 D matrix will do
  683. btScalar invD_times_Y[6]; //D^{-1} * Y [dofxdof x dofx1 = dofx1] <=> D^{-1} * u; better moved to buffers since it is recalced in calcAccelerationDeltasMultiDof; num_dof of btScalar would cover all bodies
  684. btSpatialMotionVector result; //holds results of the SolveImatrix op; it is a spatial motion vector (accel)
  685. btScalar Y_minus_hT_a[6]; //Y - h^{T} * a; it's dofx1 for each body so a single 6x1 temp is enough
  686. btSpatialForceVector spatForceVecTemps[6]; //6 temporary spatial force vectors
  687. btSpatialTransformationMatrix fromParent; //spatial transform from parent to child
  688. btSymmetricSpatialDyad dyadTemp; //inertia matrix temp
  689. btSpatialTransformationMatrix fromWorld;
  690. fromWorld.m_trnVec.setZero();
  691. /////////////////
  692. // ptr to the joint accel part of the output
  693. btScalar *joint_accel = output + 6;
  694. // Start of the algorithm proper.
  695. // First 'upward' loop.
  696. // Combines CompTreeLinkVelocities and InitTreeLinks from Mirtich.
  697. rot_from_parent[0] = btMatrix3x3(m_baseQuat); //m_baseQuat assumed to be alias!?
  698. //create the vector of spatial velocity of the base by transforming global-coor linear and angular velocities into base-local coordinates
  699. spatVel[0].setVector(rot_from_parent[0] * base_omega, rot_from_parent[0] * base_vel);
  700. if (isBaseStaticOrKinematic())
  701. {
  702. zeroAccSpatFrc[0].setZero();
  703. }
  704. else
  705. {
  706. const btVector3 &baseForce = isConstraintPass ? m_baseConstraintForce : m_baseForce;
  707. const btVector3 &baseTorque = isConstraintPass ? m_baseConstraintTorque : m_baseTorque;
  708. //external forces
  709. zeroAccSpatFrc[0].setVector(-(rot_from_parent[0] * baseTorque), -(rot_from_parent[0] * baseForce));
  710. //adding damping terms (only)
  711. const btScalar linDampMult = 1., angDampMult = 1.;
  712. zeroAccSpatFrc[0].addVector(angDampMult * m_baseInertia * spatVel[0].getAngular() * (DAMPING_K1_ANGULAR + DAMPING_K2_ANGULAR * spatVel[0].getAngular().safeNorm()),
  713. linDampMult * m_baseMass * spatVel[0].getLinear() * (DAMPING_K1_LINEAR + DAMPING_K2_LINEAR * spatVel[0].getLinear().safeNorm()));
  714. //
  715. //p += vhat x Ihat vhat - done in a simpler way
  716. if (m_useGyroTerm)
  717. zeroAccSpatFrc[0].addAngular(spatVel[0].getAngular().cross(m_baseInertia * spatVel[0].getAngular()));
  718. //
  719. zeroAccSpatFrc[0].addLinear(m_baseMass * spatVel[0].getAngular().cross(spatVel[0].getLinear()));
  720. }
  721. //init the spatial AB inertia (it has the simple form thanks to choosing local body frames origins at their COMs)
  722. spatInertia[0].setMatrix(btMatrix3x3(0, 0, 0, 0, 0, 0, 0, 0, 0),
  723. //
  724. btMatrix3x3(m_baseMass, 0, 0,
  725. 0, m_baseMass, 0,
  726. 0, 0, m_baseMass),
  727. //
  728. btMatrix3x3(m_baseInertia[0], 0, 0,
  729. 0, m_baseInertia[1], 0,
  730. 0, 0, m_baseInertia[2]));
  731. rot_from_world[0] = rot_from_parent[0];
  732. //
  733. for (int i = 0; i < num_links; ++i)
  734. {
  735. const int parent = m_links[i].m_parent;
  736. rot_from_parent[i + 1] = btMatrix3x3(m_links[i].m_cachedRotParentToThis);
  737. rot_from_world[i + 1] = rot_from_parent[i + 1] * rot_from_world[parent + 1];
  738. fromParent.m_rotMat = rot_from_parent[i + 1];
  739. fromParent.m_trnVec = m_links[i].m_cachedRVector;
  740. fromWorld.m_rotMat = rot_from_world[i + 1];
  741. fromParent.transform(spatVel[parent + 1], spatVel[i + 1]);
  742. // now set vhat_i to its true value by doing
  743. // vhat_i += qidot * shat_i
  744. if (!m_useGlobalVelocities)
  745. {
  746. spatJointVel.setZero();
  747. for (int dof = 0; dof < m_links[i].m_dofCount; ++dof)
  748. spatJointVel += m_links[i].m_axes[dof] * getJointVelMultiDof(i)[dof];
  749. // remember vhat_i is really vhat_p(i) (but in current frame) at this point => we need to add velocity across the inboard joint
  750. spatVel[i + 1] += spatJointVel;
  751. //
  752. // vhat_i is vhat_p(i) transformed to local coors + the velocity across the i-th inboard joint
  753. //spatVel[i+1] = fromParent * spatVel[parent+1] + spatJointVel;
  754. }
  755. else
  756. {
  757. fromWorld.transformRotationOnly(m_links[i].m_absFrameTotVelocity, spatVel[i + 1]);
  758. fromWorld.transformRotationOnly(m_links[i].m_absFrameLocVelocity, spatJointVel);
  759. }
  760. // we can now calculate chat_i
  761. spatVel[i + 1].cross(spatJointVel, spatCoriolisAcc[i]);
  762. // calculate zhat_i^A
  763. //
  764. if (isLinkAndAllAncestorsKinematic(i))
  765. {
  766. zeroAccSpatFrc[i].setZero();
  767. }
  768. else{
  769. //external forces
  770. btVector3 linkAppliedForce = isConstraintPass ? m_links[i].m_appliedConstraintForce : m_links[i].m_appliedForce;
  771. btVector3 linkAppliedTorque = isConstraintPass ? m_links[i].m_appliedConstraintTorque : m_links[i].m_appliedTorque;
  772. zeroAccSpatFrc[i + 1].setVector(-(rot_from_world[i + 1] * linkAppliedTorque), -(rot_from_world[i + 1] * linkAppliedForce));
  773. #if 0
  774. {
  775. b3Printf("stepVelocitiesMultiDof zeroAccSpatFrc[%d] linear:%f,%f,%f, angular:%f,%f,%f",
  776. i+1,
  777. zeroAccSpatFrc[i+1].m_topVec[0],
  778. zeroAccSpatFrc[i+1].m_topVec[1],
  779. zeroAccSpatFrc[i+1].m_topVec[2],
  780. zeroAccSpatFrc[i+1].m_bottomVec[0],
  781. zeroAccSpatFrc[i+1].m_bottomVec[1],
  782. zeroAccSpatFrc[i+1].m_bottomVec[2]);
  783. }
  784. #endif
  785. //
  786. //adding damping terms (only)
  787. btScalar linDampMult = 1., angDampMult = 1.;
  788. zeroAccSpatFrc[i + 1].addVector(angDampMult * m_links[i].m_inertiaLocal * spatVel[i + 1].getAngular() * (DAMPING_K1_ANGULAR + DAMPING_K2_ANGULAR * spatVel[i + 1].getAngular().safeNorm()),
  789. linDampMult * m_links[i].m_mass * spatVel[i + 1].getLinear() * (DAMPING_K1_LINEAR + DAMPING_K2_LINEAR * spatVel[i + 1].getLinear().safeNorm()));
  790. //p += vhat x Ihat vhat - done in a simpler way
  791. if (m_useGyroTerm)
  792. zeroAccSpatFrc[i + 1].addAngular(spatVel[i + 1].getAngular().cross(m_links[i].m_inertiaLocal * spatVel[i + 1].getAngular()));
  793. //
  794. zeroAccSpatFrc[i + 1].addLinear(m_links[i].m_mass * spatVel[i + 1].getAngular().cross(spatVel[i + 1].getLinear()));
  795. //
  796. //btVector3 temp = m_links[i].m_mass * spatVel[i+1].getAngular().cross(spatVel[i+1].getLinear());
  797. ////clamp parent's omega
  798. //btScalar parOmegaMod = temp.length();
  799. //btScalar parOmegaModMax = 1000;
  800. //if(parOmegaMod > parOmegaModMax)
  801. // temp *= parOmegaModMax / parOmegaMod;
  802. //zeroAccSpatFrc[i+1].addLinear(temp);
  803. //printf("|zeroAccSpatFrc[%d]| = %.4f\n", i+1, temp.length());
  804. //temp = spatCoriolisAcc[i].getLinear();
  805. //printf("|spatCoriolisAcc[%d]| = %.4f\n", i+1, temp.length());
  806. }
  807. // calculate Ihat_i^A
  808. //init the spatial AB inertia (it has the simple form thanks to choosing local body frames origins at their COMs)
  809. spatInertia[i + 1].setMatrix(btMatrix3x3(0, 0, 0, 0, 0, 0, 0, 0, 0),
  810. //
  811. btMatrix3x3(m_links[i].m_mass, 0, 0,
  812. 0, m_links[i].m_mass, 0,
  813. 0, 0, m_links[i].m_mass),
  814. //
  815. btMatrix3x3(m_links[i].m_inertiaLocal[0], 0, 0,
  816. 0, m_links[i].m_inertiaLocal[1], 0,
  817. 0, 0, m_links[i].m_inertiaLocal[2]));
  818. //printf("w[%d] = [%.4f %.4f %.4f]\n", i, vel_top_angular[i+1].x(), vel_top_angular[i+1].y(), vel_top_angular[i+1].z());
  819. //printf("v[%d] = [%.4f %.4f %.4f]\n", i, vel_bottom_linear[i+1].x(), vel_bottom_linear[i+1].y(), vel_bottom_linear[i+1].z());
  820. //printf("c[%d] = [%.4f %.4f %.4f]\n", i, coriolis_bottom_linear[i].x(), coriolis_bottom_linear[i].y(), coriolis_bottom_linear[i].z());
  821. }
  822. // 'Downward' loop.
  823. // (part of TreeForwardDynamics in Mirtich.)
  824. for (int i = num_links - 1; i >= 0; --i)
  825. {
  826. if(isLinkAndAllAncestorsKinematic(i))
  827. continue;
  828. const int parent = m_links[i].m_parent;
  829. fromParent.m_rotMat = rot_from_parent[i + 1];
  830. fromParent.m_trnVec = m_links[i].m_cachedRVector;
  831. for (int dof = 0; dof < m_links[i].m_dofCount; ++dof)
  832. {
  833. btSpatialForceVector &hDof = h[m_links[i].m_dofOffset + dof];
  834. //
  835. hDof = spatInertia[i + 1] * m_links[i].m_axes[dof];
  836. //
  837. Y[m_links[i].m_dofOffset + dof] = m_links[i].m_jointTorque[dof] - m_links[i].m_axes[dof].dot(zeroAccSpatFrc[i + 1]) - spatCoriolisAcc[i].dot(hDof);
  838. }
  839. for (int dof = 0; dof < m_links[i].m_dofCount; ++dof)
  840. {
  841. btScalar *D_row = &D[dof * m_links[i].m_dofCount];
  842. for (int dof2 = 0; dof2 < m_links[i].m_dofCount; ++dof2)
  843. {
  844. const btSpatialForceVector &hDof2 = h[m_links[i].m_dofOffset + dof2];
  845. D_row[dof2] = m_links[i].m_axes[dof].dot(hDof2);
  846. }
  847. }
  848. btScalar *invDi = &invD[m_links[i].m_dofOffset * m_links[i].m_dofOffset];
  849. switch (m_links[i].m_jointType)
  850. {
  851. case btMultibodyLink::ePrismatic:
  852. case btMultibodyLink::eRevolute:
  853. {
  854. if (D[0] >= SIMD_EPSILON)
  855. {
  856. invDi[0] = 1.0f / D[0];
  857. }
  858. else
  859. {
  860. invDi[0] = 0;
  861. }
  862. break;
  863. }
  864. case btMultibodyLink::eSpherical:
  865. case btMultibodyLink::ePlanar:
  866. {
  867. const btMatrix3x3 D3x3(D[0], D[1], D[2], D[3], D[4], D[5], D[6], D[7], D[8]);
  868. const btMatrix3x3 invD3x3(D3x3.inverse());
  869. //unroll the loop?
  870. for (int row = 0; row < 3; ++row)
  871. {
  872. for (int col = 0; col < 3; ++col)
  873. {
  874. invDi[row * 3 + col] = invD3x3[row][col];
  875. }
  876. }
  877. break;
  878. }
  879. default:
  880. {
  881. }
  882. }
  883. //determine h*D^{-1}
  884. for (int dof = 0; dof < m_links[i].m_dofCount; ++dof)
  885. {
  886. spatForceVecTemps[dof].setZero();
  887. for (int dof2 = 0; dof2 < m_links[i].m_dofCount; ++dof2)
  888. {
  889. const btSpatialForceVector &hDof2 = h[m_links[i].m_dofOffset + dof2];
  890. //
  891. spatForceVecTemps[dof] += hDof2 * invDi[dof2 * m_links[i].m_dofCount + dof];
  892. }
  893. }
  894. dyadTemp = spatInertia[i + 1];
  895. //determine (h*D^{-1}) * h^{T}
  896. for (int dof = 0; dof < m_links[i].m_dofCount; ++dof)
  897. {
  898. const btSpatialForceVector &hDof = h[m_links[i].m_dofOffset + dof];
  899. //
  900. dyadTemp -= symmetricSpatialOuterProduct(hDof, spatForceVecTemps[dof]);
  901. }
  902. fromParent.transformInverse(dyadTemp, spatInertia[parent + 1], btSpatialTransformationMatrix::Add);
  903. for (int dof = 0; dof < m_links[i].m_dofCount; ++dof)
  904. {
  905. invD_times_Y[dof] = 0.f;
  906. for (int dof2 = 0; dof2 < m_links[i].m_dofCount; ++dof2)
  907. {
  908. invD_times_Y[dof] += invDi[dof * m_links[i].m_dofCount + dof2] * Y[m_links[i].m_dofOffset + dof2];
  909. }
  910. }
  911. spatForceVecTemps[0] = zeroAccSpatFrc[i + 1] + spatInertia[i + 1] * spatCoriolisAcc[i];
  912. for (int dof = 0; dof < m_links[i].m_dofCount; ++dof)
  913. {
  914. const btSpatialForceVector &hDof = h[m_links[i].m_dofOffset + dof];
  915. //
  916. spatForceVecTemps[0] += hDof * invD_times_Y[dof];
  917. }
  918. fromParent.transformInverse(spatForceVecTemps[0], spatForceVecTemps[1]);
  919. zeroAccSpatFrc[parent + 1] += spatForceVecTemps[1];
  920. }
  921. // Second 'upward' loop
  922. // (part of TreeForwardDynamics in Mirtich)
  923. if (isBaseStaticOrKinematic())
  924. {
  925. spatAcc[0].setZero();
  926. }
  927. else
  928. {
  929. if (num_links > 0)
  930. {
  931. m_cachedInertiaValid = true;
  932. m_cachedInertiaTopLeft = spatInertia[0].m_topLeftMat;
  933. m_cachedInertiaTopRight = spatInertia[0].m_topRightMat;
  934. m_cachedInertiaLowerLeft = spatInertia[0].m_bottomLeftMat;
  935. m_cachedInertiaLowerRight = spatInertia[0].m_topLeftMat.transpose();
  936. }
  937. solveImatrix(zeroAccSpatFrc[0], result);
  938. spatAcc[0] = -result;
  939. }
  940. // now do the loop over the m_links
  941. for (int i = 0; i < num_links; ++i)
  942. {
  943. // qdd = D^{-1} * (Y - h^{T}*apar) = (S^{T}*I*S)^{-1} * (tau - S^{T}*I*cor - S^{T}*zeroAccFrc - S^{T}*I*apar)
  944. // a = apar + cor + Sqdd
  945. //or
  946. // qdd = D^{-1} * (Y - h^{T}*(apar+cor))
  947. // a = apar + Sqdd
  948. const int parent = m_links[i].m_parent;
  949. fromParent.m_rotMat = rot_from_parent[i + 1];
  950. fromParent.m_trnVec = m_links[i].m_cachedRVector;
  951. fromParent.transform(spatAcc[parent + 1], spatAcc[i + 1]);
  952. if(!isLinkAndAllAncestorsKinematic(i))
  953. {
  954. for (int dof = 0; dof < m_links[i].m_dofCount; ++dof)
  955. {
  956. const btSpatialForceVector &hDof = h[m_links[i].m_dofOffset + dof];
  957. //
  958. Y_minus_hT_a[dof] = Y[m_links[i].m_dofOffset + dof] - spatAcc[i + 1].dot(hDof);
  959. }
  960. btScalar *invDi = &invD[m_links[i].m_dofOffset * m_links[i].m_dofOffset];
  961. //D^{-1} * (Y - h^{T}*apar)
  962. mulMatrix(invDi, Y_minus_hT_a, m_links[i].m_dofCount, m_links[i].m_dofCount, m_links[i].m_dofCount, 1, &joint_accel[m_links[i].m_dofOffset]);
  963. spatAcc[i + 1] += spatCoriolisAcc[i];
  964. for (int dof = 0; dof < m_links[i].m_dofCount; ++dof)
  965. spatAcc[i + 1] += m_links[i].m_axes[dof] * joint_accel[m_links[i].m_dofOffset + dof];
  966. }
  967. if (m_links[i].m_jointFeedback)
  968. {
  969. m_internalNeedsJointFeedback = true;
  970. btVector3 angularBotVec = (spatInertia[i + 1] * spatAcc[i + 1] + zeroAccSpatFrc[i + 1]).m_bottomVec;
  971. btVector3 linearTopVec = (spatInertia[i + 1] * spatAcc[i + 1] + zeroAccSpatFrc[i + 1]).m_topVec;
  972. if (jointFeedbackInJointFrame)
  973. {
  974. //shift the reaction forces to the joint frame
  975. //linear (force) component is the same
  976. //shift the angular (torque, moment) component using the relative position, m_links[i].m_dVector
  977. angularBotVec = angularBotVec - linearTopVec.cross(m_links[i].m_dVector);
  978. }
  979. if (jointFeedbackInWorldSpace)
  980. {
  981. if (isConstraintPass)
  982. {
  983. m_links[i].m_jointFeedback->m_reactionForces.m_bottomVec += m_links[i].m_cachedWorldTransform.getBasis() * angularBotVec;
  984. m_links[i].m_jointFeedback->m_reactionForces.m_topVec += m_links[i].m_cachedWorldTransform.getBasis() * linearTopVec;
  985. }
  986. else
  987. {
  988. m_links[i].m_jointFeedback->m_reactionForces.m_bottomVec = m_links[i].m_cachedWorldTransform.getBasis() * angularBotVec;
  989. m_links[i].m_jointFeedback->m_reactionForces.m_topVec = m_links[i].m_cachedWorldTransform.getBasis() * linearTopVec;
  990. }
  991. }
  992. else
  993. {
  994. if (isConstraintPass)
  995. {
  996. m_links[i].m_jointFeedback->m_reactionForces.m_bottomVec += angularBotVec;
  997. m_links[i].m_jointFeedback->m_reactionForces.m_topVec += linearTopVec;
  998. }
  999. else
  1000. {
  1001. m_links[i].m_jointFeedback->m_reactionForces.m_bottomVec = angularBotVec;
  1002. m_links[i].m_jointFeedback->m_reactionForces.m_topVec = linearTopVec;
  1003. }
  1004. }
  1005. }
  1006. }
  1007. // transform base accelerations back to the world frame.
  1008. const btVector3 omegadot_out = rot_from_parent[0].transpose() * spatAcc[0].getAngular();
  1009. output[0] = omegadot_out[0];
  1010. output[1] = omegadot_out[1];
  1011. output[2] = omegadot_out[2];
  1012. const btVector3 vdot_out = rot_from_parent[0].transpose() * (spatAcc[0].getLinear() + spatVel[0].getAngular().cross(spatVel[0].getLinear()));
  1013. output[3] = vdot_out[0];
  1014. output[4] = vdot_out[1];
  1015. output[5] = vdot_out[2];
  1016. /////////////////
  1017. //printf("q = [");
  1018. //printf("%.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f ", m_baseQuat.x(), m_baseQuat.y(), m_baseQuat.z(), m_baseQuat.w(), m_basePos.x(), m_basePos.y(), m_basePos.z());
  1019. //for(int link = 0; link < getNumLinks(); ++link)
  1020. // for(int dof = 0; dof < m_links[link].m_dofCount; ++dof)
  1021. // printf("%.6f ", m_links[link].m_jointPos[dof]);
  1022. //printf("]\n");
  1023. ////
  1024. //printf("qd = [");
  1025. //for(int dof = 0; dof < getNumDofs() + 6; ++dof)
  1026. // printf("%.6f ", m_realBuf[dof]);
  1027. //printf("]\n");
  1028. //printf("qdd = [");
  1029. //for(int dof = 0; dof < getNumDofs() + 6; ++dof)
  1030. // printf("%.6f ", output[dof]);
  1031. //printf("]\n");
  1032. /////////////////
  1033. // Final step: add the accelerations (times dt) to the velocities.
  1034. if (!isConstraintPass)
  1035. {
  1036. if (dt > 0.)
  1037. applyDeltaVeeMultiDof(output, dt);
  1038. }
  1039. /////
  1040. //btScalar angularThres = 1;
  1041. //btScalar maxAngVel = 0.;
  1042. //bool scaleDown = 1.;
  1043. //for(int link = 0; link < m_links.size(); ++link)
  1044. //{
  1045. // if(spatVel[link+1].getAngular().length() > maxAngVel)
  1046. // {
  1047. // maxAngVel = spatVel[link+1].getAngular().length();
  1048. // scaleDown = angularThres / spatVel[link+1].getAngular().length();
  1049. // break;
  1050. // }
  1051. //}
  1052. //if(scaleDown != 1.)
  1053. //{
  1054. // for(int link = 0; link < m_links.size(); ++link)
  1055. // {
  1056. // if(m_links[link].m_jointType == btMultibodyLink::eRevolute || m_links[link].m_jointType == btMultibodyLink::eSpherical)
  1057. // {
  1058. // for(int dof = 0; dof < m_links[link].m_dofCount; ++dof)
  1059. // getJointVelMultiDof(link)[dof] *= scaleDown;
  1060. // }
  1061. // }
  1062. //}
  1063. /////
  1064. /////////////////////
  1065. if (m_useGlobalVelocities)
  1066. {
  1067. for (int i = 0; i < num_links; ++i)
  1068. {
  1069. const int parent = m_links[i].m_parent;
  1070. //rot_from_parent[i+1] = btMatrix3x3(m_links[i].m_cachedRotParentToThis); /// <- done
  1071. //rot_from_world[i+1] = rot_from_parent[i+1] * rot_from_world[parent+1]; /// <- done
  1072. fromParent.m_rotMat = rot_from_parent[i + 1];
  1073. fromParent.m_trnVec = m_links[i].m_cachedRVector;
  1074. fromWorld.m_rotMat = rot_from_world[i + 1];
  1075. // vhat_i = i_xhat_p(i) * vhat_p(i)
  1076. fromParent.transform(spatVel[parent + 1], spatVel[i + 1]);
  1077. //nice alternative below (using operator *) but it generates temps
  1078. /////////////////////////////////////////////////////////////
  1079. // now set vhat_i to its true value by doing
  1080. // vhat_i += qidot * shat_i
  1081. spatJointVel.setZero();
  1082. for (int dof = 0; dof < m_links[i].m_dofCount; ++dof)
  1083. spatJointVel += m_links[i].m_axes[dof] * getJointVelMultiDof(i)[dof];
  1084. // remember vhat_i is really vhat_p(i) (but in current frame) at this point => we need to add velocity across the inboard joint
  1085. spatVel[i + 1] += spatJointVel;
  1086. fromWorld.transformInverseRotationOnly(spatVel[i + 1], m_links[i].m_absFrameTotVelocity);
  1087. fromWorld.transformInverseRotationOnly(spatJointVel, m_links[i].m_absFrameLocVelocity);
  1088. }
  1089. }
  1090. }
  1091. void btMultiBody::solveImatrix(const btVector3 &rhs_top, const btVector3 &rhs_bot, btScalar result[6]) const
  1092. {
  1093. int num_links = getNumLinks();
  1094. ///solve I * x = rhs, so the result = invI * rhs
  1095. if (num_links == 0)
  1096. {
  1097. // in the case of 0 m_links (i.e. a plain rigid body, not a multibody) rhs * invI is easier
  1098. if ((m_baseInertia[0] >= SIMD_EPSILON) && (m_baseInertia[1] >= SIMD_EPSILON) && (m_baseInertia[2] >= SIMD_EPSILON))
  1099. {
  1100. result[0] = rhs_bot[0] / m_baseInertia[0];
  1101. result[1] = rhs_bot[1] / m_baseInertia[1];
  1102. result[2] = rhs_bot[2] / m_baseInertia[2];
  1103. }
  1104. else
  1105. {
  1106. result[0] = 0;
  1107. result[1] = 0;
  1108. result[2] = 0;
  1109. }
  1110. if (m_baseMass >= SIMD_EPSILON)
  1111. {
  1112. result[3] = rhs_top[0] / m_baseMass;
  1113. result[4] = rhs_top[1] / m_baseMass;
  1114. result[5] = rhs_top[2] / m_baseMass;
  1115. }
  1116. else
  1117. {
  1118. result[3] = 0;
  1119. result[4] = 0;
  1120. result[5] = 0;
  1121. }
  1122. }
  1123. else
  1124. {
  1125. if (!m_cachedInertiaValid)
  1126. {
  1127. for (int i = 0; i < 6; i++)
  1128. {
  1129. result[i] = 0.f;
  1130. }
  1131. return;
  1132. }
  1133. /// Special routine for calculating the inverse of a spatial inertia matrix
  1134. ///the 6x6 matrix is stored as 4 blocks of 3x3 matrices
  1135. btMatrix3x3 Binv = m_cachedInertiaTopRight.inverse() * -1.f;
  1136. btMatrix3x3 tmp = m_cachedInertiaLowerRight * Binv;
  1137. btMatrix3x3 invIupper_right = (tmp * m_cachedInertiaTopLeft + m_cachedInertiaLowerLeft).inverse();
  1138. tmp = invIupper_right * m_cachedInertiaLowerRight;
  1139. btMatrix3x3 invI_upper_left = (tmp * Binv);
  1140. btMatrix3x3 invI_lower_right = (invI_upper_left).transpose();
  1141. tmp = m_cachedInertiaTopLeft * invI_upper_left;
  1142. tmp[0][0] -= 1.0;
  1143. tmp[1][1] -= 1.0;
  1144. tmp[2][2] -= 1.0;
  1145. btMatrix3x3 invI_lower_left = (Binv * tmp);
  1146. //multiply result = invI * rhs
  1147. {
  1148. btVector3 vtop = invI_upper_left * rhs_top;
  1149. btVector3 tmp;
  1150. tmp = invIupper_right * rhs_bot;
  1151. vtop += tmp;
  1152. btVector3 vbot = invI_lower_left * rhs_top;
  1153. tmp = invI_lower_right * rhs_bot;
  1154. vbot += tmp;
  1155. result[0] = vtop[0];
  1156. result[1] = vtop[1];
  1157. result[2] = vtop[2];
  1158. result[3] = vbot[0];
  1159. result[4] = vbot[1];
  1160. result[5] = vbot[2];
  1161. }
  1162. }
  1163. }
  1164. void btMultiBody::solveImatrix(const btSpatialForceVector &rhs, btSpatialMotionVector &result) const
  1165. {
  1166. int num_links = getNumLinks();
  1167. ///solve I * x = rhs, so the result = invI * rhs
  1168. if (num_links == 0)
  1169. {
  1170. // in the case of 0 m_links (i.e. a plain rigid body, not a multibody) rhs * invI is easier
  1171. if ((m_baseInertia[0] >= SIMD_EPSILON) && (m_baseInertia[1] >= SIMD_EPSILON) && (m_baseInertia[2] >= SIMD_EPSILON))
  1172. {
  1173. result.setAngular(rhs.getAngular() / m_baseInertia);
  1174. }
  1175. else
  1176. {
  1177. result.setAngular(btVector3(0, 0, 0));
  1178. }
  1179. if (m_baseMass >= SIMD_EPSILON)
  1180. {
  1181. result.setLinear(rhs.getLinear() / m_baseMass);
  1182. }
  1183. else
  1184. {
  1185. result.setLinear(btVector3(0, 0, 0));
  1186. }
  1187. }
  1188. else
  1189. {
  1190. /// Special routine for calculating the inverse of a spatial inertia matrix
  1191. ///the 6x6 matrix is stored as 4 blocks of 3x3 matrices
  1192. if (!m_cachedInertiaValid)
  1193. {
  1194. result.setLinear(btVector3(0, 0, 0));
  1195. result.setAngular(btVector3(0, 0, 0));
  1196. result.setVector(btVector3(0, 0, 0), btVector3(0, 0, 0));
  1197. return;
  1198. }
  1199. btMatrix3x3 Binv = m_cachedInertiaTopRight.inverse() * -1.f;
  1200. btMatrix3x3 tmp = m_cachedInertiaLowerRight * Binv;
  1201. btMatrix3x3 invIupper_right = (tmp * m_cachedInertiaTopLeft + m_cachedInertiaLowerLeft).inverse();
  1202. tmp = invIupper_right * m_cachedInertiaLowerRight;
  1203. btMatrix3x3 invI_upper_left = (tmp * Binv);
  1204. btMatrix3x3 invI_lower_right = (invI_upper_left).transpose();
  1205. tmp = m_cachedInertiaTopLeft * invI_upper_left;
  1206. tmp[0][0] -= 1.0;
  1207. tmp[1][1] -= 1.0;
  1208. tmp[2][2] -= 1.0;
  1209. btMatrix3x3 invI_lower_left = (Binv * tmp);
  1210. //multiply result = invI * rhs
  1211. {
  1212. btVector3 vtop = invI_upper_left * rhs.getLinear();
  1213. btVector3 tmp;
  1214. tmp = invIupper_right * rhs.getAngular();
  1215. vtop += tmp;
  1216. btVector3 vbot = invI_lower_left * rhs.getLinear();
  1217. tmp = invI_lower_right * rhs.getAngular();
  1218. vbot += tmp;
  1219. result.setVector(vtop, vbot);
  1220. }
  1221. }
  1222. }
  1223. void btMultiBody::mulMatrix(const btScalar *pA, const btScalar *pB, int rowsA, int colsA, int rowsB, int colsB, btScalar *pC) const
  1224. {
  1225. for (int row = 0; row < rowsA; row++)
  1226. {
  1227. for (int col = 0; col < colsB; col++)
  1228. {
  1229. pC[row * colsB + col] = 0.f;
  1230. for (int inner = 0; inner < rowsB; inner++)
  1231. {
  1232. pC[row * colsB + col] += pA[row * colsA + inner] * pB[col + inner * colsB];
  1233. }
  1234. }
  1235. }
  1236. }
  1237. void btMultiBody::calcAccelerationDeltasMultiDof(const btScalar *force, btScalar *output,
  1238. btAlignedObjectArray<btScalar> &scratch_r, btAlignedObjectArray<btVector3> &scratch_v) const
  1239. {
  1240. // Temporary matrices/vectors -- use scratch space from caller
  1241. // so that we don't have to keep reallocating every frame
  1242. int num_links = getNumLinks();
  1243. scratch_r.resize(m_dofCount);
  1244. scratch_v.resize(4 * num_links + 4);
  1245. btScalar *r_ptr = m_dofCount ? &scratch_r[0] : 0;
  1246. btVector3 *v_ptr = &scratch_v[0];
  1247. // zhat_i^A (scratch space)
  1248. btSpatialForceVector *zeroAccSpatFrc = (btSpatialForceVector *)v_ptr;
  1249. v_ptr += num_links * 2 + 2;
  1250. // rot_from_parent (cached from calcAccelerations)
  1251. const btMatrix3x3 *rot_from_parent = &m_matrixBuf[0];
  1252. // hhat (cached), accel (scratch)
  1253. // hhat is NOT stored for the base (but ahat is)
  1254. const btSpatialForceVector *h = (btSpatialForceVector *)(m_dofCount > 0 ? &m_vectorBuf[0] : 0);
  1255. btSpatialMotionVector *spatAcc = (btSpatialMotionVector *)v_ptr;
  1256. v_ptr += num_links * 2 + 2;
  1257. // Y_i (scratch), invD_i (cached)
  1258. const btScalar *invD = m_dofCount > 0 ? &m_realBuf[6 + m_dofCount] : 0;
  1259. btScalar *Y = r_ptr;
  1260. ////////////////
  1261. //aux variables
  1262. btScalar invD_times_Y[6]; //D^{-1} * Y [dofxdof x dofx1 = dofx1] <=> D^{-1} * u; better moved to buffers since it is recalced in calcAccelerationDeltasMultiDof; num_dof of btScalar would cover all bodies
  1263. btSpatialMotionVector result; //holds results of the SolveImatrix op; it is a spatial motion vector (accel)
  1264. btScalar Y_minus_hT_a[6]; //Y - h^{T} * a; it's dofx1 for each body so a single 6x1 temp is enough
  1265. btSpatialForceVector spatForceVecTemps[6]; //6 temporary spatial force vectors
  1266. btSpatialTransformationMatrix fromParent;
  1267. /////////////////
  1268. // First 'upward' loop.
  1269. // Combines CompTreeLinkVelocities and InitTreeLinks from Mirtich.
  1270. // Fill in zero_acc
  1271. // -- set to force/torque on the base, zero otherwise
  1272. if (isBaseStaticOrKinematic())
  1273. {
  1274. zeroAccSpatFrc[0].setZero();
  1275. }
  1276. else
  1277. {
  1278. //test forces
  1279. fromParent.m_rotMat = rot_from_parent[0];
  1280. fromParent.transformRotationOnly(btSpatialForceVector(-force[0], -force[1], -force[2], -force[3], -force[4], -force[5]), zeroAccSpatFrc[0]);
  1281. }
  1282. for (int i = 0; i < num_links; ++i)
  1283. {
  1284. zeroAccSpatFrc[i + 1].setZero();
  1285. }
  1286. // 'Downward' loop.
  1287. // (part of TreeForwardDynamics in Mirtich.)
  1288. for (int i = num_links - 1; i >= 0; --i)
  1289. {
  1290. if(isLinkAndAllAncestorsKinematic(i))
  1291. continue;
  1292. const int parent = m_links[i].m_parent;
  1293. fromParent.m_rotMat = rot_from_parent[i + 1];
  1294. fromParent.m_trnVec = m_links[i].m_cachedRVector;
  1295. for (int dof = 0; dof < m_links[i].m_dofCount; ++dof)
  1296. {
  1297. Y[m_links[i].m_dofOffset + dof] = force[6 + m_links[i].m_dofOffset + dof] - m_links[i].m_axes[dof].dot(zeroAccSpatFrc[i + 1]);
  1298. }
  1299. btVector3 in_top, in_bottom, out_top, out_bottom;
  1300. const btScalar *invDi = &invD[m_links[i].m_dofOffset * m_links[i].m_dofOffset];
  1301. for (int dof = 0; dof < m_links[i].m_dofCount; ++dof)
  1302. {
  1303. invD_times_Y[dof] = 0.f;
  1304. for (int dof2 = 0; dof2 < m_links[i].m_dofCount; ++dof2)
  1305. {
  1306. invD_times_Y[dof] += invDi[dof * m_links[i].m_dofCount + dof2] * Y[m_links[i].m_dofOffset + dof2];
  1307. }
  1308. }
  1309. // Zp += pXi * (Zi + hi*Yi/Di)
  1310. spatForceVecTemps[0] = zeroAccSpatFrc[i + 1];
  1311. for (int dof = 0; dof < m_links[i].m_dofCount; ++dof)
  1312. {
  1313. const btSpatialForceVector &hDof = h[m_links[i].m_dofOffset + dof];
  1314. //
  1315. spatForceVecTemps[0] += hDof * invD_times_Y[dof];
  1316. }
  1317. fromParent.transformInverse(spatForceVecTemps[0], spatForceVecTemps[1]);
  1318. zeroAccSpatFrc[parent + 1] += spatForceVecTemps[1];
  1319. }
  1320. // ptr to the joint accel part of the output
  1321. btScalar *joint_accel = output + 6;
  1322. // Second 'upward' loop
  1323. // (part of TreeForwardDynamics in Mirtich)
  1324. if (isBaseStaticOrKinematic())
  1325. {
  1326. spatAcc[0].setZero();
  1327. }
  1328. else
  1329. {
  1330. solveImatrix(zeroAccSpatFrc[0], result);
  1331. spatAcc[0] = -result;
  1332. }
  1333. // now do the loop over the m_links
  1334. for (int i = 0; i < num_links; ++i)
  1335. {
  1336. if(isLinkAndAllAncestorsKinematic(i))
  1337. continue;
  1338. const int parent = m_links[i].m_parent;
  1339. fromParent.m_rotMat = rot_from_parent[i + 1];
  1340. fromParent.m_trnVec = m_links[i].m_cachedRVector;
  1341. fromParent.transform(spatAcc[parent + 1], spatAcc[i + 1]);
  1342. for (int dof = 0; dof < m_links[i].m_dofCount; ++dof)
  1343. {
  1344. const btSpatialForceVector &hDof = h[m_links[i].m_dofOffset + dof];
  1345. //
  1346. Y_minus_hT_a[dof] = Y[m_links[i].m_dofOffset + dof] - spatAcc[i + 1].dot(hDof);
  1347. }
  1348. const btScalar *invDi = &invD[m_links[i].m_dofOffset * m_links[i].m_dofOffset];
  1349. mulMatrix(const_cast<btScalar *>(invDi), Y_minus_hT_a, m_links[i].m_dofCount, m_links[i].m_dofCount, m_links[i].m_dofCount, 1, &joint_accel[m_links[i].m_dofOffset]);
  1350. for (int dof = 0; dof < m_links[i].m_dofCount; ++dof)
  1351. spatAcc[i + 1] += m_links[i].m_axes[dof] * joint_accel[m_links[i].m_dofOffset + dof];
  1352. }
  1353. // transform base accelerations back to the world frame.
  1354. btVector3 omegadot_out;
  1355. omegadot_out = rot_from_parent[0].transpose() * spatAcc[0].getAngular();
  1356. output[0] = omegadot_out[0];
  1357. output[1] = omegadot_out[1];
  1358. output[2] = omegadot_out[2];
  1359. btVector3 vdot_out;
  1360. vdot_out = rot_from_parent[0].transpose() * spatAcc[0].getLinear();
  1361. output[3] = vdot_out[0];
  1362. output[4] = vdot_out[1];
  1363. output[5] = vdot_out[2];
  1364. /////////////////
  1365. //printf("delta = [");
  1366. //for(int dof = 0; dof < getNumDofs() + 6; ++dof)
  1367. // printf("%.2f ", output[dof]);
  1368. //printf("]\n");
  1369. /////////////////
  1370. }
  1371. void btMultiBody::predictPositionsMultiDof(btScalar dt)
  1372. {
  1373. int num_links = getNumLinks();
  1374. if(!isBaseKinematic())
  1375. {
  1376. // step position by adding dt * velocity
  1377. //btVector3 v = getBaseVel();
  1378. //m_basePos += dt * v;
  1379. //
  1380. btScalar *pBasePos;
  1381. btScalar *pBaseVel = &m_realBuf[3]; //note: the !pqd case assumes m_realBuf holds with base velocity at 3,4,5 (should be wrapped for safety)
  1382. // reset to current position
  1383. for (int i = 0; i < 3; ++i)
  1384. {
  1385. m_basePos_interpolate[i] = m_basePos[i];
  1386. }
  1387. pBasePos = m_basePos_interpolate;
  1388. pBasePos[0] += dt * pBaseVel[0];
  1389. pBasePos[1] += dt * pBaseVel[1];
  1390. pBasePos[2] += dt * pBaseVel[2];
  1391. }
  1392. ///////////////////////////////
  1393. //local functor for quaternion integration (to avoid error prone redundancy)
  1394. struct
  1395. {
  1396. //"exponential map" based on btTransformUtil::integrateTransform(..)
  1397. void operator()(const btVector3 &omega, btQuaternion &quat, bool baseBody, btScalar dt)
  1398. {
  1399. //baseBody => quat is alias and omega is global coor
  1400. //!baseBody => quat is alibi and omega is local coor
  1401. btVector3 axis;
  1402. btVector3 angvel;
  1403. if (!baseBody)
  1404. angvel = quatRotate(quat, omega); //if quat is not m_baseQuat, it is alibi => ok
  1405. else
  1406. angvel = omega;
  1407. btScalar fAngle = angvel.length();
  1408. //limit the angular motion
  1409. if (fAngle * dt > ANGULAR_MOTION_THRESHOLD)
  1410. {
  1411. fAngle = btScalar(0.5) * SIMD_HALF_PI / dt;
  1412. }
  1413. if (fAngle < btScalar(0.001))
  1414. {
  1415. // use Taylor's expansions of sync function
  1416. axis = angvel * (btScalar(0.5) * dt - (dt * dt * dt) * (btScalar(0.020833333333)) * fAngle * fAngle);
  1417. }
  1418. else
  1419. {
  1420. // sync(fAngle) = sin(c*fAngle)/t
  1421. axis = angvel * (btSin(btScalar(0.5) * fAngle * dt) / fAngle);
  1422. }
  1423. if (!baseBody)
  1424. quat = btQuaternion(axis.x(), axis.y(), axis.z(), btCos(fAngle * dt * btScalar(0.5))) * quat;
  1425. else
  1426. quat = quat * btQuaternion(-axis.x(), -axis.y(), -axis.z(), btCos(fAngle * dt * btScalar(0.5)));
  1427. //equivalent to: quat = (btQuaternion(axis.x(),axis.y(),axis.z(),btCos( fAngle*dt*btScalar(0.5) )) * quat.inverse()).inverse();
  1428. quat.normalize();
  1429. }
  1430. } pQuatUpdateFun;
  1431. ///////////////////////////////
  1432. //pQuatUpdateFun(getBaseOmega(), m_baseQuat, true, dt);
  1433. //
  1434. if(!isBaseKinematic())
  1435. {
  1436. btScalar *pBaseQuat;
  1437. // reset to current orientation
  1438. for (int i = 0; i < 4; ++i)
  1439. {
  1440. m_baseQuat_interpolate[i] = m_baseQuat[i];
  1441. }
  1442. pBaseQuat = m_baseQuat_interpolate;
  1443. btScalar *pBaseOmega = &m_realBuf[0]; //note: the !pqd case assumes m_realBuf starts with base omega (should be wrapped for safety)
  1444. //
  1445. btQuaternion baseQuat;
  1446. baseQuat.setValue(pBaseQuat[0], pBaseQuat[1], pBaseQuat[2], pBaseQuat[3]);
  1447. btVector3 baseOmega;
  1448. baseOmega.setValue(pBaseOmega[0], pBaseOmega[1], pBaseOmega[2]);
  1449. pQuatUpdateFun(baseOmega, baseQuat, true, dt);
  1450. pBaseQuat[0] = baseQuat.x();
  1451. pBaseQuat[1] = baseQuat.y();
  1452. pBaseQuat[2] = baseQuat.z();
  1453. pBaseQuat[3] = baseQuat.w();
  1454. }
  1455. // Finally we can update m_jointPos for each of the m_links
  1456. for (int i = 0; i < num_links; ++i)
  1457. {
  1458. btScalar *pJointPos;
  1459. pJointPos = &m_links[i].m_jointPos_interpolate[0];
  1460. if (m_links[i].m_collider && m_links[i].m_collider->isStaticOrKinematic())
  1461. {
  1462. switch (m_links[i].m_jointType)
  1463. {
  1464. case btMultibodyLink::ePrismatic:
  1465. case btMultibodyLink::eRevolute:
  1466. {
  1467. pJointPos[0] = m_links[i].m_jointPos[0];
  1468. break;
  1469. }
  1470. case btMultibodyLink::eSpherical:
  1471. {
  1472. for (int j = 0; j < 4; ++j)
  1473. {
  1474. pJointPos[j] = m_links[i].m_jointPos[j];
  1475. }
  1476. break;
  1477. }
  1478. case btMultibodyLink::ePlanar:
  1479. {
  1480. for (int j = 0; j < 3; ++j)
  1481. {
  1482. pJointPos[j] = m_links[i].m_jointPos[j];
  1483. }
  1484. break;
  1485. }
  1486. default:
  1487. break;
  1488. }
  1489. }
  1490. else
  1491. {
  1492. btScalar *pJointVel = getJointVelMultiDof(i);
  1493. switch (m_links[i].m_jointType)
  1494. {
  1495. case btMultibodyLink::ePrismatic:
  1496. case btMultibodyLink::eRevolute:
  1497. {
  1498. //reset to current pos
  1499. pJointPos[0] = m_links[i].m_jointPos[0];
  1500. btScalar jointVel = pJointVel[0];
  1501. pJointPos[0] += dt * jointVel;
  1502. break;
  1503. }
  1504. case btMultibodyLink::eSpherical:
  1505. {
  1506. //reset to current pos
  1507. for (int j = 0; j < 4; ++j)
  1508. {
  1509. pJointPos[j] = m_links[i].m_jointPos[j];
  1510. }
  1511. btVector3 jointVel;
  1512. jointVel.setValue(pJointVel[0], pJointVel[1], pJointVel[2]);
  1513. btQuaternion jointOri;
  1514. jointOri.setValue(pJointPos[0], pJointPos[1], pJointPos[2], pJointPos[3]);
  1515. pQuatUpdateFun(jointVel, jointOri, false, dt);
  1516. pJointPos[0] = jointOri.x();
  1517. pJointPos[1] = jointOri.y();
  1518. pJointPos[2] = jointOri.z();
  1519. pJointPos[3] = jointOri.w();
  1520. break;
  1521. }
  1522. case btMultibodyLink::ePlanar:
  1523. {
  1524. for (int j = 0; j < 3; ++j)
  1525. {
  1526. pJointPos[j] = m_links[i].m_jointPos[j];
  1527. }
  1528. pJointPos[0] += dt * getJointVelMultiDof(i)[0];
  1529. btVector3 q0_coors_qd1qd2 = getJointVelMultiDof(i)[1] * m_links[i].getAxisBottom(1) + getJointVelMultiDof(i)[2] * m_links[i].getAxisBottom(2);
  1530. btVector3 no_q0_coors_qd1qd2 = quatRotate(btQuaternion(m_links[i].getAxisTop(0), pJointPos[0]), q0_coors_qd1qd2);
  1531. pJointPos[1] += m_links[i].getAxisBottom(1).dot(no_q0_coors_qd1qd2) * dt;
  1532. pJointPos[2] += m_links[i].getAxisBottom(2).dot(no_q0_coors_qd1qd2) * dt;
  1533. break;
  1534. }
  1535. default:
  1536. {
  1537. }
  1538. }
  1539. }
  1540. m_links[i].updateInterpolationCacheMultiDof();
  1541. }
  1542. }
  1543. void btMultiBody::stepPositionsMultiDof(btScalar dt, btScalar *pq, btScalar *pqd)
  1544. {
  1545. int num_links = getNumLinks();
  1546. if(!isBaseKinematic())
  1547. {
  1548. // step position by adding dt * velocity
  1549. //btVector3 v = getBaseVel();
  1550. //m_basePos += dt * v;
  1551. //
  1552. btScalar *pBasePos = (pq ? &pq[4] : m_basePos);
  1553. btScalar *pBaseVel = (pqd ? &pqd[3] : &m_realBuf[3]); //note: the !pqd case assumes m_realBuf holds with base velocity at 3,4,5 (should be wrapped for safety)
  1554. pBasePos[0] += dt * pBaseVel[0];
  1555. pBasePos[1] += dt * pBaseVel[1];
  1556. pBasePos[2] += dt * pBaseVel[2];
  1557. }
  1558. ///////////////////////////////
  1559. //local functor for quaternion integration (to avoid error prone redundancy)
  1560. struct
  1561. {
  1562. //"exponential map" based on btTransformUtil::integrateTransform(..)
  1563. void operator()(const btVector3 &omega, btQuaternion &quat, bool baseBody, btScalar dt)
  1564. {
  1565. //baseBody => quat is alias and omega is global coor
  1566. //!baseBody => quat is alibi and omega is local coor
  1567. btVector3 axis;
  1568. btVector3 angvel;
  1569. if (!baseBody)
  1570. angvel = quatRotate(quat, omega); //if quat is not m_baseQuat, it is alibi => ok
  1571. else
  1572. angvel = omega;
  1573. btScalar fAngle = angvel.length();
  1574. //limit the angular motion
  1575. if (fAngle * dt > ANGULAR_MOTION_THRESHOLD)
  1576. {
  1577. fAngle = btScalar(0.5) * SIMD_HALF_PI / dt;
  1578. }
  1579. if (fAngle < btScalar(0.001))
  1580. {
  1581. // use Taylor's expansions of sync function
  1582. axis = angvel * (btScalar(0.5) * dt - (dt * dt * dt) * (btScalar(0.020833333333)) * fAngle * fAngle);
  1583. }
  1584. else
  1585. {
  1586. // sync(fAngle) = sin(c*fAngle)/t
  1587. axis = angvel * (btSin(btScalar(0.5) * fAngle * dt) / fAngle);
  1588. }
  1589. if (!baseBody)
  1590. quat = btQuaternion(axis.x(), axis.y(), axis.z(), btCos(fAngle * dt * btScalar(0.5))) * quat;
  1591. else
  1592. quat = quat * btQuaternion(-axis.x(), -axis.y(), -axis.z(), btCos(fAngle * dt * btScalar(0.5)));
  1593. //equivalent to: quat = (btQuaternion(axis.x(),axis.y(),axis.z(),btCos( fAngle*dt*btScalar(0.5) )) * quat.inverse()).inverse();
  1594. quat.normalize();
  1595. }
  1596. } pQuatUpdateFun;
  1597. ///////////////////////////////
  1598. //pQuatUpdateFun(getBaseOmega(), m_baseQuat, true, dt);
  1599. //
  1600. if(!isBaseKinematic())
  1601. {
  1602. btScalar *pBaseQuat = pq ? pq : m_baseQuat;
  1603. btScalar *pBaseOmega = pqd ? pqd : &m_realBuf[0]; //note: the !pqd case assumes m_realBuf starts with base omega (should be wrapped for safety)
  1604. //
  1605. btQuaternion baseQuat;
  1606. baseQuat.setValue(pBaseQuat[0], pBaseQuat[1], pBaseQuat[2], pBaseQuat[3]);
  1607. btVector3 baseOmega;
  1608. baseOmega.setValue(pBaseOmega[0], pBaseOmega[1], pBaseOmega[2]);
  1609. pQuatUpdateFun(baseOmega, baseQuat, true, dt);
  1610. pBaseQuat[0] = baseQuat.x();
  1611. pBaseQuat[1] = baseQuat.y();
  1612. pBaseQuat[2] = baseQuat.z();
  1613. pBaseQuat[3] = baseQuat.w();
  1614. //printf("pBaseOmega = %.4f %.4f %.4f\n", pBaseOmega->x(), pBaseOmega->y(), pBaseOmega->z());
  1615. //printf("pBaseVel = %.4f %.4f %.4f\n", pBaseVel->x(), pBaseVel->y(), pBaseVel->z());
  1616. //printf("baseQuat = %.4f %.4f %.4f %.4f\n", pBaseQuat->x(), pBaseQuat->y(), pBaseQuat->z(), pBaseQuat->w());
  1617. }
  1618. if (pq)
  1619. pq += 7;
  1620. if (pqd)
  1621. pqd += 6;
  1622. // Finally we can update m_jointPos for each of the m_links
  1623. for (int i = 0; i < num_links; ++i)
  1624. {
  1625. if (!(m_links[i].m_collider && m_links[i].m_collider->isStaticOrKinematic()))
  1626. {
  1627. btScalar *pJointPos;
  1628. pJointPos= (pq ? pq : &m_links[i].m_jointPos[0]);
  1629. btScalar *pJointVel = (pqd ? pqd : getJointVelMultiDof(i));
  1630. switch (m_links[i].m_jointType)
  1631. {
  1632. case btMultibodyLink::ePrismatic:
  1633. case btMultibodyLink::eRevolute:
  1634. {
  1635. //reset to current pos
  1636. btScalar jointVel = pJointVel[0];
  1637. pJointPos[0] += dt * jointVel;
  1638. break;
  1639. }
  1640. case btMultibodyLink::eSpherical:
  1641. {
  1642. //reset to current pos
  1643. btVector3 jointVel;
  1644. jointVel.setValue(pJointVel[0], pJointVel[1], pJointVel[2]);
  1645. btQuaternion jointOri;
  1646. jointOri.setValue(pJointPos[0], pJointPos[1], pJointPos[2], pJointPos[3]);
  1647. pQuatUpdateFun(jointVel, jointOri, false, dt);
  1648. pJointPos[0] = jointOri.x();
  1649. pJointPos[1] = jointOri.y();
  1650. pJointPos[2] = jointOri.z();
  1651. pJointPos[3] = jointOri.w();
  1652. break;
  1653. }
  1654. case btMultibodyLink::ePlanar:
  1655. {
  1656. pJointPos[0] += dt * getJointVelMultiDof(i)[0];
  1657. btVector3 q0_coors_qd1qd2 = getJointVelMultiDof(i)[1] * m_links[i].getAxisBottom(1) + getJointVelMultiDof(i)[2] * m_links[i].getAxisBottom(2);
  1658. btVector3 no_q0_coors_qd1qd2 = quatRotate(btQuaternion(m_links[i].getAxisTop(0), pJointPos[0]), q0_coors_qd1qd2);
  1659. pJointPos[1] += m_links[i].getAxisBottom(1).dot(no_q0_coors_qd1qd2) * dt;
  1660. pJointPos[2] += m_links[i].getAxisBottom(2).dot(no_q0_coors_qd1qd2) * dt;
  1661. break;
  1662. }
  1663. default:
  1664. {
  1665. }
  1666. }
  1667. }
  1668. m_links[i].updateCacheMultiDof(pq);
  1669. if (pq)
  1670. pq += m_links[i].m_posVarCount;
  1671. if (pqd)
  1672. pqd += m_links[i].m_dofCount;
  1673. }
  1674. }
  1675. void btMultiBody::fillConstraintJacobianMultiDof(int link,
  1676. const btVector3 &contact_point,
  1677. const btVector3 &normal_ang,
  1678. const btVector3 &normal_lin,
  1679. btScalar *jac,
  1680. btAlignedObjectArray<btScalar> &scratch_r1,
  1681. btAlignedObjectArray<btVector3> &scratch_v,
  1682. btAlignedObjectArray<btMatrix3x3> &scratch_m) const
  1683. {
  1684. // temporary space
  1685. int num_links = getNumLinks();
  1686. int m_dofCount = getNumDofs();
  1687. scratch_v.resize(3 * num_links + 3); //(num_links + base) offsets + (num_links + base) normals_lin + (num_links + base) normals_ang
  1688. scratch_m.resize(num_links + 1);
  1689. btVector3 *v_ptr = &scratch_v[0];
  1690. btVector3 *p_minus_com_local = v_ptr;
  1691. v_ptr += num_links + 1;
  1692. btVector3 *n_local_lin = v_ptr;
  1693. v_ptr += num_links + 1;
  1694. btVector3 *n_local_ang = v_ptr;
  1695. v_ptr += num_links + 1;
  1696. btAssert(v_ptr - &scratch_v[0] == scratch_v.size());
  1697. //scratch_r.resize(m_dofCount);
  1698. //btScalar *results = m_dofCount > 0 ? &scratch_r[0] : 0;
  1699. scratch_r1.resize(m_dofCount+num_links);
  1700. btScalar * results = m_dofCount > 0 ? &scratch_r1[0] : 0;
  1701. btScalar* links = num_links? &scratch_r1[m_dofCount] : 0;
  1702. int numLinksChildToRoot=0;
  1703. int l = link;
  1704. while (l != -1)
  1705. {
  1706. links[numLinksChildToRoot++]=l;
  1707. l = m_links[l].m_parent;
  1708. }
  1709. btMatrix3x3 *rot_from_world = &scratch_m[0];
  1710. const btVector3 p_minus_com_world = contact_point - m_basePos;
  1711. const btVector3 &normal_lin_world = normal_lin; //convenience
  1712. const btVector3 &normal_ang_world = normal_ang;
  1713. rot_from_world[0] = btMatrix3x3(m_baseQuat);
  1714. // omega coeffients first.
  1715. btVector3 omega_coeffs_world;
  1716. omega_coeffs_world = p_minus_com_world.cross(normal_lin_world);
  1717. jac[0] = omega_coeffs_world[0] + normal_ang_world[0];
  1718. jac[1] = omega_coeffs_world[1] + normal_ang_world[1];
  1719. jac[2] = omega_coeffs_world[2] + normal_ang_world[2];
  1720. // then v coefficients
  1721. jac[3] = normal_lin_world[0];
  1722. jac[4] = normal_lin_world[1];
  1723. jac[5] = normal_lin_world[2];
  1724. //create link-local versions of p_minus_com and normal
  1725. p_minus_com_local[0] = rot_from_world[0] * p_minus_com_world;
  1726. n_local_lin[0] = rot_from_world[0] * normal_lin_world;
  1727. n_local_ang[0] = rot_from_world[0] * normal_ang_world;
  1728. // Set remaining jac values to zero for now.
  1729. for (int i = 6; i < 6 + m_dofCount; ++i)
  1730. {
  1731. jac[i] = 0;
  1732. }
  1733. // Qdot coefficients, if necessary.
  1734. if (num_links > 0 && link > -1)
  1735. {
  1736. // TODO: (Also, we are making 3 separate calls to this function, for the normal & the 2 friction directions,
  1737. // which is resulting in repeated work being done...)
  1738. // calculate required normals & positions in the local frames.
  1739. for (int a = 0; a < numLinksChildToRoot; a++)
  1740. {
  1741. int i = links[numLinksChildToRoot-1-a];
  1742. // transform to local frame
  1743. const int parent = m_links[i].m_parent;
  1744. const btMatrix3x3 mtx(m_links[i].m_cachedRotParentToThis);
  1745. rot_from_world[i + 1] = mtx * rot_from_world[parent + 1];
  1746. n_local_lin[i + 1] = mtx * n_local_lin[parent + 1];
  1747. n_local_ang[i + 1] = mtx * n_local_ang[parent + 1];
  1748. p_minus_com_local[i + 1] = mtx * p_minus_com_local[parent + 1] - m_links[i].m_cachedRVector;
  1749. // calculate the jacobian entry
  1750. switch (m_links[i].m_jointType)
  1751. {
  1752. case btMultibodyLink::eRevolute:
  1753. {
  1754. results[m_links[i].m_dofOffset] = n_local_lin[i + 1].dot(m_links[i].getAxisTop(0).cross(p_minus_com_local[i + 1]) + m_links[i].getAxisBottom(0));
  1755. results[m_links[i].m_dofOffset] += n_local_ang[i + 1].dot(m_links[i].getAxisTop(0));
  1756. break;
  1757. }
  1758. case btMultibodyLink::ePrismatic:
  1759. {
  1760. results[m_links[i].m_dofOffset] = n_local_lin[i + 1].dot(m_links[i].getAxisBottom(0));
  1761. break;
  1762. }
  1763. case btMultibodyLink::eSpherical:
  1764. {
  1765. results[m_links[i].m_dofOffset + 0] = n_local_lin[i + 1].dot(m_links[i].getAxisTop(0).cross(p_minus_com_local[i + 1]) + m_links[i].getAxisBottom(0));
  1766. results[m_links[i].m_dofOffset + 1] = n_local_lin[i + 1].dot(m_links[i].getAxisTop(1).cross(p_minus_com_local[i + 1]) + m_links[i].getAxisBottom(1));
  1767. results[m_links[i].m_dofOffset + 2] = n_local_lin[i + 1].dot(m_links[i].getAxisTop(2).cross(p_minus_com_local[i + 1]) + m_links[i].getAxisBottom(2));
  1768. results[m_links[i].m_dofOffset + 0] += n_local_ang[i + 1].dot(m_links[i].getAxisTop(0));
  1769. results[m_links[i].m_dofOffset + 1] += n_local_ang[i + 1].dot(m_links[i].getAxisTop(1));
  1770. results[m_links[i].m_dofOffset + 2] += n_local_ang[i + 1].dot(m_links[i].getAxisTop(2));
  1771. break;
  1772. }
  1773. case btMultibodyLink::ePlanar:
  1774. {
  1775. results[m_links[i].m_dofOffset + 0] = n_local_lin[i + 1].dot(m_links[i].getAxisTop(0).cross(p_minus_com_local[i + 1])); // + m_links[i].getAxisBottom(0));
  1776. results[m_links[i].m_dofOffset + 1] = n_local_lin[i + 1].dot(m_links[i].getAxisBottom(1));
  1777. results[m_links[i].m_dofOffset + 2] = n_local_lin[i + 1].dot(m_links[i].getAxisBottom(2));
  1778. break;
  1779. }
  1780. default:
  1781. {
  1782. }
  1783. }
  1784. }
  1785. // Now copy through to output.
  1786. //printf("jac[%d] = ", link);
  1787. while (link != -1)
  1788. {
  1789. for (int dof = 0; dof < m_links[link].m_dofCount; ++dof)
  1790. {
  1791. jac[6 + m_links[link].m_dofOffset + dof] = results[m_links[link].m_dofOffset + dof];
  1792. //printf("%.2f\t", jac[6 + m_links[link].m_dofOffset + dof]);
  1793. }
  1794. link = m_links[link].m_parent;
  1795. }
  1796. //printf("]\n");
  1797. }
  1798. }
  1799. void btMultiBody::wakeUp()
  1800. {
  1801. m_sleepTimer = 0;
  1802. m_awake = true;
  1803. }
  1804. void btMultiBody::goToSleep()
  1805. {
  1806. m_awake = false;
  1807. }
  1808. void btMultiBody::checkMotionAndSleepIfRequired(btScalar timestep)
  1809. {
  1810. extern bool gDisableDeactivation;
  1811. if (!m_canSleep || gDisableDeactivation)
  1812. {
  1813. m_awake = true;
  1814. m_sleepTimer = 0;
  1815. return;
  1816. }
  1817. // motion is computed as omega^2 + v^2 + (sum of squares of joint velocities)
  1818. btScalar motion = 0;
  1819. {
  1820. for (int i = 0; i < 6 + m_dofCount; ++i)
  1821. motion += m_realBuf[i] * m_realBuf[i];
  1822. }
  1823. if (motion < m_sleepEpsilon)
  1824. {
  1825. m_sleepTimer += timestep;
  1826. if (m_sleepTimer > m_sleepTimeout)
  1827. {
  1828. goToSleep();
  1829. }
  1830. }
  1831. else
  1832. {
  1833. m_sleepTimer = 0;
  1834. if (m_canWakeup)
  1835. {
  1836. if (!m_awake)
  1837. wakeUp();
  1838. }
  1839. }
  1840. }
  1841. void btMultiBody::forwardKinematics(btAlignedObjectArray<btQuaternion> &world_to_local, btAlignedObjectArray<btVector3> &local_origin)
  1842. {
  1843. int num_links = getNumLinks();
  1844. // Cached 3x3 rotation matrices from parent frame to this frame.
  1845. btMatrix3x3 *rot_from_parent = (btMatrix3x3 *)&m_matrixBuf[0];
  1846. rot_from_parent[0] = btMatrix3x3(m_baseQuat); //m_baseQuat assumed to be alias!?
  1847. for (int i = 0; i < num_links; ++i)
  1848. {
  1849. rot_from_parent[i + 1] = btMatrix3x3(m_links[i].m_cachedRotParentToThis);
  1850. }
  1851. int nLinks = getNumLinks();
  1852. ///base + num m_links
  1853. world_to_local.resize(nLinks + 1);
  1854. local_origin.resize(nLinks + 1);
  1855. world_to_local[0] = getWorldToBaseRot();
  1856. local_origin[0] = getBasePos();
  1857. for (int k = 0; k < getNumLinks(); k++)
  1858. {
  1859. const int parent = getParent(k);
  1860. world_to_local[k + 1] = getParentToLocalRot(k) * world_to_local[parent + 1];
  1861. local_origin[k + 1] = local_origin[parent + 1] + (quatRotate(world_to_local[k + 1].inverse(), getRVector(k)));
  1862. }
  1863. for (int link = 0; link < getNumLinks(); link++)
  1864. {
  1865. int index = link + 1;
  1866. btVector3 posr = local_origin[index];
  1867. btScalar quat[4] = {-world_to_local[index].x(), -world_to_local[index].y(), -world_to_local[index].z(), world_to_local[index].w()};
  1868. btTransform tr;
  1869. tr.setIdentity();
  1870. tr.setOrigin(posr);
  1871. tr.setRotation(btQuaternion(quat[0], quat[1], quat[2], quat[3]));
  1872. getLink(link).m_cachedWorldTransform = tr;
  1873. }
  1874. }
  1875. void btMultiBody::updateCollisionObjectWorldTransforms(btAlignedObjectArray<btQuaternion> &world_to_local, btAlignedObjectArray<btVector3> &local_origin)
  1876. {
  1877. world_to_local.resize(getNumLinks() + 1);
  1878. local_origin.resize(getNumLinks() + 1);
  1879. world_to_local[0] = getWorldToBaseRot();
  1880. local_origin[0] = getBasePos();
  1881. if (getBaseCollider())
  1882. {
  1883. btVector3 posr = local_origin[0];
  1884. // float pos[4]={posr.x(),posr.y(),posr.z(),1};
  1885. btScalar quat[4] = {-world_to_local[0].x(), -world_to_local[0].y(), -world_to_local[0].z(), world_to_local[0].w()};
  1886. btTransform tr;
  1887. tr.setIdentity();
  1888. tr.setOrigin(posr);
  1889. tr.setRotation(btQuaternion(quat[0], quat[1], quat[2], quat[3]));
  1890. getBaseCollider()->setWorldTransform(tr);
  1891. getBaseCollider()->setInterpolationWorldTransform(tr);
  1892. }
  1893. for (int k = 0; k < getNumLinks(); k++)
  1894. {
  1895. const int parent = getParent(k);
  1896. world_to_local[k + 1] = getParentToLocalRot(k) * world_to_local[parent + 1];
  1897. local_origin[k + 1] = local_origin[parent + 1] + (quatRotate(world_to_local[k + 1].inverse(), getRVector(k)));
  1898. }
  1899. for (int m = 0; m < getNumLinks(); m++)
  1900. {
  1901. btMultiBodyLinkCollider *col = getLink(m).m_collider;
  1902. if (col)
  1903. {
  1904. int link = col->m_link;
  1905. btAssert(link == m);
  1906. int index = link + 1;
  1907. btVector3 posr = local_origin[index];
  1908. // float pos[4]={posr.x(),posr.y(),posr.z(),1};
  1909. btScalar quat[4] = {-world_to_local[index].x(), -world_to_local[index].y(), -world_to_local[index].z(), world_to_local[index].w()};
  1910. btTransform tr;
  1911. tr.setIdentity();
  1912. tr.setOrigin(posr);
  1913. tr.setRotation(btQuaternion(quat[0], quat[1], quat[2], quat[3]));
  1914. col->setWorldTransform(tr);
  1915. col->setInterpolationWorldTransform(tr);
  1916. }
  1917. }
  1918. }
  1919. void btMultiBody::updateCollisionObjectInterpolationWorldTransforms(btAlignedObjectArray<btQuaternion> &world_to_local, btAlignedObjectArray<btVector3> &local_origin)
  1920. {
  1921. world_to_local.resize(getNumLinks() + 1);
  1922. local_origin.resize(getNumLinks() + 1);
  1923. if(isBaseKinematic()){
  1924. world_to_local[0] = getWorldToBaseRot();
  1925. local_origin[0] = getBasePos();
  1926. }
  1927. else
  1928. {
  1929. world_to_local[0] = getInterpolateWorldToBaseRot();
  1930. local_origin[0] = getInterpolateBasePos();
  1931. }
  1932. if (getBaseCollider())
  1933. {
  1934. btVector3 posr = local_origin[0];
  1935. // float pos[4]={posr.x(),posr.y(),posr.z(),1};
  1936. btScalar quat[4] = {-world_to_local[0].x(), -world_to_local[0].y(), -world_to_local[0].z(), world_to_local[0].w()};
  1937. btTransform tr;
  1938. tr.setIdentity();
  1939. tr.setOrigin(posr);
  1940. tr.setRotation(btQuaternion(quat[0], quat[1], quat[2], quat[3]));
  1941. getBaseCollider()->setInterpolationWorldTransform(tr);
  1942. }
  1943. for (int k = 0; k < getNumLinks(); k++)
  1944. {
  1945. const int parent = getParent(k);
  1946. world_to_local[k + 1] = getInterpolateParentToLocalRot(k) * world_to_local[parent + 1];
  1947. local_origin[k + 1] = local_origin[parent + 1] + (quatRotate(world_to_local[k + 1].inverse(), getInterpolateRVector(k)));
  1948. }
  1949. for (int m = 0; m < getNumLinks(); m++)
  1950. {
  1951. btMultiBodyLinkCollider *col = getLink(m).m_collider;
  1952. if (col)
  1953. {
  1954. int link = col->m_link;
  1955. btAssert(link == m);
  1956. int index = link + 1;
  1957. btVector3 posr = local_origin[index];
  1958. // float pos[4]={posr.x(),posr.y(),posr.z(),1};
  1959. btScalar quat[4] = {-world_to_local[index].x(), -world_to_local[index].y(), -world_to_local[index].z(), world_to_local[index].w()};
  1960. btTransform tr;
  1961. tr.setIdentity();
  1962. tr.setOrigin(posr);
  1963. tr.setRotation(btQuaternion(quat[0], quat[1], quat[2], quat[3]));
  1964. col->setInterpolationWorldTransform(tr);
  1965. }
  1966. }
  1967. }
  1968. int btMultiBody::calculateSerializeBufferSize() const
  1969. {
  1970. int sz = sizeof(btMultiBodyData);
  1971. return sz;
  1972. }
  1973. ///fills the dataBuffer and returns the struct name (and 0 on failure)
  1974. const char *btMultiBody::serialize(void *dataBuffer, class btSerializer *serializer) const
  1975. {
  1976. btMultiBodyData *mbd = (btMultiBodyData *)dataBuffer;
  1977. getBasePos().serialize(mbd->m_baseWorldPosition);
  1978. getWorldToBaseRot().inverse().serialize(mbd->m_baseWorldOrientation);
  1979. getBaseVel().serialize(mbd->m_baseLinearVelocity);
  1980. getBaseOmega().serialize(mbd->m_baseAngularVelocity);
  1981. mbd->m_baseMass = this->getBaseMass();
  1982. getBaseInertia().serialize(mbd->m_baseInertia);
  1983. {
  1984. char *name = (char *)serializer->findNameForPointer(m_baseName);
  1985. mbd->m_baseName = (char *)serializer->getUniquePointer(name);
  1986. if (mbd->m_baseName)
  1987. {
  1988. serializer->serializeName(name);
  1989. }
  1990. }
  1991. mbd->m_numLinks = this->getNumLinks();
  1992. if (mbd->m_numLinks)
  1993. {
  1994. int sz = sizeof(btMultiBodyLinkData);
  1995. int numElem = mbd->m_numLinks;
  1996. btChunk *chunk = serializer->allocate(sz, numElem);
  1997. btMultiBodyLinkData *memPtr = (btMultiBodyLinkData *)chunk->m_oldPtr;
  1998. for (int i = 0; i < numElem; i++, memPtr++)
  1999. {
  2000. memPtr->m_jointType = getLink(i).m_jointType;
  2001. memPtr->m_dofCount = getLink(i).m_dofCount;
  2002. memPtr->m_posVarCount = getLink(i).m_posVarCount;
  2003. getLink(i).m_inertiaLocal.serialize(memPtr->m_linkInertia);
  2004. getLink(i).m_absFrameTotVelocity.m_topVec.serialize(memPtr->m_absFrameTotVelocityTop);
  2005. getLink(i).m_absFrameTotVelocity.m_bottomVec.serialize(memPtr->m_absFrameTotVelocityBottom);
  2006. getLink(i).m_absFrameLocVelocity.m_topVec.serialize(memPtr->m_absFrameLocVelocityTop);
  2007. getLink(i).m_absFrameLocVelocity.m_bottomVec.serialize(memPtr->m_absFrameLocVelocityBottom);
  2008. memPtr->m_linkMass = getLink(i).m_mass;
  2009. memPtr->m_parentIndex = getLink(i).m_parent;
  2010. memPtr->m_jointDamping = getLink(i).m_jointDamping;
  2011. memPtr->m_jointFriction = getLink(i).m_jointFriction;
  2012. memPtr->m_jointLowerLimit = getLink(i).m_jointLowerLimit;
  2013. memPtr->m_jointUpperLimit = getLink(i).m_jointUpperLimit;
  2014. memPtr->m_jointMaxForce = getLink(i).m_jointMaxForce;
  2015. memPtr->m_jointMaxVelocity = getLink(i).m_jointMaxVelocity;
  2016. getLink(i).m_eVector.serialize(memPtr->m_parentComToThisPivotOffset);
  2017. getLink(i).m_dVector.serialize(memPtr->m_thisPivotToThisComOffset);
  2018. getLink(i).m_zeroRotParentToThis.serialize(memPtr->m_zeroRotParentToThis);
  2019. btAssert(memPtr->m_dofCount <= 3);
  2020. for (int dof = 0; dof < getLink(i).m_dofCount; dof++)
  2021. {
  2022. getLink(i).getAxisBottom(dof).serialize(memPtr->m_jointAxisBottom[dof]);
  2023. getLink(i).getAxisTop(dof).serialize(memPtr->m_jointAxisTop[dof]);
  2024. memPtr->m_jointTorque[dof] = getLink(i).m_jointTorque[dof];
  2025. memPtr->m_jointVel[dof] = getJointVelMultiDof(i)[dof];
  2026. }
  2027. int numPosVar = getLink(i).m_posVarCount;
  2028. for (int posvar = 0; posvar < numPosVar; posvar++)
  2029. {
  2030. memPtr->m_jointPos[posvar] = getLink(i).m_jointPos[posvar];
  2031. }
  2032. {
  2033. char *name = (char *)serializer->findNameForPointer(m_links[i].m_linkName);
  2034. memPtr->m_linkName = (char *)serializer->getUniquePointer(name);
  2035. if (memPtr->m_linkName)
  2036. {
  2037. serializer->serializeName(name);
  2038. }
  2039. }
  2040. {
  2041. char *name = (char *)serializer->findNameForPointer(m_links[i].m_jointName);
  2042. memPtr->m_jointName = (char *)serializer->getUniquePointer(name);
  2043. if (memPtr->m_jointName)
  2044. {
  2045. serializer->serializeName(name);
  2046. }
  2047. }
  2048. memPtr->m_linkCollider = (btCollisionObjectData *)serializer->getUniquePointer(getLink(i).m_collider);
  2049. }
  2050. serializer->finalizeChunk(chunk, btMultiBodyLinkDataName, BT_ARRAY_CODE, (void *)&m_links[0]);
  2051. }
  2052. mbd->m_links = mbd->m_numLinks ? (btMultiBodyLinkData *)serializer->getUniquePointer((void *)&m_links[0]) : 0;
  2053. // Fill padding with zeros to appease msan.
  2054. #ifdef BT_USE_DOUBLE_PRECISION
  2055. memset(mbd->m_padding, 0, sizeof(mbd->m_padding));
  2056. #endif
  2057. return btMultiBodyDataName;
  2058. }
  2059. void btMultiBody::saveKinematicState(btScalar timeStep)
  2060. {
  2061. //todo: clamp to some (user definable) safe minimum timestep, to limit maximum angular/linear velocities
  2062. if (m_kinematic_calculate_velocity && timeStep != btScalar(0.))
  2063. {
  2064. btVector3 linearVelocity, angularVelocity;
  2065. btTransformUtil::calculateVelocity(getInterpolateBaseWorldTransform(), getBaseWorldTransform(), timeStep, linearVelocity, angularVelocity);
  2066. setBaseVel(linearVelocity);
  2067. setBaseOmega(angularVelocity);
  2068. setInterpolateBaseWorldTransform(getBaseWorldTransform());
  2069. }
  2070. }
  2071. void btMultiBody::setLinkDynamicType(const int i, int type)
  2072. {
  2073. if (i == -1)
  2074. {
  2075. setBaseDynamicType(type);
  2076. }
  2077. else if (i >= 0 && i < getNumLinks())
  2078. {
  2079. if (m_links[i].m_collider)
  2080. {
  2081. m_links[i].m_collider->setDynamicType(type);
  2082. }
  2083. }
  2084. }
  2085. bool btMultiBody::isLinkStaticOrKinematic(const int i) const
  2086. {
  2087. if (i == -1)
  2088. {
  2089. return isBaseStaticOrKinematic();
  2090. }
  2091. else
  2092. {
  2093. if (m_links[i].m_collider)
  2094. return m_links[i].m_collider->isStaticOrKinematic();
  2095. }
  2096. return false;
  2097. }
  2098. bool btMultiBody::isLinkKinematic(const int i) const
  2099. {
  2100. if (i == -1)
  2101. {
  2102. return isBaseKinematic();
  2103. }
  2104. else
  2105. {
  2106. if (m_links[i].m_collider)
  2107. return m_links[i].m_collider->isKinematic();
  2108. }
  2109. return false;
  2110. }
  2111. bool btMultiBody::isLinkAndAllAncestorsStaticOrKinematic(const int i) const
  2112. {
  2113. int link = i;
  2114. while (link != -1) {
  2115. if (!isLinkStaticOrKinematic(link))
  2116. return false;
  2117. link = m_links[link].m_parent;
  2118. }
  2119. return isBaseStaticOrKinematic();
  2120. }
  2121. bool btMultiBody::isLinkAndAllAncestorsKinematic(const int i) const
  2122. {
  2123. int link = i;
  2124. while (link != -1) {
  2125. if (!isLinkKinematic(link))
  2126. return false;
  2127. link = m_links[link].m_parent;
  2128. }
  2129. return isBaseKinematic();
  2130. }