Distribute a ROS 2 robotic system across Arm devices with Zenoh
Introduction
Understand the distributed ROS 2 topology
Connect the ROS 2 control container with Zenoh
Connect the Raspberry Pi
Verify cross-device ROS 2 communication
Isolate multiple ROS 2 robots that share a Zenoh router
Next Steps
Distribute a ROS 2 robotic system across Arm devices with Zenoh
Set up the edge device
After connecting the control container, you’ll connect a Raspberry Pi to the Zenoh router.
A Raspberry Pi 5 running 64-bit Raspberry Pi OS was used for validating the Learning Path. You can also use a Raspberry Pi 4 or another Linux-based Arm device.
Connect to the Raspberry Pi over SSH or open a terminal on an attached display. Confirm that the operating system is 64-bit:
uname -m
The expected output is:
aarch64
Docker keeps ROS 2 and its dependencies separate from the host operating system. Install Docker if it’s not already present:
curl -fsSL https://get.docker.com | sudo sh
sudo usermod -aG docker $USER
Log out and log back in so that the new group membership takes effect, then verify Docker:
docker version
The client and server sections should both report linux/arm64.
Select an address the Raspberry Pi can reach
The <your_arm_server_ip> that you use must identify the selected Arm server that the Raspberry Pi can reach. It’s not automatically the same address used by your laptop.
Consider the following when selecting an IP address to use:
- Use a private or LAN address when the Raspberry Pi has a route to that network.
- Use a public address only when a private route or VPN is unavailable, and restrict TCP port
7447to the Raspberry Pi’s address or trusted network using firewall rules. - Don’t use
172.x. Those are internal Docker addresses.
On the selected Arm server, display the available addresses and select the server’s IP:
hostname -I
On the Raspberry Pi, replace <your_arm_server_ip> with your selected IP address and test the Zenoh TCP port:
python3 -c "import socket; socket.create_connection(('<your_arm_server_ip>',7447),5); print('router reachable')"
If this test times out, fix the network path before starting ROS 2. For an Amazon EC2 server, permit inbound TCP port 7447 only from the Raspberry Pi’s public egress address or trusted network in the instance security group. Don’t allow access from 0.0.0.0/0.
Start the edge container
On the Raspberry Pi, replace <your_arm_server_ip> with your selected IP address and create the edge container:
docker run -d --name pi_edge --net=host \
-e ZENOH_CONFIG_OVERRIDE='mode="client";connect/endpoints=["tcp/<server_ip>:7447"]' \
odinlmshen/ros2-zenoh-arm:jazzy-edge \
sleep infinity
--net=host gives the container direct access to the Raspberry Pi’s network interfaces. The configuration override makes every rmw_zenoh session in the container connect to the server router as a client.
First, get the container ID for the control container. From an SSH session on the Arm server, run:
docker ps
The output is similar to:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c0b8da0d49d4 odinlmshen/ros2-zenoh-arm:jazzy-edge "/ros_entrypoint.sh …" 4 days ago Up 4 days pi_edge
Use the container ID to open a bash shell in the running container on your Raspberry Pi:
docker exec -it c0b8da0d49d4 /bin/bash
Next, load ROS 2 in the bash shell:
source /opt/ros/jazzy/setup.bash
Confirm the middleware and endpoint:
echo $RMW_IMPLEMENTATION
echo $ZENOH_CONFIG_OVERRIDE
The output is similar to the following, where <your_arm_server_ip> is the IP address of your selected Arm server:
rmw_zenoh_cpp
mode="client";connect/endpoints=["tcp/<your_arm_server_ip>:7447"]
Run source /opt/ros/jazzy/setup.bash in every new docker exec shell on your Raspberry Pi.
What you’ve accomplished and what’s next
You’ve started the edge container on the Raspberry Pi and configured it as a client of the Zenoh router.
Next, you’ll verify the ROS 2 graph, sensor data, and bidirectional messages across the devices.