Średnio zaawansowane · Kulka w wirującym pierścieniu

Lekcja 7: Krok po kroku w czasie

Zbuduj w Pythonie wzór „Kulka w wirującym pierścieniu” i po drodze naucz się:

  • symulacja: małe kroki czasu w pętli while
  • wektory jako tablice numpy
  • iloczyn skalarny i odbicie
  • kąty z np.arctan2, zawinięte dookoła
  • break, żeby wyjść z pętli

Najpierw obejrzyj

Film gra z YouTube po kliknięciu.

spinning-ring.py
"""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

Nie masz Pythona na tym komputerze? Notatnik uruchamia ten sam skrypt, zadania i odpowiedzi w przeglądarce, w Google Colab. Notatnik jest po angielsku.

Linijka po linijce

  1. v[1] -= g * dt

    Grawitacja: w każdym kroku prędkość pionowa spada o g·dt.

  2. p = p + v * dt

    Kulka przesuwa się o swoją prędkość razy krok czasu. Ten najprostszy sposób liczenia kroków to metoda Eulera.

  3. if r > R - ball:

    Brzeg kulki dotyka ściany, gdy jej środek jest o jeden promień kulki od pierścienia.

  4. off = abs((angle - centre + np.pi) % (2 * np.pi) - np.pi)

    Kąt między kulką a środkiem szczeliny, zawinięty do przedziału −π … π, tak żeby 359° liczyło się jako 1° różnicy.

  5. v = v - 2 * np.dot(v, normal) * normal

    Odbicie: odejmij dwa razy część prędkości wzdłuż normalnej. Obrót pierścienia w ogóle tu nie wchodzi.

  6. p = normal * (R - ball)

    Postaw kulkę z powrotem na ścianie, żeby żaden krok nie zostawił jej na zewnątrz.

Twoja kolej

  1. Sprawdź energię, ½·|v|² + g·y na jednostkę masy: wypisz ją na początku i na końcu. Czy się nie zmienia?

    Podpowiedź

    np.dot(v, v) to |v|².

    Odpowiedź

    Prawie: przez cały przebieg spada o około 2 %, z 3.83 do 3.75. Proste kroki i dosuwanie kulki do ściany trochę jej tracą.

  2. Zmniejsz dt o połowę. Co dzieje się z energią i z chwilą ucieczki kulki?

    Podpowiedź

    dt = 0.00025.

    Odpowiedź

    Energia spada teraz o około 1 % zamiast 2 %; kulka nadal ucieka po około 3,9 s.

  3. Dlaczego linijka odbicia w ogóle nie używa spin?

    Podpowiedź

    W którą stronę porusza się punkt ściany?

    Odpowiedź

    Bez tarcia ściana może pchać tylko wzdłuż normalnej, a wirująca ściana porusza się wzdłuż stycznej, pod kątem prostym do niej.

Quiz

1. Co mierzy np.dot(v, normal)?
2. Co robi break w pętli while?
3. Jaki zakres zwraca np.arctan2(y, x)?
4. Dlaczego mniejsze kroki czasu poprawiają symulację?
5. Co zmienia obrót pierścienia?

Fiszki

Przeczytaj przód, powiedz sobie, co jest z tyłu, potem otwórz kartę.

  • Krok Eulera

    położenie += prędkość · dt; prędkość += przyspieszenie · dt.

  • Odbicie

    v − 2·(v · n)·n, gdzie n to jednostkowa normalna ściany.

  • np.arctan2(y, x)

    Kąt punktu (x, y), od −π do π.

  • break

    Od razu wychodzi z pętli, w której jest.

  • Sprawdzenie energii

    Bez tarcia ½·|v|² + g·y powinno być prawie stałe: test symulacji.

Te fiszki na osobnej stronie →