コンテンツにスキップ

Transfer Burn with TCM — WASM Guest Plugin

円軌道 → 円軌道の Hohmann 遷移 + TCM (Trajectory Correction Maneuver) を 実装した最小 plugin。1 plugin の中で姿勢制御 (RW) と推力指令 (thruster) を同時に司令 する composite controller の example でもある。

毎 tick で以下を同時に出力:

出力内容
rw: RwCommand::Torques(…)body-Y を velocity 方向に向ける PD 姿勢制御
thruster: ThrusterCommand::Throttles(…)state machine で決定した throttle

これらを Command の別フィールドに載せて同じ Option<Command> で返すだけ。 WIT v0 の Command record は rw / mtq / thruster をそれぞれ option で持っているので、1 plugin でいくつでも同時司令できる。

stateDiagram-v2
    direction LR
    [*] --> FirstBurn
    FirstBurn --> Coast: sma ≥ (r₁+r₂)/2
    Coast --> SecondBurn: coast_elapsed ≥ T_transfer/2
    SecondBurn --> Trim: sma ≥ r_target
    Trim --> Trim: sma < r_target − deadband<br/>→ throttle = 1
    note right of FirstBurn
        prograde 連続噴射で<br/>transfer ellipse まで上昇
    end note
    note right of Coast
        throttle = 0<br/>半周期タイマで apogee 検出
    end note
    note right of SecondBurn
        apogee で再び prograde<br/>SMA を target まで上げて円化
    end note
    note right of Trim
        SMA ベースの TCM<br/>(drag 等で decay したら補正)
    end note
  • FirstBurn: prograde 連続噴射で SMA を transfer ellipse の値 (r_initial + r_target)/2 まで上げる。
  • Coast: throttle=0。transfer ellipse 上を慣性飛行。半周期タイマで apogee 到達を判定(finite-burn 損失で r がぴったり届かない場合でも ロバスト、実機の maneuver 計画でも一般的)。
  • SecondBurn: target SMA まで prograde 噴射で円化。
  • Trim (TCM): drag や初期 burn 誤差で SMA が deadband 分下がったら 補正 burn。instantaneous の r で判定すると楕円軌道 perigee で毎周期 発火してしまうので、軌道サイズ (SMA) ベースで判定する。

目標 body frame は LVLH の tangential-normal-radial 相当:

  • y_body_target = v̂ (prograde)
  • z_body_target = (r × v) / |r × v| (orbit normal)
  • x_body_target = y × z (radial-outward 近傍)

これを quaternion 化し、left-invariant error に対する PD τ = -Kp·θ - Kd·ω を RW トルクとして発行。結果として body-Y の推力 ベクトルは常に prograde を向き、低推力・長時間 burn や apogee での SecondBurn でも姿勢整合が取れる(この姿勢トラッキングがないと 半周期後の SecondBurn は retrograde になって軌道が崩壊する)。

Terminal window
cd plugin-sdk/examples
cargo build -p orts-example-plugin-transfer-burn-with-tcm --target wasm32-wasip2 --release

出力: target/wasm32-wasip2/release/orts_example_plugin_transfer_burn_with_tcm.wasm

付属の orts.toml には 500 km → 2000 km (高度 4 倍) の Hohmann 遷移 demo が入っている。2-body only (atmosphere=none)、sim 7000 s。

Terminal window
cd plugin-sdk/examples/transfer-burn-with-tcm
orts run --config orts.toml --output stdout --format csv > sim.csv
uv run plot.py # → transfer_burn_with_tcm.png

Transfer Burn with TCM

  • 左 (ECI XY trajectory): 地球、初期円軌道 (500 km)、目標円軌道 (2000 km)、 実軌道を重ね描き。throttle>0 の区間は 赤い太線、coast は橙色の細線。 FirstBurn が初期軌道接線方向で点火され、Coast (transfer ellipse) を半周後、 反対側で SecondBurn が発火して目標円軌道に載っている様子が読める。
  • 右上 (Altitude): 500 → 2000 km の単調上昇。burn 区間 (赤シェード) で FirstBurn (t ≈ 0 – 37 s) が一瞬ジャンプ、Coast 中に transfer ellipse の apogee へ向けて滑らかに上昇、t ≈ 3350 s の SecondBurn で circularize。 各 burn の Δalt 値が注釈付き。
  • 右下 (Orbital speed): burn 区間 (赤シェード) と Δv 注釈 付き。 FirstBurn で 7.613 → 7.98 km/s に加速、Coast 中は vis-viva により altitude 上昇と引き換えに 7.98 → 6.55 km/s に減速、SecondBurn で 6.55 → 6.90 km/s に再加速して target 円軌道の速度へ。教科書 Hohmann の 2-impulse 特性そのもの。

burn 区間の検出は orts が CSV に出力する throttle_0 / throttle_1 / throttle_2 カラムに基づく(ThrusterThrottle3D component)。plot では throttle > 0 の tick を burn とみなしている。

Controller config は orts.toml の TOML として書き、host が plugin に JSON 文字列としてシリアライズして渡す:

[satellites.controller.config]
target_altitude_km = 2000.0 # 目標円軌道高度 [km]
mu_km3_s2 = 398600.4418 # 中心天体の重力定数 [km³/s²]
deadband_km = 5.0 # TCM の dead zone 半幅 [km]
num_thrusters = 1 # [satellites.thruster.thrusters] と一致
num_rws = 3 # [satellites.reaction_wheels] と一致
kp = 500.0 # 姿勢 PD 比例ゲイン
kd = 150.0 # 姿勢 PD 微分ゲイン
sample_period = 0.1 # 制御サンプル周期 [s]

推進器・RW の物理パラメータは host 側で定義(plugin は thrust_n / isp_s / max_torque 等の物理量を知らなくてよい):

[satellites.reaction_wheels]
type = "three_axis"
inertia = 0.05
max_momentum = 100.0
max_torque = 10.0
[satellites.thruster]
dry_mass = 100.0
[[satellites.thruster.thrusters]]
thrust_n = 5000.0
isp_s = 230.0
direction_body = [0.0, 1.0, 0.0] # +Y body
  • num_thrusters / num_rws は WIT v0 に actuator inventory API がない ため plugin config に書く必要がある。host の [satellites.thruster.thrusters] / [satellites.reaction_wheels] と 一致させるのは開発者責任(不一致は CLI 側 length check で reject)。
  • 目標高度が初期高度より低い場合、prograde のみの推進器では軌道降下 できず plugin は FirstBurn 開始時に Err を返す。
  • FirstBurn の Δv は sample_period 粒度で決まるため、精密な軌道制御には sample_period を小さくするか、finite-burn 計画と closed-loop 合流を 組むとよい(今回の demo は時間ベース半周期タイマで apogee を外さない ロバスト設計)。

orts run 経由で plugin が thrust を出していることの E2E 検証:

Terminal window
cargo test -p orts-cli --test thruster_plugin_e2e