Robocodec is a robotics data format library for reading, writing, and converting MCAP and ROS1 bag files. It provides a unified API with automatic format detection, parallel processing, and support for multiple message encodings (CDR, Protobuf, JSON) and schema types (ROS .msg, ROS2 IDL, OMG IDL).
- Clean API - Only
RoboReader,RoboWriter,RoboRewriterexposed at top level - Auto-Detection - Format detected from file extension or URL scheme
- Fast - Parallel processing with rayon, zero-copy memory-mapped files
- S3-Native - First-class support for
s3://URLs (AWS S3, MinIO, Alibaba OSS, etc.) - Transformations - Topic/type renaming during file rewriting
# Cargo.toml
[dependencies]
robocodec = "0.1"use robocodec::RoboReader;
// Format auto-detected from extension
let reader = RoboReader::open("data.mcap")?;
println!("Found {} channels", reader.channels().len());Python bindings are available but must be built from source:
git clone https://github.com/archebase/robocodec.git
cd robocodec
make build-python-devfrom robocodec import RoboReader
reader = RoboReader("data.mcap")
print(f"Found {len(reader.channels)} channels")Note: PyPI release is coming soon. For now, build from source using the instructions above.
use robocodec::RoboReader;
let reader = RoboReader::open("file.mcap")?;
// List all channels
for channel in reader.channels() {
println!("{}: {} messages", channel.topic, channel.message_count);
}
// Get message count
println!("Total messages: {}", reader.message_count());use robocodec::RoboWriter;
let mut writer = RoboWriter::create("output.mcap")?;
let channel_id = writer.add_channel("/topic", "MessageType", "cdr", None)?;
// ... write messages ...
writer.finish()?;use robocodec::RoboReader;
let reader = RoboReader::open("file.mcap")?;
for result in reader.decoded()? {
let msg = result?;
println!("Topic: {}", msg.topic());
println!("Data: {:?}", msg.message);
println!("Log time: {:?}", msg.log_time);
}Robocodec supports reading directly from S3-compatible storage using s3:// URLs:
use robocodec::RoboReader;
// Format and S3 access auto-detected
let reader = RoboReader::open("s3://my-bucket/path/to/data.mcap")?;
println!("Found {} channels", reader.channels().len());S3-compatible services (AWS S3, Alibaba Cloud OSS, MinIO, etc.) require credentials via environment variables:
# AWS S3
export AWS_ACCESS_KEY_ID="your-access-key"
export AWS_SECRET_ACCESS_KEY="your-secret-key"
export AWS_REGION="us-east-1" # optional, defaults to us-east-1
# For Alibaba Cloud OSS, MinIO, or other S3-compatible services
export AWS_ACCESS_KEY_ID="your-oss-access-key"
export AWS_SECRET_ACCESS_KEY="your-oss-secret-key"Note: While we use AWS-standard environment variable names for compatibility, robocodec works with any S3-compatible storage service.
For S3-compatible services with custom endpoints:
Option 1: Environment variable (global)
export S3_ENDPOINT="http://localhost:9000" # MinIO
export S3_ENDPOINT="https://oss-cn-hangzhou.aliyuncs.com" # Alibaba OSSOption 2: URL query parameter (per-request)
use robocodec::RoboReader;
// MinIO running locally
let reader = RoboReader::open("s3://bucket/data.mcap?endpoint=http://localhost:9000")?;
// Alibaba Cloud OSS (Hangzhou region)
let reader = RoboReader::open(
"s3://bucket/data.mcap?endpoint=https://oss-cn-hangzhou.aliyuncs.com"
)?;The rewriter processes files in the same format, optionally applying topic and type transformations:
use robocodec::{RoboRewriter, TransformBuilder, RewriteOptions};
let transform = TransformBuilder::new()
.with_topic_rename("/old/topic", "/new/topic")
.build();
let options = RewriteOptions::default().with_transforms(transform);
let rewriter = RoboRewriter::with_options("input.mcap", options)?;
rewriter.rewrite("output.mcap")?;Note: The rewriter preserves the same format. Cross-format conversion is not currently supported.
Add to Cargo.toml:
[dependencies]
robocodec = "0.1"Optional features:
robocodec = { version = "0.1", features = ["jemalloc"] }| Feature | Description | Default |
|---|---|---|
s3 |
S3-compatible storage support (AWS S3, MinIO, etc.) | ✅ Yes |
python |
Python bindings | ❌ No |
jemalloc |
Use jemalloc allocator (Linux only) | ❌ No |
python |
Python bindings | ❌ No |
jemalloc |
Use jemalloc allocator (Linux only) | ❌ No |
Build from source (PyPI release coming soon):
git clone https://github.com/archebase/robocodec.git
cd robocodec
make build-python-dev| Format | Read | Write |
|---|---|---|
| MCAP | ✅ | ✅ |
| ROS1 Bag | ✅ | ✅ |
| RRF2 (Rerun) | ✅ | ✅ |
Note: RRF2 support is compatible with Rerun 0.27+. Earlier versions use a different format and are not supported.
| Encoding | Description |
|---|---|
| CDR | Common Data Representation (ROS1/ROS2) |
| Protobuf | Protocol Buffers |
| JSON | JSON encoding |
- ROS
.msgfiles (ROS1) - ROS2 IDL (Interface Definition Language)
- OMG IDL (Object Management Group)
MulanPSL v2 - see LICENSE
make test # Run all tests
make test-rust # Run Rust tests only
make test-python # Run Python tests onlyRobocodec includes comprehensive fuzzing infrastructure for parser security and robustness testing:
./scripts/fuzz_init.sh # Initialize fuzzing infrastructure (one-time setup)
make fuzz # Quick fuzzing check (30s per target)
make fuzz-all # Extended fuzzing (1min per target)
make fuzz-mcap # Fuzz MCAP parser onlyFor detailed fuzzing documentation, see docs/FUZZING.md.
make bench # Run performance benchmarks
make bench-compare # Compare against baseline