How to Use CFM for Springy Joints in Ammo.js
This article explains how to use Constraint Force Mixing (CFM) and Error Reduction Parameter (ERP) in ammo.js to configure springy, elastic physics joints. You will learn the mechanics behind these two parameters, how they interact to simulate spring-damper systems, and the exact code implementation required to apply them to your constraints.
In ammo.js (a direct port of the Bullet physics engine), constraints are rigid by default. To make a joint behave like a spring, you must adjust two parameters: Constraint Force Mixing (CFM) and the Error Reduction Parameter (ERP).
Understanding CFM and ERP
To simulate elasticity, ammo.js allows joints to be violated slightly and specifies how they should recover.
- CFM (Constraint Force Mixing): Defines the
“softness” of the constraint. A CFM of
0makes the constraint completely rigid. A positive CFM value allows the connected bodies to violate the constraint boundaries, acting like a spring. - ERP (Error Reduction Parameter): Defines how fast
the constraint error (the violation of the joint’s limit) is corrected.
It represents the restoring force. An ERP of
0means no correction (the joint will stretch and never pull back), while an ERP of1means the joint tries to correct all error in a single simulation step.
Mathematical Mapping to Spring Constants
If you have a specific spring stiffness (\(k\)) and damping (\(c\)), you can calculate the corresponding ERP and CFM values using your physics time step (\(h\)):
\[\text{ERP} = \frac{h \cdot k}{h \cdot k + c}\]
\[\text{CFM} = \frac{1}{h \cdot k + c}\]
Implementation in Ammo.js
To apply these parameters to a constraint, such as a
btGeneric6DofConstraint (6 Degrees of Freedom), use the
setParam method.
Below is the JavaScript code to configure a springy axis on a constraint:
// Assuming 'constraint' is an instantiated Ammo.btGeneric6DofConstraint
// and 'Ammo' is the loaded WebAssembly/JS module.
// Bullet/Ammo.js Enum values for parameters
const BT_CONSTRAINT_ERP = 1;
const BT_CONSTRAINT_CFM = 2;
// Target axis:
// 0, 1, 2 correspond to linear translation (X, Y, Z)
// 3, 4, 5 correspond to angular rotation (X, Y, Z)
const AXIS_X = 0;
// Calculate or define your ERP and CFM values
const erpVal = 0.3; // Low ERP for a softer, slower spring rebound
const cfmVal = 0.1; // High CFM to allow joint deviation
// Apply the parameters to the constraint
constraint.setParam(BT_CONSTRAINT_ERP, erpVal, AXIS_X);
constraint.setParam(BT_CONSTRAINT_CFM, cfmVal, AXIS_X);Tips for Tuning Springy Joints
- Keep CFM Small: CFM values should generally be
small (e.g., between
0.001and0.5). Extremely high CFM values will make the joint completely disconnect or behave erratically. - Configure All Active Axes: If you want a 3D spring,
you must apply the ERP and CFM settings to axes
0,1, and2individually. - Use Stop Parameters for Limits: If your joint has
limits enabled, use
BT_CONSTRAINT_STOP_ERP(3) andBT_CONSTRAINT_STOP_CFM(4) to define the springiness specifically when the joint hits its limit boundaries.