自分で作った関数やクラスをライブラリとしてまとめると、複数のスクリプトから再利用できます。
.py ファイルがモジュールです。他のファイルから import できます。
simlec/utils.py:
"""ユーティリティ関数"""
import numpy as np
def calc_norm(v):
"""ベクトルのノルムを計算"""
return np.sqrt(np.sum(v**2))
def deg2rad(deg):
"""度をラジアンに変換"""
return deg * np.pi / 180.0# import文でモジュールを読み込む
from simlec.utils import calc_norm, deg2rad
v = np.array([3, 4])
print(calc_norm(v)) # 5.0
print(deg2rad(90)) # 1.5707...複数のモジュールをまとめたディレクトリがパッケージです。__init__.py を置くことでパッケージになります。
simlec/
├── __init__.py # パッケージの初期化
├── rocket.py # ロケットクラス
├── integrators.py # 数値積分法
└── utils.py # ユーティリティ
よく使う機能をパッケージ直下から使えるようにします。
simlec/__init__.py:
"""小型ロケット飛翔シミュレータ"""
from .rocket import Rocket
from .integrators import euler_step, rk4_step
__version__ = "1.0.0"これにより、以下のように使えます:
from simlec import Rocket"""ロケットクラス"""
import numpy as np
class Rocket:
"""ロケットを表すクラス"""
def __init__(self, mass, thrust, Cd=0.5, A=0.01):
self.mass = mass
self.thrust = thrust
self.Cd = Cd
self.A = A
# 状態
self.position = np.array([0.0, 0.0, 0.0])
self.velocity = np.array([0.0, 0.0, 0.0])
def calc_drag(self, rho=1.225):
"""空気抵抗を計算"""
v_mag = np.linalg.norm(self.velocity)
if v_mag < 1e-10:
return np.zeros(3)
v_unit = self.velocity / v_mag
drag_mag = 0.5 * rho * v_mag**2 * self.Cd * self.A
return -drag_mag * v_unit
def calc_forces(self, thrust_direction):
"""全ての力を計算"""
# 推力
F_thrust = self.thrust * thrust_direction
# 重力
F_gravity = np.array([0, 0, -self.mass * 9.8])
# 空気抵抗
F_drag = self.calc_drag()
return F_thrust + F_gravity + F_drag"""数値積分法"""
import numpy as np
def euler_step(f, y, t, dt):
"""
オイラー法の1ステップ
Parameters
----------
f : callable
微分方程式 dy/dt = f(t, y)
y : array
現在の状態
t : float
現在時刻
dt : float
時間刻み
Returns
-------
array
次の状態
"""
return y + dt * f(t, y)
def rk4_step(f, y, t, dt):
"""
ルンゲクッタ4次法の1ステップ
Parameters
----------
f : callable
微分方程式 dy/dt = f(t, y)
y : array
現在の状態
t : float
現在時刻
dt : float
時間刻み
Returns
-------
array
次の状態
"""
k1 = f(t, y)
k2 = f(t + dt/2, y + dt/2 * k1)
k3 = f(t + dt/2, y + dt/2 * k2)
k4 = f(t + dt, y + dt * k3)
return y + dt/6 * (k1 + 2*k2 + 2*k3 + k4)"""ユーティリティ関数"""
import numpy as np
def calc_norm(v):
"""ベクトルのノルムを計算"""
return np.linalg.norm(v)
def normalize(v):
"""単位ベクトルを返す"""
n = calc_norm(v)
if n < 1e-10:
return np.zeros_like(v)
return v / n
def deg2rad(deg):
"""度をラジアンに変換"""
return np.radians(deg)
def rad2deg(rad):
"""ラジアンを度に変換"""
return np.degrees(rad)from simlec import Rocket
from simlec.integrators import euler_step, rk4_step
from simlec.utils import deg2rad
# ロケットの作成
rocket = Rocket(mass=1.0, thrust=50.0)
# シミュレーション...scripts/01_python/06_packaging_example.py を実行してください:
python scripts/01_python/06_packaging_example.pyこれで Part 1: Pythonの使い方 は終了です。