u/Visible04

▲ 15 r/ROS+1 crossposts

Update on BAGEL: new features and future plans!

Hi again r/ROS,

Following up on my earlier post about BAGEL, a browser-based ROS bag viewer/editor with no native dependencies and no ROS install. Since v1.0 it's grown from a viewer into something closer to a full robotics debugging tool. Quick links for anyone new here:

Link: https://bagel-ros2.vercel.app

Source: https://github.com/Hussain004/BAGEL

Full changelog with design rationale: https://github.com/Hussain004/BAGEL/blob/main/FEATURES.md

What's new since v1.0:

Bag editing (v1.1, v1.2)

  • Trim by time range, drop topics you don't need, export a fresh indexed MCAP, all client-side, no CLI.
  • Works across every format BAGEL reads: .mcap, ROS2 .db3, and ROS1 .bag all edit down to MCAP now.

URDF robot models and richer 3D (v1.3)

  • Drop a URDF (or paste one) and the robot animates in the 3D scene, following the bag's /tf and joint states.
  • MESH_RESOURCE and TRIANGLE_LIST markers render real meshes instead of a placeholder.
  • CameraInfo overlay (principal point reticle, intrinsics badge), a wireframe camera frustum in the 3D scene, and one-click undistort using the calibration.
  • Saved per-data-type display defaults, loop playback, per-camera frustum hide toggles.

Analysis and shareability (v1.4)

  • Bag Health dashboard: per-topic Hz, jitter, gaps, and bandwidth with color-coded waately see which topic dropped out or is publishing erratically.
  • Inline math expressions as derived plot series (unit conversions, vector magnitudes, bias correction), real tokenizer/AST, no eval.
  • Export any panel as a WebM video or PNG sequence for a time window.
  • Timeline bookmarks/annotations that round-trip through the share URL.

Live robot data (v1.5)

  • The big one: paste a ws:// URL (the same protocol Foxglove Studio and foxglove_bridvery panel updates in real time from a running robot. No ROS install, no account, justa browser tab.
  • Record live sessions straight to a proper indexed MCAP from the browser.
  • Works over ROS1 bridges too, not just ROS2. - Sim clock (/clock) support, so Gazebo/Isaac Sim sessions get correct timestamps ins
  • Cross-bag health comparison when multiple bags are loaded.

Format breadth and RViz parity (v1.6) - Standalone .pcd / .ply viewer, no bag wrapping needed.

  • Foxglove Studio's JSON-schema MCAPs (foxglove.* types) decode correctly now instead of showing empty panels.
  • WebCodecs-based H264/H265 video decoding for foxglove.CompressedVideo topics.
  • Zoom and pan in the image viewer.

What's next?

v1.7 is up next: a 3D measurement tool (click two points, get a distance), nav_msgs/Path rendering, more colormaps, image-on-point-cloud projection using camera intrinsics, then bag merge/split, then QoS inspection (surfacing reliability/durability/history per topic).

u/Visible04 — 15 hours ago
▲ 40 r/ROS

BAGEL: browser-native ROS1 & ROS2 bag visualizer

Hi all,

I've been building BAGEL (BAG ExpLoration), a static web app that opens ROS bag files (.mcap, ROS2 .db3, and legacy ROS1 .bag) directly in the browser, with no native dependencies and no ROS install. Wanted to share it here for feedback and in case it's useful to anyone.

Link: https://bagel-ros2.vercel.app

Source: https://github.com/Hussain004/BAGEL

Demo Videos: https://youtube.com/playlist?list=PLHZhJb0NUk4Jv26hmARxgLa_dVw6Ab5j8&si=2Zl8iBUqWjkdn_1u

##What it currently does:

  • Parses .mcap (via u/mcap/core), ROS2 .db3 (sql.js / WASM SQLite), and ROS1 .bag (via u/foxglove/rosbag) through the same drop zone
  • Topic inspector with type, message count, and Hz; searchable and sortable
  • Time-series plots (uPlot) for any numeric topic: auto-extracts every numeric leaf field, per-field visibility toggles, smart zoom-range capture
  • Image viewer for sensor_msgs/Image (rgb8 / bgr8 / rgba8 / mono8 / mono16) and CompressedImage (jpeg / png) with lazy single-message reads, so multi-GB image streams open near-instantly
  • 3D scene (Three.js) for PointCloud2 (including Livox-style list-of-struct CustomMsg, detected by shape rather than type name), LaserScan, and pose-bearing topics: height / intensity / single-colour, range filter, ring-buffer + voxel-grid point accumulation, Shift+Click custom orbit pivot, configurable up-axis
  • TF-aware rendering across every 2D and 3D panel that composes header.frame_id → user-selected world frame from /tf and /tf_static, applies the cached Matrix4 to the rendered geometry
  • 2D trajectory plotting from Odometry, PoseStamped, PoseWithCovarianceStamped, TransformStamped, and NavSatFix (equirectangular projection from the first GPS fix)
  • TF tree panel: top-down view of the frame hierarchy with current transform at the playhead time
  • Dockable VSCode-style panels: drag a panel header onto another's edge to split horizontally / vertically; layout encoded in a sharable URL hash
  • Per-topic CSV / NDJSON export
  • Multi-bag overlay. Compare runs side-by-side (algorithm A vs B, before/after experiment, sim vs real).
  • Remote URL loading. Paste a bag URL and BAGEL streams it via HTTP Range and only the chunks you scrub through hit the network.
  • Custom schemas. ROS2 .db3 files don't embed schemas, so anything outside the standard packages failed silently. BAGEL adds a paste flow with localStorage persistence, simply paste your .msg definition once, every future bag with that type decodes automatically.

... and more

##A few technical bits:

  • All parsing (MCAP zstd-decompression, sql.js queries, CDR / ROS1 message deserialization) runs in a dedicated Web Worker; the React render loop stays responsive while a topic decodes
  • MCAP's IndexedReader does range reads against the source File handle (via BlobReadable) instead of loading the whole bag (bags well over 2 GB work in the browser)
  • ROS1 type names (sensor_msgs/Image) are normalized to ROS2 form (sensor_msgs/msg/Image) at the parser layer, and a recursive { sec, nsec } → { sec, nsec, nanosec } alias pass lets the same panels work across both formats with zero per-panel changes
  • Point cloud and laser scan decoding posts back transferable Float32Array buffers from the worker (zero-copy onto the main thread, no DataView walks on the UI side)
  • MCAP and ROS1 .bag both embed schemas, so any custom message type alive in the producing graph deserializes for those formats. .db3 falls back to a bundled registry covering std_msgs, geometry_msgs, sensor_msgs, nav_msgs, tf2_msgs, rcl_interfaces, and builtin_interfaces

Happy to hear feature requests, bug reports, or "this would be useful if it also did X" suggestions. Issues and PRs welcome on GitHub.

Thanks!

Edit: Shipped BAGEL v1.0. Notable additions since this post:

  • DiagnosticArray panel for diagnostic_msgs/DiagnosticArray. Swimlane timeline (one row per (hardware_id, name) component, coloured by OK / WARN / ERROR / STALE across time) plus an at-playhead inspector that lists every non-OK component with its message field and key/value pairs. Click any cell on the swimlane to seek.
  • Log (rosout) panel for rcl_interfaces/Log (ROS2) and rosgraph_msgs/Log (ROS1). Virtualised list so 100k+ entry logs filter in under a frame. Severity, node-name, and full-text filters; click any row to seek the playhead to that log's stamp; auto-follow toggle pins the row closest to the playhead.
  • OccupancyGrid rendering in the 3D scene for nav_msgs/OccupancyGrid. SLAM maps (gmapping, slam_toolbox, cartographer, costmap publishers from nav2 / move_base) render as a textured plane, posed by info.origin and TF-resolved against the chosen world frame.
  • OpenStreetMap tile underlay for NavSatFix. Opt-in toggle on the trajectory plot fetches OSM tiles for the visible viewport, so a GPS trace shows actual streets instead of a bare canvas. Default off because fetching tiles breaks the "no data leaves your machine" pitch.
  • Anchor picker UI for the multi-bag anchor alignment mode. The "Set anchor" button picks the focused bag's current time as its sync event, so once you mark the same physical moment in each bag (race start, sensor trigger, flag drop), the timelines lock together. Anchors round-trip through the URL hash.
  • Light theme toggle in the toolbar (sun / moon icon). Dark stays the default; the light pass uses a WCAG-tuned accent palette so the data viz still reads on white surfaces.
  • 168-test Vitest suite covering every parser path and utility, with synthetic in-memory MCAP fixtures generated at test setup time so contributors don't need to drop GB-sized bags into the repo. GitHub Actions CI runs tsc -b + pnpm test on every PR.

Per-release detail (including design rationale): https://github.com/Hussain004/BAGEL/blob/main/FEATURES.md.

u/Visible04 — 1 month ago