rerun-mcap について
Rerun の `McapReader` で MCAP ファイルを取り込むためのスキルです。遅延チャンクストリーム、スキーマに基づくデコード、トピックのフィルタリング、空データの原因を説明します。
主な機能
- 01MCAP を遅延チャンクストリームとして読み込む
- 02スキーマに基づくトピックのデコード
- 03RE2 パターンによるトピックの絞り込み
- 04カスタムメッセージへの意味付け
- 05タイムスタンプ解釈の調整
活用シーン
- 01MCAP センサー記録の確認
- 02記録から特定トピックを抽出
- 03Rerun 向けのカスタム protobuf メッセージのデコード
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ rerun-io/ rerun --skill rerun-mcapインストール後、Claude Code で/rerun-mcapを入力して読み込まれたか確認します。
詳細
Rerun MCAP の取り込み
McapReader は、MCAP ファイルを遅延チャンクストリームに変換します。各トピックのパスにエンティティが 1 つ作成され、メッセージのペイロードはプラグイン可能なデコーダーによってデコードされます。このスキルでは、リーダーのオプション、各トピックの変換先、およびエラーなしで空のストリームが返される原因となる失敗モードについて説明します。ストリームの仕組み(フィルター、ドロップ、レンズ、マージ、書き込み)については、rerun-chunk-processing を参照してください。
API
from rerun.chunk import McapReader
reader = McapReader(mcap_path) # see help(McapReader) for the full option set
stream = reader.stream()
MCAP に埋め込まれた URDF も取り込めます(その場合は rerun-urdf を参照してください)。
トピックの変換先
デフォルトのデコーダー(decoders=None)では、メッセージのスキーマ名によってトピックの変換先が決まります。アーキタイプはそのまま通し、raw の :message トピックのみにレンズを適用してください。
| MCAP スキーマ名 | デコード先 | 対応方法 |
|---|---|---|
foxglove.FrameTransforms | Transform3D | そのまま通す。手作業で構築しない |
foxglove.CameraCalibration | Pinhole | そのまま通す |
foxglove.CompressedVideo | VideoStream(実際のサンプルバイト)+CoordinateFrame | そのまま通す |
その他の foxglove.* 既知の型 | 対応するアーキタイプ | そのまま通す |
ros2 の既知の型(ros2msg / ros2_reflection) | アーキタイプ | そのまま通す |
独自の schemas.proto.* / カスタム protobuf | 1 つの <schema.name>:message 構造体 | DeriveLens + Selector を使ってセマンティクスを付与する |
つまり、カメラのトピックはすでに Pinhole として、動画は VideoStream として、frame_transforms トピックは Transform3D として届きます。カスタムメッセージ(例:カスタムの関節状態スキーマ、カスタムのグリッパーステータス列挙型)のみがリフレクションまたは raw データとして届き、レンズが必要です。
foxglove デコーダーがスキーマからアーキタイプへのマッピングを行います。foxglove メッセージは protobuf で_エンコード_されているため、protobuf デコーダーを介して動作します。そのため、decoders=None のままにしてください(検証済み:decoders=["protobuf"] のみでは foxglove.CameraCalibration は raw の :message のままですが、foxglove を追加すると Pinhole になります)。ファイルを確認するには、McapReader(path).stream() を実行し、何かが欠けている、または再構築が必要だと判断する前に、McapSchema:name といくつかの Chunk.format() を読み取ってください。
- エンティティのパス = トピック名(
/sensors/joint_statesは/sensors/joint_statesのままです)。 早い段階でフィルターします:McapReader(path).stream().filter(content="/sensors/**")。 - リフレクションでデコードされたメッセージは、
<fully.qualified.MessageName>:messageという名前の単一の構造体コンポーネントになります。 レンズ内でSelector(Selector(".joint_positions"))を使ってこのメッセージをたどります。これにより、カスタムメッセージに Rerun のセマンティクスを付与できます(rerun-chunk-processingの DeriveLens パターンを参照してください)。 - トピックの正規表現では RE2 構文を使い、アンカーは付いていません。
camは/external/cam_lowと/camera_infoに一致します。 必要に応じて明示的にアンカーを付けてください(例:^/external/cam)。可能であれば.filter(...)よりもリーダー側のトピックフィルタリングを優先してください。除外するトピックはデコードされなくなります。
低レベルの mcap パッケージを使う場合
McapReader はペイロードを列形式のチャンクストリームに保持します。ほとんどの場合、これで十分です。
ペイロードなしの raw レコードメタデータが必要な場合、またはコンテナー自体を書き換える必要がある場合(スキーマ、チャンネル、メッセージの再登録)に限り、mcap.reader.make_reader を使ってください。
注意点
- エラーは出ないのにストリームが空になる場合:トピック正規表現が何も一致しなかったか、デコーダーが行を生成しなかったチャンネルが原因です。小さなテストファイルに対して
reader.stream().to_chunks()のいくつかのチャンクでChunk.format()を確認するか、まずトピック名をmcapCLI/パッケージと照合してください。 - トピック正規表現はアンカーなしの RE2 であり、除外は包含の後に適用されます。
timeline_type="timestamp"は、MCAP のログ時刻をエポックからの壁時計ナノ秒として解釈します。記録のクロックが間違っている場合は、下流でタイムスタンプを変更せず、リーダーのtimestamp_offset_nsで修正してください。- デコーダーのサブセットでは、どのデコーダーも対象にしないトピックは通知なしにスキップされます。トピックが見つからない場合は、デコーダー選択が原因でないことを確認するため、
decoders=Noneで再試行してください。 - 修正レンズの例はデータセット固有です。
robot_data_preprocessingの例にあるPinhole:resolutionの入れ替えのようなMutateLensをコピーする前に、McapReader(path).stream()から生のコンポーネントを読み取り、_ご自身の_データに不具合があることを確認してください。確認せずに適用すると、正しいキャリブレーションが破損します(正しい648×480が480×648になるなど)。 foxgloveは、各メッセージの.frame_id(および画像平面のサフィックス)から、カメラのPinhole:child_frameと動画のCoordinateFrame:frameの両方を導出するため、キャリブレーションと動画のトピックでframe_idが共通していれば、両者は一致します。それらのトピックで_異なる_frame_idが設定されている場合に限り、動画フレームが分岐して動画が画像平面から切り離されます。その場合は、カメラごとのMutateLensをCoordinateFrame:frameに適用して、動画フレームを正しい位置に移してください。
参考資料
- エンドツーエンドの MCAP パイプライン:
https://github.com/rerun-io/rerun/tree/main/examples/python/robot_data_preprocessing rerun-chunk-processing(ストリーム/レンズの仕組み)、rerun-urdf(関節状態トピックからの FK)、rerun-data-model(モデリングの判断)