🤚Inspire 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:
TCP/UDP<->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 time
import socket
import threading
import signal
import sys
global port
port = 2562
addr_l = '10.10.10.18'
addr_r = '10.10.10.38'
global cnt
cnt = 0
global sok_l,sok_r
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, addr, id, add, num, val):
global port
sbytes = [0xEB, 0x90]
sbytes.append(id) # id
sbytes.append(num + 3) # len
sbytes.append(0x12) # cmd
sbytes.append(add & 0xFF)
sbytes.append((add >> 8) & 0xFF) # add
for i in range(num):
sbytes.append(val[i])
checksum = 0x00
for i in range(2, len(sbytes)):
checksum += sbytes[i]
checksum &= 0xFF
sbytes.append(checksum)
ser.sendto(bytes(sbytes),(addr,port))
time.sleep(0.01)
recv = ser.recv(1024)
# print(recv)
def readRegister(ser, addr, id, add, num, mute=False):
sbytes = [0xEB, 0x90]
sbytes.append(id) # id
sbytes.append(0x04) # len
sbytes.append(0x11) # cmd
sbytes.append(add & 0xFF)
sbytes.append((add >> 8) & 0xFF) # add
sbytes.append(num)
checksum = 0x00
for i in range(2, len(sbytes)):
checksum += sbytes[i]
checksum &= 0xFF
sbytes.append(checksum)
ser.sendto(bytes(sbytes),(addr,port))
time.sleep(0.01)
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 register:', end='')
for i in range(num):
print(val[i], end=' ')
print()
return val
def write6(ser, addr, 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, addr, id, regdict[str], 12, val_reg)
def read6(ser, addr, id, str):
if str == 'angleSet' or str == 'forceSet' or str == 'speedSet' or str == 'angleAct' or str == 'forceAct':
val = readRegister(ser,addr, id, regdict[str], 12, True)
if len(val) < 12:
print('not read data')
return
val_act = []
for i in range(6):
val_act.append((val[2*i] & 0xFF) + (val[1 + 2*i] << 8))
return val_act
# print('read value:', 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,addr, id, regdict[str], 6, True)
if len(val_act) < 6:
print('not read data')
return None
return val_act
# print('read value:', end='')
# for i in range(6):
# print(val_act[i], end=' ')
# print()
def timer_thread():
global cnt
while True:
time.sleep(1)
print(cnt)
cnt = 0
def hand_ctrl(lr,str,val):
global sok_l,sok_r
if lr == 'l':
write6(sok_l, addr_l, 1, str, val)
elif lr == 'r':
write6(sok_r, addr_r, 1, str, val)
def hand_get(lr,str='angleAct'):
global sok_l,sok_r
if lr == 'l':
return read6(sok_l, addr_l, 1, str)
elif lr == 'r':
return read6(sok_r, addr_r, 1, str)
def hand_l_thread():
global cnt
hand_ctrl('l','speedSet',[800, 800, 800, 800, 800, 800])
time.sleep(1)
hand_ctrl('l','forceSet',[600, 600, 600, 600, 600, 600])
time.sleep(1)
hand_ctrl('l','angleSet',[1000, 1000, 1000, 1000, 1000, 1000])
time.sleep(2)
loop = True
while loop:
print(hand_get('l','angleAct'))
print(hand_get('l','forceAct'))
hand_ctrl('l','angleSet',[1000, 1000, 1000, 1000, 1000, 1000])
time.sleep(1)
hand_ctrl('l','angleSet',[0, 0, 0, 0, 1000, 1000])
time.sleep(1)
hand_ctrl('l','angleSet',[1000, 1000, 1000, 1000, 1000, 1000])
time.sleep(1)
hand_ctrl('l','angleSet',[1000, 1000, 1000, 1000, 0, 0])
time.sleep(1)
def hand_r_thread():
global cnt
hand_ctrl('r','speedSet',[800, 800, 800, 800, 800, 800])
time.sleep(1)
hand_ctrl('r','forceSet',[600, 600, 600, 600, 600, 600])
time.sleep(1)
hand_ctrl('r','angleSet',[1000, 1000, 1000, 1000, 1000, 1000])
time.sleep(2)
loop = True
while loop:
print(hand_get('r','angleAct'))
print(hand_get('r','forceAct'))
hand_ctrl('r','angleSet',[1000, 1000, 1000, 1000, 1000, 1000])
time.sleep(1)
hand_ctrl('r','angleSet',[0, 0, 0, 0, 1000, 1000])
time.sleep(1)
hand_ctrl('r','angleSet',[1000, 1000, 1000, 1000, 1000, 1000])
time.sleep(1)
hand_ctrl('r','angleSet',[1000, 1000, 1000, 1000, 0, 0])
time.sleep(1)
def sig_handler(signum, frame):
#is_exit = True
print('You pressed Ctrl + C!')
sys.exit(0)
sok_l = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sok_l.settimeout(1)
sok_r = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sok_r.settimeout(1)
signal.signal(signal.SIGINT,sig_handler)
# t1 = threading.Thread(target=timer_thread)
# t1.daemon = True
# t1.start()
t2 = threading.Thread(target=hand_l_thread)
t2.daemon = True
t2.start()
t3 = threading.Thread(target=hand_r_thread)
t3.daemon = True
t3.start()
while True:
time.sleep(1)