Skip to content

Commit b33c662

Browse files
Updated the Zenoh queryable example for clarity and consistency. Improved structure, simplified language, and clarified the battery health calculation.
1 parent 4012285 commit b33c662

File tree

7 files changed

+74
-63
lines changed

7 files changed

+74
-63
lines changed

content/learning-paths/cross-platform/zenoh-multinode-ros2/1_intro-zenoh.md

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,21 +15,21 @@ Such systems require fast, reliable, and scalable data communication between nod
1515
This includes not just broadcasting sensor updates or actuator commands (pub/sub), but also performing state queries, storing values for later use, and even distributed computation across nodes.
1616

1717
A modern protocol must be:
18-
* Low-latency: Immediate delivery of time-critical messages.
19-
* High-throughput: Efficient data flow across many devices.
20-
* Decentralized: No reliance on central brokers or fixed infrastructure.
21-
* Flexible: Able to run on lightweight edge devices, across WANs, or inside cloud-native environments.
18+
* Low-latency: immediate delivery of time-critical messages
19+
* High-throughput: efficient data flow across many devices
20+
* Decentralized: no reliance on central brokers or fixed infrastructure
21+
* Flexible: able to run on lightweight edge devices, across WANs, or inside cloud-native environments
2222

2323
Traditional communication stacks such as Data Distribution Service (DDS) serve as the backbone for middleware like ROS 2. However, DDS struggles in multi-network or wireless environments where multicast is unavailable, or NAT traversal is needed. Zenoh was developed to address these challenges with a unified approach to data movement, storage, and interaction across heterogeneous, distributed systems.
2424

2525
## What is Zenoh? A scalable pub/sub protocol for the industrial edge
2626

2727
[Eclipse Zenoh](https://zenoh.io/) is a modern, open-source, data-centric communication protocol that goes beyond traditional pub/sub. Designed specifically for edge computing, industrial IoT, robotics, and autonomous systems, Zenoh unifies:
2828

29-
- Data in motion through a powerful and efficient pub/sub model.
30-
- Data at rest via geo-distributed storage plugins.
31-
- Data in use with direct query support.
32-
- On-demand computation via queryable nodes that can generate data dynamically.
29+
- Data in motion through a powerful and efficient pub/sub model
30+
- Data at rest via geo-distributed storage plugins
31+
- Data in use with direct query support
32+
- On-demand computation via queryable nodes that can generate data dynamically
3333

3434
Unlike most traditional stacks, Zenoh is fully decentralized and designed to operate across cloud-to-edge-to-thing topologies, making it ideal for industrial robotics, autonomous systems, and smart environments.
3535

@@ -42,7 +42,7 @@ In this Learning Path, you’ll use Zenoh to build and validate a multi-node dis
4242
You can substitute Raspberry Pi with any Linux-based Arm device that supports networking, such as a Cortex-A or Neoverse board.
4343

4444
By the end of this Learning Path, you'll be able to:
45-
- Explain the core architecture and data flow principles behind Eclipse Zenoh protocol, including its support for pub/sub, querying, and queryable edge functions.
46-
- Build and run distributed Zenoh examples across multiple Arm-based nodes using Raspberry Pi or other Arm Linux devices.
47-
- Rebuild and extend a Zenoh queryable node to simulate edge-side logic.
45+
- Explain the core architecture and data flow principles behind Eclipse Zenoh protocol, including its support for pub/sub, querying, and queryable edge functions
46+
- Build and run distributed Zenoh examples across multiple Arm-based nodes using Raspberry Pi or other Arm Linux devices
47+
- Rebuild and extend a Zenoh queryable node to simulate edge-side logic
4848

content/learning-paths/cross-platform/zenoh-multinode-ros2/2_zenoh-install.md

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,9 @@ layout: learningpathall
99

1010
## Set up Zenoh on Arm devices
1111

12-
This section shows how to install and build the open-source Eclipse Zenoh protocol on Arm-based devices like Raspberry Pi.
12+
This section shows you how to install and build the open-source Eclipse Zenoh protocol on Arm-based devices like Raspberry Pi.
1313

14-
The following instructions have been verified on Raspberry Pi 4 and 5, but you can use any Arm Linux device. These steps apply to Raspberry Pi and other Arm-based Linux platforms.
15-
16-
Before building Zenoh, make sure your system has the necessary development tools and runtime libraries.
14+
The following instructions have been verified on Raspberry Pi 4 and 5, but you can use any Arm Linux device. These steps apply to Raspberry Pi and other Arm-based Linux platforms. Before building Zenoh, make sure your system has the necessary development tools and runtime libraries.
1715

1816
### Install the Rust development environment
1917

content/learning-paths/cross-platform/zenoh-multinode-ros2/3_zenoh-multinode.md

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,21 +11,16 @@ layout: learningpathall
1111

1212
After building Zenoh and its core examples, the next step is to deploy them across multiple Arm-based devices.
1313

14-
If you’ve already installed Zenoh on an Arm Cortex-A or Neoverse platform as shown in the previous section, you can simply copy the compiled binaries from `~/zenoh/target/release/` to each of your Raspberry Pi devices.
14+
If you’ve already installed Zenoh on an Arm Cortex-A or Neoverse platform as shown in the previous section, you can copy the compiled binaries from `~/zenoh/target/release/` to each of your Raspberry Pi devices.
1515

16-
However, to streamline deployment across multiple devices and ensure repeatability, this section demonstrates how to package Zenoh into a Docker image for batch rollout and scalable testing.
16+
To simplify and scale deployment across multiple devices, this section shows how to containerize Zenoh with Docker for streamlined distribution and consistent multi-node testing. This containerized approach enables repeatable rollouts and makes it easier to test distributed communication across Raspberry Pi, Arm cloud instances (like AWS Graviton), and Arm Virtual Hardware.
1717

18-
This containerized approach not only simplifies deployment on Raspberry Pi, but also integrates seamlessly with Arm cloud platforms such as AWS Graviton Arm Cortex-A Linux or Arm Virtual Hardware, enabling a consistent cloud-to-edge development and validation workflow.
19-
20-
In this session, you’ll use Raspberry Pi boards to simulate a scalable distributed environment. The same workflow applies to any Arm Linux system, including cloud instances and virtual hardware.
21-
22-
This setup allows you to simulate real-world, cross-node communication scenarios, making it ideal for evaluating Zenoh’s performance in robotics and industrial IoT applications.
18+
In this session, you’ll use Raspberry Pi boards to simulate a scalable distributed environment. The same workflow applies to any Arm Linux system, including cloud instances and virtual hardware. This setup allows you to simulate real-world, cross-node communication scenarios, making it ideal for evaluating Zenoh’s performance in robotics and industrial IoT applications. Zenoh is ideal for robotics and industrial IoT systems that require fast, decentralized communication. It supports scalable data exchange across devices using pub/sub, storage, and query models.
2319

2420
### Install Docker on Raspberry Pi
25-
To simplify this process and ensure consistency, you can use Docker to containerize your Zenoh and ROS 2 environment.
26-
This lets you quickly replicate the same runtime on any device without needing to rebuild from source.
21+
To simplify this process and ensure consistency, you can use Docker to containerize your Zenoh and ROS 2 environment. This lets you quickly replicate the same runtime on any device without needing to rebuild from source.
2722

28-
This enables multi-node testing and real-world distributed communication scenarios.
23+
This enables scalable, multi-node testing in realistic distributed environments.
2924

3025
First, install Docker on each Raspberry Pi device:
3126

@@ -146,9 +141,9 @@ docker run -it --network=host zenoh-node
146141

147142
The Zenoh example binaries are now available within this container, allowing you to test pub/sub and query flows across devices.
148143

149-
## Run Zenoh in a multi-node environment
144+
## Run Zenoh examples in a multi-node environment
150145

151-
You’re now ready to run and test Zenoh communication flows across distributed edge devices.
146+
With Zenoh running inside containers across devices, you’re now ready to explore real-time communication using prebuilt examples.
152147

153148
The following examples are written in Rust and precompiled in your container image. They're fully interoperable and can be used to demonstrate Zenoh's key capabilities across devices. The Rust binaries are available in the `$ZENOH_LOC/target/release/examples/` directory. If you haven't set `ZENOH_LOC`, they can be found under `~/zenoh/target/release/examples/`.
154149

content/learning-paths/cross-platform/zenoh-multinode-ros2/4_zenoh-ex1-pubsub.md

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,18 @@ This example demonstrates Zenoh's real-time publish/subscribe model across two R
1212

1313
The subscriber listens for all data published under the key expression `demo/example/**`, which matches any topic beginning with `demo/example/`.
1414

15-
## Start the subscriber node
15+
### Start the subscriber node
1616

17-
Run the subscriber example on one of the Raspberry Pi systems.
17+
Run the subscriber example on one of the Raspberry Pi systems:
1818

1919
```bash
2020
cd ~/zenoh/target/release/examples
2121
./z_sub
2222
```
2323

24-
## Start the publisher node
24+
### Start the publisher node
2525

26-
Then, log in to the other Raspberry Pi and run the publisher.
26+
Then, log in to the other Raspberry Pi and run the publisher:
2727

2828
```bash
2929
cd ~/zenoh/target/release/examples
@@ -34,15 +34,13 @@ cd ~/zenoh/target/release/examples
3434
You can run both `z_sub` and `z_pub` on the same device for testing, but running them on separate Raspberry Pis demonstrates Zenoh’s distributed discovery and cross-node communication.
3535
{{% /notice %}}
3636

37-
## Observe the pub/sub data flow
37+
### Observe the pub/sub data flow
3838

39-
The result is shown below:
39+
The results are shown below:
4040

4141
![img1 Zenoh subscriber receiving messages from a publisher in a two-terminal view#center](zenoh_ex1.gif "Simple Pub/Sub")
4242

43-
The left-side window shows the `z_sub` program.
44-
45-
It receives values with the key `demo/example/zenoh-rs-pub` continuously published by `z_pub` running in the right-side window.
43+
The left-side window shows the `z_sub` program. It receives values with the key `demo/example/zenoh-rs-pub` continuously published by `z_pub` running in the right-side window.
4644

4745
This example confirms that Zenoh’s zero-configuration peer discovery and real-time pub/sub communication are working correctly across physical nodes.
4846

content/learning-paths/cross-platform/zenoh-multinode-ros2/5_zenoh-ex2-storagequery.md

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,22 +7,25 @@ weight: 6
77
layout: learningpathall
88
---
99

10-
## Example 2: Storage and query
10+
## Query historical data using Zenoh’s storage engine
1111

12-
The second example adds Zenoh's data storage and querying capabilities by enabling nodes to retrieve historical values on demand.
12+
This example demonstrates Zenoh's data storage and query model which enables nodes to retrieve previously published values—even after the original publisher goes offline.
1313

14-
Building on the previous pub/sub example, you’ll now explore how Zenoh supports persistent data storage and on-demand querying, a powerful feature for robotics and IIoT applications.
14+
Building on the previous pub/sub example, you’ll now run a lightweight Zenoh daemon that stores key–value pairs in memory. Then, you’ll publish data with `z_put` and retrieve it using `z_get`.
1515

16-
In a typical warehouse or factory scenario, autonomous robots can periodically publish sensor data,such as position, temperature, or battery level—that a central system or peer robot may later need to query.
16+
This pattern is ideal for robotics and IIoT scenarios where devices intermittently connect or request snapshots of remote state.
1717

18+
For example, in a warehouse or factory:
19+
- Robots can periodically publish position, temperature, or battery level
20+
- A central system or peer node can later query these values on demand
1821

1922
Unlike Pub/Sub, which requires live, real-time message exchange, Zenoh's storage and query model enables asynchronous access to data that was published earlier, even if the original publisher is no longer online.
2023

2124
In this example, you’ll run the `zenohd` daemon with in-memory storage and use `z_put` to publish data and `z_get` to retrieve it.
2225

2326
This is especially useful for distributed systems where nodes may intermittently connect or request snapshots of state from peers.
2427

25-
### Step 1: Start the Zenoh daemon with in-memory storage
28+
### Start the Zenoh daemon with in-memory storage
2629

2730
On one Raspberry Pi, launch the Zenoh daemon with a configuration that enables in-memory storage for keys in the `demo/example/**` directory.
2831

@@ -37,7 +40,7 @@ You should see log messages indicating that the storage_manager plugin is loaded
3740

3841
If port 7447 is already in use, either stop any previous Zenoh processes or configure a custom port using the `listen.endpoints.router` setting.
3942

40-
### Step 2: Publish data
43+
### Publish a value
4144

4245
On 2nd Raspberry Pi device, use `z_put` to send a key-value pair that will be handled by the `zenohd` storage.
4346

@@ -48,7 +51,7 @@ cd ~/zenoh/target/release/examples
4851

4952
This command stores the string `Hello from storage!` under the key demo/example/test1.
5053

51-
### Step 3: Query the data
54+
### Query the stored value
5255

5356
Back on first Raspberry Pi, you can now query the stored data from any Zenoh connected node.
5457

@@ -68,9 +71,18 @@ The result is shown below:
6871

6972
![img2 alt-text#center](zenoh_ex2.gif "Figure 2: Storage and Query")
7073

71-
{{% notice tip %}}
74+
{{% notice Tip %}}
7275
If you have more than two Raspberry Pi devices, you can run the `z_get` command on a third device to validate that storage queries work seamlessly across a multi-node setup.
7376
{{% /notice %}}
7477

7578
This example shows how Zenoh's storage with query model supports asynchronous data access and resilient state-sharing—critical capabilities in robotics and industrial IoT systems where network connectivity may be intermittent or system components loosely coupled.
7679

80+
## What's next
81+
82+
Now that you've seen how Zenoh handles pub/sub and storage-based queries, you're ready to build reactive and intelligent edge nodes.
83+
84+
In the next example, you’ll implement a **Zenoh queryable** that responds to runtime parameters,such as battery level and temperature, by computing and returning a real-time health score. This showcases how Zenoh supports on-demand edge computation without needing to pre-store data.
85+
86+
87+
88+

content/learning-paths/cross-platform/zenoh-multinode-ros2/6_zenoh-ex3-queryable.md

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,25 @@
11
---
2-
title: Run a Zenoh queryable example for edge computation
2+
title: Run a Zenoh queryable node for on-demand edge computation
33

44
weight: 7
55

66
### FIXED, DO NOT MODIFY
77
layout: learningpathall
88
---
99

10-
## Example 3: Computation on query
10+
## Computation on query
1111

12-
Next, you’ll explore Zenoh's queryable capability, which lets a node dynamically respond to data queries by executing a custom computation or data generation function.
12+
This example demonstrates Zenoh's queryable capability, which lets a node respond to incoming data requests by computing results in real time, rather than returning previously stored values.
1313

1414
Unlike `zenohd` which simply returns stored data, a queryable node can register to handle a specific key expression and generate responses at runtime. This is ideal for distributed computing at the edge, where lightweight devices, such as Raspberry Pi nodes, can respond to requests with calculated values. This enables sensor fusion, AI inference results, and diagnostics.
1515

16-
### Use Case: On-Demand battery health estimation
16+
### Use case: estimate battery health on demand
1717

1818
Imagine a robot fleet management system where the central planner queries each robot for its latest battery health score, which is not published continuously but calculated only when queried.
1919

20-
This saves bandwidth and enables edge compute optimization using Zenoh's Queryable.
20+
This reduces bandwidth usage and enables edge-side optimization using Zenoh's queryable feature.
2121

22-
### Step 1: Launch a queryable node
22+
### Launch a queryable node
2323

2424
On one Raspberry Pi device, run the `z_queryable` Zenoh example to register a queryable handler.
2525

@@ -38,7 +38,7 @@ Press CTRL-C to quit...
3838

3939
The node is now ready to accept queries on the key `demo/example/zenoh-rs-queryable` and respond with a predefined message.
4040

41-
### Step 2: Trigger a query from another node
41+
### Trigger a query from another node
4242

4343
On the other Raspberry Pi device, run the `z_get` example.
4444

@@ -71,4 +71,7 @@ This model enables edge-based intelligence, such as:
7171

7272
Queryable is a key feature for data-in-use scenarios, allowing fine-grained, on-demand compute inside your Zenoh-powered architecture.
7373

74-
Next, you’ll extend this Queryable pattern to perform parameterized computation, simulating edge diagnostics and adaptive inference.
74+
## What's next
75+
76+
In the next example, you'll extend this queryable pattern to support **runtime parameters**, such as battery level and temperature, allowing each node to return a calculated health score on demand.
77+

content/learning-paths/cross-platform/zenoh-multinode-ros2/7_zenoh-querycomp.md

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
title: Run a Zenoh queryable with parameterized computation
2+
title: Run a Zenoh queryable with parameterized Rust computation
33
weight: 8
44

55
### FIXED, DO NOT MODIFY
@@ -14,15 +14,15 @@ You’ll learn how to use Zenoh's Queryable API in Rust to build a parameterized
1414

1515
This extends a previous example by supporting runtime query parameters like battery level and temperature.
1616

17-
## Use Case: Real-time battery health via computation
17+
## Use case: real-time battery health through on-demand computation
1818

1919
In robotic fleet management, a central controller may need to assess each robot’s battery health on demand.
2020

2121
Instead of streaming data continuously, robots expose a queryable endpoint that returns a real-time health score based on current battery level and temperature.
2222

2323
This saves bandwidth and enables lightweight edge-side decision-making.
2424

25-
### Step 1: Create a new Zenoh rust project
25+
### Create a new Zenoh rust project
2626

2727
On any Raspberry Pi:
2828

@@ -40,7 +40,7 @@ tokio = { version = "1", features = ["full"] }
4040
url = "2"
4141
```
4242

43-
### Step 2: Implement the queryable node
43+
### Implement the queryable node
4444

4545
Next, log in to the other Raspberry Pi.
4646

@@ -103,8 +103,14 @@ Inside the callback:
103103
- A health score is computed from these inputs.
104104
- The result is sent back to the querying client using query.reply().
105105

106+
{{% notice Tip %}}
107+
You can extend this queryable pattern to respond to other real-time diagnostics, such as CPU load, camera snapshots, or local ML inference results.
108+
{{% /notice %}}
109+
106110
This design pattern enables efficient, on-demand data exchange with minimal bandwidth usage. This is ideal for edge computing scenarios where resources and connectivity are constrained.
107111

112+
### Battery health estimation formula
113+
108114
The health score is calculated using the following logic:
109115

110116
```rust
@@ -115,16 +121,15 @@ This formula estimates battery health as a percentage, considering both battery
115121
- battery: Current battery level (default 50%)
116122
- temp: Current temperature (default 25°C)
117123

118-
The health estimation logic begins with the battery level as the baseline score.
119-
If the temperature rises above 25°C, the score is adjusted downward—specifically, for every 2°C above this threshold, the health is reduced by 1%.
124+
This logic computes battery health as a percentage, adjusting for elevated temperatures. If temperature exceeds 25°C, the score is reduced by 1% for every 2°C increase.
120125

121126
To ensure the calculation remains safe even when the temperature is below 25°C, the code uses saturating_sub(25), which prevents the result from becoming negative and avoids potential underflow errors.
122127

123-
For example, if battery = 88 and temp = 32, then:
128+
For example, if `battery = 88` and `temp = 32`, then:
124129
- Temperature offset = (32 - 25) / 2 = 3
125130
- Health = 88 - 3 = 85%
126131

127-
### Step 3: Build and run
132+
### Build and run
128133

129134
```bash
130135
cd $HOME/zenoh/zenoh_battery_estimator
@@ -138,7 +143,7 @@ After the build process, you will see:
138143
Finished `release` profile [optimized] target(s) in 1m 22s
139144
```
140145

141-
### Step 4: Query it with parameters
146+
### Query it with parameters
142147

143148
Run it on the Raspberry Pi you used for the build run:
144149

@@ -156,9 +161,9 @@ cd ~/zenoh/target/release/examples
156161

157162
The result is shown below:
158163

159-
![img4 alt-text#center](zenoh_ex4.gif "Figure 4: Dynamic Queryable with Computation")
164+
![img4 Estimated battery health query#center](zenoh_ex4.gif "Figure 4: Dynamic Queryable with Computation")
160165

161-
The excepted output is:
166+
The expected output is:
162167

163168
```output
164169
>> Received ('robot/battery/estimate': 'Estimated battery health: 85%')

0 commit comments

Comments
 (0)