Helicopter Flight Dynamics in Matter.js

This article explains how to simulate 2D helicopter flight dynamics within the Matter.js physics engine by modeling main rotor lift, engine reaction torque, and tail rotor stabilization. By applying directed vector forces and angular adjustments on each physics step, you can recreate realistic vertical ascent, directional tilting, and rotational counter-forces using standard rigid-body mechanics.

Modeling the Helicopter Rigid Body

To model a helicopter in Matter.js, represent the aircraft as either a single rigid body or a compound body consisting of a main fuselage and a tail boom. The center of mass should sit slightly below the main rotor mast to provide passive pendulum stability.

const { Engine, Render, Runner, Bodies, Composite, Body, Vector } = Matter;

const fuselage = Bodies.rectangle(400, 300, 80, 30, { density: 0.002 });
const tailBoom = Bodies.rectangle(350, 300, 70, 10, { density: 0.001 });

const helicopter = Body.create({
  parts: [fuselage, tailBoom],
  frictionAir: 0.02 // Provides baseline atmospheric drag
});

Main Rotor Lift Dynamics

The main rotor generates thrust perpendicular to the aircraft's longitudinal axis. In Matter.js, this force must be computed using the body’s current angle (\(\theta\)) and applied at the rotor mast position.

To account for directional control (cyclic input), introduce a small tilt offset (\(\alpha\)) relative to the fuselage:

\[\vec{F}_{\text{lift}} = \begin{bmatrix} L \cdot \sin(\theta + \alpha) \\ -L \cdot \cos(\theta + \alpha) \end{bmatrix}\]

Applying this force to the helicopter:

function applyMainRotorLift(helicopter, liftMagnitude, cyclicTilt = 0) {
  const effectiveAngle = helicopter.angle + cyclicTilt;
  const forceVector = {
    x: liftMagnitude * Math.sin(effectiveAngle),
    y: -liftMagnitude * Math.cos(effectiveAngle)
  };

  // Rotor position slightly above the fuselage center of mass
  const rotorOffset = Vector.rotate({ x: 0, y: -20 }, helicopter.angle);
  const rotorPosition = Vector.add(helicopter.position, rotorOffset);

  Body.applyForce(helicopter, rotorPosition, forceVector);
}

Engine Reaction Torque and Tail Rotor Balancing

According to Newton's third law, spinning the main rotor imparts an equal and opposite torque onto the helicopter body. In a top-down or pitch/yaw-coupled 2D projection:

  1. Reaction Torque: A rotational force proportional to main rotor power rotates the fuselage in the opposite direction of rotor rotation.
  2. Tail Rotor Counter-Force: The tail rotor generates a thrust vector located at the end of the tail boom to neutralize this reaction torque and provide directional steering.

In a 2D side-view simulation, the tail rotor primarily controls pitch trim, whereas in a top-down view, it controls yaw. To simulate the side-view flight dynamic where the tail provides anti-torque stabilization and pitch authority:

function applyTailRotor(helicopter, mainRotorLift, trimInput) {
  // Main rotor induces an unwanted rotational torque
  const reactionTorque = mainRotorLift * 0.08;

  // Tail rotor produces opposing force applied at the tail tip
  const tailArmDistance = -65; // Distance from center of mass to tail rotor
  const tailPosition = Vector.add(
    helicopter.position,
    Vector.rotate({ x: tailArmDistance, y: 0 }, helicopter.angle)
  );

  // Calculate balancing force plus pilot trim/pitch input
  const requiredCounterForce = (reactionTorque / tailArmDistance) + trimInput;
  const tailForceVector = Vector.rotate({ x: 0, y: requiredCounterForce }, helicopter.angle);

  Body.applyForce(helicopter, tailPosition, tailForceVector);
}

Physics Integration Loop

Combine these calculations within the beforeUpdate engine event to apply forces consistently before Matter.js integrates velocity and position.

let collectiveInput = 0.05; // Upward throttle / lift power
let cyclicInput = 0.05;     // Rotor tilt for forward/backward movement
let pedalInput = 0.0;       // Anti-torque control adjustment

Matter.Events.on(engine, 'beforeUpdate', () => {
  // 1. Apply primary upward lift and cyclic tilt
  applyMainRotorLift(helicopter, collectiveInput, cyclicInput);

  // 2. Apply tail rotor forces to counteract spin and steer
  applyTailRotor(helicopter, collectiveInput, pedalInput);

  // 3. Angular damping to simulate air resistance on the tail surface
  helicopter.torque -= helicopter.angularVelocity * 0.15;
});

Aerodynamic Stabilization Tips