Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 77 additions & 0 deletions content/learning-paths/cross-platform/ros2-zenoh-arm/_index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
---
title: Build a ROS 2 and Zenoh simulation environment on an Arm server

description: Set up ROS 2 Jazzy with rmw_zenoh in Docker, then run and evaluate a Neobotix ROX simulation on an Arm server.

minutes_to_complete: 60

who_is_this_for: Developers who want to build and examine a containerized ROS 2 robotics simulation on an Arm server.

learning_objectives:
- Set up a Docker-based ROS 2 Jazzy development and simulation environment on an Arm server
- Configure `rmw_zenoh` as the ROS 2 middleware and explore communication between ROS 2 nodes
- Launch and interact with a Neobotix ROX robot simulation using Gazebo, Navigation2, and RViz
- Evaluate Zenoh router behaviour and the effect of shared-memory transport

prerequisites:
- An Arm server running Linux with at least 8 CPU cores, 16 GB of RAM, and 30 GB of free disk space
- Docker and Docker Compose installed
- Network access to ports 6080 and 6081 on the Arm server
- Basic familiarity with Linux terminal commands

author:
- Odin Shen
- Kwashie Andoh
- Habib Ogunbanwo

generate_summary_faq: false
rerun_summary: false
rerun_faqs: false

### Tags
skilllevels: Introductory
subjects: Containers and Virtualization
armips:
- Neoverse
tools_software_languages:
- ROS 2
- rmw_zenoh
- Docker
- Gazebo
- Navigation2
- RViz
operatingsystems:
- Linux

further_reading:
- resource:
title: ROS 2 Jazzy RMW implementations
link: https://docs.ros.org/en/jazzy/Installation/RMW-Implementations.html
type: documentation
- resource:
title: rmw_zenoh source and documentation
link: https://github.com/ros2/rmw_zenoh
type: documentation
- resource:
title: Navigation2 getting started
link: https://docs.nav2.org/getting_started/index.html
type: documentation
- resource:
title: Gazebo Harmonic getting started
link: https://gazebosim.org/docs/harmonic/getstarted/
type: documentation
- resource:
title: ROS 2 and Zenoh on Arm source repository
link: https://github.com/odincodeshen/ros2-zenoh-arm
type: website
- resource:
title: Install Docker
link: /install-guides/docker/
type: documentation

### FIXED, DO NOT MODIFY
# ================================================================================
weight: 1 # _index.md always has weight of 1 to order correctly
layout: "learningpathall" # All files under learning paths have this same wrapper
learning_path_main_page: "yes" # This should be surfaced when looking for related content. Only set for _index.md of learning path content.
---
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
# ================================================================================
# FIXED, DO NOT MODIFY THIS FILE
# ================================================================================
weight: 21 # Set to always be larger than the content in this path to be at the end of the navigation.
title: "Next Steps" # Always the same, html page title.
layout: "learningpathall" # All files under learning paths have this same wrapper for Hugo processing.
---
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
---
title: Configure Zenoh for ROS 2
description: Create separate Zenoh router and session configuration files, then configure ROS 2 processes to use them.
weight: 3

layout: "learningpathall"
---

## Understand the Zenoh configuration files

`rmw_zenoh` uses two configuration files with different responsibilities:

- `ROUTER_CONFIG.json5` configures the Zenoh router
- `SESSION_CONFIG.json5` configures the normal ROS 2 and Zenoh sessions

Keep the installed templates unchanged. You copy them to `~/container_data/` so you can modify the working copies later. This directory is a Docker volume, so the files persist when the container restarts and are also accessible from the host.

## Copy the router and session configurations

Open a terminal in the `robot` container. Copy each installed template to the corresponding working file:

```bash
cp /opt/ros/jazzy/share/rmw_zenoh_cpp/config/DEFAULT_RMW_ZENOH_ROUTER_CONFIG.json5 \
~/container_data/ROUTER_CONFIG.json5

cp /opt/ros/jazzy/share/rmw_zenoh_cpp/config/DEFAULT_RMW_ZENOH_SESSION_CONFIG.json5 \
~/container_data/SESSION_CONFIG.json5
```

{{% notice Important %}}
The two commands look similar, but the source files are different. Copy `DEFAULT_RMW_ZENOH_ROUTER_CONFIG.json5` to `ROUTER_CONFIG.json5` and `DEFAULT_RMW_ZENOH_SESSION_CONFIG.json5` to `SESSION_CONFIG.json5`.
{{% /notice %}}

## Load the workshop environment

Source the workshop environment so ROS 2 uses the new configuration files:

```bash
source ~/workshop_env.bash
```

The output should show both exported paths:

```output
ZENOH_ROUTER_CONFIG_URI=/home/ubuntu/container_data/ROUTER_CONFIG.json5
ZENOH_SESSION_CONFIG_URI=/home/ubuntu/container_data/SESSION_CONFIG.json5
```

{{% notice Note %}}
From this point, run `source ~/workshop_env.bash` whenever you open a new terminal in the `robot` container.
{{% /notice %}}

## What you've accomplished and what's next

You've created and verified separate router and session configurations, then loaded their paths into the ROS 2 environment. Next, you'll use three ROS 2 processes to observe the router's role in discovery.
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
---
title: Control the robot directly
description: Publish velocity commands to the Neobotix ROX base with teleoperation or ROS 2, then verify movement through odometry.
weight: 7

layout: "learningpathall"
---

## Understand the velocity interface

The ROX base subscribes to the `/cmd_vel` topic using the `geometry_msgs/Twist` message type. The message carries linear and angular velocity commands.

Any process that publishes to `/cmd_vel` can control the base. Navigation2 uses this same interface, so it is one publisher to the robot rather than a privileged control path.

Open a sourced terminal in the `robot` container:

```bash
source ~/workshop_env.bash
```

## Control the robot with the keyboard

Start keyboard teleoperation:

```bash
just teleop
```

Use the key bindings displayed in the terminal to drive the robot while you observe its movement in RViz.

![Keyboard teleoperation terminal showing the movement key bindings for controlling the robot.](images/robot-teleoperation.png)

## Publish a velocity command

You can also publish a single command that sets the forward velocity to `0.2 m/s`:

```bash
ros2 topic pub --once /cmd_vel geometry_msgs/msg/Twist "{linear: {x: 0.2}}"
```

The command uses the same `/cmd_vel` interface as teleoperation and Navigation2.

## Verify movement with odometry

Read one odometry message and display the robot position:

```bash
ros2 topic echo /odom --once | grep -A2 position
```

The `x` position should advance when the robot moves. On the supplied reference system, a 3-second command at `0.2 m/s` moved the robot from approximately `x = 0` to `x = 0.39 m`:

```output
x: 0.3899999883542309
```

This value is an example, not an exact target. Acceleration behaviour and the robot's starting position affect the result.

{{% notice Note %}}
The UR10 arm on the ROX uses a `JointTrajectory` action rather than `Twist`. Publishing `Twist` to the base and `JointTrajectory` to the arm follows the standard ROS interface for each mechanism.
{{% /notice %}}

## What you've learned and what's next

You've controlled the robot through the same velocity interface used by Navigation2 and confirmed its movement through `/odom`. Next, you'll inspect the CPU cost, simulation speed, and internal traffic of the running system.
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
---
title: Enable Zenoh shared-memory transport
description: Enable shared memory in the Zenoh router and session configurations, then compare point-cloud latency and loopback traffic.
weight: 9

layout: "learningpathall"
---

## Understand the shared-memory experiment

By default, processes on the same machine exchange data over TCP loopback. Zenoh shared-memory transport places large messages in `/dev/shm` and avoids the network stack. Applications don't need code changes or loaned buffers, and Zenoh falls back to TCP if shared memory is unavailable.

You first measure the default TCP-loopback latency. You then enable shared memory in both Zenoh configuration files, restart the relevant processes, and repeat the measurement.

## Measure the TCP-loopback baseline

Stop Navigation2 in Terminal 3. The latency measurement needs wall-clock timestamps, and Navigation2 doesn't operate in this mode.

Stop the current simulation. Restart it in Terminal 2 with wall-clock time and without the Gazebo viewer:

```bash
just rox_simu use_wall_time:=True no_gui
```

Open a new terminal, source the environment, and measure the point-cloud latency:

```bash
source ~/workshop_env.bash
just cam_latency
```

On the supplied reference system, the point-cloud latency is around `9–10 ms`:

```output
Mean : 9.40 ms | Std : 0.82 ms | Min : 7.91 ms | Max : 12.15 ms
```

Record the mean for comparison.

## Enable shared memory in both configurations

Open both of these working files:

- `~/container_data/ROUTER_CONFIG.json5`
- `~/container_data/SESSION_CONFIG.json5`

In each file, find the `transport/shared_memory` block and change its `enabled` value to:

```json5
enabled: true,
```

{{% notice Important %}}
Both files contain multiple `enabled` fields. In both `ROUTER_CONFIG.json5` and `SESSION_CONFIG.json5`, change only the `enabled` value inside the `shared_memory` block.
{{% /notice %}}

The router and ROS 2 sessions read these files when their processes start. Stop the router and simulation processes with `Ctrl+C`, then restart them so they load the updated setting:

```bash
# Router terminal
just router
```

```bash
# Simulation terminal
just rox_simu use_wall_time:=True no_gui
```

Run the latency measurement again from a sourced terminal:

```bash
just cam_latency
```

The supplied reference system produced these results:

| Measurement | TCP loopback (default) | Shared memory |
|---|---|---|
| Mean latency | `9.3–10.2 ms` | `6.3–7.4 ms` |
| Standard deviation | Approximately `1.0 ms` | Approximately `0.65 ms` |
| `/dev/shm` usage | `8 KB` | `247 MB` |

The reference mean latency improves by approximately 30%, with lower jitter. Your result depends on the server, workload, and run conditions; compare the two measurements from your own system.

## Verify the transport change

Check the shared-memory directory and loopback traffic:

```bash
ls /dev/shm
just iftop_lo
```

`.zenoh` files should appear under `/dev/shm` for Zenoh processes using shared memory. The large loopback flows should also disappear because the data now moves through memory.

## Verify the complete Learning Path

Use this checklist to confirm the final environment:

- [ ] Both Docker containers show `Up`, and their browser desktops are accessible
- [ ] The talker and listener continue exchanging messages after the router stops
- [ ] `just rox_simu no_gui` and `just rox_nav2` start without errors, and Navigation2 reports `Managed nodes are active`
- [ ] `/scan` arrives at approximately 8 Hz
- [ ] RViz reports `Feedback: reached` after the robot navigates to a valid goal
- [ ] The robot moves through teleoperation or a `/cmd_vel` publication, and `/odom` confirms the movement
- [ ] `just top`, `just rt_factor`, and `just iftop_lo` produce output
- [ ] You recorded both latency measurements, and `.zenoh` files appear under `/dev/shm`; the supplied reference system shows lower shared-memory latency

## What you've accomplished

You've built a ROS 2 Jazzy simulation environment on an Arm server, observed Zenoh discovery behaviour, navigated and controlled a Neobotix ROX robot, measured resource use, and compared TCP-loopback communication with shared-memory transport.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
---
title: Visualize and navigate the robot with RViz
description: Inspect the Neobotix ROX map and costmaps in RViz, then send a Navigation2 goal and verify that the robot reaches it.
weight: 6

layout: "learningpathall"
---

## Understand the RViz navigation view

RViz subscribes to ROS 2 topics and displays the robot model, laser scans, camera data, map, and Navigation2 costmaps. It also provides tools that publish messages, including the goal tool used here.

The navigation view contains several layers:

- The *map* shows the known environment
- The *global costmap* combines the static map with navigation costs across the mapped area
- The *local costmap* moves with the robot and reflects live sensor data nearby
- The *inflation layer* creates the red-to-blue gradient near walls, increasing the cost of paths that pass close to obstacles

## Start RViz

Open a new terminal in the `robot` container, source the environment, and start the Navigation2 RViz configuration:

```bash
source ~/workshop_env.bash
just rviz_nav2
```

Wait for the map and costmaps to render. The light blue area represents free space. The small window that follows the robot is the local costmap, while the fixed background is the global costmap.

## Send a navigation goal

1. Click Nav2 Goal in the top toolbar.
2. Move your mouse onto the mapped area in the centre.
- Click and hold somewhere in the free/light-blue area.
- While holding the mouse button, drag a short distance. You'll see an arrow appear.
3. Where you first clicked = where you want the robot to go.
4. Direction of the arrow = direction you want the robot facing when it arrives.
5. Release the mouse button.

Nav2 should then calculate a path and the robot should begin moving.

Goals outside the mapped costmap don't have a valid planned path, so the robot won't move toward them.

![RViz showing the Neobotix ROX robot, navigation map, costmaps, and Navigation2 panel.](images/rviz-navigation-goal.png)

## Verify the navigation result

The robot should plan a path, drive to the goal, and report `Feedback: reached`. A successful reference result is:

```output
Navigation: active
Feedback: reached
Distance remaining: 0.03 m
Recoveries: 0
```

The final remaining distance can vary with the selected goal and simulation run. Reaching the goal without recovery behaviour is the success criterion.

## What you've accomplished and what's next

You've interpreted the map, costmaps, and inflation layer, then set a goal position and orientation with RViz. Next, you'll bypass Navigation2's planner and publish velocity commands directly to the robot base.
Loading
Loading