kuavo-humanoid-sdk-ws 1.2.2__20250922181225-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 (41) hide show
  1. kuavo_humanoid_sdk/__init__.py +6 -0
  2. kuavo_humanoid_sdk/common/logger.py +45 -0
  3. kuavo_humanoid_sdk/common/websocket_kuavo_sdk.py +26 -0
  4. kuavo_humanoid_sdk/interfaces/__init__.py +4 -0
  5. kuavo_humanoid_sdk/interfaces/data_types.py +293 -0
  6. kuavo_humanoid_sdk/interfaces/end_effector.py +62 -0
  7. kuavo_humanoid_sdk/interfaces/robot.py +22 -0
  8. kuavo_humanoid_sdk/interfaces/robot_info.py +56 -0
  9. kuavo_humanoid_sdk/kuavo/__init__.py +11 -0
  10. kuavo_humanoid_sdk/kuavo/core/audio.py +32 -0
  11. kuavo_humanoid_sdk/kuavo/core/core.py +602 -0
  12. kuavo_humanoid_sdk/kuavo/core/dex_hand_control.py +114 -0
  13. kuavo_humanoid_sdk/kuavo/core/leju_claw_control.py +67 -0
  14. kuavo_humanoid_sdk/kuavo/core/ros/audio.py +86 -0
  15. kuavo_humanoid_sdk/kuavo/core/ros/control.py +1045 -0
  16. kuavo_humanoid_sdk/kuavo/core/ros/observation.py +125 -0
  17. kuavo_humanoid_sdk/kuavo/core/ros/param.py +246 -0
  18. kuavo_humanoid_sdk/kuavo/core/ros/sat_utils.py +103 -0
  19. kuavo_humanoid_sdk/kuavo/core/ros/state.py +426 -0
  20. kuavo_humanoid_sdk/kuavo/core/ros/tools.py +196 -0
  21. kuavo_humanoid_sdk/kuavo/core/ros/vision.py +280 -0
  22. kuavo_humanoid_sdk/kuavo/core/ros_env.py +233 -0
  23. kuavo_humanoid_sdk/kuavo/dexterous_hand.py +198 -0
  24. kuavo_humanoid_sdk/kuavo/leju_claw.py +232 -0
  25. kuavo_humanoid_sdk/kuavo/robot.py +462 -0
  26. kuavo_humanoid_sdk/kuavo/robot_arm.py +192 -0
  27. kuavo_humanoid_sdk/kuavo/robot_audio.py +39 -0
  28. kuavo_humanoid_sdk/kuavo/robot_head.py +39 -0
  29. kuavo_humanoid_sdk/kuavo/robot_info.py +114 -0
  30. kuavo_humanoid_sdk/kuavo/robot_observation.py +69 -0
  31. kuavo_humanoid_sdk/kuavo/robot_state.py +303 -0
  32. kuavo_humanoid_sdk/kuavo/robot_tool.py +58 -0
  33. kuavo_humanoid_sdk/kuavo/robot_vision.py +82 -0
  34. kuavo_humanoid_sdk/kuavo_strategy/__init__.py +2 -0
  35. kuavo_humanoid_sdk/kuavo_strategy/grasp_box/grasp_box_strategy.py +418 -0
  36. kuavo_humanoid_sdk/kuavo_strategy/kuavo_strategy.py +63 -0
  37. kuavo_humanoid_sdk/msg/__init__.py +4 -0
  38. kuavo_humanoid_sdk_ws-1.2.2.dist-info/METADATA +276 -0
  39. kuavo_humanoid_sdk_ws-1.2.2.dist-info/RECORD +41 -0
  40. kuavo_humanoid_sdk_ws-1.2.2.dist-info/WHEEL +6 -0
  41. kuavo_humanoid_sdk_ws-1.2.2.dist-info/top_level.txt +1 -0
@@ -0,0 +1,198 @@
1
+ #!/usr/bin/env python3
2
+ # coding: utf-8
3
+ from typing import Tuple
4
+ from kuavo_humanoid_sdk.interfaces.end_effector import EndEffector
5
+ from kuavo_humanoid_sdk.interfaces.data_types import EndEffectorSide, EndEffectorState, KuavoDexHandTouchState
6
+ from kuavo_humanoid_sdk.kuavo.core.dex_hand_control import DexHandControl
7
+ from kuavo_humanoid_sdk.kuavo.core.ros.state import KuavoRobotStateCoreWebsocket
8
+
9
+ class DexterousHand(EndEffector):
10
+ def __init__(self):
11
+ joint_names = ['l_thumb', 'l_thumb_aux', 'l_index', 'l_middle', 'l_ring', 'l_pinky',
12
+ 'r_thumb', 'r_thumb_aux', 'r_index', 'r_middle', 'r_ring', 'r_pinky',]
13
+ super().__init__(joint_names=joint_names)
14
+ self.dex_hand_control = DexHandControl()
15
+ self._rb_state = KuavoRobotStateCoreWebsocket()
16
+
17
+ def control(self, target_positions:list, target_velocities:list=None, target_torques:list=None)->bool:
18
+ """Set the position of the hand.
19
+
20
+ Args:
21
+ target_positions (list): List of target positions for all joints, length must be 12 (6 joints for each hand),
22
+ range => [0.0 ~ 100.0]
23
+ target_velocities (list, optional): Not supported. Defaults to None.
24
+ target_torques (list, optional): Not supported. Defaults to None.
25
+
26
+ Returns:
27
+ bool: True if control successful, False otherwise.
28
+
29
+ Note:
30
+ target_velocities and target_torques are not supported.
31
+ """
32
+ if len(target_positions) != self.joint_count():
33
+ raise ValueError(f"Target positions must have the same length as joint names {len(target_positions)} != {self.joint_count()}")
34
+
35
+ q = [max(0, min(100, pos if isinstance(pos, int) else int(pos))) for pos in target_positions]
36
+
37
+ # control the hand
38
+ return self.dex_hand_control.control(target_positions=q, side=EndEffectorSide.BOTH)
39
+
40
+ def control_right(self, target_positions:list, target_velocities:list=None, target_torques:list=None)->bool:
41
+ """Control the right dexterous hand.
42
+
43
+ Args:
44
+ target_positions (list): Target positions for right hand joints [0 ~ 100], length must be 6
45
+ target_velocities (list, optional): Not supported. Defaults to None.
46
+ target_torques (list, optional): Not supported. Defaults to None.
47
+
48
+ Returns:
49
+ bool: True if control successful, False otherwise.
50
+
51
+ Raises:
52
+ ValueError: If target positions length doesn't match joint count or values outside [0,100] range
53
+
54
+ Note:
55
+ target_velocities and target_torques are not supported.
56
+ """
57
+ if len(target_positions) != (self.joint_count()/2):
58
+ raise ValueError(f"Target positions must have the same length as joint names {len(target_positions)} != {self.joint_count()/2}.")
59
+
60
+ q = [max(0, min(100, pos if isinstance(pos, int) else int(pos))) for pos in target_positions]
61
+
62
+ return self.dex_hand_control.control(target_positions=q, side=EndEffectorSide.RIGHT)
63
+
64
+ def control_left(self, target_positions:list, target_velocities:list=None, target_torques:list=None)->bool:
65
+ """Control the left dexterous hand.
66
+
67
+ Args:
68
+ target_positions (list): Target positions for left hand joints [0 ~ 100], length must be 6
69
+ target_velocities (list, optional): Not supported. Defaults to None.
70
+ target_torques (list, optional): Not supported. Defaults to None.
71
+
72
+ Returns:
73
+ bool: True if control successful, False otherwise.
74
+
75
+ Raises:
76
+ ValueError: If target positions length doesn't match joint count or values outside [0,100] range
77
+
78
+ Note:
79
+ target_velocities and target_torques are not supported.
80
+ """
81
+ if len(target_positions) != (self.joint_count()/2):
82
+ raise ValueError(f"Target positions must have the same length as joint names {len(target_positions)} != {self.joint_count()/2}.")
83
+
84
+ q = [max(0, min(100, pos if isinstance(pos, int) else int(pos))) for pos in target_positions]
85
+
86
+ return self.dex_hand_control.control(target_positions=q, side=EndEffectorSide.LEFT)
87
+
88
+ def open(self, side: EndEffectorSide=EndEffectorSide.BOTH)->bool:
89
+ """Open the dexterous hand(s) by setting all joint positions to 0.
90
+
91
+ Args:
92
+ side (EndEffectorSide, optional): Which hand(s) to open. Defaults to EndEffectorSide.BOTH.
93
+ Can be LEFT, RIGHT, or BOTH.
94
+
95
+ Returns:
96
+ bool: True if open command sent successfully, False otherwise.
97
+ """
98
+ zero_pos = [0]*self.joint_count()
99
+ if side == EndEffectorSide.LEFT:
100
+ return self.dex_hand_control.control(target_positions=zero_pos[:len(zero_pos)//2], side=EndEffectorSide.LEFT)
101
+ elif side == EndEffectorSide.RIGHT:
102
+ return self.dex_hand_control.control(target_positions=zero_pos[len(zero_pos)//2:], side=EndEffectorSide.RIGHT)
103
+ else:
104
+ return self.dex_hand_control.control(target_positions=zero_pos, side=EndEffectorSide.BOTH)
105
+
106
+ def make_gesture(self, l_gesture_name: str, r_gesture_name: str)->bool:
107
+ """Make predefined gestures for both hands.
108
+
109
+ Args:
110
+ l_gesture_name (str): Name of gesture for left hand. None to skip left hand.
111
+ r_gesture_name (str): Name of gesture for right hand. None to skip right hand.
112
+
113
+ Returns:
114
+ bool: True if gesture command sent successfully, False otherwise.
115
+
116
+ Note:
117
+ gestures e.g.: 'fist', 'ok', 'thumbs_up', '666'...
118
+ """
119
+ gesture = []
120
+ if l_gesture_name is not None:
121
+ gesture.append({'gesture_name':l_gesture_name, 'hand_side':EndEffectorSide.LEFT})
122
+ self.dex_hand_control.make_gestures(gesture)
123
+ if r_gesture_name is not None:
124
+ gesture.append({'gesture_name':r_gesture_name, 'hand_side':EndEffectorSide.RIGHT})
125
+ self.dex_hand_control.make_gestures(gesture)
126
+ return True
127
+ def get_gesture_names(self)->list:
128
+ """Get the names of all gestures.
129
+
130
+ Returns:
131
+ list: List of gesture names.
132
+ e.g.: ['fist', 'ok', 'thumbs_up', '666', 'number_1', 'number_2', 'number_3', ... ],
133
+ None if no gestures.
134
+ """
135
+ return self.dex_hand_control.get_gesture_names()
136
+
137
+ def get_state(self)->Tuple[EndEffectorState, EndEffectorState]:
138
+ """Get the state of the dexterous hand.
139
+
140
+ Returns:
141
+ Tuple[EndEffectorState, EndEffectorState]: The state of the dexterous hand.
142
+ """
143
+ return self._rb_state.eef_state
144
+
145
+ def get_position(self)->Tuple[list, list]:
146
+ """Get the position of the dexterous hand.
147
+
148
+ Returns:
149
+ Tuple[list, list]: The position of the dexterous hand.
150
+ """
151
+ state = self._rb_state.eef_state
152
+ return (state[0].position, state[1].position)
153
+
154
+ def get_velocity(self)->Tuple[list, list]:
155
+ """Get the velocity of the dexterous hand.
156
+
157
+ Returns:
158
+ Tuple[list, list]: The velocity of the dexterous hand.
159
+ """
160
+ state = self._rb_state.eef_state
161
+ return (state[0].velocity, state[1].velocity)
162
+
163
+ def get_effort(self)->Tuple[list, list]:
164
+ """Get the effort of the dexterous hand.
165
+
166
+ Returns:
167
+ Tuple[list, list]: The effort of the dexterous hand.
168
+
169
+ Note:
170
+ 0 ~ 100 for each finger. Fraction of max motor current, absolute number.
171
+ The max motor current is 600mA, in a word, 100.
172
+ """
173
+ state = self._rb_state.eef_state
174
+ return (state[0].effort, state[1].effort)
175
+
176
+ def get_grasping_state(self)->Tuple[EndEffectorState.GraspingState, EndEffectorState.GraspingState]:
177
+ """Get the grasping state of the dexterous hand.
178
+
179
+ Note:
180
+ The grasping state is not implemented yet.
181
+
182
+ Returns:
183
+ Tuple[EndEffectorState.GraspingState, EndEffectorState.GraspingState]: The grasping state of the dexterous hand.
184
+ """
185
+ raise NotImplementedError("This function is not implemented yet")
186
+
187
+
188
+ class TouchDexterousHand(DexterousHand):
189
+ def __init__(self):
190
+ super().__init__()
191
+
192
+ def get_touch_state(self)-> Tuple[KuavoDexHandTouchState, KuavoDexHandTouchState]:
193
+ """Get the touch state of the dexterous hand.
194
+
195
+ Returns:
196
+ Tuple[KuavoDexHandTouchState, KuavoDexHandTouchState]
197
+ """
198
+ return self._rb_state.dexhand_touch_state
@@ -0,0 +1,232 @@
1
+ #!/usr/bin/env python3
2
+ # coding: utf-8
3
+ import time
4
+ from typing import Tuple
5
+ from kuavo_humanoid_sdk.interfaces.end_effector import EndEffector
6
+ from kuavo_humanoid_sdk.interfaces.data_types import EndEffectorSide, EndEffectorState
7
+ from kuavo_humanoid_sdk.kuavo.core.leju_claw_control import LejuClawControl
8
+ from kuavo_humanoid_sdk.kuavo.core.ros.state import KuavoRobotStateCoreWebsocket
9
+
10
+ class LejuClaw(EndEffector):
11
+ def __init__(self):
12
+ super().__init__(joint_names=['left_claw', 'right_claw'])
13
+ self.leju_claw_control = LejuClawControl()
14
+ self._rb_state = KuavoRobotStateCoreWebsocket()
15
+
16
+ def control(self, target_positions: list, target_velocities:list=None, target_torques: list=None)->bool:
17
+ """Control the claws to grip.
18
+
19
+ Args:
20
+ target_positions (list): The target positions of the claws.
21
+ target_velocities (list, optional): The target velocities of the claws. If None, default value [90, 90] will be used.
22
+ target_torques (list, optional): The target torques of the claws. If None, default value [1.0, 1.0] will be used.
23
+
24
+ Note:
25
+ The target_positions, target_velocities, target_torques must be a list of length `self.joint_count()`.
26
+ After calling this function, you can call wait_for_finish() to wait until the claws reach the target position.
27
+
28
+ Warning:
29
+ If the claws are still in motion from a previous command, this request may be dropped.
30
+
31
+ Returns:
32
+ bool: True if the claws are successfully gripped, False otherwise
33
+ """
34
+ if target_positions is None or len(target_positions) != self.joint_count():
35
+ raise ValueError("Target positions must be provided.")
36
+
37
+ target_positions = [max(0.0, min(100.0, pos)) for pos in target_positions]
38
+ if target_velocities is None:
39
+ target_velocities = [90, 90]
40
+ else:
41
+ if len(target_velocities) != self.joint_count():
42
+ raise ValueError("Target velocities must be a list of length 2.")
43
+ target_velocities = [max(0.0, min(100.0, vel)) for vel in target_velocities]
44
+
45
+ if target_torques is None:
46
+ target_torques = [1.0, 1.0]
47
+ else:
48
+ if len(target_torques) != self.joint_count():
49
+ raise ValueError("Target torques must be a list of length 2.")
50
+ target_torques = [max(0.0, min(10.0, torque)) for torque in target_torques]
51
+
52
+ return self.leju_claw_control.control(target_positions, target_velocities, target_torques, EndEffectorSide.BOTH)
53
+
54
+ def control_left(self, target_positions:list, target_velocities:list=None, target_torques:list=None)->bool:
55
+ """Control the left claw to grip.
56
+
57
+ Args:
58
+ target_positions (list): The target position of the left claw.
59
+ target_velocities (list, optional): The target velocity of the left claw. If None, default value 90 will be used.
60
+ target_torques (list, optional): The target torque of the left claw. If None, default value 1.0 will be used.
61
+
62
+ Note:
63
+ The target_positions, target_velocities, target_torques must be a list of length `self.joint_count()/2`.
64
+ After calling this function, you can call wait_for_finish() to wait until the claws reach the target position.
65
+
66
+ Warning:
67
+ If the claws are still in motion from a previous command, this request may be dropped.
68
+
69
+ Returns:
70
+ bool: True if the claw is successfully gripped, False otherwise.
71
+ """
72
+ if target_positions is None:
73
+ raise ValueError("Target positions must be provided.")
74
+
75
+ for data in [target_positions, target_velocities, target_torques]:
76
+ if data is not None and len(data) != self.joint_count()/2:
77
+ raise ValueError(f"Target data must be a list of length {self.joint_count()/2}.")
78
+
79
+ q = max(0.0, min(100.0, target_positions[0]))
80
+
81
+ if target_velocities is not None:
82
+ v = max(0.0, min(100.0, target_velocities[0]))
83
+ else:
84
+ v = 90
85
+
86
+ if target_torques is not None:
87
+ tau = max(0.0, min(10.0, target_torques[0]))
88
+ else:
89
+ tau = 1.0
90
+
91
+ return self.leju_claw_control.control([q], [v], [tau], EndEffectorSide.LEFT)
92
+
93
+ def control_right(self, target_positions:list, target_velocities:list=None, target_torques:list=None)->bool:
94
+ """Control the right claw to grip.
95
+
96
+ Args:
97
+ target_positions (list): The target position of the right claw.
98
+ target_velocities (list, optional): The target velocity of the right claw. If None, default value 90 will be used.
99
+ target_torques (list, optional): The target torque of the right claw. If None, default value 1.0 will be used.
100
+
101
+ Returns:
102
+ bool: True if the claw is successfully gripped, False otherwise.
103
+
104
+ Note:
105
+ The target_positions, target_velocities, target_torques must be a list of length `self.joint_count()/2`.
106
+ After calling this function, you can call wait_for_finish() to wait until the claws reach the target position.
107
+
108
+ Warning:
109
+ If the claws are still in motion from a previous command, this request may be dropped.
110
+ """
111
+ if target_positions is None:
112
+ raise ValueError("Target positions must be provided.")
113
+
114
+ for data in [target_positions, target_velocities, target_torques]:
115
+ if data is not None and len(data) != self.joint_count()/2:
116
+ raise ValueError(f"Target data must be a list of length {self.joint_count()/2}.")
117
+
118
+ q = max(0.0, min(100.0, target_positions[0]))
119
+
120
+ if target_velocities is not None:
121
+ v = max(0.0, min(100.0, target_velocities[0]))
122
+ else:
123
+ v = 90
124
+
125
+ if target_torques is not None:
126
+ tau = max(0.0, min(10.0, target_torques[0]))
127
+ else:
128
+ tau = 1.0
129
+
130
+ return self.leju_claw_control.control([q], [v], [tau], EndEffectorSide.RIGHT)
131
+
132
+ def open(self, side:EndEffectorSide=EndEffectorSide.BOTH)->bool:
133
+ """Control the claws to release/open.
134
+
135
+ Note:
136
+ Control the claws to open.
137
+ After calling this function, you can call wait_for_finish() to wait until the claws reach the target position.
138
+
139
+ Args:
140
+ side (EndEffectorSide, optional): The side to control. Defaults to EndEffectorSide.BOTH.
141
+
142
+ Returns:
143
+ bool: True if the claw is successfully released, False otherwise.
144
+ """
145
+ return self.leju_claw_control.release(side)
146
+
147
+ def close(self, side:EndEffectorSide=EndEffectorSide.BOTH)->bool:
148
+ """Control the claws to close/grip.
149
+
150
+ Note:
151
+ Control the claws to close.
152
+ After calling this function, you can call wait_for_finish() to wait until the claws reach the target position.
153
+
154
+ Args:
155
+ side (EndEffectorSide, optional): The side to control. Defaults to EndEffectorSide.BOTH.
156
+
157
+ Returns:
158
+ bool: True if the claw is successfully gripped, False otherwise.
159
+ """
160
+ return self.leju_claw_control.control(position=[100, 100], velocity=[90, 90], torque=[1.0, 1.0], side=side)
161
+
162
+ def get_grasping_state(self)->Tuple[EndEffectorState.GraspingState, EndEffectorState.GraspingState]:
163
+ """Get the grasping state of the claws.
164
+
165
+ Returns:
166
+ Tuple[EndEffectorState.GraspingState, EndEffectorState.GraspingState]: The grasping state of the claws.
167
+ """
168
+ return self._rb_state.eef_state.state
169
+
170
+ def get_position(self)->Tuple[list, list]:
171
+ """Get the position of the claws.
172
+
173
+ Returns:
174
+ Tuple[list, list]: The position of the claws, range [0.0, 100.0].
175
+ """
176
+ claw_state = self._rb_state.eef_state
177
+ return (claw_state[0].position, claw_state[1].position)
178
+
179
+ def get_velocity(self)->Tuple[list, list]:
180
+ """Get the velocity of the claws.
181
+
182
+ Returns:
183
+ Tuple[list, list]: The velocity of the claws.
184
+ """
185
+ claw_state = self._rb_state.eef_state
186
+ return (claw_state[0].velocity, claw_state[1].velocity)
187
+
188
+ def get_effort(self)->Tuple[list, list]:
189
+ """Get the effort of the claws.
190
+
191
+ Returns:
192
+ Tuple[list, list]: The effort of the claws.
193
+ """
194
+ claw_state = self._rb_state.eef_state
195
+ return (claw_state[0].effort, claw_state[1].effort)
196
+
197
+ def get_state(self)->Tuple[EndEffectorState, EndEffectorState]:
198
+ """Get the state of the claws.
199
+
200
+ Returns:
201
+ Tuple[EndEffectorState, EndEffectorState]: The state of the claws.
202
+ - position: The position of the claws, range [0.0, 100.0].
203
+ - velocity: The velocity of the claws.
204
+ - effort: The effort of the claws.
205
+ - state: The grasping state of the claws.
206
+ """
207
+ return self._rb_state.eef_state
208
+
209
+ def wait_for_finish(self, side: EndEffectorSide=EndEffectorSide.BOTH, timeout:float=2.5):
210
+ """Wait for the claw motion to finish.
211
+
212
+ Args:
213
+ side (EndEffectorSide, optional): The side of the claw to wait for. Defaults to EndEffectorSide.BOTH.
214
+ timeout (float, optional): The timeout duration in seconds. Defaults to 2.5.
215
+
216
+ Returns:
217
+ bool: True if motion completed before timeout, False otherwise.
218
+ """
219
+ start_time = time.time()
220
+ while time.time() - start_time < timeout:
221
+ if side == EndEffectorSide.BOTH:
222
+ if self._rb_state.eef_state[0].state >= EndEffectorState.GraspingState.REACHED and \
223
+ self._rb_state.eef_state[1].state >= EndEffectorState.GraspingState.REACHED:
224
+ return True
225
+ elif side == EndEffectorSide.LEFT:
226
+ if self._rb_state.eef_state[0].state >= EndEffectorState.GraspingState.REACHED:
227
+ return True
228
+ elif side == EndEffectorSide.RIGHT:
229
+ if self._rb_state.eef_state[1].state >= EndEffectorState.GraspingState.REACHED:
230
+ return True
231
+ time.sleep(0.1)
232
+ return False