Home Forums Software Development Get Eye XYZ Position – cannot find the functions for TX_INTERACTIONBEHAVIORTYPE_

Viewing 15 posts - 1 through 15 (of 16 total)
  • Author
    Posts
  • #1330
    Laser Erich
    Participant

    Hello,

    I’m searching for the functions for the TX_INTERACTIONBEHAVIORTYPE_EYEPOSITIONDATA.
    I’m tracking the GAZEPOINT as follows:

    setting the TX_GAZEPOINTDATAPRAMS parms = { TX_GAZEPOINTDATAMODE_LIGHTLYFILTERED };

    create the InteractionBehavior:
    txCreateInteractorBehavior( … TX_INTERACTIONBEHAVIORYPE_GAZEPOINTDATA)
    txSetGazePointDataBehaviorParams( …);

    creat an EventHandler using txGetGazePointDataEventParams(…)

    the same procedure works for FIXATIONDATAPARM …
    but I cannot find the corresponding methods for EYEPOSTIONDATA

    I cannot find the TX_EYEPOSITIONPARAMS and the txSetEyePositonDataBehaviorParams()
    (TX_INTERACTIONBEHAVIORTYPE_EYEPOSITIONDATA and txGetEyePostijonDataEventParams() are available)

    #1331
    Anders
    Participant

    Hi Manuel,
    since there are no parameters to be specified for the eye position data stream, you should use the generic function txCreateInteractorBehavior instead.

    #1338
    Laser Erich
    Participant

    Thank you for the hint.

    I create the InteractorBehavior for TX_INTERACTIONBEHAVIORTYPE_EYEPOSITIONDATA now without params.

    I registered an eventhandler for TX_INTERACTIONBEHAVIORTYPE_EYEPOSITIONDATA and for TX_INTERACTIONBEHAVIORTYPE_GAZEPOINTDATA but don’t get any EyePositionData Events (only TX_INTERACTIONBEHAVIORTYPE_GAZEPOINTDATA Events)

    How do I get Tobii to create EYEPOSITIONDATA Events?

    #1339
    Laser Erich
    Participant

    Additinally (I think I found my error):

    I create the behavior for the EyePositionInteractor via
    txCreateInteractorBehavior(eyePositionInteractor, &eyePositionBehavior, TX_INTERACTIONBEHAVIORTYPE_EYEPOSITIONDATA);

    And if I check if the result is
    TX_RESULT_OK
    that’s false.

    How am I supposed to change?

    #1340
    Laser Erich
    Participant

    I’m still trying to get the gazePosition and eyePosition from TobiiEyeX simultaniously.
    I can initiate and register TX_INTERACTIONBEHAVIORTYPE_EYEPOSITIONDATA and TX_INTERACTIONBEHAVIORTYPE_GAZEPOINTDATA seperatly, but when try to create two interactors, the second one won’t work.
    I tried to create two seperate TX_CONTEXTHANDLEs and two different Interactors with no success.
    Is it possible to track gazepoint and eyeposition simultaniously?

    #1342
    Anders
    Participant

    Hi Manuel,
    it’s certainly possible to get gaze position and eye position simultaneously.

    You can use one interactor or two, that doesn’t matter. But you should only set up one context and one event handler function.

    Here’s how I did it. I started from the MinimalGazeDataStream.c sample and modified the InitializeGlobalInteractorSnapshot function like so:

    
    BOOL InitializeGlobalInteractorSnapshot(TX_CONTEXTHANDLE hContext)
    {
    ...
    	TX_HANDLE hBehavior = TX_EMPTY_HANDLE;
    
    ...
    	success &= txCreateInteractorBehavior(hInteractor, &hBehavior, TX_INTERACTIONBEHAVIORTYPE_EYEPOSITIONDATA) == TX_RESULT_OK;
    
    	txReleaseObject(&hBehavior);
    	txReleaseObject(&hInteractor);
    
    	return success;
    }
    

    Note that hBehavior has to be initialized to TX_EMPTY_HANDLE or else the call will fail.

    And then, in the HandleEvent function I added a clause like so:

    
    	if (txGetEventBehavior(hEvent, &hBehavior, TX_INTERACTIONBEHAVIORTYPE_EYEPOSITIONDATA) == TX_RESULT_OK) {
    		printf("gotcha!\n");
    		txReleaseObject(&hBehavior);
    	}
    
    #1344
    Laser Erich
    Participant

    First of all thank you.

    That’s exactly what I’m doing:

    
    TX_HANDLE eyePositionInteractor = TX_EMPTY_HANDLE;
    	TX_HANDLE eyePositionBehavior   = TX_EMPTY_HANDLE;
    	
    	bool success;
    	success = txCreateGlobalInteractorSnapshot(hContext, InteractorId2, &g_hGlobalInteractorSnapshot, &eyePositionInteractor) == TX_RESULT_OK;
    	success &= txCreateInteractorBehavior(eyePositionInteractor, &eyePositionBehavior, TX_INTERACTIONBEHAVIORTYPE_EYEPOSITIONDATA) == TX_RESULT_OK;
    
    	txReleaseObject(&eyePositionBehavior);
    	txReleaseObject(&eyePositionInteractor);
    
    	return success;
    

    And then, for the second interactor i call

    
    TX_HANDLE gazeInteractor = TX_EMPTY_HANDLE;
    	TX_HANDLE gazeBehavior   = TX_EMPTY_HANDLE;
    	TX_GAZEPOINTDATAPARAMS params = { TX_GAZEPOINTDATAMODE_LIGHTLYFILTERED };
    	bool success;
    
    	success = txCreateGlobalInteractorSnapshot(hContext, InteractorId, &g_hGlobalInteractorSnapshot, &gazeInteractor) == TX_RESULT_OK;
    
    	success &= txCreateInteractorBehavior(gazeInteractor, &gazeBehavior, TX_INTERACTIONBEHAVIORTYPE_GAZEPOINTDATA) == TX_RESULT_OK;
    	success &= txSetGazePointDataBehaviorParams(gazeBehavior, &params) == TX_RESULT_OK;
    
    	txReleaseObject(&gazeBehavior);
    	txReleaseObject(&gazeInteractor);
    	
    	return success;
    

    But only the first initialized interactor will do it’s work…

    PS: the second initialization returns false

    #1347
    Laser Erich
    Participant

    ok – found a solution.

    when using just one TX_HANDLE INTERACTOR and assigning it to both TX_HANDLE BEHAVIORs I get an event containing both datastreams.

    #1876
    Edward Ryklin
    Participant

    Since upgrading to TobiiEyeXSdk-Cpp-0.32.384, this problem reemerges.

    Code used before the upgrade that use to work, but now only the first call to CreateIteractorBehavior will work (in this case gaze data) :

    BOOL BeethovenTobiiEyeX::InitializeGlobalInteractorSnapshot(TX_CONTEXTHANDLE hContext)
    {
    TX_HANDLE hInteractor = TX_EMPTY_HANDLE;
    TX_HANDLE hBehavior = TX_EMPTY_HANDLE;
    TX_GAZEPOINTDATAPARAMS params = { TX_GAZEPOINTDATAMODE_LIGHTLYFILTERED };
    BOOL success;

    success = txCreateGlobalInteractorSnapshot(
    hContext,
    InteractorId,
    &g_hGlobalInteractorSnapshot,
    &hInteractor) == TX_RESULT_OK;

    success &= txCreateInteractorBehavior(hInteractor, &hBehavior, TX_BEHAVIORTYPE_GAZEPOINTDATA) == TX_RESULT_OK;
    success &= txSetGazePointDataBehaviorParams(hBehavior, &params) == TX_RESULT_OK;

    success &= txCreateInteractorBehavior(hInteractor, &hBehavior, TX_BEHAVIORTYPE_EYEPOSITIONDATA) == TX_RESULT_OK;
    success &= txSetGazePointDataBehaviorParams(hBehavior, &params) == TX_RESULT_OK;

    txReleaseObject(&hBehavior);
    txReleaseObject(&hInteractor);
    return success;
    }

    Code after :

    BOOL BeethovenTobiiEyeX::InitializeGlobalInteractorSnapshot(TX_CONTEXTHANDLE hContext)
    {
    TX_HANDLE hInteractor = TX_EMPTY_HANDLE;

    TX_GAZEPOINTDATAPARAMS params = { TX_GAZEPOINTDATAMODE_UNFILTERED };
    BOOL success;

    success = txCreateGlobalInteractorSnapshot(
    hContext,
    InteractorId,
    &g_hGlobalInteractorSnapshot,
    &hInteractor) == TX_RESULT_OK;

    success &= txCreateGazePointDataBehavior(hInteractor, &params) == TX_RESULT_OK;

    txReleaseObject(&hInteractor);
    return success;
    }

    Note, that here the function
    txCreateInteractorBehavior

    has been replaced with
    txCreateGazePointDataBehavior

    and
    txSetGazePointDataBehaviorParams
    has been removed.

    there is no function “like” txCreateGazePointDataBehavior for EyePointData.

    #1877
    Edward Ryklin
    Participant

    In addition, since upgrading to TobiiEyeXSdk-Cpp-0.32.384

    The eye position coordinates are inverted, which requires we multiply by -1.

    The eye position is offset with screenWidth/2 and screenHeight/2

    Please follow up to confirm.

    #1880
    Anders
    Participant

    Hi Edward,

    I think the problem in your code snippet (“code before”) is that the hBehavior handle isn’t released between the calls to txCreateInteractorBehavior. If you add a txReleaseHandle in between, the code should still work. The EyeX API now validates that the handles are set to TX_EMPTY_HANDLE on input, and since the handle is set to a valid behavior by the first call the validation will fail.

    Note that you still have the choice to use the txCreateInteractorBehavior/txSetXyzBehaviorParams form, as you did in your “Code before” sample. You don’t have to use the shorthand form as shown in your “Code after” sample.

    Here is a code snippet demonstrating how to add multiple data streams. (Cut and paste into the MinimalGazeDataStreams sample if you want to try it.)

    BOOL InitializeGlobalInteractorSnapshot(TX_CONTEXTHANDLE hContext)
    {
    	TX_HANDLE hInteractor = TX_EMPTY_HANDLE;
    	TX_GAZEPOINTDATAPARAMS params = { TX_GAZEPOINTDATAMODE_LIGHTLYFILTERED };
    	TX_FIXATIONDATAPARAMS fixationDataParams = { TX_FIXATIONDATAMODE_SENSITIVE };
    	TX_HANDLE hBehaviorWithoutParameters = TX_EMPTY_HANDLE;
    	BOOL success;
    
    	success = txCreateGlobalInteractorSnapshot(
    		hContext,
    		InteractorId,
    		&g_hGlobalInteractorSnapshot,
    		&hInteractor) == TX_RESULT_OK;
    	success &= txCreateGazePointDataBehavior(hInteractor, &params) == TX_RESULT_OK;
    
    	// add a second behavior to the same interactor: fixation data
    	success &= txCreateFixationDataBehavior(hInteractor, &fixationDataParams) == TX_RESULT_OK;
    
    	// add a third behavior to the same interactor: eye position data.
    	// this one is a bit different because it doesn't take any parameters. 
    	// therefore we use the generic txCreateInteractorBehavior function (and remember to release the handle!)
    	success &= txCreateInteractorBehavior(hInteractor, &hBehaviorWithoutParameters, TX_BEHAVIORTYPE_EYEPOSITIONDATA) == TX_RESULT_OK;
    	txReleaseObject(&hBehaviorWithoutParameters);
    
    	txReleaseObject(&hInteractor);
    
    	return success;
    }
    

    As for the question regarding eye position coordinates: you are absolutely correct that the coordinate system used has its origin at the center of the screen. But what makes me puzzled is that it has been that way (in the EyeX API, not in the Gaze API!) for as long as I can remember.

    #1959
    zhangmeng
    Participant

    the right code is like this:

    BOOL InitializeGlobalInteractorSnapshot(TX_CONTEXTHANDLE hContext)
    {
        TX_HANDLE hInteractor = TX_EMPTY_HANDLE;
        TX_GAZEPOINTDATAPARAMS params = { TX_GAZEPOINTDATAMODE_LIGHTLYFILTERED };
        TX_FIXATIONDATAPARAMS fixationDataParams = { TX_FIXATIONDATAMODE_SENSITIVE };
        TX_HANDLE hBehaviorWithoutParameters = TX_EMPTY_HANDLE;
        BOOL success;
     
        success = txCreateGlobalInteractorSnapshot(
            hContext,
            InteractorId,
            &g_hGlobalInteractorSnapshot,
            &hInteractor) == TX_RESULT_OK;
        success &= txCreateGazePointDataBehavior(hInteractor, &params) == TX_RESULT_OK;
     
        // add a second behavior to the same interactor: fixation data
        success &= txCreateFixationDataBehavior(hInteractor, &fixationDataParams) == TX_RESULT_OK;
     
        // add a third behavior to the same interactor: eye position data.
        // this one is a bit different because it doesn't take any parameters.
        // therefore we use the generic txCreateInteractorBehavior function (and remember to release the handle!)
        success &= txCreateInteractorBehavior(hInteractor, &hBehaviorWithoutParameters, TX_BEHAVIORTYPE_EYEPOSITIONDATA) == TX_RESULT_OK;
        txReleaseObject(&hBehaviorWithoutParameters);
     
        txReleaseObject(&hInteractor);
        return success;
    }
    and get data, the code is:
    void OnGazeDataEvent(TX_HANDLE hGazeDataBehavior)
    {
    	//TX_GAZEPOINTDATAEVENTPARAMS eventParams;
    	TX_EYEPOSITIONDATAEVENTPARAMS eventParams;
    	//printf ("%d", txGetEyePositionDataEventParams(hGazeDataBehavior, &eventParams));
    	//printf ("%d", TX_RESULT_OK);//TX_RESULT_INVALIDBEHAVIORTYPE
    	//printf ("%d", TX_RESULT_INVALIDBEHAVIORTYPE);
    	if (txGetEyePositionDataEventParams(hGazeDataBehavior, &eventParams) == TX_RESULT_OK) {
    	//if (txGetGazePointDataEventParams(hGazeDataBehavior, &eventParams) == TX_RESULT_OK) {
    		printf("Gaze Data: timestamp %d ms\n", eventParams.HasLeftEyePosition);
    		//printf("Gaze Data: (%.1f, %.1f) timestamp %.0f ms\n", eventParams.X, eventParams.Y, eventParams.Timestamp);
    	} else {
    		printf("Failed to interpret gaze data event packet.\n");
    		printf ("Error code: %d.\n", txGetEyePositionDataEventParams(hGazeDataBehavior, &eventParams));
    	}
    }
    Next, there is a small detail you should not ignore:
    if (txGetEventBehavior(hEvent, &hBehavior, TX_BEHAVIORTYPE_EYEPOSITIONDATA) == TX_RESULT_OK) {
    		OnGazeDataEvent(hBehavior);
    		txReleaseObject(&hBehavior);
    	}

    That is all, So the eye data can be got successfully.

    #2129
    Edward Ryklin
    Participant

    After upgrading to Tobii EyeX 1.0.0 the RIGHT eye position is noticeably broken. Yes I also upgraded to SDK for C++ 1.1

    Furthermore, the code samples above are inadequate. There is some asynchronous problem that ensues. Again this was not an issue in earlier versions.

    This is a huge waste of my time. I don’t want to debug your product for you.

    #2132
    Robert [Tobii]
    Participant

    Hi Edward,

    I’m sure we can work out a solution for you. Can you please just be a bit more specific on what the problems are, i.e:
    1) In which way is the right eye position broken? Do you get any data at all or is the data just noisier than before?
    2) What kind of asynchronous problems have you experienced?
    3) When you are referring to “earlier versions” of Tobii SDKs, do you mean the Gaze SDK or Analytics SDK?

    #2135
    Edward Ryklin
    Participant

    This did not happen in earlier versions of the eyeX SDK. This has no bearing on the Gaze SDK for Rex, or Analytics SDK which doesn’t even work with the EyeX.

    Lets burn more time on this…

    when the HandleEvent function is called, and the event type is determined to be TX_BEHAVIORTYPE_EYEPOSITIONDATA, we were instructed to process it as follows:

    if (txGetEventBehavior(hEvent, &hBehavior, TX_BEHAVIORTYPE_EYEPOSITIONDATA) == TX_RESULT_OK) {
    OnPositionDataEvent(hBehavior);
    txReleaseObject(&hBehavior);
    }

    The OnPositionDataEvent function gets the eyeposition information by the following method:

    if (txGetEyePositionDataEventParams(hPositionDataBehavior, &eventParams) == TX_RESULT_OK) {

    }

    here, the eventParams.RightEyeX and eventParams.RightEyeY return invalid values, for no apparent reason.

    Specifically, they will be both set to a value such as -9.2559631349317831e+061

    While the LeftEyeX and LeftEyeY values will be set to acceptable values corresponding to the range of pixels found in my display.

    The EyeDetection Indicator widget shows both my eyes are detected properly.

    Regarding the asynchronous problem… I can’t provide you with exact details yet, however I can say this much. It is logical that for each gaze coordinate their is an eye position value. That would be necessary to render the location of the eyes and gaze simultaneously. It seems that the SDK is designed to deliver these parameters asynchronously, and therefore can not guarantee that there is an eye and gaze coordinate for each sample. In fact, I believe that the HandleEvent function can be called by an eye position event while it is still processing a gaze position event. That is likely to be the problem. This did not happen in earlier versions of the EyeX SDK.

    It is particularly frustrating and a huge time drain when SDK upgrades break existing functionality and force developers to reprogram previously working code for ostensibly no good reason! Please do not release SDK updates until you have tested and retested every single unit, and do not deprecate functions every time there is an update. I am neither interested in refactoring function names just because your developers thought of a better naming convention, nor of posting these rants online.

Viewing 15 posts - 1 through 15 (of 16 total)
  • You must be logged in to reply to this topic.