Wednesday, May 06, 2009

Linux joystick calibration considered useful

For a long time I was under the impression that joystick calibration is no longer needed with current day joysticks, yesterday I however figured out that I was wrong, kind of at least. While it is true that todays joysticks normally don't need to be calibrated manually, the values they submit over USB are fine the way they are, the Linux joydev calibration interface can still prove extremely useful or harmfull for that matter. The way calibration in Linux works is that you basically have four values for each axis (they are stored a little different internally in js_corr::coef[], but you can convert):
  • center_min
  • center_max
  • range_min
  • range_max
These are calculated from absflat, absmin and absmax as reported by evdev and in turn I assume by USB (haven't yet looked where those values come from) and used to transform the raw USB values (range often 0,255, but can vary with sticks) to the one of the joydev interface (range -32767, 32767). The thing now is that these values have terrible defaults for most of the sticks I have tested, resulting in a deadzone far larger then needed and in a loss of far range of the joystick.

On the SideWinder Precision 2 stick for example they result in a 10% deadzone, which is very noticable and annoying in games, as they make it impossible to make small movements. They also result in a deadzone on the throttle control, which is totally useless. The cool thing is that those issues are not a limitation of the hardware, but just the result of the calibration values and those can be tweaked with ease, jstest-gtk contains a tab where you can tweak those values directly. Or if you don't want to bother with that, you can just use jscal, which ships with most distros:

jscal -s 6,1,0,127,127,4227201,4194176,1,0,127,127,4227201,4194176,1,0,127,127,4227201,4194176,1,0,127,127,4227201,4194176,1,0,0,0,536854528,536854528,1,0,0,0,536854528,536854528 /dev/input/js0

The values are not persistant, so a reboot or unplug will reset them.

That issue aside, one can do a few more useful things with the calibration interface, such as inverting an axis. The joydev interface also allows to reorder axis and buttons, if the default might not be suited for a game, that feature seems to be broken in jscal that ships with Ubuntu, but will be implemented in jstest-gtk soon (Update: its implemented).

One annoying thing with the joydev however is that there doesn't seem to be a way to get the event device associated with the joydev device, there also doesn't seem to be a way to reset calibration and button mapping back to the defaults, once changed.

Edit: The above explanation, while true, has only limited use, as most games use SDL and SDL will use evdev by default, not joydev and evdev doesn't support any kind of calibration. SDL can however be forced to use the joystick device via:

export SDL_JOYSTICK_DEVICE=/dev/input/js0

1 comment:

Unknown said...
This comment has been removed by a blog administrator.