Added gamepad support
This commit is contained in:
parent
7052b1271e
commit
063ab4fd43
40
config.py
40
config.py
@ -86,6 +86,9 @@ T_FORCE_VIOLATION = 0.3
|
||||
# Note that the angular velocity is also [m/s], not [rad/s], to ensure that the robot
|
||||
# moves with constant speed regardless of direction in the polar plane.
|
||||
# IMPORTANT: VEL_Z should be tuned to Z_MIN to avoid smashing into the table.
|
||||
#
|
||||
# T_DIR_CHANGE_COOLDOWN is a cooldown between change of commands. With this, the robot
|
||||
# have a chance to decelerate before changing direction, which smooths out motion.
|
||||
VEL = 0.1 #[m/s]
|
||||
VEL_Z = 0.05 #[m/s]
|
||||
ACC = 0.5 #[m/s^2]
|
||||
@ -106,6 +109,43 @@ Z_MAX = TABLE_Z + 4.5*BLOCK_DIM #4 blocks high
|
||||
|
||||
|
||||
|
||||
# GAMEPAD MAP
|
||||
#
|
||||
# For the Microsoft xBox 360 controller. Button/axes codes are listed
|
||||
# below for reference.
|
||||
#
|
||||
# Buttons
|
||||
# A:0
|
||||
# B:1
|
||||
# X:2
|
||||
# Y:3
|
||||
# LB:4
|
||||
# RB:5
|
||||
# Back:6
|
||||
# Start:7
|
||||
BUTTON_MAP = {
|
||||
4: (0, 0, -1),
|
||||
5: (0, 0, 1)
|
||||
}
|
||||
# Hat switch:0 (All or nothing for direction). returns (+-1, +-1) = (+-x. +-y)
|
||||
# hx, hy = hat
|
||||
HATCODE = 0 #set to -1 to avoid polling hat
|
||||
HX = 10
|
||||
HY = 11
|
||||
HAT_MAP = {
|
||||
HX: (0, 1, 0),
|
||||
HY: (-1, 0, 0) #inverted
|
||||
}
|
||||
# Axes (Not supported)
|
||||
# Joystick left, x-axis:0
|
||||
# Joystick left, y-axis:1
|
||||
# Joystick right, x-axis:3
|
||||
# Joystick right, x-axis:4
|
||||
# Left trigger:2
|
||||
# Right trigger:5
|
||||
|
||||
|
||||
|
||||
# AUTO/LOOP CONTROL
|
||||
#
|
||||
# When looping, the robot use the same velocity for r, theta and z.
|
||||
|
||||
BIN
config.pyc
BIN
config.pyc
Binary file not shown.
88
demo.py
88
demo.py
@ -14,6 +14,13 @@ class UR5Demo(object):
|
||||
pygame.display.set_caption("UR5 Demo")
|
||||
self.font = pygame.font.SysFont(None, config.FONTSIZE)
|
||||
|
||||
pygame.joystick.init()
|
||||
self.padcount = pygame.joystick.get_count()
|
||||
self.gamepad = None
|
||||
self.hatcode = config.HATCODE
|
||||
self.hat_map = config.HAT_MAP
|
||||
self.but_map = config.BUTTON_MAP
|
||||
|
||||
# move vectors are in cylinder coords
|
||||
self.kb_map = {
|
||||
pygame.K_UP: (-1,0,0),
|
||||
@ -39,11 +46,21 @@ class UR5Demo(object):
|
||||
msg = []
|
||||
if error:
|
||||
msg.append(error)
|
||||
|
||||
msg.append("Setting robot to freedrive mode...")
|
||||
self._disptxt(msg)
|
||||
try:
|
||||
self.controller.set_freedrive(True)
|
||||
except Exception, e:
|
||||
msg.append("Could not set freedrive mode: %s" % e)
|
||||
self._disptxt(msg)
|
||||
time.sleep(1) # give freedrive mode some time to set
|
||||
|
||||
msg.append("Disconnecting robot...")
|
||||
self._disptxt(msg)
|
||||
if self.controller:
|
||||
self.controller.cleanup()
|
||||
time.sleep(3) # Give the UR5 threads a chance to terminate
|
||||
time.sleep(2) # Give the UR5 threads a chance to terminate
|
||||
msg.append("Exit...")
|
||||
self._disptxt(msg)
|
||||
pygame.quit()
|
||||
@ -216,6 +233,47 @@ class UR5Demo(object):
|
||||
|
||||
self.clock.tick(config.MENU_FPS)
|
||||
|
||||
def gamepad_control(self):
|
||||
t = time.time()
|
||||
running = True
|
||||
while running:
|
||||
pressed = pygame.key.get_pressed()
|
||||
for e in pygame.event.get():
|
||||
if e.type == pygame.QUIT:
|
||||
self.sig_quit = True
|
||||
if pressed[pygame.K_ESCAPE] or self.sig_quit:
|
||||
running = False
|
||||
|
||||
vec = (0,0,0)
|
||||
if self.hatcode >= 0:
|
||||
hx, hy = self.gamepad.get_hat(self.hatcode)
|
||||
mx = [hx*i for i in self.hat_map[config.HX]]
|
||||
my = [hy*i for i in self.hat_map[config.HY]]
|
||||
vec = map(sum, zip(vec, mx, my))
|
||||
for m in (self.but_map[code] for code in self.but_map if self.gamepad.get_button(code) > 0):
|
||||
vec = map(sum, zip(vec, m))
|
||||
|
||||
new_t = time.time()
|
||||
dt = max(new_t-t, 1/config.CTR_FPS)
|
||||
t = new_t
|
||||
|
||||
try:
|
||||
self.controller.update(tuple(vec), dt)
|
||||
except Exception, e:
|
||||
self._disptxt(["Error: %s" % e])
|
||||
time.sleep(2)
|
||||
running = False
|
||||
|
||||
f = self.controller.zforce
|
||||
self._disptxt([
|
||||
"Gamepad control \"%s\"" % self.gamepad.get_name(),
|
||||
" ",
|
||||
"move vec: %s" % str(vec),
|
||||
"dt: %.3f" % dt,
|
||||
"force z: %s %.1f" % (" " if f>0 else "", f)
|
||||
])
|
||||
self.clock.tick(config.CTR_FPS)
|
||||
|
||||
def keyboard_control(self):
|
||||
t = time.time()
|
||||
running = True
|
||||
@ -308,7 +366,10 @@ class UR5Demo(object):
|
||||
self._disptxt(menu)
|
||||
|
||||
elif pressed[pygame.K_c]:
|
||||
self.keyboard_control()
|
||||
if self.gamepad:
|
||||
self.gamepad_control()
|
||||
else:
|
||||
self.keyboard_control()
|
||||
self._disptxt(menu)
|
||||
|
||||
elif pressed[pygame.K_q] or self.sig_quit:
|
||||
@ -325,7 +386,11 @@ class UR5Demo(object):
|
||||
self._disptxt(msg)
|
||||
try:
|
||||
self.controller = DemoController(config)
|
||||
msg.append("Freedrive mode off...")
|
||||
self._disptxt(msg)
|
||||
self.controller.set_freedrive(False)
|
||||
time.sleep(0.5)
|
||||
msg.append("Going to home position...")
|
||||
msg.append("Calibrating cylinder coordinate system...")
|
||||
self._disptxt(msg)
|
||||
self.controller.calibrate_cylinder_sys()
|
||||
@ -333,6 +398,25 @@ class UR5Demo(object):
|
||||
return self.quit(error=("Error: %s" % e))
|
||||
msg.append("Calibration done.")
|
||||
self._disptxt(msg)
|
||||
|
||||
if self.padcount > 0:
|
||||
msg.append("Found %d gamepad" % self.padcount)
|
||||
msg.append("Initializing gamepad..")
|
||||
self._disptxt(msg)
|
||||
try:
|
||||
self.gamepad = pygame.joystick.Joystick(0)
|
||||
self.gamepad.init()
|
||||
except Exception, e:
|
||||
return self.quit(error=("Error: %s" % e))
|
||||
msg.append("Gamepad \"%s\" initialized" % self.gamepad.get_name())
|
||||
else:
|
||||
msg.append("Found no gamepads")
|
||||
msg.append("Using keyboard for manual control")
|
||||
|
||||
self._disptxt(msg)
|
||||
time.sleep(1)
|
||||
msg.append("Starting application...")
|
||||
self._disptxt(msg)
|
||||
time.sleep(1)
|
||||
|
||||
return self.main_menu()
|
||||
|
||||
90
testgamepad.py
Executable file
90
testgamepad.py
Executable file
@ -0,0 +1,90 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import pygame, sys
|
||||
|
||||
|
||||
def main():
|
||||
pygame.init()
|
||||
screen = pygame.display.set_mode((600,800))
|
||||
font = pygame.font.SysFont(None, 24)
|
||||
clock = pygame.time.Clock()
|
||||
|
||||
def _disptxt(s_arr):
|
||||
screen.fill((255,255,255))
|
||||
for i,s in enumerate(s_arr):
|
||||
screen.blit(font.render(s, True, (0,0,0)), (10, 10 + i*24))
|
||||
pygame.display.flip()
|
||||
|
||||
pad_map = {
|
||||
pygame.K_UP: (-1,0,0),
|
||||
pygame.K_DOWN: (1,0,0),
|
||||
pygame.K_LEFT: (0,-1,0),
|
||||
pygame.K_RIGHT: (0,1,0),
|
||||
pygame.K_w: (0,0,1),
|
||||
pygame.K_s: (0,0,-1)
|
||||
}
|
||||
|
||||
pygame.joystick.init()
|
||||
joystick_count = pygame.joystick.get_count()
|
||||
if joystick_count > 0:
|
||||
_disptxt(["Found %d joysticks." % joystick_count])
|
||||
else:
|
||||
_disptxt(["Found no joysticks.", "Exit..."])
|
||||
time.sleep(1)
|
||||
pygame.quit()
|
||||
return 1
|
||||
|
||||
joystick = pygame.joystick.Joystick(0)
|
||||
joystick.init()
|
||||
axes = joystick.get_numaxes()
|
||||
buttons = joystick.get_numbuttons()
|
||||
hats = joystick.get_numhats()
|
||||
_disptxt([
|
||||
"Using joystick \"%s\"" % joystick.get_name(),
|
||||
"Number of axes: %d" % axes,
|
||||
"Number of buttons: %d" % buttons,
|
||||
"Number of hats: %d" % hats
|
||||
|
||||
])
|
||||
|
||||
|
||||
running = True
|
||||
while running:
|
||||
b_msg = []
|
||||
ax_msg = []
|
||||
hat_msg = []
|
||||
for e in pygame.event.get():
|
||||
pressed = pygame.key.get_pressed()
|
||||
if e.type == pygame.QUIT or pressed[pygame.K_ESCAPE]:
|
||||
running = False
|
||||
|
||||
# Possible joystick actions: JOYAXISMOTION JOYBALLMOTION JOYBUTTONDOWN JOYBUTTONUP JOYHATMOTION
|
||||
#if e.type == pygame.JOYBUTTONDOWN:
|
||||
# b_msg.append("Joystick button pressed.")
|
||||
#if e.type == pygame.JOYBUTTONUP:
|
||||
# b_msg.append("Joystick button released.")
|
||||
|
||||
|
||||
for i in range(axes):
|
||||
axis = joystick.get_axis(i)
|
||||
ax_msg.append("Axis %d value %.2f" % (i, axis))
|
||||
|
||||
for i in range(buttons):
|
||||
button = joystick.get_button(i)
|
||||
b_msg.append("Button %d value %.2f" % (i, button))
|
||||
|
||||
# Hat switch. All or nothing for direction, not like joysticks.
|
||||
# Value comes back in an array.
|
||||
for i in range(hats):
|
||||
hat = joystick.get_hat(i)
|
||||
hat_msg.append("Hat %d value %s" % (i, str(hat)))
|
||||
|
||||
_disptxt(b_msg + hat_msg + ax_msg)
|
||||
clock.tick(60)
|
||||
|
||||
pygame.quit()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@ -314,6 +314,8 @@ if __name__ == '__main__':
|
||||
print "Initializing..."
|
||||
try:
|
||||
controller = DemoController(config)
|
||||
controller.set_freedrive(False)
|
||||
time.sleep(1)
|
||||
controller.calibrate_cylinder_sys()
|
||||
except Exception, e:
|
||||
print e
|
||||
|
||||
@ -250,7 +250,7 @@ class DemoController(object):
|
||||
# check projected constraints.
|
||||
rnext = r + dr*0.031
|
||||
thetanext = theta + dtheta*0.029
|
||||
znext = z + dz*0.012
|
||||
znext = z + dz*0.009
|
||||
if (rnext < self.r_min and dr < 0) or (rnext > self.r_max and dr > 0):
|
||||
r = self.r_min if dr < 0 else self.r_max
|
||||
dr = 0
|
||||
@ -277,7 +277,7 @@ class DemoController(object):
|
||||
self.t_ch = 0
|
||||
elif not self.t_ch: #from another command
|
||||
self.t_ch = time.time()
|
||||
self.robot.stopl(acc=self.stop_acc)
|
||||
self.robot.stopl(acc=self.stop_acc*2)
|
||||
elif time.time() - self.t_ch > self.t_chcmd:
|
||||
self.move(vec)
|
||||
self.prev_vec = vec
|
||||
|
||||
Binary file not shown.
BIN
urx/__init__.pyc
BIN
urx/__init__.pyc
Binary file not shown.
BIN
urx/robot.pyc
BIN
urx/robot.pyc
Binary file not shown.
BIN
urx/urrtmon.pyc
BIN
urx/urrtmon.pyc
Binary file not shown.
BIN
urx/ursecmon.pyc
BIN
urx/ursecmon.pyc
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user