🤚Dexterous hands
Adam can be equipped with Inspire Robotics' humanoid five-fingered dexterous hand. This dexterous hand has 6 degrees of freedom and 12 moving joints, and can simulate human hands to achieve complex actions.
🕹️Control method
The official dexterous hand defaults to using serial port/485 communication for control. Adam will use a passthrough module to convert it to Ethernet protocol, making it a node sub-device of Adam, facilitating Ethernet operations such as tcp/udp and better integrating into the Adam robot ecosystem.
- Communication process:
udp/tcp
<->serial port
<->485
<->hand
.
The following control example uses udp to control five fingers.
id | 0 | 1 | 2 | 3 | 4 | 5 |
---|---|---|---|---|---|---|
Joint | pinky | ring | middle | index | thumb-bend | thumb-rotation |
The above id corresponds to the control of each finger and corresponds to the numerical input order of the write6
function in the following demo.
🐍Python demo
import serial
import time
import socket
# Hand address and port
global addr, port
addr = '10.10.10.180'
port = 2333
regdict = {
'ID': 1000,
'baudrate': 1001,
'clearErr': 1004,
'forceClb': 1009,
'angleSet': 1486,
'forceSet': 1498,
'speedSet': 1522,
'angleAct': 1546,
'forceAct': 1582,
'errCode': 1606,
'statusCode': 1612,
'temp': 1618,
'actionSeq': 2320,
'actionRun': 2322
}
def writeRegister(ser, id, add, num, val):
global addr, port
sbytes = [0xEB, 0x90]
sbytes.append(id) # Device id
sbytes.append(num + 3) # Data length
sbytes.append(0x12) # Command
sbytes.append(add & 0xFF)
sbytes.append((add >> 8) & 0xFF) # Address
for i in range(num):
sbytes.append(val[i])
# Checksum
checksum = 0x00
for i in range(2, len(sbytes)):
checksum += sbytes[i]
checksum &= 0xFF
sbytes.append(checksum)
# Send data
ser.sendto(bytes(sbytes), (addr, port))
time.sleep(0.01)
# Receive data
recv = ser.recv(1024)
print(recv)
def readRegister(ser, id, add, num, mute=False):
sbytes = [0xEB, 0x90]
sbytes.append(id) # Device ID
sbytes.append(0x04) # Data length
sbytes.append(0x11) # Command
sbytes.append(add & 0xFF)
sbytes.append((add >> 8) & 0xFF) # Address
sbytes.append(num)
# Checksum
checksum = 0x00
for i in range(2, len(sbytes)):
checksum += sbytes[i]
checksum &= 0xFF
sbytes.append(checksum)
# Send data
ser.sendto(bytes(sbytes), (addr, port))
time.sleep(0.01)
# Receive data
recv = ser.recv(1024)
if len(recv) == 0:
return []
num = (recv[3] & 0xFF) - 3
val = []
for i in range(num):
val.append(recv[7 + i])
if not mute:
print('read:', end='')
for i in range(num):
print(val[i], end=' ')
print()
return val
def write6(ser, id, str, val):
if str == 'angleSet' or str == 'forceSet' or str == 'speedSet':
val_reg = []
for i in range(6):
val_reg.append(val[i] & 0xFF)
val_reg.append((val[i] >> 8) & 0xFF)
writeRegister(ser, id, regdict[str], 12, val_reg)
else:
print('Function error. Correct way: str set to \'angleSet\'/\'forceSet\'/\'speedSet\'. val is a list of length 6, with values ranging from 0 to 1000. -1 is allowed as a placeholder.')
def read6(ser, id, str):
if str == 'angleSet' or str == 'forceSet' or str == 'speedSet' or str == 'angleAct' or str == 'forceAct':
val = readRegister(ser, id, regdict[str], 12, True)
if len(val) < 12:
print('no data')
return
val_act = []
for i in range(6):
val_act.append((val[2*i] & 0xFF) + (val[1 + 2*i] << 8))
print('read:', end='')
for i in range(6):
print(val_act[i], end=' ')
print()
elif str == 'errCode' or str == 'statusCode' or str == 'temp':
val_act = readRegister(ser, id, regdict[str], 6, True)
if len(val_act) < 6:
print('Not received data')
return
print('read:', end='')
for i in range(6):
print(val_act[i], end=' ')
print()
else:
print('Function error. Correct way: str set to \'angleSet\'/\'forceSet\'/\'speedSet\'/\'angleAct\'/\'forceAct\'/\'errCode\'/\'statusCode\'/\'temp\'')
if __name__ == '__main__':
ser = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
ser.settimeout(1)
print('Set dexterous hand motion angle parameters. --1 means not to set the motion angle!')
write6(ser, 1, 'speedSet', [100, 100, 100, 100, 100, 100])
time.sleep(2)
print('Set dexterity hand grip strength parameters!')
write6(ser, 1, 'forceSet', [500, 500, 500, 500, 500, 500])
time.sleep(1)
print('Set dexterous hand motion angle parameters0. --1 means not to set the motion angle!')
write6(ser, 1, 'angleSet', [0, 0, 0, 0, 400, -1])
time.sleep(3)
# Read the actual angle
read6(ser, 1, 'angleAct')
time.sleep(1)
print('Set dexterous hand motion angle parameters: 1000. --1 means not to set the motion angle!')
write6(ser, 1, 'angleSet', [1000, 1000, 1000, 1000, 400, -1])
time.sleep(3)
# Read the actual angle
read6(ser, 1, 'angleAct')
time.sleep(1)
# Read error code
read6(ser, 1, 'errCode')
time.sleep(1)
print('Set up a dexterity library sequence: 8!')
writeRegister(ser, 1, regdict['actionSeq'], 1, [8])
time.sleep(1)
print('Run the current sequence of dexterous hand actions!')
writeRegister(ser, 1, regdict['actionRun'], 1, [1])