Matlab/Octave - Step-by-step guide

This is a more detailed version of the four step guide to a functional application that's described on the Getting started page. This guide is aimed at the first-time user of Tobii Pro SDK, who perhaps also is pretty new to programming in Matlab/Octave.

Step-by-step guide to your first eye tracking application

The following text is meant to guide you - a new user of the Tobii Pro SDK (and maybe also new to eye tracking and programming in Matlab/Octave) - to writing your first eye tracking study application!
Prerequisites: Matlab and/or Octave and Pro SDK should be installed on your computer (see installation section on the Getting started page), and there should be an eye tracker connected, either via USB or network.

Step 0 : Preparations!

This guide will not provide a complete runnable script that you can just copy-paste into your editor and run. Instead we try to describe the concepts and reasons behind the code, and you can choose to use (or copy-paste...) these snippets either in your existing Matlab/Octave code, or in a completely new file. However, if you want the simplest of scenarios, you can copy-paste every line of code described here, in the order they appear, into a new file, and it should run nicely.

Before you can start using Pro SDK functions in your Matlab or Octave application, you need to make sure the Tobii Pro SDK is available in your environment. This can be done by running your code in the same folder where you extracted the Tobii Pro SDK package, or alternatively, and as better way, you should add the path of the folder containing the Tobii Pro SDK to the Matlab or Octave environment.

addpath(genpath('path'))

Step 1 : Find the eye tracker!

Now you're ready to start working with Tobii Pro eye tracking!
In the EyeTrackingOperations class there's a function for searching for eye trackers: find_all_eyetrackers().
So start by creating an instance of the EyeTrackingOperations class:

tobii = EyeTrackingOperations();

This function will look for both eye trackers connected directly to your computer via usb or ethernet cable, as well as eye trackers connected to the same network as your computer. To search for eye trackers simply call find_all_eyetrackers() and assign the output to a new variable:
found_eyetrackers = tobii.find_all_eyetrackers()

The return value of find_all_eyetrackers() is an array of EyeTracker objects. You can access the meta data of the (first) eye tracker, and print it, like this:
my_eyetracker = found_eyetrackers(1)
disp(["Address: ", my_eyetracker.Address])
disp(["Model: ", my_eyetracker.Model])
disp(["Name (It's OK if this is empty): ", my_eyetracker.Name])
disp(["Serial number: ", my_eyetracker.SerialNumber])

Step 2 : Calibrate the eye tracker

Let's be blunt, calibration is a bit complicated. So, if this is indeed your first eye tracking application, we recommend that you either skip calibration (all Tobii Pro eye trackers are pre-configured with a default calibration, so you will get gaze data even if you skip calibration), or use Tobii Pro Eye Tracker Manager to perform the calibration. You can calibrate the eye tracker with Tobii Pro Eye Tracker Manager before running your application, or call Tobii Pro Eye Tracker Manager with a command line parameter (from within your code) that launches directly into calibration mode. Read more here.

If you really want to dig into how to create your own calibration procedure, read the calibration part of the Common concepts area of this site, and check out the calibration code example in the SDK reference guide.

Step 3 : Get gaze data!

The eye tracker outputs a gaze data sample at a regular interval (30, 60, 120, 300, etc, times per seconds, depending on model). To get hold of this data, you tell the Tobii Pro SDK that you want to start collecting gaze data, using the method from the eye tracker object previously created.

 my_eyetracker.get_gaze_data();
The first call to this method simply starts the data callection and the subsequent calls return the data collected in between each call. This will start to collect gaze data in the background, so if you want to collect data for a second simply use:
 pause(1);
Now we are able to fetch the data collected during that time:
 gaze_data = my_eyetracker.get_gaze_data();
The gaze_data variable will be an array of objects of the GazeData class. We can access the latest data point collected:
 latest_gaze_data = gaze_data(end);
Now you can access the data as the following example suggests:
fprintf('SystemRequestTimeStamp: %d\n',latest_gaze_data.SystemTimeStamp);
fprintf('DeviceTimeStamp: %d\n',latest_gaze_data.DeviceTimeStamp);

disp('Left Eye');

fprintf('GazePoint.OnDisplayArea: %.2f %.2f\n',latest_gaze_data.LeftEye.GazePoint.OnDisplayArea);
fprintf('GazePoint.InUserCoordinateSystem: %.2f %.2f %.2f\n',latest_gaze_data.LeftEye.GazePoint.InUserCoordinateSystem);
fprintf('GazePoint.Validity: %s\n',char(latest_gaze_data.LeftEye.GazePoint.Validity));

fprintf('GazeOrigin.InUserCoordinateSystem: %.2f %.2f %.2f\n',latest_gaze_data.LeftEye.GazeOrigin.InUserCoordinateSystem);
fprintf('GazeOrigin.InTrackBoxCoordinateSystem: %.2f %.2f %.2f\n',latest_gaze_data.LeftEye.GazeOrigin.InTrackBoxCoordinateSystem);
fprintf('GazeOrigin.Validity: %s\n',char(latest_gaze_data.LeftEye.GazeOrigin.Validity));

fprintf('Pupil.Diameter: %.2f\n',latest_gaze_data.LeftEye.Pupil.Diameter);
fprintf('Pupil.Validity: %s\n',char(latest_gaze_data.LeftEye.Pupil.Validity));

disp('Right Eye');

fprintf('GazePoint.OnDisplayArea: %.2f %.2f\n',latest_gaze_data.RightEye.GazePoint.OnDisplayArea);
fprintf('GazePoint.InUserCoordinateSystem: %.2f %.2f %.2f\n',latest_gaze_data.RightEye.GazePoint.InUserCoordinateSystem);
fprintf('GazePoint.Validity: %s\n',char(latest_gaze_data.RightEye.GazePoint.Validity));

fprintf('GazeOrigin.InUserCoordinateSystem: %.2f %.2f %.2f\n',latest_gaze_data.RightEye.GazeOrigin.InUserCoordinateSystem);
fprintf('GazeOrigin.InTrackBoxCoordinateSystem: %.2f %.2f %.2f\n',latest_gaze_data.RightEye.GazeOrigin.InTrackBoxCoordinateSystem);
fprintf('GazeOrigin.Validity: %s\n',char(latest_gaze_data.RightEye.GazeOrigin.Validity));

fprintf('Pupil.Diameter: %.2f\n',latest_gaze_data.RightEye.Pupil.Diameter);
fprintf('Pupil.Validity: %s\n',char(latest_gaze_data.RightEye.Pupil.Validity));

Step 4 : Wrapping up!

Now that we have collected the gaze data that we want, we should let the eye tracker (and SDK) know that we're done. You do this by stopping collection of gaze data:

my_eyetracker.stop_gaze_data()
And that's all folks!