2 Bullet Continuous Collision Detection and Physics Library
3 Copyright (c) 2013 Erwin Coumans http://bulletphysics.org
5 This software is provided 'as-is', without any express or implied warranty.
6 In no event will the authors be held liable for any damages 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 freely,
9 subject to the following restrictions:
11 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.
12 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
13 3. This notice may not be removed or altered from any source distribution.
16 ///This file was written by Erwin Coumans
18 #include "btMultiBodyGearConstraint.h"
19 #include "btMultiBody.h"
20 #include "btMultiBodyLinkCollider.h"
21 #include "BulletCollision/CollisionDispatch/btCollisionObject.h"
23 btMultiBodyGearConstraint::btMultiBodyGearConstraint(btMultiBody* bodyA, int linkA, btMultiBody* bodyB, int linkB, const btVector3& pivotInA, const btVector3& pivotInB, const btMatrix3x3& frameInA, const btMatrix3x3& frameInB)
24 : btMultiBodyConstraint(bodyA, bodyB, linkA, linkB, 1, false, MULTIBODY_CONSTRAINT_GEAR),
28 m_relativePositionTarget(0)
32 void btMultiBodyGearConstraint::finalizeMultiDof()
34 allocateJacobiansMultiDof();
36 m_numDofsFinalized = m_jacSizeBoth;
39 btMultiBodyGearConstraint::~btMultiBodyGearConstraint()
43 int btMultiBodyGearConstraint::getIslandIdA() const
49 btMultiBodyLinkCollider* col = m_bodyA->getBaseCollider();
51 return col->getIslandTag();
55 if (m_bodyA->getLink(m_linkA).m_collider)
56 return m_bodyA->getLink(m_linkA).m_collider->getIslandTag();
62 int btMultiBodyGearConstraint::getIslandIdB() const
68 btMultiBodyLinkCollider* col = m_bodyB->getBaseCollider();
70 return col->getIslandTag();
74 if (m_bodyB->getLink(m_linkB).m_collider)
75 return m_bodyB->getLink(m_linkB).m_collider->getIslandTag();
81 void btMultiBodyGearConstraint::createConstraintRows(btMultiBodyConstraintArray& constraintRows,
82 btMultiBodyJacobianData& data,
83 const btContactSolverInfo& infoGlobal)
85 // only positions need to be updated -- data.m_jacobians and force
86 // directions were set in the ctor and never change.
88 if (m_numDofsFinalized != m_jacSizeBoth)
94 if (m_numDofsFinalized != m_jacSizeBoth)
97 if (m_maxAppliedImpulse == 0.f)
100 // note: we rely on the fact that data.m_jacobians are
101 // always initialized to zero by the Constraint ctor
103 unsigned int offsetA = 6 + (m_bodyA->getLink(m_linkA).m_dofOffset + linkDoF);
104 unsigned int offsetB = 6 + (m_bodyB->getLink(m_linkB).m_dofOffset + linkDoF);
106 // row 0: the lower bound
107 jacobianA(0)[offsetA] = 1;
108 jacobianB(0)[offsetB] = m_gearRatio;
110 btScalar posError = 0;
111 const btVector3 dummy(0, 0, 0);
115 int numRows = getNumRows();
117 for (int row = 0; row < numRows; row++)
119 btMultiBodySolverConstraint& constraintRow = constraintRows.expandNonInitializing();
122 btScalar currentPosition = m_bodyA->getJointPosMultiDof(m_linkA)[dof];
123 btScalar currentVelocity = m_bodyA->getJointVelMultiDof(m_linkA)[dof];
126 if (m_gearAuxLink >= 0)
128 auxVel = m_bodyA->getJointVelMultiDof(m_gearAuxLink)[dof];
130 currentVelocity += auxVel;
133 btScalar currentPositionA = m_bodyA->getJointPosMultiDof(m_linkA)[dof];
134 if (m_gearAuxLink >= 0)
136 currentPositionA -= m_bodyA->getJointPosMultiDof(m_gearAuxLink)[dof];
138 btScalar currentPositionB = m_gearRatio * m_bodyA->getJointPosMultiDof(m_linkB)[dof];
139 btScalar diff = currentPositionB + currentPositionA;
140 btScalar desiredPositionDiff = this->m_relativePositionTarget;
141 posError = -m_erp * (desiredPositionDiff - diff);
144 btScalar desiredRelativeVelocity = auxVel;
146 fillMultiBodyConstraint(constraintRow, data, jacobianA(row), jacobianB(row), dummy, dummy, dummy, dummy, posError, infoGlobal, -m_maxAppliedImpulse, m_maxAppliedImpulse, false, 1, false, desiredRelativeVelocity);
148 constraintRow.m_orgConstraint = this;
149 constraintRow.m_orgDofIndex = row;
151 //expect either prismatic or revolute joint type for now
152 btAssert((m_bodyA->getLink(m_linkA).m_jointType == btMultibodyLink::eRevolute) || (m_bodyA->getLink(m_linkA).m_jointType == btMultibodyLink::ePrismatic));
153 switch (m_bodyA->getLink(m_linkA).m_jointType)
155 case btMultibodyLink::eRevolute:
157 constraintRow.m_contactNormal1.setZero();
158 constraintRow.m_contactNormal2.setZero();
159 btVector3 revoluteAxisInWorld = quatRotate(m_bodyA->getLink(m_linkA).m_cachedWorldTransform.getRotation(), m_bodyA->getLink(m_linkA).m_axes[0].m_topVec);
160 constraintRow.m_relpos1CrossNormal = revoluteAxisInWorld;
161 constraintRow.m_relpos2CrossNormal = -revoluteAxisInWorld;
165 case btMultibodyLink::ePrismatic:
167 btVector3 prismaticAxisInWorld = quatRotate(m_bodyA->getLink(m_linkA).m_cachedWorldTransform.getRotation(), m_bodyA->getLink(m_linkA).m_axes[0].m_bottomVec);
168 constraintRow.m_contactNormal1 = prismaticAxisInWorld;
169 constraintRow.m_contactNormal2 = -prismaticAxisInWorld;
170 constraintRow.m_relpos1CrossNormal.setZero();
171 constraintRow.m_relpos2CrossNormal.setZero();