Home Forums Software Development Getting the Pupillary Distance Reply To: Getting the Pupillary Distance

#11849
Chaim Dryzun
Participant

Hi,

I downloaded the Tobbi Stream Engine API and wrote a small C++ code.
I succeeded getting the normalized eye position (tobii_eye_position_normalized_t) and the track box dimensions (tobii_track_box_t).
I am trying to un-normalize the eye position and calculate the PD (pupillary distance).
I get a number which seems in the right order, but it is very sensitive to the distance from the Tobii eye tracker (It becomes larger as I get closer to the eye tracker). I guess I need to perform some more distance normalization.

Can you please help me understand which part am I missing?

Here is my C++ code:

#include <tobii/tobii.h>
#include <tobii/tobii_streams.h>
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <windows.h>
#include <assert.h>

tobii_track_box_t track_box;

void eye_position_callback(tobii_eye_position_normalized_t const* eye_pos, void* user_data)
{
if ((eye_pos->left_validity == TOBII_VALIDITY_VALID) && (eye_pos->right_validity == TOBII_VALIDITY_VALID))
{
double N_X_L, N_Y_L, N_Z_L, N_X_R, N_Y_R, N_Z_R, U_X_L, U_Y_L, U_Z_L, U_X_R, U_Y_R, U_Z_R;
N_X_L = eye_pos->left_xyz[0];
N_Y_L = eye_pos->left_xyz[1];
N_Z_L = eye_pos->left_xyz[2];

N_X_R = eye_pos->right_xyz[0];
N_Y_R = eye_pos->right_xyz[1];
N_Z_R = eye_pos->right_xyz[2];

U_X_L = ((track_box.back_lower_left_xyz[0] – track_box.front_upper_right_xyz[0]) * N_X_L);
U_Y_L = ((track_box.back_lower_left_xyz[1] – track_box.front_upper_right_xyz[1]) * N_Y_L);
U_Z_L = ((track_box.back_upper_right_xyz[2] – track_box.front_lower_left_xyz[2]) * N_Z_L);

U_X_R = ((track_box.back_lower_left_xyz[0] – track_box.front_upper_right_xyz[0]) * N_X_R);
U_Y_R = ((track_box.back_lower_left_xyz[1] – track_box.front_upper_right_xyz[1]) * N_Y_R);
U_Z_R = ((track_box.back_lower_left_xyz[2] – track_box.front_upper_right_xyz[2]) * N_Z_R);

double PD = sqrt(pow(U_X_R – U_X_L, 2.0) + pow(U_Y_R – U_Y_L, 2.0) + pow(U_Z_R – U_Z_L, 2.0));

printf(“PD : %f\r”, PD);
}
}

static void url_receiver(char const* url, void* user_data)
{
char* buffer = (char*)user_data;
if (*buffer != ‘\0’) return; // only keep first value

if (strlen(url) < 256)
strcpy(buffer, url);
}

int main()
{
tobii_api_t* api;
tobii_error_t error = tobii_api_create(&api, NULL, NULL);
assert(error == TOBII_ERROR_NO_ERROR);

char url[256] = { 0 };
error = tobii_enumerate_local_device_urls(api, url_receiver, url);
assert(error == TOBII_ERROR_NO_ERROR && *url != ‘\0’);

tobii_device_t* device;
error = tobii_device_create(api, url, &device);
assert(error == TOBII_ERROR_NO_ERROR);

error = tobii_eye_position_normalized_subscribe(device, eye_position_callback, 0);
assert(error == TOBII_ERROR_NO_ERROR);

error = tobii_get_track_box(device, &track_box);
assert(error == TOBII_ERROR_NO_ERROR);

// print just a couple of values of the track box data
printf(“Front upper left is (%f, %f, %f)\n”,
track_box.front_upper_left_xyz[0],
track_box.front_upper_left_xyz[1],
track_box.front_upper_left_xyz[2]);
printf(“Front upper right is (%f, %f, %f)\n”,
track_box.front_upper_right_xyz[0],
track_box.front_upper_right_xyz[1],
track_box.front_upper_right_xyz[2]);
printf(“Front lower left is (%f, %f, %f)\n”,
track_box.front_lower_left_xyz[0],
track_box.front_lower_left_xyz[1],
track_box.front_lower_left_xyz[2]);
printf(“Front lower right is (%f, %f, %f)\n”,
track_box.front_lower_right_xyz[0],
track_box.front_lower_right_xyz[1],
track_box.front_lower_right_xyz[2]);

printf(“Back upper left is (%f, %f, %f)\n”,
track_box.back_upper_left_xyz[0],
track_box.back_upper_left_xyz[1],
track_box.back_upper_left_xyz[2]);
printf(“Back upper right is (%f, %f, %f)\n”,
track_box.back_upper_right_xyz[0],
track_box.back_upper_right_xyz[1],
track_box.back_upper_right_xyz[2]);
printf(“Back lower left is (%f, %f, %f)\n”,
track_box.back_lower_left_xyz[0],
track_box.back_lower_left_xyz[1],
track_box.back_lower_left_xyz[2]);
printf(“Back lower right is (%f, %f, %f)\n”,
track_box.back_lower_right_xyz[0],
track_box.back_lower_right_xyz[1],
track_box.back_lower_right_xyz[2]);

printf(“\n”);

for (;;)
{
error = tobii_wait_for_callbacks(NULL, 1, &device);
assert(error == TOBII_ERROR_NO_ERROR || error == TOBII_ERROR_TIMED_OUT);

error = tobii_device_process_callbacks(device);
assert(error == TOBII_ERROR_NO_ERROR);

if (GetKeyState(VK_ESCAPE) & 0x8000)
break;
}

error = tobii_eye_position_normalized_unsubscribe(device);
assert(error == TOBII_ERROR_NO_ERROR);

error = tobii_device_destroy(device);
assert(error == TOBII_ERROR_NO_ERROR);

error = tobii_api_destroy(api);
assert(error == TOBII_ERROR_NO_ERROR);
return 0;
}

Thanks,
Chaim