0

I am using Builder in standalone PsychoPy 1.80.07 in Windows. I'm trying to figure out how to create a Code Component to receive responses from a Logitech F310 Gamepad. Ideally, I would like to just use the triggers. I do not get any error code when I run the experiment (which is the Stroop keyboard IO demo with the IO keyboard code component code replaced with the below code). It seems to run fine, but it just shows the first trial and waits for a subject response as thought it isn't hearing the gamepad. Also, I am able to run the XInput Gamepad Coder Demo, and everything works just fine. I'm a novice at coding, so any help in pointing out where I've made mistakes would be much appreciated!

Here is what I have in my Code Component:

#Begin Experiment

try:
    from psychopy import visual, core
    from psychopy.iohub import launchHubServer, EventConstants
    from psychopy.data import getDateStr

    kwargs={'psychopy_monitor_name':'default','xinput.Gamepad':{}}
    io=launchHubServer(**kwargs)
    gamepad=io.devices.gamepad
except Exception, e:
    import sys
    print "!! Error starting ioHub: ",e," Exiting..."
    sys.exit(1)

#Begin Routine

response_event=None
trial_start=0
io.clearEvents()

#Each Frame

if frameN == 0:
    io.clearEvents('all')
    trial_start=core.getTime()
else:
    gamepadState=gamepad.getEvents()
    for anyState in gamepadState:
        if anyState in [u'left_trigger',u'right_trigger']:
            response_event=gamepadState
            continueRoutine = False 
            break

#End Routine

trials.addData("trial_start_time", trial_start)
if response_event:
    trials.addData("resp.time", response_event.time)
    trials.addData("resp.rt", response_event.time-trial_start)
    trials.addData("resp.duration", response_event.duration)
    trials.addData('resp.keys',response_event.key)
    trials.addData('resp.corr', response_event.key.lower()==corrAns)
else:
    trials.addData("resp.time",-1.0)
    trials.addData("resp.rt", -1.0)
    trials.addData("resp.duration", -1.0)
    trials.addData('resp.keys','None')
    trials.addData('resp.corr', False)

#End Experiment

io.quit()
  • My suspicion is that gamePadState contains more than just strings corresponding to what button was pushed, and hence your "if anyState in…" check would always fail. Can you let us know what the result of "print(anyState); print(type(anyState))" is? – Michael MacAskill Sep 14 '14 at 21:10

1 Answers1

1

If you want to get the latest value of the left and right triggers on the gamepad, you can read those values directly with getTriggers(), and not use getEvents() at all.

getTriggers() will return a dict containing the last read state of the triggers by iohub and the time the values were read.

For example, assuming 'gamepad' is a variable holding your iohub xinput gamepad device instance:

gp_triggers = gamepad.getTriggers()
# psychopy time that the trigger values were actually read (in sec.msec)
trig_time = gp_triggers['time']
# values will be between 0.0 and 1.0. 0.0 = Not pressed at all; 1.0 = fully pressed.
left_val, right_val = gp_triggers['left_trigger'], gp_triggers['right_trigger'] 

Then use left_val and right_val in a conditional that makes sense for when you want to accept the gamepad triggers state as a response. For example, if you want to accept a response when either trigger is more than 50% pressed:

if left_val > 0.5 and right_val > 0.5:
    # set some response vars like you were
    response = gp_triggers
    continueRoutine = False 
    break        

Then later in your code you can access the values of the response dict again:

resp_time = response['time']
left_val, right_val = response['left_trigger'], response['right_trigger'] 
Sol Simpson
  • 101
  • 3
  • Sol, it is working! Now I just need to make the jump to making this do what I need in my experiment. I want the gamepad response to be limited to a window beginning at frame 168 and lasting for the next 48 frames. I also want to log RT and whether the response was correct by comparing the response to $correctAns. I also need to send a ttl signal via parallel port (address 0xDF00) at the RT that sends "5" if the response is correct and "10" if it is incorrect. I'll be set to go once these issues are resolved. – SkepticalMat Sep 16 '14 at 19:05