rosbag と一緒に「その時の状態」を残す (launch wrapper)
git rev + dirty diff + param snapshot + ros env を録画時に自動で残す。sidecar dir か MCAP 内蔵。実装は rc26 流儀の XML 1 ファイル + shell script (Option B) を採用
要点: rosbag 単体は「後で見たとき何が動いていたか」を残さない。録画起動時に git rev + dirty diff + ros2 param dump の snapshot + ros env を残す launch wrapper を書く。標準ツールは無い。採用: Option B (rc26 流儀の XML 1 ファイル + shell script)。sidecar dir と MCAP 内蔵の両方に吐く。
問題
rosbag に入るのは topic データだけ。抜けるのは:
- git rev + dirty diff (commit していないコードで走った場合の再現)
- 各ノードの実効パラメータ (yaml + launch override + 実行中 set 済みの合成後)
- launch args
ROS_DOMAIN_ID/RMW_IMPLEMENTATION/ DDS 設定- インストール済み ros-* パッケージの版
- ハード状態 (CAN if 名、カメラ s/n)
どこに保存するか
sidecar dir (手元開発向け)
bag_2026-08-28_abc1234/
├── rosbag2_2026_08_28-.../ # rosbag2 出力
└── manifest/
├── git_rev.txt
├── git.patch # dirty tree の再現に必須
├── params_snapshot.yaml # ros2 param dump 全ノード
├── ros_env.txt
├── nodes.txt / topics.txt
└── rosdep.txtgrep しやすい。ディレクトリごと配る必要がある。
MCAP 内蔵 (配布向け)
MCAP は Attachment (任意ファイル埋め込み: name / media_type / log_time / create_time / data) と Metadata (key-value マップ) を第一級 record 型で持つ。.mcap 1 ファイルに snapshot を全部詰められる。Foxglove Studio の "Data source info" panel から一覧・DL 可能。
mcap attach bag.mcap --file manifest/git.patch \
--name git.patch --media-type text/x-diff
mcap attach bag.mcap --file manifest/params_snapshot.yaml \
--name params.yaml --media-type application/yaml
mcap metadata add bag.mcap --name run \
--key git_rev=abc1234 --key branch=main --key host=$(hostname)
mcap info bag.mcap # summary
mcap list attachments bag.mcap
mcap get attachment bag.mcap --name git.patch --output /tmp/git.patchフラグ名は版で微妙にブレる。mcap --help で確認。
rosbag2_snapshotは名前が紛らわしいが循環バッファ用途 (異なる問題)。混同注意。
両方吐くのが実務
sidecar は手元 grep 用、MCAP 内蔵は配布用。post-hoc で mcap attach を呼ぶだけなので実装コストは大差ない。両方吐くのが結局最適。
Option 比較
| Python (A) | XML+shell (B, 採用) | 純 XML (C) | |
|---|---|---|---|
| フック機構 | TimerAction / OnProcessExit / OpaqueFunction 全部揃う | shell の trap | <event_handler> のみ |
| 読みやすさ | 意図が構文に出る | shell 部分は分離 | 分かりにくい |
| rc26 流儀との整合 | 別枠 | 同じ (<executable> 1 発) | 同じ |
| デバッグ | Python debugger | bash -x | XML の展開ログ頼み |
Bを採用する理由: rc26 の rosbag_record.launch.xml が <executable> 1 発の流儀。XML は形を揃えて中身は shell で書く方が後から読みやすい。Python launch は機能豊富だが、この用途では shell の trap で十分。C は罠が多い (TimerAction 相当が無い、<let> の評価タイミングが読みにくい)。
Option B の実装
XML (rc26 の rosbag_record.launch.xml と同形):
<launch>
<arg name="rosbag_base" default="$(env HOME)/rosbags"/>
<executable
cmd="$(find-pkg-share salamander_bringup)/scripts/rosbag_with_manifest.sh $(var rosbag_base)"
output="screen"/>
</launch>shell (実体):
#!/bin/bash
BAG_DIR="$1/rosbag2_$(date +%Y_%m_%d-%H_%M_%S)"
MANIFEST="$BAG_DIR/manifest"
mkdir -p "$MANIFEST"
# pre-record snapshot
cd "${WS_ROOT:-$HOME/ros2_ws}"
git rev-parse HEAD > "$MANIFEST/git_rev.txt"
git rev-parse --abbrev-ref HEAD >> "$MANIFEST/git_rev.txt"
git diff HEAD > "$MANIFEST/git.patch"
env | grep -E '^ROS_|^RMW_' > "$MANIFEST/ros_env.txt"
ros2 node list -a > "$MANIFEST/nodes.txt" 2>/dev/null || true
ros2 topic list -t > "$MANIFEST/topics.txt" 2>/dev/null || true
dpkg -l 'ros-*' | awk '/^ii/{print $2,$3}' > "$MANIFEST/rosdep.txt" || true
# post-hoc (record 終了時)
finish() {
for f in "$BAG_DIR"/*.mcap; do
[ -f "$f" ] || continue
mcap attach "$f" --file "$MANIFEST/git.patch" --name git.patch --media-type text/x-diff 2>/dev/null || true
mcap attach "$f" --file "$MANIFEST/params_snapshot.yaml" --name params.yaml --media-type application/yaml 2>/dev/null || true
mcap attach "$f" --file "$MANIFEST/ros_env.txt" --name ros_env.txt --media-type text/plain 2>/dev/null || true
mcap metadata add "$f" --name run \
--key "git_rev=$(cat "$MANIFEST/git_rev.txt" | head -1)" \
--key "host=$(hostname)" 2>/dev/null || true
done
}
trap finish EXIT INT TERM
# param dump は 5s 後 (ノード立ち上がり待ち)
( sleep 5
for n in $(ros2 node list 2>/dev/null); do
echo "# --- $n ---"
ros2 param dump "$n" 2>/dev/null
done > "$MANIFEST/params_snapshot.yaml" ) &
# record — exec しない (trap を効かせるため)
ros2 bag record -a --storage mcap -o "$BAG_DIR"注意: exec ros2 bag record にすると trap が効かなくなる。裸で呼ぶ。
補助: /parameter_events を bag に含める
param dump snapshot と組み合わせて、実行中の param set 変更を record 期間中は追える。
ros2 bag record --include-hidden-topics ...
# または明示
ros2 bag record /parameter_events /topic1 ...限界: /parameter_events は set のときしか流れない。開始前に declare 済みのパラメータは初期スナップショットとして流れてこない。真の snapshot は ros2 param dump (上記) で取る。
復元
レビュー時:
manifest/git.patchをgit apply(またはmcap get attachment bag.mcap --name git.patch --output /tmp/git.patch)params_snapshot.yamlで launch override- これで「その時の状態」が再現。CI で自動 replay 基盤にもなる
関連
- [[rosbag-analysis-workflow]] — 記録した bag をどう解析するかの三層分担