SMI RED eye tracking plugin 1.0

src/EyeTracking.cpp

Go to the documentation of this file.
00001 
00012 #include "Plugin.h"
00013 
00014 
00018 FixationData* fixationData;
00019 SampleData* newSample;
00020 
00021 boost::mutex mutexFixation;
00022 boost::mutex mutexSample;
00023 
00024 bool bNewFixationData;
00025 bool bNewSampleData;
00026 
00027 
00031 EyeTracking::EyeTracking()
00032 {
00033   m_accuracyData = new AccuracyStruct();
00034         m_systemInfoData = new SystemInfoStruct();
00035   m_calibrationData = new CalibrationStruct();
00036   fixationData = new FixationData();
00037   newSample = new SampleData();
00038 
00039   // Launch update loop thread
00040   exitRequested = false;
00041   loopThread = 0;
00042   loopThread = new boost::thread(boost::bind(&EyeTracking::GoThread, this));
00043 
00044   // Initialize flag for new fixation data
00045   bNewFixationData = false;
00046   bNewSampleData = false;
00047 }
00048 
00049 EyeTracking::~EyeTracking()
00050 {
00051   // Stop update loop thread
00052   exitRequested = true;
00053   if (loopThread != 0)
00054     loopThread->join();
00055 
00056   // Close connection to SMI RED
00057   Disconnect();
00058 
00059   // Free pointers to data structures
00060   delete(m_accuracyData);
00061         delete(m_systemInfoData);
00062         delete(m_calibrationData);
00063 
00064   // Delete class instance for callbacks messages
00065   delete(fixationData);
00066   delete(newSample);
00067 }
00068 
00069 
00073 void EyeTracking::SetCalibration(int method, int visualization, int displayDevice, int speed, int autoAccept, int foregroundBrightness, 
00074                                  int backgroundBrightness, int targetShape, int targetSize, char* targetFilename)
00075 {
00076   // Set up parameters
00077   m_calibrationData->method = method;
00078   m_calibrationData->visualization = visualization;
00079   m_calibrationData->displayDevice = displayDevice;
00080   m_calibrationData->speed = speed;
00081   m_calibrationData->autoAccept = autoAccept;
00082   m_calibrationData->foregroundBrightness = foregroundBrightness;
00083   m_calibrationData->backgroundBrightness = backgroundBrightness;
00084   m_calibrationData->targetShape = targetShape;
00085   m_calibrationData->targetSize = targetSize;
00086   strcpy_s(m_calibrationData->targetFilename, targetFilename);
00087 
00088   // Set up calibration
00089   iV_SetupCalibration(m_calibrationData);
00090 }
00091 
00092 bool EyeTracking::Calibrate(int validation)
00093 {
00094   // Launch calibration process
00095   if (iV_Calibrate() != RET_SUCCESS)
00096   {
00097     MMechostr(0, "EyeTracking::Calibrate -> iV_Calibrate() FAILURE\n");
00098     return false;
00099   }
00100   else
00101   {
00102     MMechostr(0, "EyeTracking::Calibrate -> iV_Calibrate() OK\n");
00103     
00104     // Check if validation must be done
00105     if (validation == 0)
00106     {
00107       AddCallbacks();
00108       PostMessage(HScol, SMI_CALIBRATION_DONE_CB, (int)this, (LPARAM)NULL);
00109       return true;
00110     }
00111 
00112     // Run validation process
00113     else
00114     {
00115       if (iV_Validate() != RET_SUCCESS)
00116       {
00117         MMechostr(0, "EyeTracking::Calibrate -> iV_Validate() FAILURE\n");
00118         return false;
00119       }
00120       else
00121       {
00122         // If validation successful, add the callbacks to start the gaze data acquisition
00123         AddCallbacks();
00124         PostMessage(HScol, SMI_CALIBRATION_DONE_CB, (int)this, (LPARAM)NULL);
00125         return true;
00126       }
00127     }
00128   }
00129 }
00130 
00131 
00135 // TODO: Fix issue when trying to load calibration from a file (check extension)
00136 bool EyeTracking::LoadCalibrationFromFile(char* fileName)
00137 {
00138   if (iV_LoadCalibration(fileName) != RET_SUCCESS)
00139     return false;
00140   else
00141     return true;
00142 }
00143 
00144 
00148 // TODO: Fix issue when trying to save calibration to a file (check extension)
00149 bool EyeTracking::SaveCalibrationToFile(char* fileName)
00150 {
00151   if (iV_SaveCalibration(fileName) != RET_SUCCESS)
00152     return false;
00153   else
00154     return true;
00155 }
00156 
00157 
00161 AccuracyStruct* EyeTracking::GetAccuracy()
00162 {
00163   iV_GetAccuracy(m_accuracyData, 0);
00164   return m_accuracyData;
00165 }
00166 
00167 SystemInfoStruct* EyeTracking::GetSystemInfo()
00168 {
00169   iV_GetSystemInfo(m_systemInfoData);
00170   return m_systemInfoData;
00171 }
00172 
00173 CalibrationStruct* EyeTracking::GetCalibration()
00174 {
00175   return m_calibrationData;
00176 }
00177 
00178 
00182 bool EyeTracking::Connect(char* senderIp, int senderPort, char* receiverIp, int receiverPort)
00183 {
00184   if (iV_Connect(senderIp, senderPort, receiverIp, receiverPort) == RET_SUCCESS)
00185   {
00186     PostMessage(HScol, SMI_CONNECTED_CB, (int)this, (LPARAM)NULL);
00187     return true;
00188   }
00189   else
00190   {
00191     PostMessage(HScol, SMI_DISCONNECTED_CB, (int)this, (LPARAM)NULL);
00192     return false;
00193   }
00194 }
00195 
00196 bool EyeTracking::Disconnect()
00197 {
00198   if (iV_Disconnect() != RET_SUCCESS)
00199     return false;
00200   else
00201     return true;
00202 }
00203 
00204 
00208 bool EyeTracking::ShowTrackingWindow()
00209 {
00210   if (iV_ShowTrackingMonitor() != RET_SUCCESS)
00211     return false;
00212   else
00213     return true;
00214 }
00215 
00216 
00220 bool EyeTracking::CreateLogFile(char* logFileName)
00221 {
00222   // Default: log everything
00223   if (iV_SetLogger(LOG_LEVEL_ALL_FCT, logFileName) != RET_SUCCESS)
00224     return false;
00225   else
00226     return true;
00227 }
00228 
00229 bool EyeTracking::WriteToLog(char* logFileLine)
00230 {
00231   if (iV_Log(logFileLine))
00232     return false;
00233   else
00234     return true;
00235 }
00236 
00237 
00241 int __stdcall EyeTracking::SampleCallbackFunction(SampleStruct sampleData)
00242 {
00243   // Check if eyes have been detected by SMI RED
00244   /*if ((sampleData.leftEye.gazeX > 0.0 && sampleData.leftEye.gazeY > 0.0) || (sampleData.rightEye.gazeX > 0.0 && sampleData.rightEye.gazeY > 0.0))
00245   {
00246     // Lock mutex
00247     boost::mutex::scoped_lock lockSample(mutexSample, boost::defer_lock);   // defer_lock makes it initially unlocked
00248     MMechostr(0, "SampleCallbackFunction --> Mutex locked.\n");
00249 
00250     newSample->leftPupilDiameter = (float)sampleData.leftEye.diam;
00251     newSample->leftGazeX = (int)sampleData.leftEye.gazeX;
00252     newSample->leftGazeY = (int)sampleData.leftEye.gazeY;
00253 
00254     newSample->rightPupilDiameter = (float)sampleData.rightEye.diam;
00255     newSample->rightGazeX = (int)sampleData.rightEye.gazeX;
00256     newSample->rightGazeY = (int)sampleData.rightEye.gazeY;
00257     MMechostr(0, "SampleCallbackFunction --> Mutex unlocked.\n");
00258     bNewSampleData = true;
00259   }*/
00260   return 0;
00261 }
00262 
00263 int __stdcall EyeTracking::CalibrationUpdated(CalibrationPointStruct calibrationPoint)
00264 {
00265   return 0;
00266 }
00267 
00268 int __stdcall EyeTracking::FixationUpdated(EventStruct eventDataSample)
00269 {
00270   // Lock mutex
00271   boost::mutex::scoped_lock lockFixation(mutexFixation, boost::defer_lock);   // defer_lock makes it initially unlocked
00272   MMechostr(0, "FixationUpdated --> Mutex locked.\n");
00273 
00274   // Convert fixation duration to milliseconds
00275   fixationData->duration = eventDataSample.duration / 1000.0f;
00276 
00277   // Get position [X,Y]
00278   fixationData->posX = (int)eventDataSample.positionX;
00279   fixationData->posY = (int)eventDataSample.positionY;
00280   MMechostr(0, "FixationUpdated --> Mutex unlocked.\n");
00281   bNewFixationData = true;
00282   
00283   return 0;
00284 }
00285 
00286 
00290 void EyeTracking::AddCallbacks()
00291 {
00292   // Called when iView X has generated a new raw data sample
00293   iV_SetSampleCallback(SampleCallbackFunction);
00294 
00295   // Called when a calibration point has changed, the calibration has been finished or aborted
00296   iV_SetCalibrationCallback(CalibrationUpdated);
00297 
00298   // Called when a real-time detected fixation has ended
00299   iV_SetEventCallback(FixationUpdated);
00300 }
00301 
00302 
00306 void EyeTracking::HandleFixationEvent()
00307 {
00308   // Lock during operation
00309   boost::mutex::scoped_lock lockFixation(mutexFixation, boost::defer_lock);   // defer_lock makes it initially unlocked
00310   MMechostr(0, "GoThread --> Mutex [fixation] locked.\n");
00311 
00312   // Send notification to Scol handle
00313   PostMessage(HScol, SMI_NEW_FIXATION_CB, (int)this, (LPARAM)fixationData);
00314   MMechostr(0, "GoThread --> Mutex [fixation] unlocked.\n");
00315 
00316   // Reset flag to detect new data arrival
00317   bNewFixationData = false;
00318 }
00319 
00320 
00324 void EyeTracking::HandleSampleEvent()
00325 {
00326   // Lock during operation
00327   boost::mutex::scoped_lock lockSample(mutexSample, boost::defer_lock);   // defer_lock makes it initially unlocked
00328   MMechostr(0, "GoThread --> Mutex [sample] locked.\n");
00329 
00330   // Send notification to Scol handle
00331   PostMessage(HScol, SMI_NEW_SAMPLE_CB, (int)this, (LPARAM)newSample);
00332   MMechostr(0, "GoThread --> Mutex [sample] unlocked.\n");
00333 
00334   // Reset flag to detect new data arrival
00335   bNewFixationData = false;
00336 }
00337 
00338 
00342 void EyeTracking::GoThread()
00343 {
00344   while(!exitRequested)
00345   {
00346     // Check arrival of new fixation data
00347     if (bNewFixationData)
00348     {
00349       HandleFixationEvent();
00350     }
00351 
00352     // Check arrival of new sample data
00353     if (bNewSampleData)
00354     {
00355       //HandleSampleEvent(); 
00356     }
00357   }
00358 }