はじめに
高校力学の問題で、
『空気抵抗がなければ、地上の人がボールを最も遠くに投げることができるのは、地面から何度の角度で投げたときか?』
という有名な問題がある。
これは、水平方向と鉛直方向で運動方程式を立てることで解くことができる。
解としては、有名角45度である。
しかし、実際の場合は空気抵抗を考慮する必要性が出てくる。こうなると手計算では解くのは難しい。そこで、今回は計算機を用いて、そのような場合における投げる角度の最適解を推定する。
具体的には、空気抵抗がある場合とない場合のボールの軌道をPythonを用いてまずは描写する。
次に、空気抵抗がない場合では、投げる角度が45度のとき、最も遠くにボールを飛ばせるということをシミュレーションする。
最後に、空気抵抗がありの場合では、投げる角度は45度と比較しどうなるのかを調査する。
運動方程式
ボールを投げたあと、空中のボールに対する運動方程式を考える。
ボールの質量を$m$,重力加速度を$g$,空気抵抗に関する係数を$k$とする。
ただし、空気抵抗は、ボールの推進方向に対して逆向きに働くものとする。
この場合のボールの運動方程式は、速度ベクトル、加速度ベクトルを$\textbf{v},\textbf{a}$とすると以下のようになる。
m\textbf{a}=-m\textbf{g}-k\textbf{v}
プログラム
上記の運動方程式に対して、オイラー法を使った数値計算を行う。
ボールの軌道
地面から45度の角度でボールを投げる。
空気抵抗なし
import numpy as np
import matplotlib.pyplot as plt
import japanize_matplotlib
import math
t_max=0.1
delta_t=1.0*10**(-5)
#ボールの質量
m=1.0
#空気抵抗
k=0
#重力加速度
g=9.8
#初速度の大きさ
v_0=1
theta_degree=45
theta=theta_degree*math.pi/180
t_ary=[]
x_ary_t=[]
xx_ary_t=[]
yy_ary_t=[]
def gra(v_ary):
t=0
x_ary=np.zeros((2))
while(x_ary[1]>=0):
a_ary=(-m*np.array([0,g])-k*v_ary)/m
v_ary=v_ary+a_ary*delta_t
x_ary=x_ary+v_ary*delta_t
x_ary_t.append(x_ary)
xx_ary_t.append(x_ary[0])
yy_ary_t.append(x_ary[1])
t_ary.append(t)
t=t+delta_t
return x_ary_t,t_ary
#初速度
v_ary=m*np.array([v_0*np.cos(theta),v_0*np.sin(theta)])
x_ary_t,t_ary=gra(v_ary)
n=100
xx=np.linspace(0,xx_ary_t[-1],n)
yy=math.tan(theta)*xx
#投げる方向
plt.plot(xx,yy,":",color="black",label="投げる方向")
#ボールの軌道
plt.plot(xx_ary_t,yy_ary_t,color="blue",label="ボールの軌道")
plt.xlabel("x軸")
plt.ylabel("y軸")
plt.legend()
plt.savefig("ボールの軌道_空気抵抗なし.png")
plt.show()
このように、おなじみの放物線軌道となる。
空気抵抗あり
空気抵抗の係数:$k=100$として計算を行った。
このように、水平方向の速度がほぼなくなった瞬間、ほぼ垂直に落下してしまう。
最大飛距離
飛距離の逆数を目的関数として最急降下法を用いることで、最大飛距離をたたき出す、角度を推定する。ただし、初期角度を30度とした。
#野球ボールを一番遠くに投げるためには、地面から45度の角度で投げればいい??
#空気抵抗がない場合
import numpy as np
import matplotlib.pyplot as plt
import japanize_matplotlib
import math
delta_t=1e-5
delta_degree_theta=1
alpha=10
#ボールの質量
m=1.0
#空気抵抗
k=0
#重力加速度
g=9.8
#初速度の大きさ
v_0=1
def gra(theta_degree):
theta=theta_degree*math.pi/180
v_ary=np.array([v_0*np.cos(theta),v_0*np.sin(theta)])
t_ary=[]
x_ary_t=[]
xx_ary_t=[]
yy_ary_t=[]
t=0
x_ary=np.zeros((2))
while(x_ary[1]>=0):
a_ary=(-m*np.array([0,g])-k*v_ary)/m
v_ary=v_ary+a_ary*delta_t
x_ary=x_ary+v_ary*delta_t
x_ary_t.append(x_ary)
xx_ary_t.append(x_ary[0])
yy_ary_t.append(x_ary[1])
t_ary.append(t)
t=t+delta_t
return xx_ary_t,yy_ary_t,t_ary
#初期のボールを投げる角度
theta_degree=30
def d_length(theta_degree):
theta_degree1=theta_degree
xx_ary_t,yy_ary_t,t_ary=gra(theta_degree1)
x_inv1=1/(xx_ary_t[-1])
theta_degree2=theta_degree+delta_degree_theta
xx_ary_t,yy_ary_t,t_ary=gra(theta_degree2)
x_inv2=1/(xx_ary_t[-1])
d_x_inv=(x_inv2-x_inv1)/delta_degree_theta
return d_x_inv
num=50
theta_degree_ary=[]
i_ary=[]
for i in range(num):
#初速度
theta_degree=theta_degree-alpha*d_length(theta_degree)
theta_degree_ary.append(theta_degree)
i_ary.append(i)
plt.plot(i_ary,theta_degree_ary)
plt.xlabel("試行回数[回]")
plt.ylabel("ボールを投げる角度[度]")
plt.savefig("最大距離を取る初期角度_空気抵抗なし.png")
plt.show()
最急降下法によって飛距離の最大値を取る角度を推定したところ、45度周辺になることが分かった。
空気抵抗あり
空気抵抗の係数:$k=100$として計算を行った。
このように、15度付近に漸近したことから、比較的水平に近い方向に投げれば飛距離を稼ぐことができる。
まとめ
今回は、高校の力学でよく扱う問題を数値計算で考察してみた。結果として、空気抵抗がある場合は、空気抵抗がない場合と比べてより水平方向に投げれば、遠くに投げることができる。
この問題は、空気抵抗がない場合は、議論が盛んだがある場合はあまり議論されないので、本記事で扱った。



