MCPcopy Index your code
hub / github.com/Hussain004/BAGEL

github.com/Hussain004/BAGEL @main

Chat with this repo
repository ↗ · DeepWiki ↗ · + Follow
1,263 symbols 3,113 edges 156 files 145 documented · 11%
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

BAGEL Logo

BAGEL

BAG ExpLoration: ROS Bag File Web Visualizer

Explore ROS1 & ROS2 bag files in your browser. No installation required.

License: MIT TypeScript React Vite Version

→ Live Demo · Report Bug · Request Feature


What is BAGEL?

BAGEL is a fully static web application that lets you explore ROS bag files (.mcap, .db3, .bag) and standalone point cloud files (.pcd, .ply) entirely in your browser needing no server, no installation, no account. Just drag and drop!

Robotics engineers and researchers frequently generate bag files during experiments, SLAM runs, and sensor calibration. Inspecting these files currently requires a full ROS1 or ROS2 installation, Foxglove Studio (increasingly commercial), or writing custom Python scripts for every inspection task.

BAGEL eliminates this friction.

Why BAGEL?

Problem BAGEL Solution
Need ROS1/ROS2 installed to inspect bag files Works in any modern browser
Foxglove Studio going commercial 100% open source, MIT licensed
ros2 bag info gives text-only output Rich visual interface with search & filtering
Can't share bag contents easily Zero-install, you can send anyone the URL
Students struggle with ROS tooling No setup required, just drag and drop
Legacy ROS1 bags require old toolchains Drag the .bag straight in (no conversion needed)

Demo

Quick tour with the bundled sample bag

Stress test with a real-world SLAM dataset

Data featured in this demo is from the excellent open-access M2DGR dataset provided by the SJTU-ViSYS team, which was instrumental in stress-testing this visualizer's spatial rendering capabilities.


Features

A condensed feature list is below. Detailed version-by-version release notes (with the design rationale behind every feature) live in FEATURES.md.

File formats and live sources

Format Notes
ROS2 .mcap Including zstd-compressed chunks (the new ROS2 default). Foxglove Studio JSON-encoded channels (schemaEncoding: "jsonschema", encoding: "json") supported from v1.6.1.
ROS2 .db3 SQLite via sql.js / WASM
ROS1 .bag Including bz2 and lz4 compressed chunks
Remote URLs HTTP Range requests, so only the chunks you scrub through hit the network. .mcap / .bag stream lazily; .db3 eager-fetches (sql.js needs it in memory).
Foxglove WebSocket (v1.5.0) Paste a ws:// or wss:// URL to connect to a live robot running foxglove_bridge or rosbridge_suite. All panels update in real time. Per-topic ring buffer holds the last 10,000 messages per topic; Follow/Pause button lets you scrub back into history without disconnecting. Auto-reconnect with exponential backoff.
.pcd point clouds (v1.6.0) All three PCD 0.7 encodings: ascii, binary, binary_compressed (LZF). All color modes (height, intensity, rgb, single). Feeds directly into the ThreeDScene panel via a synthetic sensor_msgs/PointCloud2 message.
.ply point clouds (v1.6.0) ASCII + binary_little_endian + binary_big_endian. RGB from red/green/blue uchar properties or packed rgb float. Drop a .ply and the cloud appears instantly in the 3D panel with all existing color, range-filter, and accumulator settings.

Visualization panels

  • TimeSeriesPlot: chart any numeric leaf field (linear.x, orientation.w, etc.) on uPlot. Math expressions as derived series: type field_a * 2 + field_b in the series editor to plot any arithmetic combination of fields from the same topic without writing code. (v1.4.1)
  • ImageViewer: sensor_msgs/Image (rgb8 / bgr8 / rgba8 / mono8 / mono16) and CompressedImage (jpeg / png) with lazy single-message reads. Foxglove equivalents (foxglove.RawImage, foxglove.CompressedImage) supported via JSON schema translation. (v1.6.1) H264/H265 video via foxglove.CompressedVideo using the browser's WebCodecs VideoDecoder with a fast keyframe index for efficient seeking. (v1.6.2) Scroll to zoom (cursor-centered), drag to pan, double-click to reset; zoom percentage shown in the footer. (v1.6.3) Optional sensor_msgs/CameraInfo overlay (principal-point reticle + focal-length badge + calibration-likely-unfilled chip) toggles from the panel header. (v1.3.2) undistort button applies per-frame plumb-bob (Brown-Conrady) undistortion using the paired CameraInfo's D coefficients. (v1.3.4)
  • ThreeDScene (Three.js): PointCloud2, LaserScan, MarkerArray (all twelve primitives: CUBE / SPHERE / CYLINDER / ARROW / LINE_STRIP / LINE_LIST / CUBE_LIST / SPHERE_LIST / POINTS / TEXT_VIEW_FACING / MESH_RESOURCE / TRIANGLE_LIST from v1.3.1), OccupancyGrid, pose markers, camera frustums for every sensor_msgs/CameraInfo topic with per-camera hide checkboxes on multi-camera rigs (v1.3.2 / v1.3.4). Custom orbit pivot, range filter, point accumulation, configurable up-axis.
  • TrajectoryPlot: Odometry / Pose / PoseWithCovariance / TransformStamped / NavSatFix as a 2D polyline, with an opt-in OpenStreetMap tile underlay for GPS traces.
  • TFTree: /tf + /tf_static hierarchy with current transforms at the playhead time.
  • DiagnosticArray: swimlane timeline + at-playhead inspector for diagnostic_msgs/DiagnosticArray. (v1.0)
  • Log (rosout): virtualised list for rcl_interfaces/Log and rosgraph_msgs/Log with severity, node-name, and full-text filters. (v1.0)
  • RawMessageInspector: collapsible JSON tree of the deserialized message at the playhead.

All panels resolve header.frame_id through /tf + /tf_static against a user-selected world frame.

Multi-bag overlay

  • Drop multiple bags into the same session; each gets a colour tint that flows through every panel.
  • Three time-alignment modes: wall-clock, bag-start, and anchor (with a "Set anchor" picker UI in v1.0 so you can lock runs to a physical sync event).
  • Per-bag parser Web Worker so parsing bag B doesn't queue behind bag A's decode.

Layout, sharing, and export

  • Drag-to-dock VSCode-style panel layout. Per-panel state (3D display settings, plot zoom, TF selection) survives docking.
  • Sharable URL hashes encode layout + playhead + bag URL + per-bag anchors. v0.5 / v0.7 / v0.9 hash forms still parse, so old links keep working.
  • Per-topic CSV / NDJSON export from every panel header.
  • Bag editing / MCAP clip export: trim the time range, drop topics you don't need, download a fresh indexed .mcap. Replaces the mcap filter CLI workflow for the common cuts. v1.2 extends the editor to ROS1 .bag and ROS2 .db3 inputs alongside MCAP - output is always MCAP regardless of input format. .db3 topics whose type isn't in BAGEL's bundled registry are flagged in the modal and excluded by default; opt them in to include them with a schema-less channel. (v1.1 / v1.2)
  • Paste-your-own .msg schema flow for ROS2 .db3 topics whose types aren't in the bundled registry. Persisted across sessions in localStorage.
  • Clip export: Export button in the Toolbar renders any open panel (Image, Plot, Trajectory, or 3D Scene) frame-by-frame to a PNG zip or WebM video. Uses a frame-sync protocol (seek playhead, 2x rAF + 250 ms settle, canvas.toBlob()) so every panel type captures correctly. PNG frames are zipped with fflate at level 0 (no re-compression of already-deflated PNGs); WebM uses a two-phase MediaRecorder + captureStream(0) + requestFrame() approach so video playback speed is always correct. (v1.4.2)
  • Timeline bookmarks: drop named markers at any timestamp on the scrubber (double-click the bar, click the + button, or press M), click a tick to seek, hover to see the label. Bookmarks persist to localStorage per bag and are encoded in the URL hash (bm=) for sharing. (v1.4.3)

Robot model (URDF) overlay (v1.3.0)

  • Drop a .urdf and the robot appears in every 3D panel, anchored to its root link in world space via the bag's /tf stream. Joints animate from sensor_msgs/JointState (auto-detected) when the bag publishes it; static URDFs render at their rest pose. A toolbar "Robot" button opens the load modal; the Display card in each 3D panel grows a per-panel robot model hide toggle.
  • Geometry support: box / cylinder / sphere primitives + .stl / .dae / .obj meshes. Loaders are lazy-imported on first use of each file type so primitives-only URDFs don't pay the Collada loader's bundle cost.
  • package:// resolver: paste a URL prefix or drag-drop a folder per referenced package; URL bindings persist across sessions in localStorage under bagel:package-roots:v1. No auto-fetch from ROS distros - BAGEL only loads meshes from where you point it.
  • Bundled sample robot URDF (public/sample-bags/sample-robot.urdf) pairs with tour.mcap so the "Try a sample robot" button in the modal demonstrates the full flow on a fresh checkout.

Live robot data (v1.5.0 - v1.5.6)

  • Foxglove WebSocket client: connect to a live robot by pasting a ws://host:8765 URL into the new "Connect" input. Works with foxglove_bridge (ROS2) and rosbridge_suite (ROS1/ROS2). Implements foxglove.websocket.v1 - binary MESSAGE_DATA frames for message payloads, JSON frames for topic advertisement.
  • Per-topic ring buffer: the last 10,000 messages per topic are held in memory. All existing panels (Image, Plot, 3D Scene, Trajectory, TF Tree, Log) display live data without any panel-level changes - the hooks detect a live entry and read from the ring buffer instead of the parser worker.
  • Follow / Pause mode: the timeline's Follow button (also in the Toolbar chip) keeps the playhead at the live edge. Press Pause to scrub back through buffered history; press Follow to snap forward again.
  • Auto-reconnect: exponential backoff on disconnect: 1s, 2s, 4s, 8s, 16s, 30s. Connection status shown as a pulsing dot (emerald = connected, amber = reconnecting, rose = error) on the toolbar chip.
  • CDR and JSON decoding in the main thread. ROS2 CDR via @foxglove/rosmsg2-serialization, ROS1 CDR via @foxglove/rosmsg-serialization - both already bundled as bag-parsing dependencies, no new packages. (v1.5.3 adds encoding: "ros1" for ROS1 bridges)
  • Live MCAP recording (v1.5.2): Record button in the Toolbar (visible when a live connection is active) buffers every incoming message. Click Stop to serialize all captured data to a fully-indexed MCAP file and download it instantly. The output opens back in BAGEL or any mcap-compatible tool without conversion.
  • Recording size limit + topic filter (v1.5.5): 500 MB hard cap auto-stops the recording and downloads immediately. A filter icon lets you select a subset of topics before recording starts. Byte count turns amber above 400 MB as a warning.
  • Sim clock support (v1.5.4): when /clock is advertised, messages with logTimeNs = 0 (common in Gazebo/Isaac Sim) use the simulation clock value instead of wall-clock time, keeping plots readable in simulation sessions. A SIM badge appears on the toolbar chip.
  • Cross-bag health comparison (v1.5.6): the Health panel shows a chip strip at the top when multiple bags are loaded. Click any chip to switch the stats view to that bag without opening a new panel. Active chip is highlighted; live bags are excluded.

Analysis tools (v1.4)

  • Bag Health dashboard (v1.4.0, extended v1.5.6): a per-topic analytics panel showing measured Hz, jitter (p50/p95 inter-message gap deviation), gap events (pauses longer than 3x the expected period), and bandwidth (bytes/s). Opens from a Health button in the Toolbar. Data is computed once per bag in a background scan and cached. (v1.5.6) When multiple bags are loaded, a chip strip at the top lets you switch the view between bags without opening additional panels.
  • Math expressions in plots (v1.4.1): type arithmetic expressions (vel_x * 2 + offset, sqrt(x*x + y*y)) as derived series directly in the TimeSeriesPlot panel. References other numeric fields from the same topic; evaluated in a sandboxed expression engine (no eval).
  • Clip export (v1.4.2): render any panel to an animated PNG zip or WebM video via a frame-sync protocol. Toolbar Export button opens the modal.
  • Timeline bookmarks (v1.4.3): named markers on the scrubber, persisted per bag and shareable via the bm= URL hash segment.

UX and quality

  • Light + dark themes (toggle in the toolbar; persisted per browser). (v1.0)
  • Keyboard shortcuts: Space to play, ← / → to step, L to loop, M to bookmark (v1.4.3), Esc to close panels, T to focus topic search, O to open a bag, ? for the cheat-sheet.
  • Loop playback: a Timeline toolbar toggle wraps the playhead back to start at end-of-bag instead of pausing, persisted across reloads. (v1.3.3)
  • Saved Display defaults: per-data-type defaults for the 3D panel's Display card (colour mode, accumulator, point size, range filter, up a

Extension points exported contracts — how you extend this code

PlyProp (Interface)
One PLY property declaration.
src/parsers/ply.ts
BatchResponse (Interface)
* Streamed decoded-message batch for `readDeserializedMessages`. The client * accumulates these into the full array; th
src/workers/parser.worker.ts
ErrorBoundaryState (Interface)
(no doc)
src/App.tsx
TopicInfo (Interface)
(no doc)
src/types/bag.ts
AnnotationTickProps (Interface)
(no doc)
src/components/layout/Timeline.tsx
PointField (Interface)
(no doc)
src/utils/pointcloud.ts
Annotation (Interface)
(no doc)
src/store/annotationStore.ts
RecordedMsg (Interface)
(no doc)
src/live/liveRecorder.ts

Core symbols most depended-on inside this repo

get
called by 265
src/parsers/db3.ts
set
called by 201
src/parsers/mcap.ts
push
called by 184
src/live/liveRingBuffer.ts
createFileSource
called by 63
src/parsers/source.ts
dispose
called by 62
src/components/panels/ThreeDScene/markerSet.ts
bytesToFile
called by 61
tests/fixtures/synth.ts
addMessage
called by 33
src/live/liveRecorder.ts
clamp01
called by 26
src/components/panels/ThreeDScene/markerObjects.ts

Shape

Function 847
Interface 222
Method 148
Class 46

Languages

TypeScript100%

Modules by API surface

src/components/panels/ThreeDScene/index.tsx40 symbols
src/parsers/mcap.ts39 symbols
src/components/panels/ThreeDScene/markerObjects.ts37 symbols
src/parsers/urdf.ts35 symbols
tests/fixtures/synth.ts34 symbols
src/workers/parserClient.ts31 symbols
src/components/layout/Toolbar.tsx29 symbols
scripts/build-sample-bag.mjs27 symbols
src/parsers/db3.ts26 symbols
src/components/panels/ImageViewer/index.tsx26 symbols
src/parsers/source.ts24 symbols
src/workers/parser.worker.ts22 symbols

For agents

$ claude mcp add BAGEL \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact