Locking joints dynamically in position


I want to lock and unlock joints depending on some “triggers”. E.g. if an actor is at position x a joint should be locked, unlocked otherwise. I use D6Joints for all joints, so locking and unlocking joints is normally done by using

setMotion(axis, PxD6Motion::eFREE)

However, this set the joint instantaneously to the zero position (i.e. 0 degree rotation). How can I lock a joint at a particular position, particularly at the position it is at the moment of locking?


Hey Johannes,

I am not familiar with “setMotion(axis, PxD6Motion::eFREE)” to be able to lock the joint as it commands it to be free. You probably also use “setMotion(axis, PxD6Motion:: eLOCKED)”. The later indeed locks the joint to the reference orientation.

We leave joints at eFree or eLimited and lock joints in place with the joint drive. For the joint drive we calculate the current relative position off the actors (as PhysX 3.x does not provide as simple function for that grrrr….). Then we use:
-setdrive(PXD6Drive, PxD6JointDrive) (set the stiffness and damping gains for one axis)
-setDriveVelocity(Drive_pos_vel,Drive_rot_vel) (set the desired velocity)

  • setDrivePosition(DriveTransform) (set the desired orientation).

To get the current relative position off the actors (DriveTransform) we use the following code (you should correct naming and references yourself):
PxTransform a0_lp = JT->getLocalPose(PxJointActorIndex::eACTOR0);
PxTransform a1_lp = JT->getLocalPose(PxJointActorIndex::eACTOR1);

PxTransform a1_if_jt_at_o = a1_lp;

/// where is the actor now ? (pretending that the joint is the origin)
PxTransform T0 = Actor0->getGlobalPose();
PxTransform T1 = Actor1->getGlobalPose();
PxTransform a1_if_jt_at_o_now = (T0.getInverse()*T1).getInverse()*a0_lp;

// find the differenc between the original and current transfom of actor1
DriveTransform = (a1_if_jt_at_o.getInverse()*a1_if_jt_at_o_now).getInverse();

Good luck

Thanks. This is a very good idea and I might use it for some other purpose. Right now I found a solution, where I switch the joint limits to very close positions. With 3.3.1 it now works as expected.