ROS 2 Zenoh Guide 2026
Zenoh is a pub/sub protocol that works natively over WiFi, 5G, and WAN — no multicast, no VPN required. With rmw_zenoh, you get cross-network ROS 2 communication for multi-robot fleets with a single router process.
Why Zenoh over DDS?
| Feature | DDS (CycloneDDS/FastDDS) | Zenoh (rmw_zenoh) |
|---|---|---|
| Discovery | UDP multicast (LAN only) | Peer or router-based (works on WiFi/WAN) |
| Cross-network | Requires bridge/VPN | Native via Zenoh router |
| WiFi robots | Multicast often filtered by AP | Unicast — no AP restrictions |
| Bandwidth | CDR overhead per message | Compact encoding, optional compression |
| Multi-host | Domain bridge or DDS relay | Single `zenohd` router process |
| Intra-process | Supported (DDS) | Supported (shared memory segment) |
Install rmw_zenoh (ROS 2 Jazzy / Humble)
# Option 1: apt (Jazzy only — Ubuntu 24.04) sudo apt install ros-jazzy-rmw-zenoh-cpp # Option 2: build from source (Humble + Jazzy) mkdir -p ~/zenoh_ws/src && cd ~/zenoh_ws/src git clone https://github.com/ros2/rmw_zenoh.git cd ~/zenoh_ws rosdep install --from-paths src --ignore-src -r -y colcon build --cmake-args -DCMAKE_BUILD_TYPE=Release # Zenoh router binary (needed for multi-host) cargo install zenohd # OR download pre-built: # https://github.com/eclipse-zenoh/zenoh/releases
Switch RMW to Zenoh
Set RMW_IMPLEMENTATION before sourcing ROS 2. All nodes in that shell use Zenoh:
# Single session export RMW_IMPLEMENTATION=rmw_zenoh_cpp source /opt/ros/jazzy/setup.bash # Persist in .bashrc echo 'export RMW_IMPLEMENTATION=rmw_zenoh_cpp' >> ~/.bashrc # Verify ros2 doctor --report | grep -A2 middleware
Note: All nodes communicating together must use the same RMW. Mixed-RMW setups require a bridge (ros1_bridge pattern).
Single-Host Setup (No Router)
On a single machine, Zenoh uses peer-to-peer discovery automatically — no router needed:
# Terminal 1 — publisher export RMW_IMPLEMENTATION=rmw_zenoh_cpp ros2 topic pub /chatter std_msgs/msg/String "data: hello zenoh" --rate 5 # Terminal 2 — subscriber export RMW_IMPLEMENTATION=rmw_zenoh_cpp ros2 topic echo /chatter # Confirm Zenoh is active ros2 topic info /chatter -v | grep -A3 "node name"
Multi-Host Setup: Zenoh Router
For WiFi robots or machines on different subnets, run zenohd on a reachable host (your laptop or server):
# === On the router machine (e.g. 192.168.1.100) === zenohd --listen tcp/0.0.0.0:7447 # Alternatively with a config file for more control: zenohd --config /etc/zenoh/router.json5
# === On Robot 1 (e.g. 192.168.1.50) ===
# Create Zenoh config pointing to the router
cat > ~/zenoh_robot.json5 << 'EOF'
{
mode: "client",
connect: {
endpoints: ["tcp/192.168.1.100:7447"]
}
}
EOF
export RMW_IMPLEMENTATION=rmw_zenoh_cpp
export ZENOH_ROUTER_CHECK_ATTEMPTS=-1
ros2 run demo_nodes_cpp talker
# === On Laptop ===
cat > ~/zenoh_laptop.json5 << 'EOF'
{
mode: "client",
connect: { endpoints: ["tcp/192.168.1.100:7447"] }
}
EOF
export RMW_IMPLEMENTATION=rmw_zenoh_cpp
ros2 topic echo /chatterConfig location: rmw_zenoh reads $ZENOH_ROUTER_CONFIG_URI or defaults to peer mode. Point it to your JSON5: export ZENOH_ROUTER_CONFIG_URI=file:///home/ubuntu/zenoh_robot.json5
Router JSON5 Config Reference
// /etc/zenoh/router.json5 — production router
{
mode: "router",
listen: {
endpoints: ["tcp/0.0.0.0:7447"]
},
// Allow robots to scout the router via UDP multicast on same LAN
scouting: {
multicast: {
enabled: true,
address: "224.0.0.224:7446",
interface: "auto"
}
},
// Shared memory for intra-host zero-copy
plugins_loading: { enabled: true },
plugins: {
shared_memory: { enabled: true }
},
// Limit topic bandwidth (bytes/s per key expression)
// qos: { ... } — available in Zenoh 1.x
}Multi-Robot Fleet Pattern
Namespace each robot to avoid topic collisions, then remap on the router for fleet-level aggregation:
# Robot 1 export RMW_IMPLEMENTATION=rmw_zenoh_cpp ros2 launch my_robot robot.launch.py robot_namespace:=robot1 # Robot 2 export RMW_IMPLEMENTATION=rmw_zenoh_cpp ros2 launch my_robot robot.launch.py robot_namespace:=robot2 # Fleet manager on laptop — subscribe to all robots at once export RMW_IMPLEMENTATION=rmw_zenoh_cpp ros2 topic echo /robot1/scan # laser scan from robot 1 ros2 topic echo /robot2/scan # laser scan from robot 2 # With wildcards (Zenoh key expression) # ros2 topic echo /**/scan # NOT standard ROS 2, but works via Zenoh API directly
Bandwidth & Latency Tuning
Shared Memory (same host, zero-copy)
# Enable SHM in Zenoh config — both publisher and subscriber must enable it export ZENOH_SHM=enabled # Verify: ros2 topic pub latency drops to <5µs for large messages
Reduce discovery traffic on WiFi
# Set multicast scouting to false on robots (they connect to router only)
# In zenoh_robot.json5:
scouting: { multicast: { enabled: false } }QoS: limit image topic to 10 Hz on WAN link
ros2 topic pub /camera/image sensor_msgs/msg/Image \ --qos-history keep-last --qos-depth 1 --rate 10
Zenoh CLI Diagnostics
zenoh-scout
Discover all Zenoh peers and routers on the network
z_pub --key 'ros2/chatter' --value 'hello'
Publish directly via Zenoh key (bypasses ROS 2 type system)
z_sub --key 'ros2/**'
Subscribe to all ROS 2 topics via Zenoh wildcard
ros2 doctor --report | grep middleware
Confirm rmw_zenoh is active in current shell
RUST_LOG=zenoh=debug zenohd
Run router with debug logging for connection issues
ros2 topic bw /scan --rmw-implementation rmw_zenoh_cpp
Measure bandwidth of a topic over Zenoh
Common Issues
Nodes don't discover each other across WiFi
WiFi APs block UDP multicast by default. Switch robots to client mode with a router: set mode:'client' and connect to zenohd IP:7447. Peer mode requires multicast which most APs filter.
ZENOH_ROUTER_CHECK_ATTEMPTS timeout on startup
Set ZENOH_ROUTER_CHECK_ATTEMPTS=-1 to disable the router check (useful when running without a router in peer mode). Or start zenohd before any ROS 2 nodes.
ros2 topic list shows topics but echo gets nothing
Mismatched QoS. Zenoh maps ROS 2 QoS but reliability must match. Try --qos-reliability best_effort on both sides, or set Transient Local for late-joining subscribers.
Next Steps
- → ROS 2 DDS & RMW guide — compare CycloneDDS, FastDDS and Zenoh for your use case
- → ROS 2 QoS guide — tune reliability, durability and deadline policies before deploying over WiFi
- → ROS 2 Intra-Process guide — zero-copy within a single host (no Zenoh router needed)