Python 中的非弹性碰撞
Inelastic collision in Python
这是我第一次 post 来这里。我正在尝试学习 python 代码。我使用 turtle 模块制作了一个程序,该程序模拟一个弹跳球遭受非弹性碰撞,以减少每次弹跳的最大高度。它一直有效,直到球在非常短的高度弹跳并且它停止弹跳以使球以恒定(小)速度向下移动 - 这显然不是预期的。
"floor" 是 y = -100
坐标处的一条线。
我的迭代代码是这样的:
while t < 5000:
vy += g
h += vy
corpo.goto(0, h)
if h <= -100 and g == 0:
vy = 0
h = -100
g = 0
if abs(vy) <= 0.000000000000000000001 and h <= -100:
vy = 0
g = 0
h = -100
elif h <= -100 and vy < 0:
vy = -vy * 0.75
print(vy)
t += dt
问题是你的完成条件永远不会满足,可能是因为你在速度上增加了加速度(假设 g
指的是重力,如果不是,你真的应该考虑给它一个不同的名字).另一个问题是,即使进行了该更正,只有在 g * dt
小于 0.000000000000000000001 / 0.75
时才会满足 abs(vy) <= 0.000000000000000000001
的完成条件,否则 vy
永远不会小足够。
有两种方法可以解决后一个问题,您可以将完成条件扩展到 g * dt
,即
if abs(vy) <= abs(g * dt) and h <= -100:
# ...
或者您可以在 h <= -100
时关闭重力并稍微提高阈值,即
t = 0
dt = 0.0001
vy = 0
h = 0
g = -5
while t < 500:
if h <= -100 and g == 0:
vy = 0
h = -100
g = 0
break
if abs(vy) <= 0.0001 and h <= -100:
vy = 0
g = 0
h = -100
elif h <= -100 and vy < 0:
vy = -vy * 0.75
elif h > -100:
vy += g * dt
h += vy
print(h, vy)
t += dt
前者保证收敛(球会停止),后者则不然(可能会无限震荡).由于前者保证收敛,因此通常更可取 - 但不完全现实。
不过,最现实的解决方案是将两者结合起来,即
t = 0
dt = 0.001
vy = 0
h = 0
g = -9.81
while t < 500:
if h <= -100 and g == 0:
vy = 0
h = -100
g = 0
break
if abs(vy) <= abs(g * dt)*2 and h <= -100:
vy = 0
g = 0
h = -100
elif h <= -100 and vy < 0:
vy = -vy * 0.75
elif h > -100:
vy += g * dt
h += vy
print(h, vy)
t += dt
请注意,时间步长的某些值 dt
不会发生收敛 - 如果遇到这种情况,完成条件或时间步长的比例应该是已调整。
这是我第一次 post 来这里。我正在尝试学习 python 代码。我使用 turtle 模块制作了一个程序,该程序模拟一个弹跳球遭受非弹性碰撞,以减少每次弹跳的最大高度。它一直有效,直到球在非常短的高度弹跳并且它停止弹跳以使球以恒定(小)速度向下移动 - 这显然不是预期的。
"floor" 是 y = -100
坐标处的一条线。
我的迭代代码是这样的:
while t < 5000:
vy += g
h += vy
corpo.goto(0, h)
if h <= -100 and g == 0:
vy = 0
h = -100
g = 0
if abs(vy) <= 0.000000000000000000001 and h <= -100:
vy = 0
g = 0
h = -100
elif h <= -100 and vy < 0:
vy = -vy * 0.75
print(vy)
t += dt
问题是你的完成条件永远不会满足,可能是因为你在速度上增加了加速度(假设 g
指的是重力,如果不是,你真的应该考虑给它一个不同的名字).另一个问题是,即使进行了该更正,只有在 g * dt
小于 0.000000000000000000001 / 0.75
时才会满足 abs(vy) <= 0.000000000000000000001
的完成条件,否则 vy
永远不会小足够。
有两种方法可以解决后一个问题,您可以将完成条件扩展到 g * dt
,即
if abs(vy) <= abs(g * dt) and h <= -100:
# ...
或者您可以在 h <= -100
时关闭重力并稍微提高阈值,即
t = 0
dt = 0.0001
vy = 0
h = 0
g = -5
while t < 500:
if h <= -100 and g == 0:
vy = 0
h = -100
g = 0
break
if abs(vy) <= 0.0001 and h <= -100:
vy = 0
g = 0
h = -100
elif h <= -100 and vy < 0:
vy = -vy * 0.75
elif h > -100:
vy += g * dt
h += vy
print(h, vy)
t += dt
前者保证收敛(球会停止),后者则不然(可能会无限震荡).由于前者保证收敛,因此通常更可取 - 但不完全现实。
不过,最现实的解决方案是将两者结合起来,即
t = 0
dt = 0.001
vy = 0
h = 0
g = -9.81
while t < 500:
if h <= -100 and g == 0:
vy = 0
h = -100
g = 0
break
if abs(vy) <= abs(g * dt)*2 and h <= -100:
vy = 0
g = 0
h = -100
elif h <= -100 and vy < 0:
vy = -vy * 0.75
elif h > -100:
vy += g * dt
h += vy
print(h, vy)
t += dt
请注意,时间步长的某些值 dt
不会发生收敛 - 如果遇到这种情况,完成条件或时间步长的比例应该是已调整。