Double pendulum animation

Posted JUN 21, 2017


Having been a front-end developer for quite some time, I canvas animations, they're one of my favourite things to code. It’s simple, you do not have to bother about frameworks, architecture, and all the stuff that takes away the fun in coding (JavaScript fatigue anyone ?). Recently, I decided to create a personal website (you are reading it right now!), and wanted to build an animation on its front page. My mind wandering to find inspiration, I remembered a video that recently fascinated me. Youtube user "Make Anything" 3D-printed a double pendulum, attached a light to it, and filmed the whole thing. The result was so beautiful and chaotic, that I decided that this would be my next animation.

A bit of maths

To be honest, I would not be able to find the differential equations for this system. If you want to read about the tools used to solve it you can, here. Let's suppose we are all able to solve it, and let's write the equations which describe the system.

In order to find the value of and we need to integrate the equations above. As far as I know, no analytic form can be found, and we need to approximate the integration. One can use multiple methods, but here I went for simplicity, and used a simple Euler method.

The code

To begin, lets code the computation of the angles of the pendulum. We first need to translate the equations into JavaScript code. A bit cumbersome, but necessary.

// th1 and th2 are the thetas
// th1d and th2d are the derivates of th1 and th2

// Acceleration of theta1
function th1a(th1, th2, th1d, th2d) {
  var n1 = m2 * l1 * th1d * th1d * sin(th2 - th1) * cos(th2 - th1);
  var n2 = m2 * g * sin(th2) * cos(th2 - th1);
  var n3 = m2 * l2 * th2d * th2d * sin(th2 - th1);
  var n4 = - m * g * sin(th1);

  var d = (m * l1) - m2 * l1 * cos(th2 - th1) * cos(th2 - th1);

  return (n1 + n2 + n3 + n4) / d;

// Acceleration of theta2
function th2a(th1, th2, th1d, th2d) {
  var n1 = - m2 * l2 * th2d * th2d * sin(th2 - th1) * cos(th2 - th1);
  var n2 = m * (g * sin(th1) * cos(th2 - th1) - l1 * th1d * th1d * sin(th2 - th1) - g * sin(th2));

  var d = (m * l2) - m2 * l2 * cos(th2 - th1) * cos(th2 - th1);

  return (n1 + n2) / d;

Next we need to code a loop, which will compute the thetas (using Euler's method), and draw the pendulum on the canvas. For the loop I used raf, a polyfill to requestAnimationFrame.

// Initial values chosen randomly

// th1 and th2 are the thetas
var th1 = Math.random() * 2 * pi;
var th2 = Math.random() * 2 * pi;

// th1d and th2d are the derivates of th1 and th2
var th1d = (Math.random() - 0.5) * 2;
var th2d = (Math.random() - 0.5) * 2;

// requestAnimationFrame loop
raf(function tick() {
  // dt is chosen empirically
  var dt = 0.01;

  // Euler method
  th1d += th1a(th1, th2, th1d, th2d) * dt;
  th2d += th2a(th1, th2, th1d, th2d) * dt;

  th1 += th1d * dt;
  th2 += th2d * dt;

  updateCanvas(th1, th2);


Now, the only thing left to code is the canvas code to display our pendulum (the updateCanvas function). You will need to have a canvas element in your HTML, with the ID "animation".

var canvas = document.getElementById('animation');
var context = canvas.getContext('2D');

function drawCircle(x, y) {
  context.arc(x, y, 5, 0, 2 * Math.PI, false);

function drawPendulum(x1, y1, x2, y2) {
  context.moveTo(width / 2, height / 2);
  context.lineTo(x1, y1);
  context.lineWidth = 1;

  context.moveTo(x1, y1);
  context.lineTo(x2, y2);
  context.lineWidth = 1;

  drawCircle(x1, y1);
  drawCircle(x2, y2);

// the drawing function
function updateCanvas(th1, th2) {
  drawPendulum(th1ToX(th1), th1ToY(th1), th2toX(th2), th2ToY(th2));

We did not talked about the th1To(X/Y) end th2To(X/Y) functions right? These functions translate thetas to their coordinates in the canvas. Here is the last snippet of code.

// We need the width and height of the canvas
var width = canvas.offsetWidth;
var height = canvas.offsetHeight;

// The width and height of the canvas will allow us
// to position the pendulum at the center.
function th1ToX(th1) {
  return width / 2 - sin(th1) * l1; 

function th1ToY(th1) {
  return height / 2 + cos(th1) * l1;

function th2ToX(th1, th2) {
  return th1ToX(th1) - sin(th2) * l2;

function th2ToY(th1, th2) {
  return th1ToY(th1) + cos(th2) * l2;

The Result

I hope you learned some things while reading this post! You can find a more colorful animation on the home page of this website, here. You can find the full code here.