Python SDK for ROS 2 communication via Zenoh - Use ROS 2 without ROS 2 environment
Project description
zenoh-ros2-sdk
Python SDK for ROS 2 communication via Zenoh - Use ROS 2 without ROS 2 environment
Enable ROS 2 topic publishing and subscribing in pure Python applications. Publishers and subscribers automatically appear in ros2 topic list and work seamlessly with existing ROS 2 nodes using rmw_zenoh.
Documentation
- Docs (GitHub Pages): robotis-git.github.io/zenoh_ros2_sdk
- API Reference (in this repo):
docs/api/
Features
- ✅ No ROS 2 installation required - Works with just Python and Zenoh
- ✅ Appears in
ros2 topic list- Uses liveliness tokens for ROS 2 discovery - ✅ Automatic resource management - GIDs, node IDs, entity IDs handled automatically
- ✅ Session pooling - Multiple publishers/subscribers share the same Zenoh session
- ✅ Automatic message/service loading - Automatically downloads message and service definitions from Git repositories
- ✅ Type hash computation - Computes ROS2-compatible type hashes from message/service definitions
- ✅ Type registration - Automatic message and service type registration
- ✅ Service support - Create service clients and servers with automatic type loading
- ✅ Clean API - Simple, intuitive interface
Quick Start
Install
pip install zenoh-ros2-sdk
Simple Publisher
from zenoh_ros2_sdk import ROS2Publisher
# Message type loading is automatic (no need to call load_message_type)
# Create publisher - msg_definition is optional, auto-loads from registry
pub = ROS2Publisher(
topic="/chatter",
msg_type="std_msgs/msg/String",
domain_id=30
)
# Publish messages
pub.publish(data="Hello World!")
pub.publish(data="Another message")
pub.close()
Simple Subscriber
from zenoh_ros2_sdk import ROS2Subscriber
# Message type loading is automatic (no need to call load_message_type)
def on_message(msg):
print(f"Received: {msg.data}")
# Create subscriber - msg_definition is optional, auto-loads from registry
sub = ROS2Subscriber(
topic="/chatter",
msg_type="std_msgs/msg/String",
callback=on_message,
domain_id=30
)
# Keep running
import time
time.sleep(10)
sub.close()
Simple Service Server
from zenoh_ros2_sdk import ROS2ServiceServer, get_message_class
# Service type loading is automatic (no need to call load_service_type)
def service_handler(request):
# Get response message class
Response = get_message_class("example_interfaces/srv/AddTwoInts_Response")
# Process request and return response
return Response(sum=request.a + request.b)
# Create service server
server = ROS2ServiceServer(
service_name="/add_two_ints",
srv_type="example_interfaces/srv/AddTwoInts",
callback=service_handler,
domain_id=30
)
# Keep running
import time
time.sleep(10)
server.close()
Simple Service Client
from zenoh_ros2_sdk import ROS2ServiceClient
# Service type loading is automatic (no need to call load_service_type)
# Create service client
client = ROS2ServiceClient(
service_name="/add_two_ints",
srv_type="example_interfaces/srv/AddTwoInts",
domain_id=30
)
# Make synchronous service call
response = client.call(a=5, b=3)
if response:
print(f"Sum: {response.sum}")
# Make asynchronous service call
def callback(response):
if response:
print(f"Sum: {response.sum}")
client.call_async(callback, a=10, b=20)
client.close()
Architecture
Key Components
-
ZenohSession (Singleton)
- Manages shared Zenoh session
- Handles type registration
- Generates unique GIDs
- Manages node/entity ID counters
-
ROS2Publisher
- Creates publisher with liveliness tokens
- Handles attachments (sequence, timestamp, GID)
- Appears in
ros2 topic list
-
ROS2Subscriber
- Subscribes to topics
- Deserializes CDR messages
- Calls user callback
-
ROS2ServiceClient
- Creates service client with liveliness tokens
- Sends requests using Zenoh queries
- Receives responses asynchronously
- Supports both synchronous and asynchronous calls
-
ROS2ServiceServer
- Creates service server with liveliness tokens
- Receives requests via Zenoh queryable
- Calls user callback with request
- Sends response back to client
Resource Management
- GID Generation: Uses UUID4 to generate unique 16-byte GIDs
- Node IDs: Auto-incremented per node
- Entity IDs: Auto-incremented per publisher/subscriber
- Session Reuse: All publishers/subscribers share the same Zenoh session
Examples
See the examples/ folder (and examples/README.md) for self-contained example scripts (numbered in recommended learning order):
01_publish_string.py- Basic publisher example with String messages02_subscribe_string.py- Basic subscriber example with String messages03_publish_twist.py- Publishing Twist messages (nested types)04_subscribe_twist.py- Subscribing to Twist messages (nested types)05_publish_joint_state.py- Publishing JointState messages (arrays and nested types)06_subscribe_joint_state.py- Subscribing to JointState messages (arrays and nested types)07_service_server.py- Service server example (AddTwoInts service)08_service_client.py- Service client example (synchronous and asynchronous calls)09_subscribe_compressed_image.py- Subscribe to CompressedImage messages (camera stream example; ZED topic by default)10_service_server_queue.py- Service server example (queue mode; ros-z style:take_request()/send_response())
Each example is self-contained and uses automatic message/service type loading. You can copy and modify them for your use cases.
Advanced Usage
Using Message Registry (Recommended)
The SDK automatically downloads message definitions from Git repositories. Message types are loaded automatically when creating publishers/subscribers:
from zenoh_ros2_sdk import ROS2Publisher, get_message_class
# Message type loading is automatic - no need to call load_message_type
# Get message classes for easy object creation
Vector3 = get_message_class("geometry_msgs/msg/Vector3")
Twist = get_message_class("geometry_msgs/msg/Twist")
# Create publisher - message type is automatically loaded
pub = ROS2Publisher(
topic="/cmd_vel",
msg_type="geometry_msgs/msg/Twist",
domain_id=30
)
# Create message objects
linear = Vector3(x=0.5, y=0.0, z=0.0)
angular = Vector3(x=0.0, y=0.0, z=0.2)
pub.publish(linear=linear, angular=angular)
pub.close()
Manual Message Definitions
You can still provide message definitions manually if needed:
from zenoh_ros2_sdk import ROS2Publisher
pub = ROS2Publisher(
topic="/counter",
msg_type="std_msgs/msg/Int32",
msg_definition="int32 data\n",
domain_id=30
)
pub.publish(data=42)
pub.close()
Configuration
Parameters
domain_id: ROS domain ID (default: 0)router_ip: Zenoh router IP addressrouter_port: Zenoh router portnode_name: Custom node name (auto-generated if not provided)namespace: Node namespace (default: "/")
Zenoh configuration override (advanced)
You can override the Zenoh session configuration using the ZENOH_CONFIG_OVERRIDE
environment variable (a semicolon-separated list of path=value entries). This is
useful for enabling features like shared memory transport or forcing client mode:
export ZENOH_CONFIG_OVERRIDE='transport/shared_memory/enabled=true;mode="client";connect/endpoints=["tcp/192.168.6.2:7447"]'
Notes:
- Values are parsed as JSON5. If the value is a string, it must be quoted (e.g.,
mode="client").
Requirements
- Python 3.8+
eclipse-zenohPython package (>=0.10.0)rosbagsPython package (>=0.11.0, for message serialization)GitPythonPython package (>=3.1.18, for automatic message downloading from git repositories)tqdmPython package (>=4.64.0, for download progress indicators)
Optional Dependencies
For development and testing:
# From PyPI:
pip install "zenoh-ros2-sdk[dev]"
# From source:
pip install -e ".[dev]"
Installation
From PyPI
pip install zenoh-ros2-sdk
From source
git clone https://github.com/robotis-git/zenoh_ros2_sdk.git
cd zenoh_ros2_sdk
pip install -e .
Install dependencies separately
If installing from source, you can install dependencies separately:
pip install eclipse-zenoh>=0.10.0 rosbags>=0.11.0 GitPython>=3.1.18 tqdm>=4.64.0
Running Examples
# Publish String messages
python3 examples/01_publish_string.py
# Subscribe to String messages
python3 examples/02_subscribe_string.py
# Publish Twist messages
python3 examples/03_publish_twist.py
# Subscribe to Twist messages
python3 examples/04_subscribe_twist.py
# Publish JointState messages
python3 examples/05_publish_joint_state.py
# Subscribe to JointState messages
python3 examples/06_subscribe_joint_state.py
# Run service server
python3 examples/07_service_server.py
# Run service client (in another terminal)
python3 examples/08_service_client.py
# Subscribe to CompressedImage (edit topic/router_ip in the script if needed)
python3 examples/09_subscribe_compressed_image.py
# Service server (queue mode)
python3 examples/10_service_server_queue.py
Design Decisions
- Singleton Session: All publishers/subscribers share one Zenoh session for efficiency
- Auto GID Generation: Uses UUID4 for unique GIDs per publisher
- Liveliness Tokens: Automatically declared so publishers appear in
ros2 topic list - Type Hash Computation: Automatically computes ROS2-compatible type hashes from message definitions using the same algorithm as ROS2
- Message Registry: Automatically downloads message definitions from Git repositories and caches them locally
- Clean API: Abstracts away Zenoh/rmw_zenoh complexity
Future Improvements
- Support for more message types out of the box
- Action support
- Better error handling and retry logic
- Connection pooling and reconnection
- QoS configuration options
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file zenoh_ros2_sdk-0.1.1.tar.gz.
File metadata
- Download URL: zenoh_ros2_sdk-0.1.1.tar.gz
- Upload date:
- Size: 52.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
176ae4f0996ec7f4c77d32bcf5062bd22ebcff05a4556a2a0ed5af67ccdd30c4
|
|
| MD5 |
808f0f25bd5f0d625b336ba50818cc75
|
|
| BLAKE2b-256 |
b214b5c75e871f0a2058ca6dd7315c69f6e22f3ad8999a1d4b5c9144e54ef631
|
File details
Details for the file zenoh_ros2_sdk-0.1.1-py3-none-any.whl.
File metadata
- Download URL: zenoh_ros2_sdk-0.1.1-py3-none-any.whl
- Upload date:
- Size: 50.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1d33474c5e97bf16b5012bf681a12464abea7356ce5cc77f376eadb3bb142939
|
|
| MD5 |
4fa098d266915e89c65386b6bf8ec6e0
|
|
| BLAKE2b-256 |
bff05074c319dccd62aa8d9b25d2f43369da8162422eb76352e43bedabea1418
|