Simulate and animate a double pendulum modelled as an index-1 DAE system in Cartesian coordinates, solved with explicit Runge-Kutta methods.
from simulation import run
run() # creates a random pendulum, simulates 30 s, saves animations/YYYY-MM-DD_HH-MM.mp4That's it. The animation is saved as an .mp4 file in the animations/ subdirectory (created automatically). ffmpeg must be installed and on your PATH.
from simulation import run
run()Pendulum(m, x, y, u, v) — mass, position (x, y), velocity (u, v). Set velocities to 0 to release from rest.
from simulation import run, Pendulum, DoublePendulum
p1 = Pendulum(m=2.7, x=2.5, y=-3.7, u=0, v=0)
p2 = Pendulum(m=3.1, x=0.2, y=-6.3, u=0, v=0)
dp = DoublePendulum(p1, p2)
run(dp, duration=20, filename='my_pendulum')Pass num_perturbations to overlay several nearly-identical trajectories and watch them diverge:
from simulation import run
run(num_perturbations=8, perturbation_amount=1e-5)from simulation import run, DOPRI5
run(method=DOPRI5, step_size=0.005)Available methods (all importable directly from simulation):
| Name | Import |
|---|---|
| Forward Euler | Euler |
| Explicit midpoint | ExplicitMidpoint |
| Ralston | Ralston |
| Kutta 3rd order | Kutta3 |
| RK4 (default) | RK4 |
| Runge-Kutta-Fehlberg | RKF |
| Cash-Karp | CK |
| Dormand-Prince | DOPRI5 |
from simulation import (
create_random_example, create_perturbations,
simulate, simulate_multiple_examples,
)
from animations import single_animation, multi_animation
# Simulate
example = create_random_example()
result = simulate(example, duration=30, step_size=0.001)
# Animate
single_animation(result, example, filename='my_run')
# Multiple perturbed copies
perturbed = create_perturbations(10, example, amount=1e-5)
results = simulate_multiple_examples(perturbed)
multi_animation(results, example)
git clone https://github.com/narimiran/double_pendulum.git
cd double_pendulum
pip install numpy matplotlib
System dependency: ffmpeg must be installed and available on your PATH for saving .mp4 files.
Headless / server environments: set the matplotlib backend before importing anything:
import matplotlib
matplotlib.use('Agg')
from simulation import run
run()
Q: Why Cartesian coordinates?
A: The original task was to implement the double pendulum as a DAE system in Cartesian coordinates. Everything else grew from there.
Q: Why can't I use implicit Runge-Kutta methods?
A: Implicit methods require solving a non-linear system at each step, which is not implemented here.
Q: Is there damping or friction?
A: No. The only force acting on the system is gravity.
