Wilbert's website at SocSci

> Software> Python> Hardware> Joystick

computer/joystick.html 2019-04-05

Joystick in Python

Low level, Linux and other unices except osx

import struct
with open("/dev/input/js0", "rb") as f:
	while True:
		a = f.read(8)
		t, value, code, index = struct.unpack("<Ihbb", a) # 4 bytes, 2 bytes, 1 byte, 1 byte
		# t: time in ms
		# index: button/axis number (0 for x-axis)
		# code: 1 for buttons, 2 for axis
		# value: axis position, 0 for center, 1 for buttonpress, 0 for button release
		print("t: {:10d} ms, value: {:6d}, code: {:1d}, index: {:1d}".format(t, value, code, index))

Psychopy, all OSes

from __future__ import print_function
import sys
from psychopy.hardware import joystick
from psychopy import visual

joystick.backend = 'pygame' # must match the Window
win = visual.Window([400,400], winType=joystick.backend)

j = joystick.Joystick(0)

while True:
	win.flip() # flipping updates the joystick info
	val = ["{:6.3f}".format(i) for i in j.getAllAxes()]
	buttons = [int(i) for i in j.getAllButtons()]
	print("val: {}, {}".format(val, buttons), end='\r')

Note that you can use either 'pygame' or 'pyglet' as value for joystick.backend and winType. With Psychopy version 1.84.2 on OSX only 'pygame' will work. Otherwise you get the error:

AttributeError: 'PygletDevice' object has no attribute 'dispatch_events'
as decribed in this post. Note that it is similar to a problem with the same Psychopy version on windows which has a workaround described here as 'problem 2'.

Pyglet, all OSes

import pyglet

window = pyglet.window.Window(width=400, height=400)

# open first joystick
joysticks = pyglet.input.get_joysticks()  # requires pyglet 1.2
if joysticks:
	joystick = joysticks[0]
	print("ERROR: no joystick")

def on_draw():

def on_key_press(symbol, modifiers):
	print("query based joystick position: {}".format(joystick.x))
def on_joybutton_press(joystick, button):
	print("event based joystick response")


Pyglet, in Psychopy

You can also use the Pyglet functions directly in Psychopy. Note the opening and closing of the joystick in the event loop. This can be used as a workaround in osx, and is not generally the preferred method. This method may not work at all.

import pyglet
from psychopy import visual

win = visual.Window([400,400], winType='pyglet')
text = visual.TextStim(win, "")
joysticks = pyglet.input.get_joysticks()  # requires pyglet 1.2
j = joysticks[0]

while True:
    text.text = "{:6.3f}, {:6.3f}".format(j.x, j.y)