|
SMI RED eye tracking plugin 1.0
|
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 }
1.7.3