Differential Torque in Matter.js Car Simulation
Simulating realistic vehicle dynamics in Matter.js requires distributing rotational drive force unevenly between wheels based on turning angles, traction, and wheel speeds. This article explains how to model differential torque across drive wheels—such as an open or limited-slip differential (LSD)—in a 2D Matter.js environment by monitoring wheel angular velocities and dynamically distributing torque values on every physics engine update tick.
Understanding Differential Types in 2D Physics
In a vehicle, the differential allows the driven wheels to rotate at different speeds while supplying power. In a 2D physics engine like Matter.js, vehicles are typically modeled either in a side-profile view (front and rear axles) or a top-down view (left and right wheels).
- Open Differential: Supplies equal torque to both wheels (\(T_1 = T_2 = \frac{T_{\text{engine}}}{2}\)). If one wheel loses traction and spins rapidly, the total applied propulsion collapses to the limit of the slipping wheel.
- Locked Differential (Spool): Forces both wheels to rotate at identical speeds regardless of resistance, causing tire scrub during sharp turns.
- Limited-Slip Differential (LSD): Transmits equal base torque until an angular velocity delta (\(\Delta\omega\)) is detected between the wheels, at which point torque is redirected to the slower-spinning wheel with more grip.
Step-by-Step Implementation
1. Setup the Drive Wheels
Define your driven wheels as standard circular rigid bodies and attach them to the chassis using revolute constraints or stiff distance constraints.
const wheelA = Matter.Bodies.circle(x1, y1, radius, { friction: 0.8 });
const wheelB = Matter.Bodies.circle(x2, y2, radius, { friction: 0.8 });2. Listen to the Engine's Pre-Update Loop
All torque computations must occur inside the
beforeUpdate event listener to ensure forces are applied
immediately before the solver executes collision resolution and position
integration.
Matter.Events.on(engine, 'beforeUpdate', () => {
applyDifferentialTorque(wheelA, wheelB, throttleInput);
});3. Calculate Angular Velocities
Query the current rotational speed (angularVelocity) of
both wheels directly from their Matter.js body properties:
const omegaA = wheelA.angularVelocity;
const omegaB = wheelB.angularVelocity;
const deltaOmega = omegaA - omegaB;4. Compute Torque Allocation
Open Differential Model
For an open differential, base torque is split evenly. If speed matching is desired to prevent runaway free-spinning, dampening can be applied to the faster wheel:
function applyOpenDifferential(wheelA, wheelB, throttle) {
const totalTorque = throttle * MAX_TORQUE;
const halfTorque = totalTorque / 2;
wheelA.torque += halfTorque;
wheelB.torque += halfTorque;
}Limited-Slip Differential (LSD) Model
An LSD redistributes torque from the slipping wheel back to the traction-bearing wheel using a stiffness coefficient (\(K_{lsd}\)):
function applyLimitedSlipDifferential(wheelA, wheelB, throttle) {
const totalTorque = throttle * MAX_TORQUE;
const baseTorque = totalTorque * 0.5;
// Determine differential speed
const deltaOmega = wheelA.angularVelocity - wheelB.angularVelocity;
// Transfer torque proportional to the difference in rotational speed
const kLsd = 0.05; // LSD bias factor
const transferTorque = Math.max(-baseTorque, Math.min(baseTorque, deltaOmega * kLsd));
// Wheel A loses torque if spinning faster; Wheel B gains it
const torqueA = baseTorque - transferTorque;
const torqueB = baseTorque + transferTorque;
wheelA.torque += torqueA;
wheelB.torque += torqueB;
}Top-Down Vehicle Considerations
For top-down vehicles, rotational torque alone applied to the wheels will not propel the vehicle forward. In this case, torque translates to linear forward force applied at the wheel’s contact patch.
Compute the forward vector of each wheel and apply force using
Matter.Body.applyForce:
function applyTopDownDriveForce(wheel, torqueValue) {
const angle = wheel.angle;
const forceMagnitude = torqueValue / wheel.circleRadius;
const forceVector = {
x: Math.cos(angle) * forceMagnitude,
y: Math.sin(angle) * forceMagnitude
};
Matter.Body.applyForce(wheel, wheel.position, forceVector);
}By substituting raw body torque with vector forces distributed according to the LSD or open differential logic, top-down vehicles will accurately display understeer, oversteer, and power-sliding characteristics depending on traction states.