def setRumble(self, lowFrequencyValue=0, highFrequencyValue=0, duration=1.0): """ Sets the xinput.Gamepad device's vibration / rumble feedback state for each of the low and high requency vibration motors. This ethod is only supported on devices that physically support rumble setting. By using different low and high drequence settings and duraations, different vibration feedback effects can be achieved. This can be further enhanced by adjusting each motors output state in steps over a period of time. The percentage provided for each vibration motor indicates how string the motor should be enabled relative to the full range of vitration strengths supported. This method runs asyncronously to the PsychoPy experiment script, so regardless of the duration set, the method returns when the vibration command has been issued to the device by the ioHub Process. If the experiment script sets the rumble state again before the last rumble state's duration is complete, then the new setRumble updates the rumble state and the previous state is ended prior to the full duration specified by the earlier command. Args: lowFrequencyValue (float): Percentage that the low frequency rumble motor should be set to within it's possible output range. 0.0 is Off. 100.0 is full power. The underlying rumble API uses 16 bit resolution values for setting rumble state. highFrequencyValue (float): Percentage that the high frequency rumble motor should be set to within it's possible output range. 0.0 is Off. 100.0 is full power. The underlying rumble API uses 16 bit resolution values for setting rumble state. duration (float): sec.msec duration that the rumble settings should be acctive for. When the duration had passed, the rumble states are set to 0. REgardless of the duration value, the method is run asyncronously and returns to the PsychoPy script as soon as the sate changes have been issues to the native device. Returns: (float,float): (command_return_time, command_call_duration), where command_return_time is the sec.msec time that the call to the native device to update vibration setting returned to the ioHub process, and command_call_duration is the sec.msec time taken for the native device call to return to the ioHub process. """ DeNormalizedLowFrequencyValue = int(65535.0 * (lowFrequencyValue / 100.0)) DeNormalizedHighFrequencyValue = int(65535.0 * (highFrequencyValue / 100.0)) if DeNormalizedLowFrequencyValue < 0: self._rumble.wLeftMotorSpeed = 0 elif DeNormalizedLowFrequencyValue > 65535: self._rumble.wLeftMotorSpeed = 65535 else: self._rumble.wLeftMotorSpeed = DeNormalizedLowFrequencyValue if DeNormalizedHighFrequencyValue < 0: self._rumble.wRightMotorSpeed = 0 elif DeNormalizedHighFrequencyValue > 65535: self._rumble.wRightMotorSpeed = 65535 else: self._rumble.wRightMotorSpeed = DeNormalizedHighFrequencyValue t1 = Computer.getTime() xinput._xinput_dll.XInputSetState(self.device_number, xinput.pointer(self._rumble)) t2 = Computer.getTime() gevent.spawn(self._delayedRumble, delay=duration) return t2, t2 - t1
def updateBatteryInformation(self): """ Informs the xinput gamepad to read the battery status information from the native device and return the latest battery status information. Given the possible uses of the returned information, it is unlikely that the status needs to be read from the native device every time the calling program needs battery status. Therefore using the getLastReadBatteryInfo() can be called instead as needed. Args: None Returns: tuple: (battery_level, battery_type) where battery_level is a string constant indicating if the device's battery is at a low, medium, or high charge level. battery_type indicates if the gamepad actually uses a battery, or if it is a wired device and is powered via USB. In the latter case, ['BATTERY_LEVEL_FULL', 'BATTERY_TYPE_WIRED'] is always returned. """ xinput._xinput_dll.XInputGetBatteryInformation( self. device_number, # Index of the gamer associated with the device xinput.BATTERY_DEVTYPE_GAMEPAD, # Which device on this user index xinput.pointer(self._battery_information)) # Contains the level # and types of batteries bl = XInputGamePadConstants._batteryLevels.getName( self._battery_information.BatteryLevel) bt = XInputGamePadConstants._batteryTypes.getName( self._battery_information.BatteryType) return bl, bt
def updateBatteryInformation(self): """Informs the xinput gamepad to read the battery status information from the native device and return the latest battery status information. Given the possible uses of the returned information, it is unlikely that the status needs to be read from the native device every time the calling program needs battery status. Therefore using the getLastReadBatteryInfo() can be called instead as needed. Args: None Returns: tuple: (battery_level, battery_type) where battery_level is a string constant indicating if the device's battery is at a low, medium, or high charge level. battery_type indicates if the gamepad actually uses a battery, or if it is a wired device and is powered via USB. In the latter case, ['BATTERY_LEVEL_FULL', 'BATTERY_TYPE_WIRED'] is always returned. """ if not hasattr(xinput._xinput_dll,'XInputGetBatteryInformation'): return 'N/A', 'N/A' xinput._xinput_dll.XInputGetBatteryInformation( self.device_number, # Index of the gamer associated with the device xinput.BATTERY_DEVTYPE_GAMEPAD, # Which device on this user index xinput.pointer(self._battery_information)) # Contains the level # and types of batteries bl = XInputGamePadConstants._batteryLevels.getName( self._battery_information.BatteryLevel) bt = XInputGamePadConstants._batteryTypes.getName( self._battery_information.BatteryType) return bl, bt
def setRumble(self,lowFrequencyValue=0,highFrequencyValue=0,duration=1.0): DeNormalizedLowFrequencyValue= int(65535.0*(lowFrequencyValue/100.0)) DeNormalizedHighFrequencyValue= int(65535.0*(highFrequencyValue/100.0)) if DeNormalizedLowFrequencyValue < 0: self._rumble.wLeftMotorSpeed=0 elif DeNormalizedLowFrequencyValue > 65535: self._rumble.wLeftMotorSpeed=65535 else: self._rumble.wLeftMotorSpeed=DeNormalizedLowFrequencyValue if DeNormalizedHighFrequencyValue < 0: self._rumble.wRightMotorSpeed=0 elif DeNormalizedHighFrequencyValue > 65535: self._rumble.wRightMotorSpeed=65535 else: self._rumble.wRightMotorSpeed=DeNormalizedHighFrequencyValue t1=Computer.getTime() xinput._xinput_dll.XInputSetState(self.device_number, xinput.pointer(self._rumble)) t2=Computer.getTime() gevent.spawn(self._delayedRumble,delay=duration) return t2, t2-t1
def _delayedRumble(self, lowFrequencyValue=0, highFrequencyValue=0, delay=0): gevent.sleep(delay) self._rumble.wLeftMotorSpeed = 0 self._rumble.wRightMotorSpeed = 0 xinput._xinput_dll.XInputSetState(self.device_number, xinput.pointer(self._rumble))
def updateBatteryInformation(self): xinput._xinput_dll.XInputGetBatteryInformation( self.device_number, # Index of the gamer associated with the device xinput.BATTERY_DEVTYPE_GAMEPAD,# Which device on this user index xinput.pointer(self._battery_information)) # Contains the level # and types of batteries bl=XInputGamePadConstants._batteryLevels.getName(self._battery_information.BatteryLevel) bt=XInputGamePadConstants._batteryTypes.getName(self._battery_information.BatteryType) return bl,bt
def setRumble(self,lowFrequencyValue=0,highFrequencyValue=0,duration=1.0): """ Sets the xinput.Gamepad device's vibration / rumble feedback state for each of the low and high requency vibration motors. This ethod is only supported on devices that physically support rumble setting. By using different low and high drequence settings and duraations, different vibration feedback effects can be achieved. This can be further enhanced by adjusting each motors output state in steps over a period of time. The percentage provided for each vibration motor indicates how string the motor should be enabled relative to the full range of vitration strengths supported. This method runs asyncronously to the PsychoPy experiment script, so regardless of the duration set, the method returns when the vibration command has been issued to the device by the ioHub Process. If the experiment script sets the rumble state again before the last rumble state's duration is complete, then the new setRumble updates the rumble state and the previous state is ended prior to the full duration specified by the earlier command. Args: lowFrequencyValue (float): Percentage that the low frequency rumble motor should be set to within it's possible output range. 0.0 is Off. 100.0 is full power. The underlying rumble API uses 16 bit resolution values for setting rumble state. highFrequencyValue (float): Percentage that the high frequency rumble motor should be set to within it's possible output range. 0.0 is Off. 100.0 is full power. The underlying rumble API uses 16 bit resolution values for setting rumble state. duration (float): sec.msec duration that the rumble settings should be acctive for. When the duration had passed, the rumble states are set to 0. REgardless of the duration value, the method is run asyncronously and returns to the PsychoPy script as soon as the sate changes have been issues to the native device. Returns: (float,float): (command_return_time, command_call_duration), where command_return_time is the sec.msec time that the call to the native device to update vibration setting returned to the ioHub process, and command_call_duration is the sec.msec time taken for the native device call to return to the ioHub process. """ DeNormalizedLowFrequencyValue= int(65535.0*(lowFrequencyValue/100.0)) DeNormalizedHighFrequencyValue= int(65535.0*(highFrequencyValue/100.0)) if DeNormalizedLowFrequencyValue < 0: self._rumble.wLeftMotorSpeed=0 elif DeNormalizedLowFrequencyValue > 65535: self._rumble.wLeftMotorSpeed=65535 else: self._rumble.wLeftMotorSpeed=DeNormalizedLowFrequencyValue if DeNormalizedHighFrequencyValue < 0: self._rumble.wRightMotorSpeed=0 elif DeNormalizedHighFrequencyValue > 65535: self._rumble.wRightMotorSpeed=65535 else: self._rumble.wRightMotorSpeed=DeNormalizedHighFrequencyValue t1=Computer.getTime() xinput._xinput_dll.XInputSetState(self.device_number, xinput.pointer(self._rumble)) t2=Computer.getTime() gevent.spawn(self._delayedRumble,delay=duration) return t2, t2-t1
def _delayedRumble( self, lowFrequencyValue=0, highFrequencyValue=0, delay=0): gevent.sleep(delay) self._rumble.wLeftMotorSpeed = 0 self._rumble.wRightMotorSpeed = 0 xinput._xinput_dll.XInputSetState( self.device_number, xinput.pointer( self._rumble))
def updateCapabilitiesInformation(self): xinput._xinput_dll.XInputGetCapabilities( self.device_number, xinput.XINPUT_FLAG_GAMEPAD, xinput.pointer(self._capabilities)) t=self._capabilities.Type s=self._capabilities.SubType f=self._capabilities.Flags g=self._capabilities.Gamepad b=g.wButtons blt=g.bLeftTrigger brt=g.bRightTrigger lxt=g.sThumbLX lyt=g.sThumbLY rxt=g.sThumbRX ryt=g.sThumbRY v=self._capabilities.Vibration lf=v.wLeftMotorSpeed hf=v.wRightMotorSpeed return (t,s,f),b,(blt,brt),((lxt,lyt),(rxt,ryt)),(lf,hf)
def _poll(self): t=Computer.getTime() result = xinput._xinput_dll.XInputGetState(self.device_number, xinput.pointer(self._device_state_buffer)) t2=Computer.getTime() if result == xinput.ERROR_SUCCESS: changed = self._checkForStateChange() if len(changed) > 0: temp=self._device_state self._device_state = self._device_state_buffer self._state_time=t2 self._time_ci=t2-t self._device_state_buffer=temp delay=(t-self._last_poll_time)/2.0 # assuming normal distribution, on average delay will be 1/2 the # inter poll interval buttons=0 if len(changed.get('Buttons',[])) > 0: buttons=self._device_state.Gamepad.wButtons gpe= [ 0, # experiment_id filled in by ioHub 0, # session_id filled in by ioHub self.device_number, # device id : number 0-3 representing which controller event is from. Computer._getNextEventID(), # unique event id GamepadStateChangeEvent.EVENT_TYPE_ID, # id representation of event type self._state_time, # device Time t, # logged time self._state_time, # time (i.e. ioHub Time) self._time_ci, # confidence Interval delay, # delay 0, buttons, # buttons id's that were pressed at the time of the state change. 'B', # buttons 1 char placeholder changed.get('LeftThumbStick',(0.0,0.0,0.0)), # normalized x,y, and magnitude value for left thumb stick changed.get('RightThumbStick',(0.0,0.0,0.0)), # normalized x,y, and magnitude value for right thumb stick changed.get('LeftTrigger',0.0), # normalized degree pressed for left trigger button changed.get('RightTrigger',0.0) # normalized degree pressed for left trigger button ] self._addNativeEventToBuffer(gpe) else: # TODO: device has disconnected, create a special event..... temp=self._device_state self._device_state = self._device_state_buffer self._state_time=t self._time_ci=t2-t self._device_state_buffer=temp delay=(t-self._last_poll_time)/2.0 # assuming normal distribution, on average delay will be 1/2 the # inter poll interval gpe= [ 0, # experiment_id filled in by ioHub 0, # session_id filled in by ioHub self.device_number, # number 0-3 representing which controller event is from. Computer._getNextEventID(), # unique event id GamepadDisconnectEvent.EVENT_TYPE_ID, # id representation of event type self._state_time, # device Time t, # logged time self._state_time, # time (i.e. ioHub Time) self._time_ci, # confidence Interval delay, # delay 0, #filter_id 0 by default 0, # buttons id's that were pressed at the time of the state change. 'B', # buttons 1 char placeholder 0, # normalized x,y, and magnitude value for left thumb stick 0, # normalized x,y, and magnitude value for right thumb stick 0, # normalized degree pressed for left trigger button 0 # normalized degree pressed for left trigger button ] self._addNativeEventToBuffer(gpe) self._close() self._last_poll_time=t return True
def updateCapabilitiesInformation(self): """ Informs the xinput gamepad to read the capability information available from the native device and return this data in a dictionary format. Given the possible uses of the returned information, it is unlikely that the capability information needs to be read from the native device every time the calling program needs to know what capabilities the device supports. Therefore using the getLastReadCapabilitiesInfo() method will likely be a better choice to use during the runtime of your program. An even better option would be to read the device capabilities from the ioHub Process once, cache them in your script as local variables, and use the local variables you created during the rest of the experiment. ;) The return value is a dict, keys represent different reported capability types, and the associated value is what the current deive supports for the given capability: * type : either XBOX360_GAMEPAD or OTHER_XINPUT_GAMEPAD * subtype : either XINPUT_GAMEPAD or XINPUT_UNKNOWN_SUBTYPE * supported_buttons : list of the supported buttons in string form, as specified in the XInputGamePadConstants class. * left_trigger_support : True == supported, False otherwise * right_trigger_support : True == supported, False otherwise * low_frequency_vibration_support : True == supported, False otherwise * high_frequency_vibration_support : True == supported, False otherwise Args: None Returns: tuple: The device capabilities in dict format. """ xinput._xinput_dll.XInputGetCapabilities( self.device_number, xinput.XINPUT_FLAG_GAMEPAD, xinput.pointer(self._capabilities)) capabilities_dict=dict() capabilities_dict['type']=XInputGamePadConstants._capabilities.getName(self._capabilities.Type) s=self._capabilities.SubType if s == xinput.XINPUT_DEVSUBTYPE_GAMEPAD: capabilities_dict['subtype']=XInputGamePadConstants._capabilities.getName(XInputGamePadConstants._capabilities.XINPUT_GAMEPAD) else: capabilities_dict['subtype']=XInputGamePadConstants._capabilities.getName(XInputGamePadConstants._capabilities.XINPUT_UNKNOWN_SUBTYPE) f=self._capabilities.Flags g=self._capabilities.Gamepad b=g.wButtons capabilities_dict['supported_buttons']=[k for k,v in self._getButtonNameList(b).iteritems() if v is True] capabilities_dict['left_trigger_support']=g.bLeftTrigger==255 capabilities_dict['right_trigger_support']=g.bRightTrigger==255 capabilities_dict['left_thumbstick_x_support']=g.sThumbLX==-64 capabilities_dict['left_thumbstick_y_support']=g.sThumbLY==-64 capabilities_dict['right_thumbstick_x_support']=g.sThumbRX==-64 capabilities_dict['right_thumbstick_x_support']=g.sThumbRY==-64 v=self._capabilities.Vibration capabilities_dict['low_frequency_vibration_support']=v.wLeftMotorSpeed==255 capabilities_dict['high_frequency_vibration_support']=v.wRightMotorSpeed==255 self._last_read_capabilities_dict=capabilities_dict return self._last_read_capabilities_dict
def _poll(self): t = Computer.getTime() result = xinput._xinput_dll.XInputGetState( self.device_number, xinput.pointer(self._device_state_buffer)) t2 = Computer.getTime() if result == xinput.ERROR_SUCCESS: changed = self._checkForStateChange() if len(changed) > 0: temp = self._device_state self._device_state = self._device_state_buffer self._state_time = t2 self._time_ci = t2 - t self._device_state_buffer = temp delay = ( t - self._last_poll_time ) / 2.0 # assuming normal distribution, on average delay will be 1/2 the # inter poll interval buttons = 0 if len(changed.get('Buttons', [])) > 0: buttons = self._device_state.Gamepad.wButtons gpe = [ 0, # experiment_id filled in by ioHub 0, # session_id filled in by ioHub self. device_number, # device id : number 0-3 representing which controller event is from. Computer._getNextEventID(), # unique event id GamepadStateChangeEvent. EVENT_TYPE_ID, # id representation of event type self._state_time, # device Time t, # logged time self._state_time, # time (i.e. ioHub Time) self._time_ci, # confidence Interval delay, # delay 0, buttons, # buttons id's that were pressed at the time of the state change. 'B', # buttons 1 char placeholder changed.get( 'LeftThumbStick', (0.0, 0.0, 0.0) ), # normalized x,y, and magnitude value for left thumb stick changed.get( 'RightThumbStick', (0.0, 0.0, 0.0) ), # normalized x,y, and magnitude value for right thumb stick changed.get( 'LeftTrigger', 0.0 ), # normalized degree pressed for left trigger button changed.get( 'RightTrigger', 0.0 ) # normalized degree pressed for left trigger button ] self._addNativeEventToBuffer(gpe) else: # TODO: device has disconnected, create a special event..... temp = self._device_state self._device_state = self._device_state_buffer self._state_time = t self._time_ci = t2 - t self._device_state_buffer = temp delay = ( t - self._last_poll_time ) / 2.0 # assuming normal distribution, on average delay will be 1/2 the # inter poll interval gpe = [ 0, # experiment_id filled in by ioHub 0, # session_id filled in by ioHub self. device_number, # number 0-3 representing which controller event is from. Computer._getNextEventID(), # unique event id GamepadDisconnectEvent. EVENT_TYPE_ID, # id representation of event type self._state_time, # device Time t, # logged time self._state_time, # time (i.e. ioHub Time) self._time_ci, # confidence Interval delay, # delay 0, #filter_id 0 by default 0, # buttons id's that were pressed at the time of the state change. 'B', # buttons 1 char placeholder 0, # normalized x,y, and magnitude value for left thumb stick 0, # normalized x,y, and magnitude value for right thumb stick 0, # normalized degree pressed for left trigger button 0 # normalized degree pressed for left trigger button ] self._addNativeEventToBuffer(gpe) self._close() self._last_poll_time = t return True
def updateCapabilitiesInformation(self): """ Informs the xinput gamepad to read the capability information available from the native device and return this data in a dictionary format. Given the possible uses of the returned information, it is unlikely that the capability information needs to be read from the native device every time the calling program needs to know what capabilities the device supports. Therefore using the getLastReadCapabilitiesInfo() method will likely be a better choice to use during the runtime of your program. An even better option would be to read the device capabilities from the ioHub Process once, cache them in your script as local variables, and use the local variables you created during the rest of the experiment. ;) The return value is a dict, keys represent different reported capability types, and the associated value is what the current deive supports for the given capability: * type : either XBOX360_GAMEPAD or OTHER_XINPUT_GAMEPAD * subtype : either XINPUT_GAMEPAD or XINPUT_UNKNOWN_SUBTYPE * supported_buttons : list of the supported buttons in string form, as specified in the XInputGamePadConstants class. * left_trigger_support : True == supported, False otherwise * right_trigger_support : True == supported, False otherwise * low_frequency_vibration_support : True == supported, False otherwise * high_frequency_vibration_support : True == supported, False otherwise Args: None Returns: tuple: The device capabilities in dict format. """ xinput._xinput_dll.XInputGetCapabilities( self.device_number, xinput.XINPUT_FLAG_GAMEPAD, xinput.pointer(self._capabilities)) capabilities_dict = dict() capabilities_dict[ 'type'] = XInputGamePadConstants._capabilities.getName( self._capabilities.Type) s = self._capabilities.SubType if s == xinput.XINPUT_DEVSUBTYPE_GAMEPAD: capabilities_dict[ 'subtype'] = XInputGamePadConstants._capabilities.getName( XInputGamePadConstants._capabilities.XINPUT_GAMEPAD) else: capabilities_dict[ 'subtype'] = XInputGamePadConstants._capabilities.getName( XInputGamePadConstants._capabilities.XINPUT_UNKNOWN_SUBTYPE ) f = self._capabilities.Flags g = self._capabilities.Gamepad b = g.wButtons capabilities_dict['supported_buttons'] = [ k for k, v in self._getButtonNameList(b).iteritems() if v is True ] capabilities_dict['left_trigger_support'] = g.bLeftTrigger == 255 capabilities_dict['right_trigger_support'] = g.bRightTrigger == 255 capabilities_dict['left_thumbstick_x_support'] = g.sThumbLX == -64 capabilities_dict['left_thumbstick_y_support'] = g.sThumbLY == -64 capabilities_dict['right_thumbstick_x_support'] = g.sThumbRX == -64 capabilities_dict['right_thumbstick_x_support'] = g.sThumbRY == -64 v = self._capabilities.Vibration capabilities_dict[ 'low_frequency_vibration_support'] = v.wLeftMotorSpeed == 255 capabilities_dict[ 'high_frequency_vibration_support'] = v.wRightMotorSpeed == 255 self._last_read_capabilities_dict = capabilities_dict return self._last_read_capabilities_dict