From 7dc20f380c80b1b0597e619e66d23921f0309aa0 Mon Sep 17 00:00:00 2001 From: Wim Vriend Date: Tue, 8 Mar 2011 22:10:06 +0000 Subject: Start after update 1.5 Begin placing faceAPI in DLL git-svn-id: svn+ssh://svn.code.sf.net/p/facetracknoir/code@52 19e81ba0-9b1a-49c3-bd6c-561e1906d5fb --- FaceTrackNoIR/FTNServer.cpp | 294 ++++++++++++++++++++++++++++++ FaceTrackNoIR/FTNServer.h | 107 +++++++++++ FaceTrackNoIR/FTNoIR_FTNServerControls.ui | 261 ++++++++++++++++++++++++++ FaceTrackNoIR/FaceTrackNoIR.cpp | 4 +- FaceTrackNoIR/tracker.cpp | 77 +++++--- FaceTrackNoIR/tracker.h | 33 +++- 6 files changed, 744 insertions(+), 32 deletions(-) create mode 100644 FaceTrackNoIR/FTNServer.cpp create mode 100644 FaceTrackNoIR/FTNServer.h create mode 100644 FaceTrackNoIR/FTNoIR_FTNServerControls.ui (limited to 'FaceTrackNoIR') diff --git a/FaceTrackNoIR/FTNServer.cpp b/FaceTrackNoIR/FTNServer.cpp new file mode 100644 index 00000000..101d06a5 --- /dev/null +++ b/FaceTrackNoIR/FTNServer.cpp @@ -0,0 +1,294 @@ +/******************************************************************************** +* FaceTrackNoIR This program is a private project of the some enthusiastic * +* gamers from Holland, who don't like to pay much for * +* head-tracking. * +* * +* Copyright (C) 2010 Wim Vriend (Developing) * +* Ron Hendriks (Researching and Testing) * +* * +* Homepage * +* * +* This program is free software; you can redistribute it and/or modify it * +* under the terms of the GNU General Public License as published by the * +* Free Software Foundation; either version 3 of the License, or (at your * +* option) any later version. * +* * +* This program is distributed in the hope that it will be useful, but * +* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * +* more details. * +* * +* You should have received a copy of the GNU General Public License along * +* with this program; if not, see . * +* * +* FTNServer FTNServer is the Class, that communicates headpose-data * +* to another FaceTrackNoIR program, using UDP. * +* It is based on the (Linux) example made by Melchior FRANZ. * +********************************************************************************/ +/* + Modifications (last one on top): + 20101224 - WVR: Base class is no longer inheriting QThread. sendHeadposeToGame + is called from run() of Tracker.cpp +*/ +#include +#include +#include "FTNServer.h" +#include "Tracker.h" +#include + +/** constructor **/ +FTNServer::FTNServer( Tracker *parent ) { + + // Save the parent + headTracker = parent; + loadSettings(); +} + +/** destructor **/ +FTNServer::~FTNServer() { + if (inSocket != 0) { + inSocket->close(); + delete inSocket; + } + + if (outSocket != 0) { + outSocket->close(); + delete outSocket; + } +} + +// +// Update Headpose in Game. +// +void FTNServer::sendHeadposeToGame() { +int no_bytes; +QHostAddress sender; +quint16 senderPort; + + // + // Create UDP-sockets if they don't exist already. + // They must be created here, because they must be in the Tracker thread (Tracker::run()) + // + if (inSocket == 0) { + qDebug() << "FTNServer::sendHeadposeToGame creating sockets"; + inSocket = new QUdpSocket(); + // Connect the inSocket to the port, to receive messages + if (!inSocket->bind(QHostAddress::Any, destPort+1)) { + qDebug() << "FTNServer::writePendingDatagrams says: unable to bind inSocket!"; + delete inSocket; + inSocket = 0; + } + } + + if (outSocket == 0) { + outSocket = new QUdpSocket(); + } + + // + // Copy the Raw measurements directly to the client. + // + TestData.x = virtPosX; + TestData.y = virtPosY; + TestData.z = virtPosZ; + TestData.pitch = virtRotX; + TestData.yaw = virtRotY; + TestData.roll = virtRotZ; + + // + // Try to send an UDP-message to the receiver + // + + //! [1] + no_bytes = outSocket->writeDatagram((const char *) &TestData, sizeof( TestData ), destIP, destPort); + if ( no_bytes > 0) { +// qDebug() << "FTNServer::writePendingDatagrams says: bytes send =" << no_bytes << sizeof( double ); + } + else { + qDebug() << "FTNServer::writePendingDatagrams says: nothing sent!"; + } + + // + // Receiver may send data, so we must read that here. + // + if (inSocket != 0) { + while (inSocket->hasPendingDatagrams()) { + + QByteArray datagram; + datagram.resize(inSocket->pendingDatagramSize()); + + inSocket->readDatagram( (char * ) &cmd, sizeof(cmd), &sender, &senderPort); + + fg_cmd = cmd; // Let's just accept that command for now... + if ( cmd > 0 ) { + qDebug() << "FTNServer::sendHeadposeToGame hasPendingDatagrams, cmd = " << cmd; + headTracker->handleGameCommand ( cmd ); // Send it upstream, for the Tracker to handle + } + } + } +} + +// +// Check if the Client DLL exists and load it (to test it), if so. +// Returns 'true' if all seems OK. +// +bool FTNServer::checkServerInstallationOK( HANDLE handle ) +{ + // Init. the data + TestData.x = 0.0f; + TestData.y = 0.0f; + TestData.z = 0.0f; + TestData.yaw = 0.0f; + TestData.pitch = 0.0f; + TestData.roll = 0.0f; +// TestData.status = 0; + fg_cmd = 1; + + inSocket = 0; + outSocket = 0; + + return true; +} + +// +// Load the current Settings from the currently 'active' INI-file. +// +void FTNServer::loadSettings() { + + QSettings settings("Abbequerque Inc.", "FaceTrackNoIR"); // Registry settings (in HK_USER) + + QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString(); + QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file) + + iniFile.beginGroup ( "FTN" ); + + QString destAddr = iniFile.value ( "IP-1", 192 ).toString() + "." + iniFile.value ( "IP-2", 168 ).toString() + "." + iniFile.value ( "IP-3", 2 ).toString() + "." + iniFile.value ( "IP-4", 1 ).toString(); + destIP = QHostAddress( destAddr ); + destPort = iniFile.value ( "PortNumber", 5550 ).toInt(); + + iniFile.endGroup (); +} + +// +// Constructor for server-settings-dialog +// +FTNServerControls::FTNServerControls( QWidget *parent, Qt::WindowFlags f ) : +QWidget( parent , f) +{ + ui.setupUi( this ); + + QPoint offsetpos(100, 100); + this->move(parent->pos() + offsetpos); + + // Connect Qt signals to member-functions + connect(ui.btnOK, SIGNAL(clicked()), this, SLOT(doOK())); + connect(ui.btnCancel, SIGNAL(clicked()), this, SLOT(doCancel())); + connect(ui.spinIPFirstNibble, SIGNAL(valueChanged(int)), this, SLOT(settingChanged())); + connect(ui.spinIPSecondNibble, SIGNAL(valueChanged(int)), this, SLOT(settingChanged())); + connect(ui.spinIPThirdNibble, SIGNAL(valueChanged(int)), this, SLOT(settingChanged())); + connect(ui.spinIPFourthNibble, SIGNAL(valueChanged(int)), this, SLOT(settingChanged())); + connect(ui.spinPortNumber, SIGNAL(valueChanged(int)), this, SLOT(settingChanged())); + + // Load the settings from the current .INI-file + loadSettings(); +} + +// +// Destructor for server-dialog +// +FTNServerControls::~FTNServerControls() { + qDebug() << "~FTNServerControls() says: started"; +} + +// +// OK clicked on server-dialog +// +void FTNServerControls::doOK() { + save(); + this->close(); +} + +// override show event +void FTNServerControls::showEvent ( QShowEvent * event ) { + loadSettings(); +} + +// +// Cancel clicked on server-dialog +// +void FTNServerControls::doCancel() { + // + // Ask if changed Settings should be saved + // + if (settingsDirty) { + int ret = QMessageBox::question ( this, "Settings have changed", "Do you want to save the settings?", QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel, QMessageBox::Discard ); + + qDebug() << "doCancel says: answer =" << ret; + + switch (ret) { + case QMessageBox::Save: + save(); + this->close(); + break; + case QMessageBox::Discard: + this->close(); + break; + case QMessageBox::Cancel: + // Cancel was clicked + break; + default: + // should never be reached + break; + } + } + else { + this->close(); + } +} + +// +// Load the current Settings from the currently 'active' INI-file. +// +void FTNServerControls::loadSettings() { + +// qDebug() << "loadSettings says: Starting "; + QSettings settings("Abbequerque Inc.", "FaceTrackNoIR"); // Registry settings (in HK_USER) + + QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString(); + QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file) + +// qDebug() << "loadSettings says: iniFile = " << currentFile; + + iniFile.beginGroup ( "FTN" ); + ui.spinIPFirstNibble->setValue( iniFile.value ( "IP-1", 192 ).toInt() ); + ui.spinIPSecondNibble->setValue( iniFile.value ( "IP-2", 168 ).toInt() ); + ui.spinIPThirdNibble->setValue( iniFile.value ( "IP-3", 2 ).toInt() ); + ui.spinIPFourthNibble->setValue( iniFile.value ( "IP-4", 1 ).toInt() ); + + ui.spinPortNumber->setValue( iniFile.value ( "PortNumber", 5550 ).toInt() ); + iniFile.endGroup (); + + settingsDirty = false; +} + +// +// Save the current Settings to the currently 'active' INI-file. +// +void FTNServerControls::save() { + + QSettings settings("Abbequerque Inc.", "FaceTrackNoIR"); // Registry settings (in HK_USER) + + QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString(); + QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file) + + iniFile.beginGroup ( "FTN" ); + iniFile.setValue ( "IP-1", ui.spinIPFirstNibble->value() ); + iniFile.setValue ( "IP-2", ui.spinIPSecondNibble->value() ); + iniFile.setValue ( "IP-3", ui.spinIPThirdNibble->value() ); + iniFile.setValue ( "IP-4", ui.spinIPFourthNibble->value() ); + iniFile.setValue ( "PortNumber", ui.spinPortNumber->value() ); + iniFile.endGroup (); + + settingsDirty = false; +} + +//END diff --git a/FaceTrackNoIR/FTNServer.h b/FaceTrackNoIR/FTNServer.h new file mode 100644 index 00000000..f392e708 --- /dev/null +++ b/FaceTrackNoIR/FTNServer.h @@ -0,0 +1,107 @@ +/******************************************************************************** +* FaceTrackNoIR This program is a private project of the some enthusiastic * +* gamers from Holland, who don't like to pay much for * +* head-tracking. * +* * +* Copyright (C) 2010 Wim Vriend (Developing) * +* Ron Hendriks (Researching and Testing) * +* * +* Homepage * +* * +* This program is free software; you can redistribute it and/or modify it * +* under the terms of the GNU General Public License as published by the * +* Free Software Foundation; either version 3 of the License, or (at your * +* option) any later version. * +* * +* This program is distributed in the hope that it will be useful, but * +* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * +* more details. * +* * +* You should have received a copy of the GNU General Public License along * +* with this program; if not, see . * +* * +* FTNServer FTNServer is the Class, that communicates headpose-data * +* to FlightGear, using UDP. * +* It is based on the (Linux) example made by Melchior FRANZ. * +********************************************************************************/ +#pragma once +#ifndef INCLUDED_FTNSERVER_H +#define INCLUDED_FTNSERVER_H + +#include "FTNoIR_cxx_protocolserver.h" +#include "..\ftnoir_tracker_base\ftnoir_tracker_base.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; +using namespace v4friend::ftnoir; + +#include "ui_FTNoIR_FTNServercontrols.h" + +class Tracker; // pre-define parent-class to avoid circular includes + +class FTNServer : public ProtocolServerBase { + Q_OBJECT + +public: + + // public member methods + FTNServer( Tracker *parent ); + ~FTNServer(); + + // protected member methods +protected: + bool checkServerInstallationOK( HANDLE handle ); + void sendHeadposeToGame(); + void setVirtPosX(float pos) { virtPosX = pos; } + void setVirtPosY(float pos) { virtPosY = pos; } + void setVirtPosZ(float pos) { virtPosZ = pos; } + +private: + Tracker *headTracker; // For upstream messages... + THeadPoseData TestData; + QUdpSocket *inSocket; // Receive from FligthGear + QUdpSocket *outSocket; // Send to FligthGear + qint32 cmd; + qint32 fg_cmd; // Command from FlightGear + QHostAddress destIP; // Destination IP-address + int destPort; // Destination port-number + void loadSettings(); +}; + +// Widget that has controls for FTNoIR protocol server-settings. +class FTNServerControls: public QWidget, public Ui::UICFTNServerControls +{ + Q_OBJECT +public: + + explicit FTNServerControls( QWidget *parent=0, Qt::WindowFlags f=0 ); + virtual ~FTNServerControls(); + void showEvent ( QShowEvent * event ); + +private: + Ui::UICFTNServerControls ui; + void loadSettings(); + void save(); + + /** helper **/ + bool settingsDirty; + +private slots: + void doOK(); + void doCancel(); + void settingChanged() { settingsDirty = true; }; +}; + + + +#endif//INCLUDED_FTNSERVER_H +//END diff --git a/FaceTrackNoIR/FTNoIR_FTNServerControls.ui b/FaceTrackNoIR/FTNoIR_FTNServerControls.ui new file mode 100644 index 00000000..44c7e99f --- /dev/null +++ b/FaceTrackNoIR/FTNoIR_FTNServerControls.ui @@ -0,0 +1,261 @@ + + + UICFTNServerControls + + + + 0 + 0 + 411 + 156 + + + + FTNoIR protocol settings FaceTrackNoIR + + + + images/FaceTrackNoIR.icoimages/FaceTrackNoIR.ico + + + Qt::LeftToRight + + + false + + + + + + + + + 60 + 16777215 + + + + 255 + + + 1 + + + + + + + + 60 + 16777215 + + + + 255 + + + 1 + + + + + + + + 60 + 16777215 + + + + 255 + + + 1 + + + + + + + + 60 + 16777215 + + + + 255 + + + 1 + + + + + + + IP-address remote PC + + + + + + + Port-number + + + + + + + 5550 + + + 10000 + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + Enter IP-address and port-number for the remote PC. + + + true + + + + + + + Remember: you may have to change firewall-settings too! + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + QLayout::SetDefaultConstraint + + + + + + 0 + 0 + + + + + 100 + 0 + + + + + 100 + 16777215 + + + + OK + + + + + + + + 0 + 0 + + + + + 100 + 0 + + + + + 100 + 16777215 + + + + Cancel + + + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 10 + 20 + + + + + + + + + + spinIPFirstNibble + spinIPSecondNibble + spinIPThirdNibble + spinIPFourthNibble + spinPortNumber + btnOK + btnCancel + + + + + startEngineClicked() + stopEngineClicked() + cameraSettingsClicked() + + diff --git a/FaceTrackNoIR/FaceTrackNoIR.cpp b/FaceTrackNoIR/FaceTrackNoIR.cpp index 7197a5f7..d8184fff 100644 --- a/FaceTrackNoIR/FaceTrackNoIR.cpp +++ b/FaceTrackNoIR/FaceTrackNoIR.cpp @@ -398,7 +398,7 @@ void FaceTrackNoIR::loadSettings() { // Put the filename in the window-title. // QFileInfo pathInfo ( currentFile ); - setWindowTitle ( "FaceTrackNoIR (1.5) - " + pathInfo.fileName() ); + setWindowTitle ( "FaceTrackNoIR (1.6) - " + pathInfo.fileName() ); // // Get a List of all the INI-files in the (currently active) Settings-folder. @@ -492,7 +492,7 @@ void FaceTrackNoIR::startTracker( ) { // Show the video widget ui.video_frame->show(); - _display = new VideoDisplayWidget( tracker->getEngine(), ui.video_frame ); + _display = new VideoDisplayWidget( tracker->getEngine(), ui.video_frame, 0 ); l = new QVBoxLayout(ui.video_frame); l->setMargin(0); l->setSpacing(0); diff --git a/FaceTrackNoIR/tracker.cpp b/FaceTrackNoIR/tracker.cpp index 6455f9b6..2571be40 100644 --- a/FaceTrackNoIR/tracker.cpp +++ b/FaceTrackNoIR/tracker.cpp @@ -55,8 +55,8 @@ #define USE_HEADPOSE_CALLBACK //#define USE_DEBUG_CLIENT -using namespace sm::faceapi; -using namespace sm::faceapi::qt; +//using namespace sm::faceapi; +//using namespace sm::faceapi::qt; // Flags bool Tracker::confid = false; @@ -104,27 +104,60 @@ QLibrary *filterLib; Tracker::hTrackMutex = CreateMutexA(NULL, false, "HeadPose_mutex"); + // + // Initialize the headpose-data + // + Tracker::Yaw.initHeadPoseData(); + Tracker::Pitch.initHeadPoseData(); + Tracker::Roll.initHeadPoseData(); + Tracker::X.initHeadPoseData(); + Tracker::Y.initHeadPoseData(); + Tracker::Z.initHeadPoseData(); + + // + // Start the selected Tracker-engine + // switch (selectedTracker) { case FT_SM_FACEAPI: - try { - // Initialize the faceAPI Qt library - sm::faceapi::qt::initialize(); - smLoggingSetFileOutputEnable( false ); - - // Initialize the API - faceapi_scope = new APIScope; - - // Create head-tracking engine v2 using first detected webcam - CameraInfo::registerType(SM_API_CAMERA_TYPE_WDM); - _engine = QSharedPointer(new HeadTrackerV2()); - - // starts the faceapi engine - _engine->start(); - } - catch (sm::faceapi::Error &e) - { - /* ERROR with camera */ - QMessageBox::warning(0,"faceAPI Error",e.what(),QMessageBox::Ok,QMessageBox::NoButton); + //try { + // // Initialize the faceAPI Qt library + // sm::faceapi::qt::initialize(); + // smLoggingSetFileOutputEnable( false ); + + // // Initialize the API + // faceapi_scope = new APIScope(); + + // //if (APIScope::internalQtGuiIsDisabled()){ + // // QMessageBox::warning(0,"faceAPI Error","Something Bad",QMessageBox::Ok,QMessageBox::NoButton); + // //} + + // // Create head-tracking engine v2 using first detected webcam + // CameraInfo::registerType(SM_API_CAMERA_TYPE_WDM); + // _engine = QSharedPointer(new HeadTrackerV2()); + + // // starts the faceapi engine + // _engine->start(); + //} + //catch (sm::faceapi::Error &e) + //{ + // /* ERROR with camera */ + // QMessageBox::warning(0,"faceAPI Error",e.what(),QMessageBox::Ok,QMessageBox::NoButton); + //} + trackerLib = new QLibrary("FTNoIR_Tracker_SM.dll"); + + getIT = (importGetTracker) trackerLib->resolve("GetTracker"); + + if (getIT) { + ITrackerPtr ptrXyz(getIT()); + if (ptrXyz) + { + pTracker = ptrXyz; + pTracker->Initialize(); + qDebug() << "Tracker::setup Function Resolved!"; + } + } + else { + QMessageBox::warning(0,"FaceTrackNoIR Error", "DLL not loaded",QMessageBox::Ok,QMessageBox::NoButton); } break; @@ -681,7 +714,7 @@ void Tracker::run() { //for lower cpu load usleep(10000); - yieldCurrentThread(); +// yieldCurrentThread(); } } diff --git a/FaceTrackNoIR/tracker.h b/FaceTrackNoIR/tracker.h index 3eeae2f2..bfed3cd4 100644 --- a/FaceTrackNoIR/tracker.h +++ b/FaceTrackNoIR/tracker.h @@ -23,7 +23,7 @@ #ifndef __TRACKER_H__ #define __TRACKER_H__ -#include +//#include #include #include #include @@ -46,7 +46,7 @@ #include "FTNServer.h" // FaceTrackNoIR-server (for client-server) #include "FTNoIR_cxx_protocolserver.h" -#include "FTNoIR_Tracker_base.h" +#include "..\ftnoir_tracker_base\FTNoIR_Tracker_base.h" #include "FTNoIR_Filter_base.h" #include "AutoClosePtr.h" @@ -94,14 +94,31 @@ class FaceTrackNoIR; // pre-define parent-class to avoid circular includes // // Structure to hold all variables concerning one of 6 DOF's // -struct THeadPoseDOF { +class THeadPoseDOF { +public: + void initHeadPoseData(){ + headPos = 0.0f; + initial_headPos = 0.0f; + offset_headPos = 0.0f; + invert = 0.0f; + red = 0.0f; + rawList.clear(); + maxItems = 10.0f; + prevPos = 0.0f; + prevRawPos = 0.0f; +// curve.??? + NeutralZone = 0; + MaxInput = 0; + confidence = 0.0f; + newSample = FALSE; + } float headPos; // Current position (from faceTracker, radials or meters) float initial_headPos; // Position on startup (first valid value) float offset_headPos; // Offset for centering float invert; // Invert measured value (= 1.0f or -1.0f) float red; // Reduction factor (used for EWMA-filtering, between 0.0f and 1.0f) QList rawList; // List of 'n' headPos values (used for moving average) - int maxItems; // Maximum number of elements is rawList + int maxItems; // Maximum number of elements in rawList float prevPos; // Previous Position float prevRawPos; // Previous Raw Position QPainterPath curve; // Bezier curve to translate input -> output @@ -138,10 +155,10 @@ private: FTNoIR_Client selectedClient; FTNoIR_Face_Tracker selectedTracker; - /** face api variables **/ - APIScope *faceapi_scope; - QSharedPointer _engine; - smEngineHandle _engine_handle; + ///** face api variables **/ +// APIScope *faceapi_scope; + // QSharedPointer _engine; + //smEngineHandle _engine_handle; static ITrackerPtr pTracker; // Pointer to Tracker instance (in DLL) static IFilterPtr pFilter; // Pointer to Filter instance (in DLL) -- cgit v1.2.3