attachment:validateCalibration.m of EyeTrackingWithMatlab - Meg Wiki
location: attachment:validateCalibration.m of EyeTrackingWithMatlab

Attachment 'validateCalibration.m'

Download

   1 % Calibration routine for SMI IViewX eyetracker and Psychtoolbox,
   2 % using the serial port for communication. This function validates
   3 % a previous calibration. It's generally a good idea to pass the
   4 % exact same params struct here as you provided to calibrateEyeTracker.
   5 % NB, MeanDevXY is in deg visual angle, so is completely dependent on
   6 % you appropriately configuring IViewX settings to match your setup. The
   7 % other values are in pixels.
   8 % Currently only reports validation parameters for the left eye if tracking
   9 % binocular. As near as I can tell, this information is never transmitted,
  10 % so little can be done at this end.
  11 % Syntax:
  12 % [success,RMSdev,RMSdevdist,MeanDevXY] = validateCalibration(window,ET_serial,ET_params)
  13 % Inputs (all params are optional):
  14 % window - Psychtoolbox screen handle
  15 % ET_serial - Opened serial port object for scanner.
  16 % ET_params - struct with eye tracking parameters. All are optional.
  17 %   npoints - (13) calibration points. DO NOT change between calib and
  18 %       validation.
  19 % 	bgcolour - ([128 128 128]) background colour (RGB)
  20 % 	targcolour - ([255 255 255]) target colour (RGB)
  21 % 	targsize - (20) target height/width in pixels
  22 % 	acceptkey - ([spacebar]) key for forcing point acceptance
  23 % 	quitkey - ([escapekey]) key for aborting calibration
  24 % 		Use KbName('UnifyKeyNames') to get names for other keys
  25 % 13/4/2010 J Carlin
  26 function [ready,RMSdev, RMSdevdist, MeanDevXY] = validateCalibration(window,ET_serial,ET_params)
  27 
  28 % If no serial object entered, crash out
  29 if ~exist('ET_serial','var') || isempty(ET_serial)
  30     error('ET_serial must be defined! See calibrateEyeTracker')
  31 end
  32 
  33 % By default, calls time out in 10 SECONDS.
  34 % This is clearly unacceptably slow for our
  35 % purposes. Now 100 ms.
  36 set(ET_serial,'timeout',.1);
  37 % The downside is that Matlab spits out a lot of
  38 % warnings. Let's disable these...
  39 wstate=warning('off','MATLAB:serial:fgetl:unsuccessfulRead');
  40 
  41 % If you don't know what you want, we will fill this in with
  42 % defaults.
  43 if ~exist('ET_params','var')
  44 	ET_params = struct;
  45 end
  46 
  47 % Screen settings
  48 sc = Screen('Resolution',window);
  49 schw = [sc.width sc.height];
  50 
  51 KbName('UnifyKeyNames');
  52 
  53 % These are the default settings
  54 default_params = struct(...
  55 	'bgcolour',[128 128 128],...
  56 	'targcolour',[255 255 255],...
  57 	'targsize',20, ...
  58 	'npoints',13, ...
  59 	'acceptkey',KbName('space'), ...
  60 	'quitkey',KbName('escape') ...
  61 	);
  62 
  63 % Now put in defaults for whatever was left undefined
  64 fns = fieldnames(default_params);
  65 for fn = fns'
  66 	if ~isfield(ET_params,fn{1})
  67 		ET_params.(fn{1}) = default_params.(fn{1});
  68 	end
  69 end
  70 
  71 % Draw background
  72 Screen(window,'FillRect',ET_params.bgcolour);
  73 
  74 % Display settings for targets
  75 % Make a cross - studiously avoiding alpha blending here to
  76 % maximise compatibility (but you will need to im processing toolbox)
  77 % Settings
  78 cross_orgsize = 100;
  79 cross_linewidth = .05;
  80 % Build cross
  81 cs = round((cross_orgsize / 2) - (cross_orgsize * cross_linewidth));
  82 ce = round((cross_orgsize / 2) + (cross_orgsize * cross_linewidth));
  83 cr = zeros(cross_orgsize);
  84 cr(:,cs:ce) = 1;
  85 cr(cs:ce,:) = 1;
  86 % Resize - Since square, no point to bicubic interpolation
  87 cr_rs = imresize(cr,[ET_params.targsize ET_params.targsize],'nearest');
  88 % Make target uint8, colour
  89 rgb_t = ET_params.targcolour;
  90 cros = uint8(cat(3,cr_rs*rgb_t(1),cr_rs*rgb_t(2),cr_rs*rgb_t(3)));
  91 % Make an appropriately-coloured background
  92 rgb = ET_params.bgcolour;
  93 bg = uint8(ones(ET_params.targsize));
  94 bg_rgb =cat(3,bg*rgb(1),bg*rgb(2),bg*rgb(3));
  95 % Put background and target together
  96 target = bg_rgb;
  97 target(find(cros)) = cros(find(cros));
  98 % Draw texture
  99 targetbuf = Screen('MakeTexture',window,target);
 100 % Set up basic rect
 101 targetrect = [0 0 size(target,1) size(target,2)];
 102 
 103 % Start validation
 104 fprintf(ET_serial,sprintf('ET_VLS'));
 105 ready = 0;
 106 readyonce = 0; % Extra check to catch second eye in bino mode
 107 ntries = 0;
 108 points = zeros(ET_params.npoints,2);
 109 
 110 % Initialise output vars for graceful errors
 111 RMSdev = [];
 112 RMSdevdist = [];
 113 MeanDevXY = [];
 114 
 115 rc = 0;
 116 while ~ready
 117 	ntries = ntries+1;
 118 
 119 	% If no connection with serial, return anyway
 120 	if ntries > 500
 121 		fprintf('Serial port communication failure!\n')
 122 		break
 123 	end
 124 
 125 	% Check for manual attempts to move things along
 126 	[keyisdown, secs, keyCode] = KbCheck;
 127 	if keyisdown
 128 		k = find(keyCode);
 129 		k = k(1);
 130 		% Force acceptance of current point
 131 		if k == ET_params.acceptkey
 132 			fprintf('Accepting point...\n')
 133             %WaitSecs(.2); % Time to let go of key...
 134             % Now stop execution until the key is released
 135             while KbCheck
 136                 WaitSecs(.01);
 137             end
 138             fprintf(ET_serial,'ET_ACC');
 139 		% Give up on calibration
 140 		elseif k == ET_params.quitkey
 141 			fprintf('Calibration attempt aborted!\n')
 142 			fprintf(ET_serial,'ET_BRK');
 143 			break
 144 		end
 145     end
 146 
 147     % Ensure a second run through after receiving the first
 148     % ET_VLS return, so that we catch the second eye too.
 149     if readyonce
 150         ready = 1;
 151     end
 152 
 153 	% Check if the eye tracker has something to say
 154     response = fgetl(ET_serial);
 155     
 156 	% What might the eye tracker have to say?
 157 	if ~isempty(response)
 158 		% Save each response - mainly for debugging
 159 		rc = rc+1;
 160         resplog{rc} = response;
 161 		% Split by spaces
 162 		command_etc = strread(regexprep(response,' ',' '),'%s');
 163 		command = command_etc{1};
 164 
 165 		%%% What we do next depends on the command we got:
 166 		% Calibration point change
 167         if strcmp(command,'ET_CHG')
 168             % Coordinates for point
 169             xy = points(str2num(command_etc{2}),:);
 170 			% Rect for point
 171 			pointrect = CenterRectOnPoint(targetrect,xy(1),xy(2));
 172 			% Draw into rect
 173 			Screen('DrawTexture',window,targetbuf,[],pointrect);
 174             Screen(window,'Flip');
 175             % Reset timeout counter
 176             ntries = 0;
 177 
 178             % Calibation point definition
 179         elseif strcmp(command,'ET_PNT')
 180             points(str2num(command_etc{2}),:) = ...
 181 				[str2num(command_etc{3}) str2num(command_etc{4})];
 182 
 183 		% Screen size verification
 184 		%elseif strcmp(command,'ET_CSZ')
 185 		% Actually, we don't want calibration area
 186 			% to match screen size.
 187 			% So arguments are X and Y size
 188 			%sc = Screen('Resolution',window);
 189 			%if str2num(command_etc{2}) ~= sc.width
 190 				%fprintf('Calibration failed - Screen width mismatch\n')
 191 				%break
 192 			%elseif str2num(command_etc{3}) ~= sc.height
 193 				%fprintf('Calibration failed - Screen height mismatch\n')
 194 				%break
 195 			%end
 196        
 197         % Validation finished
 198         % The twist here is that ET_VLS returns twice if
 199         % in binocular mode... So need to go through a last
 200         % check after finishing this.
 201         elseif strcmp(command,'ET_VLS')
 202             % Command_etc should now contain various numbers
 203             values = str2num(char(command_etc(3:5)))';
 204             % SMI for some reason insists on including a degree
 205             % symbol for the last 2, which complicates things...
 206             values(end+1) = str2num(command_etc{6}(1:end-1));
 207             values(end+1) = str2num(command_etc{7}(1:end-1));
 208             
 209             if ~readyonce
 210                 RMSdev = values(1:2);
 211                 RMSdevdist = values(3);
 212                 MeanDevXY = values(4:5);
 213             else % Right eye
 214                 RMSdev(2,:) = values(1:2);
 215                 RMSdevdist(2,:) = values(3);
 216                 MeanDevXY(2,:) = values(4:5);
 217             end            
 218             readyonce = 1;
 219             
 220         
 221         % Various commands we don't care about
 222         elseif strcmp(command,'ET_REC') || ...
 223                 strcmp(command,'ET_CLR') || ...
 224                 strcmp(command,'ET_CAL') || ...
 225                 strcmp(command,'ET_CSZ') || ...
 226                 strcmp(command,'ET_ACC') || ...
 227                 strcmp(command,'ET_CPA') || ...
 228                 strcmp(command,'ET_FIN') || ...
 229                 strcmp(command,'ET_LEV')
 230             continue
 231 
 232 		% Catch all
 233 		else
 234 			fprintf(sprintf(['Validation failed - received unrecognised '...
 235 				'input: %s\n'],response));
 236             fprintf(ET_serial,'ET_BRK');
 237 			break % DEBUG
 238 		end % Resp interpretation
 239 	end % Resp check
 240 end % While
 241 
 242 % Clear the target texture from memory
 243 Screen('Close',targetbuf);
 244 % Return warning state to whatever it started as
 245 warning(wstate.state,wstate.identifier);

Attached Files

To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.
  • [get | view] (2010-06-10 15:38:10, 14.5 KB) [[attachment:ET_tools_10.zip]]
  • [get | view] (2010-06-10 15:40:21, 9.5 KB) [[attachment:calibrateEyeTracker.m]]
  • [get | view] (2010-06-10 15:40:08, 6.2 KB) [[attachment:doDriftCorrection.m]]
  • [get | view] (2010-06-10 15:40:31, 8.3 KB) [[attachment:validateCalibration.m]]
 All files | Selected Files: delete move to page copy to page

You are not allowed to attach a file to this page.