2022-07-13 15:11:25 +00:00
|
|
|
import rtde_control #pip install ur_rtde
|
|
|
|
#pip install ur_rtde
|
|
|
|
#use python 3.9
|
|
|
|
#use min PIP 19
|
|
|
|
#check /Python/Python39/Lib/site-packages/ if install was done in correct Python version
|
|
|
|
#Visual Studio >= 2019 must be installed with C++ Packages
|
|
|
|
#boost must be installed (https://www.boost.org/)
|
|
|
|
#"Modul wurde nicht gefunden" Error indicates missing dependencies
|
|
|
|
#use https://github.com/lucasg/Dependencies/releases to check missing dependencies (drop rtde.dll, from /Python/Python39/Lib/site-packages/)
|
2022-07-13 15:11:55 +00:00
|
|
|
#magic-trick: copy missing DLL from boost directory into python site-packages folder
|
2022-07-13 15:11:25 +00:00
|
|
|
|
2022-06-10 13:08:48 +00:00
|
|
|
import rtde_receive
|
|
|
|
import time
|
|
|
|
import math
|
|
|
|
import socket
|
|
|
|
import numpy as np
|
|
|
|
|
|
|
|
import pygame
|
|
|
|
|
2022-06-14 18:01:12 +00:00
|
|
|
use_rtde=True
|
2022-06-10 13:08:48 +00:00
|
|
|
|
|
|
|
pygame.init()
|
|
|
|
width=500
|
|
|
|
height=500
|
|
|
|
screen = pygame.display.set_mode([width, height])
|
|
|
|
running = True
|
|
|
|
|
|
|
|
c_border = (100,100,100)
|
|
|
|
c_name=(200,200,200)
|
|
|
|
c_cursor = (255,255,255)
|
|
|
|
c_text=(255,255,255)
|
|
|
|
|
|
|
|
def mapFromTo(x,a,b,c,d):
|
|
|
|
y=(x-a)/(b-a)*(d-c)+c
|
|
|
|
return y
|
|
|
|
|
|
|
|
def text_to_screen(screen, text, x, y, size = 50,
|
|
|
|
color = (200, 000, 000)):
|
|
|
|
|
|
|
|
text = str(text)
|
|
|
|
font = pygame.font.SysFont(None, size)
|
|
|
|
text = font.render(text, True, color)
|
|
|
|
screen.blit(text, (x, y))
|
|
|
|
|
|
|
|
|
|
|
|
def drawBar(screen,_topleft,_size,_pos,_name,_text):
|
|
|
|
pygame.draw.rect(screen, c_border, (_topleft[0],_topleft[1],_size[0],_size[1]))
|
|
|
|
text_to_screen(screen,_name,_topleft[0],_topleft[1],_size[1],c_name)
|
|
|
|
pygame.draw.line(screen, c_cursor, (_topleft[0]+_pos*_size[0],_topleft[1]),(_topleft[0]+_pos*_size[0],_topleft[1]+_size[1]))
|
|
|
|
text_to_screen(screen,_text,_size[0]+_topleft[0],_topleft[1],_size[1],c_text)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Socket stuff
|
|
|
|
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
|
|
host =""
|
|
|
|
port =30002
|
|
|
|
s.bind((host,port))
|
|
|
|
s.listen(1) # Number of connections
|
|
|
|
s.setblocking(False)
|
|
|
|
client = None
|
|
|
|
|
|
|
|
|
|
|
|
# Robot Control Stuff
|
|
|
|
if use_rtde:
|
|
|
|
rtde_c = rtde_control.RTDEControlInterface("192.168.1.101")
|
|
|
|
rtde_r = rtde_receive.RTDEReceiveInterface("192.168.1.101")
|
|
|
|
|
|
|
|
def toRad(d):
|
|
|
|
return d/360*2*math.pi
|
|
|
|
|
|
|
|
def toDeg(r):
|
|
|
|
return r*360/2/math.pi
|
|
|
|
|
|
|
|
|
|
|
|
def RPYtoVec(roll,pitch,yaw):
|
|
|
|
yawMatrix = np.matrix([
|
|
|
|
[math.cos(yaw), -math.sin(yaw), 0],
|
|
|
|
[math.sin(yaw), math.cos(yaw), 0],
|
|
|
|
[0, 0, 1]
|
|
|
|
])
|
|
|
|
|
|
|
|
pitchMatrix = np.matrix([
|
|
|
|
[math.cos(pitch), 0, math.sin(pitch)],
|
|
|
|
[0, 1, 0],
|
|
|
|
[-math.sin(pitch), 0, math.cos(pitch)]
|
|
|
|
])
|
|
|
|
|
|
|
|
rollMatrix = np.matrix([
|
|
|
|
[1, 0, 0],
|
|
|
|
[0, math.cos(roll), -math.sin(roll)],
|
|
|
|
[0, math.sin(roll), math.cos(roll)]
|
|
|
|
])
|
|
|
|
|
|
|
|
R = yawMatrix * pitchMatrix * rollMatrix
|
|
|
|
|
|
|
|
theta = math.acos(((R[0, 0] + R[1, 1] + R[2, 2]) - 1) / 2)
|
|
|
|
multi = 1 / (2 * math.sin(theta))
|
|
|
|
|
|
|
|
rx = multi * (R[2, 1] - R[1, 2]) * theta
|
|
|
|
ry = multi * (R[0, 2] - R[2, 0]) * theta
|
|
|
|
rz = multi * (R[1, 0] - R[0, 1]) * theta
|
|
|
|
|
|
|
|
return rx, ry, rz
|
|
|
|
|
|
|
|
paused=True
|
|
|
|
|
|
|
|
|
|
|
|
if use_rtde:
|
|
|
|
actual_q = rtde_r.getActualQ() #current joint rotations in radians.
|
|
|
|
print("Actual Q:"+str(actual_q))
|
|
|
|
#fw_actual_q = rtde_c.getForwardKinematics(actual_q)
|
|
|
|
fw_actual_q = rtde_c.getForwardKinematics()
|
|
|
|
print("forward Actual Q:"+str(fw_actual_q))
|
|
|
|
joint_q=rtde_c.getInverseKinematics(fw_actual_q)
|
|
|
|
print("Final Q:"+str(joint_q))
|
|
|
|
|
|
|
|
winkellimit=45
|
|
|
|
|
2022-06-14 18:01:12 +00:00
|
|
|
maxbasedeviation=60 # in degrees, maximum rotation deviation from 0°
|
|
|
|
basespeed=1.5
|
2022-06-10 13:08:48 +00:00
|
|
|
distfromcenter=0.9
|
|
|
|
basedeviation=0
|
|
|
|
centerpos=[math.cos(toRad(180))*distfromcenter,math.sin(toRad(180))*distfromcenter,0.91]
|
|
|
|
#centerpos=[-0.895,-0.177,0.91]
|
|
|
|
centerrotRPY=[-1.572,0,1.572] #roll, pitch, yaw
|
|
|
|
|
|
|
|
pan=0 #-=left, +=right, degrees
|
|
|
|
tilt=0 #-=down, +=up, degrees
|
|
|
|
|
|
|
|
joint_q_init=[0,toRad(-90),toRad(90),toRad(-180),toRad(-90),toRad(0)] #start position
|
|
|
|
joint_q=joint_q_init
|
|
|
|
|
|
|
|
|
|
|
|
#rtde_c.moveJ([0,toRad(-90),toRad(90-tilt/2),toRad(-180-tilt/2),toRad(-90-pan),toRad(0)],0.1,0.1)
|
|
|
|
if use_rtde:
|
|
|
|
rtde_c.moveJ(joint_q,0.2,0.1) #move to initial position
|
|
|
|
|
|
|
|
|
|
|
|
# Parameters
|
|
|
|
|
|
|
|
|
|
|
|
velocity = 0.2 #0.5
|
|
|
|
acceleration = 0.1 #0.5
|
|
|
|
frequency= 100
|
|
|
|
dt = 1.0/frequency # 2ms
|
|
|
|
lookahead_time = 0.1
|
|
|
|
gain = 300
|
|
|
|
|
|
|
|
|
|
|
|
speed_1=[0.2,0.2,0.2,0.2,0.2,0.2]
|
2022-06-14 18:01:12 +00:00
|
|
|
speed_2=[0.5,0.5,0.5,1,1,1]
|
|
|
|
speed_3=[1,1,1,3,3,3]
|
|
|
|
speed_4=[2,2,2,4,4,4]
|
2022-06-10 13:08:48 +00:00
|
|
|
|
|
|
|
speed=speed_1
|
|
|
|
|
|
|
|
|
|
|
|
joint_min=[toRad(-90),toRad(-90-40),toRad(90-90),toRad(-180-80),toRad(-90-90),toRad(0-75)]
|
|
|
|
joint_max=[toRad(90),toRad(-90+40),toRad(90+40),toRad(-180+110),toRad(-90+90),toRad(0+75)]
|
|
|
|
|
2022-08-23 08:01:34 +00:00
|
|
|
manual_pan=0
|
|
|
|
manual_tilt=0
|
|
|
|
manual_last_time=0
|
|
|
|
manual_speed=0.5
|
|
|
|
|
2022-06-10 13:08:48 +00:00
|
|
|
|
|
|
|
def constrain(v,_min,_max):
|
|
|
|
return min(_max,max(_min,v))
|
|
|
|
|
|
|
|
|
2022-06-10 13:57:28 +00:00
|
|
|
receivetimearray=np.zeros(100)
|
|
|
|
receivetimearray_pos=0
|
|
|
|
time_last_data_received=time.time()
|
2022-06-10 13:08:48 +00:00
|
|
|
while running:
|
|
|
|
|
|
|
|
start = time.time()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for event in pygame.event.get():
|
|
|
|
if event.type == pygame.KEYDOWN:
|
|
|
|
if event.key == pygame.K_p and paused==False:
|
|
|
|
print("paused")
|
|
|
|
paused=True
|
|
|
|
if event.key == pygame.K_s and paused==True:
|
|
|
|
print("resumed")
|
|
|
|
paused=False
|
|
|
|
if event.key == pygame.K_q:
|
|
|
|
print("stop")
|
|
|
|
running=False
|
|
|
|
if event.key == pygame.K_1:
|
|
|
|
speed=speed_1
|
|
|
|
if event.key == pygame.K_2:
|
|
|
|
speed=speed_2
|
|
|
|
if event.key == pygame.K_3:
|
|
|
|
speed=speed_3
|
2022-06-14 18:01:12 +00:00
|
|
|
if event.key == pygame.K_4:
|
|
|
|
speed=speed_4
|
2022-08-23 08:01:34 +00:00
|
|
|
|
2022-06-10 13:08:48 +00:00
|
|
|
|
|
|
|
if event.type == pygame.QUIT:
|
|
|
|
running = False
|
|
|
|
|
2022-08-23 08:01:34 +00:00
|
|
|
|
|
|
|
# Live key movement
|
|
|
|
if time.time()+0.1 >= manual_last_time: #limit frequency. in seconds
|
|
|
|
manual_last_time=time.time()
|
|
|
|
keys = pygame.key.get_pressed()
|
|
|
|
if keys[pygame.K_LEFT]:
|
|
|
|
manual_pan -= manual_speed
|
|
|
|
if keys[pygame.K_RIGHT]:
|
|
|
|
manual_pan += manual_speed
|
|
|
|
if keys[pygame.K_UP]:
|
|
|
|
manual_tilt += manual_speed
|
|
|
|
if keys[pygame.K_DOWN]:
|
|
|
|
manual_tilt -= manual_speed
|
|
|
|
#print("Manual pan="+str(manual_pan)+" tilt="+str(manual_tilt)+" time="+str(time.time()))
|
|
|
|
|
2022-06-10 13:08:48 +00:00
|
|
|
# Receive Socket stuff
|
|
|
|
try:
|
|
|
|
client, address = s.accept()
|
|
|
|
print("Connected to", address)
|
|
|
|
|
|
|
|
except socket.error:
|
|
|
|
pass
|
|
|
|
|
|
|
|
if client is not None:
|
|
|
|
try:
|
|
|
|
data = client.recv( 1024 ).decode( 'utf-8' )
|
|
|
|
if data:
|
|
|
|
lastdata=data.split('\n')
|
2022-06-10 13:57:28 +00:00
|
|
|
_timediff=time.time()-time_last_data_received
|
|
|
|
receivetimearray[receivetimearray_pos]=_timediff
|
|
|
|
receivetimearray_pos+=1
|
|
|
|
receivetimearray_pos%=len(receivetimearray)
|
|
|
|
time_last_data_received=time.time()
|
2022-06-10 13:08:48 +00:00
|
|
|
#print("Received :", repr(data))
|
|
|
|
if (len(lastdata)>1):
|
|
|
|
splitdata=lastdata[-2].split(",")
|
|
|
|
if len(splitdata)==2:
|
|
|
|
try:
|
|
|
|
_pan=float(splitdata[0])
|
|
|
|
_tilt=float(splitdata[1])
|
|
|
|
|
|
|
|
|
|
|
|
if _pan>=-winkellimit and _pan <=winkellimit and _tilt>=-winkellimit and _tilt <=winkellimit:
|
|
|
|
pan=_pan
|
|
|
|
tilt=_tilt
|
|
|
|
|
2022-06-14 18:01:12 +00:00
|
|
|
#print("Pan="+str(pan)+" Tilt="+str(tilt))
|
2022-06-10 13:08:48 +00:00
|
|
|
except ValueError:
|
|
|
|
print("Not a float")
|
|
|
|
except socket.error:
|
|
|
|
pass
|
2022-08-23 08:01:34 +00:00
|
|
|
else:
|
|
|
|
_pan=manual_pan
|
|
|
|
_tilt=manual_tilt
|
|
|
|
|
|
|
|
if _pan>=-winkellimit and _pan <=winkellimit and _tilt>=-winkellimit and _tilt <=winkellimit:
|
|
|
|
pan=_pan
|
|
|
|
tilt=_tilt
|
|
|
|
|
|
|
|
|
2022-06-10 13:08:48 +00:00
|
|
|
|
|
|
|
|
|
|
|
# Robot Control stuff
|
|
|
|
if use_rtde:
|
|
|
|
if not paused:
|
2022-06-14 18:01:12 +00:00
|
|
|
basedeviation=min(maxbasedeviation,max(-maxbasedeviation,basedeviation+pan*basespeed/frequency))
|
|
|
|
basedeviation*=-winkellimit*basespeed/frequency/maxbasedeviation+1
|
2022-06-10 13:57:28 +00:00
|
|
|
basedeviation=min(maxbasedeviation,max(-maxbasedeviation,basedeviation))
|
|
|
|
|
2022-06-10 13:08:48 +00:00
|
|
|
|
|
|
|
baserotation=toRad(180-basedeviation) #positive is ccw
|
|
|
|
centerpos=[math.cos(baserotation)*distfromcenter,math.sin(baserotation)*distfromcenter,0.91]
|
|
|
|
_rot=RPYtoVec(centerrotRPY[0]+toRad(tilt),centerrotRPY[1],centerrotRPY[2]+toRad(-pan))
|
|
|
|
pos_q=[centerpos[0],centerpos[1],centerpos[2],_rot[0],_rot[1],_rot[2]]
|
|
|
|
joint_q_aim=rtde_c.getInverseKinematics(pos_q,joint_q_init)
|
|
|
|
|
|
|
|
#joint_q_aim = rtde_c.getInverseKinematics([-0.895,-0.173,0.911,2.4,2.4,2.4])
|
|
|
|
# inverse kinematics: rx+ =look up
|
|
|
|
# ry+ = look right
|
|
|
|
# rz+ = rotate CW
|
|
|
|
|
|
|
|
|
|
|
|
reachable=rtde_c.isPoseWithinSafetyLimits(pos_q)
|
|
|
|
if not reachable:
|
|
|
|
print("Reachable:"+str(reachable))
|
|
|
|
|
|
|
|
|
|
|
|
insideJointConstraints=True
|
|
|
|
for i in range(6):
|
|
|
|
if joint_q_aim[i]<joint_min[i] or joint_q_aim[i]>joint_max[i]:
|
|
|
|
print("Joint "+str(i)+" Outside constraint with "+str(joint_q_aim[i])+" ("+str(toDeg(joint_q_aim[i]))+")")
|
|
|
|
insideJointConstraints=False
|
|
|
|
|
|
|
|
|
|
|
|
if reachable and insideJointConstraints and not paused:
|
|
|
|
for i in range(6):
|
|
|
|
joint_q[i] += constrain(joint_q_aim[i]-joint_q[i], -speed[i]/frequency,speed[i]/frequency) #constrain joint speeds
|
|
|
|
|
|
|
|
|
|
|
|
#print(joint_q)
|
|
|
|
|
|
|
|
|
|
|
|
if not paused:
|
|
|
|
rtde_c.servoJ(joint_q, velocity, acceleration, dt, lookahead_time, gain)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
screen.fill((0,0,0))
|
|
|
|
#pygame.draw.circle(screen, (0, 0, 255), (250, 250), 75)
|
|
|
|
jointnames=["Base","Shoulder","Elbow","Wrist1","Wrist2","Wrist3"]
|
2022-06-14 18:01:12 +00:00
|
|
|
|
|
|
|
|
|
|
|
drawBar(screen,(10,10+30*0),(100,20),mapFromTo(pan,-winkellimit,winkellimit,0.0,1.0),"Pan",str(round(pan,2))+"°")
|
|
|
|
drawBar(screen,(10,10+30*1),(100,20),mapFromTo(tilt,-winkellimit,winkellimit,0.0,1.0),"Tilt",str(round(tilt,2))+"°")
|
|
|
|
|
2022-06-10 13:08:48 +00:00
|
|
|
|
|
|
|
for i in range(6):
|
2022-06-14 18:01:12 +00:00
|
|
|
drawBar(screen,(10,10+30*(3+i)),(100,20),mapFromTo(joint_q[i],joint_min[i],joint_max[i],0.0,1.0),jointnames[i],str(round(toDeg(joint_q[i]),2))+"°")
|
|
|
|
|
2022-08-23 08:01:34 +00:00
|
|
|
if use_rtde:
|
|
|
|
for i in range(6):
|
|
|
|
_jointdiff = joint_q_aim[i]-joint_q[i]
|
|
|
|
drawBar(screen,(200,10+30*(3+i)),(100,20),mapFromTo(_jointdiff,-speed[i]/frequency,speed[i]/frequency,0.0,1.0),"diff_"+str(jointnames[i]),str(round(toDeg(_jointdiff),3))+"°")
|
2022-06-10 13:08:48 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
2022-06-14 18:01:12 +00:00
|
|
|
drawBar(screen,(10,10+30*10),(100,20),mapFromTo(basedeviation,-maxbasedeviation,maxbasedeviation,0.0,1.0),"basedeviation",str(round(basedeviation,2))+"°")
|
2022-06-10 13:08:48 +00:00
|
|
|
|
2022-06-14 18:01:12 +00:00
|
|
|
drawBar(screen,(200,10+30*10),(100,20),mapFromTo(np.mean(receivetimearray),0,1.0,0.0,1.0),"Receive Interval",str(round(np.mean(receivetimearray),3))+"s")
|
|
|
|
drawBar(screen,(200,10+30*11),(100,20),mapFromTo(np.max(receivetimearray),0,1.0,0.0,1.0),"Max Receive Int.",str(round(np.max(receivetimearray),3))+"s")
|
2022-06-10 13:57:28 +00:00
|
|
|
|
2022-06-10 13:08:48 +00:00
|
|
|
|
|
|
|
text_to_screen(screen,"paused: "+str(paused),10,height-20-12*2-20*3,20,c_text)
|
2022-06-14 18:01:12 +00:00
|
|
|
text_to_screen(screen,"speed: "+str(speed),10,height-20-12*4-20,20,c_text)
|
|
|
|
text_to_screen(screen,"1: "+str(speed_1),10,height-20-12*3,12,c_text)
|
|
|
|
text_to_screen(screen,"2: "+str(speed_2),10,height-20-12*2,12,c_text)
|
|
|
|
text_to_screen(screen,"3: "+str(speed_3),10,height-20-12*1,12,c_text)
|
|
|
|
text_to_screen(screen,"4: "+str(speed_4),10,height-20-12*0,12,c_text)
|
2022-06-10 13:08:48 +00:00
|
|
|
|
|
|
|
text_to_screen(screen,"Press q to stop",250,height-20-20*3,20,c_text)
|
|
|
|
text_to_screen(screen,"Press p to pause",250,height-20-20*2,20,c_text)
|
2022-06-14 18:01:12 +00:00
|
|
|
text_to_screen(screen,"Press 1,2,3,4 to change speed",250,height-20-20*1,20,c_text)
|
2022-06-10 13:08:48 +00:00
|
|
|
text_to_screen(screen,"Press s to resume",250,height-20-20*0,20,c_text)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pygame.display.flip()
|
|
|
|
|
|
|
|
end = time.time()
|
|
|
|
stepduration = end - start
|
|
|
|
|
|
|
|
if stepduration < dt:
|
|
|
|
time.sleep(dt - stepduration)
|
|
|
|
|
|
|
|
print("Finished")
|
|
|
|
|
|
|
|
if use_rtde:
|
|
|
|
rtde_c.servoStop()
|
|
|
|
rtde_c.stopScript()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
s.close()
|
|
|
|
|