rosbags
v0.0.4
Published
Minimal ROS bag (v1.2) reader and writer ported from rosbags python implementation.
Readme
rosbags – zero-dependency ROS1 bag reader & writer for Node & the browser
This directory contains a minimal implementation of a ROS1 (format v2.0)
bag reader and writer in pure JavaScript with zero runtime dependencies.
The only modules it relies on are provided by Node.js itself (fs, path, …), which
means it also works unchanged in the browser after bundling.
The code is a direct, line-for-line port of the rosbags reference implementation written in Python. All record layouts, headers and constants are identical, so a bag produced here can be opened with any existing ROS tooling.
Quick start
# Run the small unit-test suite (writes & reads a few bags)
npm testInstall via npm
npm install rosbagsUsage in Node (ESM)
import { Writer, Reader } from 'rosbags';
// Write a bag
const writer = new Writer('example.bag');
writer.open();
const conn = writer.addConnection('/foo', 'std_msgs/msg/Int8');
writer.write(conn, 1n, Buffer.from([0x01]));
writer.close();
// Read a bag
const reader = new Reader('example.bag');
reader.open();
for (const msg of reader.messages()) {
console.log(msg.connection.topic, msg.time, msg.data);
}
reader.close();Usage in Node (CommonJS)
const { Writer, Reader } = require('rosbags');
// ...identical to aboveUsage in the Browser via CDN
Add a single script tag that exposes rosbags globally:
<script src="https://unpkg.com/rosbags/dist/rosbags.browser.js"></script>
<script>
// The bundle already contains a Buffer poly-fill, no extra scripts needed.
const { Writer, Reader } = rosbags;
// Write a bag in memory
const w = new Writer();
w.open();
const c = w.addConnection('/foo', 'std_msgs/msg/Int8');
w.write(c, 123n, new Uint8Array([0x42]));
w.close();
const blob = new Blob([w.getUint8Array()], { type: 'application/octet-stream' });
// download or upload blob here
// Read a bag from a file input
document.getElementById('bag-input').addEventListener('change', async (evt) => {
const file = evt.target.files[0];
const buffer = await file.arrayBuffer();
const reader = new Reader(buffer);
reader.open();
for (const msg of reader.messages()) {
console.log(msg.connection.topic, msg.time);
}
reader.close();
});
</script>Writing a bag to disk
// After installing from npm:
import { Writer } from 'rosbags'; // Node ESM variant
const bag = new Writer('example.bag'); // pass a path ⇒ write to disk
bag.open();
// Register a topic/connection first
const conn = bag.addConnection('/foo', 'std_msgs/msg/Int8');
// Then stream messages (timestamp in **nanoseconds**)
bag.write(conn, 1n, Buffer.from([0x01]));
bag.write(conn, 2n, Buffer.from([0x02]));
bag.close();Creating a bag entirely in memory (browser-friendly)
import { Writer } from 'rosbags';
const writer = new Writer(); // no path ⇒ keep data in memory
writer.open();
const conn = writer.addConnection('/bar', 'std_msgs/msg/Int8');
writer.write(conn, 42n, new Uint8Array([0xff]));
writer.close();
const raw = writer.getUint8Array(); // Uint8Array containing the .bag file
// …upload, download or feed into a WebWorker here…Reading a bag from disk
import { Reader } from 'rosbags';
const reader = new Reader('example.bag');
reader.open();
// Get summary information
for (const conn of reader.connections) {
console.log(`topic: ${conn.topic}, type: ${conn.msgtype}, messages: ${conn.msgcount}`);
}
// Iterate over all messages
for (const msg of reader.messages()) {
console.log(msg.connection.topic, msg.time, msg.data);
}
// Filter by topic
for (const msg of reader.messages({ topics: ['/foo'] })) {
// ...
}
reader.close();Reading a bag from memory (browser-friendly)
import { Reader } from 'rosbags';
// `buffer` can be an ArrayBuffer or Uint8Array from a file input or fetch
const reader = new Reader(buffer);
reader.open();
// ... same as reading from diskTesting
The tests live in js/tests/:
test_writer1.js– verifies the writer against a set of hand-rolled assertions (header sizes, chunk flags, …).test_writer_rosbag_read.js– round-trip check that writes with this writer and reads back using the upstreamrosbagnpm dependency.test_reader.js- round-trip check that writes with our writer and reads back with our reader, including complex message types.
Run the suite via:
npm testPublishing to npm
The package.json includes convenience scripts:
npm run build– Generates self-contained bundles using esbuild:dist/rosbags.node.mjs(ESM for Node)dist/rosbags.js(CommonJS for Node)dist/rosbags.browser.js(IIFE for browsers)
npm publish– Publish the package. AprepublishOnlyhook ensures the bundle is rebuilt and the tests are green before the actual upload.
Everything required at runtime is embedded in the generated bundle, so the published module stays dependency-free.
License
This JavaScript port is released under the MIT license (see LICENSE).
