Lição 7: Avançar no tempo passo a passo
Construa em Python o padrão “Bola dentro de um anel giratório” e aprenda pelo caminho:
- uma simulação: pequenos passos de tempo num loop while
- vetores como arrays numpy
- o produto escalar e uma reflexão
- ângulos com np.arctan2, reduzidos a uma volta
- break para sair de um loop
Veja-o primeiro
É reproduzido a partir do YouTube depois de um clique.
"""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
Não tem Python neste computador? O notebook executa o mesmo script, os exercícios e as respostas no navegador, no Google Colab. O notebook está em inglês.
Linha a linha
v[1] -= g * dtA gravidade: a cada passo, a velocidade vertical diminui em g·dt.
p = p + v * dtO deslocamento da bola é a sua velocidade vezes o passo de tempo. Esta forma mais simples de avançar chama-se método de Euler.
if r > R - ball:A borda da bola chega à parede quando o seu centro está a um raio da bola do anel.
off = abs((angle - centre + np.pi) % (2 * np.pi) - np.pi)O ângulo entre a bola e o meio da abertura, reduzido ao intervalo −π … π, para que 359° conte como 1° de distância.
v = v - 2 * np.dot(v, normal) * normalA reflexão: retirar duas vezes a parte da velocidade ao longo da normal. A rotação do anel não entra nela.
p = normal * (R - ball)Pôr a bola de volta na parede, para que um passo nunca a deixe do lado de fora.
Experimente
Verifique a energia, ½·|v|² + g·y por unidade de massa: mostre-a no início e no fim. Mantém-se igual?
Pista
np.dot(v, v) é |v|².
Resposta
Quase: diminui cerca de 2% ao longo da execução, de 3,83 para 3,75. Os passos simples e o empurrão de volta para a parede perdem um pouco.
Reduza dt a metade. O que acontece à energia e ao momento em que a bola escapa?
Pista
dt = 0.00025.
Resposta
A energia passa a diminuir cerca de 1% em vez de 2%; a bola ainda escapa após cerca de 3,9 s.
Por que razão a linha do ricochete nem sequer usa spin?
Pista
Em que direção se move um ponto da parede?
Resposta
Sem atrito, a parede só pode empurrar ao longo da normal, e uma parede que gira move-se ao longo da tangente, em ângulo reto com ela.
Quiz
Flashcards
Leia a frente, tente recordar o verso e só depois abra o cartão.
Passo de Euler
posição += velocidade · dt; velocidade += aceleração · dt.
Reflexão
v − 2·(v · n)·n, com n a normal unitária da parede.
np.arctan2(y, x)
O ângulo do ponto (x, y), de −π a π.
break
Sai imediatamente do loop em que está.
Verificação da energia
½·|v|² + g·y deve manter-se quase constante sem atrito: um teste de uma simulação.