Note
Go to the end to download the full example code
Use joystick controlsΒΆ
This example demonstrates how to use a joystick as an input device using button presses and continuous analog movement to control the position of a circle on the screen.
exp_name: joyExp
date: 2023-07-25 19_08_25.025297
file: /home/circleci/project/examples/experiments/joystick_experiment.py
participant: foo
session: 001
2023-07-25 19:08:25,025 - INFO - Expyfun: Using version 2.0.0.dev0 (requested dev)
2023-07-25 19:08:25,026 - INFO - Expyfun: Setting up sound card using pyglet backend with 2 playback channels
2023-07-25 19:08:25,221 - WARNING - Expyfun: Mismatch between reported stim sample rate (24414) and device sample rate (44100.0). Experiment Controller will resample for you, but this takes a non-trivial amount of processing time and may compromise your experimental timing and/or cause artifacts.
2023-07-25 19:08:25,221 - INFO - Expyfun: Setting up screen
2023-07-25 19:08:25,253 - EXP - Expyfun: Set screen visibility True
2023-07-25 19:08:25,268 - INFO - Initialized [1400 900] window on screen XlibScreen(display=<pyglet.canvas.xlib.XlibDisplay object at 0x7f1a95b502b0>, x=0, y=0, width=1400, height=900, xinerama=0) with DPI 69.73
2023-07-25 19:08:25,268 - INFO - Expyfun: Initializing dummy triggering mode
2023-07-25 19:08:25,269 - INFO - Expyfun: Initialization complete
2023-07-25 19:08:25,269 - EXP - Expyfun: Participant: foo
2023-07-25 19:08:25,269 - EXP - Expyfun: Session: 001
2023-07-25 19:08:25,351 - INFO - Expyfun: Exiting
2023-07-25 19:08:25,357 - EXP - Expyfun: Audio stopped and reset.
# Author: Eric Larson <larson.eric.d@gmail.com>
#
# License: BSD (3-clause)
from expyfun import ExperimentController, analyze, building_doc
from expyfun.visual import Circle, Text
print(__doc__)
joystick = not building_doc
move_rate = 0.05 # map -1<->1 stick range to something decent for 60Hz refresh
noise_thresh = 0.01 # permit slight miscalibration
# on a Logitech Cordless Rumblepad, the right stick is the analog one,
# and it has values stored in z and rz
joy_keys = ('z', 'rz')
with ExperimentController('joyExp', participant='foo', session='001',
output_dir=None, version='dev',
joystick=joystick) as ec:
circles = [Circle(ec, 0.5, units='deg',
fill_color=(1., 1., 1., 0.2), line_color='w')]
# We use normalized units for "pos" so we need to compensate in movement
# so that X/Y movement is even
ratios = [1., ec.window_size_pix[0] / float(ec.window_size_pix[1])]
pressed = ''
if not building_doc:
ec.listen_joystick_button_presses()
count = 0
screenshot = None
pos = [0., 0.]
while pressed != '2': # enable a clean quit (button number 3)
#######################################################################
# Draw things
Text(ec, str(count), pos=(1, -1),
anchor_x='right', anchor_y='bottom').draw()
for circle in circles[::-1]:
circle.draw()
screenshot = ec.screenshot() if screenshot is None else screenshot
ec.flip()
#######################################################################
# Get presses
if not building_doc:
pressed = ec.get_joystick_button_presses()
ec.listen_joystick_button_presses() # clear events
else:
pressed = [('2',)]
count += len(pressed)
#######################################################################
# Move the cursor
for idx, (key, ratio) in enumerate(zip(joy_keys, ratios)):
delta = 0. if building_doc else ec.get_joystick_value(key)
if abs(delta) > noise_thresh: # remove noise
pos[idx] = max(min(
pos[idx] + move_rate * ratio * delta, 1), -1)
circles[0].set_pos(pos, units='norm')
if pressed:
circles.insert(1, Circle(ec, 1, units='deg',
fill_color='r', line_color='w'))
circles[1].set_pos(pos, units='norm')
if len(circles) > 5:
circles.pop(-1)
pressed = pressed[0][0] # for exit condition
ec.check_force_quit()
analyze.plot_screen(screenshot)
Total running time of the script: ( 0 minutes 0.417 seconds)