Thursday, February 28, 2013

gamepad issues on OS X

The PC client currently supports the use of a 4-axis gamepad (e.g., PS3 controller) for flying.  I ordered a $10 USB controller from eBay, plugged it in, and tried some of the default settings.

The gamepad was recognized, and values showed up in the client for pitch/roll/yaw/thrust as the axis were moved; however, one of the axis always changed 2 of the controls, and the range wasn't correct for 1 of the axis.

I found a tool called HID_n_Seek to look at the output from all of the USB endpoints, and discovered that there are actually 5 endpoints that change value as the axis are moved.  4 of them behaved as expected, and 1 of them seemed to combine the output from a few different axis.

Likewise, a test using pygame (which is currently used by the Crazyflie PC client for the joystick input) showed the same thing.  I found this test script:


#!/usr/bin/env python

import pygame, time
#from pygame import joystick, event

pygame.init()
#joystick.init()
j = pygame.joystick.Joystick(0)
j.init()
print 'Initialized Joystick : %s' % j.get_name()
try:
    while True:
        time.sleep(1)
        pygame.event.pump()
        for i in range(0, j.get_numaxes()):
            if j.get_axis(i) != 0.00:
                print 'Axis %i reads %.2f' % (i, j.get_axis(i))
        for i in range(0, j.get_numbuttons()):
            if j.get_button(i) != 0:
                print 'Button %i reads %i' % (i, j.get_button(i))
except KeyboardInterrupt:
    j.quit()
    

Which produced output like this:

Axis 0 reads 0.00
Axis 1 reads 0.00
Axis 2 reads 0.05
Axis 3 reads 0.00
Axis 4 reads 0.00
...

After moving each axis, it appears that we we want to ignore axis 2.  i.e., the mapping looks like this:

Axis 0 - Left stick (L = -1.0, R = 1.0)
Axis 1 - Left stick (U = -1.0, D = 1.0)
Axis 3 - Right stick (L = -1.0, R = 1.0)
Axis 4 - Right stick (U = -1.0, D = 1.0)
IGNORE AXIS 2 (affect by all sticks)


So now it's simply a matter of figuring out the best way to modify the Crazyflie PC client to use axis 0, 1, 3, and 4 for input, and skip axis 2.  Remapping the configs/input/*.json fixes the axis; for example:


     "axis": [
          {"name":"Roll", "type":"Input.AXIS", "id":4, "scale":1.0, "key":"roll"},
          {"name":"Pitch", "type":"Input.AXIS", "id":3, "scale":-1.0, "key":"pitch"},
          {"name":"Yaw", "type":"Input.AXIS", "id":0, "scale":1.0, "key":"yaw"},
          {"name":"Thrust", "type":"Input.AXIS", "id":1, "scale":-1.0, "key":"thrust"},
          {"name":"Pitch Cal+", "type":"Input.BUTTON", "id":7, "scale":-1.0, "key":"pitchcal"},
          {"name":"Pitch Cal-", "type":"Input.BUTTON", "id":5, "scale":1.0, "key":"pitchcal"},
          {"name":"Roll Cal +", "type":"Input.BUTTON", "id":6, "scale":1.0, "key":"rollcal"},
          {"name":"Roll Cal -", "type":"Input.BUTTON", "id":8, "scale":-1.0, "key":"rollcal"},
          {"name":"Killswtich", "type":"Input.BUTTON", "id":14, "scale":1.0, "key":"estop"},
          {"name":"Exit", "type":"Input.BUTTON", "id":12, "scale":1.0, "key":"exit"}
     ]}

However, that breaks one of the buttons (because the buttons should be 4-7, not 5-8, and the inputs are stored as an array indexed by the id, so we can't have both a button and axis at id 4).  So perhaps need to make a code change such that we can have an axis/button with the same id...

Update:
I created a patch back on 3/1 that got merged in; this controller should work under OS X now.

No comments:

Post a Comment