Shihui Guo

Directly Setting A Torque at A Joint In Bullet

In ODE(Open Dynamic Engine), Motors allow you to set joint velocities directly. However, you may instead wish to set the torque or force at a joint instead. These functions do just that. Note that they don't affect the motor, but simply call dBodyAddForce dBodyAddTorque on the bodies attached to it.

void dJointAddHingeTorque( dJointID j, dReal torque )
    dxJointHinge* joint = ( dxJointHinge* )j;
    dVector3 axis;
    dAASSERT( joint );
    checktype( joint, Hinge );

    if ( joint->flags & dJOINT_REVERSE )
        torque = -torque;

    getAxis( joint, axis, joint->axis1 );
    axis[0] *= torque;
    axis[1] *= torque;
    axis[2] *= torque;

    if ( joint->node[0].body != 0 )
        dBodyAddTorque( joint->node[0].body, axis[0], axis[1], axis[2] );
    if ( joint->node[1].body != 0 )
        dBodyAddTorque( joint->node[1].body, -axis[0], -axis[1], -axis[2] );

That is, it applies a torque with magnitude torque, in the direction of the hinge axis, to body 1, and with the same magnitude but in opposite direction to body 2. This function is just a wrapper for dBodyAddTorque.

There is no such implementation in bullet, but surely we can implement it by ourselves. For example if you have a hinge btHingeConstraint* pHinge you may get its axis in world space and apply a torque T to both bodies:

btVector3 hingeAxisLocal = pHinge->getAFrame().getBasis().getColumn(2); // z-axis of constraint frame
btVector3 hingeAxisWorld = pHinge->getRigidBodyA().getWorldTransform().getBasis() * hingeAxisLocal;
btVector3 hingeTorque = T * hingeAxisWorld;

Bullet has a wider feature of complete collision detection, softbody etc, but in modelling rigid body links, it doesn't have advantage over ODE. One of its major issues here is not being stable in the case of large mass ratio (two neighbour objects have significantly different mass, such as a robotic finger linked to an arm).

ODE Source Code
Bullet Forum Post
Bullet Forum Post