From Physics Simulation Wiki
Bullet engine (as of version 2.82) supports 6 types of constraints, as described below.
Examples using constraints can be found at Demos/ConstraintDemo
A sliding constraint example can be found at Demos/ForkLiftDemo
A ragdoll example using cone twist constraints can be found at Demos/RagdollDemo
If we enable the DebugDrawing
Point-to-Point (Ball socket)
The point to point constraint, also known as ball socket joint, limits the translation so that the local pivot points of two rigidbodies match in worldspace. A chain of rigidbodies can be connected using this constraint.
The point-to-point constraint uses the following constructors:
btPoint2PointConstraint(btRigidBody& rbA, const btVector3& pivotInA); btPoint2PointConstraint(btRigidBody& rbA, btRigidBody& rbB, const btVector3& pivotInA, const btVector3& pivotInB);
Hinge constraint, or revolute joint, restricts two additional angular degrees of freedom, so the body can only rotate around one axis, the hinge axis. This can be useful to represent doors or wheels rotating around one axis. Limits and motor can be specified for the hinge.
The hinge constraint uses the following constructors:
btHingeConstraint(btRigidBody& rbA, const btTransform& rbAFrame, bool useReferenceFrameA = false)
btHingeConstraint(btRigidBody& rbA, const btVector3& pivotInA, btVector3& axisInA, bool useReferenceFrameA = false);
The pivot and axis in A/B are all expressed in local coordinate of Object A/B. For a door, even if we lay down the door, axisInA/B is still (0,1,0).
As long as the constraint structure doesn't change, the local coordinates won't change.
btHingeConstraint(btRigidBody& rbA,btRigidBody& rbB, const btVector3& pivotInA, const btVector3& pivotInB, btVector3& axisInA, btVector3& axisInB, bool useReferenceFrameA = false);
Normally two axis in hinge-connected objects should align and point to the same direction, such as a door. But you can set two axis as different vectors.
btHingeConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& rbAFrame, const btTransform& rbBFrame, bool useReferenceFrameA = false)
Hinge rotation limits
The hinge constraint has the following method for setting its limits:
void setLimit(btScalar low, btScalar high, btScalar softness=0.9f, btScalar_biasFactor=0.3f, btScalar relaxationFactor=1.0f)
The slider constraint allows the body to rotate around one axis and translate along this axis.
The slider twist uses the following constructor:
btSliderConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB, bool useLinearReferenceFrameA);
The cone twist is a special point-to-point constraint that adds cone and twist axis limits. The x-axis serves as twist axis. It is useful when creating ragdolls, specially for limbs like the upper arm.
The cone twist constraint uses the following constructors:
btConeTwistConstraint(btRigidBody& rbA, const btTransform& rbAFrame) btConeTwistConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& rbAFrame, const btTransform& rbBFrame)
It may be a little tricky to set up the constraint limit for cone twist constraint:
void btConeTwistConstraint::setLimit(btScalar _swingSpan1,btScalar _swingSpan2,btScalar _twistSpan,btScalar _softness = 1.f, btScalar _biasFactor = 0.3f, btScalar _relaxationFactor = 1.0f )
Let's see the examples in Ragdoll Demo to better understand:
//Spline-Head Joint coneC->setLimit(M_PI_4, M_PI_4, M_PI_2); //Hip-Thigh Joint coneC->setLimit(M_PI_4, M_PI_4, 0); // Torso-Shoulder Joint coneC->setLimit(M_PI_2, M_PI_2, 0);
From the definition, we know the first two limits are cone limits, while the last one is twist limit. First, let's discuss about the twist limit, for the head, you are supposed to turn your head Left/Right, which equals pi/2 (What you doing is twisting along the axis). While your head can lean foward, or backward, Left/Right to your shoulder, about pi/4, it accounts for first two parameters.
For your upper arm and thigh, they are not supposed to twist along the bone, leading to third parameter as 0. But the space your upper arm/thigh can occupy is a cone, and the angles for this cone is pi/4 (thigh) and pi/2 (upper arm).
Generic 6 Degrees of Freedom (DoF) Constraint
This generic constraint can emulate a variety of standard constraints, by configuring each of the 6 degrees of freedom (DoF). The first 3 DoF axis are linear axis, which represent translation of rigid bodies, and the latter 3 axis represent the angular motion. Each axis can be either locked, free or limited. Note that several combinations that include free and/or limited angular degrees of freedom are undefined.
The generic 6DoF constraint has the following constructor:
btGeneric6DofConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB, bool useLinearReferenceFrameA)
On construction of a new btGeneric6DofConstraint, all axis are locked. The limits of the 6DoF constraint are set through 4 vectors. Two represent the upper and lower limits of the angular motion and the other two do the same for the linear motion.
btGeneric6DofConstraint has the following methods for setting limits:
void setLinearLowerLimit(const btVector3& linearLower) void setLinearUpperLimit(const btVector3& linearUpper) void setAngularLowerLimit(const btVector3& angularLower) void setAngularUpperLimit(const btVector3& angularUpper)
For each axis, if
- lower limit = upper limit
The axis is locked
- lower limit < upper limit
The axis is limited between the specified values
- lower limit > upper limit
The axis is free and has no limits
The fixed constraint has all the degrees of freedom locked.
It uses the following constructor:
btFixedConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB);