I am trying to implement a ragdoll in Bullet Physics, mimicking one I created in a Maya plugin which uses PhysX. I have everything 1:1 besides constraint motors.
In physX, motors simply have linear and angular damping/stiffness and a target represented as a mat4 (position and rotation).
Ideally I'd be using btConeTwist
but it doesn't seem to have linear/angular motor settings so I have switched to btGeneric6DofConstraint
which does provide accessability, which I am setting as follows, I think it's correct...
// Angular
joint.dof6->getRotationalLimitMotor(0)->m_damping = joint.drive_angularDamping;
joint.dof6->getRotationalLimitMotor(1)->m_damping = joint.drive_angularDamping;
joint.dof6->getRotationalLimitMotor(2)->m_damping = joint.drive_angularDamping;
joint.dof6->getRotationalLimitMotor(0)->m_limitSoftness = (1 / joint.drive_angularStiffness);
joint.dof6->getRotationalLimitMotor(1)->m_limitSoftness = (1 / joint.drive_angularStiffness);
joint.dof6->getRotationalLimitMotor(2)->m_limitSoftness = (1 / joint.drive_angularStiffness);
// Linear
joint.dof6->getTranslationalLimitMotor()->m_damping = joint.drive_linearDampening;
joint.dof6->getTranslationalLimitMotor()->m_limitSoftness = (1 / joint.drive_linearStiffness);
The problem is I can not find any way to set the motor target. It must have one, that is a motor's sole purpose, rotating/translating a rigid body towards a target rotation/translation.
The Bullet docs are lacking to say the least, any insight or advice would be incredible.
You should be using the btGeneric6DofSpring2Constraint
. It's the most flexible and feature rich out of all of Bullets constraints as well as the most stable from my experience. From what I can tell you understand how to setup the constraint frames and the rest of the constraint, so I'll skip that part. Setup is the same as all the rest.
It's quite straight forward from there. Let's start with a simple target velocity for the constraint. You have to enable the motor, set the max motor force, and finally the target velocity. The index corresponds to the axis in the constraint. Linear X, Y, and Z are 0, 1, and 2. Rotational X, Y, and Z are 3, 4, and 5. The target velocity for rotation is in radians a second. So this example creates a rotational motor around the X axis in the constraint frame that is attempting to move at 180 degrees a second.
pConstraint->enableMotor(3, true);
pConstraint->setMaxMotorForce(3, 10000.0);
pConstraint->setTargetVelocity(3, M_PI);
A servo, or a motor with a target, is slightly more complicated but not much. It's all the same as the previous section but with two additions. First, enabling the servo, and setting the servo target. Note, you must still set a target velocity in order for it to work. The servo target is in radians for rotation. So in this example the servo is trying to get to a rotation of 90 degrees around the constraint X axis.
pConstraint->enableMotor(3, true);
pConstraint->setMaxMotorForce(3, 10000.0);
pConstraint->setTargetVelocity(3, 10.0);
pConstraint->setServo(3, true);
pConstraint->setServoTarget(3, M_PI / 2.0);
It should be noted the btGeneric6DofSpring2Constraint
uses Euler angles and thus is subject to gimbal lock. One axis is constrained to [-PI / 2, PI / 2] instead of the full 360 degrees of motion. This axis is the middle axis in the rotation order. By default the order is X, Y, Z so the Y axis is constrained. If this is a problem you can use one of the other rotation orders.
The constraint code is decently commented. I think you'll find answers to any other questions in there. The Bullet forums also have several conversations on constraints which are useful.