コード例 #1
0
// ######################################################################
Point2D<int> EyeTrackerEyeLink::getFixationPos() const
{
#ifndef HAVE_EYELINK
  LFATAL("Proprietary EyeLink developer API not installed");
	return Point2D<int>(-1,-1);
#else
	int i, x, y;				

	while (1) { // using while loop to consume the eye data queue 
    i = eyelink_get_next_data(NULL);   // check for new data item
		if (i == FIXUPDATE) {
    	eyelink_get_float_data(&evt);
			x = (int)evt.fe.gavx;
			y = (int)evt.fe.gavy;
     	//LINFO("Eyelink Time (FIXUPDATE) : %i (%i, %i)\n", (int)evt.fe.time, x, y);
			break;
		}
	}

	return Point2D<int>(x, y);
#endif 
}
コード例 #2
0
PsychError EyelinkGetNextDataType(void)
{
   int type = 0;

   //all sub functions should have these two lines
   PsychPushHelp(useString, synopsisString, seeAlsoString);
   if(PsychIsGiveHelp()){PsychGiveHelp();return(PsychError_none);};

   //check to see if the user supplied superfluous arguments
   PsychErrorExit(PsychCapNumInputArgs(0));
   PsychErrorExit(PsychRequireNumInputArgs(0));
   PsychErrorExit(PsychCapNumOutputArgs(1));

	// Verify eyelink is up and running
	EyelinkSystemIsConnected();
	EyelinkSystemIsInitialized();

   type = eyelink_get_next_data(NULL);

   PsychCopyOutDoubleArg(1, TRUE,  type);
   
   return(PsychError_none);
}
コード例 #3
0
int gaze_control_trial(UINT32 time_limit)
{
	UINT32 trial_start;		/* trial start time (for timeout) */
	UINT32 drawing_time;	/* retrace-to-draw delay*/
	int button;				/* the button pressed (0 if timeout) */
	int error;				/* trial result code*/

	ALLF_DATA evt;			/* buffer to hold sample and event data*/
	int eye_used = -1;		/* indicates which eye's data to display*/
	int i;

	SDL_Surface *gbm;			/* The bitmap containing the stimulus display*/

	   /* This supplies the title at the bottom of the eyetracker display */
	eyecmd_printf("record_status_message 'GAZE CONTROL TRIAL' ");

	/*	
	Always send a TRIALID message before starting to record. 
	It should contain trial condition data required for analysis.
	*/
	eyemsg_printf("TRIALID CONTROL");

  /* TRIAL_VAR_DATA message is recorded for EyeLink Data Viewer analysis
	It specifies the list of trial variables value for the trial 
	This must be specified within the scope of an individual trial (i.e., after 
	"TRIALID" and before "TRIAL_RESULT") 
	*/
	eyemsg_printf("!V TRIAL_VAR_DATA GAZECTRL");
	/* 
	IMGLOAD command is recorded for EyeLink Data Viewer analysis
	It displays a default image on the overlay mode of the trial viewer screen. 
	Writes the image filename + path info
     */
	eyemsg_printf("!V IMGLOAD FILL images/grid.png");	

	/* 
	IAREA command is recorded for EyeLink Data Viewer analysis
	It creates a set of interest areas by reading the segment files
	Writes segmentation filename + path info
	*/
	eyemsg_printf("!V IAREA FILE segments/grid.ias"); 

	/* Before recording, we place reference graphics on the EyeLink display*/
	set_offline_mode();			/* Must be offline to draw to EyeLink screen*/
	gbm = draw_grid_to_bitmap_segment("grid.ias", "segments", 1);;/* Draw bitmap and EyeLink reference graphics*/
	segment_source = gbm;

	/* 
		Save bitmap and transfer to the tracker pc.
		Since it takes a long to save the bitmap to the file, the 
		value of sv_options should be set as SV_NOREPLACE to save time
	*/

	bitmap_save_and_backdrop(gbm, 0, 0, 0, 0, "grid.png", "images", SV_NOREPLACE,
				  0, 0, (UINT16)(BX_MAXCONTRAST|((eyelink_get_tracker_version(NULL)>=2)?0:BX_GRAYSCALE)));

	   /* DO PRE-TRIAL DRIFT CORRECTION */
	   /* We repeat if ESC key pressed to do setup. */
	while(1)
	{              /* Check link often so we can exit if tracker stopped*/
	  if(!eyelink_is_connected()) return ABORT_EXPT;
	   /* We let do_drift_correct() draw target in this example*/
	   /* 3rd argument would be 0 if we already drew the display*/
	  error = do_drift_correct((INT16)(SCRWIDTH/2), (INT16)(SCRHEIGHT/2), 1, 1);
		   /* repeat if ESC was pressed to access Setup menu */
	  if(error!=27) break;
	}

	clear_full_screen_window(target_background_color);  /* make sure display is blank*/

		/* Configure EyeLink to send fixation updates every 50 msec*/
	eyecmd_printf("link_event_filter = LEFT,RIGHT,FIXUPDATE");
	eyecmd_printf("fixation_update_interval = 50");
	eyecmd_printf("fixation_update_accumulate = 50");

	init_regions();	/* Initialize regions for this display*/

	/* 
		Start data recording to EDF file, BEFORE DISPLAYING STIMULUS 
		You should always start recording 50-100 msec before required
		otherwise you may lose a few msec of data 
	*/
	error = start_recording(1,1,0,1);   /* send events only through link*/
	if(error != 0)           /* ERROR: couldn't start recording*/
	{
	  SDL_FreeSurface(gbm);   /* Be sure to delete bitmap before exiting!*/
	  return error;        /* Return the error code*/
	}
							  /* record for 100 msec before displaying stimulus */
	begin_realtime_mode(100);   /* Windows 2000/XP: no interruptions from now on*/

	/* 
		DISPLAY OUR IMAGE TO SUBJECT  by copying bitmap to display
		Because of faster drawing speeds and good refresh locking,
		we now place the stimulus onset message just after display refresh 
		and before drawing the stimulus.  This is accurate and will allow 
		drawing a new stimulus each display refresh.
	 
		However, we do NOT send the message after the retrace--this may take too long
		instead, we add a number to the message that represents the delay 
		from the event to the message in msec
	*/


	/* COPY BITMAP to display*/
	SDL_BlitSurface(gbm, NULL, window,NULL);
	Flip(window);
	drawing_time = current_msec();                   /* time of retrace*/
	trial_start = drawing_time;
	SDL_BlitSurface(gbm, NULL, window,NULL);
	



	/* delay from retrace (time to draw)*/
	drawing_time = current_msec()-drawing_time;    
	/* message for RT recording in analysis */
	eyemsg_printf("%d DISPLAY ON", drawing_time);
	/* message marks zero-plot time for EDFVIEW */
	eyemsg_printf("SYNCTIME %d", drawing_time);	 

	

	/* Print a title for the trial (for demo only)*/
	get_new_font("Times Roman", 24, 1);     
	graphic_printf(window,target_foreground_color, NONE, SCRWIDTH/2, 24, "Gaze Control Trial");
	

	if(!eyelink_wait_for_block_start(100, 0, 1))  /* wait for link event data*/
	{
	  end_trial();
	  alert_printf("ERROR: No link events received!");
	  return TRIAL_ERROR;
	}
	eye_used = eyelink_eye_available(); /* determine which eye(s) are available*/ 
	switch(eye_used)		      /* select eye, add annotation to EDF file	*/
	{			
	  case RIGHT_EYE:
		eyemsg_printf("EYE_USED 1 RIGHT");
		break;
	  case BINOCULAR:           /* both eye's data present: use left eye only*/
		eye_used = LEFT_EYE;
	  case LEFT_EYE:
		eyemsg_printf("EYE_USED 0 LEFT");
		break;
	}
								 
	/* Now get ready for trial loop*/
	eyelink_flush_keybuttons(0);   /* reset keys and buttons from tracker */

	/* 
		we don't use getkey() especially in a time-critical trial
		as Windows may interrupt us and cause an unpredicatable delay
		so we would use buttons or tracker keys only  
		Trial loop: till timeout or response -- added code for processing
		FIXUPDATE events
	*/
	while(1) 
	{ 
		/* First, check if recording aborted */
	  if((error=check_recording())!=0) return error;  
								 
	  /* Check if trial time limit expired*/
	  if(current_time() > trial_start+time_limit)
		{
			eyemsg_printf("TIMEOUT");    /* message to log the timeout */
			end_trial();                 /* local function to stop recording*/
			button = 0;                  /* trial result message is 0 if timeout */
			break;                       /* exit trial loop*/
		}

	  if(break_pressed())     /* check for program termination or ALT-F4 or CTRL-C keys*/
		{
			end_trial();         /* local function to stop recording*/
			return ABORT_EXPT;   /* return this code to terminate experiment*/
		}

	  /* check for local ESC key to abort trial (useful in debugging)   */
	  if(escape_pressed())    
		 {
			end_trial();         /* local function to stop recording*/
			return SKIP_TRIAL;   /* return this code if trial terminated*/
		 }

		/* BUTTON RESPONSE TEST */
		/* Check for eye-tracker buttons pressed
		/* This is the preferred way to get response data or end trials	*/
	  button = eyelink_last_button_press(NULL);
	  if(button!=0)       /* button number, or 0 if none pressed*/
		{
		  /* message to log the button press*/
			eyemsg_printf("ENDBUTTON %d", button);  
			/* local function to stop recording*/
			end_trial();                            
			break; /* exit trial loop*/
		}

		/* GET FIXUPDATE EVENTS, PROCESS*/

		i = eyelink_get_next_data(NULL);    /* Check for data from link*/
		if(i == FIXUPDATE)	  /* only process FIXUPDATE events*/
		{
			/* get a copy of the FIXUPDATE event */
			eyelink_get_float_data(&evt);  
			/* only process if it's from the desired eye?*/
			if(evt.fe.eye == eye_used)	   
			{   
				/* get average position and duration of the update */
				process_fixupdate((int)(evt.fe.gavx), (int)(evt.fe.gavy),/* Process event */
	       			 evt.fe.entime-evt.fe.sttime);
			}
		}
	}/* end of loop*/
	/* report response result: 0=timeout, else button number*/
	eyemsg_printf("TRIAL_RESULT %d", button);
		/* Call this at the end of the trial, to handle special conditions*/
	SDL_FreeSurface(gbm);
	segment_source = NULL;
	return check_record_exit();
}
コード例 #4
0
bool Eyelink::update() {
    MWTime inputtime;
    
    boost::mutex::scoped_lock lock(EyelinkDriverLock);
	if(eyelink_is_connected())	{
		while(eyelink_get_next_data(NULL)) {
			if(eyelink_in_data_block(1,0)) { //only if data contains samples
				eyelink_get_float_data(&evt);
                
                inputtime = this->clock->getCurrentTimeUS();
                
                // occasionally, send the current time together with the sample time back to the tracker (and log it there)
                if ( ack_msg_counter++ % 512 == 0 )
                    eyemsg_printf((char*)"SAMPLE %ld received %lld",(long)evt.time,inputtime);
				
                // now update all the variables
				if (e_time != NULL) e_time -> setValue( (long)evt.time ,inputtime);
				
				if( evt.gx[RIGHT_EYE] != MISSING_DATA &&
                   evt.gy[RIGHT_EYE] != MISSING_DATA &&
                   evt.gx[LEFT_EYE] != MISSING_DATA &&
                   evt.gy[LEFT_EYE] != MISSING_DATA &&
                   (e_x != NULL || e_y != NULL || e_z != NULL) ) {
					
					//p4321z = 1; 
					
					p43x = evt.gx[LEFT_EYE]/e_dist + 1;
					p43y = evt.gy[LEFT_EYE]/e_dist;
					
					p21x = evt.gx[RIGHT_EYE]/e_dist - 2;
					p21y = evt.gy[RIGHT_EYE]/e_dist;
					
					d4321 = p43x * p21x + p43y * p21y + 1;
					d4343 = p43x * p43x + p43y * p43y + 1;
					d2121 = p21x * p21x + p21y * p21y + 1;
					
					denom = d2121 * d4343 - d4321 * d4321;
					
					if (abs(denom) > 1e-6) { // should always be true when e_dist is really tracking range
						
						numer = p43x * d4321 - p21x * d4343;
                        
						mua = numer / denom;
						mub = (p43x + d4321 * mua) / d4343;
                        
						pax = 1 + mua * p21x;
						pay = mua * p21y;
						paz = -1 + mua; //-p4321z + mua * p4321z;
						pbx = mub * p43x;
						pby = mub * p43y;
						pbz = -1 + mub; //-p4321z + mub * p4321z;
                        
						if (e_x != NULL) e_x -> setValue(pax + 0.5*(pbx-pax),inputtime);
						if (e_y != NULL) e_y -> setValue(pay + 0.5*(pby-pay),inputtime);
						if (e_z != NULL) e_z -> setValue(paz + 0.5*(pbz-paz),inputtime);
					}
				}
				else {
					if (e_x != NULL && e_x->getValue().getFloat() != MISSING_DATA)
						e_x -> setValue((float)MISSING_DATA,inputtime);
					if (e_y != NULL && e_y->getValue().getFloat() != MISSING_DATA)
						e_y -> setValue((float)MISSING_DATA,inputtime);
					if (e_z != NULL && e_z->getValue().getFloat() != MISSING_DATA)
						e_z -> setValue((float)MISSING_DATA,inputtime);
				}
				
				if( evt.gx[RIGHT_EYE] != MISSING_DATA &&
                   evt.gy[RIGHT_EYE] != MISSING_DATA ){
					if (e_rx != NULL) e_rx -> setValue( evt.gx[RIGHT_EYE] ,inputtime);
					if (e_ry != NULL) e_ry -> setValue( evt.gy[RIGHT_EYE] ,inputtime);
				}
				else {
					if (e_rx != NULL && e_rx->getValue().getFloat() != MISSING_DATA)
						e_rx -> setValue((float)MISSING_DATA,inputtime);
					if (e_ry != NULL && e_ry->getValue().getFloat() != MISSING_DATA)
						e_ry -> setValue((float)MISSING_DATA,inputtime);
				}
				
				if( evt.gx[LEFT_EYE] != MISSING_DATA &&
                   evt.gy[LEFT_EYE] != MISSING_DATA ){
					if (e_lx != NULL) e_lx -> setValue( evt.gx[LEFT_EYE] ,inputtime);
					if (e_ly != NULL) e_ly -> setValue( evt.gy[LEFT_EYE] ,inputtime);
				}
				else {
					if (e_lx != NULL && e_lx->getValue().getFloat() != MISSING_DATA)
						e_lx -> setValue((float)MISSING_DATA,inputtime);
					if (e_ly != NULL && e_ly->getValue().getFloat() != MISSING_DATA)
						e_ly -> setValue((float)MISSING_DATA,inputtime);
				}
				
				if( evt.hx[RIGHT_EYE] != -7936.0f &&
                   evt.hy[RIGHT_EYE] != -7936.0f ){
					if (h_rx != NULL) h_rx -> setValue( evt.hx[RIGHT_EYE] ,inputtime);
					if (h_ry != NULL) h_ry -> setValue( evt.hy[RIGHT_EYE] ,inputtime);
				}
				else {
					if (h_rx != NULL && h_rx->getValue().getFloat() != MISSING_DATA)
						h_rx -> setValue((float)MISSING_DATA,inputtime);
					if (h_ry != NULL && h_ry->getValue().getFloat() != MISSING_DATA)
						h_ry -> setValue((float)MISSING_DATA,inputtime);
				}
				
				if( evt.hx[LEFT_EYE] != -7936.0f &&
                   evt.hy[LEFT_EYE] != -7936.0f ){
					if (h_lx != NULL) h_lx -> setValue( evt.hx[LEFT_EYE] ,inputtime);
					if (h_ly != NULL) h_ly -> setValue( evt.hy[LEFT_EYE] ,inputtime);
				}
				else {
					if (h_lx != NULL && h_lx->getValue().getFloat() != MISSING_DATA)
						h_lx -> setValue((float)MISSING_DATA,inputtime);
					if (h_ly != NULL && h_ly->getValue().getFloat() != MISSING_DATA)
						h_ly -> setValue((float)MISSING_DATA,inputtime);
				}
				
				if( evt.px[RIGHT_EYE] != MISSING_DATA &&
                   evt.py[RIGHT_EYE] != MISSING_DATA ){
					if (p_rx != NULL) p_rx -> setValue( evt.px[RIGHT_EYE] ,inputtime);
					if (p_ry != NULL) p_ry -> setValue( evt.py[RIGHT_EYE] ,inputtime);
				}
				else {
					if (p_rx != NULL && p_rx->getValue().getFloat() != MISSING_DATA)
						p_rx -> setValue((float)MISSING_DATA,inputtime);
					if (p_ry != NULL && p_ry->getValue().getFloat() != MISSING_DATA)
						p_ry -> setValue((float)MISSING_DATA,inputtime);
				}
				
				if( evt.px[LEFT_EYE] != MISSING_DATA &&
                   evt.py[LEFT_EYE] != MISSING_DATA ){
					if (p_lx != NULL) p_lx -> setValue( evt.px[LEFT_EYE] ,inputtime);
					if (p_ly != NULL) p_ly -> setValue( evt.py[LEFT_EYE] ,inputtime);
				}
				else {
					if (p_lx != NULL && p_lx->getValue().getFloat() != MISSING_DATA)
						p_lx -> setValue((float)MISSING_DATA,inputtime);
					if (p_ly != NULL && p_ly->getValue().getFloat() != MISSING_DATA)
						p_ly -> setValue((float)MISSING_DATA,inputtime);
				}
				
				if( evt.pa[RIGHT_EYE] != 0 ){
					if (p_r != NULL) p_r -> setValue( evt.pa[RIGHT_EYE] ,inputtime);
				}
				else {
					if (p_r != NULL && p_r->getValue().getFloat() != 0)
						p_r -> setValue((float)MISSING_DATA,inputtime);
				}
				
				if( evt.pa[LEFT_EYE] != 0 ){
					if (p_l != NULL) p_l -> setValue( evt.pa[LEFT_EYE] ,inputtime);
				}
				else {
					if (p_l != NULL && p_l->getValue().getFloat() != 0)
						p_l -> setValue((float)MISSING_DATA,inputtime);
				}
			}
		}
	}
	else {
		if(++errors * update_period > (MWorksTime)1000000) { //just a quick hack but impossible to ignore by the user
			merror(M_IODEVICE_MESSAGE_DOMAIN, "Fatal Error! EyeLink Connection Lost!!");
			errors = 0;
		}
	}
	
	return true;
}