How Ammo.js Resolves Conflicting Rigid Body Constraints

This article explains how Ammo.js, a WebAssembly port of the Bullet Physics engine, handles situations where multiple, opposing constraints are applied to a single rigid body. You will learn about the underlying mathematical solver, the iterative process used to find physical compromises, and how parameters like ERP and CFM prevent simulation instability when constraints clash.

The Sequential Impulse Solver

At its core, Ammo.js utilizes Bullet’s Sequential Impulse (SI) solver, which is a specialized implementation of the Projected Gauss-Seidel (PGS) method.

Unlike global solvers that attempt to solve all constraint equations simultaneously using complex matrix inversions, the SI solver processes constraints one by one, in a sequence.

When a rigid body is subjected to conflicting constraints (for example, a door hinge trying to keep a body in place while a slide joint tries to pull it away), the SI solver handles the conflict through an iterative approximation process:

  1. Local Resolution: The solver looks at the first constraint and calculates the impulse (force applied over time) required to satisfy it. It applies this impulse to the rigid body, altering its velocity.
  2. Sequential Progression: It then moves to the second, conflicting constraint. It calculates the impulse required to satisfy this second constraint based on the body’s new velocity, and applies it. This second step will likely partially violate the first constraint.
  3. Iteration: The solver repeats this sequence over multiple iterations (typically 10 to 20 times per physics step).

With each iteration, the corrections become smaller, and the rigid body gradually converges toward a compromise state that minimizes the overall error across all applied constraints.

Soft Constraints: ERP and CFM

To prevent infinite forces and simulation crashes when constraints are physically impossible to satisfy simultaneously, Ammo.js introduces “softness” into the constraints using two key parameters:

By adjusting CFM and ERP, Ammo.js turns rigid mathematical boundaries into spring-like relationships. If two constraints conflict, the body will settle at a balance point determined by the relative stiffness (CFM) of the conflicting joints.

Determinism and Solver Iterations

Because the solver processes constraints sequentially, the order in which constraints are evaluated can affect the final output. Ammo.js randomizes or carefully structures the processing order of constraints to maintain stability and prevent bias toward one specific constraint.

To resolve severe conflicts more accurately, you can increase the solver iteration count in your physics world settings. Higher iteration counts give the sequential impulse solver more opportunities to distribute the error evenly, resulting in a more stable compromise at the cost of CPU performance.