Dalaran — Apache-2.0, robotics-first visualization and data infrastructure for multimodal time-series. ROS 2 native, reads existing .rrd recordings. A hard fork of Rerun.
777
stars
8,754
commits
Rust
primary language
Aug 12, 2026
updated
Dalaran is an Apache-2.0, robotics-first observability and visualization stack for multimodal time-series data — ROS 2 topics, LiDAR sweeps, camera streams, IMU, and TF transforms, recorded and replayed on one timeline.
You log data from your robot, your simulator, or an offline pipeline; Dalaran stores it in an Arrow-backed columnar chunk store, renders it in a 3D/2D viewer that stays in sync across every sensor, and hands the same data back to you as dataframes when you want to compute on it instead of look at it.
pip install dalaran-sdk
import dalaran as dl
import numpy as np
dl.init("dalaran_example_app", spawn=True) # spawn a viewer process and stream to it
positions = np.random.default_rng(0).normal(size=(1000, 3)).astype(np.float32)
colors = np.random.default_rng(1).integers(0, 255, size=(1000, 3), dtype=np.uint8)
for frame in range(100):
dl.set_time("frame", sequence=frame)
dl.log("world/points", dl.Points3D(positions + frame * 0.01, colors=colors))
Write to a file instead of a live viewer with dl.save("session.dlr"), then
open it later with dalaran session.dlr.
cargo add dalaran
fn main() -> Result<(), Box<dyn std::error::Error>> {
let rec = dalaran::RecordingStreamBuilder::new("dalaran_example_app").spawn()?;
let positions: Vec<_> = (0..1000)
.map(|i| ((i % 10) as f32, ((i / 10) % 10) as f32, (i / 100) as f32))
.collect();
rec.set_time_sequence("frame", 0);
rec.log("world/points", &dalaran::Points3D::new(positions))?;
Ok(())
}
Fetch the SDK in your CMakeLists.txt and link against dalaran_sdk:
include(FetchContent)
FetchContent_Declare(dalaran_sdk URL
https://github.com/Flaminis/Dalaran/releases/latest/download/dalaran_cpp_sdk.zip)
FetchContent_MakeAvailable(dalaran_sdk)
target_link_libraries(your_target PRIVATE dalaran_sdk)
#include <dalaran.hpp>
int main() {
const auto rec = dalaran::RecordingStream("dalaran_example_app");
rec.spawn().exit_on_failure();
rec.set_time_sequence("frame", 0);
rec.log("world/points", dalaran::Points3D({{0.0f, 0.0f, 0.0f}, {1.0f, 1.0f, 1.0f}}));
}
The dalaran binary is both the viewer and the CLI. It ships with the Python
wheel, or you can install it on its own:
cargo install dalaran-cli --locked
dalaran --help
dalaran session.dlr # open a recording
dalaran --serve # serve a web viewer
Recordings are .dlr files and saved blueprints are .dbl files. Live streams
and remote catalogs are addressed with dalaran:// URIs.
Everything below is what Dalaran adds for robotics teams specifically, and everything below works today — it is code in this repository with tests, not a roadmap. What is not built yet lives in ROADMAP.md.
dalaran.robot, a high-level robotics logging API — one handle that knows
about a robot: joint states, base pose, sensor frames, and URDF-driven link
transforms, so you log robot.log_joint_states(...) instead of hand-rolling a
dozen entity paths and quaternion conversions. Point it at a URDF and joint
limits, joint axes and <mimic> joints are honoured for you..msg types without patching the
core. Today the repository already ingests MCAP and a set of common ROS
message schemas.x-forward
z-up, ENU vs. NED for positions and orientations, map/odom/base_link
frame semantics that make the direction hard to get backwards) as first-class
helpers, because silently mismatched axis conventions are the single most
common way a robotics visualization ends up wrong.nav_msgs/OccupancyGrid, nav2_msgs/Costmap
and nav2's /global_costmap and /local_costmap topics land on the GridMap
archetype with proper origin/resolution handling, instead of being flattened
into an untyped image. nav2's cost semantics are modelled properly, so
INSCRIBED_INFLATED_OBSTACLE and LETHAL_OBSTACLE are drawn as the categories
they are rather than as points on the cost gradient, a costmap's layers stack
as separate entities with their own draw order and opacity, and the rolling
local window keeps one entity while its origin moves.dalaran doctor — a diagnostic subcommand that inspects your environment
(build info, wgpu adapters and drivers, DALARAN_* variables, headless and
ROS 2 setup, recording integrity) and tells you what is wrong in plain
language. It lives in the viewer binary, so it still runs when your Python
installation is the thing that is broken; dalaran-doctor covers the
interpreter and SDK/viewer version skew from the Python side..dlrpack portable dataset bundles — a single file that
carries recordings, the blueprint, referenced assets, and metadata, so
"here is the run that failed" is one artifact you can hand to a colleague..rrd recordingsDalaran did not change the storage container. The on-disk format still uses the
RRF2 fourcc, so dalaran recording.rrd opens an upstream recording directly —
no renaming and no conversion step — and dalaran convert will turn one into a
.dlr if you want it normalized.
How far that goes, stated precisely, because "compatible" is easy to overclaim:
.rrd/.rbl extensions are accepted everywhere
.dlr/.dbl are.rerun:*
and Dalaran writes dalaran:*; readers accept both, so chunks, entity paths,
timelines and segment ids resolve out of an upstream file.Rust crates live under crates/ and are prefixed dl_*. The table lists the
ones worth knowing about first; each directory has its own README.md.
| Crate | Group | What it does |
|---|---|---|
dalaran | top | Umbrella crate. What cargo add dalaran gives you. |
dalaran-cli | top | The dalaran binary: viewer, CLI, web server. |
dl_sdk | top | The logging SDK proper: RecordingStream and sinks. |
dalaran_c | top | C API (dl_/DL_ prefixed), which the C++ SDK wraps. |
dl_types | store | Generated archetypes, components, and datatypes. |
dl_log_types | store | Entity paths, timelines, and core log primitives. |
dl_chunk | store | The Arrow chunk: the unit of data everything moves in. |
dl_chunk_store | store | Indexed storage and retrieval of chunks. |
dl_query | store | Latest-at and range queries over the store. |
dl_dataframe | store | Dataframe view of a recording, for getting data back out. |
dl_log_encoding | store | The .dlr container: encode, decode, migrate. |
dl_mcap | store | MCAP ingestion. |
dl_ros_msg | utils | ROS message schema parsing and decoding. |
dl_tf | store | Transform trees and frame resolution. |
dl_server | store | Self-hostable catalog/data server. |
dl_viewer | viewer | The viewer application shell. |
dl_renderer | viewer | wgpu rendering backend. |
Language bindings live in dalaran_py/ (Python, package
dalaran, distribution dalaran-sdk), dalaran_cpp/ (C++,
namespace dalaran:: with the alias dl), and dalaran_js/
(web).
ARCHITECTURE.md has the long version.
BUILD.md — building from sourceARCHITECTURE.md — how the pieces fit togetherROADMAP.md — what we are doing next, and what we are notDalaran is under active development and the API is still evolving. Expect
breaking changes between releases, and read CHANGELOG.md
before upgrading. We would rather ship a small honest surface than a large
speculative one, so features listed as in progress above are exactly that.
Bug reports, robotics-integration reports, and pull requests are welcome. Start
with CONTRIBUTING.md for the dev setup, commit
conventions, and sign-off requirement, and please read
CODE_OF_CONDUCT.md.
Security issues should not go through the public issue tracker — see
SECURITY.md.
The Dalaran mark and wordmark live in docs/assets/ and are
original artwork. docs/assets/BRANDING.md describes
the palette and how you may use them.
Rust
81.7%
Python
14.3%
C++
2.3%
Dalaran — Apache-2.0, robotics-first visualization and data infrastructure for multimodal time-series. ROS 2 native, reads existing .rrd recordings. A hard fork of Rerun.
777
stars
8,754
commits
Rust
primary language
Aug 12, 2026
updated
Dalaran is an Apache-2.0, robotics-first observability and visualization stack for multimodal time-series data — ROS 2 topics, LiDAR sweeps, camera streams, IMU, and TF transforms, recorded and replayed on one timeline.
You log data from your robot, your simulator, or an offline pipeline; Dalaran stores it in an Arrow-backed columnar chunk store, renders it in a 3D/2D viewer that stays in sync across every sensor, and hands the same data back to you as dataframes when you want to compute on it instead of look at it.
pip install dalaran-sdk
import dalaran as dl
import numpy as np
dl.init("dalaran_example_app", spawn=True) # spawn a viewer process and stream to it
positions = np.random.default_rng(0).normal(size=(1000, 3)).astype(np.float32)
colors = np.random.default_rng(1).integers(0, 255, size=(1000, 3), dtype=np.uint8)
for frame in range(100):
dl.set_time("frame", sequence=frame)
dl.log("world/points", dl.Points3D(positions + frame * 0.01, colors=colors))
Write to a file instead of a live viewer with dl.save("session.dlr"), then
open it later with dalaran session.dlr.
cargo add dalaran
fn main() -> Result<(), Box<dyn std::error::Error>> {
let rec = dalaran::RecordingStreamBuilder::new("dalaran_example_app").spawn()?;
let positions: Vec<_> = (0..1000)
.map(|i| ((i % 10) as f32, ((i / 10) % 10) as f32, (i / 100) as f32))
.collect();
rec.set_time_sequence("frame", 0);
rec.log("world/points", &dalaran::Points3D::new(positions))?;
Ok(())
}
Fetch the SDK in your CMakeLists.txt and link against dalaran_sdk:
include(FetchContent)
FetchContent_Declare(dalaran_sdk URL
https://github.com/Flaminis/Dalaran/releases/latest/download/dalaran_cpp_sdk.zip)
FetchContent_MakeAvailable(dalaran_sdk)
target_link_libraries(your_target PRIVATE dalaran_sdk)
#include <dalaran.hpp>
int main() {
const auto rec = dalaran::RecordingStream("dalaran_example_app");
rec.spawn().exit_on_failure();
rec.set_time_sequence("frame", 0);
rec.log("world/points", dalaran::Points3D({{0.0f, 0.0f, 0.0f}, {1.0f, 1.0f, 1.0f}}));
}
The dalaran binary is both the viewer and the CLI. It ships with the Python
wheel, or you can install it on its own:
cargo install dalaran-cli --locked
dalaran --help
dalaran session.dlr # open a recording
dalaran --serve # serve a web viewer
Recordings are .dlr files and saved blueprints are .dbl files. Live streams
and remote catalogs are addressed with dalaran:// URIs.
Everything below is what Dalaran adds for robotics teams specifically, and everything below works today — it is code in this repository with tests, not a roadmap. What is not built yet lives in ROADMAP.md.
dalaran.robot, a high-level robotics logging API — one handle that knows
about a robot: joint states, base pose, sensor frames, and URDF-driven link
transforms, so you log robot.log_joint_states(...) instead of hand-rolling a
dozen entity paths and quaternion conversions. Point it at a URDF and joint
limits, joint axes and <mimic> joints are honoured for you..msg types without patching the
core. Today the repository already ingests MCAP and a set of common ROS
message schemas.x-forward
z-up, ENU vs. NED for positions and orientations, map/odom/base_link
frame semantics that make the direction hard to get backwards) as first-class
helpers, because silently mismatched axis conventions are the single most
common way a robotics visualization ends up wrong.nav_msgs/OccupancyGrid, nav2_msgs/Costmap
and nav2's /global_costmap and /local_costmap topics land on the GridMap
archetype with proper origin/resolution handling, instead of being flattened
into an untyped image. nav2's cost semantics are modelled properly, so
INSCRIBED_INFLATED_OBSTACLE and LETHAL_OBSTACLE are drawn as the categories
they are rather than as points on the cost gradient, a costmap's layers stack
as separate entities with their own draw order and opacity, and the rolling
local window keeps one entity while its origin moves.dalaran doctor — a diagnostic subcommand that inspects your environment
(build info, wgpu adapters and drivers, DALARAN_* variables, headless and
ROS 2 setup, recording integrity) and tells you what is wrong in plain
language. It lives in the viewer binary, so it still runs when your Python
installation is the thing that is broken; dalaran-doctor covers the
interpreter and SDK/viewer version skew from the Python side..dlrpack portable dataset bundles — a single file that
carries recordings, the blueprint, referenced assets, and metadata, so
"here is the run that failed" is one artifact you can hand to a colleague..rrd recordingsDalaran did not change the storage container. The on-disk format still uses the
RRF2 fourcc, so dalaran recording.rrd opens an upstream recording directly —
no renaming and no conversion step — and dalaran convert will turn one into a
.dlr if you want it normalized.
How far that goes, stated precisely, because "compatible" is easy to overclaim:
.rrd/.rbl extensions are accepted everywhere
.dlr/.dbl are.rerun:*
and Dalaran writes dalaran:*; readers accept both, so chunks, entity paths,
timelines and segment ids resolve out of an upstream file.Rust crates live under crates/ and are prefixed dl_*. The table lists the
ones worth knowing about first; each directory has its own README.md.
| Crate | Group | What it does |
|---|---|---|
dalaran | top | Umbrella crate. What cargo add dalaran gives you. |
dalaran-cli | top | The dalaran binary: viewer, CLI, web server. |
dl_sdk | top | The logging SDK proper: RecordingStream and sinks. |
dalaran_c | top | C API (dl_/DL_ prefixed), which the C++ SDK wraps. |
dl_types | store | Generated archetypes, components, and datatypes. |
dl_log_types | store | Entity paths, timelines, and core log primitives. |
dl_chunk | store | The Arrow chunk: the unit of data everything moves in. |
dl_chunk_store | store | Indexed storage and retrieval of chunks. |
dl_query | store | Latest-at and range queries over the store. |
dl_dataframe | store | Dataframe view of a recording, for getting data back out. |
dl_log_encoding | store | The .dlr container: encode, decode, migrate. |
dl_mcap | store | MCAP ingestion. |
dl_ros_msg | utils | ROS message schema parsing and decoding. |
dl_tf | store | Transform trees and frame resolution. |
dl_server | store | Self-hostable catalog/data server. |
dl_viewer | viewer | The viewer application shell. |
dl_renderer | viewer | wgpu rendering backend. |
Language bindings live in dalaran_py/ (Python, package
dalaran, distribution dalaran-sdk), dalaran_cpp/ (C++,
namespace dalaran:: with the alias dl), and dalaran_js/
(web).
ARCHITECTURE.md has the long version.
BUILD.md — building from sourceARCHITECTURE.md — how the pieces fit togetherROADMAP.md — what we are doing next, and what we are notDalaran is under active development and the API is still evolving. Expect
breaking changes between releases, and read CHANGELOG.md
before upgrading. We would rather ship a small honest surface than a large
speculative one, so features listed as in progress above are exactly that.
Bug reports, robotics-integration reports, and pull requests are welcome. Start
with CONTRIBUTING.md for the dev setup, commit
conventions, and sign-off requirement, and please read
CODE_OF_CONDUCT.md.
Security issues should not go through the public issue tracker — see
SECURITY.md.
The Dalaran mark and wordmark live in docs/assets/ and are
original artwork. docs/assets/BRANDING.md describes
the palette and how you may use them.
(top 30 of 175)
Rust
81.7%
Python
14.3%
C++
2.3%