b2GearJoint.cpp 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. /*
  2. * Copyright (c) 2007 Erin Catto http://www.gphysics.com
  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 "b2GearJoint.h"
  19. #include "b2RevoluteJoint.h"
  20. #include "b2PrismaticJoint.h"
  21. #include "../b2Body.h"
  22. #include "../b2World.h"
  23. // Gear Joint:
  24. // C0 = (coordinate1 + ratio * coordinate2)_initial
  25. // C = C0 - (cordinate1 + ratio * coordinate2) = 0
  26. // Cdot = -(Cdot1 + ratio * Cdot2)
  27. // J = -[J1 ratio * J2]
  28. // K = J * invM * JT
  29. // = J1 * invM1 * J1T + ratio * ratio * J2 * invM2 * J2T
  30. //
  31. // Revolute:
  32. // coordinate = rotation
  33. // Cdot = angularVelocity
  34. // J = [0 0 1]
  35. // K = J * invM * JT = invI
  36. //
  37. // Prismatic:
  38. // coordinate = dot(p - pg, ug)
  39. // Cdot = dot(v + cross(w, r), ug)
  40. // J = [ug cross(r, ug)]
  41. // K = J * invM * JT = invMass + invI * cross(r, ug)^2
  42. b2GearJoint::b2GearJoint(const b2GearJointDef* def)
  43. : b2Joint(def)
  44. {
  45. b2JointType type1 = def->joint1->GetType();
  46. b2JointType type2 = def->joint2->GetType();
  47. b2Assert(type1 == e_revoluteJoint || type1 == e_prismaticJoint);
  48. b2Assert(type2 == e_revoluteJoint || type2 == e_prismaticJoint);
  49. b2Assert(def->joint1->GetBody1()->IsStatic());
  50. b2Assert(def->joint2->GetBody1()->IsStatic());
  51. m_revolute1 = NULL;
  52. m_prismatic1 = NULL;
  53. m_revolute2 = NULL;
  54. m_prismatic2 = NULL;
  55. float32 coordinate1, coordinate2;
  56. m_ground1 = def->joint1->GetBody1();
  57. m_body1 = def->joint1->GetBody2();
  58. if (type1 == e_revoluteJoint)
  59. {
  60. m_revolute1 = (b2RevoluteJoint*)def->joint1;
  61. m_groundAnchor1 = m_revolute1->m_localAnchor1;
  62. m_localAnchor1 = m_revolute1->m_localAnchor2;
  63. coordinate1 = m_revolute1->GetJointAngle();
  64. }
  65. else
  66. {
  67. m_prismatic1 = (b2PrismaticJoint*)def->joint1;
  68. m_groundAnchor1 = m_prismatic1->m_localAnchor1;
  69. m_localAnchor1 = m_prismatic1->m_localAnchor2;
  70. coordinate1 = m_prismatic1->GetJointTranslation();
  71. }
  72. m_ground2 = def->joint2->GetBody1();
  73. m_body2 = def->joint2->GetBody2();
  74. if (type2 == e_revoluteJoint)
  75. {
  76. m_revolute2 = (b2RevoluteJoint*)def->joint2;
  77. m_groundAnchor2 = m_revolute2->m_localAnchor1;
  78. m_localAnchor2 = m_revolute2->m_localAnchor2;
  79. coordinate2 = m_revolute2->GetJointAngle();
  80. }
  81. else
  82. {
  83. m_prismatic2 = (b2PrismaticJoint*)def->joint2;
  84. m_groundAnchor2 = m_prismatic2->m_localAnchor1;
  85. m_localAnchor2 = m_prismatic2->m_localAnchor2;
  86. coordinate2 = m_prismatic2->GetJointTranslation();
  87. }
  88. m_ratio = def->ratio;
  89. m_constant = coordinate1 + m_ratio * coordinate2;
  90. m_impulse = 0.0f;
  91. }
  92. void b2GearJoint::InitVelocityConstraints(const b2TimeStep& step)
  93. {
  94. b2Body* g1 = m_ground1;
  95. b2Body* g2 = m_ground2;
  96. b2Body* b1 = m_body1;
  97. b2Body* b2 = m_body2;
  98. float32 K = 0.0f;
  99. m_J.SetZero();
  100. if (m_revolute1)
  101. {
  102. m_J.angular1 = -1.0f;
  103. K += b1->m_invI;
  104. }
  105. else
  106. {
  107. b2Vec2 ug = b2Mul(g1->GetXForm().R, m_prismatic1->m_localXAxis1);
  108. b2Vec2 r = b2Mul(b1->GetXForm().R, m_localAnchor1 - b1->GetLocalCenter());
  109. float32 crug = b2Cross(r, ug);
  110. m_J.linear1 = -ug;
  111. m_J.angular1 = -crug;
  112. K += b1->m_invMass + b1->m_invI * crug * crug;
  113. }
  114. if (m_revolute2)
  115. {
  116. m_J.angular2 = -m_ratio;
  117. K += m_ratio * m_ratio * b2->m_invI;
  118. }
  119. else
  120. {
  121. b2Vec2 ug = b2Mul(g2->GetXForm().R, m_prismatic2->m_localXAxis1);
  122. b2Vec2 r = b2Mul(b2->GetXForm().R, m_localAnchor2 - b2->GetLocalCenter());
  123. float32 crug = b2Cross(r, ug);
  124. m_J.linear2 = -m_ratio * ug;
  125. m_J.angular2 = -m_ratio * crug;
  126. K += m_ratio * m_ratio * (b2->m_invMass + b2->m_invI * crug * crug);
  127. }
  128. // Compute effective mass.
  129. b2Assert(K > 0.0f);
  130. m_mass = 1.0f / K;
  131. if (step.warmStarting)
  132. {
  133. // Warm starting.
  134. b1->m_linearVelocity += b1->m_invMass * m_impulse * m_J.linear1;
  135. b1->m_angularVelocity += b1->m_invI * m_impulse * m_J.angular1;
  136. b2->m_linearVelocity += b2->m_invMass * m_impulse * m_J.linear2;
  137. b2->m_angularVelocity += b2->m_invI * m_impulse * m_J.angular2;
  138. }
  139. else
  140. {
  141. m_impulse = 0.0f;
  142. }
  143. }
  144. void b2GearJoint::SolveVelocityConstraints(const b2TimeStep& step)
  145. {
  146. B2_NOT_USED(step);
  147. b2Body* b1 = m_body1;
  148. b2Body* b2 = m_body2;
  149. float32 Cdot = m_J.Compute( b1->m_linearVelocity, b1->m_angularVelocity,
  150. b2->m_linearVelocity, b2->m_angularVelocity);
  151. float32 impulse = m_mass * (-Cdot);
  152. m_impulse += impulse;
  153. b1->m_linearVelocity += b1->m_invMass * impulse * m_J.linear1;
  154. b1->m_angularVelocity += b1->m_invI * impulse * m_J.angular1;
  155. b2->m_linearVelocity += b2->m_invMass * impulse * m_J.linear2;
  156. b2->m_angularVelocity += b2->m_invI * impulse * m_J.angular2;
  157. }
  158. bool b2GearJoint::SolvePositionConstraints(float32 baumgarte)
  159. {
  160. B2_NOT_USED(baumgarte);
  161. float32 linearError = 0.0f;
  162. b2Body* b1 = m_body1;
  163. b2Body* b2 = m_body2;
  164. float32 coordinate1, coordinate2;
  165. if (m_revolute1)
  166. {
  167. coordinate1 = m_revolute1->GetJointAngle();
  168. }
  169. else
  170. {
  171. coordinate1 = m_prismatic1->GetJointTranslation();
  172. }
  173. if (m_revolute2)
  174. {
  175. coordinate2 = m_revolute2->GetJointAngle();
  176. }
  177. else
  178. {
  179. coordinate2 = m_prismatic2->GetJointTranslation();
  180. }
  181. float32 C = m_constant - (coordinate1 + m_ratio * coordinate2);
  182. float32 impulse = m_mass * (-C);
  183. b1->m_sweep.c += b1->m_invMass * impulse * m_J.linear1;
  184. b1->m_sweep.a += b1->m_invI * impulse * m_J.angular1;
  185. b2->m_sweep.c += b2->m_invMass * impulse * m_J.linear2;
  186. b2->m_sweep.a += b2->m_invI * impulse * m_J.angular2;
  187. b1->SynchronizeTransform();
  188. b2->SynchronizeTransform();
  189. // TODO_ERIN not implemented
  190. return linearError < b2_linearSlop;
  191. }
  192. b2Vec2 b2GearJoint::GetAnchor1() const
  193. {
  194. return m_body1->GetWorldPoint(m_localAnchor1);
  195. }
  196. b2Vec2 b2GearJoint::GetAnchor2() const
  197. {
  198. return m_body2->GetWorldPoint(m_localAnchor2);
  199. }
  200. b2Vec2 b2GearJoint::GetReactionForce(float32 inv_dt) const
  201. {
  202. // TODO_ERIN not tested
  203. b2Vec2 P = m_impulse * m_J.linear2;
  204. return inv_dt * P;
  205. }
  206. float32 b2GearJoint::GetReactionTorque(float32 inv_dt) const
  207. {
  208. // TODO_ERIN not tested
  209. b2Vec2 r = b2Mul(m_body2->GetXForm().R, m_localAnchor2 - m_body2->GetLocalCenter());
  210. b2Vec2 P = m_impulse * m_J.linear2;
  211. float32 L = m_impulse * m_J.angular2 - b2Cross(r, P);
  212. return inv_dt * L;
  213. }
  214. float32 b2GearJoint::GetRatio() const
  215. {
  216. return m_ratio;
  217. }