From 308a4d882e416e092471f6455a1151c3c45b6fed Mon Sep 17 00:00:00 2001 From: Luca Della Vedova Date: Thu, 21 Nov 2024 10:49:32 +0800 Subject: [PATCH 1/4] Migrate to ros2dds bridge Signed-off-by: Luca Della Vedova --- .../config/zenoh/nexus_network_config.yaml | 60 ++++++++++++--- .../launch/zenoh_bridge.launch.py | 2 +- .../nexus_network_configuration.py | 26 +++---- .../schemas/nexus_network_schema.json | 73 ++++++++++++++----- nexus_zenoh_bridge_dds_vendor/CMakeLists.txt | 4 +- 5 files changed, 114 insertions(+), 51 deletions(-) diff --git a/nexus_integration_tests/config/zenoh/nexus_network_config.yaml b/nexus_integration_tests/config/zenoh/nexus_network_config.yaml index d16ae54..2dc2d46 100644 --- a/nexus_integration_tests/config/zenoh/nexus_network_config.yaml +++ b/nexus_integration_tests/config/zenoh/nexus_network_config.yaml @@ -2,32 +2,68 @@ # Use 'client' when there is an available Zenoh router, otherwise # use 'peer' for a distributed system. mode: peer -# When true, discovery info is forwarded to the remote plugins/bridges -forward_discovery: false # When true, activates a REST API used to administer Zenoh Bridge configurations enable_rest_api: true -# Additional endpoints to allow, these could be endpoints not defined in REDF but are necessary for lifecycle transitions -add_allowed_endpoints: ["/list_workcells", "/.*/workcell_state", "/.*/is_task_doable", "/.*/request", "/.*/queue_task", "/.*/remove_pending_task", "/register_workcell", "/register_transporter", ".*/available", ".*/transport", "/estop", "/.*/pause", "/.*/get_state", "/.*/change_state", "/.*/signal"] system_orchestrators: - - ros_namespace: system_orchestrator # ROS Namespace of the endpoints + - namespace: system_orchestrator # ROS Namespace of the endpoints # ROS Domain ID - domain_id: 14 + domain_id: 0 # Listening TCP Address of Zenoh bridge tcp_listen: ["0.0.0.0:7447"] # HTTP Port for the REST API rest_api_http_port: 8000 + allow: + publishers: [] + # TODO(luca) check if we need estop + subscribers: ["/estop", "/.*/workcell_state"] + service_servers: ["/list_workcells", "/register_workcell", "/register_transporter"] + # TODO(luca) check if transporter needs available endpoint + service_clients: ["/.*/queue_task", "/.*/remove_pending_task", "/.*/pause", "/.*/signal", "/.*/get_state", "/.*/change_state", "/.*/is_task_doable"] + action_servers: [] + # TODO(luca) check if we really need transporter client + action_clients: ["/.*/request", "/.*/transport"] + queries_timeout: + default: 600.0 + workcell_orchestrators: - - ros_namespace: workcell_1 - domain_id: 15 + - namespace: workcell_1 + domain_id: 1 tcp_connect: ["0.0.0.0:7447"] rest_api_http_port: 8001 - - ros_namespace: workcell_2 - domain_id: 16 + allow: + publishers: ["/workcell_1/workcell_state"] + subscribers: [] + service_servers: ["/workcell_1/is_task_doable", "/workcell_1/queue_task", "/workcell_1/remove_pending_task", "/workcell_1/get_state", "/workcell_1/change_state", "/workcell_1/signal", "/workcell_1/pause"] + service_clients: ["/register_workcell"] + action_servers: ["/workcell_1/request"] + action_clients: [] + queries_timeout: + default: 600.0 + - namespace: workcell_2 + domain_id: 2 tcp_connect: ["0.0.0.0:7447"] rest_api_http_port: 8002 - - ros_namespace: workcell_3 - domain_id: 17 + allow: + publishers: ["/workcell_2/workcell_state"] + subscribers: [] + service_servers: ["/workcell_2/is_task_doable", "/workcell_2/queue_task", "/workcell_2/remove_pending_task", "/workcell_2/get_state", "/workcell_2/change_state", "/workcell_2/signal", "/workcell_2/pause"] + service_clients: ["/register_workcell"] + action_servers: ["/workcell_2/request"] + action_clients: [] + queries_timeout: + default: 600.0 + - namespace: workcell_3 + domain_id: 3 tcp_connect: ["0.0.0.0:7447"] rest_api_http_port: 8003 + allow: + publishers: ["workcell_3/workcell_state"] + subscribers: [] + service_servers: ["workcell_3/is_task_doable", "workcell_3/queue_task", "workcell_3/remove_pending_task", "workcell_3/get_state", "workcell_3/change_state"] + service_clients: ["/register_workcell"] + action_servers: ["workcell_3/request"] + action_clients: [] + queries_timeout: + default: 600.0 diff --git a/nexus_integration_tests/launch/zenoh_bridge.launch.py b/nexus_integration_tests/launch/zenoh_bridge.launch.py index b6adb2c..acd5009 100644 --- a/nexus_integration_tests/launch/zenoh_bridge.launch.py +++ b/nexus_integration_tests/launch/zenoh_bridge.launch.py @@ -40,7 +40,7 @@ def launch_setup(context, *args, **kwargs): cmd = [ ExecutableInPackage( - executable="zenoh_bridge_dds", + executable="zenoh_bridge_ros2dds", package="nexus_zenoh_bridge_dds_vendor", ), "--config", diff --git a/nexus_network_configuration/nexus_network_configuration/nexus_network_configuration.py b/nexus_network_configuration/nexus_network_configuration/nexus_network_configuration.py index d97de9e..7eb1064 100644 --- a/nexus_network_configuration/nexus_network_configuration/nexus_network_configuration.py +++ b/nexus_network_configuration/nexus_network_configuration/nexus_network_configuration.py @@ -48,10 +48,7 @@ def __init__( # Set global variables self.enable_rest_api = self.nexus_net_cfg["enable_rest_api"] - self.add_allowed_endpoints = self.nexus_net_cfg[ - "add_allowed_endpoints"] self.bridge_mode = self.nexus_net_cfg["mode"] - self.forward_discovery = self.nexus_net_cfg["forward_discovery"] self.zenoh_cfg_file_extension = "json5" @@ -146,11 +143,11 @@ def zenoh_cfg( zenoh_dict = { "plugins": { - "dds": { + "ros2dds": { "domain": orchestrator["domain_id"], - "group_member_id": orchestrator["ros_namespace"], - "forward_discovery": self.forward_discovery, - "allow": allowed_endpoints, + "namespace": orchestrator["namespace"], + "allow": orchestrator["allow"], + "queries_timeout": orchestrator["queries_timeout"], }, }, "mode": self.bridge_mode, @@ -180,7 +177,7 @@ def generate_zenoh_config(self, output_dir): orchestrators_zenoh_cfg = [] allowed_endpoints = self.generate_allowed_endpoints( - self.redf_cfg, self.add_allowed_endpoints) + self.redf_cfg) # Generate system orchestrator zenoh dictionary for orchestrator in nexus_net_cfg["system_orchestrators"]: @@ -212,18 +209,17 @@ def generate_zenoh_config(self, output_dir): for zenoh_cfg in orchestrators_zenoh_cfg: write_filepath = os.path.join( output_dir, - zenoh_cfg["plugins"]["dds"]["group_member_id"] + zenoh_cfg["plugins"]["ros2dds"]["namespace"] + "." + self.zenoh_cfg_file_extension, ) - # This has been removed in Zenoh 1.0.0 - del zenoh_cfg["plugins"]["dds"]["group_member_id"] + del zenoh_cfg["plugins"]["ros2dds"]["namespace"] self.write_to_json(write_filepath, zenoh_cfg) print(f"Generated Zenoh configuration at {write_filepath}") def generate_allowed_endpoints(self, - redf_cfg, - add_allowed_endpoints): + redf_cfg + ): """ Generate allowed endpoints string from REDF configuration. @@ -234,8 +230,6 @@ def generate_allowed_endpoints(self, ---------- redf_cfg : dict REDF Configuration dictionary - add_allowed_endpoints : array - Additional endpoints allowed Returns ------- @@ -253,8 +247,6 @@ def generate_allowed_endpoints(self, elif endpoint.get("service_name"): allowed_endpoints.append(endpoint["service_name"]) - allowed_endpoints.extend(add_allowed_endpoints) - allowed_endpoints_str = "" for endpoint_str in allowed_endpoints: # Searches for namespace defined in curly braces in REDF endpoints. diff --git a/nexus_network_configuration/schemas/nexus_network_schema.json b/nexus_network_configuration/schemas/nexus_network_schema.json index 9e208b2..c6cfc8d 100644 --- a/nexus_network_configuration/schemas/nexus_network_schema.json +++ b/nexus_network_configuration/schemas/nexus_network_schema.json @@ -6,9 +6,7 @@ "type": "object", "required": [ "mode", - "forward_discovery", "enable_rest_api", - "add_allowed_endpoints", "system_orchestrators", "workcell_orchestrators" ], @@ -18,18 +16,10 @@ "type": "string", "enum": ["peer", "client"] }, - "forward_discovery": { - "description": "When true, discovery info is forwarded to the remote plugins/bridges", - "type": "boolean" - }, "enable_rest_api":{ "description": "When true, activates a REST API used to administer Zenoh Bridge configurations", "type": "boolean" }, - "add_allowed_endpoints":{ - "description": "Additional endpoints to allow, these could be endpoints not defined in REDF but are necessary for lifecycle transitions", - "type": "array" - }, "system_orchestrators": { "type": "array", "items": { "$ref": "#/$defs/system_orchestrator_unit"} @@ -41,12 +31,45 @@ }, "$defs": { + "queries_timeout": { + "description": "Timeout parameters for Zenoh queries", + "type": "object", + "properties": { + "default": { + "type": "number" + } + } + }, + "allow": { + "description": "Additional endpoints to allow, these could be endpoints not defined in REDF but are necessary for lifecycle transitions", + "type": "object", + "properties": { + "subscribers": { + "type": "array" + }, + "publishers": { + "type": "array" + }, + "service_servers": { + "type": "array" + }, + "service_clients": { + "type": "array" + }, + "action_servers": { + "type": "array" + }, + "action_clients": { + "type": "array" + } + } + }, "system_orchestrator_unit": { "type": "object", - "required": ["ros_namespace", "domain_id", "tcp_listen"], + "required": ["namespace", "domain_id", "tcp_listen"], "properties": { - "ros_namespace":{ - "$ref": "#/$defs/ros_namespace" + "namespace":{ + "$ref": "#/$defs/namespace" }, "domain_id":{ "$ref": "#/$defs/domain_id" @@ -56,15 +79,21 @@ }, "rest_api_http_port":{ "$ref": "#/$defs/rest_api_http_port" + }, + "allow":{ + "$ref": "#/$defs/allow" + }, + "queries_timeout":{ + "$ref": "#/$defs/queries_timeout" } } }, "workcell_orchestrator_unit": { "type": "object", - "required": ["ros_namespace", "domain_id", "tcp_connect"], + "required": ["namespace", "domain_id", "tcp_connect"], "properties": { - "ros_namespace":{ - "$ref": "#/$defs/ros_namespace" + "namespace":{ + "$ref": "#/$defs/namespace" }, "domain_id":{ "$ref": "#/$defs/domain_id" @@ -74,10 +103,16 @@ }, "rest_api_http_port":{ "$ref": "#/$defs/rest_api_http_port" + }, + "allow":{ + "$ref": "#/$defs/allow" + }, + "queries_timeout":{ + "$ref": "#/$defs/queries_timeout" } } }, - "ros_namespace":{ + "namespace":{ "description": "ROS Namespace of the endpoints", "type": "string" }, @@ -85,7 +120,7 @@ "description": "ROS Domain ID", "type": "integer", "minimum": 0, - "maxmimum": 232 + "maximum": 232 }, "tcp_connect":{ "description": "TCP Address of system orchestrator Zenoh bridge", @@ -99,7 +134,7 @@ "description": "HTTP Port for the REST API", "type": "integer", "minimum": 0, - "maxmimum": 65535 + "maximum": 65535 } } } diff --git a/nexus_zenoh_bridge_dds_vendor/CMakeLists.txt b/nexus_zenoh_bridge_dds_vendor/CMakeLists.txt index ea92efd..163404f 100644 --- a/nexus_zenoh_bridge_dds_vendor/CMakeLists.txt +++ b/nexus_zenoh_bridge_dds_vendor/CMakeLists.txt @@ -11,14 +11,14 @@ find_package(ament_cmake REQUIRED) find_package(ament_cmake_vendor_package REQUIRED) ament_vendor(zeno_bridge_dds_vendor - VCS_URL https://github.com/eclipse-zenoh/zenoh-plugin-dds.git + VCS_URL https://github.com/eclipse-zenoh/zenoh-plugin-ros2dds.git VCS_VERSION 1.0.2 ) # TODO(sloretz) make a nice way to get this path from ament_vendor set(INSTALL_DIR "${CMAKE_CURRENT_BINARY_DIR}/zeno_bridge_dds_vendor-prefix/install") install( - DIRECTORY "${INSTALL_DIR}/lib/zenoh_bridge_dds/" + DIRECTORY "${INSTALL_DIR}/lib/zenoh_bridge_ros2dds/" DESTINATION "lib/${PROJECT_NAME}" USE_SOURCE_PERMISSIONS ) From 0cbb8ece2be8a21825e593163c4e26242a10156d Mon Sep 17 00:00:00 2001 From: Luca Della Vedova Date: Wed, 11 Dec 2024 16:08:49 +0800 Subject: [PATCH 2/4] Bump ros2dds bridge version to fix warning spam Signed-off-by: Luca Della Vedova --- nexus_zenoh_bridge_dds_vendor/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nexus_zenoh_bridge_dds_vendor/CMakeLists.txt b/nexus_zenoh_bridge_dds_vendor/CMakeLists.txt index 163404f..eeba689 100644 --- a/nexus_zenoh_bridge_dds_vendor/CMakeLists.txt +++ b/nexus_zenoh_bridge_dds_vendor/CMakeLists.txt @@ -12,7 +12,7 @@ find_package(ament_cmake_vendor_package REQUIRED) ament_vendor(zeno_bridge_dds_vendor VCS_URL https://github.com/eclipse-zenoh/zenoh-plugin-ros2dds.git - VCS_VERSION 1.0.2 + VCS_VERSION 1.0.4 ) # TODO(sloretz) make a nice way to get this path from ament_vendor From d813ae98af56b35a7fa66ed544d546425a12945b Mon Sep 17 00:00:00 2001 From: Luca Della Vedova Date: Thu, 26 Dec 2024 15:48:04 +0800 Subject: [PATCH 3/4] Revert patch bump Signed-off-by: Luca Della Vedova --- nexus_zenoh_bridge_dds_vendor/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nexus_zenoh_bridge_dds_vendor/CMakeLists.txt b/nexus_zenoh_bridge_dds_vendor/CMakeLists.txt index eeba689..163404f 100644 --- a/nexus_zenoh_bridge_dds_vendor/CMakeLists.txt +++ b/nexus_zenoh_bridge_dds_vendor/CMakeLists.txt @@ -12,7 +12,7 @@ find_package(ament_cmake_vendor_package REQUIRED) ament_vendor(zeno_bridge_dds_vendor VCS_URL https://github.com/eclipse-zenoh/zenoh-plugin-ros2dds.git - VCS_VERSION 1.0.4 + VCS_VERSION 1.0.2 ) # TODO(sloretz) make a nice way to get this path from ament_vendor From 9af090301487a0b78f7b22bb9e5a3d0b1d5bd9e0 Mon Sep 17 00:00:00 2001 From: Luca Della Vedova Date: Thu, 26 Dec 2024 15:55:53 +0800 Subject: [PATCH 4/4] Bump to last known good patch version Signed-off-by: Luca Della Vedova --- nexus_zenoh_bridge_dds_vendor/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nexus_zenoh_bridge_dds_vendor/CMakeLists.txt b/nexus_zenoh_bridge_dds_vendor/CMakeLists.txt index 163404f..13e508c 100644 --- a/nexus_zenoh_bridge_dds_vendor/CMakeLists.txt +++ b/nexus_zenoh_bridge_dds_vendor/CMakeLists.txt @@ -12,7 +12,7 @@ find_package(ament_cmake_vendor_package REQUIRED) ament_vendor(zeno_bridge_dds_vendor VCS_URL https://github.com/eclipse-zenoh/zenoh-plugin-ros2dds.git - VCS_VERSION 1.0.2 + VCS_VERSION 1.0.3 ) # TODO(sloretz) make a nice way to get this path from ament_vendor