From b4d6c9876c4f20ad9c2c84e5cfb14bc159ab265a Mon Sep 17 00:00:00 2001 From: weipengzhe <3389096668@qq.com> Date: Fri, 18 Sep 2026 14:55:07 +0800 Subject: [PATCH] =?UTF-8?q?=E5=B7=B2=E7=BB=8F=E5=8F=AF=E4=BB=A5=E6=AD=A3?= =?UTF-8?q?=E5=B8=B8=E9=A9=B1=E5=8A=A8=E7=81=B5=E5=B7=A7=E6=89=8B=E5=B9=B6?= =?UTF-8?q?=E8=8E=B7=E5=8F=96=E5=8F=8D=E9=A6=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../launch/linker_hand_double.launch.py | 4 +- .../LinkerHand/config/setting.yaml | 10 +- .../linker_hand_l20_can.cpython-312.pyc | Bin 0 -> 29695 bytes .../core/can/linker_hand_l20_can.py | 206 ++++++++++++------ .../__pycache__/linker_hand.cpython-312.pyc | Bin 0 -> 36093 bytes .../linker_hand_ros2_sdk/linker_hand.py | 24 +- 6 files changed, 164 insertions(+), 80 deletions(-) create mode 100644 src/linker_hand_ros2_sdk/linker_hand_ros2_sdk/LinkerHand/core/can/__pycache__/linker_hand_l20_can.cpython-312.pyc create mode 100644 src/linker_hand_ros2_sdk/linker_hand_ros2_sdk/__pycache__/linker_hand.cpython-312.pyc diff --git a/src/linker_hand_ros2_sdk/launch/linker_hand_double.launch.py b/src/linker_hand_ros2_sdk/launch/linker_hand_double.launch.py index f5c283a..4f50f53 100644 --- a/src/linker_hand_ros2_sdk/launch/linker_hand_double.launch.py +++ b/src/linker_hand_ros2_sdk/launch/linker_hand_double.launch.py @@ -14,7 +14,7 @@ def generate_launch_description(): 'hand_type': 'left', # 配置Linker Hand灵巧手类型 left | right 字母为小写 'hand_joint': "L20", # O6\L6P\L6\L7\L10\L20\G20(工业版)\L21 字母为大写 'is_touch': True, # 配置Linker Hand灵巧手是否有压力传感器 True | False - 'can': 'can0', # 这里需要修改为实际的CAN总线名称 如果是win系统则类似于 PCAN_USBBUS1 + 'can': 'can1', # 这里需要修改为实际的CAN总线名称 如果是win系统则类似于 PCAN_USBBUS1 "modbus": "None" # "None" | "/dev/ttyUSB0" 这里需要修改为实际的Modbus总线名称 如果是win系统则 COM* Ubuntu则为/dev/ttyUSB* }], ), @@ -28,7 +28,7 @@ def generate_launch_description(): 'hand_type': 'right', # 配置Linker Hand灵巧手类型 left | right 字母为小写 'hand_joint': "L20", # O6\L6P\L6\L7\L10\L20\G20(工业版)\L21 字母为大写 'is_touch': True, # 配置Linker Hand灵巧手是否有压力传感器 True | False - 'can': 'can1', # 这里需要修改为实际的CAN总线名称 如果是win系统则类似于 PCAN_USBBUS1 + 'can': 'can0', # 这里需要修改为实际的CAN总线名称 如果是win系统则类似于 PCAN_USBBUS1 "modbus": "None" # "None" | "/dev/ttyUSB0" 这里需要修改为实际的Modbus总线名称 如果是win系统则 COM* Ubuntu则为/dev/ttyUSB* }], ), diff --git a/src/linker_hand_ros2_sdk/linker_hand_ros2_sdk/LinkerHand/config/setting.yaml b/src/linker_hand_ros2_sdk/linker_hand_ros2_sdk/LinkerHand/config/setting.yaml index f3a7511..793e043 100644 --- a/src/linker_hand_ros2_sdk/linker_hand_ros2_sdk/LinkerHand/config/setting.yaml +++ b/src/linker_hand_ros2_sdk/linker_hand_ros2_sdk/LinkerHand/config/setting.yaml @@ -3,9 +3,9 @@ LINKER_HAND: # 手部配置信息 LEFT_HAND: EXISTS: True # 是否存在左手 TOUCH: True # 是否有压力传感器 - CAN: "can0" # 配置CAN端口 默认can0 如果MODUBS不为"None",则CAN配置失效。 如果是win系统则类似于 PCAN_USBBUS1。注:蓝色盒子为Linux下can0,WIN下位PCAN_USBBUS1。透明盒子Linux下为can0,WIN下为0 + CAN: "can1" # 配置CAN端口 默认can0 如果MODUBS不为"None",则CAN配置失效。 如果是win系统则类似于 PCAN_USBBUS1。注:蓝色盒子为Linux下can0,WIN下位PCAN_USBBUS1。透明盒子Linux下为can0,WIN下为0 MODBUS: "None" # 通讯协议是否为485 默认None 如果启动485,则是设备端口 /dev/ttyUSB* CAN配置失效 当前只支持O6/L6.后续版本正在努力增加中 - JOINT: L10 # 左手型号 O6/L6/L7/L10/L20/G20/L21/L25/ + JOINT: L20 # 左手型号 O6/L6/L7/L10/L20/G20/L21/L25/ NAME: # 默认值,不用修改 - joint41 - joint42 @@ -29,11 +29,11 @@ LINKER_HAND: # 手部配置信息 - joint60 RIGHT_HAND: - EXISTS: False # 是否存在右手 - TOUCH: False # 是否有压力传感器 + EXISTS: True # 是否存在右手 + TOUCH: True # 是否有压力传感器 CAN: "can0" # 配置CAN端口 默认can0 如果MODUBS不为"None",则CAN配置失效。 如果是win系统则类似于 PCAN_USBBUS1。注:蓝色盒子为Linux下can0,WIN下位PCAN_USBBUS1。透明盒子Linux下为can0,WIN下为0 MODBUS: "None" # 通讯协议是否为485 默认None 如果启动485,则是设备端口 /dev/ttyUSB* CAN配置失效 当前只支持O6/L6.后续版本正在努力增加中 - JOINT: L10 # 右手型号 O6/L6/L7/L10/L20/G20/L21/L25/ + JOINT: L20 # 右手型号 O6/L6/L7/L10/L20/G20/L21/L25/ NAME: # 默认值,不用修改 - joint71 - joint72 diff --git a/src/linker_hand_ros2_sdk/linker_hand_ros2_sdk/LinkerHand/core/can/__pycache__/linker_hand_l20_can.cpython-312.pyc b/src/linker_hand_ros2_sdk/linker_hand_ros2_sdk/LinkerHand/core/can/__pycache__/linker_hand_l20_can.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c92aaee89a056bfdab747ce920255ae1dca185b1 GIT binary patch literal 29695 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 Qwwrdv(C~R&gk(_tUo_u%?f?J) literal 0 HcmV?d00001 diff --git a/src/linker_hand_ros2_sdk/linker_hand_ros2_sdk/LinkerHand/core/can/linker_hand_l20_can.py b/src/linker_hand_ros2_sdk/linker_hand_ros2_sdk/LinkerHand/core/can/linker_hand_l20_can.py index 5b5f36e..18410d9 100644 --- a/src/linker_hand_ros2_sdk/linker_hand_ros2_sdk/LinkerHand/core/can/linker_hand_l20_can.py +++ b/src/linker_hand_ros2_sdk/linker_hand_ros2_sdk/LinkerHand/core/can/linker_hand_l20_can.py @@ -10,21 +10,40 @@ from can.exceptions import CanError class FrameProperty(Enum): INVALID_FRAME_PROPERTY = 0x00 # Invalid CAN frame property | No return - JOINT_PITCH_R = 0x01 # Short frame pitch angle - finger base flexion | Returns this type of data - JOINT_YAW_R = 0x02 # Short frame yaw angle - finger abduction/adduction | Returns this type of data - JOINT_ROLL_R = 0x03 # Short frame roll angle - only used for thumb | Returns this type of data - JOINT_TIP_R = 0x04 # Short frame fingertip angle control | Returns this type of data - JOINT_SPEED_R = 0x05 # Short frame speed - motor running speed control | Returns this type of data - JOINT_CURRENT_R = 0x06 # Short frame current - motor running current feedback | Returns this type of data - JOINT_FAULT_R = 0x07 # Short frame fault - motor running fault feedback | Returns this type of data - REQUEST_DATA_RETURN = 0x09 # Request data return | Returns all data - JOINT_PITCH_NR = 0x11 # Pitch angle - finger base flexion | No return for this type of data - JOINT_YAW_NR = 0x12 # Yaw angle - finger abduction/adduction | No return for this type of data - JOINT_ROLL_NR = 0x13 # Roll angle - only used for thumb | No return for this type of data - JOINT_TIP_NR = 0x14 # Fingertip angle control | No return for this type of data - JOINT_SPEED_NR = 0x15 # Speed - motor running speed control | No return for this type of data - JOINT_CURRENT_NR = 0x16 # Current - motor running current feedback | No return for this type of data - JOINT_FAULT_NR = 0x17 # Fault - motor running fault feedback | No return for this type of data + ROLL_POS = 0x01 # All fingers roll joint position + YAW_POS = 0x02 # All fingers yaw joint position + ROOT1_POS = 0x03 # All fingers root1 joint position + ROOT2_POS = 0x04 # All fingers root2 joint position + ROOT3_POS = 0x05 # All fingers root3 joint position + TIP_POS = 0x06 # All fingers tip joint position + ROLL_SPEED = 0x09 # All fingers roll joint speed + YAW_SPEED = 0x0A # All fingers yaw joint speed + ROOT1_SPEED = 0x0B # All fingers root1 joint speed + ROOT2_SPEED = 0x0C # All fingers root2 joint speed + ROOT3_SPEED = 0x0D # All fingers root3 joint speed + TIP_SPEED = 0x0E # All fingers tip joint speed + ROLL_TORQUE = 0x11 # All fingers roll joint load/current threshold + YAW_TORQUE = 0x12 # All fingers yaw joint load/current threshold + ROOT1_TORQUE = 0x13 # All fingers root1 joint load/current threshold + ROOT2_TORQUE = 0x14 # All fingers root2 joint load/current threshold + ROOT3_TORQUE = 0x15 # All fingers root3 joint load/current threshold + TIP_TORQUE = 0x16 # All fingers tip joint load/current threshold + ROLL_FAULT = 0x19 # All fingers roll joint fault + YAW_FAULT = 0x1A # All fingers yaw joint fault + ROOT1_FAULT = 0x1B # All fingers root1 joint fault + ROOT2_FAULT = 0x1C # All fingers root2 joint fault + ROOT3_FAULT = 0x1D # All fingers root3 joint fault + TIP_FAULT = 0x1E # All fingers tip joint fault + ROLL_TEMPERATURE = 0x21 # All fingers roll joint temperature + YAW_TEMPERATURE = 0x22 # All fingers yaw joint temperature + ROOT1_TEMPERATURE = 0x23 # All fingers root1 joint temperature + ROOT2_TEMPERATURE = 0x24 # All fingers root2 joint temperature + ROOT3_TEMPERATURE = 0x25 # All fingers root3 joint temperature + TIP_TEMPERATURE = 0x26 # All fingers tip joint temperature + FINGER_SPEED = 0x81 # Per-finger speed + FINGER_TORQUE = 0x82 # Per-finger torque/current threshold + FINGER_FAULT = 0x83 # Per-finger fault + FINGER_TEMPERATURE = 0x84 # Per-finger temperature HAND_UID = 0xC0 # Device unique identifier Read only -------- HAND_HARDWARE_VERSION = 0xC1 # Hardware version Read only -------- HAND_SOFTWARE_VERSION = 0xC2 # Software version Read only -------- @@ -42,9 +61,13 @@ class LinkerHandL20Can: self.running = True self.x05 = [255] * 5 self.x06, self.x07 = [],[] + self.x09, self.x0a, self.x0b, self.x0c, self.x0d, self.x0e = [[-1] * 5 for _ in range(6)] + self.x11, self.x12, self.x13, self.x14, self.x15, self.x16 = [[-1] * 5 for _ in range(6)] + self.x19, self.x1a, self.x1b, self.x1c, self.x1d, self.x1e = [[-1] * 5 for _ in range(6)] + self.x21, self.x22, self.x23, self.x24, self.x25, self.x26 = [[-1] * 5 for _ in range(6)] + self.x81, self.x82, self.x83, self.x84 = [[-1] * 5 for _ in range(4)] # New pressure sensors self.xb0,self.xb1,self.xb2,self.xb3,self.xb4,self.xb5 = [-1] * 5,[-1] * 5,[-1] * 5,[-1] * 5,[-1] * 5,[-1] * 5 - self.x09 = self.x0b = self.x0c = self.x0d = [-1] * 5 self.thumb_matrix = np.full((12, 6), -1) self.index_matrix = np.full((12, 6), -1) self.middle_matrix = np.full((12, 6), -1) @@ -89,12 +112,12 @@ class LinkerHandL20Can: self.normal_force, self.tangential_force, self.tangential_force_dir, self.approach_inc = \ [[-1] * 5 for _ in range(4)] - # Start receive thread - self.get_touch_type() - time.sleep(0.1) + # Start receive thread before querying touch type so replies can be processed. self.receive_thread = threading.Thread(target=self.receive_response) self.receive_thread.daemon = True self.receive_thread.start() + self.get_touch_type() + time.sleep(0.1) def init_can_bus(self, channel, baudrate): """ @@ -168,16 +191,16 @@ class LinkerHandL20Can: def set_finger_base(self, angles): - self.send_command(FrameProperty.JOINT_PITCH_NR, angles) + self.send_command(FrameProperty.ROOT1_POS, angles) def set_finger_tip(self, angles): - self.send_command(FrameProperty.JOINT_TIP_NR, angles) + self.send_command(FrameProperty.TIP_POS, angles) def set_finger_middle(self, angles): - self.send_command(FrameProperty.JOINT_YAW_NR, angles) + self.send_command(FrameProperty.YAW_POS, angles) def set_thumb_roll(self, angle): - self.send_command(FrameProperty.JOINT_ROLL_NR, angle) + self.send_command(FrameProperty.ROLL_POS, angle) def send_command(self, frame_property, data_list,sleep=0.002): frame_property_value = int(frame_property.value) if hasattr(frame_property, 'value') else frame_property @@ -202,35 +225,36 @@ class LinkerHandL20Can: self.send_command(frame, angles) def set_joint_yaw(self, angles): - self.send_command(0x02, angles) + self.send_command(FrameProperty.YAW_POS, angles) def set_joint_roll(self, thumb_roll): - self.send_command(0x03, [thumb_roll, 0, 0, 0, 0]) + self.send_command(FrameProperty.ROLL_POS, [thumb_roll, 0, 0, 0, 0]) def set_joint_speed(self, speed): - self.x05 = speed - self.send_command(0x05, speed) + self.x81 = speed + self.send_command(FrameProperty.FINGER_SPEED, speed) def set_electric_current(self, e_c=[]): - self.send_command(0x06, e_c) + self.x82 = e_c + self.send_command(FrameProperty.FINGER_TORQUE, e_c) def get_normal_force(self): - self.send_command(0x20,[]) + self.send_command(0x90, []) def get_tangential_force(self): - self.send_command(0x21,[]) + self.send_command(0x91, []) def get_tangential_force_dir(self): - self.send_command(0x22,[]) + self.send_command(0x92, []) def get_approach_inc(self): - self.send_command(0x23,[]) + self.send_command(0x93, []) def get_electric_current(self, e_c=[]): - self.send_command(0x06, e_c) + self.send_command(FrameProperty.FINGER_TORQUE, e_c) def request_device_info(self): self.send_command(0xC0, [0]) @@ -263,28 +287,73 @@ class LinkerHandL20Can: self.x05 = list(response_data) elif frame_type == 0x06: self.x06 = list(response_data) - elif frame_type == 0x07: - self.x07 = list(response_data) elif frame_type == 0x09: self.x09 = list(response_data) + elif frame_type == 0x0A: + self.x0a = list(response_data) elif frame_type == 0x0B: self.x0b = list(response_data) elif frame_type == 0x0C: self.x0c = list(response_data) elif frame_type == 0x0D: self.x0d = list(response_data) + elif frame_type == 0x0E: + self.x0e = list(response_data) + elif frame_type == 0x11: + self.x11 = list(response_data) + elif frame_type == 0x12: + self.x12 = list(response_data) + elif frame_type == 0x13: + self.x13 = list(response_data) + elif frame_type == 0x14: + self.x14 = list(response_data) + elif frame_type == 0x15: + self.x15 = list(response_data) + elif frame_type == 0x16: + self.x16 = list(response_data) + elif frame_type == 0x19: + self.x19 = list(response_data) + elif frame_type == 0x1A: + self.x1a = list(response_data) + elif frame_type == 0x1B: + self.x1b = list(response_data) + elif frame_type == 0x1C: + self.x1c = list(response_data) + elif frame_type == 0x1D: + self.x1d = list(response_data) + elif frame_type == 0x1E: + self.x1e = list(response_data) elif frame_type == 0x20: d = list(response_data) self.normal_force = [float(i) for i in d] elif frame_type == 0x21: - d = list(response_data) - self.tangential_force = [float(i) for i in d] + self.x21 = list(response_data) elif frame_type == 0x22: - d = list(response_data) - self.tangential_force_dir = [float(i) for i in d] + self.x22 = list(response_data) elif frame_type == 0x23: - d = list(response_data) - self.approach_inc = [float(i) for i in d] + self.x23 = list(response_data) + elif frame_type == 0x24: + self.x24 = list(response_data) + elif frame_type == 0x25: + self.x25 = list(response_data) + elif frame_type == 0x26: + self.x26 = list(response_data) + elif frame_type == 0x81: + self.x81 = list(response_data) + elif frame_type == 0x82: + self.x82 = list(response_data) + elif frame_type == 0x83: + self.x83 = list(response_data) + elif frame_type == 0x84: + self.x84 = list(response_data) + elif frame_type == 0x90: + self.normal_force = [float(i) for i in list(response_data)] + elif frame_type == 0x91: + self.tangential_force = [float(i) for i in list(response_data)] + elif frame_type == 0x92: + self.tangential_force_dir = [float(i) for i in list(response_data)] + elif frame_type == 0x93: + self.approach_inc = [float(i) for i in list(response_data)] elif frame_type == 0xb0: self.xb0 = list(response_data) elif frame_type == 0xb1: @@ -350,57 +419,56 @@ class LinkerHandL20Can: if len(speed) != 5: raise ValueError("Speed list must have 5 elements.") return - self.send_command(0x05,speed) + self.x81 = speed + self.send_command(FrameProperty.FINGER_SPEED, speed) def set_torque(self, torque=[]): '''Set torque, not supported for L20''' print("Set torque, not supported for L20") def set_current(self, current=[]): - '''Set current''' - self.set_electric_current(e_c=current) + '''Set per-finger torque/current threshold.''' + self.x82 = current + self.send_command(FrameProperty.FINGER_TORQUE, current) def get_version(self): '''Get version, currently not supported''' return [0] * 5 def get_current_status(self): '''Get current finger joint status''' - self.send_command(0x01,[],sleep=0.01) - self.send_command(0x02,[],sleep=0.01) - self.send_command(0x03,[],sleep=0.01) - self.send_command(0x04,[],sleep=0.01) - return self.x01 + self.x02 + self.x03 + self.x04 + self.send_command(FrameProperty.ROOT1_POS, [], sleep=0.01) + self.send_command(FrameProperty.YAW_POS, [], sleep=0.01) + self.send_command(FrameProperty.ROLL_POS, [], sleep=0.01) + self.send_command(FrameProperty.TIP_POS, [], sleep=0.01) + return self.x03 + self.x02 + self.x01 + self.x06 def get_current_pub_status(self): time.sleep(0.01) - return self.x01 + self.x02 + self.x03 + self.x04 + return self.x03 + self.x02 + self.x01 + self.x06 def get_speed(self): '''Get current motor speed''' - self.send_command(0x05, [0]) + self.send_command(FrameProperty.FINGER_SPEED, []) time.sleep(0.001) - return self.x05 + return self.x81 def get_current(self): - '''Get current threshold''' - self.send_command(0x06, [0]) - return self.x06 + '''Get per-finger torque/current threshold.''' + self.send_command(FrameProperty.FINGER_TORQUE, []) + return self.x82 def get_torque(self): - '''Get current motor torque, not supported for L20''' - return [0] * 5 + '''Get current motor torque/current threshold.''' + self.send_command(FrameProperty.FINGER_TORQUE, []) + return self.x82 def get_fault(self): - self.send_command(0x07,[]) + self.send_command(FrameProperty.FINGER_FAULT, []) time.sleep(0.01) - return self.x07 + return self.x83 def get_temperature(self): '''Get motor temperature''' - self.send_command(0x09,[]) - self.send_command(0x0b,[]) - self.send_command(0x0c,[]) - self.send_command(0x0d,[]) - - return self.x09+self.x0b+self.x0c+self.x0d + self.send_command(FrameProperty.FINGER_TEMPERATURE, []) + return self.x84 def clear_faults(self): '''Clear motor faults''' - self.send_command(0x07, [1, 1, 1, 1, 1]) + self.send_command(FrameProperty.FINGER_FAULT, [1, 1, 1, 1, 1]) def get_touch_type(self): '''Get touch type''' @@ -412,7 +480,7 @@ class LinkerHandL20Can: elif self.xb0 == [1]: return 1 else: - self.send_command(0x20,[],sleep=0.03) + self.send_command(0x90, [], sleep=0.03) time.sleep(0.01) if self.normal_force[0] == -1: return -1 @@ -458,8 +526,8 @@ class LinkerHandL20Can: def get_faults(self): '''Get motor fault codes''' - self.send_command(0x07, []) - return self.x07 + self.send_command(FrameProperty.FINGER_FAULT, []) + return self.x83 def get_force(self): '''Get pressure sensor data''' return [self.normal_force,self.tangential_force,self.tangential_force_dir,self.approach_inc] diff --git a/src/linker_hand_ros2_sdk/linker_hand_ros2_sdk/__pycache__/linker_hand.cpython-312.pyc b/src/linker_hand_ros2_sdk/linker_hand_ros2_sdk/__pycache__/linker_hand.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..408d74998a3a1917b805ae8c8c4a2f6744916b11 GIT binary patch literal 36093 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 Ph0l-9=rUwQq>}#+k&}M$ literal 0 HcmV?d00001 diff --git a/src/linker_hand_ros2_sdk/linker_hand_ros2_sdk/linker_hand.py b/src/linker_hand_ros2_sdk/linker_hand_ros2_sdk/linker_hand.py index 6e7d22f..34d4e1d 100644 --- a/src/linker_hand_ros2_sdk/linker_hand_ros2_sdk/linker_hand.py +++ b/src/linker_hand_ros2_sdk/linker_hand_ros2_sdk/linker_hand.py @@ -192,6 +192,12 @@ class LinkerHand(Node): self.matrix_touch_pub = self.create_publisher(String, self.topic(f'/cb_{self.hand_type}_hand_matrix_touch'), 10) self.matrix_touch_pub_pc = self.create_publisher(PointCloud2, self.topic(f'/cb_{self.hand_type}_hand_matrix_touch_pc'), 10) self.matrix_touch_mass_pub = self.create_publisher(String, self.topic(f'/cb_{self.hand_type}_hand_matrix_touch_mass'), 10) + elif self.hand_joint == "L20": + ColorMsg(msg=f"{self.hand_type} {self.hand_joint} matrix pressure sensing enabled", color='green') + self.touch_type = 2 + self.matrix_touch_pub = self.create_publisher(String, self.topic(f'/cb_{self.hand_type}_hand_matrix_touch'), 10) + self.matrix_touch_pub_pc = self.create_publisher(PointCloud2, self.topic(f'/cb_{self.hand_type}_hand_matrix_touch_pc'), 10) + self.matrix_touch_mass_pub = self.create_publisher(String, self.topic(f'/cb_{self.hand_type}_hand_matrix_touch_mass'), 10) elif self.touch_type > 1: ColorMsg(msg=f"{self.hand_type} {self.hand_joint} Equipped with matrix pressure sensing", color='green') self.matrix_touch_pub = self.create_publisher(String, self.topic(f'/cb_{self.hand_type}_hand_matrix_touch'), 10) @@ -223,7 +229,7 @@ class LinkerHand(Node): pose = [255, 200, 255, 255, 255, 255, 180, 180, 180, 41] speed = [200, 250, 250, 250, 250, 250, 250, 250, 250, 250] elif self.hand_joint == "L20": - pose = [255,255,255,255,255,255,10,100,180,240,245,255,255,255,255,255,255,255,255,255] + pose = None elif self.hand_joint == "G20": # G20 uses a different CAN protocol from L20 even though both # expose a 20-value ROS command. This is the calibrated startup @@ -236,8 +242,19 @@ class LinkerHand(Node): elif self.hand_joint == "L25": pose = [75, 255, 255, 255, 255, 176, 97, 81, 114, 147, 202, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255] if self.startup_pose: - if pose is None or len(self.startup_pose) != len(pose): - expected = 0 if pose is None else len(pose) + expected_lengths = { + "O6": 6, + "L6": 6, + "L6P": 6, + "L7": 7, + "L10": 10, + "L20": 20, + "G20": 20, + "L21": 25, + "L25": 25, + } + expected = expected_lengths.get(str(self.hand_joint).upper(), 0) + if len(self.startup_pose) != expected: raise ValueError( f'startup_pose for {self.hand_joint} must contain {expected} values' ) @@ -376,7 +393,6 @@ class LinkerHand(Node): } if self.run_count == 9: - self.api.clear_faults() # 自动清除错误编码 self.run_count = 0 self.run_count += 1 time.sleep(0.003)