Bullet Collision Detection & Physics Library
btMultiBodySphericalJointLimit.cpp
Go to the documentation of this file.
1 /*
2 Bullet Continuous Collision Detection and Physics Library
3 Copyright (c) 2018 Erwin Coumans http://bulletphysics.org
4 
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:
10 
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.
14 */
15 
17 
19 #include "btMultiBody.h"
25 
27  btScalar swingxRange,
28  btScalar swingyRange,
29  btScalar twistRange,
30  btScalar maxAppliedImpulse)
31  : btMultiBodyConstraint(body, body, link, body->getLink(link).m_parent, 3, true, MULTIBODY_CONSTRAINT_SPHERICAL_LIMIT),
32  m_desiredVelocity(0, 0, 0),
33  m_desiredPosition(0,0,0,1),
34  m_use_multi_dof_params(false),
35  m_kd(1., 1., 1.),
36  m_kp(0.2, 0.2, 0.2),
37  m_erp(1),
38  m_rhsClamp(SIMD_INFINITY),
39  m_maxAppliedImpulseMultiDof(maxAppliedImpulse, maxAppliedImpulse, maxAppliedImpulse),
40  m_pivotA(m_bodyA->getLink(link).m_eVector),
41  m_pivotB(m_bodyB->getLink(link).m_eVector),
42  m_swingxRange(swingxRange),
43  m_swingyRange(swingyRange),
44  m_twistRange(twistRange)
45 
46 {
47 
48  m_maxAppliedImpulse = maxAppliedImpulse;
49 }
50 
51 
53 {
55  // note: we rely on the fact that data.m_jacobians are
56  // always initialized to zero by the Constraint ctor
57  int linkDoF = 0;
58  unsigned int offset = 6 + (m_bodyA->getLink(m_linkA).m_dofOffset + linkDoF);
59 
60  // row 0: the lower bound
61  // row 0: the lower bound
62  jacobianA(0)[offset] = 1;
63 
64  jacobianB(1)[offset] = -1;
65 
67 }
68 
69 
71 {
72 }
73 
75 {
76  if (this->m_linkA < 0)
77  {
79  if (col)
80  return col->getIslandTag();
81  }
82  else
83  {
85  {
87  }
88  }
89  return -1;
90 }
91 
93 {
94  if (m_linkB < 0)
95  {
97  if (col)
98  return col->getIslandTag();
99  }
100  else
101  {
103  {
105  }
106  }
107  return -1;
108 }
109 
112  const btContactSolverInfo& infoGlobal)
113 {
114  // only positions need to be updated -- data.m_jacobians and force
115  // directions were set in the ctor and never change.
116 
118  {
120  }
121 
122  //don't crash
124  return;
125 
126 
127  if (m_maxAppliedImpulse == 0.f)
128  return;
129 
130  const btScalar posError = 0;
131  const btVector3 zero(0, 0, 0);
132 
133 
134  btVector3 axis[3] = { btVector3(1, 0, 0), btVector3(0, 1, 0), btVector3(0, 0, 1) };
135 
140 
142  btVector3 vTwist(0,0,1);
143 
144  btVector3 vConeNoTwist = quatRotate(currentQuat, vTwist);
145  vConeNoTwist.normalize();
146  btQuaternion qABCone = shortestArcQuat(vTwist, vConeNoTwist);
147  qABCone.normalize();
148  btQuaternion qABTwist = qABCone.inverse() * currentQuat;
149  qABTwist.normalize();
150  btQuaternion desiredQuat = qABTwist;
151 
152 
153  btQuaternion relRot = currentQuat.inverse() * desiredQuat;
154  btVector3 angleDiff;
156 
157  btScalar limitRanges[3] = {m_swingxRange, m_swingyRange, m_twistRange};
158 
160  btQuaternion qMinTwist = qABTwist;
161  btScalar twistAngle = qABTwist.getAngle();
162 
163  if (twistAngle > SIMD_PI) // long way around. flip quat and recalculate.
164  {
165  qMinTwist = -(qABTwist);
166  twistAngle = qMinTwist.getAngle();
167  }
168  btVector3 vTwistAxis = btVector3(qMinTwist.x(), qMinTwist.y(), qMinTwist.z());
169  if (twistAngle > SIMD_EPSILON)
170  vTwistAxis.normalize();
171 
172  if (vTwistAxis.dot(vTwist)<0)
173  twistAngle*=-1.;
174 
175  angleDiff[2] = twistAngle;
176 
177 
178  for (int row = 0; row < getNumRows(); row++)
179  {
180  btScalar allowed = limitRanges[row];
181  btScalar damp = 1;
182  if((angleDiff[row]>-allowed)&&(angleDiff[row]<allowed))
183  {
184  angleDiff[row]=0;
185  damp=0;
186 
187  } else
188  {
189  if (angleDiff[row]>allowed)
190  {
191  angleDiff[row]-=allowed;
192 
193  }
194  if (angleDiff[row]<-allowed)
195  {
196  angleDiff[row]+=allowed;
197 
198  }
199  }
200 
201 
202  int dof = row;
203 
204  btScalar currentVelocity = m_bodyA->getJointVelMultiDof(m_linkA)[dof];
205  btScalar desiredVelocity = this->m_desiredVelocity[row];
206 
207  double kd = m_use_multi_dof_params ? m_kd[row % 3] : m_kd[0];
208  btScalar velocityError = (desiredVelocity - currentVelocity) * kd;
209 
210  btMatrix3x3 frameAworld;
211  frameAworld.setIdentity();
212  frameAworld = m_bodyA->localFrameToWorld(m_linkA, frameAworld);
213  btScalar posError = 0;
214  {
217  {
219  {
220  btVector3 constraintNormalAng = frameAworld.getColumn(row % 3);
221  double kp = m_use_multi_dof_params ? m_kp[row % 3] : m_kp[0];
222  posError = kp*angleDiff[row % 3];
223  double max_applied_impulse = m_use_multi_dof_params ? m_maxAppliedImpulseMultiDof[row % 3] : m_maxAppliedImpulse;
224  //should multiply by time step
225  //max_applied_impulse *= infoGlobal.m_timeStep
226 
227  double min_applied_impulse = -max_applied_impulse;
228 
229 
230  if (posError>0)
231  max_applied_impulse=0;
232  else
233  min_applied_impulse=0;
234 
235  if (btFabs(posError)>SIMD_EPSILON)
236  {
237  btMultiBodySolverConstraint& constraintRow = constraintRows.expandNonInitializing();
238  fillMultiBodyConstraint(constraintRow, data, 0, 0, constraintNormalAng,
239  zero, zero, zero,//pure angular, so zero out linear parts
240  posError,
241  infoGlobal,
242  min_applied_impulse, max_applied_impulse, true,
243  1.0, false, 0, 0,
244  damp);
245  constraintRow.m_orgConstraint = this;
246  constraintRow.m_orgDofIndex = row;
247  }
248  break;
249  }
250  default:
251  {
252  btAssert(0);
253  }
254  };
255  }
256  }
257 }
258 
259 
261 {
262  btTransform tr;
263  tr.setIdentity();
264  if (m_bodyB)
265  {
267  tr.setOrigin(pivotBworld);
268  drawer->drawTransform(tr, 0.1);
269  }
270 }
static btVector3 vTwist(1, 0, 0)
@ MULTIBODY_CONSTRAINT_SPHERICAL_LIMIT
btQuaternion shortestArcQuat(const btVector3 &v0, const btVector3 &v1)
Definition: btQuaternion.h:940
btVector3 quatRotate(const btQuaternion &rotation, const btVector3 &v)
Definition: btQuaternion.h:926
#define SIMD_PI
Definition: btScalar.h:526
float btScalar
The btScalar type abstracts floating point numbers, to easily switch between double and single floati...
Definition: btScalar.h:314
btScalar btFabs(btScalar x)
Definition: btScalar.h:497
#define SIMD_INFINITY
Definition: btScalar.h:544
#define SIMD_EPSILON
Definition: btScalar.h:543
#define btAssert(x)
Definition: btScalar.h:153
int getIslandTag() const
static bool matrixToEulerXYZ(const btMatrix3x3 &mat, btVector3 &xyz)
The btIDebugDraw interface class allows hooking up a debug renderer to visually debug simulations.
Definition: btIDebugDraw.h:27
virtual void drawTransform(const btTransform &transform, btScalar orthoLen)
Definition: btIDebugDraw.h:163
The btMatrix3x3 class implements a 3x3 rotation matrix, to perform linear algebra in combination with...
Definition: btMatrix3x3.h:50
void setIdentity()
Set the matrix to the identity.
Definition: btMatrix3x3.h:323
btVector3 getColumn(int i) const
Get a column of the matrix as a vector.
Definition: btMatrix3x3.h:142
btScalar * jacobianA(int row)
btScalar * jacobianB(int row)
btScalar fillMultiBodyConstraint(btMultiBodySolverConstraint &solverConstraint, btMultiBodyJacobianData &data, btScalar *jacOrgA, btScalar *jacOrgB, const btVector3 &constraintNormalAng, const btVector3 &constraintNormalLin, const btVector3 &posAworld, const btVector3 &posBworld, btScalar posError, const btContactSolverInfo &infoGlobal, btScalar lowerLimit, btScalar upperLimit, bool angConstraint=false, btScalar relaxation=1.f, bool isFriction=false, btScalar desiredVelocity=0, btScalar cfmSlip=0, btScalar damping=1.0)
virtual void debugDraw(class btIDebugDraw *drawer)
virtual void createConstraintRows(btMultiBodyConstraintArray &constraintRows, btMultiBodyJacobianData &data, const btContactSolverInfo &infoGlobal)
btMultiBodySphericalJointLimit(btMultiBody *body, int link, btScalar swingxRange, btScalar swingyRange, btScalar twistRange, btScalar maxAppliedImpulse)
This file was written by Erwin Coumans.
btMatrix3x3 localFrameToWorld(int i, const btMatrix3x3 &local_frame) const
btScalar * getJointPosMultiDof(int i)
const btMultibodyLink & getLink(int index) const
Definition: btMultiBody.h:114
btVector3 localPosToWorld(int i, const btVector3 &local_pos) const
const btMultiBodyLinkCollider * getBaseCollider() const
Definition: btMultiBody.h:128
btScalar * getJointVelMultiDof(int i)
const btScalar & x() const
Return the x value.
Definition: btQuadWord.h:113
const btScalar & z() const
Return the z value.
Definition: btQuadWord.h:117
const btScalar & y() const
Return the y value.
Definition: btQuadWord.h:115
The btQuaternion implements quaternion to perform linear algebra rotations in combination with btMatr...
Definition: btQuaternion.h:50
btScalar getAngle() const
Return the angle [0, 2Pi] of rotation represented by this quaternion.
Definition: btQuaternion.h:468
btQuaternion inverse() const
Return the inverse of this quaternion.
Definition: btQuaternion.h:497
btQuaternion & normalize()
Normalize the quaternion Such that x^2 + y^2 + z^2 +w^2 = 1.
Definition: btQuaternion.h:385
The btTransform class supports rigid transforms with only translation and rotation and no scaling/she...
Definition: btTransform.h:30
void setIdentity()
Set this transformation to the identity.
Definition: btTransform.h:167
void setOrigin(const btVector3 &origin)
Set the translational element.
Definition: btTransform.h:147
btVector3 can be used to represent 3D points and vectors.
Definition: btVector3.h:82
btVector3 & normalize()
Normalize this vector x^2 + y^2 + z^2 = 1.
Definition: btVector3.h:303
btScalar dot(const btVector3 &v) const
Return the dot product.
Definition: btVector3.h:229
1D constraint along a normal axis between bodyA and bodyB. It can be combined to solve contact and fr...
btMultiBodyConstraint * m_orgConstraint