5
\$\begingroup\$

I have a very simple (and maybe too primitive to post here but I’ll try anyway :P) question about Bullet constraints. What are arguments const btTransform &frameInA, const btTransform &frameInB, bool useLinearReferenceFrameA of Bullet’s btGeneric6DofConstraint? Documentation doesn’t say anything about them.

I think (but am not entirely sure) that the first two are Pivot Point Transformations relative to mass-center of two rigid bodies (in their own coordinate systems). And thus they should always point to the same point in world-space. Is that true?

Also, what is Linear Reference Frame?

\$\endgroup\$

1 Answer 1

3
\$\begingroup\$

Looking on the Bullet Physics forums I found a comment from Erwin (the author):

FrameA and FrameB are constraint frames in local spaces A and B respectively Limits give the allowable range of movement if frameB in frameA space (or vice versa if useLinearReferenceFrameA == false)

He then supplies some sample code to try:

{ // create a generic 6DOF constraint with spring that has rest length 10
      // and connected to dynamic body at point (-5, 0, 0)
      btScalar springRestLen(10.f);
      btScalar pivotOffset(-5.f);
      btScalar springRange(7.f); // allowed oscillation range
      btTransform tr;
      tr.setIdentity();
      tr.setOrigin(btVector3(btScalar(0.), btScalar(0.), btScalar(0.)));
      tr.getBasis().setEulerZYX(0,0,0);
      btRigidBody* pBodyA = localCreateRigidBody( 0.0, tr, shape); // static body
      pBodyA->setActivationState(DISABLE_DEACTIVATION);

      btTransform frameInA;
      frameInA = btTransform::getIdentity();
      frameInA.setOrigin(btVector3(btScalar(0.), btScalar(0.), btScalar(0.))); // in A coordinate systam

      tr.setIdentity();
      tr.setOrigin(btVector3(btScalar(springRestLen - pivotOffset), btScalar(0.), btScalar(0.))); // this is (15, 0, 0)
      tr.getBasis().setEulerZYX(0,0,0);
      btRigidBody* pBodyB = localCreateRigidBody(1.0, tr, shape); // dynamic body
      pBodyB->setActivationState(DISABLE_DEACTIVATION);

      btTransform frameInB;
      frameInB = btTransform::getIdentity();
      frameInB.setOrigin(btVector3(pivotOffset, btScalar(0.), btScalar(0.))); // in B coordinate systam

      btGeneric6DofSpringConstraint* pGen6DOFSpring = new btGeneric6DofSpringConstraint(*pBodyA, *pBodyB, frameInA, frameInB, true);
      // in WCS we should have offset between origin of frameB and frameA.
      // It should be equal to springRestLen, so we should set proper limits
      // we set useLinearReferenceFrameA to true, so limits wil be in A coordinate system
      pGen6DOFSpring->setLinearUpperLimit(btVector3(springRestLen + springRange, 0., 0.));
      pGen6DOFSpring->setLinearLowerLimit(btVector3(springRestLen - springRange, 0., 0.));
      // lock all rorations
      pGen6DOFSpring->setAngularLowerLimit(btVector3(0.f, 0.f, 0.f));
      pGen6DOFSpring->setAngularUpperLimit(btVector3(0.f, 0.f, 0.f));
      // add constraint to world 
      m_dynamicsWorld->addConstraint(pGen6DOFSpring, true);
      // draw constraint frames and limits
      pGen6DOFSpring->setDbgDrawSize(btScalar(5.f));
      // enable spring
      pGen6DOFSpring->enableSpring(0, true);
      pGen6DOFSpring->setStiffness(0, 39.478f); // period 1 sec for !kG body
      pGen6DOFSpring->setDamping(0, 0.01f); // add some damping
      // constraint force mixing prevents "locking" on limits
      pGen6DOFSpring->setParam(BT_CONSTRAINT_STOP_CFM, 1.0e-5f, 5); 
      pGen6DOFSpring->setEquilibriumPoint(); // set current position as equilibrium point
   }

The relevant forum post can be found here

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .