03 January 2013

Gamepad Input in Python

I want to be able to command my upcoming Quadrotor with a game controller, so I purchased a Gigaware PC Wired Controller for $17 from Radioshack:



Quadrotors are usually controlled with two thumbsticks (4 axes): 

  • Left Thumbstick Up/Down: Throttle
  • Left Thumbstick Left/Right: Yaw
  • Right Thumbstick Up/Down: Pitch
  • Left Thumbstick Left/Right: Roll


This inexpensive controller seems perfect for what I need it for, and there are some buttons I can use for initialization and other things. I could also use this gamepad to command, say, a certain mobile robot or a certain robot arm of mine. Or both. Simultaneously. 

Oh, and I can also use the controller to play games on my computer. Which is, you know, its intended purpose. N64 Emulator, Anyone?

I looked online for some Python example code, and the easiest came from this site. 

I modified it to make it more simple and global for my, and hopefully your, purposes:


"""
Gamepad Module
Daniel J. Gonzalez
dgonz@mit.edu

Based off code from: http://robots.dacloughb.com/project-1/logitech-game-pad/

"""

import pygame


pygame.init()

j = pygame.joystick.Joystick(0)
j.init()
print 'Initialized Joystick : %s' % j.get_name()

"""

Returns a vector of the following form:
[LThumbstickX, LThumbstickY, Unknown Coupled Axis???, 
RThumbstickX, RThumbstickY, 
Button 1/X, Button 2/A, Button 3/B, Button 4/Y, 
Left Bumper, Right Bumper, Left Trigger, Right Triller,
Select, Start, Left Thumb Press, Right Thumb Press]

Note:

No D-Pad.
Triggers are switches, not variable. 
Your controller may be different
"""

def get():

    out = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
    it = 0 #iterator
    pygame.event.pump()
    
    #Read input from the two joysticks       
    for i in range(0, j.get_numaxes()):
        out[it] = j.get_axis(i)
        it+=1
    #Read input from buttons
    for i in range(0, j.get_numbuttons()):
        out[it] = j.get_button(i)
        it+=1
    return out

def test():

    while True:
        print get()

To test the code with your gamepad, simply plug it in, open a python shell, make sure the file is saved as gamepad.py, import gamepad and run gamepad.test(). Works for me in Ubuntu 12.04. To use this in your own application, simply place gamepad.py in your working directory, import gamepad, and call gamepad.get() every time you want to view the current state vector. 



 Button 4 is not pressed

 Button 4 is pressed. Note the "1" in the vector output on screen. 

Left Thumbstick not touched, all at 0

Going kinda right on the Right Stick gives a value of -.0567, and the value is linear relative to how far I push the stick. 

Going full right on the left stick brings the value up to -1.

Groovy. I don't know what's up with the third axis the joystick is giving me. The first two values in the vector make sense: Left Thumbstick up/down and left/right. But the third value changes when I move the Left Thumbstick left/right and when I move the Right Thumbstick up/down and when i hit the Start button (Button 10). It sure as hell isn't an accelerometer or anything fun like that, so I'm just going to ignore it for now. 

Hope the code proves useful!

5 comments:

  1. Thanks Bro! That's what I needed!

    ReplyDelete
  2. Hey!
    You should be able to get the d-pad values with j.get_hatsnum() and j.get_hat(i). And i is only 0 since there is only one d-pad. (The output is a tuple)

    ReplyDelete
  3. If tired of pygame, you can try mine gamepad grabber
    http://www.gr4viton.cz/2017/03/python-gamepad-cli-grabber-drawille-cli-stick-direction-visualiser/

    ReplyDelete