開発中ロボットの実行時検証 — 正しさでなく 4 層で見る
仕様が固まっていないコードの watchdog は「正しさ」を検証できない。普遍的不変条件・宣言済み contract・sim 真値 diff・golden run 回帰の 4 層に分解する
要点: 開発中 (仕様未確定) のロボットコードに対する watchdog は「正しい動き」を定義できない。代わりに (1) 普遍的不変条件 (2) 宣言済み contract (3) sim 真値 diff (4) golden run 回帰 の 4 層で検査する。層 1 と 3 はコードが未完成でも今日から効く。
Layer 1: 普遍的不変条件 (仕様不要)
どんなロボット・どんな開発段階でも、満たさなければ確実にバグ:
- メッセージの NaN / Inf
- TF timestamp の逆行、TF tree の分断
- publisher 存在 + rate 0 (突然死)
- QoS 不整合 (pub/sub 非互換 → 無音で届かない)
- URDF joint limit を feedback が超過
- 指令と feedback の乖離が物理的に不可能な速度 (1 tick で 10 rad 等)
- ノードの死亡・意図しない respawn
機体 config (URDF + 機体 yaml) だけで書ける。watchdog の主力。
Layer 2: 宣言済み contract との突き合わせ (半静的)
コード本体の正しさではなく、コードが自分で宣言した約束を守るかを見る。宣言の在り処:
- HSM 定義 yaml — 状態遷移とタイムアウト。「X 要求 → T 秒以内に Y が変わる」を機械的に導出できる
- BT xml — port の入出力、永久ループの静的検出
- msg 定義・QoS 設定
静的検査 (yaml lint / BT 検査) + 実行時監視 (宣言された遷移が宣言時間内に起きるか) の両輪。未完成コードでも宣言済みの部分は検査可能。
Layer 3: sim 真値 diff (sim 限定の特権)
シミュレータは真値を持っている。コードの意図を知らなくても異常を数値で出せる:
- 推定位置 vs sim 内の実位置
- 把持フラグ vs 物理エンジンの実際の attach 状態
- 認識した物体数 vs シーンに置いた数
実機では作れない答え合わせが sim では常時できる。sim 用 watchdog は真値との diff を流すだけでよい。
Layer 4: golden run 回帰 (未完成コードの本命)
「正しい」は定義できなくても「前は動いてた」は定義できる:
- 動いたときの bag を golden として保存 (manifest 付き — [[rosbag-manifest-launch-wrapper]])
- 新コードで同シナリオを再実行し分布を比較 (到達時間、軌道、hz、成功率)
- 差が閾値超えなら「意図した変更か?」を報告
正解仕様でなく差分を検査する。開発中はこれが一番実用的。
構成
watchdog (常駐) = Layer 1 + Layer 2 の実行時分 + Layer 3 (sim のみ)
CI = Layer 2 の静的分 + Layer 4 (golden 比較)diagnostics topic は Layer 1-2 の出力先であって入口ではない。
既存ツール
| ツール | 用途 | 備考 |
|---|---|---|
ros2 bag record --snapshot-mode | RAM 循環バッファ。snapshot サービスで直近を書き出し | rosbag2 本体機能 (Humble 以降)。サードパーティ不要 |
rosgraph_monitor | ROS graph 構造の監視 | |
ros2 doctor | 静的な環境検査 | |
| ROSMonitoring / ROSRV | 実行時検証フレームワーク (学術系) | 実戦例少。Layer 1 自作の方が早い |
異常検出 → snapshot サービスを叩く、で「異常の直前 N 秒の bag が自動で残る」が作れる。人間が bag を渡す工程を消す部品。
関連
- [[rosbag-manifest-launch-wrapper]] — golden run の再現性を担保する manifest
- [[rosbag-analysis-workflow]] — 記録後の解析分担
rosbag2 と MCAP
記録 (record) / 再生 (play) / 変換 (convert) / 検査 (info) の CLI と、SQLite → MCAP への移行理由。QoS override、latched の落とし穴、post-mortem 解析ワークフロー。
短命プロセスの後始末は cgroup に任せる (systemd-run --scope)
ros2 run/launch の子は親の terminate で死なず残留・混信する。setsid+killpg の手書きは手続き依存で失敗する。systemd-run --user --scope + RuntimeMaxSec なら掃除を忘れても cgroup ごと必ず死ぬ