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.

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

  1. Keep CFM Small: CFM values should generally be small (e.g., between 0.001 and 0.5). Extremely high CFM values will make the joint completely disconnect or behave erratically.
  2. Configure All Active Axes: If you want a 3D spring, you must apply the ERP and CFM settings to axes 0, 1, and 2 individually.
  3. Use Stop Parameters for Limits: If your joint has limits enabled, use BT_CONSTRAINT_STOP_ERP (3) and BT_CONSTRAINT_STOP_CFM (4) to define the springiness specifically when the joint hits its limit boundaries.