An introduction to New6Dof constraints
A physics joint connects one physics body to another (or to a fixed point in space), constraining how the body(s) can move.
For instance, a door might swing on hinges. In simulation, the hinges would be represented by a joint with a single degree of freedom (DOF): rotation around the axis of the hinges. Such joints are called hinge joints.
Or a door might slide along a track. In that case, the track would be represented by a joint that’s free to translate, but only along the axis of the track. To simulate this, you’d use a joint with one translational DOF, called a slider joint.
Or imagine a pen holder mounted on a ball-and-socket: it can freely turn and twist to any orientation, but the ball end can’t leave the socket. To simulate this, you’d use a joint with 3 rotational DOFs, called a point-to-point joint.
Some physics joints can connect soft bodies or portions thereof. In Libbulletjme, a joint that can only connect rigid bodies is called a constraint.
New6Dof
is a constraint
that replaces the older SixDofJoint
and SixDofSpringJoint
constraints.
As its name implies,
New6Dof
can simulate up to 6 DOFs.
It’s so versatile, it can also emulate 4 other constraints:
It might be the only physics joint you’ll ever need.
Features
A New6Dof
constraint can be instantiated
either as a double-ended constraint (connecting 2 rigid bodies)
or as a single-ended constraint (connecting a rigid body to a fixed point).
New6Dof
can simulate up to 3 rotation DOFs
and up to 3 translation DOFs, so an instance
can potentially rotate or slide on any axis or axes.
By default, the translation DOFs are locked at a zero,
while the rotation DOFs are free to assume any angular value.
In other words, it defaults to a point-to-point joint.
By locking and/or unlocking DOFs, you simulate different types of joints:
-
For a hinge joint, lock all but one of the rotation DOFs.
-
For a slider joint, lock all 3 rotation DOFs and unlock one of the translation DOFs.
In addition to being locked or free, there’s a 3rd possibility; a DOF can be limited: allowed to assume values only in a specific range. By imposing limits, you can prevent a door from sliding or swinging beyond certain points.
In addition to limits, New6Dof
also implements motors, servos, and springs:
-
Using a motor, you can apply forces to open or close a door.
-
Using a servo, you can cause a door to move smoothly to a specific position, as if under remote control.
-
Using a spring, you can cause a door to automatically return to a neutral position when released.
You can also:
-
specify the order in which axis rotations are combined,
-
disable a constraint temporarily,
-
configure the amount of applied impulse that will break (permanently disable) a constraint,
-
customize the number of iterations used to solve a constraint, and
-
(for a double-ended constraint) configure whether collisions between the end bodies should be simulated or not.
Caveats
A New6Dof
constraint
can only connect rigid bodies (including vehicles):
no ghost objects, characters, multibodies, or soft bodies.
For a constraint to be effective:
-
the constraint and its connected body(s) must all be added to the same physics space, and
-
at least one of its ends must be a dynamic rigid body.
Even when locked, constraints exhibit some softness. A strong force, torque, or impulse can drag a locked DOF out of position or overpower the limits of a limited DOF. This is because the contact-and-constraint solver doesn’t immediately correct all position errors in physics joints. During each simulation step, it corrects only a fraction of each error, by default, 20%. This fraction is the solver’s error-reduction parameter (ERP).
For faster corrections (with more risk of instability) increase the ERP. For instance, to correct 90% of joint-position errors during each simulation step:
physicsSpace.getSolverInfo().setJointErp(0.9f); // default=0.2
Constructors
The ends of a double-ended physics joint are denoted "A" and "B", based on their order of appearance in the constructor.
By convention, the body connected to a single-ended
New6Dof
is denoted "B".
In effect, the "A" end of a single-ended constraint
connects to the physics space itself.
Certain other Constraint
subclasses use the opposite end-naming convention for single-ended constraints.
|
There are 2 New6Dof
constructors,
one for a single-ended constraint:
new New6Dof(rigidBodyB, pivotInB, pivotInWorld, rotInB, rotInWorld,
rotationOrder);
and one for a double-ended constraint:
new New6Dof(rigidBodyA, rigidBodyB, pivotInA, pivotInB,
rotInA, rotInB, rotationOrder);
The "pivot" and "rot" parameters define coordinate systems used in the constraint.
Consider that a constraint potentially involves 4 coordinate systems:
-
the local coordinate system of the rigid body at the "B" end,
-
B’s notion of the constraint coordinate system,
-
the coordinate system of the "A" end, which is either:
-
the local coordinate system of the rigid body (in a double-ended constraint) or else
-
the physics-space coordinate system (in a single-ended constraint), AND
-
-
A’s notion of the constraint coordinate system.
If all 6 DOFs were locked, then satisfying the constraint would involve making system #2 match system #4 exactly.
For a constraint that rotates, the pivot point should be the origin of the constraint’s coordinate system.
Each "pivot" parameter is defines the origin of a coordinate system,
and each "rot" parameter defines its orientation.
(Each "pivot" is an offset vector, and each "rot" is a
rotation matrix.)
To transform a location vector from system #2 to system #1,
one would multiply by the rotInB
matrix and then add the pivotInB
vector.
To transform a location vector from system #4 to system #3,
one would multiply by the rotInA
(or rotInWorld
) matrix
and then add the pivotInA
(or pivotInWorld
) vector.
To reduce complexity, it helps to initially position
the constraint and its end body(s) so that their local coordinate systems
all share the same orientation.
Then you can specify Matrix3f.IDENTITY for each "rot" parameter.
|
Example apps
HelloJoint (also in Kotlin) is a SPORT app
that demonstrates a single-ended New6Dof
constraint.
Things to notice while running the app:
-
The gray paddle is kinematic, moved by the mouse.
-
A magenta ball hangs from a single-ended point-to-point joint, indicated by the red arrow.
-
If you strike the ball with the paddle, it swings around, maintaining a constant distance from the pivot point.
HelloDoubleEnded (also in Kotlin) is a SPORT app
that demonstrates a double-ended New6Dof
constraint.
Things to notice while running the app:
-
The gray paddle is moved by the mouse.
-
A double-ended point-to-point joint (indicated by red and green arrows) connects the ball to the paddle.
-
If the paddle moves fast enough, the red and green arrows no longer meet. Even though all 3 translation DOFs are locked, the paddle’s motion drags them out of position.
Limits
The degrees of freedom are indexed as follows…
-
0: translation parallel to the X axis
-
1: translation parallel to the Y axis
-
2: translation parallel to the Z axis
-
3: rotation around the X axis
-
4: rotation around the Y axis
-
5: rotation around the Z axis
To impose limits on a DOF that is locked or free,
use the set()
method with lowerLimit < upperLimit.
constraint.set(MotorParam.LowerLimit, dofIndex, lowerLimit);
constraint.set(MotorParam.UpperLimit, dofIndex, upperLimit);
To lock a DOF that is limited or free, set both limits to the same value.
To free a DOF that is limited or locked,
use the set()
method with lowerLimit > upperLimit.
(For a free DOF, the precise limit values have no significance.)
The limits of a rotational DOF are measured in radians. |
HelloLimit (also in Kotlin) is a SPORT app
that demonstrates a single-ended New6Dof
constraint
with limited translation DOFs.
The joint’s translations are limited,
confining the ball to a horizontal square centered on the origin.
Motors
Motors are used to apply forces to a constraint.
In New6Dof
, each DOF has its own motor, which is disabled by default.
HelloMotor (also in Kotlin) is a SPORT app
that demonstrates a double-ended New6Dof
with its Y-rotation motor enabled.
-
All DOFs except Y rotation are locked at zero.
-
Y rotation is limited between 0 and 1.2 radians.
-
The pivot is located just to the left of the door.
-
Press Space bar to reverse the direction of the motor.
The force (or torque) applied by each motor is limited.
To change this limit,
use the set()
method with MotorParam.MaxMotorForce
:
constraint.set(MotorParam.MaxMotorForce, dofIndex, force);
For translation DOFs, the default maximum force is zero! |
Servos
It’s difficult to position a constraint using motors alone.
Without positional feedback,
the constraint tends to keep accelerating until some limit is hit.
Servos implement feedback, allowing for smooth, gradual motion.
In New6Dof
, each DOF has its own servo, which is disabled by default.
For a servo to be effective, its corresponding motor must also be enabled. |
HelloServo (also in Kotlin) is a SPORT app
that demonstrates a double-ended New6Dof
constraint
with its Y-rotation servo enabled.
-
All DOFs except Y rotation are locked at zero.
-
Y rotation is limited between 0 and 1.2 radians.
-
The pivot is located just to the left of the door.
-
Press 1 to gradually open the door all the way.
-
Press 3 to gradually rotate the door to the one-third open position.
-
Press 4 to gradually close the door all the way.
To adjust a servo’s rate of motion,
use the set()
method with MotorParam.TargetVelocity
:
constraint.set(MotorParam.TargetVelocity, dofIndex, velocity);
The default target velocity is zero! |
Springs
By default, a DOF that’s limited or free has no preferred position. To change this, enable the DOF’s spring and set its stiffness to a positive value. If desired, you can also configure the spring’s equilibrium value and damping ratio.
HelloSpring (also in Kotlin) is a SPORT app that demonstrates a single-ended constraint with springs.
Things to notice while running the app:
-
The joint’s X and Z translation DOFs are free.
-
Springs on the X and Z translation DOFs cause the ball to accelerate toward its equilibrium location.
-
Since there’s no damping, the ball tends to oscillate.
Summary
-
Physics joints constrain the motion of connected bodies.
-
In Libbulletjme, joints for rigid bodies are called constraints.
-
New6Dof
is a versatile constraint with 6 degrees of freedom (DOFs). It can emulate hinges, sliders, and point-to-point joints. -
Constraint DOFs will exhibit some softness, even when locked. This can be mitigated by increasing the error-reduction parameter (ERP).
-
New6Dof
also implements limits, motors, servos, and springs.