弾道計算

Download script from .\cannonball_flat.py


import sys
import numpy as np
from numpy import sqrt, exp, sin, cos, tan, pi
from matplotlib import pyplot as plt


"""
弾道計算
"""



#===================================
# 定数
#===================================
# 円周率
pi = 3.14159265358979323846

# 万有引力定数
G = 6.67430e-11 # m^3/kg/s^2

# 地球の質量、半径
Me = 5.972e24 # kg
Re = 12756.274e3 * 0.5 # m

# 重力加速度 g = G*Me/Re^2
g = 9.8 # m/s^2

# 砲弾 (cannonball) の質量 計算結果には影響しない
mc = 1.0 # kg

# 射出速度、角度
v0 = 100.0 # m/s
Q0 = 45.0 # 度

# 計算時間間隔
dt = 1

# 最大ステップ数
nmax = 100


#===================================
# グラフ設定
#===================================
fontsize = 20
# グラフの更新時間
tsleep = 0.1 # s


#============================
# 起動時引数で初期値を更新
#============================
argv = sys.argv
if len(argv) >= 2:
    v0 = float(argv[1])
if len(argv) >= 3:
    Q0 = float(argv[2])
if len(argv) >= 4:
    dt = float(argv[3])
if len(argv) >= 5:
    nmax = int(argv[4])
if len(argv) >= 6:
    tsleep = float(argv[5])


def usage():
    print("")
    print("使い方: python cannonball_flat.py 初速度(m/s) 射出角度(度) 時間間隔(s) 繰り返し回数 描画更新時間(s)")
    print("例1: python cannonball_flat.py")
    print(" 初期値 v0 = 100.0 m/s, Q0 = 45度, dt = 1 sで計算")
    print("例2: python cannonball_flat.py 10000 20 10")
    print(" v0 = 10000.0 m/s, Q0 = 20度, dt = 10 sで計算")
    print("")


# 質点に係る力のベクトル Fx, Fy を返す
def force(x, y):
    global g, mc

    return 0.0, -mc * g

def main():
    vx0 = v0 * cos(Q0 * pi / 180.0)
    vy0 = v0 * cos(Q0 * pi / 180.0)
    print("g(R0={:12.4g} m)={:10.4f} m/s^2".format(Re, G * Me / Re / Re))
    print("g={:10.4f} m/s^2".format(g))
    print("vx0 = {:10.4f} m/s".format(vx0))
    print("vy0 = {:10.4f} m/s".format(vy0))
    print("dt = {} s".format(dt))

# 初期値を配列に設定
    t = [0.0]
    vx = [vx0]
    vy = [vy0]
    x = [0.0]
    y = [0.0]

# グラフの作成
    fig = plt.figure(figsize = (8, 8))
    ax1 = fig.add_subplot(1, 1, 1)
    ax1.set_xlabel("x (m)", fontsize = fontsize)
    ax1.set_ylabel("y (m)", fontsize = fontsize)
    ax1.tick_params(labelsize = fontsize)
    plotdata, = ax1.plot(x, y, linestyle = '-', linewidth = 0.5, marker = 'o', markersize = 2.0)
# 地表を描画
    xg = [0.0, Re]
    yg = [0.0, 0.0]
    ax1.plot(xg, yg, linestyle = '-', linewidth = 0.5, color = 'red')

# 計算ループ開始
    print("{:8}: {:10}\t{:10}\t{:10}\t{:10}".format('t(s)', 'vx(m/s)', 'vy(m/s)', 'x(m)', 'y(m)'))
    for i in range(1, nmax):
        tt = i * dt
# m(vx[i] - vx[i-1]) / dt = Fx = 0
# m(vy[i] - vy[i-1]) / dt = Fy = -mg
        fx, fy = force(x[i-1], y[i-1])
        vxt = vx[i-1] + dt * fx / mc
        vyt = vy[i-1] + dt * fy / mc
# (x[i] - x[i-1]) / dt = vx[i-1]
# (y[i] - y[i-1]) / dt = vy[i-1]
        xt = x[i-1] + dt * vx[i-1]
        yt = y[i-1] + dt * vy[i-1]

        vx.append(vxt)
        vy.append(vyt)
        x.append(xt)
        y.append(yt)
        print("{:8g}: {:10.4g}\t{:10.4g}\t{:10.4g}\t{:10.4g}".format(tt, vxt, vyt, xt, yt))

# グラフの表示データを更新
        plotdata.set_data(x, y)
# グラフ表示を更新
        ax1.set_xlim([min(x), max(x)])
        ax1.set_ylim([min(y), max(y)])
        plt.tight_layout()
        plt.pause(tsleep)

# 地表に激突したら計算ループ終了
        if yt <= 0.0:
            break


    print("プログラムを終了するにはENTERキーを押してください")
    input()

    usage()

if __name__ == "__main__":
    main()