From ed2858a6109723a0191962cd4827c129b55ff934 Mon Sep 17 00:00:00 2001 From: wznln <18435084+Xuwznln@users.noreply.github.com> Date: Tue, 6 May 2025 21:57:34 +0800 Subject: [PATCH] feat: add outer resource --- test/commands/resource_add.md | 5 +++ test/experiments/plr_test.json | 42 +------------------- unilabos/ros/nodes/base_device_node.py | 52 +++++++++++++------------ unilabos/ros/nodes/presets/host_node.py | 3 +- 4 files changed, 35 insertions(+), 67 deletions(-) create mode 100644 test/commands/resource_add.md diff --git a/test/commands/resource_add.md b/test/commands/resource_add.md new file mode 100644 index 00000000..9d5fe38f --- /dev/null +++ b/test/commands/resource_add.md @@ -0,0 +1,5 @@ +使用plr_test.json启动,将Well加入Plate中 + +```bash +ros2 action send_goal /devices/host_node/add_resource_from_outer unilabos_msgs/action/_resource_create_from_outer/ResourceCreateFromOuter "{ resources: [ { 'category': '', 'children': [], 'config': { 'type': 'Well', 'size_x': 6.86, 'size_y': 6.86, 'size_z': 10.67, 'rotation': { 'x': 0, 'y': 0, 'z': 0, 'type': 'Rotation' }, 'category': 'well', 'model': null, 'max_volume': 360, 'material_z_thickness': 0.5, 'compute_volume_from_height': null, 'compute_height_from_volume': null, 'bottom_type': 'flat', 'cross_section_type': 'circle' }, 'data': { 'liquids': [], 'pending_liquids': [], 'liquid_history': [] }, 'id': 'plate_well_11_7', 'name': 'plate_well_11_7', 'pose': { 'orientation': { 'w': 1.0, 'x': 0.0, 'y': 0.0, 'z': 0.0 }, 'position': { 'x': 0.0, 'y': 0.0, 'z': 0.0 } }, 'sample_id': '', 'parent': 'plate', 'type': 'device' } ], device_ids: [ 'PLR_STATION' ], bind_parent_ids: [ 'plate' ], bind_locations: [ { 'x': 0.0, 'y': 0.0, 'z': 0.0 } ], other_calling_params: [ '{}' ] }" +``` \ No newline at end of file diff --git a/test/experiments/plr_test.json b/test/experiments/plr_test.json index c60f1b54..7fe1e3e3 100644 --- a/test/experiments/plr_test.json +++ b/test/experiments/plr_test.json @@ -6679,8 +6679,7 @@ "plate_well_11_3", "plate_well_11_4", "plate_well_11_5", - "plate_well_11_6", - "plate_well_11_7" + "plate_well_11_6" ], "parent": "deck", "type": "device", @@ -10508,45 +10507,6 @@ "pending_liquids": [], "liquid_history": [] } - }, - { - "id": "plate_well_11_7", - "name": "plate_well_11_7", - "sample_id": null, - "children": [], - "parent": "plate", - "type": "device", - "class": "", - "position": { - "x": 109.87, - "y": 7.77, - "z": 3.03 - }, - "config": { - "type": "Well", - "size_x": 6.86, - "size_y": 6.86, - "size_z": 10.67, - "rotation": { - "x": 0, - "y": 0, - "z": 0, - "type": "Rotation" - }, - "category": "well", - "model": null, - "max_volume": 360, - "material_z_thickness": 0.5, - "compute_volume_from_height": null, - "compute_height_from_volume": null, - "bottom_type": "flat", - "cross_section_type": "circle" - }, - "data": { - "liquids": [], - "pending_liquids": [], - "liquid_history": [] - } } ], "links": [] diff --git a/unilabos/ros/nodes/base_device_node.py b/unilabos/ros/nodes/base_device_node.py index dc75af96..912c6745 100644 --- a/unilabos/ros/nodes/base_device_node.py +++ b/unilabos/ros/nodes/base_device_node.py @@ -15,7 +15,7 @@ from rclpy.action.server import ServerGoalHandle from rclpy.client import Client from rclpy.callback_groups import ReentrantCallbackGroup from rclpy.service import Service -from unilabos_msgs.srv._serial_command import SerialCommand_Request +from unilabos_msgs.srv._serial_command import SerialCommand_Request, SerialCommand_Response from unilabos.resources.graphio import convert_resources_to_type, convert_resources_from_type, resource_ulab_to_plr from unilabos.ros.msgs.message_converter import ( @@ -305,7 +305,7 @@ class BaseROS2DeviceNode(Node, Generic[T]): res.response = "" return res - def append_resource(req: SerialCommand_Request, res): + def append_resource(req: SerialCommand_Request, res: SerialCommand_Response): # 物料传输到对应的node节点 rclient = self.create_client(ResourceAdd, "/resources/add") rclient.wait_for_service() @@ -314,7 +314,7 @@ class BaseROS2DeviceNode(Node, Generic[T]): namespace = command_json["namespace"] bind_parent_id = command_json["bind_parent_id"] edge_device_id = command_json["edge_device_id"] - location = command_json["location"] + location = command_json["bind_location"] other_calling_param = command_json["other_calling_param"] resources = command_json["resource"] # 本地拿到这个物料,可能需要先做初始化? @@ -341,8 +341,9 @@ class BaseROS2DeviceNode(Node, Generic[T]): except Exception as e: self.lab_logger().error("Host请求添加物料时出错") self.lab_logger().error(traceback.format_exc()) - pass + return res + # noinspection PyTypeChecker self._service_server: Dict[str, Service] = { "query_host_name": self.create_service( SerialCommand, f"/srv{self.namespace}/query_host_name", query_host_name_cb, callback_group=self.callback_group @@ -571,27 +572,28 @@ class BaseROS2DeviceNode(Node, Generic[T]): del future # 向Host更新物料当前状态 - for k, v in goal.get_fields_and_field_types().items(): - if v not in ["unilabos_msgs/Resource", "sequence"]: - continue - self.lab_logger().info(f"更新资源状态: {k}") - r = ResourceUpdate.Request() - # 仅当action_kwargs[k]不为None时尝试转换 - akv = action_kwargs[k] - apv = action_paramtypes[k] - final_type = get_type_class(apv) - if final_type is None: - continue - try: - r.resources = [ - convert_to_ros_msg(Resource, self.resource_tracker.root_resource(rs)) - for rs in convert_resources_from_type(akv, final_type) # type: ignore # FIXME # 考虑反查到最大的 - ] - response = await self._resource_clients["resource_update"].call_async(r) - self.lab_logger().debug(f"资源更新结果: {response}") - except Exception as e: - self.lab_logger().error(f"资源更新失败: {e}") - self.lab_logger().error(traceback.format_exc()) + if action_name != "add_resource_from_outer": + for k, v in goal.get_fields_and_field_types().items(): + if v not in ["unilabos_msgs/Resource", "sequence"]: + continue + self.lab_logger().info(f"更新资源状态: {k}") + r = ResourceUpdate.Request() + # 仅当action_kwargs[k]不为None时尝试转换 + akv = action_kwargs[k] + apv = action_paramtypes[k] + final_type = get_type_class(apv) + if final_type is None: + continue + try: + r.resources = [ + convert_to_ros_msg(Resource, self.resource_tracker.root_resource(rs)) + for rs in convert_resources_from_type(akv, final_type) # type: ignore # FIXME # 考虑反查到最大的 + ] + response = await self._resource_clients["resource_update"].call_async(r) + self.lab_logger().debug(f"资源更新结果: {response}") + except Exception as e: + self.lab_logger().error(f"资源更新失败: {e}") + self.lab_logger().error(traceback.format_exc()) # 发布结果 goal_handle.succeed() diff --git a/unilabos/ros/nodes/presets/host_node.py b/unilabos/ros/nodes/presets/host_node.py index 6f94b813..977ab31c 100644 --- a/unilabos/ros/nodes/presets/host_node.py +++ b/unilabos/ros/nodes/presets/host_node.py @@ -286,9 +286,10 @@ class HostNode(BaseROS2DeviceNode): "y": bind_location.y, "z": bind_location.z, }, - "other_calling_param": json.loads(other_calling_param), + "other_calling_param": json.loads(other_calling_param) if other_calling_param else {}, }, ensure_ascii=False) response = sclient.call(request) + pass pass def initialize_device(self, device_id: str, device_config: Dict[str, Any]) -> None: