Motor Constraint / Block Solver ang. vel. (turn direction)

Please don't post Bullet support questions here, use the above forums instead.
Post Reply
mikeshafer
Posts: 49
Joined: Fri Feb 24, 2012 10:45 am

Motor Constraint / Block Solver ang. vel. (turn direction)

Post by mikeshafer »

Hi there,

I got a lot working and most would ask how the hell I did it doing a lot of recoding and guessing-and-checking. It wasn't pretty. What I have now is a Jacobian solver that seems to work. It's using GJK ONLY for collision (with a ridiculous margin of 0.3 but that's okay because rag doll limbs are better modeled as rounded cubes). Stacking almost works. It stacks for a good 4 seconds before an instability occurs. Instability occurs, but here is the thing, the darn cube turns the wrong direction. I'm going to post my code from my motor constraint (the one that is responsible for all the impulse-based turning) and hope that someone can tell me why my cubes are turning the wrong direction. In other words you have a cube on top of a cube, the top cube starts sliding away and instead of falling like you expect, it turns the other way. You would think you could just negate something, but it turns out it's not that simple. Please help if you can. Thanks. The constraint is based on a block solver from http://erwincoumans.com/ftp/pub/test/ph ... namics.pdf and in bullet (see btSequentialImpulseConstraintSolver::setupContactConstraint). Please note that the code is highly unoptimized. I just want to get it to work correctly first.

Code: Select all

void MEHConstraint::ToMotor(const MEHVector3 &radius1, const MEHVector3 &radius2, const MEHVector3 &normal,
                           MEHPhysicsRigidBody *bodyA, MEHPhysicsRigidBody *bodyB, scalar penetrationVelocity, 
                           scalar erp, scalar cfm)
{
   m_jacobiVectors[0] = normal;
      
   m_jacobiVectors[1] = radius1;
   m_jacobiVectors[1].ToCrossProductWith(normal);
   
   m_jacobiVectors[2] = normal;
   m_jacobiVectors[2] *= (scalar)-1.0;

   m_jacobiVectors[3] = normal;
   m_jacobiVectors[3].ToCrossProductWith(radius2);
      
   scalar num1 = normal.DotProductWith(bodyA->GetVelocity()); // + m_jacobiVectors[1].DotProductWith(bodyA->GetAngularVelocity());
   scalar num2 = 0.0;
   
   if (bodyB)
      num2 = normal.DotProductWith(bodyB->GetVelocity()); // + m_jacobiVectors[3].DotProductWith(bodyB->GetAngularVelocity());

   scalar numerator = (scalar)0.0 - num1 - num2 - penetrationVelocity;
      
   MEHVector3 moment1 = normal;
   moment1.ToCrossProductWith(radius1);
   moment1 *= bodyA->GetInverseInertiaTensor();
   moment1.ToCrossProductWith(normal);
   
   scalar denom1 = (scalar)1.0 / bodyA->GetMass() + moment1.DotProductWith(normal);
   scalar denom2 = 0.0;

   if (bodyB)
   {
      MEHVector3 moment2 = normal;
      moment2.ToCrossProductWith(radius2);
      moment2 *= bodyB->GetInverseInertiaTensor();
      moment2.ToCrossProductWith(normal);
      moment2 *= (scalar)-1.0;
      denom2 = (scalar)1.0 / bodyB->GetMass() + moment2.DotProductWith(normal);
   }   
  
   scalar denominator = denom1 + denom2;
   
   scalar impulse;
   if (MEHISZERO(denominator))
      impulse = 0.0;
   else
      impulse = numerator / denominator;
        
   printf("impulse: %f (numerator = %f, denominator = %f)\r\npenetVel = %f\r\n", impulse, numerator, denominator, penetrationVelocity);

   if (impulse > (scalar)10.0)
      impulse = (scalar)10.0;
   else if (impulse < (scalar)-10.0)
      impulse = (scalar)-10.0;
      
   //m_constraint = m_jacobiVectors[0].DotProductWith(bodyA->GetAngularVelocity()) + impulse;
   m_constraint = impulse;
   
   m_erp = erp;
   m_cfm = cfm;
   m_calcDamping = false;

   m_bodyB = bodyB;

   m_lowerBound = 0.0;
   m_upperBound = (scalar)1e10;
}
Mike
mikeshafer
Posts: 49
Joined: Fri Feb 24, 2012 10:45 am

Re: Motor Constraint / Block Solver ang. vel. (turn directio

Post by mikeshafer »

Well it appears I have fixed it. It wasn't turning the wrong direction. It had to do with the friction constraints. Go figure.

Mike
Post Reply