Tutorial 5 -- Animations with Python

In this tutorial, we illustrate how animations can be produced with the Matplotlib module. We load the necessary functions as follows

import matplotlib.pyplot as plt
from matplotlib import animation

Examples of animations can be found in the matplotlib website: Matplotlib Animation.

Animation of a Parabolic Projectile Motion

In this first example, we want to simulate the motion of a projectile according to the parametric equations $$ x(t) = (v_0 \cos\alpha) t, \qquad y(t)= (v_0\sin\alpha) t - g\frac{t^2}{2} \qquad \text{(1-2)} $$ starting at $t=0$ with initial velocity $(v_0 \cos\alpha, v_0\sin\alpha)$. We end the motion at $t_{max}= D/v_0 \cos\alpha$ when $x= D$. At $t=t_{max}$ we have $y=h$ according (2). We will also plot a rectangular building whose base is at $(D,0)$, of width $2d$ and height $h$. We will follow these steps:

Step 1: we import the necessary modules and functions

import numpy as np
from matplotlib import pyplot as plt
from matplotlib import animation

Step 2: we define the necessary parameters, such as $v_0$, $\alpha$, $g$, $D$, $d$, etc. We will increment time with step size dt corresponding to Nstep. Nstep will also define the number of frames of the animation.

v0 = 50 # [m/s]
g = 9.81 # [m/s^2]
alpha= 50 # [deg]
D= 220 # [m]
d= 10 # [m]
alpha = alpha*np.pi/180 # launch angle
Tmax = D/(v0*np.cos(alpha)) # maximum time of motion
xmax =  D+2*d # parameters for the graphical window
ymax =  0.55*(v0*np.sin(alpha))**2 /g 
Nstep= 400   # number of time steps /number of frames
dt= Tmax/Nstep  # time increment
h= D*np.tan(alpha)-0.5*g*(D/v0/np.cos(alpha))**2 # height of rectangular object

Step 3: we set up the figure, the axis, and the plot element to be animated. This element is an empty line object with the desired attributes. The line object will be updated along the simulation at a later stage (Step 6). We also add the static rectangular object to the plot.

fig = plt.figure()
ax = plt.axes(xlim=(0, xmax), ylim=(0, ymax))
plt.xlabel('x(m): horizontal distance')
plt.ylabel('y(m): height')

line, = ax.plot([], [], 'o', ls='-', ms=8, markevery=[0,-1])

xR,yR = D-d,0. # lower left corner of rectangle
dx,dy= 2*d, h # dimensions of rectangle
rect = plt.Rectangle((xR,yR), dx,dy, facecolor= 'black', edgecolor= 'black')
ax.add_patch(rect)

Step 4: we define an initialization function to plot the background of each frame. This function sets the line object with empty data. By returning the line object, the animator now knows which plot object needs to be updated during the animation.

def init():
    line.set_data([], [])
    return line,

Step 5: we define the animation function which updates the line object with time. It has a single argument: the integer i which defines the frame number. Time is defined in terms of this integer i, according to a particular scale. In our case, the line object is defined by 2 arrays $x$ and $y$ parameterized with time according to equations (1-2). This function will be called sequencially by the animator.

def animate(i):
    t= np.linspace(0, i*dt, 2*i)
    x = v0*np.cos(alpha)*t
    y = v0*np.sin(alpha)*t -0.5*g*t**2
    line.set_data(x, y)
    return line,

Step 6: now we call the animator FuncAnimation. The resulting object must be assigned to a variable, here anim. We define the animation by the number of frames Nstep with a 20ms delay between frames. The blit keyword is important: it indicates the animator to only redraw the parts of the plot which have changed. By setting blit=True, the animations display much more quickly and the resulting video file will be smaller. The optional save command saves the data in mp4 video file. The show command display thes final result.


anim = animation.FuncAnimation(fig, animate, init_func=init, frames=Nstep, interval=20, blit=True)

# save the animation as an mp4.  This requires ffmpeg or mencoder to be
# installed.  The extra_args ensure that the x264 codec is used, so that
# the video can be embedded in html5. 

anim.save('projectile_animation.mp4', fps=30, extra_args=['-vcodec', 'libx264'])
plt.show()

The python script can be found here.

In this script, we add a clock to display the time elapsed.


[Previous Tutorial] [Next Tutorial]