STK(Systems Tool Kit、旧称AGI STK)は、航空宇宙分野で広く利用されているシミュレーションソフトウェアです。衛星の軌道解析、地上局との通信解析、センサカバレッジの分析など、ミッション設計に必要な機能を備えています。
今回は、STKを使った衛星コンステレーションの構築方法と、Pythonでの代替的なシミュレーション手法について解説します。
本記事の内容
- STKの概要と主要機能
- Walkerコンステレーションの設計パラメータ
- STKでのコンステレーション構築手順
- Pythonでのコンステレーション解析
前提知識
この記事を読む前に、以下の記事を読んでおくと理解が深まります。
STKの概要
STKは以下の主要機能を持ちます。
- 軌道伝搬: ケプラー軌道、J2摂動、高精度摂動モデル(HPOP)
- アクセス解析: 衛星間、衛星-地上局間の可視性計算
- カバレッジ解析: 地上のグリッドポイントに対するカバー率
- 通信リンク解析: リンクバジェット計算
- 3D可視化: 地球と軌道の3Dレンダリング
コンステレーション設計の基本
Walkerデルタパターン
Walker $i:T/P/F$ パターンでコンステレーションを定義します。
$$ \Omega_p = \frac{2\pi p}{P}, \quad M_{p,s} = \frac{2\pi s}{S} + \frac{2\pi F p}{T} $$
ここで $S = T/P$ は1軌道面あたりの衛星数です。
設計変数と目的関数
コンステレーション最適化の典型的な定式化は次の通りです。
$$ \min_{T, P, F, h, i} \quad T \quad (\text{総衛星数の最小化}) $$
$$ \text{subject to:} \quad C(\bm{x}) \geq C_{\text{req}} \quad (\text{被覆率条件}) $$
ここで $C(\bm{x})$ は設計変数 $\bm{x} = (T, P, F, h, i)$ に対する被覆率です。
Pythonでのコンステレーション解析
STKの代替として、Pythonでコンステレーションの被覆率解析を行ってみましょう。
import numpy as np
import matplotlib.pyplot as plt
# 定数
Re = 6371.0 # 地球半径 [km]
mu = 398600.4418 # 重力定数 [km^3/s^2]
def walker_positions(T, P, F, h, inc_deg, t=0):
"""Walkerコンステレーションの全衛星位置を計算
Returns: (lats, lons) in degrees
"""
S = T // P
a = Re + h
T_orb = 2 * np.pi * np.sqrt(a**3 / mu)
n = 2 * np.pi / T_orb
omega_e = 2 * np.pi / 86164.1
inc = np.radians(inc_deg)
lats = []
lons = []
for p in range(P):
raan = 2 * np.pi * p / P
for s in range(S):
M0 = 2 * np.pi * s / S + 2 * np.pi * F * p / T
M = M0 + n * t
lat = np.degrees(np.arcsin(np.sin(inc) * np.sin(M)))
lon_inertial = np.arctan2(np.sin(M) * np.cos(inc), np.cos(M))
lon = np.degrees(lon_inertial + raan - omega_e * t) % 360
if lon > 180:
lon -= 360
lats.append(lat)
lons.append(lon)
return np.array(lats), np.array(lons)
def coverage_analysis(sat_lats, sat_lons, h, eps_min_deg, grid_res=5):
"""グリッドベースの被覆率解析
Returns: coverage_fraction, grid_lats, grid_lons, covered_grid
"""
eps_min = np.radians(eps_min_deg)
theta_max = np.arccos(Re / (Re + h) * np.cos(eps_min)) - eps_min
theta_max_deg = np.degrees(theta_max)
# 地上グリッド
grid_lats = np.arange(-90, 91, grid_res)
grid_lons = np.arange(-180, 181, grid_res)
lat_grid, lon_grid = np.meshgrid(grid_lats, grid_lons)
covered = np.zeros_like(lat_grid, dtype=bool)
for slat, slon in zip(sat_lats, sat_lons):
# 衛星直下点からの角距離
dlat = np.radians(lat_grid - slat)
dlon = np.radians(lon_grid - slon)
a_hav = np.sin(dlat/2)**2 + \
np.cos(np.radians(slat)) * np.cos(np.radians(lat_grid)) * \
np.sin(dlon/2)**2
angular_dist = 2 * np.arcsin(np.sqrt(np.clip(a_hav, 0, 1)))
covered |= (angular_dist <= theta_max)
# 面積重み付きカバー率
weights = np.cos(np.radians(lat_grid))
coverage = np.sum(covered * weights) / np.sum(weights)
return coverage, lat_grid, lon_grid, covered
# コンステレーション設計の比較
configs = [
("Small (24/3/1)", 24, 3, 1, 1100, 53),
("Medium (48/6/1)", 48, 6, 1, 550, 53),
("Large (72/6/1)", 72, 6, 1, 550, 53),
]
fig, axes = plt.subplots(1, 3, figsize=(18, 5))
for idx, (name, T, P, F, h, inc) in enumerate(configs):
lats, lons = walker_positions(T, P, F, h, inc, t=0)
cov, lat_g, lon_g, covered = coverage_analysis(lats, lons, h, 25)
axes[idx].pcolormesh(lon_g, lat_g, covered.astype(float),
cmap='RdYlGn', alpha=0.5)
axes[idx].scatter(lons, lats, c='red', s=20, zorder=5)
axes[idx].set_xlim(-180, 180)
axes[idx].set_ylim(-90, 90)
axes[idx].set_xlabel('Longitude [deg]')
axes[idx].set_ylabel('Latitude [deg]')
axes[idx].set_title(f'{name}\nCoverage: {cov*100:.1f}%')
axes[idx].grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
# 衛星数と被覆率の関係
print("=== 衛星数と被覆率の関係 ===")
sat_counts = [12, 24, 36, 48, 60, 72, 96, 120]
coverages = []
for T_sat in sat_counts:
P_planes = max(3, T_sat // 12)
lats, lons = walker_positions(T_sat, P_planes, 1, 550, 53, t=0)
cov, _, _, _ = coverage_analysis(lats, lons, 550, 25, grid_res=5)
coverages.append(cov)
print(f" T={T_sat:3d}, P={P_planes}: Coverage = {cov*100:.1f}%")
fig, ax = plt.subplots(figsize=(8, 5))
ax.plot(sat_counts, [c * 100 for c in coverages], 'bo-', linewidth=2)
ax.set_xlabel('Number of Satellites')
ax.set_ylabel('Coverage [%]')
ax.set_title('Coverage vs Number of Satellites (h=550km, eps_min=25deg)')
ax.grid(True)
ax.set_ylim(0, 105)
plt.tight_layout()
plt.show()
まとめ
本記事では、STKを使った衛星コンステレーションの構築方法について解説しました。
- STKは航空宇宙分野の標準的なシミュレーションツールである
- Walkerデルタパターンはコンステレーション設計の基本的な手法で、$T/P/F$ パラメータで定義される
- コンステレーション最適化は衛星数最小化と被覆率制約の問題として定式化できる
- Pythonでも簡易的なコンステレーション解析が可能であり、設計の初期検討に活用できる
次のステップとして、以下の記事も参考にしてください。