action to resource & 0.9.12

This commit is contained in:
KCFeng425
2025-07-17 04:10:15 +08:00
parent f90be18926
commit 6b7564b9f9
53 changed files with 2526 additions and 761 deletions

View File

@@ -508,47 +508,90 @@ def convert_from_ros_msg_with_mapping(ros_msg: Any, value_mapping: Dict[str, str
Python字典
"""
data: Dict[str, Any] = {}
# 🔧 添加调试信息
print(f"🔍 convert_from_ros_msg_with_mapping 开始")
print(f"🔍 ros_msg 类型: {type(ros_msg)}")
print(f"🔍 ros_msg 内容: {ros_msg}")
print(f"🔍 value_mapping: {value_mapping}")
print("-" * 60)
for msg_name, attr_name in value_mapping.items():
print(f"🔍 处理映射: {msg_name} -> {attr_name}")
msg_path = msg_name.split(".")
current = ros_msg
print(f"🔍 msg_path: {msg_path}")
print(f"🔍 current 初始值: {current} (类型: {type(current)})")
try:
if not attr_name.endswith("[]"):
# 处理单值映射
for name in msg_path:
current = getattr(current, name)
data[attr_name] = convert_from_ros_msg(current)
print(f"🔍 处理单值映射")
for i, name in enumerate(msg_path):
print(f"🔍 步骤 {i}: 获取属性 '{name}'{type(current)}")
if hasattr(current, name):
current = getattr(current, name)
print(f"🔍 获取到: {current} (类型: {type(current)})")
else:
print(f"❌ 属性 '{name}' 不存在于 {type(current)}")
break
converted_value = convert_from_ros_msg(current)
print(f"🔍 转换后的值: {converted_value} (类型: {type(converted_value)})")
data[attr_name] = converted_value
print(f"✅ 设置 data['{attr_name}'] = {converted_value}")
else:
# 处理列表值映射
for name in msg_path:
print(f"🔍 处理列表值映射")
for i, name in enumerate(msg_path):
print(f"🔍 列表步骤 {i}: 处理 '{name}'{type(current)}")
if name.endswith("[]"):
base_name = name[:-2]
print(f"🔍 数组字段 base_name: '{base_name}'")
if hasattr(current, base_name):
current = list(getattr(current, base_name))
print(f"🔍 获取数组: {current} (长度: {len(current)})")
else:
print(f"❌ 数组字段 '{base_name}' 不存在")
current = []
break
else:
if isinstance(current, list):
print(f"🔍 从列表中获取属性 '{name}'")
next_level = []
for item in current:
if hasattr(item, name):
next_level.append(getattr(item, name))
current = next_level
print(f"🔍 列表处理结果: {current} (长度: {len(current)})")
elif hasattr(current, name):
current = getattr(current, name)
print(f"🔍 获取到属性: {current} (类型: {type(current)})")
else:
print(f"❌ 属性 '{name}' 不存在")
current = []
break
attr_key = attr_name[:-2]
if current:
data[attr_key] = [convert_from_ros_msg(item) for item in current]
except (AttributeError, TypeError):
converted_list = [convert_from_ros_msg(item) for item in current]
data[attr_key] = converted_list
print(f"✅ 设置 data['{attr_key}'] = {converted_list}")
else:
print(f"⚠️ 列表为空,跳过 '{attr_key}'")
except (AttributeError, TypeError) as e:
print(f"❌ 映射转换错误 {msg_name} -> {attr_name}: {e}")
logger.debug(f"Mapping conversion error for {msg_name} -> {attr_name}")
continue
print(f"🔍 当前 data 状态: {data}")
print("-" * 40)
print(f"🔍 convert_from_ros_msg_with_mapping 结束")
print(f"🔍 最终 data: {data}")
print("=" * 60)
return data

View File

@@ -562,9 +562,9 @@ class HostNode(BaseROS2DeviceNode):
for bridge in self.bridges:
if hasattr(bridge, "publish_device_status"):
bridge.publish_device_status(self.device_status, device_id, property_name)
self.lab_logger().debug(
f"[Host Node] Status updated: {device_id}.{property_name} = {msg.data}"
)
#self.lab_logger().debug(
# f"[Host Node] Status updated: {device_id}.{property_name} = {msg.data}"
#)
def send_goal(
self,

View File

@@ -182,26 +182,54 @@ class ROS2ProtocolNode(BaseROS2DeviceNode):
# 从目标消息中提取参数, 并调用Protocol生成器(根据设备连接图)生成action步骤
goal = goal_handle.request
protocol_kwargs = convert_from_ros_msg_with_mapping(goal, action_value_mapping["goal"])
# 🔧 添加调试信息
print(f"🔍 转换后的 protocol_kwargs: {protocol_kwargs}")
print(f"🔍 vessel 在转换后: {protocol_kwargs.get('vessel', 'NOT_FOUND')}")
# 向Host查询物料当前状态
for k, v in goal.get_fields_and_field_types().items():
if v in ["unilabos_msgs/Resource", "sequence<unilabos_msgs/Resource>"]:
r = ResourceGet.Request()
resource_id = (
protocol_kwargs[k]["id"] if v == "unilabos_msgs/Resource" else protocol_kwargs[k][0]["id"]
)
r.id = resource_id
r.with_children = True
response = await self._resource_clients["resource_get"].call_async(r)
protocol_kwargs[k] = list_to_nested_dict(
[convert_from_ros_msg(rs) for rs in response.resources]
)
# 🔧 完全禁用Host查询直接使用转换后的数据
print(f"🔧 跳过Host查询直接使用转换后的数据")
# 🔧 额外验证确保vessel数据完整
if 'vessel' in protocol_kwargs:
vessel_data = protocol_kwargs['vessel']
print(f"🔍 验证vessel数据: {vessel_data}")
# 如果vessel是空字典尝试重新构建
if not vessel_data or (isinstance(vessel_data, dict) and not vessel_data):
print(f"⚠️ vessel数据为空尝试从原始goal重新提取...")
# 直接从原始goal提取vessel
if hasattr(goal, 'vessel') and goal.vessel:
print(f"🔍 原始goal.vessel: {goal.vessel}")
# 手动转换vessel
vessel_data = {
'id': goal.vessel.id,
'name': goal.vessel.name,
'type': goal.vessel.type,
'category': goal.vessel.category,
'config': goal.vessel.config,
'data': goal.vessel.data
}
protocol_kwargs['vessel'] = vessel_data
print(f"✅ 手动重建vessel数据: {vessel_data}")
else:
print(f"❌ 无法从原始goal提取vessel数据")
# 创建一个基本的vessel
vessel_data = {'id': 'default_vessel'}
protocol_kwargs['vessel'] = vessel_data
print(f"🔧 创建默认vessel: {vessel_data}")
print(f"🔍 最终传递给协议的 protocol_kwargs: {protocol_kwargs}")
print(f"🔍 最终的 vessel: {protocol_kwargs.get('vessel', 'NOT_FOUND')}")
from unilabos.resources.graphio import physical_setup_graph
self.lab_logger().info(f"Working on physical setup: {physical_setup_graph}")
self.lab_logger().info(f"Protocol kwargs: {goal}")
self.lab_logger().info(f"Protocol kwargs: {action_value_mapping}")
protocol_steps = protocol_steps_generator(G=physical_setup_graph, **protocol_kwargs)
self.lab_logger().info(f"Goal received: {protocol_kwargs}, running steps: \n{protocol_steps}")
time_start = time.time()
@@ -235,14 +263,14 @@ class ROS2ProtocolNode(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)
# # 向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)
# 设置成功状态和返回值
execution_success = True