tipos perfectamente momento lineal inelastica fisica dimensiones conservacion colisiones colision python geometry pygame game-physics

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ó.