La cycloide¶

On s'intéresse à la trajectoire suivie par un point matériel situé sur la périphérie d'une roue qui roule sans glisser.

In [1]:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
from IPython.display import Image
from tqdm import tqdm
In [2]:
Image("Cycloid.png")
Out[2]:
No description has been provided for this image

Le but est de tracer les coordonnées du point $P$ comme fonction paramétrique du temps.

Le dessin est fait pour une roue qui se déplace de gauche à droite. C'est plus intuitif mais rajoute une petite diffuculté avec les signes!

Le mouvement de $P$ est la superposition d'un movement de translation horizontale à la vitesse $v_c=R\omega$, si $\omega > 0$ est la norme de la vitesse angulaire, et d'un mouvement de rotation, qui se fait dans le sens contraire du sens trigonométrique. Le point $P$ est donc repéré, dans la rotation par $\alpha =- \omega t +\alpha_0$.

De plus on choisit le temps $t=0$ tel que $P$ soit en $O$, origine du repère. Donc $\alpha (t=0)=\alpha_0=-\pi/2$

Le point $P$ a donc pour coordonnées

$$\vec{OP} = \vec{OC} + \vec{CP} = \begin{pmatrix} R \omega t \\R \end{pmatrix} + \begin{pmatrix} R \cos (-\omega t-\pi/2) \\R \sin (-\omega t -\pi/2) \end{pmatrix} = \begin{pmatrix} R \omega t - R \sin (\omega t) \\R - R \cos (\omega t) \end{pmatrix} $$

en appelant $\theta = \omega t$

$$\vec{OP} = \begin{pmatrix} R \theta - R \sin (\theta) \\R - R \cos (\theta) \end{pmatrix} $$

Le centre du cercle $C$ est donné par

$$\vec{OC} = \begin{pmatrix} R \theta \\R \end{pmatrix} $$

Le vecteur vitesse instantanée du point $P$ est obtenu par $\vec v_P= d \vec{OP}/dt$

$$\vec{v}_P = \begin{pmatrix} R \omega - R \omega \cos (\omega t) \\ R \omega \sin (\omega t) \end{pmatrix}= \begin{pmatrix} R \omega (1 - \cos (\theta) \\ R \omega \sin (\theta) \end{pmatrix} $$

In [3]:
# Définition du cercle pour son tracé. Il est composé de T segments

def circle(a, b, r):
    # (a,b): the center of the circle
    # r: the radius of the circle
    # T: The number of the segments for drawing the circle
    T = 100
    x, y = [0]*T, [0]*T
    for i,theta in enumerate(np.linspace(0,2*np.pi,T)):
        x[i] = a + r*np.cos(theta)
        y[i] = b + r*np.sin(theta)
    return x, y

# Fonction qui calcule :
# P_x; P_y, C_x, vP_x et vP_x
# pour 100 valeurs de theta entre 0 et 9 pi

def gen():
    for theta in tqdm(np.linspace(0,9*np.pi,100)):
        yield R*(theta-np.sin(theta)), R*(1-np.cos(theta)), R*theta, R*(1 - np.cos(theta)), R*np.sin(theta), theta
In [4]:
def init():
    axes[0].set_ylim(0, 20)
    axes[0].set_xlim(0, 80)
    axes[0].set_xlabel('x')
    axes[0].set_ylabel('y')
    axes[0].set_aspect('equal')
    axes[0].grid()
    
    axes[1].set_ylim(0, 10)
    axes[1].set_xlim(0, 80)
    #axes[1].set_xlabel('theta / $\pi$')
    axes[1].set_xlabel('x')
    axes[1].set_ylabel('vitesse x / $\\omega$')
    axes[1].grid()
    
    axes[2].set_ylim(-5, 5)
    axes[2].set_xlim(0, 80)
    #axes[2].set_xlabel('theta / $\pi$')
    axes[2].set_xlabel('x')
    axes[2].set_ylabel('vitesse y / $\\omega$')
    axes[2].grid()
    
    axes[1].legend()
    axes[2].legend()
    return 

def func(data):
    x, y, Rt, vx, vy, th = data
    time_text.set_text(r'$\theta$ = %.2f $\pi$' % (th/np.pi))
    xx.append(x)
    yy.append(y)
    vx_.append(vx)
    vy_.append(vy)
    ang.append(th/np.pi)
    cx, cy = circle(Rt, R, R)
    
    cycloid.set_data(xx, yy)
    line.set_data([x, Rt], [y, R])  # Ensure using lists
    circle_line.set_data(cx, cy)
    point.set_data([x], [y])  # Ensure using lists
    velx.set_data(xx, vx_)
    vely.set_data(xx, vy_)
    return
In [5]:
fig, axes = plt.subplots(3,1, figsize=(12,12))
time_text = axes[0].text(0.05, 0.8, '', transform=axes[0].transAxes)

#Plot layout setup
R = 3
cycloid, = axes[0].plot([], [], 'r-', lw=3)
line, = axes[0].plot([], [], 'y-', lw=3)
circle_line, = axes[0].plot([], [], 'g', lw=3)
point, = axes[0].plot([], [], 'bo', ms=5)

velx, = axes[1].plot([], [], 'b-', lw=3, label='vitesse x')
vely, = axes[2].plot([], [], 'b-', lw=3, label='vitesse y')


xx, yy = [], []
vx_, vy_ = [], []
ang = []
    
plt.ioff()

plt.rcParams['animation.html'] = 'html5'

animation = FuncAnimation(fig, func, gen, init_func=init, blit=False, interval=1./36*2500, save_count=100)
animation
 99%|█████████▉| 99/100 [00:32<00:00,  3.08it/s]
Out[5]:
Your browser does not support the video tag.
No description has been provided for this image
In [ ]: