def __init__( self, eyetracker_info=None, product_id=None, model=None, mainloop=None, create_sync_manager=True): self._eyetracker_info = eyetracker_info self._requested_product_id = product_id self._requested_model = model self._mainloop = mainloop self._eyetracker = None self._queue = None self._tobiiClock = None self._getTobiiClockResolution = None self._getTobiiClockTime = None self._sync_manager = None self._syncTimeEventDeque = None self._isRecording = False if eyetracker_info is None: if not TobiiTrackerBrowser.isActive(): TobiiTrackerBrowser.start() self._eyetracker_info = TobiiTrackerBrowser.findDevice( model, product_id) if self._eyetracker_info: self._mainloop = TobiiTrackerBrowser.getMainLoop() TobiiTrackerBrowser.stop() else: self._eyetracker_info = TobiiTrackerBrowser.findDevice( model, product_id) if self._eyetracker_info is None: raise exceptions.BaseException( 'Could not find a Tobii Eye Tracker matching requirements.') if self._mainloop is None: if TobiiTrackerBrowser.isActive(): self._mainloop = TobiiTrackerBrowser.getMainLoop() else: TobiiPy.init() self._mainloop = TobiiPyMainloopThread() self._mainloop.start() self._queue = Queue.Queue() TobiiPyEyeTracker.create_async( self._mainloop, self._eyetracker_info, self.on_eyetracker_created) stime = getTime() while getTime() - stime < 10.0: try: event = self._queue.get(block=True, timeout=.1) if isinstance(event, TobiiTrackerCreatedEvent): self._eyetracker = event.tracker_object self._eyetracker.events.OnFramerateChanged += self.on_external_framerate_change if hasattr( self._eyetracker.events, 'OnHeadMovementBoxChanged'): self._eyetracker.events.OnHeadMovementBoxChanged += self.on_head_box_change elif hasattr(self._eyetracker.events, 'OnTrackBoxChanged'): self._eyetracker.events.OnTrackBoxChanged += self.on_head_box_change else: print 'WARNING: TobiiClasses could not set callback hook for "self.on_head_box_change".' self._eyetracker.events.OnXConfigurationChanged += self.on_x_series_physical_config_change break self._queue.task_done() except Queue.Empty: pass if self._eyetracker is None: raise exceptions.BaseException( 'Could not connect to Tobii. Timeout.') if create_sync_manager: self._eyetracker.events.OnError += self.on_eyetracker_error self._tobiiClock = TobiiPyClock() self._getTobiiClockResolution = self._tobiiClock.get_resolution self._getTobiiClockTime = self._tobiiClock.get_time self._syncTimeEventDeque = collections.deque(maxlen=32) self._sync_manager = TobiiPySyncManager(self._tobiiClock, self._eyetracker_info, self._mainloop, self.on_sync_error, self.on_sync_status)
def __init__(self, eyetracker_info=None, product_id=None, model=None, mainloop=None, create_sync_manager=True): self._eyetracker_info = eyetracker_info self._requested_product_id = product_id self._requested_model = model self._mainloop = mainloop self._eyetracker = None self._queue = None self._tobiiClock = None self._getTobiiClockResolution = None self._getTobiiClockTime = None self._sync_manager = None self._syncTimeEventDeque = None self._isRecording = False if eyetracker_info is None: if not TobiiTrackerBrowser.isActive(): TobiiTrackerBrowser.start() self._eyetracker_info = TobiiTrackerBrowser.findDevice( model, product_id) if self._eyetracker_info: self._mainloop = TobiiTrackerBrowser.getMainLoop() TobiiTrackerBrowser.stop() else: self._eyetracker_info = TobiiTrackerBrowser.findDevice( model, product_id) if self._eyetracker_info is None: raise exceptions.BaseException( 'Could not find a Tobii Eye Tracker matching requirements.') if self._mainloop is None: if TobiiTrackerBrowser.isActive(): self._mainloop = TobiiTrackerBrowser.getMainLoop() else: TobiiPy.init() self._mainloop = TobiiPyMainloopThread() self._mainloop.start() self._queue = Queue.Queue() TobiiPyEyeTracker.create_async(self._mainloop, self._eyetracker_info, self.on_eyetracker_created) stime = getTime() while getTime() - stime < 10.0: try: event = self._queue.get(block=True, timeout=.1) if isinstance(event, TobiiTrackerCreatedEvent): self._eyetracker = event.tracker_object self._eyetracker.events.OnFramerateChanged += self.on_external_framerate_change if hasattr(self._eyetracker.events, 'OnHeadMovementBoxChanged'): self._eyetracker.events.OnHeadMovementBoxChanged += self.on_head_box_change elif hasattr(self._eyetracker.events, 'OnTrackBoxChanged'): self._eyetracker.events.OnTrackBoxChanged += self.on_head_box_change else: print 'WARNING: TobiiClasses could not set callback hook for "self.on_head_box_change".' self._eyetracker.events.OnXConfigurationChanged += self.on_x_series_physical_config_change break self._queue.task_done() except Queue.Empty: pass if self._eyetracker is None: raise exceptions.BaseException( 'Could not connect to Tobii. Timeout.') if create_sync_manager: self._eyetracker.events.OnError += self.on_eyetracker_error self._tobiiClock = TobiiPyClock() self._getTobiiClockResolution = self._tobiiClock.get_resolution self._getTobiiClockTime = self._tobiiClock.get_time self._syncTimeEventDeque = collections.deque(maxlen=32) self._sync_manager = TobiiPySyncManager(self._tobiiClock, self._eyetracker_info, self._mainloop, self.on_sync_error, self.on_sync_status)
class TobiiTracker(object): LEFT = 0 RIGHT = 1 eye_data = OrderedDict(tracker_time_usec=np.NaN, pupil_diameter_mm=np.NaN, gaze_norm=[np.NaN, np.NaN], gaze_mm=[np.NaN, np.NaN, np.NaN], eye_location_norm=[np.NaN, np.NaN, np.NaN], eye_location_mm=[np.NaN, np.NaN, np.NaN], validity_code=np.NaN, status='UNKNOWN', trigger_signal=None) def __init__( self, eyetracker_info=None, product_id=None, model=None, mainloop=None, create_sync_manager=True): self._eyetracker_info = eyetracker_info self._requested_product_id = product_id self._requested_model = model self._mainloop = mainloop self._eyetracker = None self._queue = None self._tobiiClock = None self._getTobiiClockResolution = None self._getTobiiClockTime = None self._sync_manager = None self._syncTimeEventDeque = None self._isRecording = False if eyetracker_info is None: if not TobiiTrackerBrowser.isActive(): TobiiTrackerBrowser.start() self._eyetracker_info = TobiiTrackerBrowser.findDevice( model, product_id) if self._eyetracker_info: self._mainloop = TobiiTrackerBrowser.getMainLoop() TobiiTrackerBrowser.stop() else: self._eyetracker_info = TobiiTrackerBrowser.findDevice( model, product_id) if self._eyetracker_info is None: raise exceptions.BaseException( 'Could not find a Tobii Eye Tracker matching requirements.') if self._mainloop is None: if TobiiTrackerBrowser.isActive(): self._mainloop = TobiiTrackerBrowser.getMainLoop() else: TobiiPy.init() self._mainloop = TobiiPyMainloopThread() self._mainloop.start() self._queue = Queue.Queue() TobiiPyEyeTracker.create_async( self._mainloop, self._eyetracker_info, self.on_eyetracker_created) stime = getTime() while getTime() - stime < 10.0: try: event = self._queue.get(block=True, timeout=.1) if isinstance(event, TobiiTrackerCreatedEvent): self._eyetracker = event.tracker_object self._eyetracker.events.OnFramerateChanged += self.on_external_framerate_change if hasattr( self._eyetracker.events, 'OnHeadMovementBoxChanged'): self._eyetracker.events.OnHeadMovementBoxChanged += self.on_head_box_change elif hasattr(self._eyetracker.events, 'OnTrackBoxChanged'): self._eyetracker.events.OnTrackBoxChanged += self.on_head_box_change else: print 'WARNING: TobiiClasses could not set callback hook for "self.on_head_box_change".' self._eyetracker.events.OnXConfigurationChanged += self.on_x_series_physical_config_change break self._queue.task_done() except Queue.Empty: pass if self._eyetracker is None: raise exceptions.BaseException( 'Could not connect to Tobii. Timeout.') if create_sync_manager: self._eyetracker.events.OnError += self.on_eyetracker_error self._tobiiClock = TobiiPyClock() self._getTobiiClockResolution = self._tobiiClock.get_resolution self._getTobiiClockTime = self._tobiiClock.get_time self._syncTimeEventDeque = collections.deque(maxlen=32) self._sync_manager = TobiiPySyncManager(self._tobiiClock, self._eyetracker_info, self._mainloop, self.on_sync_error, self.on_sync_status) def on_eyetracker_created(self, *args, **kwargs): # print 'on_eyetracker_created: entered' et = None if len(args) >= 2: et = args[1] else: raise exceptions.BaseException( 'WARNING: on_eyetracker_created: Unhandled args count', len(args), args) error = kwargs.get('error', None) if error: raise exceptions.BaseException( 'Connection to Tobii failed because of an exception: %s' % (str(error),)) self._queue.put(TobiiTrackerCreatedEvent(et)) return False def on_eyetracker_error(self, *args, **kwargs): print2err('TobiiTracker.on_eyetracker_error: ', args, kwargs) return False def on_sync_error(self, *args, **kwargs): print2err('TobiiTracker.on_sync_error: ', args, kwargs) return False def on_sync_status(self, *args, **kwargs): sync_state = args[0] self._syncTimeEventDeque.append(sync_state) return False def on_eyetracker_data(self, *args, **kwargs): eye_data_event = args[1] LEFT = self.LEFT RIGHT = self.RIGHT eyes = (copy.deepcopy(self.eye_data), copy.deepcopy(self.eye_data)) eyes[LEFT]['validity_code'] = eye_data_event.LeftValidity eyes[RIGHT]['validity_code'] = eye_data_event.RightValidity eyes[LEFT]['tracker_time_usec'] = eye_data_event.Timestamp eyes[RIGHT]['tracker_time_usec'] = eye_data_event.Timestamp if hasattr(eye_data_event, 'TrigSignal'): eyes[LEFT]['trigger_signal'] = eye_data_event.TrigSignal eyes[RIGHT]['trigger_signal'] = eye_data_event.TrigSignal # print "*** lastEyeData.RightGazePoint2D: # ",lastEyeData.RightGazePoint2D.__dict__ if eye_data_event.LeftValidity >= 2 and eye_data_event.RightValidity >= 2: # no eye signal eyes[LEFT]['status'] = 'Missing' eyes[RIGHT]['status'] = 'Missing' elif eye_data_event.LeftValidity < 2 and eye_data_event.RightValidity >= 2: # left eye only available eyes[LEFT]['status'] = 'Available' eyes[RIGHT]['status'] = 'Missing' eyes[LEFT]['pupil_diameter_mm'] = eye_data_event.LeftPupil eyes[LEFT]['gaze_norm'][0] = eye_data_event.LeftGazePoint2D.x eyes[LEFT]['gaze_norm'][1] = eye_data_event.LeftGazePoint2D.y eyes[LEFT]['gaze_mm'][0] = eye_data_event.LeftGazePoint3D.x eyes[LEFT]['gaze_mm'][1] = eye_data_event.LeftGazePoint3D.y eyes[LEFT]['gaze_mm'][2] = eye_data_event.LeftGazePoint3D.z eyes[LEFT]['eye_location_norm'][ 0] = eye_data_event.LeftEyePosition3DRelative.x eyes[LEFT]['eye_location_norm'][ 1] = eye_data_event.LeftEyePosition3DRelative.y eyes[LEFT]['eye_location_norm'][ 2] = eye_data_event.LeftEyePosition3DRelative.z eyes[LEFT]['eye_location_mm'][ 0] = eye_data_event.LeftEyePosition3D.x eyes[LEFT]['eye_location_mm'][ 1] = eye_data_event.LeftEyePosition3D.y eyes[LEFT]['eye_location_mm'][ 2] = eye_data_event.LeftEyePosition3D.z elif eye_data_event.LeftValidity >= 2 and eye_data_event.RightValidity < 2: # right eye only available eyes[RIGHT]['status'] = 'Available' eyes[LEFT]['status'] = 'Missing' eyes[RIGHT]['pupil_diameter_mm'] = eye_data_event.RightPupil eyes[RIGHT]['gaze_norm'][0] = eye_data_event.RightGazePoint2D.x eyes[RIGHT]['gaze_norm'][1] = eye_data_event.RightGazePoint2D.y eyes[RIGHT]['gaze_mm'][0] = eye_data_event.RightGazePoint3D.x eyes[RIGHT]['gaze_mm'][1] = eye_data_event.RightGazePoint3D.y eyes[RIGHT]['gaze_mm'][2] = eye_data_event.RightGazePoint3D.z eyes[RIGHT]['eye_location_norm'][ 0] = eye_data_event.RightEyePosition3DRelative.x eyes[RIGHT]['eye_location_norm'][ 1] = eye_data_event.RightEyePosition3DRelative.y eyes[RIGHT]['eye_location_norm'][ 2] = eye_data_event.RightEyePosition3DRelative.z eyes[RIGHT]['eye_location_mm'][ 0] = eye_data_event.RightEyePosition3D.x eyes[RIGHT]['eye_location_mm'][ 1] = eye_data_event.RightEyePosition3D.y eyes[RIGHT]['eye_location_mm'][ 2] = eye_data_event.RightEyePosition3D.z else: # binocular available eyes[RIGHT]['status'] = 'Available' eyes[LEFT]['status'] = 'Available' eyes[LEFT]['pupil_diameter_mm'] = eye_data_event.LeftPupil eyes[LEFT]['gaze_norm'][0] = eye_data_event.LeftGazePoint2D.x eyes[LEFT]['gaze_norm'][1] = eye_data_event.LeftGazePoint2D.y eyes[LEFT]['gaze_mm'][0] = eye_data_event.LeftGazePoint3D.x eyes[LEFT]['gaze_mm'][1] = eye_data_event.LeftGazePoint3D.y eyes[LEFT]['gaze_mm'][2] = eye_data_event.LeftGazePoint3D.z eyes[LEFT]['eye_location_norm'][ 0] = eye_data_event.LeftEyePosition3DRelative.x eyes[LEFT]['eye_location_norm'][ 1] = eye_data_event.LeftEyePosition3DRelative.y eyes[LEFT]['eye_location_norm'][ 2] = eye_data_event.LeftEyePosition3DRelative.z eyes[LEFT]['eye_location_mm'][ 0] = eye_data_event.LeftEyePosition3D.x eyes[LEFT]['eye_location_mm'][ 1] = eye_data_event.LeftEyePosition3D.y eyes[LEFT]['eye_location_mm'][ 2] = eye_data_event.LeftEyePosition3D.z eyes[RIGHT]['pupil_diameter_mm'] = eye_data_event.RightPupil eyes[RIGHT]['gaze_norm'][0] = eye_data_event.RightGazePoint2D.x eyes[RIGHT]['gaze_norm'][1] = eye_data_event.RightGazePoint2D.y eyes[RIGHT]['gaze_mm'][0] = eye_data_event.RightGazePoint3D.x eyes[RIGHT]['gaze_mm'][1] = eye_data_event.RightGazePoint3D.y eyes[RIGHT]['gaze_mm'][2] = eye_data_event.RightGazePoint3D.z eyes[RIGHT]['eye_location_norm'][ 0] = eye_data_event.RightEyePosition3DRelative.x eyes[RIGHT]['eye_location_norm'][ 1] = eye_data_event.RightEyePosition3DRelative.y eyes[RIGHT]['eye_location_norm'][ 2] = eye_data_event.RightEyePosition3DRelative.z eyes[RIGHT]['eye_location_mm'][ 0] = eye_data_event.RightEyePosition3D.x eyes[RIGHT]['eye_location_mm'][ 1] = eye_data_event.RightEyePosition3D.y eyes[RIGHT]['eye_location_mm'][ 2] = eye_data_event.RightEyePosition3D.z return False def on_start_tracking(self, *args, **kwargs): return False def on_stop_tracking(self, *args, **kwargs): return False def on_external_framerate_change(self, *args, **kwargs): print2err('NOTE: Tobii System Sampling Rate Changed.') return False def on_head_box_change(self, *args, **kwargs): print2err('NOTE: Tobii Head Movement Box Changed.') return False def on_x_series_physical_config_change(self, *args, **kwargs): print2err('NOTE: Tobii X Series Physical Settings Changed.') return False def getTimeSyncManager(self): return self._sync_manager def getTimeSyncState(self): return self._sync_manager.sync_state() def getCurrentEyeTrackerTime(self): return self._sync_manager.convert_from_local_to_remote( self._getTobiiClockTime()) def getCurrentLocalTobiiTime(self): return self._getTobiiClockTime() def getTobiiTimeResolution(self): return self._getTobiiClockResolution() def getMainLoop(self): return self._mainloop def getTrackerDetails(self): tobiiInfoProperties = [ 'product_id', 'given_name', 'model', 'generation', 'firmware_version', 'status'] tprops = OrderedDict() eyetracker_info = self._eyetracker_info for tp in tobiiInfoProperties: ta = getattr(eyetracker_info, tp) if callable(ta): ta = ta() tprops[tp] = ta tprops['factory_info_string'] = str(eyetracker_info.factory_info) return tprops def getTrackerInfo(self): if hasattr(self._eyetracker, 'GetUnitInfo'): return self._eyetracker.GetUnitInfo() return None def startTracking(self, et_data_rx_callback=None): if et_data_rx_callback: self.on_eyetracker_data = et_data_rx_callback self._eyetracker.events.OnGazeDataReceived += self.on_eyetracker_data self._eyetracker.StartTracking(self.on_start_tracking) self._isRecording = True return True def stopTracking(self): self._eyetracker.events.OnGazeDataReceived -= self.on_eyetracker_data self._eyetracker.StopTracking(self.on_stop_tracking) self._isRecording = False def getName(self): return self._eyetracker.GetUnitName() def setName(self, name): self._eyetracker.SetUnitName(name) def getLowBlinkMode(self): try: return self._eyetracker.GetLowblinkMode() except Exception: pass return None def setLowBlinkMode(self, enable): if hasattr(self._eyetracker, 'SetLowblinkMode'): try: if isinstance(enable, bool) or enable == 0 or enable == 1: self._eyetracker.SetLowblinkMode(enable) return self._eyetracker.GetLowblinkMode() except Exception: pass return None def setSamplingRate(self, rate): if rate in self._eyetracker.EnumerateFramerates(): self._eyetracker.SetFramerate(rate) return rate return self._eyetracker.GetFramerate() def getAvailableSamplingRates(self): return self._eyetracker.EnumerateFramerates() def getSamplingRate(self): return self._eyetracker.GetFramerate() def getIlluminationMode(self): try: return self._eyetracker.getIlluminationMode() except Exception: pass return None def getAvailableIlluminationModes(self): try: return self._eyetracker.EnumerateIlluminationModes() except Exception: return [] def setIlluminationMode(self, imode): imodes = self.getAvailableIlluminationModes() if len(imodes) > 0: if imode in imodes: self._eyetracker.SetIlluminationMode(imode) return imode return self._eyetracker.getIlluminationMode() else: print 'WARNING: setIlluminationMode is not supported by either your Tobii model, or the version of the Tobii SDK being used.' def getHeadBox(self): hb = None if hasattr(self._eyetracker, 'GetTrackBox'): hb = self._eyetracker.GetTrackBox() elif hasattr(self._eyetracker, 'GetHeadMovementBox'): hb = self._eyetracker.GetHeadMovementBox() if hb: return np.asarray([ (hb.Point1.x, hb.Point1.y, hb.Point1.z), (hb.Point2.x, hb.Point2.y, hb.Point2.z), (hb.Point3.x, hb.Point3.y, hb.Point3.z), (hb.Point4.x, hb.Point4.y, hb.Point4.z), (hb.Point5.x, hb.Point5.y, hb.Point5.z), (hb.Point6.x, hb.Point6.y, hb.Point6.z), (hb.Point7.x, hb.Point7.y, hb.Point7.z), (hb.Point8.x, hb.Point8.y, hb.Point8.z) ]) return None def setXSeriesPhysicalPlacement(self, upperLeft, upperRight, lowerLeft): if self.getTrackerDetails()['generation'] == 'X': self._eyetracker.SetXConfiguration(upperLeft, upperRight, lowerLeft) return True return False def getEyeTrackerPhysicalPlacement(self): etpc = self._eyetracker.GetXConfiguration() ll = etpc.LowerLeft ul = etpc.UpperLeft ur = etpc.UpperRight return dict(lowerLeft=(ll.x, ll.y, ll.z), upperLeft=(ul.x, ul.y, ul.z), upperRight=(ur.x, ur.y, ur.z)) def getAvailableExtensions(self): return [ OrderedDict( name=e.Name, extensionId=e.ExtensionId, protocolVersion=e.ProtocolVersion, realm=e.Realm) for e in self._eyetracker.GetAvailableExtensions()] def getEnabledExtensions(self): return [ OrderedDict( name=e.Name, extensionId=e.ExtensionId, protocolVersion=e.ProtocolVersion, realm=e.Realm) for e in self._eyetracker.GetEnabledExtensions()] def enableExtension(self, extension): extension_id = extension if isinstance(extension, OrderedDict): extension_id = extension['extensionId'] self._eyetracker.EnableExtension(extension_id) def disconnect(self): if self._isRecording: self.stopTracking() self._mainloop.stop() self._mainloop = None self._eyetracker_info = None self._requested_product_id = None self._requested_model = None self._eyetracker = None def __del__(self): if self._mainloop: self.disconnect()
class TobiiTracker(object): LEFT = 0 RIGHT = 1 eye_data = OrderedDict(tracker_time_usec=np.NaN, pupil_diameter_mm=np.NaN, gaze_norm=[np.NaN, np.NaN], gaze_mm=[np.NaN, np.NaN, np.NaN], eye_location_norm=[np.NaN, np.NaN, np.NaN], eye_location_mm=[np.NaN, np.NaN, np.NaN], validity_code=np.NaN, status='UNKNOWN', trigger_signal=None) def __init__(self, eyetracker_info=None, product_id=None, model=None, mainloop=None, create_sync_manager=True): self._eyetracker_info = eyetracker_info self._requested_product_id = product_id self._requested_model = model self._mainloop = mainloop self._eyetracker = None self._queue = None self._tobiiClock = None self._getTobiiClockResolution = None self._getTobiiClockTime = None self._sync_manager = None self._syncTimeEventDeque = None self._isRecording = False if eyetracker_info is None: if not TobiiTrackerBrowser.isActive(): TobiiTrackerBrowser.start() self._eyetracker_info = TobiiTrackerBrowser.findDevice( model, product_id) if self._eyetracker_info: self._mainloop = TobiiTrackerBrowser.getMainLoop() TobiiTrackerBrowser.stop() else: self._eyetracker_info = TobiiTrackerBrowser.findDevice( model, product_id) if self._eyetracker_info is None: raise exceptions.BaseException( 'Could not find a Tobii Eye Tracker matching requirements.') if self._mainloop is None: if TobiiTrackerBrowser.isActive(): self._mainloop = TobiiTrackerBrowser.getMainLoop() else: TobiiPy.init() self._mainloop = TobiiPyMainloopThread() self._mainloop.start() self._queue = Queue.Queue() TobiiPyEyeTracker.create_async(self._mainloop, self._eyetracker_info, self.on_eyetracker_created) stime = getTime() while getTime() - stime < 10.0: try: event = self._queue.get(block=True, timeout=.1) if isinstance(event, TobiiTrackerCreatedEvent): self._eyetracker = event.tracker_object self._eyetracker.events.OnFramerateChanged += self.on_external_framerate_change if hasattr(self._eyetracker.events, 'OnHeadMovementBoxChanged'): self._eyetracker.events.OnHeadMovementBoxChanged += self.on_head_box_change elif hasattr(self._eyetracker.events, 'OnTrackBoxChanged'): self._eyetracker.events.OnTrackBoxChanged += self.on_head_box_change else: print 'WARNING: TobiiClasses could not set callback hook for "self.on_head_box_change".' self._eyetracker.events.OnXConfigurationChanged += self.on_x_series_physical_config_change break self._queue.task_done() except Queue.Empty: pass if self._eyetracker is None: raise exceptions.BaseException( 'Could not connect to Tobii. Timeout.') if create_sync_manager: self._eyetracker.events.OnError += self.on_eyetracker_error self._tobiiClock = TobiiPyClock() self._getTobiiClockResolution = self._tobiiClock.get_resolution self._getTobiiClockTime = self._tobiiClock.get_time self._syncTimeEventDeque = collections.deque(maxlen=32) self._sync_manager = TobiiPySyncManager(self._tobiiClock, self._eyetracker_info, self._mainloop, self.on_sync_error, self.on_sync_status) def on_eyetracker_created(self, *args, **kwargs): # print 'on_eyetracker_created: entered' et = None if len(args) >= 2: et = args[1] else: raise exceptions.BaseException( 'WARNING: on_eyetracker_created: Unhandled args count', len(args), args) error = kwargs.get('error', None) if error: raise exceptions.BaseException( 'Connection to Tobii failed because of an exception: %s' % (str(error), )) self._queue.put(TobiiTrackerCreatedEvent(et)) return False def on_eyetracker_error(self, *args, **kwargs): print2err('TobiiTracker.on_eyetracker_error: ', args, kwargs) return False def on_sync_error(self, *args, **kwargs): print2err('TobiiTracker.on_sync_error: ', args, kwargs) return False def on_sync_status(self, *args, **kwargs): sync_state = args[0] self._syncTimeEventDeque.append(sync_state) return False def on_eyetracker_data(self, *args, **kwargs): eye_data_event = args[1] LEFT = self.LEFT RIGHT = self.RIGHT eyes = (copy.deepcopy(self.eye_data), copy.deepcopy(self.eye_data)) eyes[LEFT]['validity_code'] = eye_data_event.LeftValidity eyes[RIGHT]['validity_code'] = eye_data_event.RightValidity eyes[LEFT]['tracker_time_usec'] = eye_data_event.Timestamp eyes[RIGHT]['tracker_time_usec'] = eye_data_event.Timestamp if hasattr(eye_data_event, 'TrigSignal'): eyes[LEFT]['trigger_signal'] = eye_data_event.TrigSignal eyes[RIGHT]['trigger_signal'] = eye_data_event.TrigSignal # print "*** lastEyeData.RightGazePoint2D: # ",lastEyeData.RightGazePoint2D.__dict__ if eye_data_event.LeftValidity >= 2 and eye_data_event.RightValidity >= 2: # no eye signal eyes[LEFT]['status'] = 'Missing' eyes[RIGHT]['status'] = 'Missing' elif eye_data_event.LeftValidity < 2 and eye_data_event.RightValidity >= 2: # left eye only available eyes[LEFT]['status'] = 'Available' eyes[RIGHT]['status'] = 'Missing' eyes[LEFT]['pupil_diameter_mm'] = eye_data_event.LeftPupil eyes[LEFT]['gaze_norm'][0] = eye_data_event.LeftGazePoint2D.x eyes[LEFT]['gaze_norm'][1] = eye_data_event.LeftGazePoint2D.y eyes[LEFT]['gaze_mm'][0] = eye_data_event.LeftGazePoint3D.x eyes[LEFT]['gaze_mm'][1] = eye_data_event.LeftGazePoint3D.y eyes[LEFT]['gaze_mm'][2] = eye_data_event.LeftGazePoint3D.z eyes[LEFT]['eye_location_norm'][ 0] = eye_data_event.LeftEyePosition3DRelative.x eyes[LEFT]['eye_location_norm'][ 1] = eye_data_event.LeftEyePosition3DRelative.y eyes[LEFT]['eye_location_norm'][ 2] = eye_data_event.LeftEyePosition3DRelative.z eyes[LEFT]['eye_location_mm'][ 0] = eye_data_event.LeftEyePosition3D.x eyes[LEFT]['eye_location_mm'][ 1] = eye_data_event.LeftEyePosition3D.y eyes[LEFT]['eye_location_mm'][ 2] = eye_data_event.LeftEyePosition3D.z elif eye_data_event.LeftValidity >= 2 and eye_data_event.RightValidity < 2: # right eye only available eyes[RIGHT]['status'] = 'Available' eyes[LEFT]['status'] = 'Missing' eyes[RIGHT]['pupil_diameter_mm'] = eye_data_event.RightPupil eyes[RIGHT]['gaze_norm'][0] = eye_data_event.RightGazePoint2D.x eyes[RIGHT]['gaze_norm'][1] = eye_data_event.RightGazePoint2D.y eyes[RIGHT]['gaze_mm'][0] = eye_data_event.RightGazePoint3D.x eyes[RIGHT]['gaze_mm'][1] = eye_data_event.RightGazePoint3D.y eyes[RIGHT]['gaze_mm'][2] = eye_data_event.RightGazePoint3D.z eyes[RIGHT]['eye_location_norm'][ 0] = eye_data_event.RightEyePosition3DRelative.x eyes[RIGHT]['eye_location_norm'][ 1] = eye_data_event.RightEyePosition3DRelative.y eyes[RIGHT]['eye_location_norm'][ 2] = eye_data_event.RightEyePosition3DRelative.z eyes[RIGHT]['eye_location_mm'][ 0] = eye_data_event.RightEyePosition3D.x eyes[RIGHT]['eye_location_mm'][ 1] = eye_data_event.RightEyePosition3D.y eyes[RIGHT]['eye_location_mm'][ 2] = eye_data_event.RightEyePosition3D.z else: # binocular available eyes[RIGHT]['status'] = 'Available' eyes[LEFT]['status'] = 'Available' eyes[LEFT]['pupil_diameter_mm'] = eye_data_event.LeftPupil eyes[LEFT]['gaze_norm'][0] = eye_data_event.LeftGazePoint2D.x eyes[LEFT]['gaze_norm'][1] = eye_data_event.LeftGazePoint2D.y eyes[LEFT]['gaze_mm'][0] = eye_data_event.LeftGazePoint3D.x eyes[LEFT]['gaze_mm'][1] = eye_data_event.LeftGazePoint3D.y eyes[LEFT]['gaze_mm'][2] = eye_data_event.LeftGazePoint3D.z eyes[LEFT]['eye_location_norm'][ 0] = eye_data_event.LeftEyePosition3DRelative.x eyes[LEFT]['eye_location_norm'][ 1] = eye_data_event.LeftEyePosition3DRelative.y eyes[LEFT]['eye_location_norm'][ 2] = eye_data_event.LeftEyePosition3DRelative.z eyes[LEFT]['eye_location_mm'][ 0] = eye_data_event.LeftEyePosition3D.x eyes[LEFT]['eye_location_mm'][ 1] = eye_data_event.LeftEyePosition3D.y eyes[LEFT]['eye_location_mm'][ 2] = eye_data_event.LeftEyePosition3D.z eyes[RIGHT]['pupil_diameter_mm'] = eye_data_event.RightPupil eyes[RIGHT]['gaze_norm'][0] = eye_data_event.RightGazePoint2D.x eyes[RIGHT]['gaze_norm'][1] = eye_data_event.RightGazePoint2D.y eyes[RIGHT]['gaze_mm'][0] = eye_data_event.RightGazePoint3D.x eyes[RIGHT]['gaze_mm'][1] = eye_data_event.RightGazePoint3D.y eyes[RIGHT]['gaze_mm'][2] = eye_data_event.RightGazePoint3D.z eyes[RIGHT]['eye_location_norm'][ 0] = eye_data_event.RightEyePosition3DRelative.x eyes[RIGHT]['eye_location_norm'][ 1] = eye_data_event.RightEyePosition3DRelative.y eyes[RIGHT]['eye_location_norm'][ 2] = eye_data_event.RightEyePosition3DRelative.z eyes[RIGHT]['eye_location_mm'][ 0] = eye_data_event.RightEyePosition3D.x eyes[RIGHT]['eye_location_mm'][ 1] = eye_data_event.RightEyePosition3D.y eyes[RIGHT]['eye_location_mm'][ 2] = eye_data_event.RightEyePosition3D.z return False def on_start_tracking(self, *args, **kwargs): return False def on_stop_tracking(self, *args, **kwargs): return False def on_external_framerate_change(self, *args, **kwargs): print2err('NOTE: Tobii System Sampling Rate Changed.') return False def on_head_box_change(self, *args, **kwargs): print2err('NOTE: Tobii Head Movement Box Changed.') return False def on_x_series_physical_config_change(self, *args, **kwargs): print2err('NOTE: Tobii X Series Physical Settings Changed.') return False def getTimeSyncManager(self): return self._sync_manager def getTimeSyncState(self): return self._sync_manager.sync_state() def getCurrentEyeTrackerTime(self): return self._sync_manager.convert_from_local_to_remote( self._getTobiiClockTime()) def getCurrentLocalTobiiTime(self): return self._getTobiiClockTime() def getTobiiTimeResolution(self): return self._getTobiiClockResolution() def getMainLoop(self): return self._mainloop def getTrackerDetails(self): tobiiInfoProperties = [ 'product_id', 'given_name', 'model', 'generation', 'firmware_version', 'status' ] tprops = OrderedDict() eyetracker_info = self._eyetracker_info for tp in tobiiInfoProperties: ta = getattr(eyetracker_info, tp) if callable(ta): ta = ta() tprops[tp] = ta tprops['factory_info_string'] = str(eyetracker_info.factory_info) return tprops def getTrackerInfo(self): if hasattr(self._eyetracker, 'GetUnitInfo'): return self._eyetracker.GetUnitInfo() return None def startTracking(self, et_data_rx_callback=None): if et_data_rx_callback: self.on_eyetracker_data = et_data_rx_callback self._eyetracker.events.OnGazeDataReceived += self.on_eyetracker_data self._eyetracker.StartTracking(self.on_start_tracking) self._isRecording = True return True def stopTracking(self): self._eyetracker.events.OnGazeDataReceived -= self.on_eyetracker_data self._eyetracker.StopTracking(self.on_stop_tracking) self._isRecording = False def getName(self): return self._eyetracker.GetUnitName() def setName(self, name): self._eyetracker.SetUnitName(name) def getLowBlinkMode(self): try: return self._eyetracker.GetLowblinkMode() except Exception: pass return None def setLowBlinkMode(self, enable): if hasattr(self._eyetracker, 'SetLowblinkMode'): try: if isinstance(enable, bool) or enable == 0 or enable == 1: self._eyetracker.SetLowblinkMode(enable) return self._eyetracker.GetLowblinkMode() except Exception: pass return None def setSamplingRate(self, rate): if rate in self._eyetracker.EnumerateFramerates(): self._eyetracker.SetFramerate(rate) return rate return self._eyetracker.GetFramerate() def getAvailableSamplingRates(self): return self._eyetracker.EnumerateFramerates() def getSamplingRate(self): return self._eyetracker.GetFramerate() def getIlluminationMode(self): try: return self._eyetracker.getIlluminationMode() except Exception: pass return None def getAvailableIlluminationModes(self): try: return self._eyetracker.EnumerateIlluminationModes() except Exception: return [] def setIlluminationMode(self, imode): imodes = self.getAvailableIlluminationModes() if len(imodes) > 0: if imode in imodes: self._eyetracker.SetIlluminationMode(imode) return imode return self._eyetracker.getIlluminationMode() else: print 'WARNING: setIlluminationMode is not supported by either your Tobii model, or the version of the Tobii SDK being used.' def getHeadBox(self): hb = None if hasattr(self._eyetracker, 'GetTrackBox'): hb = self._eyetracker.GetTrackBox() elif hasattr(self._eyetracker, 'GetHeadMovementBox'): hb = self._eyetracker.GetHeadMovementBox() if hb: return np.asarray([(hb.Point1.x, hb.Point1.y, hb.Point1.z), (hb.Point2.x, hb.Point2.y, hb.Point2.z), (hb.Point3.x, hb.Point3.y, hb.Point3.z), (hb.Point4.x, hb.Point4.y, hb.Point4.z), (hb.Point5.x, hb.Point5.y, hb.Point5.z), (hb.Point6.x, hb.Point6.y, hb.Point6.z), (hb.Point7.x, hb.Point7.y, hb.Point7.z), (hb.Point8.x, hb.Point8.y, hb.Point8.z)]) return None def setXSeriesPhysicalPlacement(self, upperLeft, upperRight, lowerLeft): if self.getTrackerDetails()['generation'] == 'X': self._eyetracker.SetXConfiguration(upperLeft, upperRight, lowerLeft) return True return False def getEyeTrackerPhysicalPlacement(self): etpc = self._eyetracker.GetXConfiguration() ll = etpc.LowerLeft ul = etpc.UpperLeft ur = etpc.UpperRight return dict(lowerLeft=(ll.x, ll.y, ll.z), upperLeft=(ul.x, ul.y, ul.z), upperRight=(ur.x, ur.y, ur.z)) def getAvailableExtensions(self): return [ OrderedDict(name=e.Name, extensionId=e.ExtensionId, protocolVersion=e.ProtocolVersion, realm=e.Realm) for e in self._eyetracker.GetAvailableExtensions() ] def getEnabledExtensions(self): return [ OrderedDict(name=e.Name, extensionId=e.ExtensionId, protocolVersion=e.ProtocolVersion, realm=e.Realm) for e in self._eyetracker.GetEnabledExtensions() ] def enableExtension(self, extension): extension_id = extension if isinstance(extension, OrderedDict): extension_id = extension['extensionId'] self._eyetracker.EnableExtension(extension_id) def disconnect(self): if self._isRecording: self.stopTracking() self._mainloop.stop() self._mainloop = None self._eyetracker_info = None self._requested_product_id = None self._requested_model = None self._eyetracker = None def __del__(self): if self._mainloop: self.disconnect()