在二维中加速一个点
Accelerating a point in two dimensions
我有以下 Python 代码:
import math
x = 0
y = 0
acceleration = 10
angle = 0
vx = 0
vy = 0
time = 10
for _ in range(time):
vx += acceleration * math.cos(math.radians(angle))
vy += -acceleration * math.sin(math.radians(angle))
x += vx
y += vy
print(x, y)
输出:
550.0 0.0
这不是位移方程的结果。
(acceleration * time**2) / 2
= 500
我做错了什么?我想不花时间解决问题;假装它不存在。
在您的情况下,x
和 y
应更新为 vx
初始和最终的平均值
velocity 和 vy
分别。
作为
如果你想要每个时间步的 x 和 y,你应该这样做,
import math
x = 0
y = 0
acceleration = 10
angle = 0
vx = 0
vy = 0
time = 10
vx = (vx + acceleration * math.cos(math.radians(angle))*time)/2 #average of velocity
vy = (vy -acceleration * math.sin(math.radians(angle))*time)/2 #average of velocity
for _ in range(time):
x += vx
y += vy
print(x, y)
您要实现的是找到速度随时间的精确积分,其中速度本身隐含地作为加速度的积分给出。然后您尝试使用最简单的可用方法:Euler method。错误累积在所难免。
除了 Euler 方法固有的错误(不精确)之外,您的实现还存在按顺序更新变量的错误。即:您将过去的位移与当前速度结合起来——而不是与相应的过去速度结合起来。您应该计算每个变量的新值并同时更新它们。例如像这样(从您的代码中省略常量):
import math
acceleration = 10
vx = 0
x = 0
for _ in range(10):
new_x = x + vx
new_vx = vx + acceleration
x = new_x
vx = new_vx
print(x) # 450
在您当前的设置(修复)中,模拟运行如下:
您可以通过增加时间分辨率来获得更好的结果,例如通过将步长设为 0.1 而不是 1,您将得到:
如果您对更好的数值积分方法感兴趣,请关注维基百科 Runge-Kutta or Adams-Bashfort。
这里是重现情节的代码:
import numpy as np
import matplotlib.pyplot as plt
acceleration = 10
t0 = 0
t1 = 10
nb_steps = 11
ts = np.linspace(t0, t1, num=nb_steps)
vs = np.zeros_like(ts)
xs = np.zeros_like(ts)
vs[0] = 0
xs[0] = 0
true_xs = acceleration * ts ** 2 / 2
for i, t in enumerate(ts):
if i == 0:
continue # initial conditions are preset
delta_t = t - ts[i-1]
vs[i] = vs[i-1] + acceleration * delta_t
xs[i] = xs[i-1] + vs[i-1] * delta_t
plt.figure()
plt.plot(ts, vs, label='velocity')
plt.plot(ts, xs, label='displacement-sim')
plt.plot(ts, true_xs, label='displacement-true')
plt.legend()
plt.show()
我有以下 Python 代码:
import math
x = 0
y = 0
acceleration = 10
angle = 0
vx = 0
vy = 0
time = 10
for _ in range(time):
vx += acceleration * math.cos(math.radians(angle))
vy += -acceleration * math.sin(math.radians(angle))
x += vx
y += vy
print(x, y)
输出:
550.0 0.0
这不是位移方程的结果。
(acceleration * time**2) / 2
= 500
我做错了什么?我想不花时间解决问题;假装它不存在。
在您的情况下,x
和 y
应更新为 vx
初始和最终的平均值
velocity 和 vy
分别。
作为
如果你想要每个时间步的 x 和 y,你应该这样做,
import math
x = 0
y = 0
acceleration = 10
angle = 0
vx = 0
vy = 0
time = 10
vx = (vx + acceleration * math.cos(math.radians(angle))*time)/2 #average of velocity
vy = (vy -acceleration * math.sin(math.radians(angle))*time)/2 #average of velocity
for _ in range(time):
x += vx
y += vy
print(x, y)
您要实现的是找到速度随时间的精确积分,其中速度本身隐含地作为加速度的积分给出。然后您尝试使用最简单的可用方法:Euler method。错误累积在所难免。
除了 Euler 方法固有的错误(不精确)之外,您的实现还存在按顺序更新变量的错误。即:您将过去的位移与当前速度结合起来——而不是与相应的过去速度结合起来。您应该计算每个变量的新值并同时更新它们。例如像这样(从您的代码中省略常量):
import math
acceleration = 10
vx = 0
x = 0
for _ in range(10):
new_x = x + vx
new_vx = vx + acceleration
x = new_x
vx = new_vx
print(x) # 450
在您当前的设置(修复)中,模拟运行如下:
您可以通过增加时间分辨率来获得更好的结果,例如通过将步长设为 0.1 而不是 1,您将得到:
如果您对更好的数值积分方法感兴趣,请关注维基百科 Runge-Kutta or Adams-Bashfort。
这里是重现情节的代码:
import numpy as np
import matplotlib.pyplot as plt
acceleration = 10
t0 = 0
t1 = 10
nb_steps = 11
ts = np.linspace(t0, t1, num=nb_steps)
vs = np.zeros_like(ts)
xs = np.zeros_like(ts)
vs[0] = 0
xs[0] = 0
true_xs = acceleration * ts ** 2 / 2
for i, t in enumerate(ts):
if i == 0:
continue # initial conditions are preset
delta_t = t - ts[i-1]
vs[i] = vs[i-1] + acceleration * delta_t
xs[i] = xs[i-1] + vs[i-1] * delta_t
plt.figure()
plt.plot(ts, vs, label='velocity')
plt.plot(ts, xs, label='displacement-sim')
plt.plot(ts, true_xs, label='displacement-true')
plt.legend()
plt.show()