我在python中找不到这个圆圈反弹计算有什么问题

Djo*_*822 5 python debugging physics bounce

我有一个程序,圆圈可以互相反弹.我按照这里的指示旋转矢量并根据碰撞角度缩放幅度:http://www.vobarian.com/collisions/2dcollisions2.pdf

我在python中编写了这段代码(0索引表示x坐标):

norm_vect = [(object2.pos[0] - object1.pos[0]), (object2.pos[1] - object1.pos[1])]
unit = sqrt((norm_vect[0]**2) + (norm_vect[1]**2))
unit_vect = [float(norm_vect[0]) / unit, float(norm_vect[1]) /unit]
tan_vect = [-unit_vect[1], unit_vect[0]]
vel1 = object1.vel
vel2 = object2.vel
vel1_norm = vel1[0] * unit_vect[0] + vel1[1] * unit_vect[1]
vel1_tan = vel1[0] * tan_vect[0] + vel1[1] * tan_vect[1]
vel2_norm = vel2[0] * unit_vect[0] + vel2[1] * unit_vect[1]
vel2_tan = vel2[0] * tan_vect[0] + vel2[1] * tan_vect[1]
new_vel1_norm = (vel1_norm * (object1.mass - object2.mass) + 2 * object2.mass * vel2_norm) / (object1.mass + object2.mass)
new_vel2_norm = (vel2_norm * (object2.mass - object1.mass) + 2 * object1.mass * vel1_norm) / (object1.mass + object2.mass)
new_norm_vect1 = [new_vel1_norm * float(unit_vect[0]), new_vel1_norm * float(unit_vect[1])]
new_norm_vect2 = [new_vel2_norm * float(unit_vect[0]), new_vel2_norm * float(unit_vect[1])]
new_tan_vect1 = [new_vel1_norm * float(tan_vect[0]), new_vel1_norm * float(tan_vect[1])]
new_tan_vect2 = [new_vel2_norm * float(tan_vect[0]), new_vel2_norm * float(tan_vect[1])]

# Now update the object's velocity
object1.vel = [new_norm_vect1[0] + new_tan_vect1[0], + new_norm_vect1[1] + new_tan_vect1[1]]
object2.vel = [new_norm_vect2[0] + new_tan_vect2[0], + new_norm_vect2[1] + new_tan_vect2[1]]
Run Code Online (Sandbox Code Playgroud)

问题在于它有时会起作用,但不会起作用.谁能告诉我为什么?看起来如果球以直角碰撞,那么它们的出口轨迹会交换或者某种东西.我在codeskulptor浏览器中写了这个:http://www.codeskulptor.org/#user39_8q0Xdp3Y4s_2.py

任何人都可以指出我哪里出错了吗?

编辑:这可能是我处理碰撞的方式吗?以下是步骤:

    1) Draw the balls on the screen
    2) Create set of unique pairs of collidable objects 
    3) For each ball, move the ball's position 1 frame forward according to the velocity:
        ->1) Check to see if the ball is hitting a wall
        ->2) For each pairset, if the ball in question is a member of the pair:
             -->1) If distance between centers is less than sum of radii:
                    -->1)  Calculate rebound trajectories
                    ---2)  Find N such that position + rebound trajectory *N is out of collision zone
Run Code Online (Sandbox Code Playgroud)

Bas*_*els 3

在线模拟真的很酷!我没有详细研究您的完整代码,只是您在问题中发布的片段。快速浏览一下,您就可以正确计算切向和法向单位矢量、旧法向和切向速度以及新法向速度。但在那之后,你似乎有点迷失了。正如有关碰撞的文档中所解释的,碰撞期间切向速度不会改变,因此无需计算new_tan_vect1/2。我也不明白你为什么要计算new_norm_vect1,法线向量在碰撞过程中不会改变。

其他一些小备注:

  • 你为什么float()在你的代码中使用所有的东西?这通常是不需要的。如果这样做的原因是为了获得正确的除法结果,那么您确实应该from __future__ import division在代码顶部添加 a ,因为您似乎使用的是 Python2。请参阅这个老问题以获取更多信息。

  • 你所说的norm_vect实际上是非归一化法线向量,你所说的unit_vect实际上是归一化法线单位向量。我将两者都称为norm_vect,以使法向和切向之间的区别更加清晰。单位向量是任何长度为 1 的向量,因此将其用作法向量有点误导。

  • 如果您计划进行更多此类模拟,您应该考虑学习numpy. 这允许您编写矢量化计算,而不是手动写出x和的所有方程。y例如norm_vect = pos2 - pos1; norm_vect /= np.linalg.norm(norm_vect)object1.vel = norm_vect * new_vel1_norm + tang_vect * vel1_tang

我会写你的代码片段应该或多或少像这样(未经测试的代码):

from __future__ import division  # move this to the top of your program

# calculate normal and tangential unit vectors
norm_vect = [(object2.pos[0] - object1.pos[0]), 
             (object2.pos[1] - object1.pos[1])]  # stil un-normalized!
norm_length = sqrt((norm_vect[0]**2) + (norm_vect[1]**2))
norm_vect = [norm_vect[0] / norm_length, 
             norm_vect[1] / norm_length]  # do normalization
tang_vect = [-norm_vect[1], norm_vect[0]]  # rotate norm_vect by 90 degrees

# normal and tangential velocities before collision
vel1 = object1.vel
vel2 = object2.vel
vel1_norm = vel1[0] * norm_vect[0] + vel1[1] * norm_vect[1]
vel1_tang = vel1[0] * tang_vect[0] + vel1[1] * tang_vect[1]
vel2_norm = vel2[0] * norm_vect[0] + vel2[1] * norm_vect[1]
vel2_tang = vel2[0] * tang_vect[0] + vel2[1] * tang_vect[1]

# calculate velocities after collision
new_vel1_norm = (vel1_norm * (object1.mass - object2.mass) 
    + 2 * object2.mass * vel2_norm) / (object1.mass + object2.mass)
new_vel2_norm = (vel2_norm * (object2.mass - object1.mass) 
    + 2 * object1.mass * vel1_norm) / (object1.mass + object2.mass)
# no need to calculate new_vel_tang, since it does not change

# Now update the object's velocity
object1.vel = [norm_vect[0] * new_vel1_norm + tang_vect[0] * vel1_tang, 
               norm_vect[1] * new_vel1_norm + tang_vect[1] * vel1_tang]
object2.vel = [norm_vect[0] * new_vel2_norm + tang_vect[0] * vel2_tang, 
               norm_vect[1] * new_vel2_norm + tang_vect[1] * vel2_tang]
Run Code Online (Sandbox Code Playgroud)

我重命名了一些变量以使其更加清晰。