Eye tracking with Matlab (Psychtoolbox / Cogent)

Functions are available for eye tracker calibration and validation. The code is on Github. This package also includes a wrapper function (fullCalibrationRoutine) that takes you through both stages with a minimum of fuss.

These functions use serial port communication. For more advanced applications (e.g., gaze-contingent paradigms), you may wish to consider using Ethernet port communication instead. Please consult Johan Carlin if this is something you think you may need.

To get started, consider the simple example script eyetrackdemo.m, which is included in the repo. A high-level overview of what you need to achieve in your code is below:

Initialising the serial connection

The serial port needs to be set up. After this, we send text strings that the eye tracker PC interprets. These commands take the format "ET_X."

% find any lingering serial port connections - you can only have one connection at a time.
f = instrfind;
badind = strcmp(get(f,'Status'),'open');
if any(badind)
    fprintf('closing open serial port connection...\n');
    fclose(f(badind));
end

ET_serial = serial('COM1','BaudRate',115200,'Databits',8,'RequestToSend','off');
set(ET_serial,'timeout',0.1);
fopen(ET_serial);
warning('off','MATLAB:serial:fgetl:unsuccessfulRead');
% start recording data
fprintf(ET_serial,'ET_REC');

Calibration and validation using Psychtoolbox

In general, we first calibrate the eye tracker, ie, find the correspondence between the position of the pupil and the corneal reflex on the eye tracker camera sensor and horizontal and vertical pixel coordinates on the screen. We rely on SMI's calibration, but you could turn on recording before you calibrate and attempt an offline calibration with different algorithms if you prefer.

The validation routine runs through the calibration a second time, each time recording the deviation between the recorded eye position and the position of the target. Large deviations imply that the calibration didn't work as intended. The validation routine provides various performance metrics. Currently we don't have any good rule of thumbs regarding what sort of values count as 'good enough' - it would be hugely helpful if someone could record validation outputs for a number of subjects to provide an idea of what sort of quality is to be expected.

For standard requirements, just do

success = fullCalibrationRoutine(screen,ET_serial,'npoints',5,'randompointorder',1);

Where screen is an open Psychtoolbox window, ET_serial is the open serial port instance above. Many custom flags are possible. Here, we chose to do a five-point calibration with a random progression through the points.

Sending events

If you send ET_REM [x] to the eyetracker, [x] gets written as an event in the eyetracking log. This can then be used to identify your events in an analysis. Note that BeGaze can automatically match up your events with images, and for this to work the string you send must be the exact filename of the image you wish to associate the event with. So for instance, if your fixation cross image is fixation.png, sending 'ET_REM fixation.png' will then make it reasonably easy to overlay heatmaps etc over the fixation image in BeGaze.

% One way to send a trial string. You need to do this for each onset you are interested in, e.g., start of each trial.
trialname = 'mystimimage'; % Whatever your stimulus is.
fprintf(ET_serial,sprintf('ET_REM %s.png',trialname));

Finishing the recording, saving your data

Once your experiment has finished, you need to stop the eyetracking recording, and close the serial port connection. You can also use a remote command to save your data - setting this up is highly recommended, as the data otherwise gets overwritten if you forget to save manually before starting the next run!

% stop and save
fprintf(ET_serial,'ET_STP');
% appears under C:\Program Files\SMI\iView X\ on the eye track PC. Time
% stamp is a good idea because saving will fail if the filename already
% exists!
fprintf(ET_serial,...
    ['ET_SAV testdata_' datestr(now,'yyyymmdd_HHMM_SS') '.idf']);
% Close to flush buffer
fclose(ET_serial);

General notes

The most common errors you will see are related to the serial port being busy. This happens when a) you forgot to disable WinCAL before starting your experiment script, b) your script crashed and you are trying to restart without properly closing the serial port (see code snippet above that takes care of this automatically). When in doubt, restart Matlab and try again.