{"id":20099072,"url":"https://github.com/ros2/rmw_zenoh","last_synced_at":"2025-05-16T05:04:13.135Z","repository":{"id":46818507,"uuid":"277053108","full_name":"ros2/rmw_zenoh","owner":"ros2","description":"RMW for ROS 2 using Zenoh as the middleware","archived":false,"fork":false,"pushed_at":"2025-05-15T13:16:53.000Z","size":1287,"stargazers_count":295,"open_issues_count":33,"forks_count":59,"subscribers_count":39,"default_branch":"rolling","last_synced_at":"2025-05-16T05:03:52.064Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ros2.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2020-07-04T06:30:22.000Z","updated_at":"2025-05-12T19:52:48.000Z","dependencies_parsed_at":"2024-02-19T06:24:06.560Z","dependency_job_id":"320e2ee3-34c9-4cf4-970b-fd3f134f34d5","html_url":"https://github.com/ros2/rmw_zenoh","commit_stats":{"total_commits":259,"total_committers":25,"mean_commits":10.36,"dds":0.7606177606177607,"last_synced_commit":"8306a63313cd9e21883344deff9abc782636a464"},"previous_names":["ros2/rmw_zenoh","atolab/rmw_zenoh"],"tags_count":14,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ros2%2Frmw_zenoh","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ros2%2Frmw_zenoh/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ros2%2Frmw_zenoh/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ros2%2Frmw_zenoh/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ros2","download_url":"https://codeload.github.com/ros2/rmw_zenoh/tar.gz/refs/heads/rolling","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254471061,"owners_count":22076585,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-13T17:08:00.313Z","updated_at":"2025-05-16T05:04:13.124Z","avatar_url":"https://github.com/ros2.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# rmw_zenoh\n\n[![build](https://github.com/ros2/rmw_zenoh/actions/workflows/build.yaml/badge.svg)](https://github.com/ros2/rmw_zenoh/actions/workflows/build.yaml)\n[![style](https://github.com/ros2/rmw_zenoh/actions/workflows/style.yaml/badge.svg)](https://github.com/ros2/rmw_zenoh/actions/workflows/style.yaml)\n\nA ROS 2 RMW implementation based on Zenoh that is written using the zenoh-cpp bindings.\n\n## Design\n\nFor information about the Design please visit [design](docs/design.md) page.\n\n## Requirements\n- [ROS 2](https://docs.ros.org)\n\n\u003e [!NOTE]\n\u003e See available distro branches, eg. `jazzy`, for supported ROS 2 distributions.\n\n## Installation\n`rmw_zenoh` can either be installed via binaries (recommended for stable development) or built from source (recommended if latest features are needed). See instructions below.\n\n### Binary Installation\nBinary packages for supported ROS 2 distributions (see distro branches) are available on respective [Tier-1](https://www.ros.org/reps/rep-2000.html#support-tiers) platforms for the distributions.\nFirst ensure that your system is set up to install ROS 2 binaries by following the instructions [here](https://docs.ros.org/en/rolling/Installation/Ubuntu-Install-Debs.html).\n\nThen install `rmw_zenoh` binaries using the command\n\n```bash\nsudo apt update \u0026\u0026 sudo apt install ros-\u003cDISTRO\u003e-rmw-zenoh-cpp # replace \u003cDISTRO\u003e with the codename for the distribution, eg., rolling\n```\n\n### Source Installation\n\n\u003e [!NOTE]\n\u003e By default, we vendor and compile `zenoh-cpp` with a subset of `zenoh` features.\nThe `ZENOHC_CARGO_FLAGS` CMake argument may be overwritten with other features included if required.\nSee [zenoh_cpp_vendor/CMakeLists.txt](./zenoh_cpp_vendor/CMakeLists.txt) for more details.\n\n```bash\n# replace \u003cDISTRO\u003e with ROS 2 distro of choice\nmkdir ~/ws_rmw_zenoh/src -p \u0026\u0026 cd ~/ws_rmw_zenoh/src\ngit clone https://github.com/ros2/rmw_zenoh.git -b \u003cDISTRO\u003e\ncd ~/ws_rmw_zenoh\nrosdep install --from-paths src --ignore-src --rosdistro \u003cDISTRO\u003e -y\nsource /opt/ros/\u003cDISTRO\u003e/setup.bash\ncolcon build --cmake-args -DCMAKE_BUILD_TYPE=Release\n```\n\nMake sure to source the built workspace using the commands below prior to running any other commands.\n```bash\ncd ~/ws_rmw_zenoh\nsource install/setup.bash\n```\n\n## Test\n\n### Terminate ROS 2 daemon started with another RMW\n```bash\npkill -9 -f ros \u0026\u0026 ros2 daemon stop\n```\nWithout this step, ROS 2 CLI commands (e.g. `ros2 node list`) may\nnot work properly since they would query ROS graph information from the ROS 2 daemon that\nmay have been started with different a RMW.\n\n### Start the Zenoh router\n\u003e [!NOTE]\n\u003e Manually launching Zenoh router won't be necessary in the future.\n```bash\n# terminal 1\nros2 run rmw_zenoh_cpp rmw_zenohd\n```\n\n\u003e [!NOTE]\n\u003e Without the Zenoh router, nodes will not be able to discover each other since multicast discovery is disabled by default in the node's session config. Instead, nodes will receive discovery information about other peers via the Zenoh router's gossip functionality. See more information on the session configs [below](#configuration).\n\n### Run the `talker`\n```bash\n# terminal 2\nexport RMW_IMPLEMENTATION=rmw_zenoh_cpp\nros2 run demo_nodes_cpp talker\n```\n\n### Run the `listener`\n```bash\n# terminal 2\nexport RMW_IMPLEMENTATION=rmw_zenoh_cpp\nros2 run demo_nodes_cpp listener\n```\n\nThe listener node should start receiving messages over the `/chatter` topic.\n\n## Configuration\n\nBy default, `Zenoh sessions` created by `rmw_zenoh` will attempt to connect to a Zenoh router to receive discovery information.\nTo understand more about `Zenoh routers` and `Zenoh sessions`, see [Zenoh documentation](https://zenoh.io/docs/getting-started/deployment/).\n\n### Checking for a Zenoh router.\nThe `ZENOH_ROUTER_CHECK_ATTEMPTS` environment variable can be used to configure if and how a `Zenoh session` checks for the presence of a `Zenoh router`.\nThe behavior is explained in the table below.\n\n\n| ZENOH_ROUTER_CHECK_ATTEMPTS |                                                 Session behavior                                                   |\n|:---------------------------:|:------------------------------------------------------------------------------------------------------------------:|\n|               0             |                                                             Indefinitely waits for connection to a Zenoh router.   |\n|             \u003c 0             |                                                                                        Skips Zenoh router check.   |\n|             \u003e 0             | Attempts to connect to a Zenoh router in `ZENOH_ROUTER_CHECK_ATTEMPTS` attempts with 1 second wait between checks. |\n|            unset            |                                                                    Equivalent to `1`: the check is made only once. |\n\nIf after the configured number of attempts the Node is still not connected to a `Zenoh router`, the initialisation goes on anyway.\nIf a `Zenoh router` is started after initialization phase, the Node will automatically connect to it, and autoconnect to other Nodes if gossip scouting is enabled (true with default configuratiuon).\n\n### Session and Router configs\n`rmw_zenoh` relies on separate configurations files to configure the `Zenoh router` and `Zenoh session` respectively.\nFor more information on the topology of Zenoh adopted in `rmw_zenoh`, please see [Design](#design).\nDefault configuration files are used by `rmw_zenoh` however certain environment variables may be set to provide absolute paths to custom configuration files.\nThe table below summarizes the default files and the environment variables for the `Zenoh router` and `Zenoh session`.\nFor a complete list of configurable parameters, see [zenoh/DEFAULT_CONFIG.json5](https://github.com/eclipse-zenoh/zenoh/blob/main/DEFAULT_CONFIG.json5).\n\n|         |                                            Default config                                            |   Envar for custom config  |\n|---------|:----------------------------------------------------------------------------------------------------:|:--------------------------:|\n| Router  |  [DEFAULT_RMW_ZENOH_ROUTER_CONFIG.json5](rmw_zenoh_cpp/config/DEFAULT_RMW_ZENOH_ROUTER_CONFIG.json5)  |  `ZENOH_ROUTER_CONFIG_URI` |\n| Session | [DEFAULT_RMW_ZENOH_SESSION_CONFIG.json5](rmw_zenoh_cpp/config/DEFAULT_RMW_ZENOH_SESSION_CONFIG.json5) | `ZENOH_SESSION_CONFIG_URI` |\n\nFor example, to set the path to a custom `Zenoh router` configuration file,\n```bash\nexport ZENOH_ROUTER_CONFIG_URI=$HOME/MY_ZENOH_ROUTER_CONFIG.json5\n```\n\n`rmw_zenoh` allows you to override configuration fields using the `ZENOH_CONFIG_OVERRIDE` environment variable .\nThese overrides apply to `Zenoh sessions` and the `Zenoh router` **after** the `ZENOH_SESSION_CONFIG_URI` or `ZENOH_ROUTER_CONFIG_URI` (if specified)\nhas been processed.\n\nYou can specify multiple key-value pairs using the following syntax:\n```bash\nexport ZENOH_CONFIG_OVERRIDE=\"key/path/to/field1=value1;key/path/to/field2=value2\"\n```\n\n#### Examples\n\n- Make a `Zenoh router` to connect to one or more remote `Zenoh routers`:\n\n  ```bash\n  export ZENOH_CONFIG_OVERRIDE='connect/endpoints=[\"tcp/192.168.0.3:7447\", \"tcp/192.168.0.4:7447\"]'\n  ros2 run rmw_zenoh_cpp rmw_zenohd\n  ```\n\n- Enable multicast scouting (disabled by default) to allow ROS 2 nodes running on a same host to discover each other without requiring a Zenoh router:\n\n  ```bash\n  # terminal 1\n  export ZENOH_ROUTER_CHECK_ATTEMPTS=-1\n  export ZENOH_CONFIG_OVERRIDE='scouting/multicast/enabled=true'\n  ros2 run demo_nodes_cpp talker\n\n  # terminal 2\n  export ZENOH_ROUTER_CHECK_ATTEMPTS=-1\n  export ZENOH_CONFIG_OVERRIDE='scouting/multicast/enabled=true'\n  ros2 run demo_nodes_cpp listener\n  ```\n\n- Enable multicast scouting to allow ROS 2 nodes running on distinct hosts to discover each other\n  (the nodes have to listen on all available interfaces, not only `localhost` which is the default configuration):\n\n  ```bash\n  # host 1\n  export ZENOH_ROUTER_CHECK_ATTEMPTS=-1\n  export ZENOH_CONFIG_OVERRIDE='listen/endpoints=[\"tcp/0.0.0.0:0\"];scouting/multicast/enabled=true'\n  ros2 run demo_nodes_cpp talker\n\n  # host 2\n  export ZENOH_ROUTER_CHECK_ATTEMPTS=-1\n  export ZENOH_CONFIG_OVERRIDE='listen/endpoints=[\"tcp/0.0.0.0:0\"];scouting/multicast/enabled=true'\n  ros2 run demo_nodes_cpp listener\n  ```\n\n### Connecting multiple hosts\nBy default, all discovery \u0026 communication is restricted within a host, where a host is a machine running a `Zenoh router` along with various ROS 2 nodes with their default [configurations](rmw_zenoh_cpp/config/).\nTo bridge communications across two or more hosts, the `Zenoh router` configuration for one of the hosts must be updated to connect to the other host's `Zenoh router` at startup.\n\nFirst, make a copy of the [DEFAULT_RMW_ZENOH_ROUTER_CONFIG.json5](rmw_zenoh_cpp/config/DEFAULT_RMW_ZENOH_ROUTER_CONFIG.json5) and modify the `connect` block to include the endpoint(s) that the other host's `Zenoh router(s)` is listening on.\nFor example, if another `Zenoh router` is listening on IP address `192.168.1.1` and port `7447` on its host, modify the config file to connect to this router as shown below:\n\n```json5\n/// ... preceding parts of the config file.\n{\n  connect: {\n    endpoints: [\"tcp/192.168.1.1:7447\"],\n  },\n}\n/// ... following parts of the config file.\n```\n\nThen, start the `Zenoh router` after setting the `ZENOH_ROUTER_CONFIG_URI` environment variable to the absolute path of the modified config file.\n\n### Connecting to the Zenoh router on another host\n\nIn some scenarios, we want to connect to the Zenoh router on another host directly for better performance.\nFor example, it's more efficient to connect to the Zenohd of a robot while running RViz remotely.\nBy default, Zenoh router doesn't forward messages between peers, because this is unnecessary in the same host.\nTherefore, we need to switch the remote node into the client mode to make Zenoh router forward messages.\n\nAssume that the Zenoh router is listening to `tcp/192.168.1.1:7447`.\nHere are two ways to configure on the remote side:\n\n1. Copy the [DEFAULT_RMW_ZENOH_SESSION_CONFIG.json5](rmw_zenoh_cpp/config/DEFAULT_RMW_ZENOH_SESSION_CONFIG.json5) and set the `ZENOH_SESSION_CONFIG_URI` to the path of that config file.\n\n    ```json5\n    /// ... preceding parts of the config file.\n    {\n      mode: \"client\",\n      connect: {\n        endpoints: [\"tcp/192.168.1.1:7447\"],\n      },\n    }\n    /// ... following parts of the config file.\n    ```\n\n2. A simpler way is to override the config by `ZENOH_CONFIG_OVERRIDE`\n\n    ```bash\n    export ZENOH_CONFIG_OVERRIDE='mode=\"client\";connect/endpoints=[\"tcp/192.168.1.1:7447\"]' \n    ```\n\n### Security\n\nSecurity is available in `rmw_zenoh` by means of access control, authentication and encryption.\nThe [zenoh_security_tools](./zenoh_security_tools/) package contains a script to generate Zenoh configs with security configured along with documentation on its usage.\n\n### Logging\n\nThe core of Zenoh is implemented in Rust and uses a logging library that can be configured via a `RUST_LOG` environment variable.\nThis variable can be configured independently for each Node and the Zenoh router.\nFor instance:\n- `RUST_LOG=zenoh=info` activates information logs about Zenoh initialization and the endpoints it's listening on.\n- `RUST_LOG=zenoh=info,zenoh_transport=debug` adds some debug logs about the connectivity events in Zenoh.\n- `RUST_LOG=zenoh=info,zenoh::net::routing::queries=trace` adds some trace logs for each query (i.e. calls to services and actions).\n- `RUST_LOG=zenoh=debug` activates all the debug logs.\n\nFor more information on the `RUST_LOG` syntax, see https://docs.rs/env_logger/latest/env_logger/#enabling-logging.\n\n### Known Issues\n\n### Router crashes on IPv4-only systems\n\nThe default configuration shipped with `rmw_zenoh` makes the Zenoh router attempt to listen on IPv6 `ANY` only ([here](https://github.com/ros2/rmw_zenoh/blob/12f83445e00a7c25805b27f391e92a455f2d0774/rmw_zenoh_cpp/config/DEFAULT_RMW_ZENOH_ROUTER_CONFIG.json5#L82-L84)).\nOn any system without IPv6 support (either because it has been disabled or because it is non-functioning) this will cause the router to crash with an error similar to the following:\n\n\u003cdetails\u003e\u003csummary\u003eClick to expand\u003c/summary\u003e\n\n```\nWARN ThreadId(03) zenoh::net::runtime::orchestrator: Unable to open listener tcp/[::]:7447: Can not create a new TCP listener bound to tcp/[::]:7447: [Os { code: 97, kind: Uncategorized, message: \"Address family not supported by protocol\" }] at /home/buildfarm/.cargo/git/checkouts/zenoh-cc237f2570fab813/9640d22/io/zenoh-links/zenoh-link-tcp/src/unicast.rs:326.\nERROR ThreadId(03) zenohc::session: Error opening session: Can not create a new TCP listener bound to tcp/[::]:7447: [Os { code: 97, kind: Uncategorized, message: \"Address family not supported by protocol\" }] at /home/buildfarm/.cargo/git/checkouts/zenoh-cc237f2570fab813/9640d22/io/zenoh-links/zenoh-link-tcp/src/unicast.rs:326.\nError opening Session!\\n[ros2run]: Process exited with failure 1\n```\n\n\u003c/details\u003e\n\nTo resolve this, either run the router on a system with IPv6 support, or update the `listen.endpoints` list in the Zenoh configuration and replace `\"tcp/[::]:7447\"` with `\"tcp/0.0.0.0:7447\"` (ie: make the router listen on IPv4 `ANY`).\nNote: the existing entry must be *replaced*, it's not sufficient to just *add* the IPv4 entry (as that would make the router attempt to listen on both IPv4 and IPv6 `ANY` and still not work).\n\n### Crash when program terminates\n\nWhen a program terminates, global and static objects are destructed in the reverse order of their\nconstruction.\nThe `Thread Local Storage` is one such entity which the `tokio` runtime in Zenoh uses.\nIf the Zenoh session is closed after this entity is cleared, it causes a panic like seen below.\n\n```\nthread '\u003cunnamed\u003e' panicked at /rustc/aedd173a2c086e558c2b66d3743b344f977621a7/library/std/src/thread/local.rs:262:26:\ncannot access a Thread Local Storage value during or after destruction: AccessError\n```\n\nThis can happen with `rmw_zenoh` if the ROS 2 `Context` is not shutdown explicitly before the\nprogram terminates.\nIn this scenario, the `Context` will be shutdown inside the `Context`'s destructor which then closes the Zenoh session.\nSince the ordering of global/static objects is not defined, this often leads to the above panic.\n\nThe recommendation is to ensure the `Context` is shutdown before a program terminates.\nOne way to ensure this is to call `rclcpp::shutdown()` when the program exits.\nNote that composable nodes should *never* call `rclcpp::shutdown()`, as the composable node container will automatically do this.\n\nFor more details, see https://github.com/ros2/rmw_zenoh/issues/170.\n\n### rmw_zenoh is incompatible between Humble and newer distributions.\n\nSince Iron, ROS 2 introduced type hashes for messages and `rmw_zenoh` includes these type hashes in the Zenoh keyexpressions it constructs for data exchange. While participants will be discoverable, communication between Humble and newer distributions will fail, resulting in messages being silently dropped.\n\nFor more details, see https://github.com/ros2/rmw_zenoh/issues/569.\n\n## Quality Declaration files\n\nQuality Declarations for each package in this repository:\n\n* [`rmw_zenoh_cpp`](rmw_zenoh_cpp/QUALITY_DECLARATION.md)\n* [`zenoh_cpp_vendor`](zenoh_cpp_vendor/QUALITY_DECLARATION.md)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fros2%2Frmw_zenoh","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fros2%2Frmw_zenoh","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fros2%2Frmw_zenoh/lists"}