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 | # 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. | # 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. | # 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 = 0.1 #[m/s] | ||||||
| VEL_Z = 0.05 #[m/s] | VEL_Z = 0.05 #[m/s] | ||||||
| ACC = 0.5 #[m/s^2] | 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 | # AUTO/LOOP CONTROL | ||||||
| # | # | ||||||
| # When looping, the robot use the same velocity for r, theta and z. | # 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") |         pygame.display.set_caption("UR5 Demo") | ||||||
|         self.font = pygame.font.SysFont(None, config.FONTSIZE) |         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 |         # move vectors are in cylinder coords | ||||||
|         self.kb_map = { |         self.kb_map = { | ||||||
|                 pygame.K_UP: (-1,0,0), |                 pygame.K_UP: (-1,0,0), | ||||||
| @ -39,11 +46,21 @@ class UR5Demo(object): | |||||||
|         msg = [] |         msg = [] | ||||||
|         if error: |         if error: | ||||||
|             msg.append(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...") |         msg.append("Disconnecting robot...") | ||||||
|         self._disptxt(msg) |         self._disptxt(msg) | ||||||
|         if self.controller: |         if self.controller: | ||||||
|             self.controller.cleanup() |             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...") |         msg.append("Exit...") | ||||||
|         self._disptxt(msg) |         self._disptxt(msg) | ||||||
|         pygame.quit() |         pygame.quit() | ||||||
| @ -216,6 +233,47 @@ class UR5Demo(object): | |||||||
| 
 | 
 | ||||||
|             self.clock.tick(config.MENU_FPS) |             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): |     def keyboard_control(self): | ||||||
|         t = time.time() |         t = time.time() | ||||||
|         running = True |         running = True | ||||||
| @ -308,7 +366,10 @@ class UR5Demo(object): | |||||||
|                 self._disptxt(menu) |                 self._disptxt(menu) | ||||||
| 
 | 
 | ||||||
|             elif pressed[pygame.K_c]: |             elif pressed[pygame.K_c]: | ||||||
|                 self.keyboard_control() |                 if self.gamepad: | ||||||
|  |                     self.gamepad_control() | ||||||
|  |                 else: | ||||||
|  |                     self.keyboard_control() | ||||||
|                 self._disptxt(menu) |                 self._disptxt(menu) | ||||||
| 
 | 
 | ||||||
|             elif pressed[pygame.K_q] or self.sig_quit: |             elif pressed[pygame.K_q] or self.sig_quit: | ||||||
| @ -325,7 +386,11 @@ class UR5Demo(object): | |||||||
|         self._disptxt(msg) |         self._disptxt(msg) | ||||||
|         try: |         try: | ||||||
|             self.controller = DemoController(config) |             self.controller = DemoController(config) | ||||||
|  |             msg.append("Freedrive mode off...") | ||||||
|  |             self._disptxt(msg) | ||||||
|             self.controller.set_freedrive(False) |             self.controller.set_freedrive(False) | ||||||
|  |             time.sleep(0.5) | ||||||
|  |             msg.append("Going to home position...") | ||||||
|             msg.append("Calibrating cylinder coordinate system...") |             msg.append("Calibrating cylinder coordinate system...") | ||||||
|             self._disptxt(msg) |             self._disptxt(msg) | ||||||
|             self.controller.calibrate_cylinder_sys() |             self.controller.calibrate_cylinder_sys() | ||||||
| @ -333,6 +398,25 @@ class UR5Demo(object): | |||||||
|             return self.quit(error=("Error: %s" % e)) |             return self.quit(error=("Error: %s" % e)) | ||||||
|         msg.append("Calibration done.") |         msg.append("Calibration done.") | ||||||
|         self._disptxt(msg) |         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) |         time.sleep(1) | ||||||
| 
 | 
 | ||||||
|         return self.main_menu() |         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..." |     print "Initializing..." | ||||||
|     try: |     try: | ||||||
|         controller = DemoController(config) |         controller = DemoController(config) | ||||||
|  |         controller.set_freedrive(False) | ||||||
|  |         time.sleep(1) | ||||||
|         controller.calibrate_cylinder_sys() |         controller.calibrate_cylinder_sys() | ||||||
|     except Exception, e: |     except Exception, e: | ||||||
|         print e |         print e | ||||||
|  | |||||||
| @ -250,7 +250,7 @@ class DemoController(object): | |||||||
| 		# check projected constraints. | 		# check projected constraints. | ||||||
| 		rnext = r + dr*0.031 | 		rnext = r + dr*0.031 | ||||||
| 		thetanext = theta + dtheta*0.029 | 		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): | 		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 | 			r = self.r_min if dr < 0 else self.r_max | ||||||
| 			dr = 0 | 			dr = 0 | ||||||
| @ -277,7 +277,7 @@ class DemoController(object): | |||||||
| 				self.t_ch = 0 | 				self.t_ch = 0 | ||||||
| 			elif not self.t_ch: #from another command | 			elif not self.t_ch: #from another command | ||||||
| 				self.t_ch = time.time() | 				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: | 			elif time.time() - self.t_ch > self.t_chcmd: | ||||||
| 				self.move(vec) | 				self.move(vec) | ||||||
| 				self.prev_vec = 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