Modelling the trajectory of a badminton shuttlecock#

%matplotlib widget
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import IPython
from scipy import integrate

Data collection#

Further reading:

Simulation inputs:

v0 = 493.0 / 3.6  # Initial velocity [m/s]
A = 4.0e-3  # Shuttlecock cross area [m**2]
cx = 0.62  # Drag coefficient []
m = 4.0e-2  # Shuttlecock mass [kg]
rho = 1.225  # Air density [kg/m**3]
g = 9.81  # Gravity [m/s**2]

Can we simulate the trajectory ?#

Newton’s second law:#

\[ m \vec{A}(M/R) = -mg \vec y -\frac{1}{2} \rho V^2 A c_x \vec T \]
def derivative(X, t):
    """
    Target ODE: Newton's second law
    """
    x, y, vx, vy = X
    v = (vx**2 + vy**2) ** 0.5
    Tx, Ty = vx / v, vy / v
    ax = -0.5 * rho * v**2 * A * cx * Tx / m
    ay = -0.5 * rho * v**2 * A * cx * Ty / m - g
    return np.array([vx, vy, ax, ay])


x0, y0 = 0.0, 0.0
theta0 = 45.0
X0 = [x0, y0, v0 * np.cos(np.radians(theta0)), v0 * np.sin(np.radians(theta0))]
t = np.linspace(0.0, 10.0, 200)
sol = integrate.odeint(derivative, X0, t)
out = pd.DataFrame(sol, columns=["x", "y", "vx", "vy"])
out.head()
x y vx vy
0 0.000000 0.000000 96.834345 96.834345
1 4.323421 4.311938 76.793616 76.351638
2 7.831625 7.788303 63.660684 62.843454
3 10.785471 10.692467 54.394327 53.238940
4 13.337946 13.178880 47.510084 46.039129
plt.figure()
plt.plot(out.x, out.y)
plt.grid()
plt.ylim(0.0, 50.0)
plt.xlabel("Position, $x$")
plt.ylabel("Position, $y$")
plt.show()
thetas = [0.0, 10.0, 15.0, 20.0, 30.0, 45.0, 60.0, 80.0, 85.0]
plt.figure()

for theta0 in thetas:
    x0, y0 = 0.0, 3.0
    X0 = [x0, y0, v0 * np.cos(np.radians(theta0)), v0 * np.sin(np.radians(theta0))]
    t = np.linspace(0.0, 10.0, 1000)
    sol = integrate.odeint(derivative, X0, t)
    out = pd.DataFrame(sol, columns=["x", "y", "vx", "vy"])
    out["t"] = t
    plt.plot(out.x, out.y, label=r"$\theta_0 = $" + "{0}".format(theta0))
plt.legend()
plt.grid()
plt.ylim(0.0, 50.0)
plt.xlabel("Position, $x$")
plt.ylabel("Position, $y$")
plt.show()

Range as a function of \(\theta\)#

%%time
thetas = np.linspace(-180.0, 180.0, 300)
xmax = np.zeros_like(thetas)


for i in range(len(thetas)):
    theta0 = thetas[i]
    x0, y0 = 0.0, 3.0
    X0 = [x0, y0, v0 * np.sin(np.radians(theta0)), -v0 * np.cos(np.radians(theta0))]
    t = np.linspace(0.0, 10.0, 10000)
    sol = integrate.odeint(derivative, X0, t)
    out = pd.DataFrame(sol, columns=["x", "y", "vx", "vy"])
    xmax[i] = out[out.y < 0.0].iloc[0].x
CPU times: user 455 ms, sys: 0 ns, total: 455 ms
Wall time: 455 ms
plt.figure()
plt.plot(thetas, xmax)
plt.grid()
plt.xlabel(r"Start angle $\theta_0$")
plt.ylabel(r"Range $x_m$")
plt.show()