どうも、ヨスケ@Python初心者です。
GWに入った5/1より、毎日30分程度、Pythonプログラミングの学習を進めています。
今回は学習を進めてきた成果確認として、今ある知識でできるプログラムを作成して動かしてみようと思います。
まだまだ初心者なので、できることは限られていますが、アウトプットすることで理解も深まりますので、積極的に行っていきます。
■この記事でお話しすること
初めてのPythonプログラムで等加速度運動シミュレーションを作ってみた!
・「猿とヤシの実」プログラム
・オブジェクト指向は便利
・成果物をイメージしてプログラムを作るべし!
■Pythonの学習方法
以前の記事でもヨスケのプログラミング学習方法をご紹介しました。
・お作法の理解
プログラミング学習サイト「Progate」
・環境構築やコーディングに関する追加学習
Youtubeチャンネル「キノコード/ プログラミング学習チャンネル」
・学習したことを用いてアウトプット
理解したことを使って実際にプログラムを作る
このサイクルを回しながら、最終的に作りたいプログラムが作れるところまでやり切ります。
■これまでの学習の進捗
これまでのPythonプログラミング学習で、以下のコーディングルールを学びました。
- print()による表示
print("りんごを買いましょう")
- input()によるキーボード入力
count = int(input("りんごをいくつ買いますか?:"))
- if文による条件分岐
if count>10: print("買いすぎです") else : print(str(count)+"個買います。")
- リスト
foods = ["banana", 100, "apple",200, "cherry",] print(foods)
- for/while 文による繰り返し処理
i=1 while i <=10 : print("羊が"+str(i)+"匹") i += 1
- 関数
def calc_price(food_price, count): return food_price*count print(str(calc_price(100,100)))
- クラス, インスタンス
class Food: def __init__(self, name, price): self.menu_name = name self.menu_price = price apple = Food("リンゴ", 100) print(apple.menu_name +":"+ str(apple.menu_price))
クラスを作ることができるようになり、一旦区切りが良いところまで来ましたので、
今の知識でプログラムを作ってみます。
■今回の成果物
プログラミング学習の目標は「webスクレイピングによるショッピング履歴の自動取得」です。
まだまだ、道のりの途上ですので、今ある知識でできるプログラムを作ります。
色々考えましたが、ちょうど仕事で運動方程式を解く機会がたまたまあったので、物理現象を題材にしようと思います。
「猿とヤシの実」
高校で物理を専攻された人は良く知っている問題です。木から落ちるお猿にヤシの実を投げて当てるのですが、
「お猿が落ちる瞬間に、お猿がいた方向に投げれば必ず命中する」
といったものです。
ホントかよ!?というものですが、ホントです。※空気抵抗などない理想環境ですが
この「猿とヤシの実」を検証できるプログラムを作成することにします。
ただし、お猿にヤシの実を当てるのはかわいそうですので、
今回は「お猿が石を投げて、落ちるヤシに当てる」シチュエーションに変えて

おサルがヤシの実に石を投げます
オブジェクト指向とクラス
Pythonはオブジェクト指向をサポートしている言語です。
「オブジェクト指向」について、ヨスケは学生時代もオブジェクト指向言語のJavaを使っていたのですが、よく理解できなかったと記憶しています。ですが、正確に理解しなくてもプログラムは書けたのでふんわり理解すれば良いかと思います。
完璧主義は失敗のもと。
ヨスケの理解は「クラス」という設計図を使って、「インスタンス」という物を生成して、それぞれ独立した処理させる~くらいです。
たとえば、「自動車」というクラスを準備して、その中にクルマの 走る・曲がる・止まる の動きを関数として定義して大量にインスタンスを生成してやれば、交通環境シミュレーションなどが可能です。基本のクラス一つを準備すれば大量のオブジェクトを一つ一つ作る必要がないため、オブジェクト指向はとても便利であるという理解をしています。
正確な定義などは、プロになるのであれば必要かと思いますが、自身の作業の効率化目的でプログラミングを勉強している人は、言語を使うことができれば問題ないため、わからなくて良いと思います。
斜方投射と自由落下(等加速度運動)
地球上に存在するどんなものも、地球との引力(重力)の影響を受けます。投げれば放物線を描きながら落下していきます。この動きをクラスとして記述します。
一般式で表現することができれば、クラスとして定義して使用できます。
横方向をx, 縦方向をyとして、物体の位置をお猿の位置を原点としてx[m], y[m]、速度成分をvx[m/s], vy[m/s]とします。
加速度について、横方向はax = 0[m/s^2], 縦方向は重力加速度 ay = -9.8[m/s^2]です。
位置(x0, y0)から初速(vx0, vy0)で投射された物体の運動(時刻t時点の位置、速度)は以下のように記述できます。
速度 Vx(t) = ax*t + vx0,
Vy(t) = ay * t + vy0
位置 X(t) = 1/2 * ax *t*t + vx0 *t + x0,
Y(t) = 1/2 *ay*t*t + vy0*t + y0
上記の物理モデルをそのままクラスとして定義しました。
等加速度運動をする物理クラスPysical
#物理クラス Pysical
class Pysical:
#インスタンス生成時処理
def __init__(self,name,x,y,vx,vy):
self.name = name
#位置、速度 初期値設定
self.x0 = x
self.y0 = y
self.vx0 = vx
self.vy0 = vy
#横方向は加速度なし
self.ax = 0
#縦方向は重力加速度 -9.8 m/s2
self.ay = -9.8
#時刻tの位置、速さ
self.X = self.x0
self.Y = self.y0
self.VX = self.vx0
self.VY = self.vy0
#時刻tのx座標計算
def get_x_posision(self,t):
self.VX= self.vx0 + self.ax *t
self.X = self.ax * t*t /2 + self.vx0 * t + self.x0
return self.X
#時刻tのy座標計算
def get_y_posision(self,t):
self.VY = self.vy0 + self.ay*t
self.Y = self.ay * t*t /2 + self.vy0 * t + self.y0
return self.Y
おサル、ヤシの実のインスタンス生成
#初期値 お猿位置
x1 = 0
y1 = 0
#ヤシの実の方向
theta = math.pi / 3
#ヤシの実までの直線距離 [m]
Length = 15
#つぶて投擲速さ [m/s]
vel = math.sqrt(100)
#成分分解
vx1 = vel * math.cos(theta)
vy1 = vel * math.sin(theta)
#ヤシの実位置
x2 = Length * math.cos(theta)
y2 = Length * math.sin(theta)
#おさるのつぶてと、ヤシの実のインスタンス生成
monkey = Pysical("monkey",x1,y1,vx1,vy1)
yashinomi = Pysical("yashinomi",x2,y2,0,0)
おサルのつぶてとヤシの実の当たり判定
#繰り返し処理準備
#時刻
i=0
#距離
distance = Length
#データ格納用配列を準備
data=[]*1
#繰り返し処理
while i < 20:
#時刻 i secのとき
#おさるのつぶての位置計算
x1 = monkey.get_x_posision(i)
y1 = monkey.get_y_posision(i)
#ヤシの実の位置計算
x2 = yashinomi.get_x_posision(i)
y2 = yashinomi.get_y_posision(i)
#おさるのつぶてとヤシの実の距離計算
distance = math.sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2))
#データ格納用配列への入力 時刻、おさるのつぶて座標、ヤシの実座標、距離
data_pls = [i, x1,y1,x2,y2,distance]
#dataにdata_plsを行追加
data.append(data_pls)
#あたり判定
if distance < 0.0001:
print("命中!!")
print(str(i)+"秒後に"+ str(x1)+","+str(y1)+"で命中しました。")
break
#当たらず、石が通り過ぎた場合はbreak
elif x1 > x2:
print("命中なし。。。シミュレーションを終了します:")
break
#時刻を0.001秒進める
i += 0.01
csvファイルにシミュレーション結果を出力
#結果をCSVファイルに書き出し
with open('test.csv', 'w')as file:
writer=csv.writer(file,lineterminator='\n')
writer.writerows(data)
シミュレーション結果の確認
出力したcsvファイルのデータを確認しましょう。
たしかに当たりました!
ソースの中のLengthやvel,thetaの値を変えても毎回当たります。面白いですね◎
まとめ
今回はここまで半月で学習したPythonプログラミングを使って、高校物理の運動趣味レーションを作成しました。
・オブジェクト指向の正確な理解はしていませんが、大規模シミュレーションなど、システムの規模が大きくなる場合は、オブジェクト指向言語はかなり有用なのだと思います。
・学習でインプットをして知識があっても、その知識を使えるかどうかは実践をしないとわからないので、勉強した後はアウトプットを頻繁にやると良いです。今回のソースを書く際も微妙に理解できていないところがたくさんあり、修正をしていくうちに理解が深まりました。
・Pythonのソースは直感的に理解しやすいです。また、もともとヨスケは同じオブジェクト指向言語のJavaもかじったことがありましたので、何かしらのプログラムをかじった人であれば、Pythonはとっつきやすい言語だと思います。。
計算した結果をcsvファイルへ出力もできましたので、今後、progateでの学習がひと段落したらwebスクレイピングの処理もサンプルコードの理解をしながら作ってみようと思います。
以上、参考になればうれしいです。