Lektion 7: Schritt für Schritt durch die Zeit
Baue das Muster „Kugel im drehenden Ring“ in Python und lerne dabei:
- eine Simulation: kleine Zeitschritte in einer while-Schleife
- Vektoren als numpy-Arrays
- das Skalarprodukt und eine Spiegelung
- Winkel mit np.arctan2, zurückgefaltet
- break, um eine Schleife zu verlassen
Erst ansehen
Läuft nach einem Klick von YouTube.
"""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
Kein Python auf diesem Computer? Das Notebook führt dasselbe Skript, die Übungen und die Lösungen in deinem Browser aus, in Google Colab. Das Notebook ist auf Englisch.
Zeile für Zeile
v[1] -= g * dtDie Schwerkraft: Bei jedem Schritt sinkt die senkrechte Geschwindigkeit um g·dt.
p = p + v * dtDie Kugel bewegt sich um ihre Geschwindigkeit mal den Zeitschritt. Diese einfachste Art, Schritte zu machen, heißt Euler-Verfahren.
if r > R - ball:Der Rand der Kugel erreicht die Wand, wenn ihr Mittelpunkt einen Kugelradius vom Ring entfernt ist.
off = abs((angle - centre + np.pi) % (2 * np.pi) - np.pi)Der Winkel zwischen der Kugel und der Mitte der Lücke, zurückgefaltet in −π … π, damit 359° als 1° Abstand zählt.
v = v - 2 * np.dot(v, normal) * normalDie Spiegelung: Zieh den Anteil der Geschwindigkeit entlang der Normalen zweimal ab. Die Drehung des Rings spielt dabei keine Rolle.
p = normal * (R - ball)Setz die Kugel zurück auf die Wand, damit ein Schritt sie nie draußen lassen kann.
Probier es selbst
Prüfe die Energie, ½·|v|² + g·y pro Masseneinheit: Gib sie am Anfang und am Ende aus. Bleibt sie gleich?
Hinweis
np.dot(v, v) ist |v|².
Lösung
Fast: Sie sinkt über den ganzen Lauf um etwa 2 %, von 3.83 auf 3.75. Die einfachen Schritte und das Zurücksetzen auf die Wand verlieren ein wenig.
Halbiere dt. Was passiert mit der Energie und mit dem Zeitpunkt, zu dem die Kugel entkommt?
Hinweis
dt = 0.00025.
Lösung
Die Energie sinkt jetzt um etwa 1 % statt 2 %; die Kugel entkommt weiterhin nach etwa 3,9 s.
Warum verwendet die Zeile für den Abprall spin überhaupt nicht?
Hinweis
In welche Richtung bewegt sich ein Punkt der Wand?
Lösung
Ohne Reibung kann die Wand nur entlang der Normalen drücken, und eine sich drehende Wand bewegt sich entlang der Tangente, im rechten Winkel dazu.
Quiz
Lernkarten
Lies die Vorderseite, sag dir die Rückseite vor, dann öffne die Karte.
Euler-Schritt
Position += Geschwindigkeit · dt; Geschwindigkeit += Beschleunigung · dt.
Spiegelung
v − 2·(v · n)·n, mit n als Einheitsnormale der Wand.
np.arctan2(y, x)
Der Winkel des Punktes (x, y), von −π bis π.
break
Verlässt die Schleife, in der es steht, sofort.
Energieprüfung
½·|v|² + g·y sollte ohne Reibung fast konstant bleiben: ein Test für eine Simulation.