August 13, 2025
Simulating a double pendulum involves solving its equations of motion, which are derived from Lagrangian mechanics. These equations form a system of nonlinear second-order ordinary differential equations (ODEs).
The double pendulum system consists of two point masses and , attached by rigid massless rods of lengths and , swinging under gravity. Let and be the angles each pendulum makes, measured from the vertical.
Since analytical solutions aren't known, we use numerical methods to approximate the pendulum's motion.
To simulate physical systems we compute the system's state at each step using estimates of its derivatives.
The Runge-Kutta methods are a family of iterative techniques for integrating ODEs. Commonly used is the 4th-order Runge-Kutta (RK4) method. RK4 improves upon simpler methods like Euler's by sampling the derivative multiple times at each step.
Here are the differential equations, expressed in c++:
001typedef std::vector<double> State;002003// ########### Derivatives function for RK4 ###########004State derivatives(const State& y) {005 const double theta1 = y[0];006 const double theta2 = y[1];007 const double omega1 = y[2];008 const double omega2 = y[3];009010 const double delta = theta2 - theta1;011012 const double den1 = (m1 + m2) * l1 - m2 * l1 * std::cos(delta) * std::cos(delta);013 const double den2 = (l2 / l1) * den1;014015 double domega1 = (016 m2 * l1 * omega1 * omega1 * std::sin(delta) * std::cos(delta) +017 m2 * g * std::sin(theta2) * std::cos(delta) +018 m2 * l2 * omega2 * omega2 * std::sin(delta) -019 (m1 + m2) * g * std::sin(theta1)020 ) / den1;021022 double domega2 = (023 -m2 * l2 * omega2 * omega2 * std::sin(delta) * std::cos(delta) +024 (m1 + m2) * (025 g * std::sin(theta1) * std::cos(delta) -026 l1 * omega1 * omega1 * std::sin(delta) -027 g * std::sin(theta2)028 )029 ) / den2;030031 return { omega1, omega2, domega1, domega2 };032}
In the full implementation, we perform one step per frame.
001// ########### RK4 integrator step ###########002State rk4_step(const State& y, double dt) {003 const State k1 = derivatives(y);004 State y_temp(4);005006 for (int i = 0; i < 4; ++i) y_temp[i] = y[i] + 0.5 * dt * k1[i];007 const State k2 = derivatives(y_temp);008009 for (int i = 0; i < 4; ++i) y_temp[i] = y[i] + 0.5 * dt * k2[i];010 const State k3 = derivatives(y_temp);011012 for (int i = 0; i < 4; ++i) y_temp[i] = y[i] + dt * k3[i];013 const State k4 = derivatives(y_temp);014015 State y_next(4);016 for (int i = 0; i < 4; ++i)017 y_next[i] = y[i] + dt / 6.0 * (k1[i] + 2 * k2[i] + 2 * k3[i] + k4[i]);018019 return y_next;020}
