From e007864f430012ac03455142b3910760df03987d Mon Sep 17 00:00:00 2001 From: Wim Vriend Date: Fri, 24 Dec 2010 18:58:17 +0000 Subject: Removed QThread reference of protocol server-code. Have still to adapt some of them though... git-svn-id: svn+ssh://svn.code.sf.net/p/facetracknoir/code@32 19e81ba0-9b1a-49c3-bd6c-561e1906d5fb --- FaceTrackNoIR/FGServer.cpp | 6 +- FaceTrackNoIR/FTIRServer.cpp | 149 ++++++---------- FaceTrackNoIR/FTIRServer.h | 7 +- FaceTrackNoIR/FTServer.cpp | 137 ++++++--------- FaceTrackNoIR/FTServer.h | 3 +- FaceTrackNoIR/FaceTrackNoIR.vcproj | 11 -- FaceTrackNoIR/PPJoyServer.cpp | 43 +++-- FaceTrackNoIR/PPJoyServer.h | 3 +- FaceTrackNoIR/SCServer.cpp | 59 +++---- FaceTrackNoIR/SCServer.h | 3 +- FaceTrackNoIR/tracker.cpp | 338 +++++++++++++++++++------------------ FaceTrackNoIR/tracker.h | 3 + 12 files changed, 351 insertions(+), 411 deletions(-) (limited to 'FaceTrackNoIR') diff --git a/FaceTrackNoIR/FGServer.cpp b/FaceTrackNoIR/FGServer.cpp index 6b96d249..47ca31ba 100644 --- a/FaceTrackNoIR/FGServer.cpp +++ b/FaceTrackNoIR/FGServer.cpp @@ -38,8 +38,8 @@ FGServer::FGServer( Tracker *parent ) { headTracker = parent; // Create events - m_StopThread = CreateEvent(0, TRUE, FALSE, 0); - m_WaitThread = CreateEvent(0, TRUE, FALSE, 0); + //m_StopThread = CreateEvent(0, TRUE, FALSE, 0); + //m_WaitThread = CreateEvent(0, TRUE, FALSE, 0); loadSettings(); } @@ -123,7 +123,7 @@ void FGServer::run() { // Connect the inSocket to the member-function, to read FlightGear commands connect(inSocket, SIGNAL(readyRead()), this, SLOT(readPendingDatagrams()), Qt::DirectConnection); - exec(); // Exec only returns, when the thread terminates... +// exec(); // Exec only returns, when the thread terminates... } /** QThread terminate @override **/ diff --git a/FaceTrackNoIR/FTIRServer.cpp b/FaceTrackNoIR/FTIRServer.cpp index 5ecd9622..54570fcd 100644 --- a/FaceTrackNoIR/FTIRServer.cpp +++ b/FaceTrackNoIR/FTIRServer.cpp @@ -21,17 +21,15 @@ ********************************************************************************/ /* Modifications (last one on top): + 20101224 - WVR: Base class is no longer inheriting QThread. sendHeadposeToGame + is called from run() of Tracker.cpp + 20101127 - WVR: Added TrackIR.exe process for EZCA etc... 20101023 - WVR: Added TIRViews for FS2004, Combat FS3, etc... */ #include "FTIRServer.h" /** constructor **/ FTIRServer::FTIRServer() { - - // Create events - m_StopThread = CreateEvent(0, TRUE, FALSE, 0); - m_WaitThread = CreateEvent(0, TRUE, FALSE, 0); - loadSettings(); ProgramName = ""; } @@ -39,16 +37,6 @@ FTIRServer::FTIRServer() { /** destructor **/ FTIRServer::~FTIRServer() { - // Trigger thread to stop - ::SetEvent(m_StopThread); - - // Wait until thread finished - ::WaitForSingleObject(m_WaitThread, INFINITE); - - // Close handles - ::CloseHandle(m_StopThread); - ::CloseHandle(m_WaitThread); - // // Free the DLL's // @@ -62,88 +50,20 @@ FTIRServer::~FTIRServer() { if (dummyTrackIR) { dummyTrackIR->kill(); } - - //terminates the QThread and waits for finishing the QThread - terminate(); - wait(); } -/** QThread run @override **/ -void FTIRServer::run() { - importSetPosition setposition; // Inside NPClient.dll - importTIRViewsStart viewsStart = NULL; // Inside TIRViews.dll - importTIRViewsStop viewsStop = NULL; +// +// Update Headpose in Game. +// +void FTIRServer::sendHeadposeToGame() { // - // Get the setposition function from the DLL and use it! + // Check if the pointer is OK and wait for the Mutex. + // Use the setposition in the (special) DLL, to write the headpose-data. // - setposition = (importSetPosition) FTIRClientLib.resolve("SetPosition"); - if (setposition == NULL) { - qDebug() << "FTIRServer::run() says: SetPosition function not found in DLL!"; - return; - } - else { - setposition (7.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f); - } - - // - // Load the Start function from TIRViews.dll and call it, to start compatibility with older games - // - if (useTIRViews) { - viewsStart = (importTIRViewsStart) FTIRViewsLib.resolve("TIRViewsStart"); - if (viewsStart == NULL) { - qDebug() << "FTIRServer::run() says: TIRViewsStart function not found in DLL!"; - } - else { - qDebug() << "FTIRServer::run() says: TIRViewsStart executed!"; - viewsStart(); - } - - // - // Load the Stop function from TIRViews.dll. Call it when terminating the thread. - // - viewsStop = (importTIRViewsStop) FTIRViewsLib.resolve("TIRViewsStop"); - if (viewsStop == NULL) { - qDebug() << "FTIRServer::run() says: TIRViewsStop function not found in DLL!"; - } - } - - // - // Run, until termination - // - forever - { - // Check event for stop thread - if(::WaitForSingleObject(m_StopThread, 0) == WAIT_OBJECT_0) - { - if (viewsStop != NULL) { - viewsStop(); - } - - // Set event - ::SetEvent(m_WaitThread); - return; - } - - if ( (pMemData != NULL) && (WaitForSingleObject(hFTIRMutex, 100) == WAIT_OBJECT_0) ) { - -// qDebug() << "FTIRServer says: virtRotX =" << virtRotX << " virtRotY =" << virtRotY; - setposition (virtPosX, virtPosY, virtPosZ, virtRotZ, virtRotX, virtRotY ); - - //// Use this for some debug-output to file... - //QFile data("outputFTIR.txt"); - //if (data.open(QFile::WriteOnly | QFile::Append)) { - // QTextStream out(&data); - // out << virtPosX << " " << virtPosY << " " << virtPosZ << virtRotX << " " << virtRotY << " " << virtRotZ << '\n'; - //} - - //qDebug() << "FTIRServer says: pMemData.xRot =" << pMemData->data.xRot << " yRot =" << pMemData->data.yRot; - ReleaseMutex(hFTIRMutex); - } - - // just for lower cpu load - msleep(15); - yieldCurrentThread(); + if ( (pMemData != NULL) && (WaitForSingleObject(hFTIRMutex, 100) == WAIT_OBJECT_0) ) { + setposition (virtPosX, virtPosY, virtPosZ, virtRotZ, virtRotX, virtRotY ); + ReleaseMutex(hFTIRMutex); } } @@ -282,7 +202,50 @@ bool FTIRServer::checkServerInstallationOK( HANDLE handle ) } catch(...) { settings.~QSettings(); } - return FTIRCreateMapping( handle ); + + // + // Create the File-mapping for Inter Process Communication + // + if (!FTIRCreateMapping( handle )){ + return false; + } + + // + // Find the functions in the DLL's + // + // Get the setposition function from the DLL and use it! + // + setposition = (importSetPosition) FTIRClientLib.resolve("SetPosition"); + if (setposition == NULL) { + qDebug() << "FTIRServer::run() says: SetPosition function not found in DLL!"; + return false; + } + else { + setposition (7.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f); + } + + // + // Load the Start function from TIRViews.dll and call it, to start compatibility with older games + // + if (useTIRViews) { + viewsStart = (importTIRViewsStart) FTIRViewsLib.resolve("TIRViewsStart"); + if (viewsStart == NULL) { + qDebug() << "FTIRServer::run() says: TIRViewsStart function not found in DLL!"; + } + else { + qDebug() << "FTIRServer::run() says: TIRViewsStart executed!"; + viewsStart(); + } + + // + // Load the Stop function from TIRViews.dll. Call it when terminating the thread. + // + viewsStop = (importTIRViewsStop) FTIRViewsLib.resolve("TIRViewsStop"); + if (viewsStop == NULL) { + qDebug() << "FTIRServer::run() says: TIRViewsStop function not found in DLL!"; + } + } + return true; } // diff --git a/FaceTrackNoIR/FTIRServer.h b/FaceTrackNoIR/FTIRServer.h index 98273bc5..c27a1ab5 100644 --- a/FaceTrackNoIR/FTIRServer.h +++ b/FaceTrackNoIR/FTIRServer.h @@ -56,13 +56,18 @@ public: // protected member methods protected: - void run(); +// void run(); bool checkServerInstallationOK( HANDLE handle ); + void sendHeadposeToGame(); private: bool FTIRCreateMapping(HANDLE handle); void FTIRDestroyMapping(); + importSetPosition setposition; // Function inside NPClient.dll + importTIRViewsStart viewsStart; // Functions inside TIRViews.dll + importTIRViewsStop viewsStop; + HANDLE hFTIRMemMap; FTIRMemMap *pMemData; HANDLE hFTIRMutex; diff --git a/FaceTrackNoIR/FTServer.cpp b/FaceTrackNoIR/FTServer.cpp index 27808343..7814c2d3 100644 --- a/FaceTrackNoIR/FTServer.cpp +++ b/FaceTrackNoIR/FTServer.cpp @@ -41,110 +41,77 @@ // /* Modifications (last one on top): - 20100601 - WVR: Added Mutex-bit in run(). Thought it wasn't so important (still do...). - 20100523 - WVR: Implemented the Freetrack-protocol just like Freetrack does. Earlier - FaceTrackNoIR only worked with an adapted DLL, with a putdata function. - Now it works direcly in shared memory! + 20101224 - WVR: Base class is no longer inheriting QThread. sendHeadposeToGame + is called from run() of Tracker.cpp + 20100601 - WVR: Added Mutex-bit in run(). Thought it wasn't so important (still do...). + 20100523 - WVR: Implemented the Freetrack-protocol just like Freetrack does. Earlier + FaceTrackNoIR only worked with an adapted DLL, with a putdata function. + Now it works direcly in shared memory! */ #include "FTServer.h" /** constructor **/ FTServer::FTServer() { - - // Create events - m_StopThread = CreateEvent(0, TRUE, FALSE, 0); - m_WaitThread = CreateEvent(0, TRUE, FALSE, 0); - ProgramName = ""; } /** destructor **/ FTServer::~FTServer() { - // Trigger thread to stop - ::SetEvent(m_StopThread); - - // Wait until thread finished - ::WaitForSingleObject(m_WaitThread, INFINITE); - - // Close handles - ::CloseHandle(m_StopThread); - ::CloseHandle(m_WaitThread); - // // Free the DLL // FTClientLib.unload(); - //if( aDLLHandle != INVALID_HANDLE_VALUE ) - // FreeLibrary( (HMODULE) aDLLHandle ); - //terminates the QThread and waits for finishing the QThread - terminate(); - wait(); } -/** QThread run @override **/ -void FTServer::run() { - - if (pMemData != NULL) { - pMemData->data.DataID = 1; - pMemData->data.CamWidth = 100; - pMemData->data.CamHeight = 250; - } - - forever - { - // Check event for stop thread - if(::WaitForSingleObject(m_StopThread, 0) == WAIT_OBJECT_0) - { - // Set event - ::SetEvent(m_WaitThread); - return; - } - - if ( (pMemData != NULL) && (WaitForSingleObject(hFTMutex, 100) == WAIT_OBJECT_0) ) { - - // - // Copy the Raw measurements directly to the client. - // - pMemData->data.RawX = headPosX; - pMemData->data.RawY = headPosY; - pMemData->data.RawZ = headPosZ; - pMemData->data.RawPitch = headRotX; - pMemData->data.RawYaw = headRotY; - pMemData->data.RawRoll = headRotZ; +// +// Update Headpose in Game. +// +void FTServer::sendHeadposeToGame() { - // - // Multiply the FaceAPI value, with the sensitivity setting - // - pMemData->data.X = virtPosX; - pMemData->data.Y = virtPosY; - pMemData->data.Z = virtPosZ; - pMemData->data.Pitch = virtRotX; - pMemData->data.Yaw = virtRotY; - pMemData->data.Roll = virtRotZ; + // + // Check if the pointer is OK and wait for the Mutex. + // + if ( (pMemData != NULL) && (WaitForSingleObject(hFTMutex, 100) == WAIT_OBJECT_0) ) { - // - // Leave some values 0 yet... - // - pMemData->data.X1 = pMemData->data.DataID + 10; - pMemData->data.X2 = 0; - pMemData->data.X3 = 0; - pMemData->data.X4 = 0; - pMemData->data.Y1 = 0; - pMemData->data.Y2 = 0; - pMemData->data.Y3 = 0; - pMemData->data.Y4 = 0; + // + // Copy the Raw measurements directly to the client. + // + pMemData->data.RawX = headPosX; + pMemData->data.RawY = headPosY; + pMemData->data.RawZ = headPosZ; + pMemData->data.RawPitch = headRotX; + pMemData->data.RawYaw = headRotY; + pMemData->data.RawRoll = headRotZ; - //qDebug() << "FTServer says: pMemData.DataID =" << pMemData->data.DataID; - //qDebug() << "FTServer says: ProgramName =" << pMemData->ProgramName; - ReleaseMutex(hFTMutex); - } + // + // Multiply the FaceAPI value, with the sensitivity setting + // + pMemData->data.X = virtPosX; + pMemData->data.Y = virtPosY; + pMemData->data.Z = virtPosZ; + pMemData->data.Pitch = virtRotX; + pMemData->data.Yaw = virtRotY; + pMemData->data.Roll = virtRotZ; - // just for lower cpu load - msleep(15); - yieldCurrentThread(); - pMemData->data.DataID += 1; + // + // Leave some values 0 yet... + // + pMemData->data.X1 = pMemData->data.DataID + 10; + pMemData->data.X2 = 0; + pMemData->data.X3 = 0; + pMemData->data.X4 = 0; + pMemData->data.Y1 = 0; + pMemData->data.Y2 = 0; + pMemData->data.Y3 = 0; + pMemData->data.Y4 = 0; + + //qDebug() << "FTServer says: pMemData.DataID =" << pMemData->data.DataID; + //qDebug() << "FTServer says: ProgramName =" << pMemData->ProgramName; + ReleaseMutex(hFTMutex); } + + pMemData->data.DataID += 1; } // @@ -192,6 +159,12 @@ bool FTServer::FTCreateMapping(HANDLE handle) return false; } + if (pMemData != NULL) { + pMemData->data.DataID = 1; + pMemData->data.CamWidth = 100; + pMemData->data.CamHeight = 250; + } + return true; } diff --git a/FaceTrackNoIR/FTServer.h b/FaceTrackNoIR/FTServer.h index 1d7907ed..ba1dfeb2 100644 --- a/FaceTrackNoIR/FTServer.h +++ b/FaceTrackNoIR/FTServer.h @@ -62,8 +62,9 @@ public: // protected member methods protected: - void run(); +// void run(); bool checkServerInstallationOK( HANDLE handle ); + void sendHeadposeToGame(); private: bool FTCreateMapping(HANDLE handle); diff --git a/FaceTrackNoIR/FaceTrackNoIR.vcproj b/FaceTrackNoIR/FaceTrackNoIR.vcproj index f5c6e94e..4a98b8b3 100644 --- a/FaceTrackNoIR/FaceTrackNoIR.vcproj +++ b/FaceTrackNoIR/FaceTrackNoIR.vcproj @@ -1023,17 +1023,6 @@ > - - - diff --git a/FaceTrackNoIR/PPJoyServer.cpp b/FaceTrackNoIR/PPJoyServer.cpp index 812cd7cb..9a2301fd 100644 --- a/FaceTrackNoIR/PPJoyServer.cpp +++ b/FaceTrackNoIR/PPJoyServer.cpp @@ -42,8 +42,8 @@ char strDevName[100]; headTracker = parent; // Create events - m_StopThread = CreateEvent(0, TRUE, FALSE, 0); - m_WaitThread = CreateEvent(0, TRUE, FALSE, 0); + //m_StopThread = CreateEvent(0, TRUE, FALSE, 0); + //m_WaitThread = CreateEvent(0, TRUE, FALSE, 0); // Initialize arrays for (int i = 0;i < 3;i++) { @@ -72,33 +72,32 @@ PPJoyServer::~PPJoyServer() { /* Make sure we could open the device! */ if (h == INVALID_HANDLE_VALUE) { - terminate(); - wait(); + //terminate(); + //wait(); return; } - // Trigger thread to stop - ::SetEvent(m_StopThread); + //// Trigger thread to stop + //::SetEvent(m_StopThread); - // Wait until thread finished - ::WaitForSingleObject(m_WaitThread, INFINITE); + //// Wait until thread finished + //::WaitForSingleObject(m_WaitThread, INFINITE); - // Close handles - ::CloseHandle(m_StopThread); - ::CloseHandle(m_WaitThread); + //// Close handles + //::CloseHandle(m_StopThread); + //::CloseHandle(m_WaitThread); // // Free the Virtual Joystick // CloseHandle(h); //terminates the QThread and waits for finishing the QThread - terminate(); - wait(); + //terminate(); + //wait(); } /** QThread run @override **/ -void PPJoyServer::run() { - +void PPJoyServer::sendHeadposeToGame() { /* Initialise the IOCTL data structure */ JoyState.Signature= JOYSTICK_STATE_V1; @@ -116,11 +115,11 @@ void PPJoyServer::run() { forever { // Check event for stop thread - if(::WaitForSingleObject(m_StopThread, 0) == WAIT_OBJECT_0) { - // Set event - ::SetEvent(m_WaitThread); - return; - } + //if(::WaitForSingleObject(m_StopThread, 0) == WAIT_OBJECT_0) { + // // Set event + // ::SetEvent(m_WaitThread); + // return; + //} // The effective angle for faceTracking will be < 90 degrees, so we assume a smaller range here Analog[0] = scale2AnalogLimits( virtRotX, -50.0f, 50.0f ); // Pitch @@ -143,8 +142,8 @@ void PPJoyServer::run() { return; } // just for lower cpu load - msleep(15); - yieldCurrentThread(); + //msleep(15); + //yieldCurrentThread(); } } diff --git a/FaceTrackNoIR/PPJoyServer.h b/FaceTrackNoIR/PPJoyServer.h index 31e7f97a..b5fdd012 100644 --- a/FaceTrackNoIR/PPJoyServer.h +++ b/FaceTrackNoIR/PPJoyServer.h @@ -72,7 +72,8 @@ public: // protected member methods protected: - void run(); +// void run(); + void sendHeadposeToGame(); private slots: // void readPendingDatagrams(); diff --git a/FaceTrackNoIR/SCServer.cpp b/FaceTrackNoIR/SCServer.cpp index c948b8a6..9ee52f8d 100644 --- a/FaceTrackNoIR/SCServer.cpp +++ b/FaceTrackNoIR/SCServer.cpp @@ -24,21 +24,12 @@ */ #include "SCServer.h" - -//float SCServer::virtPosX = 0.0f; -//float SCServer::virtPosY = 0.0f; -//float SCServer::virtPosZ = 0.0f; -// -//float SCServer::virtRotX = 0.0f; -//float SCServer::virtRotY = 0.0f; -//float SCServer::virtRotZ = 0.0f; - /** constructor **/ SCServer::SCServer() { // Create events - m_StopThread = CreateEvent(0, TRUE, FALSE, 0); - m_WaitThread = CreateEvent(0, TRUE, FALSE, 0); + //m_StopThread = CreateEvent(0, TRUE, FALSE, 0); + //m_WaitThread = CreateEvent(0, TRUE, FALSE, 0); ProgramName = ""; } @@ -47,16 +38,16 @@ SCServer::SCServer() { SCServer::~SCServer() { // Trigger thread to stop - ::SetEvent(m_StopThread); + //::SetEvent(m_StopThread); // Wait until thread finished - if (isRunning()) { - ::WaitForSingleObject(m_WaitThread, INFINITE); - } + //if (isRunning()) { + // ::WaitForSingleObject(m_WaitThread, INFINITE); + //} - // Close handles - ::CloseHandle(m_StopThread); - ::CloseHandle(m_WaitThread); + //// Close handles + //::CloseHandle(m_StopThread); + //::CloseHandle(m_WaitThread); // // Free the DLL @@ -64,12 +55,12 @@ SCServer::~SCServer() { SCClientLib.unload(); //terminates the QThread and waits for finishing the QThread - terminate(); - wait(); + //terminate(); + //wait(); } /** QThread run @override **/ -void SCServer::run() { +void SCServer::sendHeadposeToGame() { bool blnSimConnectActive = false; HANDLE hSimConnect = NULL; // Handle to SimConnect importSimConnect_Open simconnect_open; // SimConnect function(s) in DLL @@ -109,23 +100,23 @@ float prevPosX, prevPosY, prevPosZ, prevRotX, prevRotY, prevRotZ; forever { // Check event for stop thread - if(::WaitForSingleObject(m_StopThread, 0) == WAIT_OBJECT_0) - { - // Set event - simconnect_close( hSimConnect ); - ::SetEvent(m_WaitThread); - return; - } + //if(::WaitForSingleObject(m_StopThread, 0) == WAIT_OBJECT_0) + //{ + // // Set event +// simconnect_close( hSimConnect ); + // ::SetEvent(m_WaitThread); + // return; + //} if (!blnSimConnectActive) { if (SUCCEEDED(simconnect_open(&hSimConnect, "FaceTrackNoIR", NULL, 0, 0, 0))) { qDebug() << "SCServer::run() says: SimConnect active!"; blnSimConnectActive = true; } - else { - msleep(5000); - yieldCurrentThread(); - } + //else { + // msleep(5000); + // yieldCurrentThread(); + //} } else { // @@ -148,8 +139,8 @@ float prevPosX, prevPosY, prevPosZ, prevRotX, prevRotY, prevRotZ; prevRotZ = virtRotZ; // just for lower cpu load - msleep(15); - yieldCurrentThread(); + //msleep(15); + //yieldCurrentThread(); } } } diff --git a/FaceTrackNoIR/SCServer.h b/FaceTrackNoIR/SCServer.h index 6df22b21..f107de55 100644 --- a/FaceTrackNoIR/SCServer.h +++ b/FaceTrackNoIR/SCServer.h @@ -62,8 +62,9 @@ public: // protected member methods protected: - void run(); +// void run(); bool checkServerInstallationOK( HANDLE handle ); + void sendHeadposeToGame(); private: // Private properties diff --git a/FaceTrackNoIR/tracker.cpp b/FaceTrackNoIR/tracker.cpp index 1e3c17b4..a43acd9a 100644 --- a/FaceTrackNoIR/tracker.cpp +++ b/FaceTrackNoIR/tracker.cpp @@ -23,6 +23,8 @@ *********************************************************************************/ /* Modifications (last one on top): + 20101224 - WVR: Removed the QThread inheritance of the Base Class for the protocol-servers. + Again, this drastically simplifies the code in the protocols. 20101217 - WVR: Created Base Class for the protocol-servers. This drastically simplifies the code needed here. 20101024 - WVR: Added shortkey to disable/enable one or more axis during tracking. @@ -55,6 +57,7 @@ bool Tracker::do_tracking = true; bool Tracker::do_center = false; bool Tracker::do_inhibit = false; bool Tracker::useFilter = false; +HANDLE Tracker::hTrackMutex = 0; long Tracker::prevHeadPoseTime = 0; THeadPoseDOF Tracker::Pitch; // One structure for each of 6DOF's @@ -80,6 +83,8 @@ Tracker::Tracker( int clientID, int facetrackerID ) { m_StopThread = CreateEvent(0, TRUE, FALSE, 0); m_WaitThread = CreateEvent(0, TRUE, FALSE, 0); + Tracker::hTrackMutex = CreateMutexA(NULL, false, "HeadPose_mutex"); + try { // Initialize the faceAPI Qt library sm::faceapi::qt::initialize(); @@ -157,6 +162,7 @@ Tracker::~Tracker() { // Close handles ::CloseHandle(m_StopThread); ::CloseHandle(m_WaitThread); + ::CloseHandle( Tracker::hTrackMutex ); _engine->stop(); smAPIQuit(); @@ -196,10 +202,10 @@ void Tracker::setup(QWidget *head, FaceTrackNoIR *parent) { if (server_Game) { DLL_Ok = server_Game->checkServerInstallationOK( mainApp->winId() ); - if (DLL_Ok) { - server_Game->start(); // Start the thread - } - else { + if (!DLL_Ok) { +// server_Game->start(); // Start the thread + //} + //else { QMessageBox::information(mainApp, "FaceTrackNoIR error", "Protocol is not (correctly) installed!"); } @@ -342,186 +348,191 @@ void Tracker::run() { } } - // - // Get the System-time and substract the time from the previous call. - // dT will be used for the EWMA-filter. - // - GetSystemTime ( &now ); - newHeadPoseTime = (((now.wHour * 3600) + (now.wMinute * 60) + now.wSecond) * 1000) + now.wMilliseconds; - dT = (newHeadPoseTime - Tracker::prevHeadPoseTime) / 1000.0f; - - // Remember time for next call - Tracker::prevHeadPoseTime = newHeadPoseTime; - - //if the confidence is good enough the headpose will be updated **/ - if (Tracker::confid) { + if (WaitForSingleObject(Tracker::hTrackMutex, 100) == WAIT_OBJECT_0) { // - // Most games need an offset to the initial position and NOT the - // absolute distance to the camera: so remember the initial distance - // to substract that later... + // Get the System-time and substract the time from the previous call. + // dT will be used for the EWMA-filter. // - if(Tracker::set_initial == false) { - Tracker::Pitch.initial_headPos = Tracker::Pitch.headPos; - Tracker::Yaw.initial_headPos = Tracker::Yaw.headPos; - Tracker::Roll.initial_headPos = Tracker::Roll.headPos; - Tracker::X.initial_headPos = Tracker::X.headPos; - Tracker::Y.initial_headPos = Tracker::Y.headPos; - Tracker::Z.initial_headPos = Tracker::Z.headPos; - MessageBeep (MB_ICONASTERISK); - Tracker::set_initial = true; - } + GetSystemTime ( &now ); + newHeadPoseTime = (((now.wHour * 3600) + (now.wMinute * 60) + now.wSecond) * 1000) + now.wMilliseconds; + dT = (newHeadPoseTime - Tracker::prevHeadPoseTime) / 1000.0f; - rawrotX = Tracker::Pitch.headPos- Tracker::Pitch.initial_headPos; // degrees - rawrotY = Tracker::Yaw.headPos- Tracker::Yaw.initial_headPos; - rawrotZ = Tracker::Roll.headPos - Tracker::Roll.initial_headPos; - rawposX = Tracker::X.headPos - Tracker::X.initial_headPos; // centimeters - rawposY = Tracker::Y.headPos - Tracker::Y.initial_headPos; - rawposZ = Tracker::Z.headPos - Tracker::Z.initial_headPos; + // Remember time for next call + Tracker::prevHeadPoseTime = newHeadPoseTime; - headRotXLine->setText(QString("%1").arg( rawrotX, 0, 'f', 1)); // show degrees - headRotYLine->setText(QString("%1").arg( rawrotY, 0, 'f', 1)); - headRotZLine->setText(QString("%1").arg( rawrotZ, 0, 'f', 1)); + //if the confidence is good enough the headpose will be updated **/ + if (Tracker::confid) { - headXLine->setText(QString("%1").arg( rawposX, 0, 'f', 1)); // show centimeters - headYLine->setText(QString("%1").arg( rawposY, 0, 'f', 1)); - headZLine->setText(QString("%1").arg( rawposZ, 0, 'f', 1)); - - } + // + // Most games need an offset to the initial position and NOT the + // absolute distance to the camera: so remember the initial distance + // to substract that later... + // + if(Tracker::set_initial == false) { + Tracker::Pitch.initial_headPos = Tracker::Pitch.headPos; + Tracker::Yaw.initial_headPos = Tracker::Yaw.headPos; + Tracker::Roll.initial_headPos = Tracker::Roll.headPos; + Tracker::X.initial_headPos = Tracker::X.headPos; + Tracker::Y.initial_headPos = Tracker::Y.headPos; + Tracker::Z.initial_headPos = Tracker::Z.headPos; + MessageBeep (MB_ICONASTERISK); + Tracker::set_initial = true; + } - // - // If Center is pressed, copy the current values to the offsets. - // - if (Tracker::do_center && Tracker::set_initial) { - Pitch.offset_headPos = getSmoothFromList( &Pitch.rawList )- Tracker::Pitch.initial_headPos; - Yaw.offset_headPos = getSmoothFromList( &Yaw.rawList ) - Tracker::Yaw.initial_headPos; - Roll.offset_headPos = getSmoothFromList( &Roll.rawList ) - Tracker::Roll.initial_headPos; - X.offset_headPos = getSmoothFromList( &X.rawList ) - Tracker::X.initial_headPos; - Y.offset_headPos = getSmoothFromList( &Y.rawList ) - Tracker::Y.initial_headPos; - Z.offset_headPos = getSmoothFromList( &Z.rawList ) - Tracker::Z.initial_headPos; - - Tracker::do_center = false; - } + rawrotX = Tracker::Pitch.headPos- Tracker::Pitch.initial_headPos; // degrees + rawrotY = Tracker::Yaw.headPos- Tracker::Yaw.initial_headPos; + rawrotZ = Tracker::Roll.headPos - Tracker::Roll.initial_headPos; + rawposX = Tracker::X.headPos - Tracker::X.initial_headPos; // centimeters + rawposY = Tracker::Y.headPos - Tracker::Y.initial_headPos; + rawposZ = Tracker::Z.headPos - Tracker::Z.initial_headPos; - if (Tracker::do_tracking && Tracker::confid) { + headRotXLine->setText(QString("%1").arg( rawrotX, 0, 'f', 1)); // show degrees + headRotYLine->setText(QString("%1").arg( rawrotY, 0, 'f', 1)); + headRotZLine->setText(QString("%1").arg( rawrotZ, 0, 'f', 1)); -////// Use this for some debug-output to file... -//// QFile data("output.txt"); -//// if (data.open(QFile::WriteOnly | QFile::Append)) { -//// QTextStream out(&data); -//// out << Pitch.NeutralZone << " " << getDegreesFromRads(rotX) << " " << getOutputFromCurve(&Pitch.curve, getDegreesFromRads(rotX), Pitch.NeutralZone, Pitch.MaxInput) << '\n'; -////// out << dT << " " << getSmoothFromList( &Pitch.rawList ) << " " << Pitch.offset_headPos << '\n'; -//// } + headXLine->setText(QString("%1").arg( rawposX, 0, 'f', 1)); // show centimeters + headYLine->setText(QString("%1").arg( rawposY, 0, 'f', 1)); + headZLine->setText(QString("%1").arg( rawposZ, 0, 'f', 1)); - // Pitch - if (Tracker::useFilter) { - rotX = lowPassFilter ( getSmoothFromList( &Pitch.rawList ) - Pitch.offset_headPos - Pitch.initial_headPos, - &Pitch.prevPos, dT, Tracker::Pitch.red ); - } - else { - rotX = getSmoothFromList( &Pitch.rawList ) - Pitch.offset_headPos - Pitch.initial_headPos; } - rotX = Pitch.invert * getOutputFromCurve(&Pitch.curve, rotX, Pitch.NeutralZone, Pitch.MaxInput); - // Yaw - if (Tracker::useFilter) { - rotY = lowPassFilter ( getSmoothFromList( &Yaw.rawList ) - Yaw.offset_headPos - Yaw.initial_headPos, - &Yaw.prevPos, dT, Tracker::Yaw.red ); - } - else { - rotY = getSmoothFromList( &Yaw.rawList ) - Yaw.offset_headPos - Yaw.initial_headPos; + // + // If Center is pressed, copy the current values to the offsets. + // + if (Tracker::do_center && Tracker::set_initial) { + Pitch.offset_headPos = getSmoothFromList( &Pitch.rawList )- Tracker::Pitch.initial_headPos; + Yaw.offset_headPos = getSmoothFromList( &Yaw.rawList ) - Tracker::Yaw.initial_headPos; + Roll.offset_headPos = getSmoothFromList( &Roll.rawList ) - Tracker::Roll.initial_headPos; + X.offset_headPos = getSmoothFromList( &X.rawList ) - Tracker::X.initial_headPos; + Y.offset_headPos = getSmoothFromList( &Y.rawList ) - Tracker::Y.initial_headPos; + Z.offset_headPos = getSmoothFromList( &Z.rawList ) - Tracker::Z.initial_headPos; + + Tracker::do_center = false; } - rotY = Yaw.invert * getOutputFromCurve(&Yaw.curve, rotY, Yaw.NeutralZone, Yaw.MaxInput); - // Roll - if (Tracker::useFilter) { - rotZ = lowPassFilter ( getSmoothFromList( &Roll.rawList ) - Roll.offset_headPos - Roll.initial_headPos, - &Roll.prevPos, dT, Tracker::Roll.red ); - } - else { - rotZ = getSmoothFromList( &Roll.rawList ) - Roll.offset_headPos - Roll.initial_headPos; - } - rotZ = Roll.invert * getOutputFromCurve(&Roll.curve, rotZ, Roll.NeutralZone, Roll.MaxInput); + if (Tracker::do_tracking && Tracker::confid) { - // X - if (Tracker::useFilter) { - posX = lowPassFilter ( getSmoothFromList( &X.rawList ) - X.offset_headPos - X.initial_headPos, - &X.prevPos, dT, Tracker::X.red ); - } - else { - posX = getSmoothFromList( &X.rawList ) - X.offset_headPos - X.initial_headPos; - } - posX = X.invert * getOutputFromCurve(&X.curve, posX, X.NeutralZone, X.MaxInput); + ////// Use this for some debug-output to file... + //// QFile data("output.txt"); + //// if (data.open(QFile::WriteOnly | QFile::Append)) { + //// QTextStream out(&data); + //// out << Pitch.NeutralZone << " " << getDegreesFromRads(rotX) << " " << getOutputFromCurve(&Pitch.curve, getDegreesFromRads(rotX), Pitch.NeutralZone, Pitch.MaxInput) << '\n'; + ////// out << dT << " " << getSmoothFromList( &Pitch.rawList ) << " " << Pitch.offset_headPos << '\n'; + //// } - // Y - if (Tracker::useFilter) { - posY = lowPassFilter ( getSmoothFromList( &Y.rawList ) - Y.offset_headPos - Y.initial_headPos, - &Y.prevPos, dT, Tracker::Y.red ); - } - else { - posY = getSmoothFromList( &Y.rawList ) - Y.offset_headPos - Y.initial_headPos; - } - posY = Y.invert * getOutputFromCurve(&Y.curve, posY, Y.NeutralZone, Y.MaxInput); + // Pitch + if (Tracker::useFilter) { + rotX = lowPassFilter ( getSmoothFromList( &Pitch.rawList ) - Pitch.offset_headPos - Pitch.initial_headPos, + &Pitch.prevPos, dT, Tracker::Pitch.red ); + } + else { + rotX = getSmoothFromList( &Pitch.rawList ) - Pitch.offset_headPos - Pitch.initial_headPos; + } + rotX = Pitch.invert * getOutputFromCurve(&Pitch.curve, rotX, Pitch.NeutralZone, Pitch.MaxInput); - // Z - if (Tracker::useFilter) { - posZ = lowPassFilter ( getSmoothFromList( &Z.rawList ) - Z.offset_headPos - Z.initial_headPos, - &Z.prevPos, dT, Tracker::Z.red ); - } - else { - posZ = getSmoothFromList( &Z.rawList ) - Z.offset_headPos - Z.initial_headPos; - } - posZ = Z.invert * getOutputFromCurve(&Z.curve, posZ, Z.NeutralZone, Z.MaxInput); + // Yaw + if (Tracker::useFilter) { + rotY = lowPassFilter ( getSmoothFromList( &Yaw.rawList ) - Yaw.offset_headPos - Yaw.initial_headPos, + &Yaw.prevPos, dT, Tracker::Yaw.red ); + } + else { + rotY = getSmoothFromList( &Yaw.rawList ) - Yaw.offset_headPos - Yaw.initial_headPos; + } + rotY = Yaw.invert * getOutputFromCurve(&Yaw.curve, rotY, Yaw.NeutralZone, Yaw.MaxInput); - // - // Reset value for the selected axis, if inhibition is active - // - if (Tracker::do_inhibit) { - if (InhibitKey.doPitch) rotX = 0.0f; - if (InhibitKey.doYaw) rotY = 0.0f; - if (InhibitKey.doRoll) rotZ = 0.0f; - if (InhibitKey.doX) posX = 0.0f; - if (InhibitKey.doY) posY = 0.0f; - if (InhibitKey.doZ) posZ = 0.0f; - } + // Roll + if (Tracker::useFilter) { + rotZ = lowPassFilter ( getSmoothFromList( &Roll.rawList ) - Roll.offset_headPos - Roll.initial_headPos, + &Roll.prevPos, dT, Tracker::Roll.red ); + } + else { + rotZ = getSmoothFromList( &Roll.rawList ) - Roll.offset_headPos - Roll.initial_headPos; + } + rotZ = Roll.invert * getOutputFromCurve(&Roll.curve, rotZ, Roll.NeutralZone, Roll.MaxInput); - // - // Send the Virtual Pose to selected Protocol-Server - // - // Free-track - if (selectedClient == FREE_TRACK) { - server_Game->setHeadRotX( rotX ); // degrees - server_Game->setHeadRotY( rotY ); - server_Game->setHeadRotZ( rotZ ); - - server_Game->setHeadPosX( posX ); // centimeters - server_Game->setHeadPosY( posY ); - server_Game->setHeadPosZ( posZ ); - } + // X + if (Tracker::useFilter) { + posX = lowPassFilter ( getSmoothFromList( &X.rawList ) - X.offset_headPos - X.initial_headPos, + &X.prevPos, dT, Tracker::X.red ); + } + else { + posX = getSmoothFromList( &X.rawList ) - X.offset_headPos - X.initial_headPos; + } + posX = X.invert * getOutputFromCurve(&X.curve, posX, X.NeutralZone, X.MaxInput); + + // Y + if (Tracker::useFilter) { + posY = lowPassFilter ( getSmoothFromList( &Y.rawList ) - Y.offset_headPos - Y.initial_headPos, + &Y.prevPos, dT, Tracker::Y.red ); + } + else { + posY = getSmoothFromList( &Y.rawList ) - Y.offset_headPos - Y.initial_headPos; + } + posY = Y.invert * getOutputFromCurve(&Y.curve, posY, Y.NeutralZone, Y.MaxInput); + + // Z + if (Tracker::useFilter) { + posZ = lowPassFilter ( getSmoothFromList( &Z.rawList ) - Z.offset_headPos - Z.initial_headPos, + &Z.prevPos, dT, Tracker::Z.red ); + } + else { + posZ = getSmoothFromList( &Z.rawList ) - Z.offset_headPos - Z.initial_headPos; + } + posZ = Z.invert * getOutputFromCurve(&Z.curve, posZ, Z.NeutralZone, Z.MaxInput); + + // + // Reset value for the selected axis, if inhibition is active + // + if (Tracker::do_inhibit) { + if (InhibitKey.doPitch) rotX = 0.0f; + if (InhibitKey.doYaw) rotY = 0.0f; + if (InhibitKey.doRoll) rotZ = 0.0f; + if (InhibitKey.doX) posX = 0.0f; + if (InhibitKey.doY) posY = 0.0f; + if (InhibitKey.doZ) posZ = 0.0f; + } - // FlightGear - if (server_Game) { - server_Game->setVirtRotX ( rotX ); // degrees - server_Game->setVirtRotY ( rotY ); - server_Game->setVirtRotZ ( rotZ ); - server_Game->setVirtPosX ( posX ); // centimeters - server_Game->setVirtPosY ( posY ); - server_Game->setVirtPosZ ( posZ ); + // + // Send the Virtual Pose to selected Protocol-Server + // + // Free-track + if (selectedClient == FREE_TRACK) { + server_Game->setHeadRotX( rotX ); // degrees + server_Game->setHeadRotY( rotY ); + server_Game->setHeadRotZ( rotZ ); + + server_Game->setHeadPosX( posX ); // centimeters + server_Game->setHeadPosY( posY ); + server_Game->setHeadPosZ( posZ ); + } + + // FlightGear + if (server_Game) { + server_Game->setVirtRotX ( rotX ); // degrees + server_Game->setVirtRotY ( rotY ); + server_Game->setVirtRotZ ( rotZ ); + server_Game->setVirtPosX ( posX ); // centimeters + server_Game->setVirtPosY ( posY ); + server_Game->setVirtPosZ ( posZ ); + } } - } - else { - // - // Go to initial position - // - if (server_Game) { - server_Game->setVirtRotX ( 0.0f ); - server_Game->setVirtRotY ( 0.0f ); - server_Game->setVirtRotZ ( 0.0f ); - server_Game->setVirtPosX ( 0.0f ); - server_Game->setVirtPosY ( 0.0f ); - server_Game->setVirtPosZ ( 0.0f ); + else { + // + // Go to initial position + // + if (server_Game) { + server_Game->setVirtRotX ( 0.0f ); + server_Game->setVirtRotY ( 0.0f ); + server_Game->setVirtRotZ ( 0.0f ); + server_Game->setVirtPosX ( 0.0f ); + server_Game->setVirtPosY ( 0.0f ); + server_Game->setVirtPosZ ( 0.0f ); + } } } + ReleaseMutex(Tracker::hTrackMutex); + server_Game->sendHeadposeToGame(); //for lower cpu load msleep(10); @@ -543,7 +554,8 @@ void Tracker::receiveHeadPose(void *,smEngineHeadPoseData head_pose, smCameraVid // Perform actions, when valid data is received from faceAPI. // Write the Raw headpose-data and add it to the RawList, for processing... // - if( head_pose.confidence > 0 ) { + if (( head_pose.confidence > 0 ) && (WaitForSingleObject(Tracker::hTrackMutex, 100) == WAIT_OBJECT_0) ) { + Tracker::confid = true; // Pitch @@ -574,6 +586,8 @@ void Tracker::receiveHeadPose(void *,smEngineHeadPoseData head_pose, smCameraVid Tracker::confid = false; } + ReleaseMutex(Tracker::hTrackMutex); + // for lower cpu load msleep(10); yieldCurrentThread(); diff --git a/FaceTrackNoIR/tracker.h b/FaceTrackNoIR/tracker.h index b81cf636..6a3fca93 100644 --- a/FaceTrackNoIR/tracker.h +++ b/FaceTrackNoIR/tracker.h @@ -153,6 +153,9 @@ private: static bool do_center; // Center head-position, using the shortkey static bool do_inhibit; // Inhibit DOF-axis, using the shortkey + static HANDLE hTrackMutex; // Prevent reading/writing the headpose simultaneously + + static bool useFilter; static long prevHeadPoseTime; // Time from previous sample -- cgit v1.2.3