Pythonで学ぶ物理学 -01- 斜方投射

プログラミング

どーも、masukenです。

今回の記事は、Pythonで物理シミュレーションを行おうという記事です。
どのような人に向けた記事かというと、

・Python初心者で基本的なことを知りたい。
・Pythonで何が出来るのかを知りたい。
・Pythonで物理シミュレーションをやってみたい。

という人向けの記事になっています。
第一回目は高校の物理でも最初の方にならう斜方投射をテーマにしています。

スポンサーリンク

斜方投射について

まずは、斜方投射についておさらいしてみたいと思います。
斜方投射とは以下のような動作を指します。

斜方投射(しゃほうとうしゃ)とは物体をある初速度をもって空中に投げ出す動作である。空気抵抗が十分小さく無視できる場合、斜方投射された物体の軌跡は放物線を描く。斜方投射された物体は重力の影響のみを受けるので、斜方投射された物体の運動も自由落下の一種とみなすことができる。

出典 フリー百科事典「Wikipedia」

つまり、簡単に言うと野球やサッカーなどで、ボールを投げたり、打ったり、蹴ったりした時に、
ボールが放物線を描いて動く運動のことを指しています。
(実際には、空気抵抗やボールの回転、風の影響で運動が変わってしまう。)

斜方投射では、

  • 物体の初速度
  • 物体を投げ出す角度(投射角)

が初期条件として与えられます。
そして、物体の軌跡は次の式で表すことができます。

x = vx * t
y = vy * t - (1/2) * g(重力加速度) * t^2
x, yはそれぞれ水平方向、鉛直上向きの距離。vx, vyはx成分、y成分の初速度。tは投射してからの経過時間を表す。
初速度(vx, vy)の求め方

まずは、これらの条件を元に斜方投射をPythonで実装してみたいと思います。

Pythonで斜方投射

斜方投射のコードを解説

最初、xとyは空のリストを作ります。後でappendしてxとyの値を入れていきます。
t(時間)はnumpyのlinspaceで配列を作ります。
linspace(start, stop, num)となっており、始点、終点、要素数を指定して配列を作ります。
Pythonのlist,range関数を使わなかったのは、小数点を表現するのが少し面倒になるからです。
tや初速度v、角度thetaは適当に設定します。

12行目からは初速度vと角度thetaからvx,vyを求める関数を書いています。
cosなどを計算する場合はdegreeで計算するのが面倒なので、
radianに変換してからsin,cosに代入しています。

19行目からはグラフを作る関数を書いています。
タイトルやラベル、プロットする値を指定しています。
今回の場合では、x,yのグラフを描きたいのでplt.plot(x,y)としています。
そのあとの’o’はグラフのプロットの形を示しています。

27行目でvx,vyを求めるために12行目で作ったcal_vx_vy関数を呼び出しています。
引数にはvとtheta、返り値はvx,vyを指定しています。

29行目からx,yに値を入れていきます。
for i in t: とすることで、iにtの要素を順に入れていきます。
30行目に出てきたappend()はリストの最後に()内の値を追加していく関数です。
iにtを代入して計算した値をx,yにそれぞれ追加します。
32行目はyの値が0を下回った時にforループを止めるための文です。
y[-1]はyの最後の要素、つまり直前に追加された要素を表しています。

最後にmake_graph関数を呼び出して、コードは終了です。
実際にグラフを作るとこのようになります。

何か違和感があります。

上のコードでは、投射角を30度に設定したはずですが、
上のグラフでは、投射角が60度近くに見えます。

これは、グラフのアスペクト比が合っていないからです。
x軸とy軸の目盛りを見てみると、目盛り1個あたりの大きさがx軸とy軸で違うことが分かります。
そのために、make_graph関数を少しいじってグラフを綺麗にしましょう。
make_graph関数を以下のように修正します。

make_graph関数に5~7行目を追加しました。
xlim, ylimはそれぞれx軸、y軸の上限と下限を決めるものです。
また、plt.axes().set_aspect(‘equal’)でグラフのアスペクト比を調整しています。
これでグラフを出力すると以下のようになります。

グラフのアスペクト比が揃い、投射角が30度になりました。
ただ、この場合にはylim[-2, 40]となっておりグラフの上の方が余っていますね。
ylimを調整して、いい感じの形に調整してください。

max値を求める

斜方投射の問題でよく出るのは、
物体がどの高さまで上昇したのか?やどこまで飛んだのか?や
それに要した時間(地面と衝突するまでの時間)ですよね。
それらを求めるコードを書きたいと思います。

高さの最大値、飛んだ距離の最大値とその時の時間を求める

リストの最大値を求めたいときは、max()関数を使うことで求めることができます。
最小値を求めたいときはmin()を使います。

求めたいのは、ボールの高さの最大値と、飛んだ距離の最大値なので、
max(x),max(y)とすることで飛んだ距離と、高さの最大値を求めることができます。

最大値を取った時の時間を求めたい場合はindexを取得します。
リスト名.index(値)とすることで、そのリストが値を取ったindexを取得することができます。
そのindexを時間tの配列に入れることで最大値を取った時の時間を求めることができます。
以下、上のコードの出力となります。

上のコードの出力結果

上の出力結果を見てみると、地面に衝突するまでの時間が高さの最大値を取った時の時間の
約2倍となっています。
ちょうど2倍になっていないのは、flight timeは計算の都合上
y<0となった時の時間を示しているためだと思われます。
→つまり、ちょうど地面に衝突した時間ではなく、少し地面にめり込んでいる。
もっと配列tを細かくとれば、正確に地面に衝突した時間が分かりますが、
そこまでは必要ないでしょう。

まとめ

今回は、Pythonを使って物理学の最初の方で学ぶ、斜方投射をプログラミングで表現してみました。

今後もPythonを使って物理学や数学で学んだことをコードにしてみようと思います。

それでは、また。

コメント

タイトルとURLをコピーしました