Skip to content

MCAP Recording

This example records simulated robot data to MCAP files for replay and analysis in Foxglove Studio.

After starting the application, the developer panel offers start/stop buttons and a topic selection, and the recordings can be listed and downloaded at http://localhost:8080/recordings.

#!/usr/bin/env python3
from nicegui import ui

from rosys.analysis import recording
from rosys.analysis.recording import McapRecorder, RecordingsPage
from rosys.driving import Odometer, Steerer, keyboard_control, robot_object
from rosys.geometry import Prism
from rosys.hardware import RobotSimulation, WheelsSimulation

shape = Prism.default_robot_shape()
wheels = WheelsSimulation()
robot = RobotSimulation([wheels])
odometer = Odometer(wheels)
steerer = Steerer(wheels)

recorder = McapRecorder(auto_start=False)
recording.add_event_topic(recorder, '/wheels', event=wheels.VELOCITY_MEASURED, unpack=True)
recording.add_pose_topic(recorder, '/odometry/pose', event=odometer.POSE_UPDATED, child='odometry')

RecordingsPage(recorder, header=lambda: ui.link('steering', '/'))


@ui.page('/')
def index() -> None:
    keyboard_control(steerer)
    with ui.scene():
        robot_object(shape, odometer)
    recorder.developer_ui()


ui.run(title='MCAP Recording')
Recorder
The McapRecorder writes every registered topic to rotating MCAP files under ~/.rosys/mcap. With auto_start=False it stays idle until you press the record button in developer_ui.
Topics
add_event_topic and add_pose_topic bind a topic to a RoSys event; the matching Foxglove converter is picked from the payload type automatically. The subscription is only active while a recording is open.
Image quality
Camera topics dominate a recording's size. Keyword arguments are forwarded to the converter, so add_event_topic(recorder, '/camera/front/image', event=camera.NEW_IMAGE, quality=75) records JPEGs at quality 75 instead of the default 90, roughly halving the bytes per frame.
Recordings page
RecordingsPage mounts a page for listing, renaming, reindexing and downloading recordings, plus a download endpoint at /api/recordings/{name}. The optional header callback renders shared navigation at the top of the page.