Home › Forums › Software Development › Checking whether if the eye tracker is connected
Tagged: disconnect, quit, tracker status
- This topic has 17 replies, 7 voices, and was last updated 9 years, 2 months ago by Patrik [Tobii].
- AuthorPosts
- 08/02/2014 at 10:40 #412Cheng GuoParticipant
Hello,
I am currently using the .Net binding of the eyeX library. I would like to know if there is a method that would allow me to check if an eye tracker is physically connected to the computer.
Also, what is the correct procedure for disconnecting the eye tracker (e.g. when a program quits)?
Thanks!
10/02/2014 at 18:12 #423Robert [Tobii]ParticipantHi,
1) The connection state of the eye tracker can be checked by adding an event handler to the
InteractionContext.ConnectionStateChanged
event. Look how this is done in the MinimalGazeDataStream sample in the Unity package.2) To disconnect the eye tracker properly, dispose the
InteractionContext
andInteractionSystem
instances respectivly.11/02/2014 at 08:45 #427Cheng GuoParticipantHi Robert,
Thanks for the reply.
I disconnected the eye tracker from my computer, and I run the MinimalGazeDataStream sample. I see “The connection state is now connected” printed in the console.
In the eye tracker control panel, it says “No eye tracker was found. Please plug in your eye tracker.”
Do you know why this is happening? (My guess is that the ConnectionStateChanged means connecting with the eye tracker engine but not the physical connection between the eye tracker and the computer?)
For disconnect the eye tracker properply, I did this
context.DisableConnection(); // context is InteractionContext context = null;
In the MinimalGazeDataStream sample, the InteractionSystem is never instantiated, so I am not sure how to dispose it. Thus, all I can do is to dispose the InteractionContext object. Please let me know if this is correct.
Thanks.
11/02/2014 at 10:19 #429Robert [Tobii]ParticipantSorry, I was thinking of the wrong sample. As you suspected, the
ConnectionStateChanged
only checks the connection to the EyeX Engine.EDIT: See next reply for an answer to the first question.
For the other question, it is recommended to instantiate both the InteractionSystem and InteractionContext and dispose them on exit. We might have missed one of these steps on some samples, sorry about that.
11/02/2014 at 20:07 #436Jenny [Tobii]ParticipantHi!
Robert asked me to give you an example of how to retrieve the eye tracking device status. Normally, when the eye tracking device is connected to the computer and up and running, its status would be “Tracking”. If the user has selected “Disable Eye Tracking” in the tray icon menu, the status is normally “Tracking Paused”.
This is how you can retrieve information about the eye tracking device status through the .NET binding:
First, where all handlers are registered, register a notification handler and register the context as a settings observer as well:
context.RegisterNotificationHandler(HandleNotification); context.RegisterSettingsObserver(SettingsPaths.EyeTracking);
Then, add methods for handling notification callbacks:
private void HandleNotification(InteractionNotification notification) { if (NotificationType.SettingsChanged == notification.NotificationType) { OnSettingsReceived((SettingsBag)notification.Data); } } private void OnSettingsReceived(SettingsBag data) { EyeTrackingDeviceStatus deviceStatus; var success = data.TryGetSettingValue(out deviceStatus, "eyetracking.state"); if (success) { Console.WriteLine("Eye Tracking Device Status is: " + deviceStatus); } }
Does that give you the information you need?
12/02/2014 at 08:11 #441Cheng GuoParticipantHello Jenny:
Thanks for the response. I have tried your method that this is what I did:
1) I have the eye tracker connected and running
2) I started my program with your code added
3) while my program is running, I right clicked on the EyeX icon in the system tray (I am running on windows 8) and selected “Disable Eye Tracking”After I did step #3, I received an error message in Visual Studio 2012:
“Tobii.EyeX.Client.InteractionApiException” “Result = InvalidArgument”
The error was caused by this line of code:
var success = data.TryGetSettingValue(out deviceStatus, "eyetracking.state");
oh, I forgot to mention that I am using the REX desktop version hardware.
What I am trying to solve is to detect eye tracker’s physical connection on program startup. I want to know if the eye tracker is connected so that I can decide to fire up my program or not.
The solution you provide seems to require the eye tracker to be physically connected first. (I tried to run your code without the eye tracker connected and it would not capture any error).
12/02/2014 at 16:09 #451Jenny [Tobii]ParticipantHi again,
Yep, there was a bug in the client library… It worked well on my computer for some reason, but not on Robert’s. The bug is fixed and I have uploaded new SDK packages that include the fix.
Ok, so let’s go back to what you actually want to achieve 🙂
If I understand you correctly, you have an application that there is no point in starting if there is no working eye tracking?
I believe the Eye Tracking Device Status is what you should use. It does not require the eye tracker to be physically connected and it has a state for when the eye tracker is not connected. But I think the best thing you could do is to make sure that this status is “Tracking” before starting your application. Then everything should be up and running and usable with eye tracking (eye tracker connected, correct screen mapping, calibration – all the ground work that is handled by the EyeX Engine). If the status is not “Tracking”, then something is missing in the setup, or eye tracking is disabled, so eye tracking cannot be used with the application.
But, something is missing to the code I gave you in the last reply – that code only reports changes to the status.
This is what you have to do to request the current status:
After the connection to the EyeX Engine has been established (when there has been a ConnectionStateChanged event with status ConnectionState.Connected), you can make this asynchronous call to retrieve the Eye Tracking Device Status:context.GetSettingsAsync(SettingsPaths.EyeTracking, OnSettingsReceived);
The callback method OnSettingsReceived is the same as in the reply above.
If you are only interested in making a single call to ask the current status, the above line of code plus the callback method is all you need. If you also want to react to changes to the status, you should keep the other code as well.
14/02/2014 at 06:26 #462Cheng GuoParticipantHello Jenny:
Great job! Everything works fine now on my computer. The problem is fixed by the new SDK. Thanks for the quick update 🙂
14/11/2014 at 14:42 #2013Benjamin RobertParticipantHello !
I have the same issue with the C/C++ SDK. Seems like it’s a little bit different.
Should I create a txCreateInteractorBehavior with a hBehaviorWithoutParameters ? I need to detect whenever the device is plugged or unppluged.
Thanks
14/11/2014 at 16:21 #2015AndersParticipantHi Benjamin,
take a look at the MinimalStatusNotifications sample in the C/C++ SDK, it should be a good starting point.What you want to do, in the EyeX lingo, is to register a state-changed handler for the TX_STATEPATH_EYETRACKINGSTATE engine state. You don’t have to create any interactors in this case.
14/11/2014 at 16:30 #2017Benjamin RobertParticipantThanks a lot !
14/11/2014 at 18:39 #2020Benjamin RobertParticipantHello again,
I tried to use the state-change handler and I have an error. Here’s what I do :
success = txCreateGlobalInteractorSnapshot( _context, InteractorId, &g_hGlobalInteractorSnapshot, &hInteractor) == TX_RESULT_OK; success &= txCreateGazePointDataBehavior(hInteractor, ¶ms) == TX_RESULT_OK; success &= txCreateStateBag(_context, &hStateBag, TX_STATEPATH_EYETRACKINGSTATE) == TX_RESULT_OK;
First I create a state bag in my context. Everything is going well at this point but I show you in case I don’t do it the right way. Then I register my State Handler :
bool EyeXHost::RegisterStateChangedHandler() { auto stateChangedTrampoline = [](TX_CONSTHANDLE hState, TX_USERPARAM userParam) { static_cast<EyeXHost*>(userParam)->OnEngineStateChanged(hState); }; bool success = txRegisterStateChangedHandler(_context, &_stateChangedTicket, TX_STATEPATH_USERPRESENCE, stateChangedTrampoline, this) == TX_RESULT_OK; return success; }
Same way that I do for the engine connection which works fine. Then on the method OnEngineStateChanged :
void EyeXHost::OnEngineStateChanged(TX_CONSTHANDLE hState) { TX_HANDLE hStateBag = TX_EMPTY_HANDLE; TX_BOOL success; TX_INTEGER eyeTrackingState; txGetAsyncDataContent(hState, &hStateBag); success = txGetStateValueAsInteger(hStateBag, TX_STATEPATH_EYETRACKINGSTATE, &eyeTrackingState) == TX_RESULT_OK; if (success) { switch (eyeTrackingState) { case TX_EYETRACKINGDEVICESTATUS_TRACKING: printf("Eye Tracking Device Status: 'CONNECTED'"); connectionSuccess = true; break; case TX_EYETRACKINGDEVICESTATUS_DEVICENOTCONNECTED: printf("Eye Tracking Device Status: 'NOT CONNECTED'"); connectionSuccess = false; break; default: connectionSuccess = true; } } else printf("ERROR"); txReleaseObject(&hStateBag); }
At this point I always get “ERROR”. But I don’t really understand why txGetStateValueAsInteger won’t return true. It works with the interactor and the Engine Connection callback so I’m not really sure where that come from. If you have any idea it would be great. Sorry if it’s a simple mistake.
17/11/2014 at 09:48 #2030Robert [Tobii]ParticipantHi Benjamin,
It looks like a simple copy/paste error. If you want to listen for changes in the User Presence state, try to replace TX_STATEPATH_EYETRACKINGSTATE with TX_STATEPATH_USERPRESENCE in the txGetStateValueAsInteger function call (row 9 in the last code snippet).
Then you need to check if the result is TX_USERPRESENCE_PRESENT or TX_USERPRESENCE_NOTPRESENT.
Moreover, I don’t think the txCreateStateBag row is necessary.
Please let me know how it goes.
17/11/2014 at 10:34 #2034Benjamin RobertParticipantThanks for your answer.
I’m a little bit confuse here. In your C example, you havesuccess = (txGetStateValueAsInteger(hStateBag, TX_STATEPATH_EYETRACKINGSTATE, &eyeTrackingState) == TX_RESULT_OK); if (success) { switch (eyeTrackingState) { case TX_EYETRACKINGDEVICESTATUS_TRACKING: printf("Eye Tracking Device Status: 'TRACKING'.\n" "That means that the eye tracker is up and running and trying to track your eyes.\n"); break; default: printf("The eye tracking device is not tracking.\n" "It could be a that the eye tracker is not connected, or that a screen setup or\n" "user calibration is missing. The status code is %d.\n", eyeTrackingState); } }
txGetStateValueAsInteger takes TX_STATEPATH_EYETRACKINGSTATE has an argument to check if the device is tracking. I want to check if the device is connected, I should check with the same parameter I guess because the parameter is TX_EYETRACKINGDEVICESTATUS_NOTCONNECTED and not something like TX_USERPRESENCE_NOTCONNECTED. I tried with the user presence param but it’s not working to track if the device is connected or not.
My code :
void EyeXHost::OnEngineStateChanged(TX_CONSTHANDLE hState) { TX_HANDLE hStateBag = TX_EMPTY_HANDLE; TX_BOOL success; TX_INTEGER eyeTrackingState; TX_INTEGER presenceData; txGetAsyncDataContent(hState, &hStateBag); success = (txGetStateValueAsInteger(hStateBag, TX_STATEPATH_EYETRACKINGSTATE, &eyeTrackingState) == TX_RESULT_OK); if (success) { switch (eyeTrackingState) { case TX_EYETRACKINGDEVICESTATUS_TRACKING: printf("TRACKING"); break; case TX_EYETRACKINGDEVICESTATUS_DEVICENOTCONNECTED: printf("NOT CONNECTED"); break; default: printf("The status code is %d.\n", eyeTrackingState); } } success = (txGetStateValueAsInteger(hStateBag, TX_STATEPATH_USERPRESENCE, &presenceData) == TX_RESULT_OK); if (success) { printf("User is %s\n", presenceData == TX_USERPRESENCE_PRESENT ? "present" : "NOT present"); } txReleaseObject(&hStateBag); }
17/11/2014 at 11:11 #2037Robert [Tobii]ParticipantOk, now I understand. If you are interested in the eye tracker connection you need to pass TX_STATEPATH_EYETRACKINGSTATE in the call to txRegisterStateChangedHandler (row 8 in the second code snippet in post #2020)
Then, in the switch statement you can choose to handle the device status value you are interested in, one or many of these:
TX_EYETRACKINGDEVICESTATUS_INITIALIZING,
TX_EYETRACKINGDEVICESTATUS_NOTAVAILABLE,
TX_EYETRACKINGDEVICESTATUS_INVALIDCONFIGURATION,
TX_EYETRACKINGDEVICESTATUS_DEVICENOTCONNECTED,
TX_EYETRACKINGDEVICESTATUS_TRACKING,
TX_EYETRACKINGDEVICESTATUS_TRACKINGPAUSED,
TX_EYETRACKINGDEVICESTATUS_CONFIGURING,
TX_EYETRACKINGDEVICESTATUS_UNKNOWNERROR,
TX_EYETRACKINGDEVICESTATUS_CONNECTIONERRORSee the header documentation in EyeXFrameworkTypes.h to learn more about what each enum value mean.
- AuthorPosts
- You must be logged in to reply to this topic.