То, что вы пытаетесь достичь, - это найти точный интеграл скорости во времени, где сама скорость дается неявно как интеграл ускорения. И вы пытаетесь сделать это самым простым из доступных методов: метод Эйлера . Накапливающиеся неточности неизбежны.
Помимо ошибок (неточностей), присущих методу Эйлера, ваша реализация имеет ошибку обновления переменных последовательным образом. То есть: вы комбинируете смещение в прошлом с текущей скоростью, а не с соответствующей прошлой скоростью. Вы должны вычислить новые значения каждой переменной и обновлять их одновременно. Например, как это (исключая константы из вашего кода):
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, вы получите:
Если вы заинтересованы в улучшении методов численного интегрирования, следуйте википедии по Рунге-Кутта или Адамс-Башфорт .
Вот код для воспроизведения участки:
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()