b2PrismaticJoint.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626
  1. /*
  2. * Copyright (c) 2006-2011 Erin Catto http://www.box2d.org
  3. *
  4. * This software is provided 'as-is', without any express or implied
  5. * warranty. In no event will the authors be held liable for any damages
  6. * arising from the use of this software.
  7. * Permission is granted to anyone to use this software for any purpose,
  8. * including commercial applications, and to alter it and redistribute it
  9. * freely, subject to the following restrictions:
  10. * 1. The origin of this software must not be misrepresented; you must not
  11. * claim that you wrote the original software. If you use this software
  12. * in a product, an acknowledgment in the product documentation would be
  13. * appreciated but is not required.
  14. * 2. Altered source versions must be plainly marked as such, and must not be
  15. * misrepresented as being the original software.
  16. * 3. This notice may not be removed or altered from any source distribution.
  17. */
  18. #include <Box2D/Dynamics/Joints/b2PrismaticJoint.h>
  19. #include <Box2D/Dynamics/b2Body.h>
  20. #include <Box2D/Dynamics/b2TimeStep.h>
  21. // Linear constraint (point-to-line)
  22. // d = p2 - p1 = x2 + r2 - x1 - r1
  23. // C = dot(perp, d)
  24. // Cdot = dot(d, cross(w1, perp)) + dot(perp, v2 + cross(w2, r2) - v1 - cross(w1, r1))
  25. // = -dot(perp, v1) - dot(cross(d + r1, perp), w1) + dot(perp, v2) + dot(cross(r2, perp), v2)
  26. // J = [-perp, -cross(d + r1, perp), perp, cross(r2,perp)]
  27. //
  28. // Angular constraint
  29. // C = a2 - a1 + a_initial
  30. // Cdot = w2 - w1
  31. // J = [0 0 -1 0 0 1]
  32. //
  33. // K = J * invM * JT
  34. //
  35. // J = [-a -s1 a s2]
  36. // [0 -1 0 1]
  37. // a = perp
  38. // s1 = cross(d + r1, a) = cross(p2 - x1, a)
  39. // s2 = cross(r2, a) = cross(p2 - x2, a)
  40. // Motor/Limit linear constraint
  41. // C = dot(ax1, d)
  42. // Cdot = = -dot(ax1, v1) - dot(cross(d + r1, ax1), w1) + dot(ax1, v2) + dot(cross(r2, ax1), v2)
  43. // J = [-ax1 -cross(d+r1,ax1) ax1 cross(r2,ax1)]
  44. // Block Solver
  45. // We develop a block solver that includes the joint limit. This makes the limit stiff (inelastic) even
  46. // when the mass has poor distribution (leading to large torques about the joint anchor points).
  47. //
  48. // The Jacobian has 3 rows:
  49. // J = [-uT -s1 uT s2] // linear
  50. // [0 -1 0 1] // angular
  51. // [-vT -a1 vT a2] // limit
  52. //
  53. // u = perp
  54. // v = axis
  55. // s1 = cross(d + r1, u), s2 = cross(r2, u)
  56. // a1 = cross(d + r1, v), a2 = cross(r2, v)
  57. // M * (v2 - v1) = JT * df
  58. // J * v2 = bias
  59. //
  60. // v2 = v1 + invM * JT * df
  61. // J * (v1 + invM * JT * df) = bias
  62. // K * df = bias - J * v1 = -Cdot
  63. // K = J * invM * JT
  64. // Cdot = J * v1 - bias
  65. //
  66. // Now solve for f2.
  67. // df = f2 - f1
  68. // K * (f2 - f1) = -Cdot
  69. // f2 = invK * (-Cdot) + f1
  70. //
  71. // Clamp accumulated limit impulse.
  72. // lower: f2(3) = max(f2(3), 0)
  73. // upper: f2(3) = min(f2(3), 0)
  74. //
  75. // Solve for correct f2(1:2)
  76. // K(1:2, 1:2) * f2(1:2) = -Cdot(1:2) - K(1:2,3) * f2(3) + K(1:2,1:3) * f1
  77. // = -Cdot(1:2) - K(1:2,3) * f2(3) + K(1:2,1:2) * f1(1:2) + K(1:2,3) * f1(3)
  78. // K(1:2, 1:2) * f2(1:2) = -Cdot(1:2) - K(1:2,3) * (f2(3) - f1(3)) + K(1:2,1:2) * f1(1:2)
  79. // f2(1:2) = invK(1:2,1:2) * (-Cdot(1:2) - K(1:2,3) * (f2(3) - f1(3))) + f1(1:2)
  80. //
  81. // Now compute impulse to be applied:
  82. // df = f2 - f1
  83. void b2PrismaticJointDef::Initialize(b2Body* bA, b2Body* bB, const b2Vec2& anchor, const b2Vec2& axis)
  84. {
  85. bodyA = bA;
  86. bodyB = bB;
  87. localAnchorA = bodyA->GetLocalPoint(anchor);
  88. localAnchorB = bodyB->GetLocalPoint(anchor);
  89. localAxisA = bodyA->GetLocalVector(axis);
  90. referenceAngle = bodyB->GetAngle() - bodyA->GetAngle();
  91. }
  92. b2PrismaticJoint::b2PrismaticJoint(const b2PrismaticJointDef* def)
  93. : b2Joint(def)
  94. {
  95. m_localAnchorA = def->localAnchorA;
  96. m_localAnchorB = def->localAnchorB;
  97. m_localXAxisA = def->localAxisA;
  98. m_localXAxisA.Normalize();
  99. m_localYAxisA = b2Cross(1.0f, m_localXAxisA);
  100. m_referenceAngle = def->referenceAngle;
  101. m_impulse.SetZero();
  102. m_motorMass = 0.0f;
  103. m_motorImpulse = 0.0f;
  104. m_lowerTranslation = def->lowerTranslation;
  105. m_upperTranslation = def->upperTranslation;
  106. m_maxMotorForce = def->maxMotorForce;
  107. m_motorSpeed = def->motorSpeed;
  108. m_enableLimit = def->enableLimit;
  109. m_enableMotor = def->enableMotor;
  110. m_limitState = e_inactiveLimit;
  111. m_axis.SetZero();
  112. m_perp.SetZero();
  113. }
  114. void b2PrismaticJoint::InitVelocityConstraints(const b2SolverData& data)
  115. {
  116. m_indexA = m_bodyA->m_islandIndex;
  117. m_indexB = m_bodyB->m_islandIndex;
  118. m_localCenterA = m_bodyA->m_sweep.localCenter;
  119. m_localCenterB = m_bodyB->m_sweep.localCenter;
  120. m_invMassA = m_bodyA->m_invMass;
  121. m_invMassB = m_bodyB->m_invMass;
  122. m_invIA = m_bodyA->m_invI;
  123. m_invIB = m_bodyB->m_invI;
  124. b2Vec2 cA = data.positions[m_indexA].c;
  125. float32 aA = data.positions[m_indexA].a;
  126. b2Vec2 vA = data.velocities[m_indexA].v;
  127. float32 wA = data.velocities[m_indexA].w;
  128. b2Vec2 cB = data.positions[m_indexB].c;
  129. float32 aB = data.positions[m_indexB].a;
  130. b2Vec2 vB = data.velocities[m_indexB].v;
  131. float32 wB = data.velocities[m_indexB].w;
  132. b2Rot qA(aA), qB(aB);
  133. // Compute the effective masses.
  134. b2Vec2 rA = b2Mul(qA, m_localAnchorA - m_localCenterA);
  135. b2Vec2 rB = b2Mul(qB, m_localAnchorB - m_localCenterB);
  136. b2Vec2 d = (cB - cA) + rB - rA;
  137. float32 mA = m_invMassA, mB = m_invMassB;
  138. float32 iA = m_invIA, iB = m_invIB;
  139. // Compute motor Jacobian and effective mass.
  140. {
  141. m_axis = b2Mul(qA, m_localXAxisA);
  142. m_a1 = b2Cross(d + rA, m_axis);
  143. m_a2 = b2Cross(rB, m_axis);
  144. m_motorMass = mA + mB + iA * m_a1 * m_a1 + iB * m_a2 * m_a2;
  145. if (m_motorMass > 0.0f)
  146. {
  147. m_motorMass = 1.0f / m_motorMass;
  148. }
  149. }
  150. // Prismatic constraint.
  151. {
  152. m_perp = b2Mul(qA, m_localYAxisA);
  153. m_s1 = b2Cross(d + rA, m_perp);
  154. m_s2 = b2Cross(rB, m_perp);
  155. float32 k11 = mA + mB + iA * m_s1 * m_s1 + iB * m_s2 * m_s2;
  156. float32 k12 = iA * m_s1 + iB * m_s2;
  157. float32 k13 = iA * m_s1 * m_a1 + iB * m_s2 * m_a2;
  158. float32 k22 = iA + iB;
  159. if (k22 == 0.0f)
  160. {
  161. // For bodies with fixed rotation.
  162. k22 = 1.0f;
  163. }
  164. float32 k23 = iA * m_a1 + iB * m_a2;
  165. float32 k33 = mA + mB + iA * m_a1 * m_a1 + iB * m_a2 * m_a2;
  166. m_K.ex.Set(k11, k12, k13);
  167. m_K.ey.Set(k12, k22, k23);
  168. m_K.ez.Set(k13, k23, k33);
  169. }
  170. // Compute motor and limit terms.
  171. if (m_enableLimit)
  172. {
  173. float32 jointTranslation = b2Dot(m_axis, d);
  174. if (b2Abs(m_upperTranslation - m_lowerTranslation) < 2.0f * b2_linearSlop)
  175. {
  176. m_limitState = e_equalLimits;
  177. }
  178. else if (jointTranslation <= m_lowerTranslation)
  179. {
  180. if (m_limitState != e_atLowerLimit)
  181. {
  182. m_limitState = e_atLowerLimit;
  183. m_impulse.z = 0.0f;
  184. }
  185. }
  186. else if (jointTranslation >= m_upperTranslation)
  187. {
  188. if (m_limitState != e_atUpperLimit)
  189. {
  190. m_limitState = e_atUpperLimit;
  191. m_impulse.z = 0.0f;
  192. }
  193. }
  194. else
  195. {
  196. m_limitState = e_inactiveLimit;
  197. m_impulse.z = 0.0f;
  198. }
  199. }
  200. else
  201. {
  202. m_limitState = e_inactiveLimit;
  203. m_impulse.z = 0.0f;
  204. }
  205. if (m_enableMotor == false)
  206. {
  207. m_motorImpulse = 0.0f;
  208. }
  209. if (data.step.warmStarting)
  210. {
  211. // Account for variable time step.
  212. m_impulse *= data.step.dtRatio;
  213. m_motorImpulse *= data.step.dtRatio;
  214. b2Vec2 P = m_impulse.x * m_perp + (m_motorImpulse + m_impulse.z) * m_axis;
  215. float32 LA = m_impulse.x * m_s1 + m_impulse.y + (m_motorImpulse + m_impulse.z) * m_a1;
  216. float32 LB = m_impulse.x * m_s2 + m_impulse.y + (m_motorImpulse + m_impulse.z) * m_a2;
  217. vA -= mA * P;
  218. wA -= iA * LA;
  219. vB += mB * P;
  220. wB += iB * LB;
  221. }
  222. else
  223. {
  224. m_impulse.SetZero();
  225. m_motorImpulse = 0.0f;
  226. }
  227. data.velocities[m_indexA].v = vA;
  228. data.velocities[m_indexA].w = wA;
  229. data.velocities[m_indexB].v = vB;
  230. data.velocities[m_indexB].w = wB;
  231. }
  232. void b2PrismaticJoint::SolveVelocityConstraints(const b2SolverData& data)
  233. {
  234. b2Vec2 vA = data.velocities[m_indexA].v;
  235. float32 wA = data.velocities[m_indexA].w;
  236. b2Vec2 vB = data.velocities[m_indexB].v;
  237. float32 wB = data.velocities[m_indexB].w;
  238. float32 mA = m_invMassA, mB = m_invMassB;
  239. float32 iA = m_invIA, iB = m_invIB;
  240. // Solve linear motor constraint.
  241. if (m_enableMotor && m_limitState != e_equalLimits)
  242. {
  243. float32 Cdot = b2Dot(m_axis, vB - vA) + m_a2 * wB - m_a1 * wA;
  244. float32 impulse = m_motorMass * (m_motorSpeed - Cdot);
  245. float32 oldImpulse = m_motorImpulse;
  246. float32 maxImpulse = data.step.dt * m_maxMotorForce;
  247. m_motorImpulse = b2Clamp(m_motorImpulse + impulse, -maxImpulse, maxImpulse);
  248. impulse = m_motorImpulse - oldImpulse;
  249. b2Vec2 P = impulse * m_axis;
  250. float32 LA = impulse * m_a1;
  251. float32 LB = impulse * m_a2;
  252. vA -= mA * P;
  253. wA -= iA * LA;
  254. vB += mB * P;
  255. wB += iB * LB;
  256. }
  257. b2Vec2 Cdot1;
  258. Cdot1.x = b2Dot(m_perp, vB - vA) + m_s2 * wB - m_s1 * wA;
  259. Cdot1.y = wB - wA;
  260. if (m_enableLimit && m_limitState != e_inactiveLimit)
  261. {
  262. // Solve prismatic and limit constraint in block form.
  263. float32 Cdot2;
  264. Cdot2 = b2Dot(m_axis, vB - vA) + m_a2 * wB - m_a1 * wA;
  265. b2Vec3 Cdot(Cdot1.x, Cdot1.y, Cdot2);
  266. b2Vec3 f1 = m_impulse;
  267. b2Vec3 df = m_K.Solve33(-Cdot);
  268. m_impulse += df;
  269. if (m_limitState == e_atLowerLimit)
  270. {
  271. m_impulse.z = b2Max(m_impulse.z, 0.0f);
  272. }
  273. else if (m_limitState == e_atUpperLimit)
  274. {
  275. m_impulse.z = b2Min(m_impulse.z, 0.0f);
  276. }
  277. // f2(1:2) = invK(1:2,1:2) * (-Cdot(1:2) - K(1:2,3) * (f2(3) - f1(3))) + f1(1:2)
  278. b2Vec2 b = -Cdot1 - (m_impulse.z - f1.z) * b2Vec2(m_K.ez.x, m_K.ez.y);
  279. b2Vec2 f2r = m_K.Solve22(b) + b2Vec2(f1.x, f1.y);
  280. m_impulse.x = f2r.x;
  281. m_impulse.y = f2r.y;
  282. df = m_impulse - f1;
  283. b2Vec2 P = df.x * m_perp + df.z * m_axis;
  284. float32 LA = df.x * m_s1 + df.y + df.z * m_a1;
  285. float32 LB = df.x * m_s2 + df.y + df.z * m_a2;
  286. vA -= mA * P;
  287. wA -= iA * LA;
  288. vB += mB * P;
  289. wB += iB * LB;
  290. }
  291. else
  292. {
  293. // Limit is inactive, just solve the prismatic constraint in block form.
  294. b2Vec2 df = m_K.Solve22(-Cdot1);
  295. m_impulse.x += df.x;
  296. m_impulse.y += df.y;
  297. b2Vec2 P = df.x * m_perp;
  298. float32 LA = df.x * m_s1 + df.y;
  299. float32 LB = df.x * m_s2 + df.y;
  300. vA -= mA * P;
  301. wA -= iA * LA;
  302. vB += mB * P;
  303. wB += iB * LB;
  304. }
  305. data.velocities[m_indexA].v = vA;
  306. data.velocities[m_indexA].w = wA;
  307. data.velocities[m_indexB].v = vB;
  308. data.velocities[m_indexB].w = wB;
  309. }
  310. bool b2PrismaticJoint::SolvePositionConstraints(const b2SolverData& data)
  311. {
  312. b2Vec2 cA = data.positions[m_indexA].c;
  313. float32 aA = data.positions[m_indexA].a;
  314. b2Vec2 cB = data.positions[m_indexB].c;
  315. float32 aB = data.positions[m_indexB].a;
  316. b2Rot qA(aA), qB(aB);
  317. float32 mA = m_invMassA, mB = m_invMassB;
  318. float32 iA = m_invIA, iB = m_invIB;
  319. // Compute fresh Jacobians
  320. b2Vec2 rA = b2Mul(qA, m_localAnchorA - m_localCenterA);
  321. b2Vec2 rB = b2Mul(qB, m_localAnchorB - m_localCenterB);
  322. b2Vec2 d = cB + rB - cA - rA;
  323. b2Vec2 axis = b2Mul(qA, m_localXAxisA);
  324. float32 a1 = b2Cross(d + rA, axis);
  325. float32 a2 = b2Cross(rB, axis);
  326. b2Vec2 perp = b2Mul(qA, m_localYAxisA);
  327. float32 s1 = b2Cross(d + rA, perp);
  328. float32 s2 = b2Cross(rB, perp);
  329. b2Vec3 impulse;
  330. b2Vec2 C1;
  331. C1.x = b2Dot(perp, d);
  332. C1.y = aB - aA - m_referenceAngle;
  333. float32 linearError = b2Abs(C1.x);
  334. float32 angularError = b2Abs(C1.y);
  335. bool active = false;
  336. float32 C2 = 0.0f;
  337. if (m_enableLimit)
  338. {
  339. float32 translation = b2Dot(axis, d);
  340. if (b2Abs(m_upperTranslation - m_lowerTranslation) < 2.0f * b2_linearSlop)
  341. {
  342. // Prevent large angular corrections
  343. C2 = b2Clamp(translation, -b2_maxLinearCorrection, b2_maxLinearCorrection);
  344. linearError = b2Max(linearError, b2Abs(translation));
  345. active = true;
  346. }
  347. else if (translation <= m_lowerTranslation)
  348. {
  349. // Prevent large linear corrections and allow some slop.
  350. C2 = b2Clamp(translation - m_lowerTranslation + b2_linearSlop, -b2_maxLinearCorrection, 0.0f);
  351. linearError = b2Max(linearError, m_lowerTranslation - translation);
  352. active = true;
  353. }
  354. else if (translation >= m_upperTranslation)
  355. {
  356. // Prevent large linear corrections and allow some slop.
  357. C2 = b2Clamp(translation - m_upperTranslation - b2_linearSlop, 0.0f, b2_maxLinearCorrection);
  358. linearError = b2Max(linearError, translation - m_upperTranslation);
  359. active = true;
  360. }
  361. }
  362. if (active)
  363. {
  364. float32 k11 = mA + mB + iA * s1 * s1 + iB * s2 * s2;
  365. float32 k12 = iA * s1 + iB * s2;
  366. float32 k13 = iA * s1 * a1 + iB * s2 * a2;
  367. float32 k22 = iA + iB;
  368. if (k22 == 0.0f)
  369. {
  370. // For fixed rotation
  371. k22 = 1.0f;
  372. }
  373. float32 k23 = iA * a1 + iB * a2;
  374. float32 k33 = mA + mB + iA * a1 * a1 + iB * a2 * a2;
  375. b2Mat33 K;
  376. K.ex.Set(k11, k12, k13);
  377. K.ey.Set(k12, k22, k23);
  378. K.ez.Set(k13, k23, k33);
  379. b2Vec3 C;
  380. C.x = C1.x;
  381. C.y = C1.y;
  382. C.z = C2;
  383. impulse = K.Solve33(-C);
  384. }
  385. else
  386. {
  387. float32 k11 = mA + mB + iA * s1 * s1 + iB * s2 * s2;
  388. float32 k12 = iA * s1 + iB * s2;
  389. float32 k22 = iA + iB;
  390. if (k22 == 0.0f)
  391. {
  392. k22 = 1.0f;
  393. }
  394. b2Mat22 K;
  395. K.ex.Set(k11, k12);
  396. K.ey.Set(k12, k22);
  397. b2Vec2 impulse1 = K.Solve(-C1);
  398. impulse.x = impulse1.x;
  399. impulse.y = impulse1.y;
  400. impulse.z = 0.0f;
  401. }
  402. b2Vec2 P = impulse.x * perp + impulse.z * axis;
  403. float32 LA = impulse.x * s1 + impulse.y + impulse.z * a1;
  404. float32 LB = impulse.x * s2 + impulse.y + impulse.z * a2;
  405. cA -= mA * P;
  406. aA -= iA * LA;
  407. cB += mB * P;
  408. aB += iB * LB;
  409. data.positions[m_indexA].c = cA;
  410. data.positions[m_indexA].a = aA;
  411. data.positions[m_indexB].c = cB;
  412. data.positions[m_indexB].a = aB;
  413. return linearError <= b2_linearSlop && angularError <= b2_angularSlop;
  414. }
  415. b2Vec2 b2PrismaticJoint::GetAnchorA() const
  416. {
  417. return m_bodyA->GetWorldPoint(m_localAnchorA);
  418. }
  419. b2Vec2 b2PrismaticJoint::GetAnchorB() const
  420. {
  421. return m_bodyB->GetWorldPoint(m_localAnchorB);
  422. }
  423. b2Vec2 b2PrismaticJoint::GetReactionForce(float32 inv_dt) const
  424. {
  425. return inv_dt * (m_impulse.x * m_perp + (m_motorImpulse + m_impulse.z) * m_axis);
  426. }
  427. float32 b2PrismaticJoint::GetReactionTorque(float32 inv_dt) const
  428. {
  429. return inv_dt * m_impulse.y;
  430. }
  431. float32 b2PrismaticJoint::GetJointTranslation() const
  432. {
  433. b2Vec2 pA = m_bodyA->GetWorldPoint(m_localAnchorA);
  434. b2Vec2 pB = m_bodyB->GetWorldPoint(m_localAnchorB);
  435. b2Vec2 d = pB - pA;
  436. b2Vec2 axis = m_bodyA->GetWorldVector(m_localXAxisA);
  437. float32 translation = b2Dot(d, axis);
  438. return translation;
  439. }
  440. float32 b2PrismaticJoint::GetJointSpeed() const
  441. {
  442. b2Body* bA = m_bodyA;
  443. b2Body* bB = m_bodyB;
  444. b2Vec2 rA = b2Mul(bA->m_xf.q, m_localAnchorA - bA->m_sweep.localCenter);
  445. b2Vec2 rB = b2Mul(bB->m_xf.q, m_localAnchorB - bB->m_sweep.localCenter);
  446. b2Vec2 p1 = bA->m_sweep.c + rA;
  447. b2Vec2 p2 = bB->m_sweep.c + rB;
  448. b2Vec2 d = p2 - p1;
  449. b2Vec2 axis = b2Mul(bA->m_xf.q, m_localXAxisA);
  450. b2Vec2 vA = bA->m_linearVelocity;
  451. b2Vec2 vB = bB->m_linearVelocity;
  452. float32 wA = bA->m_angularVelocity;
  453. float32 wB = bB->m_angularVelocity;
  454. float32 speed = b2Dot(d, b2Cross(wA, axis)) + b2Dot(axis, vB + b2Cross(wB, rB) - vA - b2Cross(wA, rA));
  455. return speed;
  456. }
  457. bool b2PrismaticJoint::IsLimitEnabled() const
  458. {
  459. return m_enableLimit;
  460. }
  461. void b2PrismaticJoint::EnableLimit(bool flag)
  462. {
  463. if (flag != m_enableLimit)
  464. {
  465. m_bodyA->SetAwake(true);
  466. m_bodyB->SetAwake(true);
  467. m_enableLimit = flag;
  468. m_impulse.z = 0.0f;
  469. }
  470. }
  471. float32 b2PrismaticJoint::GetLowerLimit() const
  472. {
  473. return m_lowerTranslation;
  474. }
  475. float32 b2PrismaticJoint::GetUpperLimit() const
  476. {
  477. return m_upperTranslation;
  478. }
  479. void b2PrismaticJoint::SetLimits(float32 lower, float32 upper)
  480. {
  481. b2Assert(lower <= upper);
  482. if (lower != m_lowerTranslation || upper != m_upperTranslation)
  483. {
  484. m_bodyA->SetAwake(true);
  485. m_bodyB->SetAwake(true);
  486. m_lowerTranslation = lower;
  487. m_upperTranslation = upper;
  488. m_impulse.z = 0.0f;
  489. }
  490. }
  491. bool b2PrismaticJoint::IsMotorEnabled() const
  492. {
  493. return m_enableMotor;
  494. }
  495. void b2PrismaticJoint::EnableMotor(bool flag)
  496. {
  497. m_bodyA->SetAwake(true);
  498. m_bodyB->SetAwake(true);
  499. m_enableMotor = flag;
  500. }
  501. void b2PrismaticJoint::SetMotorSpeed(float32 speed)
  502. {
  503. m_bodyA->SetAwake(true);
  504. m_bodyB->SetAwake(true);
  505. m_motorSpeed = speed;
  506. }
  507. void b2PrismaticJoint::SetMaxMotorForce(float32 force)
  508. {
  509. m_bodyA->SetAwake(true);
  510. m_bodyB->SetAwake(true);
  511. m_maxMotorForce = force;
  512. }
  513. float32 b2PrismaticJoint::GetMotorForce(float32 inv_dt) const
  514. {
  515. return inv_dt * m_motorImpulse;
  516. }
  517. void b2PrismaticJoint::Dump()
  518. {
  519. int32 indexA = m_bodyA->m_islandIndex;
  520. int32 indexB = m_bodyB->m_islandIndex;
  521. b2Log(" b2PrismaticJointDef jd;\n");
  522. b2Log(" jd.bodyA = bodies[%d];\n", indexA);
  523. b2Log(" jd.bodyB = bodies[%d];\n", indexB);
  524. b2Log(" jd.collideConnected = bool(%d);\n", m_collideConnected);
  525. b2Log(" jd.localAnchorA.Set(%.15lef, %.15lef);\n", m_localAnchorA.x, m_localAnchorA.y);
  526. b2Log(" jd.localAnchorB.Set(%.15lef, %.15lef);\n", m_localAnchorB.x, m_localAnchorB.y);
  527. b2Log(" jd.localAxisA.Set(%.15lef, %.15lef);\n", m_localXAxisA.x, m_localXAxisA.y);
  528. b2Log(" jd.referenceAngle = %.15lef;\n", m_referenceAngle);
  529. b2Log(" jd.enableLimit = bool(%d);\n", m_enableLimit);
  530. b2Log(" jd.lowerTranslation = %.15lef;\n", m_lowerTranslation);
  531. b2Log(" jd.upperTranslation = %.15lef;\n", m_upperTranslation);
  532. b2Log(" jd.enableMotor = bool(%d);\n", m_enableMotor);
  533. b2Log(" jd.motorSpeed = %.15lef;\n", m_motorSpeed);
  534. b2Log(" jd.maxMotorForce = %.15lef;\n", m_maxMotorForce);
  535. b2Log(" joints[%d] = m_world->CreateJoint(&jd);\n", m_index);
  536. }