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?


1 Answer 1


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.setOrigin(btVector3(btScalar(0.), btScalar(0.), btScalar(0.)));
      btRigidBody* pBodyA = localCreateRigidBody( 0.0, tr, shape); // static body

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

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

      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
      // 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


You must log in to answer this question.

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