Quick Start¶
Get hiroz running in under 5 minutes. Pick your language below — no ROS 2 installation required.
Pre-built Releases¶
Pre-built artifacts are available on the Releases page — no Rust toolchain required:
| Artifact | Use case | Install |
|---|---|---|
hiroz-console binary |
Monitor any ROS 2 / hiroz system | Console docs |
hiroz-bridge binary |
Bridge Humble ↔ Jazzy/Kilted | Bridge docs |
hiroz_py Python wheel |
Python pub/sub & services | Python quick start |
libhiroz Go library |
Go pub/sub & services | Go quick start |
Embed hiroz in a Rust Application¶
The rest of this page covers using hiroz from Rust. If you're using Python or Go, follow the quick start links in the table above instead.
Prerequisites:
- Rust 1.85+ (requires edition 2024) — install via rustup
- Tokio 1.x — hiroz requires an async runtime (added to
Cargo.tomlin Option 2 below) - No ROS 2 installation needed
There are two ways to get started:
- Option 1: Try the Examples — Clone the hiroz repository and run pre-built examples (fastest)
- Option 2: Create Your Own Project — Start a new Rust project with hiroz as a dependency
Option 1: Try the Examples¶
The quickest way to experience hiroz is to run the included examples from the repository.
Clone the Repository¶
Start the Eclipse Zenoh Router¶
The router is a lightweight process that lets nodes find each other — think of it as the matchmaker between publishers and subscribers. Keep it running in its own terminal for the entire session.
Terminal 1 — Start the Router:
Run the Pub/Sub Example¶
Open two more terminals and navigate to the same hiroz directory:
Terminal 2 — Start the Listener:
Terminal 3 — Start the Talker:
Success
You should see the listener receiving messages published by the talker in real-time. Press Ctrl+C to stop any process.
Understanding the Code¶
The example you just ran does four things:
- Creates a context —
ZContextBuilderconnects to the Zenoh router and sets up the ROS 2 domain. - Creates a node —
ctx.create_node("name")is the logical unit your publishers and subscribers attach to. - Publishes —
node.create_pub::<RosString>("/chatter")sends CDR-serialized ROS 2 messages on a topic. - Subscribes —
node.create_sub::<RosString>("/chatter")receives and deserializes them asynchronously.
The full example source (with CLI flags and multi-backend support) is at examples/z_pubsub.rs in the repository.
Option 2: Create Your Own Project¶
Ready to build your own hiroz application? Follow these steps to create a new project from scratch.
1. Install the Zenoh Router¶
Since you won't have access to the zenoh_router example outside the hiroz repository, you'll need to install a Zenoh router. Here are the quickest options:
Option A: Using cargo (if you have Rust):
Option B: Using pre-built binary (no Rust needed):
Download the latest release for your platform from: https://github.com/eclipse-zenoh/zenoh/releases
Then extract and run:
Option C: Using Docker:
Start the router:
Tip
For more installation options (apt, brew, Windows, etc.), see the comprehensive Zenoh Router Installation Guide.
Note
Keep the router running in a separate terminal. All hiroz applications will connect to it.
2. Create a New Rust Project¶
3. Add Dependencies¶
Add hiroz to your Cargo.toml:
[dependencies]
hiroz = { git = "https://github.com/ZettaScaleLabs/hiroz.git" }
hiroz-msgs = { git = "https://github.com/ZettaScaleLabs/hiroz.git" } # Standard ROS 2 message types
tokio = { version = "1", features = ["full"] } # Async runtime
Note
hiroz requires an async runtime. This example uses Tokio, the most popular choice in the Rust ecosystem.
4. Write Your First Application¶
Replace the contents of src/main.rs with this simple publisher example:
Simpler imports with prelude
Instead of importing Builder, Result, and ZContextBuilder separately, use use hiroz::prelude::*; to bring all common hiroz types into scope at once.
use std::time::Duration;
use hiroz::{Builder, Result, context::ZContextBuilder};
use hiroz_msgs::std_msgs::String as RosString;
#[tokio::main]
async fn main() -> Result<()> {
// Initialize hiroz context (connects to router on localhost:7447)
let ctx = ZContextBuilder::default()
.with_connect_endpoints(["tcp/127.0.0.1:7447"])
.build()?;
// Create a ROS 2 node
let node = ctx.create_node("my_talker").build()?;
// Create a publisher for the /chatter topic
let pub_handle = node.create_pub::<RosString>("/chatter").build()?;
// Publish messages every second
let mut count = 0;
loop {
let msg = RosString {
data: format!("Hello from hiroz #{}", count),
};
println!("Publishing: {}", msg.data);
pub_handle.async_publish(&msg).await?;
count += 1;
tokio::time::sleep(Duration::from_secs(1)).await;
}
}
5. Run Your Application¶
Make sure the Zenoh router (zenohd) is running in another terminal, then:
Success
You should see the application publishing messages every second. It will continue until you press Ctrl+C.
6. Test with Multiple Nodes¶
Open another terminal and create a simple listener to verify communication:
Create src/bin/listener.rs:
use hiroz::{Builder, Result, context::ZContextBuilder};
use hiroz_msgs::std_msgs::String as RosString;
#[tokio::main]
async fn main() -> Result<()> {
let ctx = ZContextBuilder::default()
.with_connect_endpoints(["tcp/127.0.0.1:7447"])
.build()?;
let node = ctx.create_node("my_listener").build()?;
let sub = node.create_sub::<RosString>("/chatter").build()?;
println!("Listening on /chatter...");
while let Ok(msg) = sub.async_recv().await {
println!("Received: {}", msg.data);
}
Ok(())
}
Run both:
# Terminal 1: Router
zenohd
# Terminal 2: Publisher
cargo run
# Terminal 3: Listener
cargo run --bin listener
Key Components¶
| Component | Purpose | Usage |
|---|---|---|
| ZContextBuilder | Initialize hiroz environment | Entry point, configure settings |
| ZContext | Manages ROS 2 connections | Create nodes from this |
| Node | Logical unit of computation | Publishers/subscribers attach here |
| Publisher | Sends messages to topics | node.create_pub::<Type>("topic") |
| Subscriber | Receives messages from topics | node.create_sub::<Type>("topic") |
Why a Zenoh router?
hiroz uses router-based discovery by default, aligning with ROS 2's official Zenoh middleware (rmw_zenoh_cpp). This provides:
- Better scalability for large deployments with many nodes
- Lower network overhead compared to multicast discovery
- Production-ready architecture used in real ROS 2 systems
See the Networking chapter for customization options.
What's Happening?¶
sequenceDiagram
accTitle: Talker publishing messages through Zenoh to a Listener
accDescr: The Talker publishes Hello messages to the Zenoh network each second, which delivers each message to the Listener who prints it to the console.
participant T as Talker
participant Z as Zenoh Network
participant L as Listener
T->>Z: Publish "Hello 0"
Z->>L: Deliver message
L->>L: Print to console
Note over T: Wait 1 second
T->>Z: Publish "Hello 1"
Z->>L: Deliver message
L->>L: Print to console
The talker publishes messages every second to the /chatter topic. The listener subscribes to the same topic and prints each received message. Zenoh handles the network transport transparently.
Info
Both nodes run independently. You can start/stop them in any order, and multiple listeners can receive from one talker simultaneously.
Next Steps¶
Now that you understand the basics:
Core Concepts:
- Pub/Sub - Deep dive into pub-sub patterns and QoS
- Services - Request-response communication
- Actions - Long-running tasks with feedback
- Message Generation - How message types work
- Custom Messages - Define your own message types
Development:
- Building - Build configurations and dependencies
- Networking - Zenoh router setup and options