|
|
@@ -2,6 +2,7 @@ import cv2
|
|
|
import re
|
|
|
import rclpy
|
|
|
import subprocess
|
|
|
+import json
|
|
|
from rclpy.action import ActionServer
|
|
|
from rclpy.node import Node
|
|
|
from geometry_msgs.msg import Twist
|
|
|
@@ -162,6 +163,39 @@ class CustomActionServer(Node):
|
|
|
self.record_status_sub = self.create_subscription(
|
|
|
Bool, "record_status", self.record_status_callback, 5
|
|
|
)
|
|
|
+ # 环境数据订阅者,动态更新导航点 / Environment data subscriber for dynamic navigation point updates
|
|
|
+ # 默认值,后续从配置动态更新
|
|
|
+ self.environment_topic = "/ai/env"
|
|
|
+ self.config_sub = self.create_subscription(
|
|
|
+ String, "/ai/config", self.config_callback, 10
|
|
|
+ )
|
|
|
+ self.environment_sub = self.create_subscription(
|
|
|
+ String, self.environment_topic, self.environment_callback, 10
|
|
|
+ )
|
|
|
+
|
|
|
+ def config_callback(self, msg):
|
|
|
+ """
|
|
|
+ 配置订阅回调函数
|
|
|
+ 从 /ai/config 解析 environment_topic
|
|
|
+ """
|
|
|
+ try:
|
|
|
+ config = json.loads(msg.data)
|
|
|
+ topics = config.get('config', {}).get('topics', {})
|
|
|
+ environment_node_config = topics.get('environment_node', {})
|
|
|
+
|
|
|
+ if environment_node_config:
|
|
|
+ new_topic = environment_node_config.get('environment_topic', '/ai/env')
|
|
|
+ if new_topic != self.environment_topic:
|
|
|
+ self.environment_topic = new_topic
|
|
|
+ # 重建订阅
|
|
|
+ if self.environment_sub:
|
|
|
+ self.destroy_subscription(self.environment_sub)
|
|
|
+ self.environment_sub = self.create_subscription(
|
|
|
+ String, self.environment_topic, self.environment_callback, 10
|
|
|
+ )
|
|
|
+ self.get_logger().info(f'[配置] 环境数据订阅 Topic 已更新: {self.environment_topic}')
|
|
|
+ except Exception as e:
|
|
|
+ self.get_logger().warn(f'解析配置数据失败: {e}')
|
|
|
|
|
|
def system_sound_init(
|
|
|
self,
|
|
|
@@ -311,6 +345,72 @@ class CustomActionServer(Node):
|
|
|
pose.pose.orientation.w = data["orientation"]["w"]
|
|
|
self.navpose_dict[name] = pose
|
|
|
|
|
|
+ def update_navpose_from_environment(self, points):
|
|
|
+ """
|
|
|
+ 从环境数据更新导航点字典
|
|
|
+ / Update navigation point dictionary from environment data
|
|
|
+ """
|
|
|
+ if not points:
|
|
|
+ return
|
|
|
+
|
|
|
+ updated_count = 0
|
|
|
+ for point in points:
|
|
|
+ point_id = point.get('id', '')
|
|
|
+ name = point.get('name', '')
|
|
|
+ position = point.get('position', {})
|
|
|
+
|
|
|
+ if not point_id or not position:
|
|
|
+ continue
|
|
|
+
|
|
|
+ pose = PoseStamped()
|
|
|
+ pose.header.frame_id = "map"
|
|
|
+
|
|
|
+ # 从 position 获取坐标
|
|
|
+ pose.pose.position.x = position.get('x', 0.0)
|
|
|
+ pose.pose.position.y = position.get('y', 0.0)
|
|
|
+ pose.pose.position.z = position.get('z', 0.0)
|
|
|
+
|
|
|
+ # 从 position 获取 orientation(如果有)
|
|
|
+ orientation = position.get('orientation', {})
|
|
|
+ if orientation:
|
|
|
+ pose.pose.orientation.x = orientation.get('x', 0.0)
|
|
|
+ pose.pose.orientation.y = orientation.get('y', 0.0)
|
|
|
+ pose.pose.orientation.z = orientation.get('z', 0.0)
|
|
|
+ pose.pose.orientation.w = orientation.get('w', 1.0)
|
|
|
+ else:
|
|
|
+ # 使用默认朝向(无旋转)
|
|
|
+ pose.pose.orientation.x = 0.0
|
|
|
+ pose.pose.orientation.y = 0.0
|
|
|
+ pose.pose.orientation.z = 0.0
|
|
|
+ pose.pose.orientation.w = 1.0
|
|
|
+
|
|
|
+ self.navpose_dict[point_id] = pose
|
|
|
+ updated_count += 1
|
|
|
+
|
|
|
+ if updated_count > 0:
|
|
|
+ self.get_logger().debug(f'[环境更新] 已更新 {updated_count} 个导航点,当前共 {len(self.navpose_dict)} 个点')
|
|
|
+
|
|
|
+ def environment_callback(self, msg):
|
|
|
+ """
|
|
|
+ 环境数据订阅回调函数
|
|
|
+ 从 /ai/env topic 接收环境数据,动态更新导航点
|
|
|
+ """
|
|
|
+ try:
|
|
|
+ env_json = json.loads(msg.data)
|
|
|
+ map_data = env_json.get('map', {})
|
|
|
+ if map_data:
|
|
|
+ points = map_data.get('points', [])
|
|
|
+ if points:
|
|
|
+ self.update_navpose_from_environment(points)
|
|
|
+ else:
|
|
|
+ self.get_logger().debug("[环境回调] map points 为空")
|
|
|
+ else:
|
|
|
+ self.get_logger().debug("[环境回调] map_data 为空")
|
|
|
+ except json.JSONDecodeError as e:
|
|
|
+ self.get_logger().warn(f'解析环境数据失败: {e}')
|
|
|
+ except Exception as e:
|
|
|
+ self.get_logger().warn(f'环境数据处理异常: {e}')
|
|
|
+
|
|
|
# def arm_grasp_init(self):
|
|
|
# """
|
|
|
# 初始化机械臂抓取功能 /initialize the grasping function of the robotic arm
|