v0.1.3 Released July 28, 2026
View on GitHub

Momentedge Clipper

Event-triggered MCAP clips from continuous ROS 2 recordings — including the seconds before the event.

✨ What's New in v0.1.3
Extended support for Rust native environments including Copper OS. Now you can deploy clipper on resource-constrained robotic systems with Rust implementations.

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/Trigger can 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:

  1. Tail. Clipper keeps the growing MCAP file open and scans new bytes incrementally.
  2. Listen. It waits for a momentedge_msgs/Trigger with a reference time and pre/post window.
  3. 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.

📚 Need detailed installation instructions? See the full installation guide on GitHub for ROS distro-specific packages and building from source.

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, or zstd (default: zstd)
  • --grace-secs — How long to wait for recording to cover the window (default: 30)
  • --interfaceros or mcap trigger interface (default: ros)

Example:

clipper --record-dir /data/bags --out-dir /data/clips \
        --clip-compression zstd --grace-secs 60
⚙️ Complete configuration reference available in the GitHub documentation.

Trigger Interface

A trigger is a momentedge_msgs/Trigger message with:

  • name (string) — Identifier for the clip filename
  • trigger_time (Time) — Reference timestamp
  • preroll (uint64) — Nanoseconds before trigger_time
  • postroll (uint64) — Nanoseconds after trigger_time
  • description (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

💬 Need help? Open an issue on GitHub or reach out at hello@momentedge.xyz