feat(mcap): add copy mode for multi-camera exports
Add an opt-in multi-camera copy layout for zed_svo_to_mcap. copy mode preserves each camera's original timestamps and cadence, writes namespaced /zedN topics without /bundle, and supports common-overlap or full-range export windows. Update the batch wrapper, Python validator, RGBD viewer, and documentation so copy-layout MCAP files are treated as a first-class format rather than invalid bundled output. Validation: - cmake --build build --target zed_svo_to_mcap -j4 - uv run python -m py_compile scripts/zed_batch_svo_to_mcap.py scripts/mcap_bundle_validator.py scripts/mcap_rgbd_viewer.py - build/bin/zed_svo_to_mcap --segment-dir /workspaces/data/kindergarten/bar/2026-03-18T11-59-41 --output /tmp/bar_11-59-41_copy_common.mcap --encoder-device nvidia --depth-mode neural_plus --depth-size optimal --bundle-policy copy --copy-range common - uv run python scripts/mcap_bundle_validator.py /tmp/bar_11-59-41_copy_common.mcap - uv run --extra viewer python scripts/mcap_rgbd_viewer.py /tmp/bar_11-59-41_copy_common.mcap --summary-only
This commit is contained in:
@@ -265,12 +265,51 @@ uv run python scripts/zed_batch_svo_to_mcap.py \
|
||||
|
||||
The batch MCAP wrapper writes `<segment>/<segment>.mcap` by default, skips existing outputs unless told otherwise, and returns a nonzero exit code if any segment fails.
|
||||
The repo includes a minimal pose config at `config/zed_pose_config.toml` so MCAP conversion does not depend on a separate `cv-mmap` checkout.
|
||||
In bundled multi-camera mode, `--start-frame` and `--end-frame` mean the first and last emitted bundle indices from the common start timestamp, inclusive.
|
||||
In bundled multi-camera timeline mode, `--start-frame` and `--end-frame` mean the first and last emitted bundle indices from the common start timestamp, inclusive.
|
||||
When stderr is attached to a TTY, `zed_batch_svo_to_mcap.py` uses a `progress-table` view by default; otherwise it emits line-oriented start/completion/failure logs plus periodic heartbeat summaries. Use `--progress-ui table` or `--progress-ui text` to override the automatic mode selection.
|
||||
|
||||
Bundled MCAP export now defaults to `--bundle-policy nearest`. That mode emits one `/bundle` manifest message per bundle timestamp on the common timeline and keeps the original per-camera timestamps on `/zedN/video`, `/zedN/depth`, and optional `/zedN/pose`. Consumers that care about grouping should follow `/bundle` instead of inferring bundle membership from identical message timestamps. Use `--bundle-policy strict` when you want the older thresholded sync behavior, and `--sync-tolerance-ms` only applies in that strict mode.
|
||||
Bundled MCAP export now defaults to `--bundle-policy nearest`. That mode emits one `/bundle` manifest message per bundle timestamp on the common timeline and keeps the original per-camera timestamps on `/zedN/video`, `/zedN/depth`, and optional `/zedN/pose`. Faster cameras are sampled onto the slowest common timeline there, so they can end up with the same message count as slower cameras. Consumers that care about grouping should follow `/bundle` instead of inferring bundle membership from identical message timestamps.
|
||||
|
||||
Use `--bundle-policy strict` when you want thresholded grouping; `--sync-tolerance-ms` only applies in that strict mode. Use `--bundle-policy copy` when you want one MCAP containing all camera namespaces with their original per-camera cadence and no `/bundle` manifest. `copy` disables `--start-frame`, `--end-frame`, and `--sync-tolerance-ms`; `--copy-range common|full` controls whether it trims to the overlap window or preserves each camera’s full timestamp range.
|
||||
See [docs/mcap_layout.md](./docs/mcap_layout.md) for the full bundled and single-camera MCAP topic contract.
|
||||
|
||||
### MCAP RGBD Viewer
|
||||
|
||||
The repo includes an example RGB+depth viewer at `scripts/mcap_rgbd_viewer.py`. It supports standalone `/camera/*` MCAPs, bundled `/bundle` + `/zedN/*` MCAPs, and multi-camera `copy` MCAPs with namespaced `/zedN/*` topics and no `/bundle`.
|
||||
|
||||
Install the optional viewer dependencies first:
|
||||
|
||||
```bash
|
||||
uv sync --extra viewer
|
||||
```
|
||||
|
||||
Then launch the interactive viewer:
|
||||
|
||||
```bash
|
||||
uv run --extra viewer python scripts/mcap_rgbd_viewer.py \
|
||||
/workspaces/data/kindergarten/bar/2026-03-18T11-59-41/2026-03-18T11-59-41.mcap \
|
||||
--camera-label zed1
|
||||
```
|
||||
|
||||
You can also use the same script without a GUI to inspect metadata or render a preview PNG:
|
||||
|
||||
```bash
|
||||
uv run --extra viewer python scripts/mcap_rgbd_viewer.py \
|
||||
--summary-only \
|
||||
/workspaces/data/kindergarten/bar/2026-03-18T11-59-41/2026-03-18T11-59-41.mcap
|
||||
```
|
||||
|
||||
```bash
|
||||
uv run --extra viewer python scripts/mcap_rgbd_viewer.py \
|
||||
--camera-label zed2 \
|
||||
--frame-index 150 \
|
||||
--export-preview /tmp/mcap_bundled_gap_preview.png \
|
||||
/workspaces/data/kindergarten/throw/2026-03-18T12-58-13/2026-03-18T12-58-13.mcap
|
||||
```
|
||||
|
||||
The viewer depends on `ffmpeg` being on `PATH` so it can build a seek-friendly preview cache for H.264/H.265 MCAP video streams.
|
||||
This is intentionally a simple preview script: it transcodes only the RGB video stream into a temporary intra-frame `mjpeg` cache and then uses that same cache for both scrubbing and normal playback. Depth data is not transcoded to `mjpeg`; it stays in the temporary raw depth cache and is decoded and color-mapped on demand.
|
||||
|
||||
### Why Mixed Hardware/Software Mode Exists
|
||||
|
||||
Bundled MCAP export opens one video encoder per camera stream. A four-camera segment therefore consumes four H.264/H.265 encoder sessions at once.
|
||||
|
||||
Reference in New Issue
Block a user