在一个封闭的系统中,移动的二维圆体(它们具有质量和速度属性)以完美的弹性相互碰撞,是所有物体的总<撞击>速度撞击>速度(速度的大小)在系统内保存了吗?
我正在基于this Stack Overflow question中概述的碰撞解决方法在Python中实现一个简单的二维物理引擎。我的期望是,当它们发生碰撞时,总速度(与每个物体相关的速度矢量的长度之和)应该在2个物体之间保持不变,并且我根据这个期望为我的分辨率方法设计了单位测试。但我发现我的测试失败了。所以我想首先确保我的假设是正确的。
如果它是正确的,我邀请您查看我的代码并解释测试失败的原因:
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
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)
我正在使用这个pygame矢量类:http://www.pygame.org/wiki/2DVectorClass
答案 0 :(得分:4)
无论碰撞的弹性如何,都会保留总动量。总速度显然不是。严格来说,速度是一个矢量,很容易看出它会随着矢量的变化而变化:例如,一个从不可移动的垂直墙上弹性反弹的球会改变它的速度。相反。
答案 1 :(得分:1)
AndreyT's answer把我拉了出来。这是我想要的单元测试:
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://stackoverflow.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)
它过去了。
答案 2 :(得分:0)
这是一个很好的问题。我不认为弹性碰撞理论中存在正确的解决方案,因为它在物理课程/书籍中教授。
在质心(CM)参考系中,相对速度在二元弹性碰撞(Huygens)中反转。由于相对速度不依赖于所选择的参考系,因此,相对速度在任意参考系中反转。这确保了相对速度的大小与CM参考系中的速度之和保持恒定。
从本质上讲,上述内容意味着:如果计算CM框架中的速度总和(速度大小),则测试/代码必须不会出现故障。
我可以通过补充信息添加以下内容。
还有另一种理论导致结果只需要恢复相对速度,而不是坚持相对速度的逆转。根据该理论,在任意参考系中,可以在两个质量块之间传递动能(KE),保持KE的总和不变。这种理论可能会导致代码/测试结果失败。
我不懂你所写的代码,因为我不熟悉计算机代码/程序。因此,我无法对您的计划进行修改。