Skip to content

機体制御とGround Truth

正式な機体制御APIは、KSPの実vessel_idへ期限付きleaseを取得してから、body frameのWrenchまたは型付きアクチュエータ指令を送ります。KSP側が所有権、SAS排他、sequence、timeout、安全上限を最終判定します。

制御フロー

  1. /ksp_vessel/lifecycleSTATE_ACTIVEまたはSTATE_CHANGEDvessel_idを受け取る。
  2. /ksp_vessel/control/authority/commandACTION_ACQUIREを送る。
  3. /ksp_vessel/control/authority/stateで同じcontroller_idlease_idSTATE_OWNEDを確認する。
  4. leaseと同じidentityを持つ指令を、timeoutより短い周期で送る。
  5. 制御終了時にACTION_RELEASEを送る。停止時に送れなくてもleaseは期限切れになる。

sequenceは同じcontroller_id + lease_idの全正式指令を通じて単調増加させます。同じ値や古い値はKSPで拒否されます。priorityが高い新規leaseだけが現在のownerをpreemptできます。同じpriorityでは先に取得したownerを維持します。

Topic

方向TopicQoS / 内容
Subscribe/ksp_vessel/control/authority/commandControlAuthorityCommandReliable。取得、更新、解放、e-stop
Publish/ksp_vessel/control/authority/stateControlAuthorityStateReliable / Transient Local。KSPが確定したowner
Subscribe/ksp_vessel/control/wrench_commandBodyWrenchCommandReliable。lease-bound body Wrench
Publish/ksp_vessel/control/wrench_feedbackWrenchFeedbackrequested / allocated / achieved / residual
Publish/ksp_vessel/lifecycleVesselLifecycleReliable / 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_HOLDSIX_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意味
requestedcontrollerが送った値
allocated安全filterとアクチュエータ配分後の要求値
achieved直前のKSP physics tickで観測したengine/RCS推力から再構成した値
allocation_residualrequested - allocated
tracking_residualrequested - achieved
saturation_ratio配分できなかった割合
tracking_error_ratio観測値との差の割合

achievedにはreaction wheel、タイヤ接触力、空力は含みません。achieved_qualityに測定遅延と除外対象を明記します。並進による回転や燃料・KSP制御則による差を隠さず、controller側で飽和を判断できます。

型付きEngineCommand.target_thrustRcsCommand.thrust_limitWheelCommand.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で設定します。

設定既定値内容
maxForceN250000force magnitude上限
maxTorqueNm100000torque magnitude上限
maxAngularSpeedRadSec0.35これを超える回転を加速する成分を除去
maxForceSlewNPerSec50000force変化率上限
maxTorqueSlewNmPerSec10000torque変化率上限
maxContinuousActuationSec30非ゼロ指令の連続時間上限
continuousResetIdleSec0.5連続時間limitを解除するゼロ指令時間

ROS側の上限よりKSP側を大きく設定し、KSP側は故障時の最終境界として使うのが基本です。

Ground Truthとframe

Topicframe_id内容
/ksp_vessel/ground_truth/posepylon_ground_truth_enu位置m、姿勢quaternion
/ksp_vessel/ground_truth/nearby_vesselspylon_ground_truth_enu自機と近隣機体の同時刻・同原点の絶対位置・速度。差分から相対状態を算出
/ksp_vessel/ground_truth/twistpylon_ground_truth_enuworld-frame速度m/s、角速度rad/s
/ksp_vessel/ground_truth/twist_bodybase_linkbody-frame速度m/s、角速度rad/s
/ksp_vessel/ground_truth/accelerationpylon_ground_truth_enuworld-frame運動学的加速度
/tfpylon_ground_truth_enu -> base_linkKSP universal time基準のdynamic TF
/tf_staticproxy fixed joint / sensor mount取付姿勢

センサーデータのtimestampはKSP universal timeからROS clockへ対応付けます。Ground Truthの最新poseを同じセンサー時刻へ最大0.1秒外挿してTFを補うため、点群より遅い姿勢周期によるfuture extrapolationを避けます。

VesselLifecycleUNAVAILABLE / ACTIVE / CHANGED / STALE、generation、origin sequence、model readinessを公開します。display nameではなくvessel_idが制御identityです。機体切替時、既存leaseと不一致なproxy modelは即座に無効になります。

型付きアクチュエータ

EngineCommandRcsCommandWheelCommandMotorCommandSeparationCommandも同じvessel_idcontroller_idlease_idsequenceを必須とします。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-sec0.5

共通setpoint controllerは制御権喪失・入力欠測・実行中の世代変更で目標を破棄します。復旧時は新たなMODE_IDLEを受けてから、後続の新しいsetpointを受理します。

PyLoNを使ったROS2アプリケーション開発のためのガイドとAPIリファレンス