workflow upload & set liquid fix & add set liquid with plate

fix upload workflow json

save class name when deserialize & protocol execute test

Support root node change pos

add unilabos_class

gather query
This commit is contained in:
Xuwznln
2026-01-28 13:23:25 +08:00
parent 3a2d9e9603
commit 5179a7e48e
15 changed files with 2619 additions and 473 deletions

View File

@@ -884,6 +884,9 @@ class BaseROS2DeviceNode(Node, Generic[T]):
parent_appended = True
# 加载状态
original_instance.location = plr_resource.location
original_instance.rotation = plr_resource.rotation
original_instance.barcode = plr_resource.barcode
original_instance.load_all_state(states)
child_count = len(original_instance.get_all_children())
self.lab_logger().info(
@@ -1319,19 +1322,32 @@ class BaseROS2DeviceNode(Node, Generic[T]):
resource_inputs = action_kwargs[k] if is_sequence else [action_kwargs[k]]
# 批量查询资源
queried_resources = []
for resource_data in resource_inputs:
queried_resources: list = [None] * len(resource_inputs)
uuid_indices: list[tuple[int, str, dict]] = [] # (index, uuid, resource_data)
# 第一遍处理没有uuid的资源收集有uuid的资源信息
for idx, resource_data in enumerate(resource_inputs):
unilabos_uuid = resource_data.get("data", {}).get("unilabos_uuid")
if unilabos_uuid is None:
plr_resource = await self.get_resource_with_dir(
resource_id=resource_data["id"], with_children=True
)
if "sample_id" in resource_data:
plr_resource.unilabos_extra["sample_uuid"] = resource_data["sample_id"]
queried_resources[idx] = plr_resource
else:
resource_tree = await self.get_resource([unilabos_uuid])
plr_resource = resource_tree.to_plr_resources()[0]
if "sample_id" in resource_data:
plr_resource.unilabos_extra["sample_uuid"] = resource_data["sample_id"]
queried_resources.append(plr_resource)
uuid_indices.append((idx, unilabos_uuid, resource_data))
# 第二遍批量查询有uuid的资源
if uuid_indices:
uuids = [item[1] for item in uuid_indices]
resource_tree = await self.get_resource(uuids)
plr_resources = resource_tree.to_plr_resources()
for i, (idx, _, resource_data) in enumerate(uuid_indices):
plr_resource = plr_resources[i]
if "sample_id" in resource_data:
plr_resource.unilabos_extra["sample_uuid"] = resource_data["sample_id"]
queried_resources[idx] = plr_resource
self.lab_logger().debug(f"资源查询结果: 共 {len(queried_resources)} 个资源")

View File

@@ -6,8 +6,6 @@ from typing import List, Dict, Any, Optional, TYPE_CHECKING
import rclpy
from rosidl_runtime_py import message_to_ordereddict
from unilabos_msgs.msg import Resource
from unilabos_msgs.srv import ResourceUpdate
from unilabos.messages import * # type: ignore # protocol names
from rclpy.action import ActionServer, ActionClient
@@ -15,7 +13,6 @@ from rclpy.action.server import ServerGoalHandle
from unilabos_msgs.srv._serial_command import SerialCommand_Request, SerialCommand_Response
from unilabos.compile import action_protocol_generators
from unilabos.resources.graphio import nested_dict_to_list
from unilabos.ros.initialize_device import initialize_device_from_dict
from unilabos.ros.msgs.message_converter import (
get_action_type,
@@ -231,15 +228,15 @@ class ROS2WorkstationNode(BaseROS2DeviceNode):
try:
# 统一处理单个或多个资源
resource_id = (
protocol_kwargs[k]["id"] if v == "unilabos_msgs/Resource" else protocol_kwargs[k][0]["id"]
protocol_kwargs[k]["id"]
if v == "unilabos_msgs/Resource"
else protocol_kwargs[k][0]["id"]
)
resource_uuid = protocol_kwargs[k].get("uuid", None)
r = SerialCommand_Request()
r.command = json.dumps({"id": resource_id, "uuid": resource_uuid, "with_children": True})
# 发送请求并等待响应
response: SerialCommand_Response = await self._resource_clients[
"resource_get"
].call_async(
response: SerialCommand_Response = await self._resource_clients["resource_get"].call_async(
r
) # type: ignore
raw_data = json.loads(response.response)
@@ -307,12 +304,52 @@ class ROS2WorkstationNode(BaseROS2DeviceNode):
# 向Host更新物料当前状态
for k, v in goal.get_fields_and_field_types().items():
if v in ["unilabos_msgs/Resource", "sequence<unilabos_msgs/Resource>"]:
r = ResourceUpdate.Request()
r.resources = [
convert_to_ros_msg(Resource, rs) for rs in nested_dict_to_list(protocol_kwargs[k])
]
response = await self._resource_clients["resource_update"].call_async(r)
if v not in ["unilabos_msgs/Resource", "sequence<unilabos_msgs/Resource>"]:
continue
self.lab_logger().info(f"更新资源状态: {k}")
try:
# 去重:使用 seen 集合获取唯一的资源对象
seen = set()
unique_resources = []
# 获取资源数据,统一转换为列表
resource_data = protocol_kwargs[k]
is_sequence = v != "unilabos_msgs/Resource"
if not is_sequence:
resource_list = [resource_data] if isinstance(resource_data, dict) else resource_data
else:
# 处理序列类型,可能是嵌套列表
resource_list = []
if isinstance(resource_data, list):
for item in resource_data:
if isinstance(item, list):
resource_list.extend(item)
else:
resource_list.append(item)
else:
resource_list = [resource_data]
for res_data in resource_list:
if not isinstance(res_data, dict):
continue
res_name = res_data.get("id") or res_data.get("name")
if not res_name:
continue
# 使用 resource_tracker 获取本地 PLR 实例
plr = self.resource_tracker.figure_resource({"name": res_name}, try_mode=False)
# 获取父资源
res = self.resource_tracker.parent_resource(plr)
if id(res) not in seen:
seen.add(id(res))
unique_resources.append(res)
# 使用新的资源树接口更新
if unique_resources:
await self.update_resource(unique_resources)
except Exception as e:
self.lab_logger().error(f"资源更新失败: {e}")
self.lab_logger().error(traceback.format_exc())
# 设置成功状态和返回值
execution_success = True