Leçon 7 : Avancer dans le temps pas à pas
Construis en Python le motif « Bille dans un anneau qui tourne » et apprends en chemin :
- une simulation : de petits pas de temps dans une boucle while
- des vecteurs sous forme de tableaux numpy
- le produit scalaire et une réflexion
- des angles avec np.arctan2, ramenés sur un tour
- break pour sortir d’une boucle
Regarde-le d’abord
Lecture depuis YouTube après un clic.
"""A ball under gravity in a ring with a gap that spins; the bounces are elastic and without friction.
Run: python spinning-ring.py (needs: pip install numpy matplotlib)
"""
import numpy as np
import matplotlib.pyplot as plt
plt.style.use("dark_background")
R, ball, g = 1.0, 0.05, 9.81 # ring radius (m), ball radius, gravity
gap, spin = np.radians(18), 2 * np.pi / 4 # an 18 degree gap, one turn every 4 seconds
p, v = np.array([0.3, 0.2]), np.array([1.8, 0.7])
dt, t, track = 0.0005, 0.0, []
while t < 60:
v[1] -= g * dt
p = p + v * dt
t += dt
track.append(p.copy())
r = np.linalg.norm(p)
if r > R - ball: # the ball touches the wall, or is at the gap
angle = np.arctan2(p[1], p[0])
centre = -np.pi / 2 + spin * t # where the gap is now
off = abs((angle - centre + np.pi) % (2 * np.pi) - np.pi)
if off < gap / 2 - ball / R: # all of the ball fits through: out
break
normal = p / r
v = v - 2 * np.dot(v, normal) * normal # the bounce: the spin plays no part in it
p = normal * (R - ball)
track = np.array(track)
print(f"escaped after {t:.1f} s" if t < 60 else "still inside after 60 s")
plt.figure(figsize=(6, 6))
plt.plot(track[:, 0], track[:, 1], color="#5eead4", linewidth=0.4)
plt.gca().add_patch(plt.Circle((0, 0), R, fill=False, color="white"))
plt.axis("equal")
plt.axis("off")
plt.show()
# Try: spin = 0 and centre = -np.pi / 2 (a still gap at the bottom): the bounces stay the same
Pas de Python sur cet ordinateur ? Le notebook exécute le même script, les exercices et les réponses dans ton navigateur, sur Google Colab. Le notebook est en anglais.
Ligne par ligne
v[1] -= g * dtLa gravité : à chaque pas, la vitesse verticale diminue de g·dt.
p = p + v * dtLa bille se déplace de sa vitesse multipliée par le pas de temps. Cette façon la plus simple d’avancer s’appelle la méthode d’Euler.
if r > R - ball:Le bord de la bille atteint la paroi quand son centre est à un rayon de bille de l’anneau.
off = abs((angle - centre + np.pi) % (2 * np.pi) - np.pi)L’angle entre la bille et le milieu de l’ouverture, ramené entre −π et π, pour que 359° compte comme un écart de 1°.
v = v - 2 * np.dot(v, normal) * normalLa réflexion : retirer deux fois la partie de la vitesse qui suit la normale. La rotation de l’anneau n’y intervient pas.
p = normal * (R - ball)Remettre la bille sur la paroi, pour qu’un pas ne puisse jamais la laisser dehors.
À toi de jouer
Vérifie l’énergie, ½·|v|² + g·y par unité de masse : affiche-la au début et à la fin. Reste-t-elle la même ?
Indice
np.dot(v, v) vaut |v|².
Réponse
Presque : elle baisse d’environ 2 % sur toute la simulation, de 3.83 à 3.75. Les pas simples et le fait de remettre la bille sur la paroi en perdent un peu.
Divise dt par deux. Qu’arrive-t-il à l’énergie et au moment où la bille s’échappe ?
Indice
dt = 0.00025.
Réponse
L’énergie baisse maintenant d’environ 1 % au lieu de 2 % ; la bille s’échappe toujours après environ 3,9 s.
Pourquoi la ligne du rebond n’utilise-t-elle pas du tout spin ?
Indice
Dans quelle direction bouge un point de la paroi ?
Réponse
Sans frottement, la paroi ne peut pousser que le long de la normale, et une paroi qui tourne se déplace le long de la tangente, perpendiculaire à la normale.
Quiz
Cartes mémoire
Lis le recto, dis-toi le verso, puis retourne la carte.
Pas d’Euler
position += vitesse · dt ; vitesse += accélération · dt.
Réflexion
v − 2·(v · n)·n, avec n la normale unitaire de la paroi.
np.arctan2(y, x)
L’angle du point (x, y), de −π à π.
break
Sort immédiatement de la boucle dans laquelle il se trouve.
Vérification de l’énergie
½·|v|² + g·y devrait rester presque constante sans frottement : un test pour une simulation.