Changeset 2882 for code/trunk/src/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp
- Timestamp:
- Mar 31, 2009, 8:05:51 PM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
code/trunk/src/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp
r2662 r2882 20 20 */ 21 21 22 23 22 #include "btGeneric6DofConstraint.h" 24 23 #include "BulletDynamics/Dynamics/btRigidBody.h" … … 27 26 28 27 28 #define D6_USE_OBSOLETE_METHOD false 29 //----------------------------------------------------------------------------- 30 31 btGeneric6DofConstraint::btGeneric6DofConstraint() 32 :btTypedConstraint(D6_CONSTRAINT_TYPE), 33 m_useLinearReferenceFrameA(true), 34 m_useSolveConstraintObsolete(D6_USE_OBSOLETE_METHOD) 35 { 36 } 37 38 //----------------------------------------------------------------------------- 39 40 btGeneric6DofConstraint::btGeneric6DofConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB, bool useLinearReferenceFrameA) 41 : btTypedConstraint(D6_CONSTRAINT_TYPE, rbA, rbB) 42 , m_frameInA(frameInA) 43 , m_frameInB(frameInB), 44 m_useLinearReferenceFrameA(useLinearReferenceFrameA), 45 m_useSolveConstraintObsolete(D6_USE_OBSOLETE_METHOD) 46 { 47 48 } 49 //----------------------------------------------------------------------------- 50 51 29 52 #define GENERIC_D6_DISABLE_WARMSTARTING 1 53 54 //----------------------------------------------------------------------------- 30 55 31 56 btScalar btGetMatrixElem(const btMatrix3x3& mat, int index); … … 37 62 } 38 63 64 //----------------------------------------------------------------------------- 65 39 66 ///MatrixToEulerXYZ from http://www.geometrictools.com/LibFoundation/Mathematics/Wm4Matrix3.inl.html 40 67 bool matrixToEulerXYZ(const btMatrix3x3& mat,btVector3& xyz); 41 68 bool matrixToEulerXYZ(const btMatrix3x3& mat,btVector3& xyz) 42 69 { 43 // // rot = cy*cz -cy*sz sy 44 // // cz*sx*sy+cx*sz cx*cz-sx*sy*sz -cy*sx 45 // // -cx*cz*sy+sx*sz cz*sx+cx*sy*sz cx*cy 46 // 47 48 if (btGetMatrixElem(mat,2) < btScalar(1.0)) 49 { 50 if (btGetMatrixElem(mat,2) > btScalar(-1.0)) 51 { 52 xyz[0] = btAtan2(-btGetMatrixElem(mat,5),btGetMatrixElem(mat,8)); 53 xyz[1] = btAsin(btGetMatrixElem(mat,2)); 54 xyz[2] = btAtan2(-btGetMatrixElem(mat,1),btGetMatrixElem(mat,0)); 55 return true; 56 } 57 else 58 { 59 // WARNING. Not unique. XA - ZA = -atan2(r10,r11) 60 xyz[0] = -btAtan2(btGetMatrixElem(mat,3),btGetMatrixElem(mat,4)); 61 xyz[1] = -SIMD_HALF_PI; 62 xyz[2] = btScalar(0.0); 63 return false; 64 } 70 // // rot = cy*cz -cy*sz sy 71 // // cz*sx*sy+cx*sz cx*cz-sx*sy*sz -cy*sx 72 // // -cx*cz*sy+sx*sz cz*sx+cx*sy*sz cx*cy 73 // 74 75 btScalar fi = btGetMatrixElem(mat,2); 76 if (fi < btScalar(1.0f)) 77 { 78 if (fi > btScalar(-1.0f)) 79 { 80 xyz[0] = btAtan2(-btGetMatrixElem(mat,5),btGetMatrixElem(mat,8)); 81 xyz[1] = btAsin(btGetMatrixElem(mat,2)); 82 xyz[2] = btAtan2(-btGetMatrixElem(mat,1),btGetMatrixElem(mat,0)); 83 return true; 65 84 } 66 85 else 67 86 { 68 // WARNING. Not unique. XAngle + ZAngle = atan2(r10,r11) 69 xyz[0] = btAtan2(btGetMatrixElem(mat,3),btGetMatrixElem(mat,4)); 70 xyz[1] = SIMD_HALF_PI; 71 xyz[2] = 0.0; 72 73 } 74 75 87 // WARNING. Not unique. XA - ZA = -atan2(r10,r11) 88 xyz[0] = -btAtan2(btGetMatrixElem(mat,3),btGetMatrixElem(mat,4)); 89 xyz[1] = -SIMD_HALF_PI; 90 xyz[2] = btScalar(0.0); 91 return false; 92 } 93 } 94 else 95 { 96 // WARNING. Not unique. XAngle + ZAngle = atan2(r10,r11) 97 xyz[0] = btAtan2(btGetMatrixElem(mat,3),btGetMatrixElem(mat,4)); 98 xyz[1] = SIMD_HALF_PI; 99 xyz[2] = 0.0; 100 } 76 101 return false; 77 102 } 78 103 79 80 81 104 //////////////////////////// btRotationalLimitMotor //////////////////////////////////// 82 83 105 84 106 int btRotationalLimitMotor::testLimitValue(btScalar test_value) … … 105 127 m_currentLimit = 0;//Free from violation 106 128 return 0; 107 108 } 109 129 130 } 131 132 //----------------------------------------------------------------------------- 110 133 111 134 btScalar btRotationalLimitMotor::solveAngularLimits( 112 113 btRigidBody * body0, btRigidBody * body1)114 { 115 116 117 118 135 btScalar timeStep,btVector3& axis,btScalar jacDiagABInv, 136 btRigidBody * body0, btSolverBody& bodyA, btRigidBody * body1, btSolverBody& bodyB) 137 { 138 if (needApplyTorques()==false) return 0.0f; 139 140 btScalar target_velocity = m_targetVelocity; 141 btScalar maxMotorForce = m_maxMotorForce; 119 142 120 143 //current error correction 121 if (m_currentLimit!=0) 122 { 123 target_velocity = -m_ERP*m_currentLimitError/(timeStep); 124 maxMotorForce = m_maxLimitForce; 125 } 126 127 maxMotorForce *= timeStep; 128 129 // current velocity difference 130 btVector3 vel_diff = body0->getAngularVelocity(); 131 if (body1) 132 { 133 vel_diff -= body1->getAngularVelocity(); 134 } 135 136 137 138 btScalar rel_vel = axis.dot(vel_diff); 144 if (m_currentLimit!=0) 145 { 146 target_velocity = -m_ERP*m_currentLimitError/(timeStep); 147 maxMotorForce = m_maxLimitForce; 148 } 149 150 maxMotorForce *= timeStep; 151 152 // current velocity difference 153 154 btVector3 angVelA; 155 bodyA.getAngularVelocity(angVelA); 156 btVector3 angVelB; 157 bodyB.getAngularVelocity(angVelB); 158 159 btVector3 vel_diff; 160 vel_diff = angVelA-angVelB; 161 162 163 164 btScalar rel_vel = axis.dot(vel_diff); 139 165 140 166 // correction velocity 141 142 143 144 145 146 147 167 btScalar motor_relvel = m_limitSoftness*(target_velocity - m_damping*rel_vel); 168 169 170 if ( motor_relvel < SIMD_EPSILON && motor_relvel > -SIMD_EPSILON ) 171 { 172 return 0.0f;//no need for applying force 173 } 148 174 149 175 150 176 // correction impulse 151 177 btScalar unclippedMotorImpulse = (1+m_bounce)*motor_relvel*jacDiagABInv; 152 178 153 179 // clip correction impulse 154 155 156 157 158 159 160 161 162 163 164 180 btScalar clippedMotorImpulse; 181 182 ///@todo: should clip against accumulated impulse 183 if (unclippedMotorImpulse>0.0f) 184 { 185 clippedMotorImpulse = unclippedMotorImpulse > maxMotorForce? maxMotorForce: unclippedMotorImpulse; 186 } 187 else 188 { 189 clippedMotorImpulse = unclippedMotorImpulse < -maxMotorForce ? -maxMotorForce: unclippedMotorImpulse; 190 } 165 191 166 192 167 193 // sort with accumulated impulses 168 btScalar lo = btScalar(-1e30); 169 btScalar hi = btScalar(1e30); 170 171 btScalar oldaccumImpulse = m_accumulatedImpulse; 172 btScalar sum = oldaccumImpulse + clippedMotorImpulse; 173 m_accumulatedImpulse = sum > hi ? btScalar(0.) : sum < lo ? btScalar(0.) : sum; 174 175 clippedMotorImpulse = m_accumulatedImpulse - oldaccumImpulse; 176 177 178 179 btVector3 motorImp = clippedMotorImpulse * axis; 180 181 182 body0->applyTorqueImpulse(motorImp); 183 if (body1) body1->applyTorqueImpulse(-motorImp); 184 185 return clippedMotorImpulse; 194 btScalar lo = btScalar(-1e30); 195 btScalar hi = btScalar(1e30); 196 197 btScalar oldaccumImpulse = m_accumulatedImpulse; 198 btScalar sum = oldaccumImpulse + clippedMotorImpulse; 199 m_accumulatedImpulse = sum > hi ? btScalar(0.) : sum < lo ? btScalar(0.) : sum; 200 201 clippedMotorImpulse = m_accumulatedImpulse - oldaccumImpulse; 202 203 btVector3 motorImp = clippedMotorImpulse * axis; 204 205 //body0->applyTorqueImpulse(motorImp); 206 //body1->applyTorqueImpulse(-motorImp); 207 208 bodyA.applyImpulse(btVector3(0,0,0), body0->getInvInertiaTensorWorld()*axis,clippedMotorImpulse); 209 bodyB.applyImpulse(btVector3(0,0,0), body1->getInvInertiaTensorWorld()*axis,-clippedMotorImpulse); 210 211 212 return clippedMotorImpulse; 186 213 187 214 … … 190 217 //////////////////////////// End btRotationalLimitMotor //////////////////////////////////// 191 218 219 220 221 192 222 //////////////////////////// btTranslationalLimitMotor //////////////////////////////////// 223 224 225 int btTranslationalLimitMotor::testLimitValue(int limitIndex, btScalar test_value) 226 { 227 btScalar loLimit = m_lowerLimit[limitIndex]; 228 btScalar hiLimit = m_upperLimit[limitIndex]; 229 if(loLimit > hiLimit) 230 { 231 m_currentLimit[limitIndex] = 0;//Free from violation 232 m_currentLimitError[limitIndex] = btScalar(0.f); 233 return 0; 234 } 235 236 if (test_value < loLimit) 237 { 238 m_currentLimit[limitIndex] = 2;//low limit violation 239 m_currentLimitError[limitIndex] = test_value - loLimit; 240 return 2; 241 } 242 else if (test_value> hiLimit) 243 { 244 m_currentLimit[limitIndex] = 1;//High limit violation 245 m_currentLimitError[limitIndex] = test_value - hiLimit; 246 return 1; 247 }; 248 249 m_currentLimit[limitIndex] = 0;//Free from violation 250 m_currentLimitError[limitIndex] = btScalar(0.f); 251 return 0; 252 } // btTranslationalLimitMotor::testLimitValue() 253 254 //----------------------------------------------------------------------------- 255 193 256 btScalar btTranslationalLimitMotor::solveLinearAxis( 194 btScalar timeStep, 195 btScalar jacDiagABInv, 196 btRigidBody& body1,const btVector3 &pointInA, 197 btRigidBody& body2,const btVector3 &pointInB, 198 int limit_index, 199 const btVector3 & axis_normal_on_a, 200 const btVector3 & anchorPos) 201 { 202 203 ///find relative velocity 204 // btVector3 rel_pos1 = pointInA - body1.getCenterOfMassPosition(); 205 // btVector3 rel_pos2 = pointInB - body2.getCenterOfMassPosition(); 206 btVector3 rel_pos1 = anchorPos - body1.getCenterOfMassPosition(); 207 btVector3 rel_pos2 = anchorPos - body2.getCenterOfMassPosition(); 208 209 btVector3 vel1 = body1.getVelocityInLocalPoint(rel_pos1); 210 btVector3 vel2 = body2.getVelocityInLocalPoint(rel_pos2); 211 btVector3 vel = vel1 - vel2; 212 213 btScalar rel_vel = axis_normal_on_a.dot(vel); 214 215 216 217 /// apply displacement correction 218 219 //positional error (zeroth order error) 220 btScalar depth = -(pointInA - pointInB).dot(axis_normal_on_a); 221 btScalar lo = btScalar(-1e30); 222 btScalar hi = btScalar(1e30); 223 224 btScalar minLimit = m_lowerLimit[limit_index]; 225 btScalar maxLimit = m_upperLimit[limit_index]; 226 227 //handle the limits 228 if (minLimit < maxLimit) 229 { 230 { 231 if (depth > maxLimit) 232 { 233 depth -= maxLimit; 234 lo = btScalar(0.); 235 236 } 237 else 238 { 239 if (depth < minLimit) 240 { 241 depth -= minLimit; 242 hi = btScalar(0.); 243 } 244 else 245 { 246 return 0.0f; 247 } 248 } 249 } 250 } 251 252 btScalar normalImpulse= m_limitSoftness*(m_restitution*depth/timeStep - m_damping*rel_vel) * jacDiagABInv; 253 254 255 256 257 btScalar oldNormalImpulse = m_accumulatedImpulse[limit_index]; 258 btScalar sum = oldNormalImpulse + normalImpulse; 259 m_accumulatedImpulse[limit_index] = sum > hi ? btScalar(0.) : sum < lo ? btScalar(0.) : sum; 260 normalImpulse = m_accumulatedImpulse[limit_index] - oldNormalImpulse; 261 262 btVector3 impulse_vector = axis_normal_on_a * normalImpulse; 263 body1.applyImpulse( impulse_vector, rel_pos1); 264 body2.applyImpulse(-impulse_vector, rel_pos2); 265 return normalImpulse; 257 btScalar timeStep, 258 btScalar jacDiagABInv, 259 btRigidBody& body1,btSolverBody& bodyA,const btVector3 &pointInA, 260 btRigidBody& body2,btSolverBody& bodyB,const btVector3 &pointInB, 261 int limit_index, 262 const btVector3 & axis_normal_on_a, 263 const btVector3 & anchorPos) 264 { 265 266 ///find relative velocity 267 // btVector3 rel_pos1 = pointInA - body1.getCenterOfMassPosition(); 268 // btVector3 rel_pos2 = pointInB - body2.getCenterOfMassPosition(); 269 btVector3 rel_pos1 = anchorPos - body1.getCenterOfMassPosition(); 270 btVector3 rel_pos2 = anchorPos - body2.getCenterOfMassPosition(); 271 272 btVector3 vel1; 273 bodyA.getVelocityInLocalPointObsolete(rel_pos1,vel1); 274 btVector3 vel2; 275 bodyB.getVelocityInLocalPointObsolete(rel_pos2,vel2); 276 btVector3 vel = vel1 - vel2; 277 278 btScalar rel_vel = axis_normal_on_a.dot(vel); 279 280 281 282 /// apply displacement correction 283 284 //positional error (zeroth order error) 285 btScalar depth = -(pointInA - pointInB).dot(axis_normal_on_a); 286 btScalar lo = btScalar(-1e30); 287 btScalar hi = btScalar(1e30); 288 289 btScalar minLimit = m_lowerLimit[limit_index]; 290 btScalar maxLimit = m_upperLimit[limit_index]; 291 292 //handle the limits 293 if (minLimit < maxLimit) 294 { 295 { 296 if (depth > maxLimit) 297 { 298 depth -= maxLimit; 299 lo = btScalar(0.); 300 301 } 302 else 303 { 304 if (depth < minLimit) 305 { 306 depth -= minLimit; 307 hi = btScalar(0.); 308 } 309 else 310 { 311 return 0.0f; 312 } 313 } 314 } 315 } 316 317 btScalar normalImpulse= m_limitSoftness*(m_restitution*depth/timeStep - m_damping*rel_vel) * jacDiagABInv; 318 319 320 321 322 btScalar oldNormalImpulse = m_accumulatedImpulse[limit_index]; 323 btScalar sum = oldNormalImpulse + normalImpulse; 324 m_accumulatedImpulse[limit_index] = sum > hi ? btScalar(0.) : sum < lo ? btScalar(0.) : sum; 325 normalImpulse = m_accumulatedImpulse[limit_index] - oldNormalImpulse; 326 327 btVector3 impulse_vector = axis_normal_on_a * normalImpulse; 328 //body1.applyImpulse( impulse_vector, rel_pos1); 329 //body2.applyImpulse(-impulse_vector, rel_pos2); 330 331 btVector3 ftorqueAxis1 = rel_pos1.cross(axis_normal_on_a); 332 btVector3 ftorqueAxis2 = rel_pos2.cross(axis_normal_on_a); 333 bodyA.applyImpulse(axis_normal_on_a*body1.getInvMass(), body1.getInvInertiaTensorWorld()*ftorqueAxis1,normalImpulse); 334 bodyB.applyImpulse(axis_normal_on_a*body2.getInvMass(), body2.getInvInertiaTensorWorld()*ftorqueAxis2,-normalImpulse); 335 336 337 338 339 return normalImpulse; 266 340 } 267 341 268 342 //////////////////////////// btTranslationalLimitMotor //////////////////////////////////// 269 343 270 271 btGeneric6DofConstraint::btGeneric6DofConstraint()272 :btTypedConstraint(D6_CONSTRAINT_TYPE),273 m_useLinearReferenceFrameA(true)274 {275 }276 277 btGeneric6DofConstraint::btGeneric6DofConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB, bool useLinearReferenceFrameA)278 : btTypedConstraint(D6_CONSTRAINT_TYPE, rbA, rbB)279 , m_frameInA(frameInA)280 , m_frameInB(frameInB),281 m_useLinearReferenceFrameA(useLinearReferenceFrameA)282 {283 284 }285 286 287 288 289 290 344 void btGeneric6DofConstraint::calculateAngleInfo() 291 345 { 292 346 btMatrix3x3 relative_frame = m_calculatedTransformA.getBasis().inverse()*m_calculatedTransformB.getBasis(); 293 294 347 matrixToEulerXYZ(relative_frame,m_calculatedAxisAngleDiff); 295 296 297 298 348 // in euler angle mode we do not actually constrain the angular velocity 299 // along the axes axis[0] and axis[2] (although we do use axis[1]) : 300 // 301 // to get constrain w2-w1 along ...not 302 // ------ --------------------- ------ 303 // d(angle[0])/dt = 0 ax[1] x ax[2] ax[0] 304 // d(angle[1])/dt = 0 ax[1] 305 // d(angle[2])/dt = 0 ax[0] x ax[1] ax[2] 306 // 307 // constraining w2-w1 along an axis 'a' means that a'*(w2-w1)=0. 308 // to prove the result for angle[0], write the expression for angle[0] from 309 // GetInfo1 then take the derivative. to prove this for angle[2] it is 310 // easier to take the euler rate expression for d(angle[2])/dt with respect 311 // to the components of w and set that to 0. 312 349 // along the axes axis[0] and axis[2] (although we do use axis[1]) : 350 // 351 // to get constrain w2-w1 along ...not 352 // ------ --------------------- ------ 353 // d(angle[0])/dt = 0 ax[1] x ax[2] ax[0] 354 // d(angle[1])/dt = 0 ax[1] 355 // d(angle[2])/dt = 0 ax[0] x ax[1] ax[2] 356 // 357 // constraining w2-w1 along an axis 'a' means that a'*(w2-w1)=0. 358 // to prove the result for angle[0], write the expression for angle[0] from 359 // GetInfo1 then take the derivative. to prove this for angle[2] it is 360 // easier to take the euler rate expression for d(angle[2])/dt with respect 361 // to the components of w and set that to 0. 313 362 btVector3 axis0 = m_calculatedTransformB.getBasis().getColumn(0); 314 363 btVector3 axis2 = m_calculatedTransformA.getBasis().getColumn(2); … … 318 367 m_calculatedAxis[2] = axis0.cross(m_calculatedAxis[1]); 319 368 320 321 // if(m_debugDrawer) 322 // { 323 // 324 // char buff[300]; 325 // sprintf(buff,"\n X: %.2f ; Y: %.2f ; Z: %.2f ", 326 // m_calculatedAxisAngleDiff[0], 327 // m_calculatedAxisAngleDiff[1], 328 // m_calculatedAxisAngleDiff[2]); 329 // m_debugDrawer->reportErrorWarning(buff); 330 // } 331 332 } 369 m_calculatedAxis[0].normalize(); 370 m_calculatedAxis[1].normalize(); 371 m_calculatedAxis[2].normalize(); 372 373 } 374 375 //----------------------------------------------------------------------------- 333 376 334 377 void btGeneric6DofConstraint::calculateTransforms() 335 378 { 336 m_calculatedTransformA = m_rbA.getCenterOfMassTransform() * m_frameInA; 337 m_calculatedTransformB = m_rbB.getCenterOfMassTransform() * m_frameInB; 338 339 calculateAngleInfo(); 340 } 341 379 m_calculatedTransformA = m_rbA.getCenterOfMassTransform() * m_frameInA; 380 m_calculatedTransformB = m_rbB.getCenterOfMassTransform() * m_frameInB; 381 calculateLinearInfo(); 382 calculateAngleInfo(); 383 } 384 385 //----------------------------------------------------------------------------- 342 386 343 387 void btGeneric6DofConstraint::buildLinearJacobian( 344 345 346 { 347 388 btJacobianEntry & jacLinear,const btVector3 & normalWorld, 389 const btVector3 & pivotAInW,const btVector3 & pivotBInW) 390 { 391 new (&jacLinear) btJacobianEntry( 348 392 m_rbA.getCenterOfMassTransform().getBasis().transpose(), 349 393 m_rbB.getCenterOfMassTransform().getBasis().transpose(), … … 355 399 m_rbB.getInvInertiaDiagLocal(), 356 400 m_rbB.getInvMass()); 357 358 } 401 } 402 403 //----------------------------------------------------------------------------- 359 404 360 405 void btGeneric6DofConstraint::buildAngularJacobian( 361 362 { 363 406 btJacobianEntry & jacAngular,const btVector3 & jointAxisW) 407 { 408 new (&jacAngular) btJacobianEntry(jointAxisW, 364 409 m_rbA.getCenterOfMassTransform().getBasis().transpose(), 365 410 m_rbB.getCenterOfMassTransform().getBasis().transpose(), … … 369 414 } 370 415 416 //----------------------------------------------------------------------------- 417 371 418 bool btGeneric6DofConstraint::testAngularLimitMotor(int axis_index) 372 419 { 373 btScalar angle = m_calculatedAxisAngleDiff[axis_index]; 374 375 //test limits 376 m_angularLimits[axis_index].testLimitValue(angle); 377 return m_angularLimits[axis_index].needApplyTorques(); 378 } 420 btScalar angle = m_calculatedAxisAngleDiff[axis_index]; 421 //test limits 422 m_angularLimits[axis_index].testLimitValue(angle); 423 return m_angularLimits[axis_index].needApplyTorques(); 424 } 425 426 //----------------------------------------------------------------------------- 379 427 380 428 void btGeneric6DofConstraint::buildJacobian() 381 429 { 382 383 // Clear accumulated impulses for the next simulation step 384 m_linearLimits.m_accumulatedImpulse.setValue(btScalar(0.), btScalar(0.), btScalar(0.)); 385 int i; 386 for(i = 0; i < 3; i++) 387 { 388 m_angularLimits[i].m_accumulatedImpulse = btScalar(0.); 389 } 390 //calculates transform 391 calculateTransforms(); 392 393 // const btVector3& pivotAInW = m_calculatedTransformA.getOrigin(); 394 // const btVector3& pivotBInW = m_calculatedTransformB.getOrigin(); 395 calcAnchorPos(); 396 btVector3 pivotAInW = m_AnchorPos; 397 btVector3 pivotBInW = m_AnchorPos; 398 399 // not used here 400 // btVector3 rel_pos1 = pivotAInW - m_rbA.getCenterOfMassPosition(); 401 // btVector3 rel_pos2 = pivotBInW - m_rbB.getCenterOfMassPosition(); 402 403 btVector3 normalWorld; 404 //linear part 405 for (i=0;i<3;i++) 406 { 407 if (m_linearLimits.isLimited(i)) 408 { 409 if (m_useLinearReferenceFrameA) 410 normalWorld = m_calculatedTransformA.getBasis().getColumn(i); 411 else 412 normalWorld = m_calculatedTransformB.getBasis().getColumn(i); 413 414 buildLinearJacobian( 415 m_jacLinear[i],normalWorld , 416 pivotAInW,pivotBInW); 417 418 } 419 } 420 421 // angular part 422 for (i=0;i<3;i++) 423 { 424 //calculates error angle 425 if (testAngularLimitMotor(i)) 426 { 427 normalWorld = this->getAxis(i); 428 // Create angular atom 429 buildAngularJacobian(m_jacAng[i],normalWorld); 430 } 431 } 432 433 434 } 435 436 437 void btGeneric6DofConstraint::solveConstraint(btScalar timeStep) 438 { 439 m_timeStep = timeStep; 440 441 //calculateTransforms(); 442 443 int i; 444 445 // linear 446 447 btVector3 pointInA = m_calculatedTransformA.getOrigin(); 448 btVector3 pointInB = m_calculatedTransformB.getOrigin(); 449 450 btScalar jacDiagABInv; 451 btVector3 linear_axis; 452 for (i=0;i<3;i++) 453 { 454 if (m_linearLimits.isLimited(i)) 455 { 456 jacDiagABInv = btScalar(1.) / m_jacLinear[i].getDiagonal(); 457 458 if (m_useLinearReferenceFrameA) 459 linear_axis = m_calculatedTransformA.getBasis().getColumn(i); 460 else 461 linear_axis = m_calculatedTransformB.getBasis().getColumn(i); 462 463 m_linearLimits.solveLinearAxis( 464 m_timeStep, 465 jacDiagABInv, 466 m_rbA,pointInA, 467 m_rbB,pointInB, 468 i,linear_axis, m_AnchorPos); 469 470 } 471 } 472 473 // angular 474 btVector3 angular_axis; 475 btScalar angularJacDiagABInv; 476 for (i=0;i<3;i++) 477 { 478 if (m_angularLimits[i].needApplyTorques()) 479 { 480 481 // get axis 482 angular_axis = getAxis(i); 483 484 angularJacDiagABInv = btScalar(1.) / m_jacAng[i].getDiagonal(); 485 486 m_angularLimits[i].solveAngularLimits(m_timeStep,angular_axis,angularJacDiagABInv, &m_rbA,&m_rbB); 487 } 488 } 489 } 430 if (m_useSolveConstraintObsolete) 431 { 432 433 // Clear accumulated impulses for the next simulation step 434 m_linearLimits.m_accumulatedImpulse.setValue(btScalar(0.), btScalar(0.), btScalar(0.)); 435 int i; 436 for(i = 0; i < 3; i++) 437 { 438 m_angularLimits[i].m_accumulatedImpulse = btScalar(0.); 439 } 440 //calculates transform 441 calculateTransforms(); 442 443 // const btVector3& pivotAInW = m_calculatedTransformA.getOrigin(); 444 // const btVector3& pivotBInW = m_calculatedTransformB.getOrigin(); 445 calcAnchorPos(); 446 btVector3 pivotAInW = m_AnchorPos; 447 btVector3 pivotBInW = m_AnchorPos; 448 449 // not used here 450 // btVector3 rel_pos1 = pivotAInW - m_rbA.getCenterOfMassPosition(); 451 // btVector3 rel_pos2 = pivotBInW - m_rbB.getCenterOfMassPosition(); 452 453 btVector3 normalWorld; 454 //linear part 455 for (i=0;i<3;i++) 456 { 457 if (m_linearLimits.isLimited(i)) 458 { 459 if (m_useLinearReferenceFrameA) 460 normalWorld = m_calculatedTransformA.getBasis().getColumn(i); 461 else 462 normalWorld = m_calculatedTransformB.getBasis().getColumn(i); 463 464 buildLinearJacobian( 465 m_jacLinear[i],normalWorld , 466 pivotAInW,pivotBInW); 467 468 } 469 } 470 471 // angular part 472 for (i=0;i<3;i++) 473 { 474 //calculates error angle 475 if (testAngularLimitMotor(i)) 476 { 477 normalWorld = this->getAxis(i); 478 // Create angular atom 479 buildAngularJacobian(m_jacAng[i],normalWorld); 480 } 481 } 482 483 } 484 } 485 486 //----------------------------------------------------------------------------- 487 488 void btGeneric6DofConstraint::getInfo1 (btConstraintInfo1* info) 489 { 490 if (m_useSolveConstraintObsolete) 491 { 492 info->m_numConstraintRows = 0; 493 info->nub = 0; 494 } else 495 { 496 //prepare constraint 497 calculateTransforms(); 498 info->m_numConstraintRows = 0; 499 info->nub = 6; 500 int i; 501 //test linear limits 502 for(i = 0; i < 3; i++) 503 { 504 if(m_linearLimits.needApplyForce(i)) 505 { 506 info->m_numConstraintRows++; 507 info->nub--; 508 } 509 } 510 //test angular limits 511 for (i=0;i<3 ;i++ ) 512 { 513 if(testAngularLimitMotor(i)) 514 { 515 info->m_numConstraintRows++; 516 info->nub--; 517 } 518 } 519 } 520 } 521 522 //----------------------------------------------------------------------------- 523 524 void btGeneric6DofConstraint::getInfo2 (btConstraintInfo2* info) 525 { 526 btAssert(!m_useSolveConstraintObsolete); 527 int row = setLinearLimits(info); 528 setAngularLimits(info, row); 529 } 530 531 //----------------------------------------------------------------------------- 532 533 int btGeneric6DofConstraint::setLinearLimits(btConstraintInfo2* info) 534 { 535 btGeneric6DofConstraint * d6constraint = this; 536 int row = 0; 537 //solve linear limits 538 btRotationalLimitMotor limot; 539 for (int i=0;i<3 ;i++ ) 540 { 541 if(m_linearLimits.needApplyForce(i)) 542 { // re-use rotational motor code 543 limot.m_bounce = btScalar(0.f); 544 limot.m_currentLimit = m_linearLimits.m_currentLimit[i]; 545 limot.m_currentLimitError = m_linearLimits.m_currentLimitError[i]; 546 limot.m_damping = m_linearLimits.m_damping; 547 limot.m_enableMotor = m_linearLimits.m_enableMotor[i]; 548 limot.m_ERP = m_linearLimits.m_restitution; 549 limot.m_hiLimit = m_linearLimits.m_upperLimit[i]; 550 limot.m_limitSoftness = m_linearLimits.m_limitSoftness; 551 limot.m_loLimit = m_linearLimits.m_lowerLimit[i]; 552 limot.m_maxLimitForce = btScalar(0.f); 553 limot.m_maxMotorForce = m_linearLimits.m_maxMotorForce[i]; 554 limot.m_targetVelocity = m_linearLimits.m_targetVelocity[i]; 555 btVector3 axis = m_calculatedTransformA.getBasis().getColumn(i); 556 row += get_limit_motor_info2(&limot, &m_rbA, &m_rbB, info, row, axis, 0); 557 } 558 } 559 return row; 560 } 561 562 //----------------------------------------------------------------------------- 563 564 int btGeneric6DofConstraint::setAngularLimits(btConstraintInfo2 *info, int row_offset) 565 { 566 btGeneric6DofConstraint * d6constraint = this; 567 int row = row_offset; 568 //solve angular limits 569 for (int i=0;i<3 ;i++ ) 570 { 571 if(d6constraint->getRotationalLimitMotor(i)->needApplyTorques()) 572 { 573 btVector3 axis = d6constraint->getAxis(i); 574 row += get_limit_motor_info2( 575 d6constraint->getRotationalLimitMotor(i), 576 &m_rbA, 577 &m_rbB, 578 info,row,axis,1); 579 } 580 } 581 582 return row; 583 } 584 585 //----------------------------------------------------------------------------- 586 587 void btGeneric6DofConstraint::solveConstraintObsolete(btSolverBody& bodyA,btSolverBody& bodyB,btScalar timeStep) 588 { 589 if (m_useSolveConstraintObsolete) 590 { 591 592 593 m_timeStep = timeStep; 594 595 //calculateTransforms(); 596 597 int i; 598 599 // linear 600 601 btVector3 pointInA = m_calculatedTransformA.getOrigin(); 602 btVector3 pointInB = m_calculatedTransformB.getOrigin(); 603 604 btScalar jacDiagABInv; 605 btVector3 linear_axis; 606 for (i=0;i<3;i++) 607 { 608 if (m_linearLimits.isLimited(i)) 609 { 610 jacDiagABInv = btScalar(1.) / m_jacLinear[i].getDiagonal(); 611 612 if (m_useLinearReferenceFrameA) 613 linear_axis = m_calculatedTransformA.getBasis().getColumn(i); 614 else 615 linear_axis = m_calculatedTransformB.getBasis().getColumn(i); 616 617 m_linearLimits.solveLinearAxis( 618 m_timeStep, 619 jacDiagABInv, 620 m_rbA,bodyA,pointInA, 621 m_rbB,bodyB,pointInB, 622 i,linear_axis, m_AnchorPos); 623 624 } 625 } 626 627 // angular 628 btVector3 angular_axis; 629 btScalar angularJacDiagABInv; 630 for (i=0;i<3;i++) 631 { 632 if (m_angularLimits[i].needApplyTorques()) 633 { 634 635 // get axis 636 angular_axis = getAxis(i); 637 638 angularJacDiagABInv = btScalar(1.) / m_jacAng[i].getDiagonal(); 639 640 m_angularLimits[i].solveAngularLimits(m_timeStep,angular_axis,angularJacDiagABInv, &m_rbA,bodyA,&m_rbB,bodyB); 641 } 642 } 643 } 644 } 645 646 //----------------------------------------------------------------------------- 490 647 491 648 void btGeneric6DofConstraint::updateRHS(btScalar timeStep) 492 649 { 493 (void)timeStep; 494 495 } 650 (void)timeStep; 651 652 } 653 654 //----------------------------------------------------------------------------- 496 655 497 656 btVector3 btGeneric6DofConstraint::getAxis(int axis_index) const 498 657 { 499 return m_calculatedAxis[axis_index]; 500 } 658 return m_calculatedAxis[axis_index]; 659 } 660 661 //----------------------------------------------------------------------------- 501 662 502 663 btScalar btGeneric6DofConstraint::getAngle(int axis_index) const 503 664 { 504 return m_calculatedAxisAngleDiff[axis_index]; 505 } 665 return m_calculatedAxisAngleDiff[axis_index]; 666 } 667 668 //----------------------------------------------------------------------------- 506 669 507 670 void btGeneric6DofConstraint::calcAnchorPos(void) … … 524 687 } // btGeneric6DofConstraint::calcAnchorPos() 525 688 689 //----------------------------------------------------------------------------- 690 691 void btGeneric6DofConstraint::calculateLinearInfo() 692 { 693 m_calculatedLinearDiff = m_calculatedTransformB.getOrigin() - m_calculatedTransformA.getOrigin(); 694 m_calculatedLinearDiff = m_calculatedTransformA.getBasis().inverse() * m_calculatedLinearDiff; 695 for(int i = 0; i < 3; i++) 696 { 697 m_linearLimits.testLimitValue(i, m_calculatedLinearDiff[i]); 698 } 699 } // btGeneric6DofConstraint::calculateLinearInfo() 700 701 //----------------------------------------------------------------------------- 702 703 int btGeneric6DofConstraint::get_limit_motor_info2( 704 btRotationalLimitMotor * limot, 705 btRigidBody * body0, btRigidBody * body1, 706 btConstraintInfo2 *info, int row, btVector3& ax1, int rotational) 707 { 708 int srow = row * info->rowskip; 709 int powered = limot->m_enableMotor; 710 int limit = limot->m_currentLimit; 711 if (powered || limit) 712 { // if the joint is powered, or has joint limits, add in the extra row 713 btScalar *J1 = rotational ? info->m_J1angularAxis : info->m_J1linearAxis; 714 btScalar *J2 = rotational ? info->m_J2angularAxis : 0; 715 J1[srow+0] = ax1[0]; 716 J1[srow+1] = ax1[1]; 717 J1[srow+2] = ax1[2]; 718 if(rotational) 719 { 720 J2[srow+0] = -ax1[0]; 721 J2[srow+1] = -ax1[1]; 722 J2[srow+2] = -ax1[2]; 723 } 724 if((!rotational) && limit) 725 { 726 btVector3 ltd; // Linear Torque Decoupling vector 727 btVector3 c = m_calculatedTransformB.getOrigin() - body0->getCenterOfMassPosition(); 728 ltd = c.cross(ax1); 729 info->m_J1angularAxis[srow+0] = ltd[0]; 730 info->m_J1angularAxis[srow+1] = ltd[1]; 731 info->m_J1angularAxis[srow+2] = ltd[2]; 732 733 c = m_calculatedTransformB.getOrigin() - body1->getCenterOfMassPosition(); 734 ltd = -c.cross(ax1); 735 info->m_J2angularAxis[srow+0] = ltd[0]; 736 info->m_J2angularAxis[srow+1] = ltd[1]; 737 info->m_J2angularAxis[srow+2] = ltd[2]; 738 } 739 // if we're limited low and high simultaneously, the joint motor is 740 // ineffective 741 if (limit && (limot->m_loLimit == limot->m_hiLimit)) powered = 0; 742 info->m_constraintError[srow] = btScalar(0.f); 743 if (powered) 744 { 745 info->cfm[srow] = 0.0f; 746 if(!limit) 747 { 748 info->m_constraintError[srow] += limot->m_targetVelocity; 749 info->m_lowerLimit[srow] = -limot->m_maxMotorForce; 750 info->m_upperLimit[srow] = limot->m_maxMotorForce; 751 } 752 } 753 if(limit) 754 { 755 btScalar k = info->fps * limot->m_ERP; 756 if(!rotational) 757 { 758 info->m_constraintError[srow] += k * limot->m_currentLimitError; 759 } 760 else 761 { 762 info->m_constraintError[srow] += -k * limot->m_currentLimitError; 763 } 764 info->cfm[srow] = 0.0f; 765 if (limot->m_loLimit == limot->m_hiLimit) 766 { // limited low and high simultaneously 767 info->m_lowerLimit[srow] = -SIMD_INFINITY; 768 info->m_upperLimit[srow] = SIMD_INFINITY; 769 } 770 else 771 { 772 if (limit == 1) 773 { 774 info->m_lowerLimit[srow] = 0; 775 info->m_upperLimit[srow] = SIMD_INFINITY; 776 } 777 else 778 { 779 info->m_lowerLimit[srow] = -SIMD_INFINITY; 780 info->m_upperLimit[srow] = 0; 781 } 782 // deal with bounce 783 if (limot->m_bounce > 0) 784 { 785 // calculate joint velocity 786 btScalar vel; 787 if (rotational) 788 { 789 vel = body0->getAngularVelocity().dot(ax1); 790 if (body1) 791 vel -= body1->getAngularVelocity().dot(ax1); 792 } 793 else 794 { 795 vel = body0->getLinearVelocity().dot(ax1); 796 if (body1) 797 vel -= body1->getLinearVelocity().dot(ax1); 798 } 799 // only apply bounce if the velocity is incoming, and if the 800 // resulting c[] exceeds what we already have. 801 if (limit == 1) 802 { 803 if (vel < 0) 804 { 805 btScalar newc = -limot->m_bounce* vel; 806 if (newc > info->m_constraintError[srow]) 807 info->m_constraintError[srow] = newc; 808 } 809 } 810 else 811 { 812 if (vel > 0) 813 { 814 btScalar newc = -limot->m_bounce * vel; 815 if (newc < info->m_constraintError[srow]) 816 info->m_constraintError[srow] = newc; 817 } 818 } 819 } 820 } 821 } 822 return 1; 823 } 824 else return 0; 825 } 826 827 //----------------------------------------------------------------------------- 828 //----------------------------------------------------------------------------- 829 //-----------------------------------------------------------------------------
Note: See TracChangeset
for help on using the changeset viewer.