kuavo-humanoid-sdk-ws 1.3.1b98__20260105150334-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 (42) 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 +11 -0
  11. kuavo_humanoid_sdk/kuavo/core/audio.py +32 -0
  12. kuavo_humanoid_sdk/kuavo/core/core.py +602 -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 +1045 -0
  17. kuavo_humanoid_sdk/kuavo/core/ros/observation.py +125 -0
  18. kuavo_humanoid_sdk/kuavo/core/ros/param.py +246 -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 +233 -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 +526 -0
  27. kuavo_humanoid_sdk/kuavo/robot_arm.py +192 -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 +114 -0
  31. kuavo_humanoid_sdk/kuavo/robot_observation.py +69 -0
  32. kuavo_humanoid_sdk/kuavo/robot_state.py +303 -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_strategy/__init__.py +2 -0
  36. kuavo_humanoid_sdk/kuavo_strategy/grasp_box/grasp_box_strategy.py +418 -0
  37. kuavo_humanoid_sdk/kuavo_strategy/kuavo_strategy.py +63 -0
  38. kuavo_humanoid_sdk/msg/__init__.py +4 -0
  39. kuavo_humanoid_sdk_ws-1.3.1b98.dist-info/METADATA +276 -0
  40. kuavo_humanoid_sdk_ws-1.3.1b98.dist-info/RECORD +42 -0
  41. kuavo_humanoid_sdk_ws-1.3.1b98.dist-info/WHEEL +6 -0
  42. kuavo_humanoid_sdk_ws-1.3.1b98.dist-info/top_level.txt +1 -0
@@ -0,0 +1,526 @@
1
+ #!/usr/bin/env python3
2
+ # coding: utf-8
3
+ from kuavo_humanoid_sdk.kuavo.core.ros_env import KuavoROSEnvWebsocket
4
+ from kuavo_humanoid_sdk.interfaces.robot import RobotBase
5
+ from kuavo_humanoid_sdk.common.logger import SDKLogger, disable_sdk_logging
6
+ from kuavo_humanoid_sdk.interfaces.data_types import KuavoPose, KuavoIKParams, KuavoManipulationMpcFrame, KuavoManipulationMpcCtrlMode, KuavoManipulationMpcControlFlow
7
+ from kuavo_humanoid_sdk.kuavo.core.core import KuavoRobotCore
8
+
9
+ from typing import Tuple
10
+ from kuavo_humanoid_sdk.kuavo.robot_info import KuavoRobotInfo
11
+ from kuavo_humanoid_sdk.kuavo.robot_arm import KuavoRobotArm
12
+ from kuavo_humanoid_sdk.kuavo.robot_head import KuavoRobotHead
13
+ from kuavo_humanoid_sdk.common.websocket_kuavo_sdk import WebSocketKuavoSDK
14
+ from kuavo_humanoid_sdk.common.launch_robot_tool import LaunchRobotTool
15
+
16
+ """
17
+ Kuavo SDK - Python Interface for Kuavo Robot Control
18
+
19
+ This module provides the main interface for controlling Kuavo robots through Python.
20
+ It includes two main classes:
21
+
22
+ KuavoSDK:
23
+ A static class providing SDK initialization and configuration functionality.
24
+ Handles core setup, ROS environment initialization, and logging configuration.
25
+
26
+ KuavoRobot:
27
+ The main robot control interface class that provides access to:
28
+ - Robot information and status (via KuavoRobotInfo)
29
+ - Arm control capabilities (via KuavoRobotArm)
30
+ - Head control capabilities (via KuavoRobotHead)
31
+ - Core robot functions (via KuavoRobotCore)
32
+
33
+ The module requires a properly configured ROS environment to function.
34
+ """
35
+ __all__ = ["KuavoSDK", "KuavoRobot"]
36
+
37
+
38
+ class KuavoSDK:
39
+ class Options:
40
+ Normal = 0x01
41
+ WithIK = 0x02
42
+
43
+ def __init__(self):
44
+ pass
45
+
46
+ @staticmethod
47
+ def Init(options:int=Options.Normal, log_level: str = "INFO",
48
+ websocket_mode: bool = False, websocket_host='127.0.0.1', websocket_port=9090, websocket_timeout=5)-> bool:
49
+ """Initialize the SDK.
50
+
51
+ Initializes the Kuavo SDK with specified options and configuration.
52
+
53
+ Args:
54
+ options (int): Configuration options for the SDK. Use KuavoSDK.Options constants.
55
+ Defaults to Options.Normal.
56
+ log_level (str): Logging level to use. Options are "ERROR", "WARN", "INFO", "DEBUG".
57
+ Defaults to "INFO".
58
+ websocket_mode (bool): Whether to use websocket mode for ROS communication.
59
+ If True, connects to ROS through websocket instead of direct connection.
60
+ Defaults to False.
61
+ websocket_host (str): Host address of the rosbridge websocket server.
62
+ Only used when websocket_mode is True. Defaults to "127.0.0.1".
63
+ websocket_port (int): Port number of the rosbridge websocket server.
64
+ Only used when websocket_mode is True. Defaults to 9090.
65
+ websocket_timeout (int): Timeout in seconds for the websocket connection.
66
+ Defaults to 5.
67
+
68
+ Returns:
69
+ bool: True if initialization succeeds, False otherwise.
70
+
71
+ Raises:
72
+ RuntimeError: If initialization fails due to missing dependencies or
73
+ connection issues.
74
+ """
75
+ WebSocketKuavoSDK.use_websocket = websocket_mode
76
+ WebSocketKuavoSDK.websocket_host = websocket_host
77
+ WebSocketKuavoSDK.websocket_port = websocket_port
78
+ WebSocketKuavoSDK.websocket_timeout = websocket_timeout
79
+ SDKLogger.setLevel(log_level.upper())
80
+ SDKLogger.debug(f" ================= Kuavo Humanoid Websocket SDK =================")
81
+
82
+ def launch_robot()->bool:
83
+ import time
84
+ import os
85
+ start_time = time.time()
86
+ launch_robot_tool = LaunchRobotTool()
87
+
88
+ # 获取机器人启动状态
89
+ success, status = launch_robot_tool.get_robot_launch_status()
90
+ if not success:
91
+ # 可能websocket服务未启动或网络不通原因
92
+ SDKLogger.error(f"[SDK] Failed to get robot launch status: {status}")
93
+ return False
94
+
95
+ SDKLogger.info(f"[SDK] Robot launch status: {status}, time elapsed: {time.time() - start_time:.2f}s")
96
+
97
+ # 如果机器人已经启动,则直接返回True
98
+ if launch_robot_tool.is_launched(status):
99
+ return True
100
+
101
+ # 未启动则启动
102
+ if launch_robot_tool.is_unlaunch(status):
103
+ print("\033[32m\n>_ 温馨提示: 机器人未启动,现在可以选择手动启动,如果需要请输入 y ,否则输入 n 退出\033[0m")
104
+ try:
105
+ while True:
106
+ choice = input().lower()
107
+ if choice == 'y':
108
+ if not launch_robot_tool.robot_start():
109
+ SDKLogger.error("机器人启动失败,请检查机器人状态")
110
+ os._exit(1)
111
+ break
112
+ elif choice == 'n':
113
+ SDKLogger.warning("用户选择不启动机器人,程序退出。")
114
+ os._exit(1)
115
+ else:
116
+ SDKLogger.error("输入错误,请输入 y 或 n")
117
+ except KeyboardInterrupt:
118
+ os._exit(1)
119
+
120
+ SDKLogger.debug(f"等待机器人启动,已耗时: {time.time() - start_time:.2f}s")
121
+
122
+ if not launch_robot_tool.robot_stand():
123
+ SDKLogger.error("机器人站立失败,请检查机器人状态")
124
+ os._exit(1)
125
+
126
+ end_time = time.time()
127
+ SDKLogger.info(f"[SDK] Robot launch time: {end_time - start_time} seconds")
128
+ return True
129
+
130
+ # Launch robot
131
+ if not launch_robot():
132
+ SDKLogger.error("[SDK] Failed to launch robot.")
133
+ return False
134
+
135
+ # Initialize core components, connect ROS Topics...
136
+ kuavo_core = KuavoRobotCore()
137
+ if log_level.upper() == 'DEBUG':
138
+ debug = True
139
+ else:
140
+ debug = False
141
+ # Check if IK option is enabled
142
+ if options & KuavoSDK.Options.WithIK:
143
+ if not KuavoROSEnvWebsocket.check_rosnode_exists('/arms_ik_node'):
144
+ print("\033[31m\nError:WithIK option is enabled but ik_node is not running, please run `roslaunch motion_capture_ik ik_node.launch`\033[0m")
145
+ exit(1)
146
+
147
+ if not kuavo_core.initialize(debug=debug):
148
+ SDKLogger.error("[SDK] Failed to initialize core components.")
149
+ return False
150
+
151
+ return True
152
+
153
+ @staticmethod
154
+ def DisableLogging():
155
+ """Disable all logging output from the SDK."""
156
+ disable_sdk_logging()
157
+
158
+ @staticmethod
159
+ def StopRobot()->bool:
160
+ """Stop the robot."""
161
+ launch_robot_tool = LaunchRobotTool()
162
+ success, status = launch_robot_tool.get_robot_launch_status()
163
+ if not success:
164
+ SDKLogger.error(f"[SDK] Failed to get robot launch status: {status}")
165
+ return False
166
+ if launch_robot_tool.is_unlaunch(status):
167
+ return True
168
+ return launch_robot_tool.robot_stop()
169
+
170
+ class KuavoRobot(RobotBase):
171
+ def __init__(self):
172
+ super().__init__(robot_type="kuavo")
173
+
174
+ kuavo_ros_env = KuavoROSEnvWebsocket()
175
+ if not kuavo_ros_env.Init():
176
+ raise RuntimeError("Failed to initialize ROS environment")
177
+
178
+ self._robot_info = KuavoRobotInfo()
179
+ self._robot_arm = KuavoRobotArm()
180
+ self._robot_head = KuavoRobotHead()
181
+ self._kuavo_core = KuavoRobotCore()
182
+ def stance(self)->bool:
183
+ """Put the robot into 'stance' mode.
184
+
185
+ Returns:
186
+ bool: True if the robot is put into stance mode successfully, False otherwise.
187
+
188
+ Note:
189
+ You can call :meth:`KuavoRobotState.wait_for_stance` to wait until the robot enters stance mode.
190
+ """
191
+ return self._kuavo_core.to_stance()
192
+
193
+ def trot(self)->bool:
194
+ """Put the robot into 'trot' mode.
195
+
196
+ Returns:
197
+ bool: True if the robot is put into trot mode successfully, False otherwise.
198
+
199
+ Note:
200
+ You can call :meth:`KuavoRobotState.wait_for_walk` to wait until the robot enters trot mode.
201
+ """
202
+ return self._kuavo_core.to_trot()
203
+
204
+ def walk(self, linear_x:float, linear_y:float, angular_z:float)->bool:
205
+ """Control the robot's motion.
206
+
207
+ Args:
208
+ linear_x (float): The linear velocity along the x-axis in m/s, range [-0.4, 0.4].
209
+ linear_y (float): The linear velocity along the y-axis in m/s, range [-0.2, 0.2].
210
+ angular_z (float): The angular velocity around the z-axis in rad/s, range [-0.4, 0.4].
211
+
212
+ Returns:
213
+ bool: True if the motion is controlled successfully, False otherwise.
214
+
215
+ Note:
216
+ You can call :meth:`KuavoRobotState.wait_for_walk` to wait until the robot enters walk mode.
217
+ """
218
+ # Limit velocity ranges
219
+ limited_linear_x = min(0.4, max(-0.4, linear_x))
220
+ limited_linear_y = min(0.2, max(-0.2, linear_y))
221
+ limited_angular_z = min(0.4, max(-0.4, angular_z))
222
+
223
+ # Check if any velocity exceeds limits.
224
+ if abs(linear_x) > 0.4:
225
+ SDKLogger.warn(f"[Robot] linear_x velocity {linear_x} exceeds limit [-0.4, 0.4], will be limited")
226
+ if abs(linear_y) > 0.2:
227
+ SDKLogger.warn(f"[Robot] linear_y velocity {linear_y} exceeds limit [-0.2, 0.2], will be limited")
228
+ if abs(angular_z) > 0.4:
229
+ SDKLogger.warn(f"[Robot] angular_z velocity {angular_z} exceeds limit [-0.4, 0.4], will be limited")
230
+ return self._kuavo_core.walk(limited_linear_x, limited_linear_y, limited_angular_z)
231
+
232
+ def jump(self):
233
+ """Jump the robot."""
234
+ pass
235
+
236
+ def squat(self, height: float, pitch: float=0.0)->bool:
237
+ """Control the robot's squat height and pitch.
238
+ Args:
239
+ height (float): The height offset from normal standing height in meters, range [-0.35, 0.0],Negative values indicate squatting down.
240
+ pitch (float): The pitch angle of the robot's torso in radians, range [-0.4, 0.4].
241
+
242
+ Returns:
243
+ bool: True if the squat is controlled successfully, False otherwise.
244
+ """
245
+ # Limit height range
246
+ MAX_HEIGHT = 0.0
247
+ MIN_HEIGHT = -0.35
248
+ MAX_PITCH = 0.4
249
+ MIN_PITCH = -0.4
250
+
251
+ limited_height = min(MAX_HEIGHT, max(MIN_HEIGHT, height))
252
+
253
+ # Check if height exceeds limits
254
+ if height > MAX_HEIGHT or height < MIN_HEIGHT:
255
+ SDKLogger.warn(f"[Robot] height {height} exceeds limit [{MIN_HEIGHT}, {MAX_HEIGHT}], will be limited")
256
+ # Limit pitch range
257
+ limited_pitch = min(MAX_PITCH, max(MIN_PITCH, pitch))
258
+
259
+ # Check if pitch exceeds limits
260
+ if abs(pitch) > MAX_PITCH:
261
+ SDKLogger.warn(f"[Robot] pitch {pitch} exceeds limit [{MIN_PITCH}, {MAX_PITCH}], will be limited")
262
+
263
+ return self._kuavo_core.squat(limited_height, limited_pitch)
264
+
265
+ def step_by_step(self, target_pose:list, dt:float=0.4, is_left_first_default:bool=True, collision_check:bool=True)->bool:
266
+ """Control the robot's motion by step.
267
+
268
+ Args:
269
+ target_pose (list): The target position of the robot in [x, y, z, yaw] m, rad.
270
+ dt (float): The time interval between each step in seconds. Defaults to 0.4s.
271
+ is_left_first_default (bool): Whether to start with the left foot. Defaults to True.
272
+ collision_check (bool): Whether to check for collisions. Defaults to True.
273
+
274
+ Returns:
275
+ bool: True if motion is successful, False otherwise.
276
+
277
+ Raises:
278
+ RuntimeError: If the robot is not in stance state when trying to control step motion.
279
+ ValueError: If target_pose length is not 4.
280
+
281
+ Note:
282
+ You can call :meth:`KuavoRobotState.wait_for_step_control` to wait until the robot enters step-control mode.
283
+ You can call :meth:`KuavoRobotState.wait_for_stance` to wait the step-control finish.
284
+ """
285
+ if len(target_pose) != 4:
286
+ raise ValueError(f"[Robot] target_pose length must be 4 (x, y, z, yaw), but got {len(target_pose)}")
287
+
288
+ return self._kuavo_core.step_control(target_pose, dt, is_left_first_default, collision_check)
289
+
290
+ def control_command_pose(self, target_pose_x: float, target_pose_y: float, target_pose_z: float, target_pose_yaw: float) -> bool:
291
+ """Control robot pose in base_link frame.
292
+
293
+ Args:
294
+ target_pose_x (float): The target x position in meters.
295
+ target_pose_y (float): The target y position in meters.
296
+ target_pose_z (float): The target z position in meters.
297
+ target_pose_yaw (float): The target yaw angle in radians.
298
+
299
+ Returns:
300
+ bool: True if the command was sent successfully, False otherwise.
301
+
302
+ Raises:
303
+ RuntimeError: If the robot is not in stance state when trying to control pose.
304
+
305
+ Note:
306
+ This command changes the robot state to 'command_pose'.
307
+ """
308
+ return self._kuavo_core.control_command_pose(target_pose_x, target_pose_y, target_pose_z, target_pose_yaw)
309
+
310
+ def control_command_pose_world(self, target_pose_x: float, target_pose_y: float, target_pose_z: float, target_pose_yaw: float) -> bool:
311
+ """Control robot pose in odom (world) frame.
312
+
313
+ Args:
314
+ target_pose_x (float): The target x position in meters.
315
+ target_pose_y (float): The target y position in meters.
316
+ target_pose_z (float): The target z position in meters.
317
+ target_pose_yaw (float): The target yaw angle in radians.
318
+
319
+ Returns:
320
+ bool: True if the command was sent successfully, False otherwise.
321
+
322
+ Raises:
323
+ RuntimeError: If the robot is not in stance state when trying to control pose.
324
+
325
+ Note:
326
+ This command changes the robot state to 'command_pose_world'.
327
+ """
328
+ return self._kuavo_core.control_command_pose_world(target_pose_x, target_pose_y, target_pose_z, target_pose_yaw)
329
+
330
+ def control_head(self, yaw: float, pitch: float)->bool:
331
+ """Control the head of the robot.
332
+
333
+ Args:
334
+ yaw (float): The yaw angle of the head in radians, range [-1.396, 1.396] (-80 to 80 degrees).
335
+ pitch (float): The pitch angle of the head in radians, range [-0.436, 0.436] (-25 to 25 degrees).
336
+
337
+ Returns:
338
+ bool: True if the head is controlled successfully, False otherwise.
339
+ """
340
+ return self._robot_head.control_head(yaw=yaw, pitch=pitch)
341
+
342
+ def enable_head_tracking(self, target_id: int)->bool:
343
+ """Enable the head tracking.
344
+ """
345
+ return self._robot_head.enable_head_tracking(target_id)
346
+
347
+ def disable_head_tracking(self)->bool:
348
+ """Disable the head tracking.
349
+ """
350
+ return self._robot_head.disable_head_tracking()
351
+
352
+ """ Robot Arm Control """
353
+ def arm_reset(self)->bool:
354
+ """Reset the robot arm.
355
+
356
+ Returns:
357
+ bool: True if the arm is reset successfully, False otherwise.
358
+ """
359
+ return self._robot_arm.arm_reset()
360
+
361
+ def manipulation_mpc_reset(self)->bool:
362
+ """Reset the robot arm.
363
+
364
+ Returns:
365
+ bool: True if the arm is reset successfully, False otherwise.
366
+ """
367
+ return self._robot_arm.manipulation_mpc_reset()
368
+
369
+ def control_arm_joint_positions(self, joint_positions:list)->bool:
370
+ """Control the position of the arm.
371
+
372
+ Args:
373
+ joint_positions (list): The target position of the arm in radians.
374
+
375
+ Returns:
376
+ bool: True if the arm is controlled successfully, False otherwise.
377
+
378
+ Raises:
379
+ ValueError: If the joint position list is not of the correct length.
380
+ ValueError: If the joint position is outside the range of [-π, π].
381
+ RuntimeError: If the robot is not in stance state when trying to control the arm.
382
+ """
383
+ if len(joint_positions) != self._robot_info.arm_joint_dof:
384
+ print("The length of the position list must be equal to the number of DOFs of the arm.")
385
+ return False
386
+
387
+ return self._robot_arm.control_arm_joint_positions(joint_positions)
388
+
389
+ def control_arm_joint_trajectory(self, times:list, q_frames:list)->bool:
390
+ """Control the target poses of the robot arm.
391
+
392
+ Args:
393
+ times (list): List of time intervals in seconds.
394
+ q_frames (list): List of joint positions in radians.
395
+
396
+ Returns:
397
+ bool: True if the control was successful, False otherwise.
398
+
399
+ Raises:
400
+ ValueError: If the times list is not of the correct length.
401
+ ValueError: If the joint position list is not of the correct length.
402
+ ValueError: If the joint position is outside the range of [-π, π].
403
+ RuntimeError: If the robot is not in stance state when trying to control the arm.
404
+
405
+ Warning:
406
+ This is an asynchronous interface. The function returns immediately after sending the command.
407
+ Users need to wait for the motion to complete on their own.
408
+ """
409
+ return self._robot_arm.control_arm_joint_trajectory(times, q_frames)
410
+
411
+ def set_fixed_arm_mode(self) -> bool:
412
+ """Freezes the robot arm.
413
+
414
+ Returns:
415
+ bool: True if the arm is frozen successfully, False otherwise.
416
+ """
417
+ return self._robot_arm.set_fixed_arm_mode()
418
+
419
+ def set_auto_swing_arm_mode(self) -> bool:
420
+ """Swing the robot arm.
421
+
422
+ Returns:
423
+ bool: True if the arm is swinging successfully, False otherwise.
424
+ """
425
+ return self._robot_arm.set_auto_swing_arm_mode()
426
+
427
+ def set_external_control_arm_mode(self) -> bool:
428
+ """External control the robot arm.
429
+
430
+ Returns:
431
+ bool: True if the arm is external controlled successfully, False otherwise.
432
+ """
433
+ return self._robot_arm.set_external_control_arm_mode()
434
+
435
+ def set_manipulation_mpc_mode(self, ctrl_mode: KuavoManipulationMpcCtrlMode) -> bool:
436
+ """
437
+ Set the manipulation mpc mode.
438
+ Returns:
439
+ bool: True if the manipulation mpc mode is set successfully, False otherwise.
440
+ """
441
+ return self._robot_arm.set_manipulation_mpc_mode(ctrl_mode)
442
+
443
+ def set_manipulation_mpc_control_flow(self, control_flow: KuavoManipulationMpcControlFlow) -> bool:
444
+ """
445
+ Set the manipulation mpc control flow.
446
+ Returns:
447
+ bool: True if the manipulation mpc control flow is set successfully, False otherwise.
448
+ """
449
+ return self._robot_arm.set_manipulation_mpc_control_flow(control_flow)
450
+
451
+ def set_manipulation_mpc_frame(self, frame: KuavoManipulationMpcFrame) -> bool:
452
+ """
453
+ Set the manipulation mpc frame.
454
+ Returns:
455
+ bool: True if the manipulation mpc frame is set successfully, False otherwise.
456
+ """
457
+ return self._robot_arm.set_manipulation_mpc_frame(frame)
458
+
459
+ """ Arm Forward kinematics && Arm Inverse kinematics """
460
+ def arm_ik(self,
461
+ left_pose: KuavoPose,
462
+ right_pose: KuavoPose,
463
+ left_elbow_pos_xyz: list = [0.0, 0.0, 0.0],
464
+ right_elbow_pos_xyz: list = [0.0, 0.0, 0.0],
465
+ arm_q0: list = None,
466
+ params: KuavoIKParams=None) -> list:
467
+ """Inverse kinematics for the robot arm.
468
+
469
+ Args:
470
+ left_pose (KuavoPose): Pose of the robot left arm, xyz and quat.
471
+ right_pose (KuavoPose): Pose of the robot right arm, xyz and quat.
472
+ left_elbow_pos_xyz (list): Position of the robot left elbow. If [0.0, 0.0, 0.0], will be ignored.
473
+ right_elbow_pos_xyz (list): Position of the robot right elbow. If [0.0, 0.0, 0.0], will be ignored.
474
+ arm_q0 (list, optional): Initial joint positions in radians. If None, will be ignored.
475
+ params (KuavoIKParams, optional): Parameters for the inverse kinematics. If None, will be ignored.
476
+ Contains:
477
+ - major_optimality_tol: Major optimality tolerance
478
+ - major_feasibility_tol: Major feasibility tolerance
479
+ - minor_feasibility_tol: Minor feasibility tolerance
480
+ - major_iterations_limit: Major iterations limit
481
+ - oritation_constraint_tol: Orientation constraint tolerance
482
+ - pos_constraint_tol: Position constraint tolerance, works when pos_cost_weight==0.0
483
+ - pos_cost_weight: Position cost weight. Set to 0.0 for high accuracy
484
+
485
+ Returns:
486
+ list: List of joint positions in radians, or None if inverse kinematics failed.
487
+
488
+ Warning:
489
+ This function requires initializing the SDK with the :attr:`KuavoSDK.Options.WithIK`.
490
+ """
491
+ return self._robot_arm.arm_ik(left_pose, right_pose, left_elbow_pos_xyz, right_elbow_pos_xyz, arm_q0, params)
492
+
493
+ def arm_fk(self, q: list) -> Tuple[KuavoPose, KuavoPose]:
494
+ """Forward kinematics for the robot arm.
495
+
496
+ Args:
497
+ q (list): List of joint positions in radians.
498
+
499
+ Returns:
500
+ Tuple[KuavoPose, KuavoPose]: Tuple of poses for the robot left arm and right arm,
501
+ or (None, None) if forward kinematics failed.
502
+
503
+ Warning:
504
+ This function requires initializing the SDK with the :attr:`KuavoSDK.Options.WithIK`.
505
+ """
506
+ return self._robot_arm.arm_fk(q)
507
+
508
+ def control_robot_end_effector_pose(self, left_pose: KuavoPose, right_pose: KuavoPose, frame: KuavoManipulationMpcFrame)->bool:
509
+ """Control the end effector pose of the robot arm.
510
+
511
+ Args:
512
+ left_pose (KuavoPose): Pose of the robot left arm, xyz and quat.
513
+ right_pose (KuavoPose): Pose of the robot right arm, xyz and quat.
514
+ frame (KuavoManipulationMpcFrame): Frame of the robot arm.
515
+
516
+ Returns:
517
+ bool: True if the end effector pose is controlled successfully, False otherwise.
518
+ """
519
+ return self._robot_arm.control_robot_end_effector_pose(left_pose, right_pose, frame)
520
+
521
+ if __name__ == "__main__":
522
+ robot = KuavoRobot()
523
+ robot.set_manipulation_mpc_mode(KuavoManipulationMpcCtrlMode.ArmOnly)
524
+ robot.set_manipulation_mpc_control_flow(KuavoManipulationMpcControlFlow.DirectToWbc)
525
+ robot.set_manipulation_mpc_frame(KuavoManipulationMpcFrame.WorldFrame)
526
+ robot.control_robot_end_effector_pose(KuavoPose(position=[0.3, 0.4, 0.9], orientation=[0.0, 0.0, 0.0, 1.0]), KuavoPose(position=[0.3, -0.5, 1.0], orientation=[0.0, 0.0, 0.0, 1.0]), KuavoManipulationMpcFrame.WorldFrame)