Lección 7: Avanzar en el tiempo
Construye en Python el patrón «Bola en un anillo giratorio» y aprende por el camino:
- una simulación: pasos de tiempo pequeños en un bucle while
- vectores como arrays de numpy
- el producto escalar y una reflexión
- ángulos con np.arctan2, reducidos a una vuelta
- break para salir de un bucle
Míralo primero
Se reproduce desde YouTube tras hacer 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
¿No tienes Python en este equipo? El cuaderno ejecuta el mismo script, los ejercicios y las respuestas en tu navegador, en Google Colab. El cuaderno está en inglés.
Línea a línea
v[1] -= g * dtLa gravedad: en cada paso, la velocidad vertical baja en g·dt.
p = p + v * dtLa bola se mueve su velocidad multiplicada por el paso de tiempo. Esta forma de avanzar, la más sencilla, se llama método de Euler.
if r > R - ball:El borde de la bola llega a la pared cuando su centro está a un radio de bola del anillo.
off = abs((angle - centre + np.pi) % (2 * np.pi) - np.pi)El ángulo entre la bola y el centro de la abertura, reducido al intervalo −π … π, para que 359° cuente como 1° de distancia.
v = v - 2 * np.dot(v, normal) * normalLa reflexión: resta dos veces la parte de la velocidad a lo largo de la normal. El giro del anillo no interviene.
p = normal * (R - ball)Devuelve la bola a la pared, para que un paso nunca pueda dejarla fuera.
Pruébalo tú
Comprueba la energía, ½·|v|² + g·y por unidad de masa: muéstrala al principio y al final. ¿Se mantiene igual?
Pista
np.dot(v, v) es |v|².
Respuesta
Casi: baja alrededor de un 2 % a lo largo de la ejecución, de 3.83 a 3.75. Los pasos sencillos y el empujón de vuelta a la pared pierden un poco.
Divide dt entre dos. ¿Qué les pasa a la energía y al momento en que escapa la bola?
Pista
dt = 0.00025.
Respuesta
Ahora la energía baja alrededor de un 1 % en lugar de un 2 %; la bola sigue escapando tras unos 3,9 s.
¿Por qué la línea del rebote no usa spin para nada?
Pista
¿Hacia dónde se mueve un punto de la pared?
Respuesta
Sin rozamiento, la pared solo puede empujar a lo largo de la normal, y una pared que gira se mueve a lo largo de la tangente, perpendicular a ella.
Cuestionario
Tarjetas de repaso
Lee el anverso, di el reverso para ti y luego abre la tarjeta.
Paso de Euler
posición += velocidad · dt; velocidad += aceleración · dt.
Reflexión
v − 2·(v · n)·n, con n la normal unitaria de la pared.
np.arctan2(y, x)
El ángulo del punto (x, y), de −π a π.
break
Sale del bucle en el que está, de inmediato.
Comprobación de la energía
½·|v|² + g·y debería mantenerse casi constante sin rozamiento: una prueba de una simulación.