kuavo-humanoid-sdk 0.1.2__py3-none-any.whl → 1.1.2a692__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.

@@ -1,3 +1,4 @@
1
+ from .msg import *
1
2
  from .interfaces import *
2
3
  from .kuavo import *
3
4
  from kuavo_humanoid_sdk.common.logger import SDKLogger, disable_sdk_logging
@@ -65,13 +65,13 @@ class EndEffectorState:
65
65
  """Data class representing the state of the end effector.
66
66
 
67
67
  Args:
68
- position (float): Position of the end effector, [0, 100]
69
- velocity (float): ...
70
- effort (float): ...
68
+ position (list): float, Position of the end effector, range: [0, 100]
69
+ velocity (list): float, ...
70
+ effort (list): float, ...
71
71
  """
72
- position: float
73
- velocity: float
74
- effort: float
72
+ position: list
73
+ velocity: list
74
+ effort: list
75
75
  class GraspingState(Enum):
76
76
  """Enum class representing the grasping states of the end effector.
77
77
 
@@ -119,4 +119,27 @@ class KuavoIKParams:
119
119
  # constraint and cost params
120
120
  oritation_constraint_tol: float = 1e-3
121
121
  pos_constraint_tol: float = 1e-3 # 0.001m, work when pos_cost_weight==0.0
122
- pos_cost_weight: float = 0.0 # If U need high accuracy, set this to 0.0 !!!
122
+ pos_cost_weight: float = 0.0 # If U need high accuracy, set this to 0.0 !!!
123
+
124
+ @dataclass
125
+ class KuavoDexHandTouchState:
126
+ """Data class representing the touch state of the dexterous hand."""
127
+
128
+ @dataclass
129
+ class KuavoTouchState:
130
+ """Data class representing the touch state of the dexterous hand."""
131
+ normal_force1: int # 法向力1
132
+ normal_force2: int # 法向力2
133
+ normal_force3: int # 法向力3
134
+ tangential_force1: int # 切向力1
135
+ tangential_force2: int # 切向力2
136
+ tangential_force3: int # 切向力3
137
+ tangential_direction1: int # 切向力方向1
138
+ tangential_direction2: int # 切向力方向2
139
+ tangential_direction3: int # 切向力方向3
140
+ self_proximity1: int # 自电容接近传感器1
141
+ self_proximity2: int # 自电容接近传感器2
142
+ mutual_proximity: int # 互电容接近传感器
143
+ status: int # 传感器状态
144
+ # 5 fingers
145
+ data: Tuple[KuavoTouchState, KuavoTouchState, KuavoTouchState, KuavoTouchState, KuavoTouchState]
@@ -4,8 +4,27 @@ from kuavo_humanoid_sdk.interfaces.data_types import EndEffectorSide, EndEffecto
4
4
 
5
5
  class EndEffector(ABC):
6
6
  def __init__(self, joint_names: list):
7
- self.joint_names = joint_names
7
+ self._joint_names = joint_names
8
+
9
+ def joint_names(self)->list:
10
+ """Returns the joint names of the end effector.
11
+
12
+ Returns:
13
+ list: The joint names of the end effector.
14
+ """
15
+ return self._joint_names
16
+
17
+ def joint_count(self) -> int:
18
+ """Returns the total number of joints in the end effector.
8
19
 
20
+ The joint_names list contains joints for both left and right end effectors.
21
+ For a single end effector, the number of joints would be joint_names.size/2.
22
+
23
+ Returns:
24
+ int: The total number of joints in the end effector.
25
+ """
26
+ return len(self._joint_names)
27
+
9
28
  @abstractmethod
10
29
  def control(self, target_positions:list, target_velocities:list, target_torques:list)->bool:
11
30
  pass
@@ -27,15 +46,15 @@ class EndEffector(ABC):
27
46
  pass
28
47
 
29
48
  @abstractmethod
30
- def get_position(self)->Tuple[float, float]:
49
+ def get_position(self)->Tuple[list, list]:
31
50
  pass
32
51
 
33
52
  @abstractmethod
34
- def get_velocity(self)->Tuple[float, float]:
53
+ def get_velocity(self)->Tuple[list, list]:
35
54
  pass
36
55
 
37
56
  @abstractmethod
38
- def get_effort(self)->Tuple[float, float]:
57
+ def get_effort(self)->Tuple[list, list]:
39
58
  pass
40
59
 
41
60
  @abstractmethod
@@ -3,5 +3,5 @@ from .robot_info import KuavoRobotInfo
3
3
  from .robot_state import KuavoRobotState
4
4
  from .robot_arm import KuavoRobotArm
5
5
  from .robot_head import KuavoRobotHead
6
- from .dexterous_hand import DexterousHand
6
+ from .dexterous_hand import DexterousHand, TouchDexterousHand
7
7
  from .leju_claw import LejuClaw
@@ -28,7 +28,7 @@ from transitions import Machine, State
28
28
  from kuavo_humanoid_sdk.interfaces.data_types import KuavoArmCtrlMode, KuavoIKParams, KuavoPose
29
29
  from kuavo_humanoid_sdk.kuavo.core.ros.control import KuavoRobotControl
30
30
  from kuavo_humanoid_sdk.kuavo.core.ros.state import KuavoRobotStateCore
31
- from kuavo_humanoid_sdk.kuavo.core.ros.param import make_robot_param, kuavo_ros_param
31
+ from kuavo_humanoid_sdk.kuavo.core.ros.param import make_robot_param
32
32
  from kuavo_humanoid_sdk.common.logger import SDKLogger
33
33
 
34
34
  # Define robot states
@@ -78,7 +78,6 @@ class KuavoRobotCore:
78
78
  raise RuntimeError if initialize failed.
79
79
  """
80
80
  try:
81
- info = make_robot_param()
82
81
  # init state by gait_name
83
82
  gait_name = self._rb_state.gait_name()
84
83
  if gait_name is not None:
@@ -173,15 +172,20 @@ class KuavoRobotCore:
173
172
  SDKLogger.warn(f"[Core] control torso height failed, robot is not in stance state({self.state})!")
174
173
  return False
175
174
 
176
- # Limit height range to [-0.3, 0.0]
177
- limited_height = min(0.0, max(-0.3, height))
178
- if height > 0.0 or height < -0.3:
179
- SDKLogger.warn(f"[Core] height {height} exceeds limit [-0.3, 0.0], will be limited")
175
+ MIN_HEIGHT = -0.35
176
+ MAX_HEIGHT = 0.0
177
+ MIN_PITCH = -0.4
178
+ MAX_PITCH = 0.4
180
179
 
181
- # Limit pitch range to [-0.4, 0.4]
182
- limited_pitch = min(0.4, max(-0.4, pitch))
183
- if abs(pitch) > 0.4:
184
- SDKLogger.warn(f"[Core] pitch {pitch} exceeds limit [-0.4, 0.4], will be limited")
180
+ # Limit height range
181
+ limited_height = min(MAX_HEIGHT, max(MIN_HEIGHT, height))
182
+ if height > MAX_HEIGHT or height < MIN_HEIGHT:
183
+ SDKLogger.warn(f"[Core] height {height} exceeds limit [{MIN_HEIGHT}, {MAX_HEIGHT}], will be limited")
184
+
185
+ # Limit pitch range
186
+ limited_pitch = min(MAX_PITCH, max(MIN_PITCH, pitch))
187
+ if abs(pitch) > MAX_PITCH:
188
+ SDKLogger.warn(f"[Core] pitch {pitch} exceeds limit [{MIN_PITCH}, {MAX_PITCH}], will be limited")
185
189
 
186
190
  return self._control.control_torso_height(limited_height, limited_pitch)
187
191
 
@@ -238,9 +242,9 @@ class KuavoRobotCore:
238
242
  max_y_step = 0.20
239
243
  max_yaw_step = 90
240
244
  else:
241
- max_x_step = 0.10
242
- max_y_step = 0.10
243
- max_yaw_step = 30
245
+ max_x_step = 0.15
246
+ max_y_step = 0.15
247
+ max_yaw_step = 45
244
248
 
245
249
  body_poses = []
246
250
 
@@ -294,6 +298,10 @@ class KuavoRobotCore:
294
298
  def control_robot_dexhand(self, left_position:list, right_position:list)->bool:
295
299
  return self._control.control_robot_dexhand(left_position, right_position)
296
300
 
301
+ def robot_dexhand_command(self, data, ctrl_mode, hand_side):
302
+ return self._control.robot_dexhand_command(data, ctrl_mode, hand_side)
303
+
304
+
297
305
  def control_leju_claw(self, postions:list, velocities:list=[90, 90], torques:list=[1.0, 1.0]) ->bool:
298
306
  return self._control.control_leju_claw(postions, velocities, torques)
299
307
 
@@ -4,6 +4,7 @@ from queue import Queue
4
4
  from kuavo_humanoid_sdk.interfaces.data_types import EndEffectorSide
5
5
  from kuavo_humanoid_sdk.kuavo.core.core import KuavoRobotCore
6
6
  from kuavo_humanoid_sdk.common.logger import SDKLogger
7
+ from kuavo_humanoid_sdk.kuavo.core.ros.param import make_robot_param, EndEffectorType
7
8
  class DexHandControl:
8
9
  _instance = None
9
10
 
@@ -19,6 +20,8 @@ class DexHandControl:
19
20
  self.thread = threading.Thread(target=self._process_queue) # Create a thread to process the queue
20
21
  self.thread.daemon = True # Set the thread as a daemon so it will exit when the main program exits
21
22
  self.thread.start() # Start the thread
23
+ kuavo_info = make_robot_param()
24
+ self._ee_type = kuavo_info['end_effector_type']
22
25
  # Initialize last command position, torque, and velocity
23
26
  self.last_cmd_position = {EndEffectorSide.LEFT: [0] * 6, EndEffectorSide.RIGHT: [0] * 6}
24
27
  self._initialized = True
@@ -26,6 +29,9 @@ class DexHandControl:
26
29
  def control(self, target_positions: list, side: EndEffectorSide):
27
30
  self.queue.put(('position', EndEffectorSide(side.value), target_positions))
28
31
 
32
+ def control_velocity(self, target_velocities: list, side: EndEffectorSide):
33
+ self.queue.put(('velocity', EndEffectorSide(side.value), target_velocities))
34
+
29
35
  def make_gestures(self, gestures:list)->bool:
30
36
  """
31
37
  Make a gesture for the dexhand.
@@ -60,26 +66,49 @@ class DexHandControl:
60
66
  return None
61
67
  return gs
62
68
 
69
+
70
+ def _process_dexhand_command(self, command, side, data):
71
+ if command == 'position':
72
+ pos = self.last_cmd_position[EndEffectorSide.LEFT] + self.last_cmd_position[EndEffectorSide.RIGHT]
73
+ if side == EndEffectorSide.BOTH:
74
+ pos = copy.deepcopy(data)
75
+ elif side == EndEffectorSide.LEFT:
76
+ pos[:6] = data
77
+ elif side == EndEffectorSide.RIGHT:
78
+ pos[6:] = data
79
+ else:
80
+ return
81
+ self._kuavo_core.control_robot_dexhand(left_position=pos[:6], right_position=pos[6:])
82
+ self.last_cmd_position[EndEffectorSide.LEFT] = pos[:6]
83
+ self.last_cmd_position[EndEffectorSide.RIGHT] = pos[6:]
84
+
85
+ def _process_touch_dexhand_command(self, command, side, data):
86
+ if command == 'position':
87
+ ctrl_mode = 0
88
+ if side == EndEffectorSide.BOTH:
89
+ self._kuavo_core.robot_dexhand_command(data, ctrl_mode, 2)
90
+ elif side == EndEffectorSide.LEFT:
91
+ self._kuavo_core.robot_dexhand_command(data, ctrl_mode, 0)
92
+ elif side == EndEffectorSide.RIGHT:
93
+ self._kuavo_core.robot_dexhand_command(data, ctrl_mode, 1)
94
+ elif command == 'velocity':
95
+ ctrl_mode = 0
96
+ if side == EndEffectorSide.BOTH:
97
+ self._kuavo_core.robot_dexhand_command(data, ctrl_mode, 2)
98
+ elif side == EndEffectorSide.LEFT:
99
+ self._kuavo_core.robot_dexhand_command(data, ctrl_mode, 0)
100
+ elif side == EndEffectorSide.RIGHT:
101
+ self._kuavo_core.robot_dexhand_command(data, ctrl_mode, 1)
102
+
63
103
  def _process_queue(self):
64
104
  while True:
65
105
  try:
66
106
  command, side, data = self.queue.get() # This will block until an item is available in the queue
67
107
  SDKLogger.debug(f'[DexHandControl] Received command: {command}, for side: {side}, with data: {data}')
68
- if command == 'position':
69
- pos = self.last_cmd_position[EndEffectorSide.LEFT] + self.last_cmd_position[EndEffectorSide.RIGHT]
70
- if side == EndEffectorSide.BOTH:
71
- pos = copy.deepcopy(data)
72
- elif side == EndEffectorSide.LEFT:
73
- pos[:6] = data
74
- elif side == EndEffectorSide.RIGHT:
75
- pos[6:] = data
76
- else:
77
- return
78
- self._kuavo_core.control_robot_dexhand(left_position=pos[:6], right_position=pos[6:])
79
- self.last_cmd_position[EndEffectorSide.LEFT] = pos[:6]
80
- self.last_cmd_position[EndEffectorSide.RIGHT] = pos[6:]
81
-
82
- # task done.
108
+ if self._ee_type == EndEffectorType.QIANGNAO:
109
+ self._process_dexhand_command(command, side, data)
110
+ elif self._ee_type == EndEffectorType.QIANGNAO_TOUCH:
111
+ self._process_touch_dexhand_command(command, side, data)
83
112
  self.queue.task_done()
84
113
  except KeyboardInterrupt:
85
114
  break
@@ -1,33 +1,44 @@
1
-
1
+ import os
2
2
  import rospy
3
3
  import numpy as np
4
4
  from typing import Tuple
5
5
  from kuavo_humanoid_sdk.common.logger import SDKLogger
6
6
  from kuavo_humanoid_sdk.interfaces.data_types import KuavoArmCtrlMode, KuavoIKParams, KuavoPose
7
7
  from kuavo_humanoid_sdk.kuavo.core.ros.sat_utils import RotatingRectangle
8
-
8
+ from kuavo_humanoid_sdk.kuavo.core.ros.param import EndEffectorType
9
9
  from geometry_msgs.msg import Twist
10
10
  from sensor_msgs.msg import JointState, Joy
11
- from kuavo_msgs.msg import gestureTask,robotHandPosition, robotHeadMotionData, armTargetPoses, switchGaitByName
12
- from kuavo_msgs.msg import footPose, footPoseTargetTrajectories
13
- from kuavo_msgs.srv import (gestureExecute, gestureExecuteRequest,gestureList, gestureListRequest,
11
+ from kuavo_humanoid_sdk.msg.kuavo_msgs.msg import (gestureTask,robotHandPosition, robotHeadMotionData, armTargetPoses, switchGaitByName,
12
+ footPose, footPoseTargetTrajectories, dexhandCommand)
13
+ from kuavo_humanoid_sdk.msg.kuavo_msgs.srv import (gestureExecute, gestureExecuteRequest,gestureList, gestureListRequest,
14
14
  controlLejuClaw, controlLejuClawRequest, changeArmCtrlMode, changeArmCtrlModeRequest)
15
- from motion_capture_ik.msg import twoArmHandPoseCmd, ikSolveParam
16
- from motion_capture_ik.srv import twoArmHandPoseCmdSrv, fkSrv
15
+ from kuavo_humanoid_sdk.msg.motion_capture_ik.msg import twoArmHandPoseCmd, ikSolveParam
16
+ from kuavo_humanoid_sdk.msg.motion_capture_ik.srv import twoArmHandPoseCmdSrv, fkSrv
17
17
 
18
18
  class ControlEndEffector:
19
- def __init__(self, eef_type: str = "qiangnao"):
20
- self._pubs = []
19
+ def __init__(self, eef_type: str = EndEffectorType.QIANGNAO):
21
20
  self._eef_type = eef_type
22
- if eef_type == "qiangnao":
21
+ self._pubs = []
22
+ if self._eef_type == EndEffectorType.QIANGNAO:
23
+ self._pub_ctrl_robot_hand = rospy.Publisher('/control_robot_hand_position', robotHandPosition, queue_size=10)
24
+ # publisher, name, require
25
+ self._pubs.append((self._pub_ctrl_robot_hand, True))
26
+ elif self._eef_type == EndEffectorType.QIANGNAO_TOUCH:
23
27
  self._pub_ctrl_robot_hand = rospy.Publisher('/control_robot_hand_position', robotHandPosition, queue_size=10)
24
- self._pubs.append(self._pub_ctrl_robot_hand)
28
+ self._pub_dexhand_command = rospy.Publisher('/dexhand/command', dexhandCommand, queue_size=10)
29
+ self._pub_dexhand_right_command = rospy.Publisher('/dexhand/right/command', dexhandCommand, queue_size=10)
30
+ self._pub_dexhand_left_command = rospy.Publisher('/dexhand/left/command', dexhandCommand, queue_size=10)
31
+ # publisher, name, require
32
+ self._pubs.append((self._pub_dexhand_command, True))
33
+ self._pubs.append((self._pub_dexhand_right_command, True))
34
+ self._pubs.append((self._pub_dexhand_left_command, True))
35
+
25
36
 
26
37
  def connect(self, timeout:float=1.0)-> bool:
27
38
  start_time = rospy.Time.now()
28
39
 
29
40
  success = True
30
- for pub in self._pubs:
41
+ for pub, require in self._pubs:
31
42
  while pub.get_num_connections() == 0:
32
43
  if (rospy.Time.now() - start_time).to_sec() > timeout:
33
44
  SDKLogger.error(f"Timeout waiting for {pub.name} connection")
@@ -39,7 +50,7 @@ class ControlEndEffector:
39
50
 
40
51
  """ Control Kuavo Robot Dexhand """
41
52
  def pub_control_robot_dexhand(self, left_position:list, right_position:list)->bool:
42
- if self._eef_type != 'qiangnao':
53
+ if not self._eef_type.startswith(EndEffectorType.QIANGNAO): # qiangnao, qiangnao_touch
43
54
  SDKLogger.warning(f"{self._eef_type} not support control dexhand")
44
55
  return False
45
56
  try :
@@ -52,9 +63,41 @@ class ControlEndEffector:
52
63
  except Exception as e:
53
64
  SDKLogger.error(f"publish robot dexhand: {e}")
54
65
  return False
66
+
67
+ def pub_dexhand_command(self, data:list, ctrl_mode, hand_side)->bool:
68
+ """
69
+ ctrl_mode: 0 --> POSITION, 1 --> VELOCITY
70
+ hand_side: 0 --> left, 1 --> right, 2-->dual
71
+ """
72
+ if not self._eef_type == EndEffectorType.QIANGNAO_TOUCH:
73
+ SDKLogger.warning(f"{self._eef_type} not support pub_left_dexhand_command")
74
+ return False
75
+ try:
76
+ if hand_side != 2 and len(data) != 6:
77
+ SDKLogger.warning("Data length should be 6")
78
+ return False
79
+ if hand_side == 2 and len(data) != 12:
80
+ SDKLogger.warning("Data length should be 12")
81
+ return False
82
+ if ctrl_mode not in [dexhandCommand.POSITION_CONTROL, dexhandCommand.VELOCITY_CONTROL]:
83
+ SDKLogger.error(f"Invalid mode for pub_left_dexhand_command: {ctrl_mode}")
84
+ return False
85
+ msg = dexhandCommand()
86
+ msg.data = [int(d) for d in data] # Convert data to integers
87
+ msg.control_mode = ctrl_mode
88
+ if hand_side == 0:
89
+ self._pub_dexhand_left_command.publish(msg)
90
+ elif hand_side == 1:
91
+ self._pub_dexhand_right_command.publish(msg)
92
+ else:
93
+ self._pub_dexhand_command.publish(msg)
94
+ return True
95
+ except Exception as e:
96
+ SDKLogger.error(f"Failed to publish left dexhand command: {e}")
97
+ return False
55
98
 
56
99
  def srv_execute_gesture(self, gestures:list)->bool:
57
- if self._eef_type != 'qiangnao':
100
+ if not self._eef_type.startswith(EndEffectorType.QIANGNAO): # qiangnao, qiangnao_touch
58
101
  SDKLogger.warning(f"{self._eef_type} not support control dexhand")
59
102
  return False
60
103
  try:
@@ -83,7 +126,7 @@ class ControlEndEffector:
83
126
  return False
84
127
 
85
128
  def srv_get_gesture_names(self)->list:
86
- if self._eef_type != 'qiangnao':
129
+ if not self._eef_type.startswith(EndEffectorType.QIANGNAO): # qiangnao, qiangnao_touch
87
130
  SDKLogger.warning(f"{self._eef_type} not support control dexhand")
88
131
  return []
89
132
  try:
@@ -264,7 +307,7 @@ class ControlRobotMotion:
264
307
  self._pub_switch_gait = rospy.Publisher('/humanoid_switch_gait_by_name', switchGaitByName, queue_size=10)
265
308
  self._pub_step_ctrl = rospy.Publisher('/humanoid_mpc_foot_pose_target_trajectories', footPoseTargetTrajectories, queue_size=10)
266
309
 
267
- def connect(self, timeout:float=1.0)-> bool:
310
+ def connect(self, timeout:float=2.0)-> bool:
268
311
  start_time = rospy.Time.now()
269
312
  publishers = [
270
313
  # (self._pub_joy, "joy publisher"),
@@ -510,6 +553,19 @@ class KuavoRobotControl:
510
553
  SDKLogger.debug(f"Control robot dexhand: {left_position}, {right_position}")
511
554
  return self.kuavo_eef_control.pub_control_robot_dexhand(left_position, right_position)
512
555
 
556
+ def robot_dexhand_command(self, data, ctrl_mode, hand_side):
557
+ """
558
+ Publish dexhand command
559
+ Args:
560
+ - data: list of 6 floats between 0 and 100
561
+ - ctrl_mode: int between 0(position), 1(velocity)
562
+ - hand_side: int between 0(left), 1(right), 2(dual)
563
+ """
564
+ if self.kuavo_eef_control is None:
565
+ SDKLogger.error("End effector control is not initialized.")
566
+ return False
567
+ return self.kuavo_eef_control.pub_dexhand_command(data, ctrl_mode, hand_side)
568
+
513
569
  def execute_gesture(self, gestures:list)->bool:
514
570
  """
515
571
  Execute gestures
@@ -2,6 +2,12 @@ import rospy
2
2
  import json
3
3
  import xml.etree.ElementTree as ET
4
4
  from kuavo_humanoid_sdk.common.logger import SDKLogger
5
+
6
+ # End effector types
7
+ class EndEffectorType:
8
+ QIANGNAO = "qiangnao"
9
+ QIANGNAO_TOUCH = "qiangnao_touch"
10
+ LEJUCLAW = "lejuclaw"
5
11
  class RosParameter:
6
12
  def __init__(self):
7
13
  pass
@@ -4,12 +4,13 @@ import time
4
4
  from typing import Tuple
5
5
  from std_msgs.msg import Float64
6
6
  from nav_msgs.msg import Odometry
7
- from kuavo_msgs.msg import sensorsData, lejuClawState, gaitTimeName
8
-
7
+ from sensor_msgs.msg import JointState
8
+ from kuavo_humanoid_sdk.msg.kuavo_msgs.msg import sensorsData, lejuClawState, gaitTimeName, dexhandTouchState
9
9
  from kuavo_msgs.srv import changeArmCtrlMode, changeArmCtrlModeRequest, getCurrentGaitName, getCurrentGaitNameRequest
10
- from ocs2_msgs.msg import mpc_observation
11
- from kuavo_humanoid_sdk.interfaces.data_types import KuavoImuData, KuavoJointData, KuavoOdometry, KuavoArmCtrlMode, EndEffectorState
12
- from kuavo_humanoid_sdk.kuavo.core.ros.param import make_robot_param
10
+ from kuavo_humanoid_sdk.msg.ocs2_msgs.msg import mpc_observation
11
+ from kuavo_humanoid_sdk.interfaces.data_types import (KuavoImuData, KuavoJointData, KuavoOdometry,
12
+ KuavoArmCtrlMode, EndEffectorState, KuavoDexHandTouchState)
13
+ from kuavo_humanoid_sdk.kuavo.core.ros.param import make_robot_param, EndEffectorType
13
14
  from kuavo_humanoid_sdk.common.logger import SDKLogger
14
15
 
15
16
  from collections import deque
@@ -66,12 +67,32 @@ class KuavoRobotStateCore:
66
67
  rospy.Subscriber("/humanoid_mpc_observation", mpc_observation, self._humanoid_mpc_observation_callback)
67
68
 
68
69
  kuavo_info = make_robot_param()
69
- if kuavo_info['end_effector_type'] == "lejuclaw":
70
+ self._ee_type = kuavo_info['end_effector_type']
71
+ if self._ee_type == EndEffectorType.LEJUCLAW:
70
72
  rospy.Subscriber("/leju_claw_state", lejuClawState, self._lejuclaw_state_callback)
71
- elif kuavo_info['end_effector_type'] == "qiangnao":
72
- pass # TODO(kuavo): add qiangnao state subscriber
73
- # rospy.Subscriber("/robot_hand_state", robotHandState, self._dexterous_hand_state_callback)
74
-
73
+ elif self._ee_type == EndEffectorType.QIANGNAO:
74
+ rospy.Subscriber("/dexhand/state", JointState, self._dexterous_hand_state_callback)
75
+ elif self._ee_type == EndEffectorType.QIANGNAO_TOUCH:
76
+ rospy.Subscriber("/dexhand/state", JointState, self._dexterous_hand_state_callback)
77
+ rospy.Subscriber("/dexhand/touch_state", dexhandTouchState, self._dexhand_touch_state_callback)
78
+ # Initialize touch state for both hands with empty KuavoDexHandTouchState instances
79
+ self._dexhand_touch_state = (
80
+ KuavoDexHandTouchState(
81
+ data=(KuavoDexHandTouchState.KuavoTouchState(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
82
+ KuavoDexHandTouchState.KuavoTouchState(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
83
+ KuavoDexHandTouchState.KuavoTouchState(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
84
+ KuavoDexHandTouchState.KuavoTouchState(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
85
+ KuavoDexHandTouchState.KuavoTouchState(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0))
86
+ ), # Left hand touch state
87
+ KuavoDexHandTouchState(
88
+ data=(KuavoDexHandTouchState.KuavoTouchState(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
89
+ KuavoDexHandTouchState.KuavoTouchState(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
90
+ KuavoDexHandTouchState.KuavoTouchState(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
91
+ KuavoDexHandTouchState.KuavoTouchState(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
92
+ KuavoDexHandTouchState.KuavoTouchState(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0))
93
+ ) # Right hand touch state
94
+ )
95
+
75
96
  """ data """
76
97
  self._terrain_height = 0.0
77
98
  self._imu_data = KuavoImuData(
@@ -93,17 +114,17 @@ class KuavoRobotStateCore:
93
114
  angular = (0.0, 0.0, 0.0)
94
115
  )
95
116
  self._eef_state = (EndEffectorState(
96
- position = 0.0,
97
- velocity = 0.0,
98
- effort = 0.0,
117
+ position = [0.0] * 12 if kuavo_info['end_effector_type'].startswith('qiangnao') else [0.0] * 2,
118
+ velocity = [0.0] * 12 if kuavo_info['end_effector_type'].startswith('qiangnao') else [0.0] * 2,
119
+ effort = [0.0] * 12 if kuavo_info['end_effector_type'].startswith('qiangnao') else [0.0] * 2,
99
120
  state=EndEffectorState.GraspingState.UNKNOWN
100
121
  ), EndEffectorState(
101
- position = 0.0,
102
- velocity = 0.0,
103
- effort = 0.0,
122
+ position = [0.0] * 12 if kuavo_info['end_effector_type'].startswith('qiangnao') else [0.0] * 2,
123
+ velocity = [0.0] * 12 if kuavo_info['end_effector_type'].startswith('qiangnao') else [0.0] * 2,
124
+ effort = [0.0] * 12 if kuavo_info['end_effector_type'].startswith('qiangnao') else [0.0] * 2,
104
125
  state=EndEffectorState.GraspingState.UNKNOWN
105
126
  ))
106
-
127
+
107
128
  # gait manager
108
129
  self._gait_manager = GaitManager()
109
130
  self._prev_gait_name = self.gait_name
@@ -156,6 +177,12 @@ class KuavoRobotStateCore:
156
177
  def eef_state(self)->Tuple[EndEffectorState, EndEffectorState]:
157
178
  return self._eef_state
158
179
 
180
+ @property
181
+ def dexhand_touch_state(self)-> Tuple[KuavoDexHandTouchState, KuavoDexHandTouchState]:
182
+ if self._ee_type != EndEffectorType.QIANGNAO_TOUCH:
183
+ raise Exception("This robot does not support touch state")
184
+ return self._dexhand_touch_state
185
+
159
186
  @property
160
187
  def current_observation_time(self) -> float:
161
188
  """Get the current observation time from MPC.
@@ -231,7 +258,7 @@ class KuavoRobotStateCore:
231
258
  position = copy.deepcopy(msg.joint_data.joint_q),
232
259
  velocity = copy.deepcopy(msg.joint_data.joint_v),
233
260
  torque = copy.deepcopy(msg.joint_data.joint_vd),
234
- acceleration = copy.deepcopy(msg.joint_data.joint_current)
261
+ acceleration = copy.deepcopy(msg.joint_data.joint_current if hasattr(msg.joint_data, 'joint_current') else msg.joint_data.joint_torque)
235
262
  )
236
263
 
237
264
  def _odom_callback(self, msg:Odometry)->None:
@@ -245,29 +272,57 @@ class KuavoRobotStateCore:
245
272
 
246
273
  def _lejuclaw_state_callback(self, msg:lejuClawState)->None:
247
274
  self._eef_state = (EndEffectorState(
248
- position = msg.data.position[0],
249
- velocity = msg.data.velocity[0],
250
- effort = msg.data.effort[0],
275
+ # left claw
276
+ position = [msg.data.position[0]],
277
+ velocity = [msg.data.velocity[0]],
278
+ effort = [msg.data.effort[0]],
251
279
  state=EndEffectorState.GraspingState(msg.state[0])
252
280
  ), EndEffectorState(
253
- position = msg.data.position[1],
254
- velocity = msg.data.velocity[1],
255
- effort = msg.data.effort[1],
281
+ # right claw
282
+ position = [msg.data.position[1]],
283
+ velocity = [msg.data.velocity[1]],
284
+ effort = [msg.data.effort[1]],
256
285
  state=EndEffectorState.GraspingState(msg.state[1])
257
286
  ))
258
287
 
259
- def _dexterous_hand_state_callback(self, msg)->None:
288
+ def _dexterous_hand_state_callback(self, msg:JointState)->None:
260
289
  self._eef_state = (EndEffectorState(
261
- position = msg.data.position[0],
262
- velocity = msg.data.velocity[0],
263
- effort = msg.data.effort[0],
264
- state=EndEffectorState.GraspingState(msg.state[0])
290
+ # left hand
291
+ position = list(msg.position[:len(msg.position)//2]),
292
+ velocity = list(msg.velocity[:len(msg.velocity)//2]),
293
+ effort = list(msg.effort[:len(msg.effort)//2]),
294
+ state=EndEffectorState.GraspingState.UNKNOWN
265
295
  ), EndEffectorState(
266
- position = msg.data.position[1],
267
- velocity = msg.data.velocity[1],
268
- effort = msg.data.effort[1],
269
- state=EndEffectorState.GraspingState(msg.state[1])
296
+ # right hand
297
+ position = list(msg.position[len(msg.position)//2:]),
298
+ velocity = list(msg.velocity[len(msg.velocity)//2:]),
299
+ effort = list(msg.effort[len(msg.effort)//2:]),
300
+ state=EndEffectorState.GraspingState.UNKNOWN
270
301
  ))
302
+
303
+ def _dexhand_touch_state_callback(self, msg:dexhandTouchState)->None:
304
+ # Update touch state for both hands
305
+ self._dexhand_touch_state = (
306
+ KuavoDexHandTouchState(
307
+ data=tuple(KuavoDexHandTouchState.KuavoTouchState(
308
+ sensor.normal_force1, sensor.normal_force2, sensor.normal_force3,
309
+ sensor.tangential_force1, sensor.tangential_force2, sensor.tangential_force3,
310
+ sensor.tangential_direction1, sensor.tangential_direction2, sensor.tangential_direction3,
311
+ sensor.self_proximity1, sensor.self_proximity2, sensor.mutual_proximity,
312
+ sensor.status
313
+ ) for sensor in msg.left_hand)
314
+ ), # Left hand touch state
315
+ KuavoDexHandTouchState(
316
+ data=tuple(KuavoDexHandTouchState.KuavoTouchState(
317
+ sensor.normal_force1, sensor.normal_force2, sensor.normal_force3,
318
+ sensor.tangential_force1, sensor.tangential_force2, sensor.tangential_force3,
319
+ sensor.tangential_direction1, sensor.tangential_direction2, sensor.tangential_direction3,
320
+ sensor.self_proximity1, sensor.self_proximity2, sensor.mutual_proximity,
321
+ sensor.status
322
+ ) for sensor in msg.right_hand)
323
+ ) # Right hand touch state
324
+ )
325
+
271
326
  def _humanoid_mpc_gait_changed_callback(self, msg: gaitTimeName):
272
327
  """
273
328
  Callback function for gait change messages.