def __init__(self): self.window = gtk.Window(gtk.WINDOW_TOPLEVEL) self.window.set_title("Upgrade Tool") self.window.connect("delete_event", self.delete_event) self.window.connect("destroy", self.destroy) self.window.set_border_width(3) self.window.set_size_request(550, -1) self.mainloop = MainloopThread() self.mainloop.start() self.vbox = gtk.VBox() self.vbox.set_spacing(3) self.selector = EyetrackerSelector(self.mainloop, self._on_selected) self.file_filter = gtk.FileFilter() self.file_filter.set_name("Tobii Upgrade Packages") self.file_filter.add_pattern("*.tobiipkg") self.chooser = gtk.FileChooserButton(title="Select Firmware File") self.chooser.add_filter(self.file_filter) self.chooser.connect('file-set', self._on_file_selected) self.hbox1 = gtk.HBox() self.hbox1.pack_start(self.selector) self.hbox1.pack_end(self.chooser) self.progress = gtk.ProgressBar() self.cancel = gtk.Button("Cancel") self.cancel.set_sensitive(False) self.start = gtk.Button("Start Upgrade") self.start.set_sensitive(False) self.start.connect('clicked', self._start_upgrade) self.hbox2 = gtk.HBox() self.hbox2.pack_start(self.progress) self.hbox2.pack_end(self.cancel, expand=False) self.hbox2.pack_end(self.start, expand=False) self.vbox.pack_start(self.hbox1, expand=False) self.vbox.pack_end(self.hbox2, expand=False) self.window.add(self.vbox) self.window.show_all() self.upgrading_device = None self.selected_file = None self.upgrade_started = False
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()
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 UpgradeTool(object): def __init__(self): self.window = gtk.Window(gtk.WINDOW_TOPLEVEL) self.window.set_title("Upgrade Tool") self.window.connect("delete_event", self.delete_event) self.window.connect("destroy", self.destroy) self.window.set_border_width(3) self.window.set_size_request(550, -1) self.mainloop = MainloopThread() self.mainloop.start() self.vbox = gtk.VBox() self.vbox.set_spacing(3) self.selector = EyetrackerSelector(self.mainloop, self._on_selected) self.file_filter = gtk.FileFilter() self.file_filter.set_name("Tobii Upgrade Packages") self.file_filter.add_pattern("*.tobiipkg") self.chooser = gtk.FileChooserButton(title="Select Firmware File") self.chooser.add_filter(self.file_filter) self.chooser.connect('file-set', self._on_file_selected) self.hbox1 = gtk.HBox() self.hbox1.pack_start(self.selector) self.hbox1.pack_end(self.chooser) self.progress = gtk.ProgressBar() self.cancel = gtk.Button("Cancel") self.cancel.set_sensitive(False) self.start = gtk.Button("Start Upgrade") self.start.set_sensitive(False) self.start.connect('clicked', self._start_upgrade) self.hbox2 = gtk.HBox() self.hbox2.pack_start(self.progress) self.hbox2.pack_end(self.cancel, expand=False) self.hbox2.pack_end(self.start, expand=False) self.vbox.pack_start(self.hbox1, expand=False) self.vbox.pack_end(self.hbox2, expand=False) self.window.add(self.vbox) self.window.show_all() self.upgrading_device = None self.selected_file = None self.upgrade_started = False def _on_file_selected(self, chooser): self.selected_file = self.chooser.get_filename() self._check_match() def _on_selected(self, device_info): self.upgrading_device = device_info self._check_match() def _check_match(self): if self.upgrading_device is None or self.selected_file is None: return self.chooser.set_sensitive(False) self.selector.set_sensitive(False) self.start.set_sensitive(False) self.cancel.set_sensitive(False) try: code = upgrade.package_is_compatible_with_device(self.mainloop, self.selected_file, self.upgrading_device) if code == 0: self.progress.set_text("") self.start.set_sensitive(True) else: msg = tobii.sdk.error_code_to_string(code) if msg.startswith("TOBII_SDK_ERROR_"): msg = msg[len("TOBII_SDK_ERROR_"):] self.progress.set_text("Not compatible: %s" % (msg)) self.start.set_sensitive(False) finally: self.chooser.set_sensitive(True) self.selector.set_sensitive(True) def _start_upgrade(self, button): if self.upgrade_started or self.upgrading_device is None: return self.start.set_sensitive(False) self.cancel.set_sensitive(False) self.upgrade_started = True try: self._upgrade_progress_init = False upgrade.begin_upgrade(self.mainloop, self.selected_file, self.upgrading_device, lambda code: glib_idle_add(self._on_upgrade_complete, code), lambda c, n, p: glib_idle_add(self._on_upgrade_progress, c, n, p), lambda c: glib_idle_add(self._on_upgrade_cancancel_changed, c)) except Exception, ex: self.upgrade_started = False self.start.set_sensitive(True) print "ERROR: ", ex