Побудувати математичну модель, яка описує положення баскетбольного м'яча в будь-який момент часу після здійснення кидка, а також точність влучення у корзину.
Вхідні параметри:
Задача — знайти функції $x(t)$, $y(t)$, $v_x(t)$, $v_y(t)$, що описують положення та швидкість м'яча після кидка в довільний момент часу $t$.
Побудуємо систему диференціальних рівнянь та визначимо початкові умови:
\begin{equation} \begin{matrix} & \left\{ \begin{matrix} \begin{aligned} m\dfrac{dv_x}{dt} &= 0\\ m\dfrac{dv_y}{dt} &= -mg\\ \dfrac{dx}{dt} &= v_x(t)\\ \dfrac{dy}{dt} &= v_y(t)\\ \end{aligned} \end{matrix} \right. \end{matrix} \begin{matrix} \begin{aligned} v_x(0) &= v_0cos(\alpha_0)\\ v_y(0) &= v_0sin(\alpha_0)\\ x(0) &= x_0\\ y(0) &= y_0\\ \end{aligned} \end{matrix} \end{equation}Продиференціюємо та отримаємо наступні функції:
\begin{equation} \begin{matrix} \begin{aligned} v_x(t) &= v_0cos(\alpha_0)\\ v_y(t) &= -gt+v_0sin(\alpha_0)\\ x(t) &= v_0cos(\alpha_0)t+x_0\\ y(t) &= -\dfrac{g}{2}t^2+v_0sin(\alpha_0)t+y_0\\ \end{aligned} \end{matrix} \end{equation}Для апроксимації даної моделі використаємо метод Ейлера, за яким значення функції на кожній наступній ітерації залежить від результату попередньої, тобто: $y_{i+1}=y_i+\Delta tf(t_i, y_i)$, де $\Delta t$ - крок ітерації.
Програмна реалізація методу Ейлера наведена нижче у вигляді функції, що приймає в якості параметрів: функцію, для якої відбувається диференціювання, початкове значення, крок та інтервал на якому необхідно знайти наближений розв'язок:
In [1]:
# Імпортуємо необхідні модулі для розрахунків та візуалізації результату
import matplotlib.pyplot as plt
from numpy import cos, sin, pi, ceil, arange
from matplotlib import rc
font = {'family': 'Verdana','weight': 'normal'}
rc('font', **font)
def euler(f, f0, h, t):
ft = [0 for i in range(len(t))]
ft[0] = f0
for i in range(len(t)-1):
ft[i+1] = ft[i]+h*f(t[i])
return ft
In [2]:
x0, y0 = 0.0, 2.0 # Початкові координати м'яча з моменту кидка
v0, a0 = 7.75, pi/3.5 # Початкова швидкість та кут кидка
xk, yk, r = 5.0, 3.0, 0.30 # Координати центра та радіус корзини
g, h = 9.8, 0.05 # Прискорення вільного падіння та крок системи
t = arange(x0, 1.5, h) # Часовий інтервал
plt.subplots(figsize=(4, 2))
plt.axes(xlim=(-1, ceil(max([v0*cos(a0)*i+x0 for i in t])+1)),
ylim=(ceil(min([-(g/2)*i**2+v0*sin(a0)*i+y0 for i in t])-1), ceil(max([-(g/2)*i**2+v0*sin(a0)*i+y0 for i in t])+1)))
plt.plot([v0*cos(a0)*i+x0 for i in t],
[-(g/2)*i**2+v0*sin(a0)*i+y0 for i in t],
'-',
color='green',
label = u'Аналітичний роз\'вязок')
plt.plot(euler(lambda t: v0*cos(a0), x0, h, t),
euler(lambda t: -g*t+v0*sin(a0), y0, h, t),
'--',
color='red',
label = u'Метод Ейлера')
plt.plot([xk-r, xk+r], [yk, yk], color='black', linewidth=4, alpha=0.75)
plt.grid(True)
plt.legend(loc='upper right', shadow=True)
plt.title(u'Траекторія руху м\'яча при кроці h=%f'%h)
plt.subplots_adjust(top=2.0, right=2.0)
for spine in ['top', 'right', 'bottom', 'left']:
plt.gca().spines[spine].set_position('zero')
accuracy, start = 0, False
plt.plot(x0, y0, 'o', ms=30, color='orange', alpha=0.75)
for i in range(len(t)):
curr_x = v0*cos(a0)*t[i]+x0
curr_y = -(g/2)*t[i]**2+v0*sin(a0)*t[i]+y0
if (curr_y >= yk):
start = True
if (curr_y <= yk and start is True):
plt.plot(curr_x, yk, 'o', ms=30, color='orange', alpha=0.75)
plt.text(curr_x-r, yk+r, u't = %.2f'%t[i])
break
if (i == len(t)-1 and start is False):
plt.plot(curr_x, curr_y, 'o', ms=30, color='orange', alpha=0.75)
plt.text(curr_x-r, curr_y+r, u't = %.2f'%t[i])
plt.show()