kuavo-humanoid-sdk 1.1.6b1123__20250610205449-py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of kuavo-humanoid-sdk might be problematic. Click here for more details.

Files changed (132) hide show
  1. kuavo_humanoid_sdk/__init__.py +6 -0
  2. kuavo_humanoid_sdk/common/logger.py +42 -0
  3. kuavo_humanoid_sdk/interfaces/__init__.py +4 -0
  4. kuavo_humanoid_sdk/interfaces/data_types.py +276 -0
  5. kuavo_humanoid_sdk/interfaces/end_effector.py +62 -0
  6. kuavo_humanoid_sdk/interfaces/robot.py +22 -0
  7. kuavo_humanoid_sdk/interfaces/robot_info.py +56 -0
  8. kuavo_humanoid_sdk/kuavo/__init__.py +11 -0
  9. kuavo_humanoid_sdk/kuavo/core/audio.py +32 -0
  10. kuavo_humanoid_sdk/kuavo/core/core.py +617 -0
  11. kuavo_humanoid_sdk/kuavo/core/dex_hand_control.py +114 -0
  12. kuavo_humanoid_sdk/kuavo/core/leju_claw_control.py +67 -0
  13. kuavo_humanoid_sdk/kuavo/core/ros/audio.py +92 -0
  14. kuavo_humanoid_sdk/kuavo/core/ros/control.py +1309 -0
  15. kuavo_humanoid_sdk/kuavo/core/ros/observation.py +94 -0
  16. kuavo_humanoid_sdk/kuavo/core/ros/param.py +183 -0
  17. kuavo_humanoid_sdk/kuavo/core/ros/sat_utils.py +103 -0
  18. kuavo_humanoid_sdk/kuavo/core/ros/state.py +606 -0
  19. kuavo_humanoid_sdk/kuavo/core/ros/tools.py +219 -0
  20. kuavo_humanoid_sdk/kuavo/core/ros/vision.py +234 -0
  21. kuavo_humanoid_sdk/kuavo/core/ros_env.py +460 -0
  22. kuavo_humanoid_sdk/kuavo/dexterous_hand.py +201 -0
  23. kuavo_humanoid_sdk/kuavo/leju_claw.py +235 -0
  24. kuavo_humanoid_sdk/kuavo/robot.py +464 -0
  25. kuavo_humanoid_sdk/kuavo/robot_arm.py +210 -0
  26. kuavo_humanoid_sdk/kuavo/robot_audio.py +39 -0
  27. kuavo_humanoid_sdk/kuavo/robot_head.py +50 -0
  28. kuavo_humanoid_sdk/kuavo/robot_info.py +113 -0
  29. kuavo_humanoid_sdk/kuavo/robot_observation.py +64 -0
  30. kuavo_humanoid_sdk/kuavo/robot_state.py +299 -0
  31. kuavo_humanoid_sdk/kuavo/robot_tool.py +82 -0
  32. kuavo_humanoid_sdk/kuavo/robot_vision.py +83 -0
  33. kuavo_humanoid_sdk/kuavo_strategy/__init__.py +2 -0
  34. kuavo_humanoid_sdk/kuavo_strategy/grasp_box/grasp_box_strategy.py +1126 -0
  35. kuavo_humanoid_sdk/kuavo_strategy/kuavo_strategy.py +104 -0
  36. kuavo_humanoid_sdk/msg/__init__.py +4 -0
  37. kuavo_humanoid_sdk/msg/kuavo_msgs/__init__.py +7 -0
  38. kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_AprilTagDetection.py +306 -0
  39. kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_AprilTagDetectionArray.py +437 -0
  40. kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_Metadata.py +199 -0
  41. kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_RobotActionState.py +112 -0
  42. kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_TFArray.py +323 -0
  43. kuavo_humanoid_sdk/msg/kuavo_msgs/msg/__init__.py +44 -0
  44. kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_armHandPose.py +160 -0
  45. kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_armPoseWithTimeStamp.py +168 -0
  46. kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_armTargetPoses.py +151 -0
  47. kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_bezierCurveCubicPoint.py +178 -0
  48. kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_dexhandCommand.py +229 -0
  49. kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_dexhandTouchState.py +256 -0
  50. kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_endEffectorData.py +227 -0
  51. kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_footPose.py +123 -0
  52. kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_footPoseTargetTrajectories.py +301 -0
  53. kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_footPoses.py +149 -0
  54. kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_fullBodyTargetTrajectories.py +258 -0
  55. kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_gaitTimeName.py +147 -0
  56. kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_gestureInfo.py +218 -0
  57. kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_gestureTask.py +149 -0
  58. kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_handPose.py +136 -0
  59. kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_headBodyPose.py +145 -0
  60. kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_ikSolveError.py +171 -0
  61. kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_ikSolveParam.py +140 -0
  62. kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_imuData.py +165 -0
  63. kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_jointBezierTrajectory.py +201 -0
  64. kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_jointCmd.py +390 -0
  65. kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_jointData.py +205 -0
  66. kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_lejuClawCommand.py +320 -0
  67. kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_lejuClawState.py +341 -0
  68. kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_motorParam.py +122 -0
  69. kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_planArmState.py +120 -0
  70. kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_questJoySticks.py +191 -0
  71. kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_qv.py +121 -0
  72. kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_robotArmQVVD.py +177 -0
  73. kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_robotHandPosition.py +225 -0
  74. kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_robotHeadMotionData.py +128 -0
  75. kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_robotState.py +222 -0
  76. kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_sensorsData.py +495 -0
  77. kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_switchGaitByName.py +200 -0
  78. kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_touchSensorStatus.py +162 -0
  79. kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_twoArmHandPose.py +272 -0
  80. kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_twoArmHandPoseCmd.py +315 -0
  81. kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_yoloDetection.py +251 -0
  82. kuavo_humanoid_sdk/msg/kuavo_msgs/msg/_yoloOutputData.py +168 -0
  83. kuavo_humanoid_sdk/msg/kuavo_msgs/srv/_ExecuteArmAction.py +281 -0
  84. kuavo_humanoid_sdk/msg/kuavo_msgs/srv/_RepublishTFs.py +373 -0
  85. kuavo_humanoid_sdk/msg/kuavo_msgs/srv/_SetJoyTopic.py +282 -0
  86. kuavo_humanoid_sdk/msg/kuavo_msgs/srv/_SpeechSynthesis.py +270 -0
  87. kuavo_humanoid_sdk/msg/kuavo_msgs/srv/__init__.py +28 -0
  88. kuavo_humanoid_sdk/msg/kuavo_msgs/srv/_changeArmCtrlMode.py +275 -0
  89. kuavo_humanoid_sdk/msg/kuavo_msgs/srv/_changeArmCtrlModeKuavo.py +236 -0
  90. kuavo_humanoid_sdk/msg/kuavo_msgs/srv/_changeMotorParam.py +299 -0
  91. kuavo_humanoid_sdk/msg/kuavo_msgs/srv/_changeTorsoCtrlMode.py +274 -0
  92. kuavo_humanoid_sdk/msg/kuavo_msgs/srv/_controlLejuClaw.py +408 -0
  93. kuavo_humanoid_sdk/msg/kuavo_msgs/srv/_enableHandTouchSensor.py +304 -0
  94. kuavo_humanoid_sdk/msg/kuavo_msgs/srv/_fkSrv.py +394 -0
  95. kuavo_humanoid_sdk/msg/kuavo_msgs/srv/_footPoseTargetTrajectoriesSrv.py +409 -0
  96. kuavo_humanoid_sdk/msg/kuavo_msgs/srv/_gestureExecute.py +339 -0
  97. kuavo_humanoid_sdk/msg/kuavo_msgs/srv/_gestureExecuteState.py +257 -0
  98. kuavo_humanoid_sdk/msg/kuavo_msgs/srv/_gestureList.py +418 -0
  99. kuavo_humanoid_sdk/msg/kuavo_msgs/srv/_getCurrentGaitName.py +253 -0
  100. kuavo_humanoid_sdk/msg/kuavo_msgs/srv/_getMotorParam.py +299 -0
  101. kuavo_humanoid_sdk/msg/kuavo_msgs/srv/_handForceLevel.py +330 -0
  102. kuavo_humanoid_sdk/msg/kuavo_msgs/srv/_jointMoveTo.py +302 -0
  103. kuavo_humanoid_sdk/msg/kuavo_msgs/srv/_planArmTrajectoryBezierCurve.py +421 -0
  104. kuavo_humanoid_sdk/msg/kuavo_msgs/srv/_planArmTrajectoryCubicSpline.py +490 -0
  105. kuavo_humanoid_sdk/msg/kuavo_msgs/srv/_playmusic.py +268 -0
  106. kuavo_humanoid_sdk/msg/kuavo_msgs/srv/_setHwIntialState.py +304 -0
  107. kuavo_humanoid_sdk/msg/kuavo_msgs/srv/_setMmCtrlFrame.py +273 -0
  108. kuavo_humanoid_sdk/msg/kuavo_msgs/srv/_setMotorEncoderRoundService.py +283 -0
  109. kuavo_humanoid_sdk/msg/kuavo_msgs/srv/_setTagId.py +275 -0
  110. kuavo_humanoid_sdk/msg/kuavo_msgs/srv/_singleStepControl.py +444 -0
  111. kuavo_humanoid_sdk/msg/kuavo_msgs/srv/_twoArmHandPoseCmdSrv.py +662 -0
  112. kuavo_humanoid_sdk/msg/motion_capture_ik/__init__.py +7 -0
  113. kuavo_humanoid_sdk/msg/ocs2_msgs/__init__.py +7 -0
  114. kuavo_humanoid_sdk/msg/ocs2_msgs/msg/__init__.py +12 -0
  115. kuavo_humanoid_sdk/msg/ocs2_msgs/msg/_constraint.py +142 -0
  116. kuavo_humanoid_sdk/msg/ocs2_msgs/msg/_controller_data.py +121 -0
  117. kuavo_humanoid_sdk/msg/ocs2_msgs/msg/_lagrangian_metrics.py +148 -0
  118. kuavo_humanoid_sdk/msg/ocs2_msgs/msg/_mode_schedule.py +150 -0
  119. kuavo_humanoid_sdk/msg/ocs2_msgs/msg/_mpc_flattened_controller.py +666 -0
  120. kuavo_humanoid_sdk/msg/ocs2_msgs/msg/_mpc_input.py +122 -0
  121. kuavo_humanoid_sdk/msg/ocs2_msgs/msg/_mpc_observation.py +209 -0
  122. kuavo_humanoid_sdk/msg/ocs2_msgs/msg/_mpc_performance_indices.py +140 -0
  123. kuavo_humanoid_sdk/msg/ocs2_msgs/msg/_mpc_solver_data.py +886 -0
  124. kuavo_humanoid_sdk/msg/ocs2_msgs/msg/_mpc_state.py +122 -0
  125. kuavo_humanoid_sdk/msg/ocs2_msgs/msg/_mpc_target_trajectories.py +239 -0
  126. kuavo_humanoid_sdk/msg/ocs2_msgs/msg/_multiplier.py +148 -0
  127. kuavo_humanoid_sdk/msg/ocs2_msgs/srv/__init__.py +1 -0
  128. kuavo_humanoid_sdk/msg/ocs2_msgs/srv/_reset.py +376 -0
  129. kuavo_humanoid_sdk-1.1.6b1123.dist-info/METADATA +291 -0
  130. kuavo_humanoid_sdk-1.1.6b1123.dist-info/RECORD +132 -0
  131. kuavo_humanoid_sdk-1.1.6b1123.dist-info/WHEEL +6 -0
  132. kuavo_humanoid_sdk-1.1.6b1123.dist-info/top_level.txt +1 -0
@@ -0,0 +1,219 @@
1
+ #! /usr/bin/env python3
2
+ # coding: utf-8
3
+
4
+ import copy
5
+ import time
6
+ import numpy as np
7
+ from typing import Tuple, Union
8
+ from kuavo_humanoid_sdk.common.logger import SDKLogger
9
+ import rospy
10
+ from kuavo_humanoid_sdk.msg.kuavo_msgs.srv import RepublishTFs
11
+ from kuavo_humanoid_sdk.msg.kuavo_msgs.msg import TFArray
12
+ import tf.transformations as tf_trans
13
+ from std_msgs.msg import Float64
14
+ from nav_msgs.msg import Odometry
15
+ from sensor_msgs.msg import JointState
16
+ from kuavo_humanoid_sdk.msg.kuavo_msgs.msg import sensorsData, lejuClawState, gaitTimeName, dexhandTouchState
17
+ from geometry_msgs.msg import TransformStamped
18
+ from kuavo_humanoid_sdk.interfaces.data_types import (PoseQuaternion, HomogeneousMatrix)
19
+ from kuavo_humanoid_sdk.kuavo.core.ros.param import make_robot_param, EndEffectorType
20
+
21
+
22
+
23
+ class KuavoRobotToolsCore:
24
+ """Provides core ROS tools for Kuavo humanoid robot transformations.
25
+
26
+ Attributes:
27
+ tf_service (rospy.ServiceProxy): Service proxy for tf2_web_republisher
28
+ _transform_cache (dict): Cache for storing recent transforms
29
+ """
30
+
31
+ def __init__(self):
32
+ """Initializes TF2 web republisher service proxy."""
33
+ if not hasattr(self, '_initialized'):
34
+ try:
35
+ # 初始化TF2 web republisher服务
36
+ rospy.wait_for_service('/republish_tfs', timeout=5.0)
37
+ self.tf_service = rospy.ServiceProxy('/republish_tfs', RepublishTFs)
38
+ self._transform_cache = {}
39
+ self._initialized = True
40
+ except Exception as e:
41
+ SDKLogger.error(f"Failed to initialize tf2_web_republisher: {str(e)}")
42
+ SDKLogger.error("Please make sure tf2_web_republisher node is running")
43
+ raise
44
+
45
+ def _get_tf_tree_transform(self, target_frame: str, source_frame: str,
46
+ time=0.0, timeout=5.0,
47
+ return_type: str = "pose_quaternion") -> Union[PoseQuaternion, HomogeneousMatrix, None]:
48
+ """Gets transform between coordinate frames using tf2_web_republisher.
49
+
50
+ Args:
51
+ target_frame (str): Target coordinate frame name
52
+ source_frame (str): Source coordinate frame name
53
+ time (rospy.Time, optional): Time of transform. Defaults to latest.
54
+ timeout (float, optional): Wait timeout in seconds. Defaults to 5.0.
55
+ return_type (str, optional): Return data format. Options:
56
+ "pose_quaternion", "homogeneous". Defaults to "pose_quaternion".
57
+
58
+ Returns:
59
+ Union[PoseQuaternion, HomogeneousMatrix, None]: Requested transform data
60
+ or None if failed
61
+ """
62
+ try:
63
+
64
+ # 调用服务
65
+ response = self.tf_service(
66
+ source_frames=[source_frame],
67
+ target_frame=target_frame,
68
+ angular_thres=0.01, # 角度阈值
69
+ trans_thres=0.01, # 平移阈值
70
+ rate=10.0, # 更新频率
71
+ timeout=rospy.Duration(timeout)
72
+ )
73
+
74
+ if response.status == -1:
75
+ SDKLogger.error(f"{source_frame} or {target_frame} not exist")
76
+ return None
77
+
78
+ # 检查话题是否发布
79
+ published_topics = rospy.get_published_topics()
80
+ if not any(topic_tuple[0] == response.topic_name for topic_tuple in published_topics):
81
+ SDKLogger.error(f"Topic {response.topic_name} not published")
82
+ return None
83
+
84
+ # 创建订阅者
85
+ transform_received = False
86
+ transform_data = None
87
+
88
+ def transform_callback(msg):
89
+ nonlocal transform_received, transform_data
90
+ transform_received = True
91
+ transform_data = msg
92
+
93
+ sub = rospy.Subscriber(response.topic_name, TFArray, transform_callback)
94
+
95
+ # 等待接收数据
96
+ start_time = rospy.Time.now()
97
+ while not transform_received or (rospy.Time.now() - start_time).to_sec() > timeout:
98
+ rospy.sleep(0.1)
99
+
100
+ # 取消订阅
101
+ sub.unregister()
102
+
103
+ if not transform_received:
104
+ SDKLogger.error("No transform data received")
105
+ return None
106
+
107
+ # 从TFArray中获取对应的变换
108
+ for tf_msg in transform_data.transforms:
109
+ if tf_msg.header.frame_id == target_frame and tf_msg.child_frame_id == source_frame:
110
+ return self._parse_transform(tf_msg.transform, return_type)
111
+
112
+ SDKLogger.error(f"No matching transform found in TFArray")
113
+ return None
114
+
115
+ except rospy.ServiceException as e:
116
+ SDKLogger.error(f"Service call failed: {str(e)}")
117
+ return None
118
+ except Exception as e:
119
+ SDKLogger.error(f"Transform error: {str(e)}")
120
+ return None
121
+
122
+ def _parse_transform(self, transform, return_type: str) -> Union[PoseQuaternion, HomogeneousMatrix, None]:
123
+ """Parses transform data to specified format.
124
+
125
+ Args:
126
+ transform (geometry_msgs/Transform): Input transform data
127
+ return_type (str): Output format type. Valid values:
128
+ "pose_quaternion", "homogeneous"
129
+
130
+ Returns:
131
+ Union[PoseQuaternion, HomogeneousMatrix, None]: Parsed transform data
132
+ in requested format, or None if invalid input
133
+
134
+ Note:
135
+ Falls back to pose_quaternion format if invalid return_type specified
136
+ """
137
+ if return_type == "pose_quaternion":
138
+ return PoseQuaternion(
139
+ position=(transform.translation.x,
140
+ transform.translation.y,
141
+ transform.translation.z),
142
+ orientation=(transform.rotation.x,
143
+ transform.rotation.y,
144
+ transform.rotation.z,
145
+ transform.rotation.w)
146
+ )
147
+ elif return_type == "homogeneous":
148
+ return HomogeneousMatrix(
149
+ matrix=self._transform_to_homogeneous(transform)
150
+ )
151
+ else:
152
+ SDKLogger.warn(f"Invalid return_type: {return_type}, using default(pose_quaternion)")
153
+ return self._parse_transform(transform, "pose_quaternion")
154
+
155
+ def _transform_to_homogeneous(self, transform) -> np.ndarray:
156
+ """Converts geometry_msgs/Transform to homogeneous matrix.
157
+
158
+ Args:
159
+ transform (geometry_msgs/Transform): Input transform message
160
+
161
+ Returns:
162
+ np.ndarray: 4x4 homogeneous transformation matrix (numpy.float32)
163
+
164
+ Example:
165
+ >>> matrix = _transform_to_homogeneous(transform_msg)
166
+ >>> print(matrix.shape)
167
+ (4, 4)
168
+ """
169
+ # 四元数转旋转矩阵
170
+ rotation = [
171
+ transform.rotation.x,
172
+ transform.rotation.y,
173
+ transform.rotation.z,
174
+ transform.rotation.w
175
+ ]
176
+ rot_matrix = tf_trans.quaternion_matrix(rotation)
177
+
178
+ # 设置平移分量
179
+ translation = [
180
+ transform.translation.x,
181
+ transform.translation.y,
182
+ transform.translation.z
183
+ ]
184
+ rot_matrix[:3, 3] = translation
185
+
186
+ return rot_matrix.astype(np.float32) # 确保矩阵数据类型一致
187
+
188
+ def get_link_pose(self, link_name: str, target_frame: str = "base_link") -> Union[PoseQuaternion, None]:
189
+ """获取指定关节链接的位姿(核心实现)
190
+
191
+ Args:
192
+ link_name (str): 关节链接名称
193
+ target_frame (str): 目标坐标系
194
+
195
+ Returns:
196
+ PoseQuaternion: 包含位置和姿态的四元数表示
197
+ """
198
+ return self._get_tf_tree_transform(
199
+ target_frame,
200
+ link_name,
201
+ return_type="pose_quaternion"
202
+ )
203
+
204
+ # if __name__ == "__main__":
205
+ # robot_tools = KuavoRobotToolsCore()
206
+ # time.sleep(0.1)
207
+ # # 获取位姿信息
208
+ # pose = robot_tools._get_tf_tree_transform("odom", "base_link", return_type="pose_quaternion")
209
+ # print(f"Position: {pose.position}")
210
+ # print(f"Orientation: {pose.orientation}")
211
+
212
+ # # 获取齐次矩阵
213
+ # homogeneous = robot_tools._get_tf_tree_transform("odom", "base_link", return_type="homogeneous")
214
+ # print(f"Transformation matrix:\n{homogeneous.matrix}")
215
+
216
+ # # 矩阵运算示例
217
+ # transform_matrix = homogeneous.matrix
218
+ # inverse_matrix = np.linalg.inv(transform_matrix) # 求逆变换
219
+ # print(f"Inverse matrix:\n{inverse_matrix}")
@@ -0,0 +1,234 @@
1
+ #! /usr/bin/env python3
2
+ # coding: utf-8
3
+
4
+ import copy
5
+ import time
6
+ from collections import deque
7
+ from typing import Tuple, Optional
8
+
9
+ from kuavo_humanoid_sdk.kuavo.core.ros.param import make_robot_param, EndEffectorType
10
+ from kuavo_humanoid_sdk.common.logger import SDKLogger
11
+ from kuavo_humanoid_sdk.interfaces.data_types import (AprilTagData, AprilTagDetection)
12
+
13
+ import rospy
14
+ from std_msgs.msg import Float64
15
+ from nav_msgs.msg import Odometry
16
+ from sensor_msgs.msg import JointState
17
+ from apriltag_ros.msg import AprilTagDetectionArray
18
+ from geometry_msgs.msg import TransformStamped, PoseStamped
19
+
20
+
21
+ class KuavoRobotVisionCore:
22
+ """Handles vision-related data processing for Kuavo humanoid robot.
23
+
24
+ Attributes:
25
+ tf_buffer (tf2_ros.Buffer): TF2 transform buffer
26
+ tf_listener (tf2_ros.TransformListener): TF2 transform listener
27
+ tf_broadcaster (tf2_ros.TransformBroadcaster): TF2 transform broadcaster
28
+ """
29
+
30
+ def __init__(self):
31
+ """Initializes vision system components including TF and AprilTag subscribers."""
32
+ if not hasattr(self, '_initialized'):
33
+
34
+
35
+ # FIRST: Initialize data structures before creating subscribers
36
+ """ data """
37
+ self._apriltag_data_from_camera = AprilTagData(
38
+ id = [],
39
+ size = [],
40
+ pose = []
41
+ )
42
+
43
+ self._apriltag_data_from_base = AprilTagData(
44
+ id = [],
45
+ size = [],
46
+ pose = []
47
+ )
48
+
49
+ self._apriltag_data_from_odom = AprilTagData(
50
+ id = [],
51
+ size = [],
52
+ pose = []
53
+ )
54
+
55
+ # THEN: Create subscribers after all data structures are initialized
56
+ self._apriltag_data_camera_sub = rospy.Subscriber('/tag_detections', AprilTagDetectionArray, self._apriltag_data_callback_camera)
57
+ self._apriltag_data_base_sub = rospy.Subscriber('/robot_tag_info', AprilTagDetectionArray, self._apriltag_data_callback_base)
58
+ self._apriltag_data_odom_sub = rospy.Subscriber('/robot_tag_info_odom', AprilTagDetectionArray, self._apriltag_data_callback_odom)
59
+
60
+ # Mark as initialized
61
+ self._initialized = True
62
+
63
+ def _apriltag_data_callback_camera(self, data):
64
+ """Callback for processing AprilTag detections from camera.
65
+
66
+ Args:
67
+ data (AprilTagDetectionArray): Raw detection data from camera
68
+ """
69
+ # 清空之前的数据
70
+ self._apriltag_data_from_camera.id = []
71
+ self._apriltag_data_from_camera.size = []
72
+ self._apriltag_data_from_camera.pose = []
73
+
74
+ # 处理每个标签检测
75
+ for detection in data.detections:
76
+ # 添加ID
77
+ for id in detection.id:
78
+ self._apriltag_data_from_camera.id.append(id)
79
+
80
+ # 添加尺寸 (从size数组中获取)
81
+ if detection.size and len(detection.size) > 0:
82
+ self._apriltag_data_from_camera.size.append(detection.size[0])
83
+ else:
84
+ self._apriltag_data_from_camera.size.append(0.0)
85
+
86
+ # 添加姿态
87
+ self._apriltag_data_from_camera.pose.append(AprilTagDetection(
88
+ position=detection.pose.pose.pose.position,
89
+ orientation=detection.pose.pose.pose.orientation
90
+ ))
91
+ # # debug
92
+ # rospy.loginfo("Apriltag data from camera: %s", self._apriltag_data_from_camera)
93
+
94
+ def _apriltag_data_callback_base(self, data):
95
+ """Callback for processing AprilTag detections from base link.
96
+
97
+ Args:
98
+ data (AprilTagDetectionArray): Raw detection data from base frame
99
+ """
100
+ # 清空之前的数据
101
+ self._apriltag_data_from_base.id = []
102
+ self._apriltag_data_from_base.size = []
103
+ self._apriltag_data_from_base.pose = []
104
+
105
+ # 处理每个标签检测
106
+ for detection in data.detections:
107
+ # 添加ID
108
+ for id in detection.id:
109
+ self._apriltag_data_from_base.id.append(id)
110
+
111
+ # 添加尺寸 (从size数组中获取)
112
+ if detection.size and len(detection.size) > 0:
113
+ self._apriltag_data_from_base.size.append(detection.size[0])
114
+ else:
115
+ self._apriltag_data_from_base.size.append(0.0)
116
+
117
+ # 添加姿态
118
+ self._apriltag_data_from_base.pose.append(AprilTagDetection(
119
+ position=detection.pose.pose.pose.position,
120
+ orientation=detection.pose.pose.pose.orientation
121
+ ))
122
+
123
+ # # debug
124
+ # rospy.loginfo("Apriltag data from base: %s", self._apriltag_data_from_base)
125
+
126
+ def _apriltag_data_callback_odom(self, data):
127
+ """Callback for processing AprilTag detections from odom.
128
+
129
+ Args:
130
+ data (AprilTagDetectionArray): Raw detection data from odom frame
131
+ """
132
+ # 清空之前的数据
133
+ self._apriltag_data_from_odom.id = []
134
+ self._apriltag_data_from_odom.size = []
135
+ self._apriltag_data_from_odom.pose = []
136
+
137
+ # 处理每个标签检测
138
+ for detection in data.detections:
139
+ # 添加ID
140
+ for id in detection.id:
141
+ self._apriltag_data_from_odom.id.append(id)
142
+
143
+ # 添加尺寸 (从size数组中获取)
144
+ if detection.size and len(detection.size) > 0:
145
+ self._apriltag_data_from_odom.size.append(detection.size[0])
146
+ else:
147
+ self._apriltag_data_from_odom.size.append(0.0)
148
+
149
+ # 添加姿态
150
+ self._apriltag_data_from_odom.pose.append(AprilTagDetection(
151
+ position=detection.pose.pose.pose.position,
152
+ orientation=detection.pose.pose.pose.orientation
153
+ ))
154
+
155
+ # # debug
156
+ # rospy.loginfo("Apriltag data from odom: %s", self._apriltag_data_from_odom)
157
+
158
+ @property
159
+ def apriltag_data_from_camera(self) -> AprilTagData:
160
+ """AprilTag detection data in camera coordinate frame.
161
+
162
+ Returns:
163
+ AprilTagData: Contains lists of tag IDs, sizes and poses
164
+ """
165
+ return self._apriltag_data_from_camera
166
+
167
+ @property
168
+ def apriltag_data_from_base(self) -> AprilTagData:
169
+ """AprilTag detection data in base_link coordinate frame.
170
+
171
+ Returns:
172
+ AprilTagData: Contains lists of tag IDs, sizes and poses
173
+ """
174
+ return self._apriltag_data_from_base
175
+
176
+ @property
177
+ def apriltag_data_from_odom(self) -> AprilTagData:
178
+ """AprilTag detection data in odom coordinate frame.
179
+
180
+ Returns:
181
+ AprilTagData: Contains lists of tag IDs, sizes and transformed poses
182
+ """
183
+ return self._apriltag_data_from_odom
184
+
185
+ def _get_data_by_id(self, target_id: int, data_source: str = "base") -> Optional[dict]:
186
+ """Retrieves AprilTag data by specific ID from selected source.
187
+
188
+ Args:
189
+ target_id (int): AprilTag ID to search for
190
+ data_source (str): Data source selector, valid options:
191
+ "camera", "base", "odom"
192
+
193
+ Returns:
194
+ Optional[dict]: Dictionary containing 'sizes' and 'poses' lists if found,
195
+ None if no matching data
196
+
197
+ Raises:
198
+ ValueError: If invalid data_source is specified
199
+ """
200
+ data_map = {
201
+ "camera": self._apriltag_data_from_camera,
202
+ "base": self._apriltag_data_from_base,
203
+ "odom": self._apriltag_data_from_odom
204
+ }
205
+
206
+ if data_source not in data_map:
207
+ # SDKLogger.error(f"Invalid data source: {data_source}, must be one of {list(data_map.keys())}")
208
+ return None
209
+
210
+ data = data_map[data_source]
211
+
212
+ # 查找所有匹配的索引
213
+ indices = [i for i, tag_id in enumerate(data.id) if tag_id == target_id]
214
+
215
+ if not indices:
216
+ # SDKLogger.debug(f"No data found for tag ID {target_id} in {data_source} source")
217
+ return None
218
+
219
+ return {
220
+ "sizes": [data.size[i] for i in indices],
221
+ "poses": [data.pose[i] for i in indices]
222
+ }
223
+
224
+ # if __name__ == "__main__":
225
+
226
+ # kuavo_robot_vision_core = KuavoRobotVisionCore()
227
+ # time.sleep(5)
228
+ # print("apriltag_data_from_camera:")
229
+ # print(kuavo_robot_vision_core.apriltag_data_from_camera)
230
+ # print("apriltag_data_from_base:")
231
+ # print(kuavo_robot_vision_core.apriltag_data_from_base)
232
+ # print("apriltag_data_from_odom:")
233
+ # print(kuavo_robot_vision_core.apriltag_data_from_odom)
234
+ # rospy.spin()