python - perfectamente - En una colisión elástica entre dos cuerpos bidimensionales, ¿se conserva la velocidad total(magnitud de la velocidad) entre los cuerpos?
momento lineal (3)
El impulso total se conserva, independientemente de cuán elástica sea la colisión. La velocidad total obviamente no. Estrictamente hablando, la velocidad es una cantidad vectorial, y es bastante fácil ver que cambiará, como una cantidad vectorial: por ejemplo, una pelota que rebota elásticamente desde una pared perpendicular inamovible cambia su velocidad a su opuesto.
Pregunta
En un sistema cerrado donde cuerpos circulares bidimensionales en movimiento (tienen atributos de masa y velocidad) colisionan entre sí con elasticidad perfecta, ¿se conserva la velocidad de velocidad total (magnitud de velocidad) de todos los cuerpos dentro del sistema?
Fondo
Estoy implementando un motor de física bidimensional simple en Python basado en el método de resolución de colisión descrito en esta pregunta sobre desbordamiento de pila . Mi expectativa es que la velocidad total (la suma de la longitud de los vectores de velocidad asociados con cada cuerpo) debe permanecer constante entre 2 cuerpos cuando colisionan y diseñé una prueba unitaria para mi método de resolución basado en esta expectativa. Pero encuentro que mi prueba falla. Así que primero quiero asegurarme de que mi suposición es correcta.
Si es correcto, lo invito a revisar mi código y explicar por qué la prueba está fallando:
Resolución de colisión
class Physics:
@staticmethod
def reflect_colliding_circles(
(c1_x, c1_y, c1_vx, c1_vy, c1_r, c1_m, c1_e),
(c2_x, c2_y, c2_vx, c2_vy, c2_r, c2_m, c2_e)):
# inverse masses, mtd, restitution
im1 = 1.0 / c1_m
im2 = 1.0 / c2_m
mtd = Physics.calculate_mtd((c1_x, c1_y, c1_r), (c2_x, c2_y, c2_r))
normal_mtd = mtd.normalized()
restitution = c1_e * c2_e
# impact speed
v = vec2d(c1_vx, c1_vy) - vec2d(c2_vx, c2_vy)
vn = v.dot(normal_mtd)
# circle moving away from each other already -- return
# original velocities
if vn > 0.0:
return vec2d(c1_vx, c1_vy), vec2d(c2_vx, c2_vy)
# collision impulse
i = (-1.0 * (1.0 + restitution) * vn) / (im1 + im2)
impulse = normal_mtd * i
# change in momentun
new_c1_v = vec2d(c1_vx, c1_vy) + (impulse * im1)
new_c2_v = vec2d(c2_vx, c2_vy) - (impulse * im2)
return new_c1_v, new_c2_v
@staticmethod
def calculate_mtd((c1_x, c1_y, c1_r), (c2_x, c2_y, c2_r)):
"""source: https://stackoverflow.com/q/345838/1093087"""
delta = vec2d(c1_x, c1_y) - vec2d(c2_x, c2_y)
d = delta.length
mtd = delta * (c1_r + c2_r - d) / d
return mtd
Prueba de unidad
def test_conservation_of_velocity_in_elastic_collisions(self):
for n in range(10):
r = 2
m = 10
e = 1.0
c1_pos = vec2d(0, 0)
c1_v = vec2d(random.randint(-100,100), random.randint(-100,100))
c2_delta = vec2d(random.randint(-100,100), random.randint(-100,100))
c2_delta.length = random.randint(50, 99) * r / 100.0
c2_pos = c1_pos + c2_delta
c2_v = vec2d(random.randint(-100,100), random.randint(-100,100))
c1_np, c2_np = Physics.translate_colliding_circles(
(c1_pos.x, c1_pos.y, r, m),
(c2_pos.x, c2_pos.y, r, m))
c1_nv, c2_nv = Physics.reflect_colliding_circles(
(c1_np.x, c1_np.y, c1_v.x, c1_v.y, r, m, e),
(c2_np.x, c2_np.y, c2_v.x, c2_v.y, r, m, e))
old_v = c1_v.length + c2_v.length
new_v = c1_nv.length + c2_nv.length
self.assertTrue(Physics.circles_overlap(
(c1_pos.x, c1_pos.y, r), (c2_pos.x, c2_pos.y, r)))
self.assertTrue(old_v - new_v < old_v * .01)
Estoy usando esta clase de vector de pygame: http://www.pygame.org/wiki/2DVectorClass
Es un excelente problema. No creo que exista la solución correcta en la teoría de las colisiones elásticas, tal como se enseña en los cursos / libros de Física.
En el marco de referencia del centro de masa (CM), la velocidad relativa se invierte, en una colisión elástica binaria (Huygens). Como la velocidad relativa no depende del cuadro de referencia elegido, se deduce que la velocidad relativa se invierte en cualquier marco de referencia arbitrario. Esto asegura que la magnitud de la velocidad relativa que es la misma que la suma de las velocidades en el cuadro de referencia CM permanece constante.
En esencia, lo que se dice arriba significa esto: si se calcula la suma de las velocidades (magnitudes de velocidad) en el cuadro CM, su prueba / código no debe presentar fallas.
Puedo agregar lo siguiente a modo de información suplementaria.
Hay otra teoría que conduce al resultado que requiere la mera restauración de la velocidad relativa y no insiste en la inversión de la velocidad relativa. De acuerdo con esta teoría, es posible, en un marco de referencia arbitrario, para la transferencia de energía cinética (KE) entre las dos masas, manteniendo inalterada la suma de los KE. Esta teoría podría llevar a la falla de resultados en su código / prueba.
No entiendo el código que escribió porque no estoy familiarizado con los códigos / programas de la computadora. Como tal, no estoy en condiciones de sugerir modificaciones en su programa.
La respuesta de AndreyT me enderezó. Aquí está la prueba de unidad que quería:
def test_conservation_of_momentum_in_elastic_collisions(self):
"""Some references:
http://en.wikipedia.org/wiki/Elastic_collision
http://en.wikipedia.org/wiki/Momentum
https://.com/a/13639140/1093087"""
for n in range(10):
r = 2
m = 10
e = 1.0
c1_pos = vec2d(0, 0)
c1_v = vec2d(random.randint(-100,100), random.randint(-100,100))
c2_delta = vec2d(random.randint(-100,100), random.randint(-100,100))
c2_delta.length = random.randint(50, 99) * r / 100.0
c2_pos = c1_pos + c2_delta
c2_v = vec2d(random.randint(-100,100), random.randint(-100,100))
momentum_before = (c1_v * m) + (c2_v * m)
c1_np, c2_np = collision.translate_colliding_circles(
(c1_pos.x, c1_pos.y, r, m),
(c2_pos.x, c2_pos.y, r, m))
c1_nv, c2_nv = collision.reflect_colliding_circles(
(c1_np.x, c1_np.y, c1_v.x, c1_v.y, r, m, e),
(c2_np.x, c2_np.y, c2_v.x, c2_v.y, r, m, e))
momentum_after = (c1_nv * m) + (c2_nv * m)
self.assertTrue(collision.circles_overlap(
(c1_pos.x, c1_pos.y, r), (c2_pos.x, c2_pos.y, r)))
self.assertEqual(momentum_before, momentum_after)
Pasó.