Overview
On a robot, the data worth keeping is sparse: most of the time nothing interesting happens. But you can't know an event mattered until after it has already started — and a useful clip needs the lead-up, not just the aftermath. That preroll only exists if the data was already on disk when the event fired.
Momentedge Clipper turns an ordinary ros2 bag record into an on-demand event recorder. It runs alongside the recorder, tails the growing MCAP file, and on each trigger cuts a standalone clip covering a window around the event — [trigger_time − preroll, trigger_time + postroll].
- MCAP in, MCAP out. Clips are standard, complete MCAP files — readable by Foxglove, the mcap CLI, and ros2 bag replay.
- Decode-free. Clipper copies message bytes straight through; it never deserializes message bodies.
- Triggers are just a topic. Anything that can publish
momentedge_msgs/Triggercan drive it. - Small and frozen-friendly. Built to be pinned at a version and left running on a robot.
How It Works
Clipper sits beside a continuous ros2 bag record:
trigger source ros2 bag record (continuous)
(fault / button / perception) │
│ momentedge_msgs/Trigger ▼
│ on /events/momentedge/trigger ./record/<bag>.mcap
▼ │
clipper ◀──────────────── tails ──────────────────┘
│
└── copies [trigger_time ± window] ──▶ ./clipped/<trigger>.mcap
Three steps:
- Tail. Clipper keeps the growing MCAP file open and scans new bytes incrementally.
- Listen. It waits for a
momentedge_msgs/Triggerwith a reference time and pre/post window. - Copy. It copies every message in the time window into a standalone clip.
Because the recording is already on disk, the preroll — the data from before the trigger — is there to copy.
Quick Start
Three commands in separate terminals (same ROS 2 environment):
# 1. Start continuous recording
ros2 bag record --all --storage mcap --output ./record
# 2. Start clipper
clipper --record-dir ./record --out-dir ./clipped
# 3. Fire a trigger (5s before and after "now")
ros2 topic pub --once /events/momentedge/trigger momentedge_msgs/msg/Trigger \
"{name: test, trigger_time: {sec: $(date +%s), nanosec: 0}, \
preroll: 5000000000, postroll: 5000000000}"
A clip lands at ./clipped/<trigger_ns>_test.mcap. Open it with Foxglove or ros2 bag info.
Key Features
- Rust Native Support (v0.1.3+) — Deploy on resource-constrained systems with Rust implementations including Copper OS
- Preroll Capture — Capture data from before the event occurred
- Standard MCAP Format — No vendor lock-in, works with all MCAP tools
- Zero Deserialization — Message-agnostic byte copying for any ROS 2 message type
- Topic-Based Triggers — Any node can publish a trigger message
- Configurable Windows — Set custom preroll/postroll durations per trigger
- Apache 2.0 Licensed — Open source and free to use
Configuration Basics
Clipper is configured via CLI flags or environment variables. All are optional:
Essential Options
--record-dir— Directory of continuous recording (default:./record)--out-dir— Where to write clips (default:./clipped)--clip-compression— Codec for clips:none,lz4, orzstd(default:zstd)--grace-secs— How long to wait for recording to cover the window (default:30)--interface—rosormcaptrigger interface (default:ros)
Example:
clipper --record-dir /data/bags --out-dir /data/clips \
--clip-compression zstd --grace-secs 60
Trigger Interface
A trigger is a momentedge_msgs/Trigger message with:
name(string) — Identifier for the clip filenametrigger_time(Time) — Reference timestamppreroll(uint64) — Nanoseconds before trigger_timepostroll(uint64) — Nanoseconds after trigger_timedescription(string) — Optional context
Publish from any node:
ros2 topic pub /events/momentedge/trigger momentedge_msgs/msg/Trigger \
"{name: 'fault_detected', \
trigger_time: {sec: 1234567890, nanosec: 500000000}, \
preroll: 10000000000, postroll: 5000000000, \
description: 'Motor overcurrent event'}"
Clipper announces each completed clip on /events/momentedge/recorded with a list of files written.
Resources & Links
📦 GitHub Repository
Source code, issues, and contributions
🚀 Release Notes
Changelog and version history
📖 Examples
Setup guides and sample configurations
🏗️ Architecture
Technical deep dive and design decisions