kuavo-humanoid-sdk-ws 1.3.2__20260122221834-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.
Files changed (43) hide show
  1. kuavo_humanoid_sdk/__init__.py +6 -0
  2. kuavo_humanoid_sdk/common/launch_robot_tool.py +170 -0
  3. kuavo_humanoid_sdk/common/logger.py +45 -0
  4. kuavo_humanoid_sdk/common/websocket_kuavo_sdk.py +26 -0
  5. kuavo_humanoid_sdk/interfaces/__init__.py +4 -0
  6. kuavo_humanoid_sdk/interfaces/data_types.py +293 -0
  7. kuavo_humanoid_sdk/interfaces/end_effector.py +62 -0
  8. kuavo_humanoid_sdk/interfaces/robot.py +22 -0
  9. kuavo_humanoid_sdk/interfaces/robot_info.py +56 -0
  10. kuavo_humanoid_sdk/kuavo/__init__.py +12 -0
  11. kuavo_humanoid_sdk/kuavo/core/audio.py +32 -0
  12. kuavo_humanoid_sdk/kuavo/core/core.py +755 -0
  13. kuavo_humanoid_sdk/kuavo/core/dex_hand_control.py +114 -0
  14. kuavo_humanoid_sdk/kuavo/core/leju_claw_control.py +67 -0
  15. kuavo_humanoid_sdk/kuavo/core/ros/audio.py +86 -0
  16. kuavo_humanoid_sdk/kuavo/core/ros/control.py +1325 -0
  17. kuavo_humanoid_sdk/kuavo/core/ros/observation.py +125 -0
  18. kuavo_humanoid_sdk/kuavo/core/ros/param.py +335 -0
  19. kuavo_humanoid_sdk/kuavo/core/ros/sat_utils.py +103 -0
  20. kuavo_humanoid_sdk/kuavo/core/ros/state.py +426 -0
  21. kuavo_humanoid_sdk/kuavo/core/ros/tools.py +197 -0
  22. kuavo_humanoid_sdk/kuavo/core/ros/vision.py +280 -0
  23. kuavo_humanoid_sdk/kuavo/core/ros_env.py +236 -0
  24. kuavo_humanoid_sdk/kuavo/dexterous_hand.py +198 -0
  25. kuavo_humanoid_sdk/kuavo/leju_claw.py +232 -0
  26. kuavo_humanoid_sdk/kuavo/robot.py +550 -0
  27. kuavo_humanoid_sdk/kuavo/robot_arm.py +235 -0
  28. kuavo_humanoid_sdk/kuavo/robot_audio.py +39 -0
  29. kuavo_humanoid_sdk/kuavo/robot_head.py +39 -0
  30. kuavo_humanoid_sdk/kuavo/robot_info.py +235 -0
  31. kuavo_humanoid_sdk/kuavo/robot_observation.py +69 -0
  32. kuavo_humanoid_sdk/kuavo/robot_state.py +346 -0
  33. kuavo_humanoid_sdk/kuavo/robot_tool.py +58 -0
  34. kuavo_humanoid_sdk/kuavo/robot_vision.py +82 -0
  35. kuavo_humanoid_sdk/kuavo/robot_waist.py +53 -0
  36. kuavo_humanoid_sdk/kuavo_strategy/__init__.py +2 -0
  37. kuavo_humanoid_sdk/kuavo_strategy/grasp_box/grasp_box_strategy.py +418 -0
  38. kuavo_humanoid_sdk/kuavo_strategy/kuavo_strategy.py +63 -0
  39. kuavo_humanoid_sdk/msg/__init__.py +4 -0
  40. kuavo_humanoid_sdk_ws-1.3.2.dist-info/METADATA +276 -0
  41. kuavo_humanoid_sdk_ws-1.3.2.dist-info/RECORD +43 -0
  42. kuavo_humanoid_sdk_ws-1.3.2.dist-info/WHEEL +6 -0
  43. kuavo_humanoid_sdk_ws-1.3.2.dist-info/top_level.txt +1 -0
@@ -0,0 +1,346 @@
1
+ #!/usr/bin/env python3
2
+ # coding: utf-8
3
+ import time
4
+ import copy
5
+ from typing import Tuple
6
+ from kuavo_humanoid_sdk.interfaces.data_types import (
7
+ KuavoImuData, KuavoJointData, KuavoOdometry, KuavoArmCtrlMode,EndEffectorState,
8
+ KuavoManipulationMpcControlFlow, KuavoManipulationMpcCtrlMode, KuavoManipulationMpcFrame)
9
+ from kuavo_humanoid_sdk.kuavo.core.ros.state import KuavoRobotStateCoreWebsocket
10
+ from kuavo_humanoid_sdk.kuavo.core.ros.param import make_robot_param
11
+
12
+ class KuavoRobotState:
13
+ def __init__(self, robot_type: str = "kuavo"):
14
+ self._rs_core = KuavoRobotStateCoreWebsocket()
15
+
16
+ @property
17
+ def imu_data(self) -> KuavoImuData:
18
+ """Get Robot IMU Data.
19
+
20
+ Gets the current IMU sensor data from the robot, including gyroscope, accelerometer,
21
+ free acceleration and orientation quaternion measurements.
22
+
23
+ Returns:
24
+ :class:`KuavoImuData`: IMU data containing:
25
+ * gyro (:obj:`tuple` of :obj:`float`): Gyroscope measurements (x, y, z) in rad/s
26
+ * acc (:obj:`tuple` of :obj:`float`): Accelerometer measurements (x, y, z) in m/s^2
27
+ * free_acc (:obj:`tuple` of :obj:`float`): Free acceleration (x, y, z) in m/s^2
28
+ * quat (:obj:`tuple` of :obj:`float`): Orientation quaternion (x, y, z, w)
29
+ """
30
+ return self._rs_core.imu_data
31
+
32
+ @property
33
+ def joint_state(self) -> KuavoJointData:
34
+ """Get Robot Joint Data.
35
+
36
+ Get Robot Joint Data, including joint positions, velocities, torques and accelerations.
37
+
38
+ The data includes:
39
+ - Joint positions (angles) in radians
40
+ - Joint velocities in radians/second
41
+ - Joint torques/efforts in Newton-meters, A
42
+ - Joint acceleration
43
+
44
+ Returns:
45
+ KuavoJointData: A dictionary containing joint state data with the following keys:
46
+ position (list[float]): Joint positions, length = joint_dof(28)
47
+ velocity (list[float]): Joint velocities, length = joint_dof(28)
48
+ torque (list[float]): Joint torques, length = joint_dof(28)
49
+ acceleration (list[float]): Joint accelerations, length = joint_dof(28)
50
+ """
51
+ return self._rs_core.joint_data
52
+
53
+ @property
54
+ def com_height(self)->float:
55
+ """Get the height of the robot's center of mass.
56
+
57
+ Returns:
58
+ float: The height of the robot's center of mass in meters.
59
+ """
60
+ return self._rs_core.com_height
61
+
62
+ @property
63
+ def odometry(self) -> KuavoOdometry:
64
+ """Get Robot Odometry Data.
65
+
66
+ Gets the current odometry data from the robot, including position, orientation,
67
+ linear velocity and angular velocity measurements.
68
+
69
+ Returns:
70
+ KuavoOdometry: A dictionary containing odometry data with the following keys:
71
+ position (tuple): Position (x, y, z) in meters
72
+ orientation (tuple): Orientation as quaternion (x, y, z, w)
73
+ linear (tuple): Linear velocity (x, y, z) in m/s
74
+ angular (tuple): Angular velocity (x, y, z) in rad/s
75
+ """
76
+ return self._rs_core.odom_data
77
+
78
+
79
+ def robot_position(self) -> Tuple[float, float, float]:
80
+ """Returns the robot's position in world coordinates.
81
+
82
+ Returns:
83
+ Tuple[float, float, float]: Position (x, y, z) in meters.
84
+ """
85
+ return tuple(self._rs_core.odom_data.position)
86
+
87
+ def robot_orientation(self) -> Tuple[float, float, float, float]:
88
+ """Returns the robot's orientation in world coordinates.
89
+
90
+ Returns:
91
+ Tuple[float, float, float, float]: Orientation as quaternion (x, y, z, w).
92
+ """
93
+ return tuple(self._rs_core.odom_data.orientation)
94
+
95
+ def linear_velocity(self) -> Tuple[float, float, float]:
96
+ """Returns the robot's linear velocity in world coordinates.
97
+
98
+ Returns:
99
+ Tuple[float, float, float]: Linear velocity (x, y, z) in m/s.
100
+ """
101
+ return tuple(self._rs_core.odom_data.linear)
102
+
103
+
104
+ def angular_velocity(self) -> Tuple[float, float, float]:
105
+ """Returns the robot's angular velocity in world coordinates.
106
+
107
+ Returns:
108
+ Tuple[float, float, float]: Angular velocity (x, y, z).
109
+ """
110
+ return tuple(self._rs_core.odom_data.angular)
111
+
112
+ def arm_joint_state(self) -> KuavoJointData:
113
+ """Get the current state of the robot arm joints.
114
+
115
+ Get the current state of the robot arm joints, including:
116
+ - Joint positions (angles) in radians
117
+ - Joint velocities in radians/second
118
+ - Joint torques/efforts in Newton-meters, A
119
+ - Joint acceleration
120
+
121
+ Returns:
122
+ KuavoJointData: Arm joint data containing:
123
+ position: list[float] * arm_dof(14)
124
+ velocity: list[float] * arm_dof(14)
125
+ torque: list[float] * arm_dof(14)
126
+ acceleration: list[float] * arm_dof(14)
127
+ """
128
+ # Get robot parameters to determine joint indices
129
+ robot_params = make_robot_param()
130
+ arm_dof = robot_params.get('arm_dof')
131
+ leg_dof = robot_params.get('leg_dof')
132
+ waist_dof = robot_params.get('waist_dof', 0) # Default to 0 if not found
133
+
134
+ if arm_dof is None or leg_dof is None or waist_dof is None:
135
+ raise ValueError("Failed to get DOF values from robot parameters")
136
+
137
+ # Calculate arm joint start index: leg_dof + waist_dof
138
+ arm_start_idx = leg_dof + waist_dof
139
+ arm_joint_indices = range(arm_start_idx, arm_start_idx + arm_dof)
140
+
141
+ return KuavoJointData(
142
+ position=[self._rs_core.joint_data.position[i] for i in arm_joint_indices],
143
+ velocity=[self._rs_core.joint_data.velocity[i] for i in arm_joint_indices],
144
+ torque=[self._rs_core.joint_data.torque[i] for i in arm_joint_indices],
145
+ acceleration=[self._rs_core.joint_data.acceleration[i] for i in arm_joint_indices]
146
+ )
147
+
148
+ def arm_control_mode(self) -> KuavoArmCtrlMode:
149
+ """Get the current control mode of the robot arm.
150
+
151
+ Returns:
152
+ KuavoArmCtrlMode: Current arm control mode:
153
+ ArmFixed: 0 - The robot arm is in a fixed position.
154
+ AutoSwing: 1 - The robot arm is in automatic swing mode.
155
+ ExternalControl: 2 - The robot arm is controlled externally.
156
+ or None.
157
+ """
158
+ return KuavoArmCtrlMode(self._rs_core.arm_control_mode)
159
+
160
+ def manipulation_mpc_ctrl_mode(self) -> KuavoManipulationMpcCtrlMode:
161
+ """Get the current control mode of the robot manipulation MPC.
162
+
163
+ Returns:
164
+ KuavoManipulationMpcCtrlMode: Current manipulation MPC control mode.
165
+
166
+ """
167
+ return self._rs_core.manipulation_mpc_ctrl_mode
168
+
169
+ def manipulation_mpc_control_flow(self) -> KuavoManipulationMpcControlFlow:
170
+ """Get the current control flow of the robot manipulation.
171
+
172
+ Returns:
173
+ KuavoManipulationMpcControlFlow: Current manipulation control flow.
174
+ """
175
+ return self._rs_core.manipulation_mpc_control_flow
176
+
177
+ def manipulation_mpc_frame(self) -> KuavoManipulationMpcFrame:
178
+ """Get the current frame of the robot manipulation MPC.
179
+
180
+ Returns:
181
+ KuavoManipulationMpcFrame: Current manipulation MPC frame.
182
+ """
183
+ return self._rs_core.manipulation_mpc_frame
184
+
185
+ def head_joint_state(self) -> KuavoJointData:
186
+ """Get the current state of the robot head joints.
187
+
188
+ Gets the current state data for the robot's head joints, including position,
189
+ velocity, torque and acceleration values.
190
+
191
+ Returns:
192
+ KuavoJointData: A data structure containing the head joint states:
193
+ position (list[float]): Joint positions in radians, length=head_dof(2)
194
+ velocity (list[float]): Joint velocities in rad/s, length=head_dof(2)
195
+ torque (list[float]): Joint torques in Nm, length=head_dof(2)
196
+ acceleration (list[float]): Joint accelerations in rad/s^2, length=head_dof(2)
197
+
198
+ The joint order is [yaw, pitch].
199
+ """
200
+ # Get head joint states from last 2 indices
201
+ head_joint_indices = range(len(self._rs_core.joint_data.position)-2, len(self._rs_core.joint_data.position))
202
+ return KuavoJointData(
203
+ position=[self._rs_core.joint_data.position[i] for i in head_joint_indices],
204
+ velocity=[self._rs_core.joint_data.velocity[i] for i in head_joint_indices],
205
+ torque=[self._rs_core.joint_data.torque[i] for i in head_joint_indices],
206
+ acceleration=[self._rs_core.joint_data.acceleration[i] for i in head_joint_indices]
207
+ )
208
+
209
+ def waist_joint_state(self, waist_dof:int) -> KuavoJointData:
210
+ """获取机器人腰部关节的当前状态
211
+ 获取机器人头部关节的当前状态数据,包括位置、速度、扭矩和加速度值。
212
+
213
+ Returns:
214
+ KuavoJointData: 包含头部关节状态的数据结构:
215
+ * position (list[float]): 关节位置,单位为弧度,长度=waist_dof
216
+ * velocity (list[float]): 关节速度,单位为rad/s,长度=waist_dof
217
+ * torque (list[float]): 关节扭矩,单位为Nm,长度=waist_dof
218
+ * acceleration (list[float]): 关节加速度,单位为rad/s^2,长度=waist_dof
219
+
220
+ """
221
+ # 环境判断
222
+ if env == 'real':
223
+ jointData = self._rs_core.joint_data
224
+ elif env == 'mujoco':
225
+ jointData = self._rs_core.joint_data
226
+ elif env == 'gazebo':
227
+ jointData = self._rs_core.joint_data_shm
228
+ else:
229
+ raise ValueError(f"Invalid environment: {self.env}")
230
+
231
+ # Get waist joint states from 13 indices
232
+ waist_joint_indices = range(12, 12+waist_dof)
233
+ return KuavoJointData(
234
+ position=[jointData.position[i] for i in waist_joint_indices],
235
+ velocity=[jointData.velocity[i] for i in waist_joint_indices],
236
+ torque=[jointData.torque[i] for i in waist_joint_indices],
237
+ acceleration=[jointData.acceleration[i] for i in waist_joint_indices]
238
+ )
239
+
240
+ def eef_state(self)->Tuple[EndEffectorState, EndEffectorState]:
241
+ """Get the current state of the robot's end effectors.
242
+
243
+ Returns:
244
+ Tuple[EndEffectorState, EndEffectorState]: A tuple containing the state of the left and right end effectors.
245
+ Each EndEffectorState contains:
246
+ - position: (float, float, float) - XYZ position in meters
247
+ - orientation: (float, float, float, float) - Quaternion orientation
248
+ - state: EndEffectorState.GraspingState - Current grasping state (UNKNOWN, OPEN, CLOSED)
249
+ """
250
+ return copy.deepcopy(self._rs_core.eef_state)
251
+
252
+ def gait_name(self)->str:
253
+ """Get the current gait name of the robot.
254
+
255
+ Returns:
256
+ str: The name of the current gait, e.g. 'trot', 'walk', 'stance', 'custom_gait'.
257
+ """
258
+ return self._rs_core.gait_name()
259
+
260
+
261
+ def is_stance(self) -> bool:
262
+ """Check if the robot is currently in stance mode.
263
+
264
+ Returns:
265
+ bool: True if robot is in stance mode, False otherwise.
266
+ """
267
+ return self._rs_core.is_gait('stance')
268
+
269
+ def is_walk(self) -> bool:
270
+ """Check if the robot is currently in walk mode.
271
+
272
+ Returns:
273
+ bool: True if robot is in walk mode, False otherwise.
274
+ """
275
+ return self._rs_core.is_gait('walk')
276
+
277
+ def is_step_control(self) -> bool:
278
+ """Check if the robot is currently in step control mode.
279
+
280
+ Returns:
281
+ bool: True if robot is in step control mode, False otherwise.
282
+ """
283
+ return self._rs_core.is_gait('custom_gait')
284
+
285
+ def wait_for_stance(self, timeout:float=5.0)->bool:
286
+ """Wait for the robot to enter stance state.
287
+
288
+ Args:
289
+ timeout (float): The maximum time to wait for the robot to enter stance state in seconds.
290
+
291
+ Returns:
292
+ bool: True if the robot enters stance state within the specified timeout, False otherwise.
293
+ """
294
+ wait_time = 0
295
+ while not self._rs_core.is_gait('stance') and wait_time < timeout:
296
+ time.sleep(0.1)
297
+ wait_time += 0.1
298
+ return self._rs_core.is_gait('stance')
299
+
300
+ def wait_for_trot(self, timeout:float=5.0)->bool:
301
+ """Wait for the robot to enter trot state.
302
+
303
+ Args:
304
+ timeout (float): The maximum time to wait for the robot to enter trot state in seconds.
305
+
306
+ Returns:
307
+ bool: True if the robot enters trot state within the specified timeout, False otherwise.
308
+ """
309
+ return self.wait_for_walk(timeout=timeout)
310
+
311
+ def wait_for_walk(self, timeout:float=5.0)->bool:
312
+ """Wait for the robot to enter walk state.
313
+
314
+ Args:
315
+ timeout (float): The maximum time to wait for the robot to enter walk state in seconds.
316
+
317
+ Returns:
318
+ bool: True if the robot enters walk state within the specified timeout, False otherwise.
319
+ """
320
+ wait_time = 0
321
+ while not self._rs_core.is_gait('walk') and wait_time < timeout:
322
+ time.sleep(0.1)
323
+ wait_time += 0.1
324
+ return self._rs_core.is_gait('walk')
325
+
326
+ def wait_for_step_control(self, timeout:float=5.0)->bool:
327
+ """Wait for the robot to enter step control state.
328
+
329
+ Args:
330
+ timeout (float): The maximum time to wait for the robot to enter step control state in seconds.
331
+
332
+ Returns:
333
+ bool: True if the robot enters step control state within the specified timeout, False otherwise.
334
+ """
335
+ wait_time = 0
336
+ while not self._rs_core.is_gait('custom_gait') and wait_time < timeout:
337
+ time.sleep(0.1)
338
+ wait_time += 0.1
339
+ return self._rs_core.is_gait('custom_gait')
340
+
341
+ # if __name__ == "__main__":
342
+ # state = KuavoRobotState()
343
+ # print(state.manipulation_mpc_frame())
344
+ # print(state.manipulation_mpc_control_flow())
345
+ # print(state.manipulation_mpc_ctrl_mode())
346
+ # print(state.arm_control_mode())
@@ -0,0 +1,58 @@
1
+ #!/usr/bin/env python3
2
+ # coding: utf-8
3
+ import math
4
+ from kuavo_humanoid_sdk.common.logger import SDKLogger
5
+ from kuavo_humanoid_sdk.interfaces.data_types import (PoseQuaternion, HomogeneousMatrix)
6
+ from kuavo_humanoid_sdk.kuavo.core.ros.tools import KuavoRobotToolsCoreWebsocket
7
+ from typing import Union
8
+
9
+ class KuavoRobotTools:
10
+ """机器人工具类,提供坐标系转换接口。
11
+
12
+ 该类封装了不同机器人坐标系之间的坐标变换查询功能,支持多种返回数据格式。
13
+ """
14
+
15
+ def __init__(self):
16
+ self.tools_core = KuavoRobotToolsCoreWebsocket()
17
+
18
+ def get_tf_transform(self, target_frame: str, source_frame: str,
19
+ return_type: str = "pose_quaternion") -> Union[PoseQuaternion, HomogeneousMatrix, None]:
20
+ """获取指定坐标系之间的变换。
21
+
22
+ Args:
23
+ target_frame (str): 目标坐标系名称
24
+ source_frame (str): 源坐标系名称
25
+ return_type (str, optional): 返回数据格式类型。有效值: \n
26
+ - "pose_quaternion" : 四元数姿态格式, \n
27
+ - "homogeneous" : 齐次矩阵格式。默认为"pose_quaternion"。\n
28
+
29
+ Returns:
30
+ Union[PoseQuaternion, HomogeneousMatrix, None]:
31
+ 指定格式的变换数据,如果失败则返回None
32
+
33
+ Raises:
34
+ ValueError: 如果提供了无效的 return_type
35
+ """
36
+ return self.tools_core._get_tf_tree_transform(target_frame, source_frame, return_type=return_type)
37
+
38
+ def get_base_to_odom(self, return_type: str = "pose_quaternion") -> Union[PoseQuaternion, HomogeneousMatrix, None]:
39
+ """获取从base_link到odom坐标系的变换。
40
+
41
+ Args:
42
+ return_type (str, optional): 返回格式类型。与get_tf_transform相同,默认为"pose_quaternion"。
43
+
44
+ Returns:
45
+ Union[PoseQuaternion, HomogeneousMatrix, None]: 变换数据或 None
46
+ """
47
+ return self.get_tf_transform("odom", "base_link", return_type)
48
+
49
+ def get_camera_to_base(self, return_type: str = "homogeneous") -> Union[PoseQuaternion, HomogeneousMatrix, None]:
50
+ """获取从camera_link到base_link坐标系的变换。
51
+
52
+ Args:
53
+ return_type (str, optional): 返回格式类型。与get_tf_transform相同,默认为"homogeneous"。
54
+
55
+ Returns:
56
+ Union[PoseQuaternion, HomogeneousMatrix, None]: 变换数据或None
57
+ """
58
+ return self.get_tf_transform("base_link", "camera_link", return_type)
@@ -0,0 +1,82 @@
1
+ #!/usr/bin/env python3
2
+ # coding: utf-8
3
+ import math
4
+ from kuavo_humanoid_sdk.common.logger import SDKLogger
5
+ from kuavo_humanoid_sdk.interfaces.data_types import (AprilTagData)
6
+ from kuavo_humanoid_sdk.kuavo.core.ros.vision import KuavoRobotVisionCoreWebsocket
7
+
8
+
9
+ class KuavoRobotVision:
10
+ """Kuavo机器人视觉系统接口。
11
+
12
+ 提供从不同坐标系获取AprilTag检测数据的接口。
13
+ """
14
+
15
+ def __init__(self, robot_type: str = "kuavo"):
16
+ """初始化视觉系统。
17
+
18
+ Args:
19
+ robot_type (str, optional): 机器人类型标识符。默认为"kuavo"
20
+ """
21
+ if not hasattr(self, '_initialized'):
22
+ self._vision_core = KuavoRobotVisionCoreWebsocket()
23
+
24
+ def get_data_by_id(self, target_id: int, data_source: str = "base") -> dict:
25
+ """获取指定ID的AprilTag检测数据。
26
+
27
+ Args:
28
+ target_id (int): 要检索的AprilTag ID
29
+ data_source (str, optional): 数据源坐标系。可以是"base"、"camera"或"odom"。默认为"base"。
30
+
31
+ Returns:
32
+ dict: 包含位置、方向和元数据的检测数据
33
+ """
34
+ return self._vision_core._get_data_by_id(target_id, data_source)
35
+
36
+ def get_data_by_id_from_camera(self, target_id: int) -> dict:
37
+ """从相机坐标系获取AprilTag数据。
38
+
39
+ Args:
40
+ target_id (int): 要检索的AprilTag ID
41
+
42
+ Returns:
43
+ dict: 包含位置、方向和元数据的检测数据。参见 :meth:`get_data_by_id` 的返回格式说明。
44
+ """
45
+ return self._vision_core._get_data_by_id(target_id, "camera")
46
+
47
+ def get_data_by_id_from_base(self, target_id: int) -> dict:
48
+ """从基座坐标系获取AprilTag数据。
49
+
50
+ Args:
51
+ target_id (int): 要检索的AprilTag ID
52
+
53
+ Returns:
54
+ dict: 包含位置、方向和元数据的检测数据。参见 :meth:`get_data_by_id` 的返回格式说明。
55
+ """
56
+ return self._vision_core._get_data_by_id(target_id, "base")
57
+
58
+ def get_data_by_id_from_odom(self, target_id: int) -> dict:
59
+ """从里程计坐标系获取AprilTag数据。
60
+
61
+ Args:
62
+ target_id (int): 要检索的AprilTag ID
63
+
64
+ Returns:
65
+ dict: 包含位置、方向和元数据的检测数据。参见 :meth:`get_data_by_id` 的返回格式说明。
66
+ """
67
+ return self._vision_core._get_data_by_id(target_id, "odom")
68
+
69
+ @property
70
+ def apriltag_data_from_camera(self) -> AprilTagData:
71
+ """AprilTagData: 相机坐标系中检测到的所有AprilTag(属性)"""
72
+ return self._vision_core.apriltag_data_from_camera
73
+
74
+ @property
75
+ def apriltag_data_from_base(self) -> AprilTagData:
76
+ """AprilTagData: 基座坐标系中检测到的所有AprilTag(属性)"""
77
+ return self._vision_core.apriltag_data_from_base
78
+
79
+ @property
80
+ def apriltag_data_from_odom(self) -> AprilTagData:
81
+ """AprilTagData: 里程计坐标系中检测到的所有AprilTag(属性)"""
82
+ return self._vision_core.apriltag_data_from_odom
@@ -0,0 +1,53 @@
1
+ #!/usr/bin/env python3
2
+ # coding: utf-8
3
+ import math
4
+ from kuavo_humanoid_sdk.kuavo.core.core import KuavoRobotCore
5
+ from kuavo_humanoid_sdk.common.logger import SDKLogger
6
+
7
+
8
+ class KuavoRobotWaist:
9
+ """
10
+ Control the waist of the robot.
11
+
12
+ The waist has 1 DOF: yaw (rotation around Z-axis).
13
+ The value is published to the topic `/robot_waist_motion_data`
14
+ as a Float64MultiArray: [yaw_degrees]
15
+ """
16
+
17
+ def __init__(self):
18
+ self._kuavo_core = KuavoRobotCore()
19
+
20
+ # Waist angle limit in degrees (recommended: -180° to +180°)
21
+ self.WAIST_LIMIT_DEG = 180
22
+
23
+ def control_waist(self, yaw: float) -> bool:
24
+ """
25
+ Control the waist of the robot.
26
+
27
+ Args:
28
+ yaw (float): The yaw angle of the waist in **degrees**.
29
+ Valid range: [-180, 180] degrees.
30
+ Values outside this range will be automatically limited.
31
+
32
+ Returns:
33
+ bool: True if the waist is controlled successfully, False otherwise.
34
+ """
35
+
36
+ # Normalize input: must be float
37
+ if not isinstance(yaw, (int, float)):
38
+ raise TypeError("yaw must be a float value representing degrees.")
39
+
40
+ # --- Check yaw limit (degrees) ---
41
+ if yaw < -self.WAIST_LIMIT_DEG or yaw > self.WAIST_LIMIT_DEG:
42
+ SDKLogger.warn(
43
+ f"[Robot] waist yaw {yaw}° exceeds limit "
44
+ f"[{-self.WAIST_LIMIT_DEG}, {self.WAIST_LIMIT_DEG}]°, will be limited"
45
+ )
46
+
47
+ # Apply limits
48
+ limited_yaw = min(self.WAIST_LIMIT_DEG, max(-self.WAIST_LIMIT_DEG, yaw))
49
+
50
+ # Convert to list format expected by lower-level interface
51
+ yaw_list = [limited_yaw]
52
+
53
+ return self._kuavo_core.control_robot_waist(yaw_list)
@@ -0,0 +1,2 @@
1
+ from .kuavo_strategy import *
2
+ from .grasp_box.grasp_box_strategy import *