テーマ
機体制御とGround Truth
正式な機体制御APIは、KSPの実vessel_idへ期限付きleaseを取得してから、body frameのWrenchまたは型付きアクチュエータ指令を送ります。KSP側が所有権、SAS排他、sequence、timeout、安全上限を最終判定します。
制御フロー
/ksp_vessel/lifecycleでSTATE_ACTIVEまたはSTATE_CHANGEDとvessel_idを受け取る。/ksp_vessel/control/authority/commandへACTION_ACQUIREを送る。/ksp_vessel/control/authority/stateで同じcontroller_idとlease_idのSTATE_OWNEDを確認する。- leaseと同じidentityを持つ指令を、timeoutより短い周期で送る。
- 制御終了時に
ACTION_RELEASEを送る。停止時に送れなくてもleaseは期限切れになる。
sequenceは同じcontroller_id + lease_idの全正式指令を通じて単調増加させます。同じ値や古い値はKSPで拒否されます。priorityが高い新規leaseだけが現在のownerをpreemptできます。同じpriorityでは先に取得したownerを維持します。
Topic
| 方向 | Topic | 型 | QoS / 内容 |
|---|---|---|---|
| Subscribe | /ksp_vessel/control/authority/command | ControlAuthorityCommand | Reliable。取得、更新、解放、e-stop |
| Publish | /ksp_vessel/control/authority/state | ControlAuthorityState | Reliable / Transient Local。KSPが確定したowner |
| Subscribe | /ksp_vessel/control/wrench_command | BodyWrenchCommand | Reliable。lease-bound body Wrench |
| Publish | /ksp_vessel/control/wrench_feedback | WrenchFeedback | requested / allocated / achieved / residual |
| Publish | /ksp_vessel/lifecycle | VesselLifecycle | Reliable / Transient Local。機体identityとframe状態 |
BodyWrenchCommand.header.frame_idは空またはbase_linkだけを受け付けます。座標は+X前、+Y左、+Z上、forceはN、torqueはN·mです。timeout_secは0.05〜10秒です。
角速度・トルクもROSの右手系です。Unityからの変換では、位置・力の軸入替に加え、軸性ベクトルの左右反転符号を補正します。角速度はGround Truth姿勢quaternionの時間差分と同じ回転方向になります。
手動確認では、まずlifecycleから実際のIDを確認します。
bash
ros2 topic echo --once /ksp_vessel/lifecycle
ros2 topic echo /ksp_vessel/control/authority/state
ros2 topic echo /ksp_vessel/control/wrench_feedback通常の連続制御には、lease更新とsequence採番を行うpylon_vehicle_controlを使ってください。
bash
ros2 run pylon_vehicle_control setpoint_controller --ros-args \
-p controller_id:=my_controller \
-p setpoint_topic:=/my_controller/setpoint共通controllerのATTITUDE_HOLDとSIX_DOFは、姿勢誤差をattitude_hold_rate_limit_deg_s以下の目標body角速度へ変換して内側の角速度loopを閉じます。上限を超える回転をさらに加速するtorque成分も除き、制動を優先します。DETUMBLEはbody角速度と反対向きのtorqueだけを生成します。
「要求」と「実現」の違い
力はN、トルクはN·mで指定します。WrenchはKSPの操舵入力へ配分され、ノズル配置、推力上限、燃料、機体状態によって実現量が変わります。制御器ではWrenchFeedbackで要求値と実現量の差を確認してください。
RCS配分器は、現在有効な各ノズルについて次をKSPと同じ軸規則で評価し、12個の正負操作channelを解きます。
useZaxisを含む実際のノズル噴射軸- ノズル位置と現在のcenter of massから得るモーメントアーム
- pitch / yaw / rollとX / Y / Zのenable設定
- moduleの作動状態と現在の最大推力
WrenchFeedbackの値は次の意味です。
| field | 意味 |
|---|---|
requested | controllerが送った値 |
allocated | 安全filterとアクチュエータ配分後の要求値 |
achieved | 直前のKSP physics tickで観測したengine/RCS推力から再構成した値 |
allocation_residual | requested - allocated |
tracking_residual | requested - achieved |
saturation_ratio | 配分できなかった割合 |
tracking_error_ratio | 観測値との差の割合 |
achievedにはreaction wheel、タイヤ接触力、空力は含みません。achieved_qualityに測定遅延と除外対象を明記します。並進による回転や燃料・KSP制御則による差を隠さず、controller側で飽和を判断できます。
型付きEngineCommand.target_thrust、RcsCommand.thrust_limit、WheelCommand.max_drive_torqueと対応するstateも同じくN/N·mです。
SAS・emergency stop・安全上限
suppress_sas: trueのleaseを取得すると、ownerが存在する期間を通じてKSP側がSASを停止し、解放または期限切れ時に元の状態へ戻します。個々のトルク指令の有無では切り替えません。
ACTION_EMERGENCY_STOPは通常のWrenchと個別overrideをゼロ化し、SASも停止したままlatchします。解除できるのはe-stopを発行した同じcontroller_id + lease_idだけです。e-stopの状態は機体切替では自動解除されません。
e-stop自体は現在のownerでなくても、activeなvessel_idと一意なlease identity、正のsequenceを指定して発行できます。解除は同じidentityでsequenceを増やします。
bash
ros2 topic pub --once /ksp_vessel/control/authority/command \
pylon_interfaces/msg/ControlAuthorityCommand \
"{action: 4, vessel_id: '<vessel-id>', controller_id: safety_operator, lease_id: '<unique-lease-id>', sequence: 1}"
ros2 topic pub --once /ksp_vessel/control/authority/command \
pylon_interfaces/msg/ControlAuthorityCommand \
"{action: 5, vessel_id: '<vessel-id>', controller_id: safety_operator, lease_id: '<unique-lease-id>', sequence: 2}"KSP側の最終制限はGameData/PyLoN/Config/ControlSafety.cfgで設定します。
| 設定 | 既定値 | 内容 |
|---|---|---|
maxForceN | 250000 | force magnitude上限 |
maxTorqueNm | 100000 | torque magnitude上限 |
maxAngularSpeedRadSec | 0.35 | これを超える回転を加速する成分を除去 |
maxForceSlewNPerSec | 50000 | force変化率上限 |
maxTorqueSlewNmPerSec | 10000 | torque変化率上限 |
maxContinuousActuationSec | 30 | 非ゼロ指令の連続時間上限 |
continuousResetIdleSec | 0.5 | 連続時間limitを解除するゼロ指令時間 |
ROS側の上限よりKSP側を大きく設定し、KSP側は故障時の最終境界として使うのが基本です。
Ground Truthとframe
| Topic | frame_id | 内容 |
|---|---|---|
/ksp_vessel/ground_truth/pose | pylon_ground_truth_enu | 位置m、姿勢quaternion |
/ksp_vessel/ground_truth/nearby_vessels | pylon_ground_truth_enu | 自機と近隣機体の同時刻・同原点の絶対位置・速度。差分から相対状態を算出 |
/ksp_vessel/ground_truth/twist | pylon_ground_truth_enu | world-frame速度m/s、角速度rad/s |
/ksp_vessel/ground_truth/twist_body | base_link | body-frame速度m/s、角速度rad/s |
/ksp_vessel/ground_truth/acceleration | pylon_ground_truth_enu | world-frame運動学的加速度 |
/tf | pylon_ground_truth_enu -> base_link | KSP universal time基準のdynamic TF |
/tf_static | proxy fixed joint / sensor mount | 取付姿勢 |
センサーデータのtimestampはKSP universal timeからROS clockへ対応付けます。Ground Truthの最新poseを同じセンサー時刻へ最大0.1秒外挿してTFを補うため、点群より遅い姿勢周期によるfuture extrapolationを避けます。
VesselLifecycleはUNAVAILABLE / ACTIVE / CHANGED / STALE、generation、origin sequence、model readinessを公開します。display nameではなくvessel_idが制御identityです。機体切替時、既存leaseと不一致なproxy modelは即座に無効になります。
型付きアクチュエータ
EngineCommand、RcsCommand、WheelCommand、MotorCommand、SeparationCommandも同じvessel_id、controller_id、lease_id、sequenceを必須とします。ownerでない指令はKSPが拒否します。不可逆な分離操作もlease外では実行されません。
Bridge起動引数
| 引数 | 既定値 |
|---|---|
--body-wrench-command-topic | /ksp_vessel/control/wrench_command |
--control-authority-command-topic | /ksp_vessel/control/authority/command |
--control-authority-state-topic | /ksp_vessel/control/authority/state |
--wrench-feedback-topic | /ksp_vessel/control/wrench_feedback |
--vessel-lifecycle-topic | /ksp_vessel/lifecycle |
--ground-truth-prefix | /ksp_vessel/ground_truth |
--actuators-prefix | /ksp_vessel/actuators |
--vehicle-command-timeout-sec | 0.5 |
共通setpoint controllerは制御権喪失・入力欠測・実行中の世代変更で目標を破棄します。復旧時は新たなMODE_IDLEを受けてから、後続の新しいsetpointを受理します。