From 7c52b9e74692fbe8d31c9069388c52043a67727a Mon Sep 17 00:00:00 2001 From: mm0zct Date: Tue, 25 Jun 2013 00:48:48 +0100 Subject: Added Sixense Razer Hydra --- CMakeLists.txt | 34 +- facetracknoir/rotation.cpp | 35 +- facetracknoir/rotation.h | 42 ++- .../ftnoir_hydra_clientcontrols.ui | 372 +++++++++++++++++++++ ftnoir_tracker_hydra/ftnoir_tracker_hydra.cpp | 155 +++++++++ ftnoir_tracker_hydra/ftnoir_tracker_hydra.h | 89 +++++ .../ftnoir_tracker_hydra_dialog.cpp | 180 ++++++++++ ftnoir_tracker_hydra/ftnoir_tracker_hydra_dll.cpp | 55 +++ 8 files changed, 920 insertions(+), 42 deletions(-) create mode 100644 ftnoir_tracker_hydra/ftnoir_hydra_clientcontrols.ui create mode 100644 ftnoir_tracker_hydra/ftnoir_tracker_hydra.cpp create mode 100644 ftnoir_tracker_hydra/ftnoir_tracker_hydra.h create mode 100644 ftnoir_tracker_hydra/ftnoir_tracker_hydra_dialog.cpp create mode 100644 ftnoir_tracker_hydra/ftnoir_tracker_hydra_dll.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 65e2f01b..c3355d16 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,7 +17,7 @@ endif() IF(WIN32) SET(SDK_SM_FACEAPI_PATH "" CACHE PATH "SeeingMachines FaceAPI SDK path") SET(SDK_RIFT "" CACHE PATH "libOVR path") - SET(SDK_VJOY "" CACHE PATH "VJoy SDK path") + SET(SDK_HYDRA "" CACHE PATH "libSixense path") SET(SDK_VJOY "" CACHE PATH "VJoy SDK path") ENDIF() file(GLOB opentrack-faceapi-wrapper-c "faceapi/*.cpp") @@ -240,7 +240,7 @@ if(NOT SDK_FACEAPI_ONLY) QT4_WRAP_UI(opentrack-tracker-hillcrest-uih ${opentrack-tracker-hillcrest-ui}) QT4_ADD_RESOURCES(opentrack-tracker-hillcrest-rcc ${opentrack-tracker-hillcrest-rc}) - file(GLOB opentrack-tracker-rift-c "ftnoir_tracker_rift/*.cpp") + file(GLOB opentrack-tracker-rift-c "ftnoir_tracker_rift/*.cpp") file(GLOB opentrack-tracker-rift-h "ftnoir_tracker_rift/*.h") QT4_WRAP_CPP(opentrack-tracker-rift-moc ${opentrack-tracker-rift-h}) file(GLOB opentrack-tracker-rift-ui "ftnoir_tracker_rift/*.ui") @@ -248,6 +248,14 @@ if(NOT SDK_FACEAPI_ONLY) QT4_WRAP_UI(opentrack-tracker-rift-uih ${opentrack-tracker-rift-ui}) QT4_ADD_RESOURCES(opentrack-tracker-rift-rcc ${opentrack-tracker-rift-rc}) + file(GLOB opentrack-tracker-hydra-c "ftnoir_tracker_hydra/*.cpp") + file(GLOB opentrack-tracker-hydra-h "ftnoir_tracker_hydra/*.h") + QT4_WRAP_CPP(opentrack-tracker-hydra-moc ${opentrack-tracker-hydra-h}) + file(GLOB opentrack-tracker-hydra-ui "ftnoir_tracker_hydra/*.ui") + file(GLOB opentrack-tracker-hydra-rc "ftnoir_tracker_hydra/*.qrc") + QT4_WRAP_UI(opentrack-tracker-hydra-uih ${opentrack-tracker-hydra-ui}) + QT4_ADD_RESOURCES(opentrack-tracker-hydra-rcc ${opentrack-tracker-hydra-rc}) + file(GLOB opentrack-tracker-faceapi-c "ftnoir_tracker_sm/*.cpp") file(GLOB opentrack-tracker-faceapi-h "ftnoir_tracker_sm/*.h") QT4_WRAP_CPP(opentrack-tracker-faceapi-moc ${opentrack-tracker-faceapi-h}) @@ -453,6 +461,19 @@ endif() endif() endif() + if(SDK_HYDRA) + include_directories("${SDK_HYDRA}/include") + include_directories("${SDK_HYDRA}/include/sixense_utils") + add_library(opentrack-tracker-hydra SHARED ${opentrack-tracker-hydra-c} ${opentrack-tracker-hydra-moc} ${opentrack-tracker-hydra-uih} ${opentrack-tracker-hydra-rcc}) + target_link_libraries(opentrack-tracker-hydra ${MY_QT_LIBS}) + if(WIN32) + target_link_libraries(opentrack-tracker-hydra "${SDK_HYDRA}/lib/win32/release_static/sixense_s.lib" "${SDK_HYDRA}/lib/win32/release_static/sixense_utils_s.lib") + endif() + if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_GNUCC) + SET_TARGET_PROPERTIES(opentrack-tracker-hydra + PROPERTIES LINK_FLAGS "-Wl,--version-script=${CMAKE_SOURCE_DIR}/facetracknoir/posix-version-script.txt") + endif() + endif() if(SDK_HILLCREST) include_directories("${SDK_HILLCREST}/include") if(WIN32) @@ -579,6 +600,15 @@ if(NOT SDK_FACEAPI_ONLY) ) endif() + if(SDK_HYDRA) + install( + TARGETS opentrack-tracker-hydra + RUNTIME DESTINATION . + LIBRARY DESTINATION . + NAMELINK_SKIP + ) + endif() + if(WIN32) if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_GNUCC) file(GLOB mingw-libgcc-s "${SDK_MINGW_PATH}/bin/libgcc_s_*.dll") diff --git a/facetracknoir/rotation.cpp b/facetracknoir/rotation.cpp index f6d16d2d..1a6e1e8e 100644 --- a/facetracknoir/rotation.cpp +++ b/facetracknoir/rotation.cpp @@ -7,42 +7,9 @@ #include "rotation.h" -#include -// ---------------------------------------------------------------------------- -Rotation Rotation::inv() -{ - return Rotation(a,-b,-c,-d); -} -// conversions -// see http://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles -void Rotation::fromEuler(double yaw, double pitch, double roll) -{ - double sin_phi = sin(roll/2.0); - double cos_phi = cos(roll/2.0); - double sin_the = sin(pitch/2.0); - double cos_the = cos(pitch/2.0); - double sin_psi = sin(yaw/2.0); - double cos_psi = cos(yaw/2.0); +// ---------------------------------------------------------------------------- - a = cos_phi*cos_the*cos_psi + sin_phi*sin_the*sin_psi; - b = sin_phi*cos_the*cos_psi - cos_phi*sin_the*sin_psi; - c = cos_phi*sin_the*cos_psi + sin_phi*cos_the*sin_psi; - d = cos_phi*cos_the*sin_psi - sin_phi*sin_the*cos_psi; -} -void Rotation::toEuler(volatile double& yaw, volatile double& pitch, volatile double& roll) -{ - roll = atan2(2.0*(a*b + c*d), 1.0 - 2.0*(b*b + c*c)); - pitch = asin(2.0*(a*c - b*d)); - yaw = atan2(2.0*(a*d + b*c), 1.0 - 2.0*(c*c + d*d)); -} -Rotation operator*(const Rotation& A, const Rotation& B) -{ - return Rotation(A.a*B.a - A.b*B.b - A.c*B.c - A.d*B.d, // quaternion multiplication - A.a*B.b + A.b*B.a + A.c*B.d - A.d*B.c, - A.a*B.c - A.b*B.d + A.c*B.a + A.d*B.b, - A.a*B.d + A.b*B.c - A.c*B.b + A.d*B.a); -} \ No newline at end of file diff --git a/facetracknoir/rotation.h b/facetracknoir/rotation.h index 9dcea285..1a4e705b 100644 --- a/facetracknoir/rotation.h +++ b/facetracknoir/rotation.h @@ -7,7 +7,7 @@ #ifndef ROTATION_H #define ROTATION_H - +#include // ---------------------------------------------------------------------------- class Rotation { friend Rotation operator*(const Rotation& A, const Rotation& B); @@ -16,16 +16,46 @@ public: Rotation(double yaw, double pitch, double roll) { fromEuler(yaw, pitch, roll); } Rotation(double a, double b, double c, double d) : a(a),b(b),c(c),d(d) {} - Rotation inv(); // inverse + Rotation inv(){ // inverse + return Rotation(a,-b,-c,-d); + } + // conversions - void fromEuler(double yaw, double pitch, double roll); - void toEuler(volatile double& yaw, volatile double& pitch, volatile double& roll); - + // see http://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles + void fromEuler(double yaw, double pitch, double roll) + { + double sin_phi = sin(roll/2.0); + double cos_phi = cos(roll/2.0); + double sin_the = sin(pitch/2.0); + double cos_the = cos(pitch/2.0); + double sin_psi = sin(yaw/2.0); + double cos_psi = cos(yaw/2.0); + + a = cos_phi*cos_the*cos_psi + sin_phi*sin_the*sin_psi; + b = sin_phi*cos_the*cos_psi - cos_phi*sin_the*sin_psi; + c = cos_phi*sin_the*cos_psi + sin_phi*cos_the*sin_psi; + d = cos_phi*cos_the*sin_psi - sin_phi*sin_the*cos_psi; + } + + void Rotation::toEuler(double& yaw, double& pitch, double& roll) + { + roll = atan2(2.0*(a*b + c*d), 1.0 - 2.0*(b*b + c*c)); + pitch = asin(2.0*(a*c - b*d)); + yaw = atan2(2.0*(a*d + b*c), 1.0 - 2.0*(c*c + d*d)); + } + protected: double a,b,c,d; // quaternion coefficients }; -Rotation operator*(const Rotation& A, const Rotation& B); // composition of rotations + +Rotation operator*(const Rotation& A, const Rotation& B) +{ + return Rotation(A.a*B.a - A.b*B.b - A.c*B.c - A.d*B.d, // quaternion multiplication + A.a*B.b + A.b*B.a + A.c*B.d - A.d*B.c, + A.a*B.c - A.b*B.d + A.c*B.a + A.d*B.b, + A.a*B.d + A.b*B.c - A.c*B.b + A.d*B.a); +} #endif //ROTATION_H diff --git a/ftnoir_tracker_hydra/ftnoir_hydra_clientcontrols.ui b/ftnoir_tracker_hydra/ftnoir_hydra_clientcontrols.ui new file mode 100644 index 00000000..1daf7a5b --- /dev/null +++ b/ftnoir_tracker_hydra/ftnoir_hydra_clientcontrols.ui @@ -0,0 +1,372 @@ + + + UIHydraControls + + + + 0 + 0 + 411 + 142 + + + + Sixense Hydra tracker settings FaceTrackNoIR + + + + images/FaceTrackNoIR.pngimages/FaceTrackNoIR.png + + + Qt::LeftToRight + + + false + + + + + + + 0 + 85 + + + + Enable Axis + + + + + 10 + 20 + 143 + 60 + + + + + + + + + + + + + + + Pitch: + + + + + + + + + 20 + 16777215 + + + + Qt::LeftToRight + + + + + + + + + + + + + + Yaw: + + + + + + + + + + 20 + 16777215 + + + + Qt::LeftToRight + + + + + + + + + + + + + Roll: + + + + + + + + + 20 + 16777215 + + + + Qt::LeftToRight + + + + + + + + + + + + + + + + + + + + + + + + + + + + + X: + + + + + + + + + 20 + 16777215 + + + + Qt::LeftToRight + + + + + + + + + + + + + + Y: + + + + + + + + + + 20 + 16777215 + + + + Qt::LeftToRight + + + + + + + + + + + + + Z: + + + + + + + + + 20 + 16777215 + + + + Qt::LeftToRight + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + 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 + + + + + + + + + + btnOK + btnCancel + + + + + startEngineClicked() + stopEngineClicked() + cameraSettingsClicked() + + diff --git a/ftnoir_tracker_hydra/ftnoir_tracker_hydra.cpp b/ftnoir_tracker_hydra/ftnoir_tracker_hydra.cpp new file mode 100644 index 00000000..24ffedcd --- /dev/null +++ b/ftnoir_tracker_hydra/ftnoir_tracker_hydra.cpp @@ -0,0 +1,155 @@ +/* Copyright: "i couldn't care less what anyone does with the 5 lines of code i wrote" - mm0zct */ +#include "ftnoir_tracker_hydra.h" +#include "facetracknoir/global-settings.h" +#include "facetracknoir/rotation.h" +#include +#define SIXENSE_STATIC_LIB +#define SIXENSE_UTILS_STATIC_LIB +#include +#include +#ifdef WIN32 +#include +#endif +#include +#include +#include +#include + +Hydra_Tracker::Hydra_Tracker() +{ + bEnableRoll = true; + bEnablePitch = true; + bEnableYaw = true; + bEnableX = true; + bEnableY = true; + bEnableZ = true; + should_quit = false; + for (int i = 0; i < 6; i++) + newHeadPose[i] = 0; +} + +Hydra_Tracker::~Hydra_Tracker() +{ + + sixenseExit(); +} + +/* +void controller_manager_setup_callback( sixenseUtils::ControllerManager::setup_step step ) { + + QMessageBox::warning(0,"OpenTrack Info", "controller manager callback",QMessageBox::Ok,QMessageBox::NoButton); + if( sixenseUtils::getTheControllerManager()->isMenuVisible() ) { + // Ask the controller manager what the next instruction string should be. + std::string controller_manager_text_string = sixenseUtils::getTheControllerManager()->getStepString(); + QMessageBox::warning(0,"OpenTrack Info", controller_manager_text_string.c_str(),QMessageBox::Ok,QMessageBox::NoButton); + // We could also load the supplied controllermanager textures using the filename: sixenseUtils::getTheControllerManager()->getTextureFileName(); + + } +}*/ + +void Hydra_Tracker::StartTracker(QFrame* videoFrame) +{ + //QMessageBox::warning(0,"FaceTrackNoIR Notification", "Tracking loading settings...",QMessageBox::Ok,QMessageBox::NoButton); + loadSettings(); + + // Init sixense + //QMessageBox::warning(0,"OpenTrack Info", "sixense init",QMessageBox::Ok,QMessageBox::NoButton); + sixenseInit(); + //QMessageBox::warning(0,"OpenTrack Info", "sixense init complete, setting controller manager",QMessageBox::Ok,QMessageBox::NoButton); + // Init the controller manager. This makes sure the controllers are present, assigned to left and right hands, and that + // the hemisphere calibration is complete. + //sixenseUtils::getTheControllerManager()->setGameType( sixenseUtils::ControllerManager::ONE_PLAYER_TWO_CONTROLLER ); + //sixenseUtils::getTheControllerManager()->registerSetupCallback( controller_manager_setup_callback ); + //QMessageBox::warning(0,"OpenTrack Info", "controller manager callback registered",QMessageBox::Ok,QMessageBox::NoButton); + return; +} + + +bool Hydra_Tracker::GiveHeadPoseData(double *data) +{ + + sixenseSetActiveBase(0); + sixenseAllControllerData acd; + sixenseGetAllNewestData( &acd ); + //sixenseUtils::getTheControllerManager()->update( &acd ); + + //sixenseControllerData cd; + Rotation quat = Rotation(acd.controllers[0].rot_quat[0],acd.controllers[0].rot_quat[1],acd.controllers[0].rot_quat[2],acd.controllers[0].rot_quat[3]); + double yaw = 0.0f; + double pitch = 0.0f; + double roll = 0.0f; + + quat.toEuler(yaw, pitch, roll); + + newHeadPose[RY] = pitch; + newHeadPose[RZ] = roll; + newHeadPose[RX] = yaw; + + + + newHeadPose[TX] = acd.controllers[0].pos[0]/50.0f; + newHeadPose[TY] = acd.controllers[0].pos[1]/50.0f; + newHeadPose[TZ] = acd.controllers[0].pos[2]/50.0f; + + //if (bEnableX) { + data[TX] = newHeadPose[TX]; + //} + //if (bEnableY) { + data[TY] = newHeadPose[TY]; + //} + //if (bEnableY) { + data[TZ] = newHeadPose[TZ]; + //} + + if (bEnableYaw) { + data[RX] = newHeadPose[RX] * 57.295781f; + } + if (bEnablePitch) { + data[RY] = newHeadPose[RY] * 57.295781f; + } + if (bEnableRoll) { + data[RZ] = newHeadPose[RZ] * 57.295781f; + } + + return true; +} + + +// +// Load the current Settings from the currently 'active' INI-file. +// +void Hydra_Tracker::loadSettings() { + + qDebug() << "FTNoIR_Tracker::loadSettings says: Starting "; + QSettings settings("opentrack"); // 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() << "FTNoIR_Tracker::loadSettings says: iniFile = " << currentFile; + + iniFile.beginGroup ( "Hydra" ); + bEnableRoll = iniFile.value ( "EnableRoll", 1 ).toBool(); + bEnablePitch = iniFile.value ( "EnablePitch", 1 ).toBool(); + bEnableYaw = iniFile.value ( "EnableYaw", 1 ).toBool(); + bEnableX = iniFile.value ( "EnableX", 1 ).toBool(); + bEnableY = iniFile.value ( "EnableY", 1 ).toBool(); + bEnableZ = iniFile.value ( "EnableZ", 1 ).toBool(); + + iniFile.endGroup (); +} + + +//////////////////////////////////////////////////////////////////////////////// +// Factory function that creates instances if the Tracker object. + +// Export both decorated and undecorated names. +// GetTracker - Undecorated name, which can be easily used with GetProcAddress +// Win32 API function. +// _GetTracker@0 - Common name decoration for __stdcall functions in C language. +//#pragma comment(linker, "/export:GetTracker=_GetTracker@0") + +extern "C" FTNOIR_TRACKER_BASE_EXPORT ITracker* CALLING_CONVENTION GetConstructor() +{ + return new Hydra_Tracker; +} diff --git a/ftnoir_tracker_hydra/ftnoir_tracker_hydra.h b/ftnoir_tracker_hydra/ftnoir_tracker_hydra.h new file mode 100644 index 00000000..3f7bf0a8 --- /dev/null +++ b/ftnoir_tracker_hydra/ftnoir_tracker_hydra.h @@ -0,0 +1,89 @@ +#include "ftnoir_tracker_base/ftnoir_tracker_base.h" +#include "ui_ftnoir_hydra_clientcontrols.h" +#include +#include +#include +#include +#include "facetracknoir/global-settings.h" +class Hydra_Tracker : public ITracker +{ +public: + Hydra_Tracker(); + ~Hydra_Tracker(); + + void StartTracker( QFrame *videoframe ); + bool GiveHeadPoseData(double *data); + void loadSettings(); + volatile bool should_quit; + void WaitForExit() { + return; + } +protected: + void run(); // qthread override run method + +private: + bool isCalibrated; + + double newHeadPose[6]; // Structure with new headpose + bool bEnableRoll; + bool bEnablePitch; + bool bEnableYaw; + + bool bEnableX; + bool bEnableY; + bool bEnableZ; + + QMutex mutex; +}; + +// Widget that has controls for FTNoIR protocol client-settings. +class TrackerControls: public QWidget, public ITrackerDialog +{ + Q_OBJECT +public: + + explicit TrackerControls(); + ~TrackerControls(); + void showEvent ( QShowEvent * event ); + + void Initialize(QWidget *parent); + void registerTracker(ITracker *tracker) {}; + void unRegisterTracker() {}; + +private: + Ui::UIHydraControls ui; + void loadSettings(); + void save(); + + /** helper **/ + bool settingsDirty; + +private slots: + void doOK(); + void doCancel(); + void settingChanged() { settingsDirty = true; }; + void settingChanged(int) { settingsDirty = true; }; +}; + +//******************************************************************************************************* +// FaceTrackNoIR Tracker DLL. Functions used to get general info on the Tracker +//******************************************************************************************************* +class FTNoIR_TrackerDll : public Metadata +{ +public: + FTNoIR_TrackerDll(); + ~FTNoIR_TrackerDll(); + + void Initialize(); + + void getFullName(QString *strToBeFilled); + void getShortName(QString *strToBeFilled); + void getDescription(QString *strToBeFilled); + void getIcon(QIcon *icon); + +private: + QString trackerFullName; // Trackers' name and description + QString trackerShortName; + QString trackerDescription; +}; + diff --git a/ftnoir_tracker_hydra/ftnoir_tracker_hydra_dialog.cpp b/ftnoir_tracker_hydra/ftnoir_tracker_hydra_dialog.cpp new file mode 100644 index 00000000..77d4963b --- /dev/null +++ b/ftnoir_tracker_hydra/ftnoir_tracker_hydra_dialog.cpp @@ -0,0 +1,180 @@ +/******************************************************************************** +* FaceTrackNoIR This program is a private project of some enthusiastic * +* gamers from Holland, who don't like to pay much for * +* head-tracking. * +* * +* Copyright (C) 2012 Wim Vriend (Developing) * +* Ron Hendriks (Researching and Testing) * +* * +* Homepage: http://facetracknoir.sourceforge.net/home/default.htm * +* * +* 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 . * +* * +********************************************************************************/ +#include "ftnoir_tracker_hydra.h" +#include "facetracknoir/global-settings.h" + +//******************************************************************************************************* +// FaceTrackNoIR Client Settings-dialog. +//******************************************************************************************************* + +// +// Constructor for server-settings-dialog +// +TrackerControls::TrackerControls() : +QWidget() +{ + ui.setupUi( this ); + + // Connect Qt signals to member-functions + connect(ui.btnOK, SIGNAL(clicked()), this, SLOT(doOK())); + connect(ui.btnCancel, SIGNAL(clicked()), this, SLOT(doCancel())); + + connect(ui.chkEnableRoll, SIGNAL(stateChanged(int)), this, SLOT(settingChanged(int))); + connect(ui.chkEnablePitch, SIGNAL(stateChanged(int)), this, SLOT(settingChanged(int))); + connect(ui.chkEnableYaw, SIGNAL(stateChanged(int)), this, SLOT(settingChanged(int))); +#if 0 + connect(ui.chkEnableX, SIGNAL(stateChanged(int)), this, SLOT(settingChanged(int))); + connect(ui.chkEnableY, SIGNAL(stateChanged(int)), this, SLOT(settingChanged(int))); + connect(ui.chkEnableZ, SIGNAL(stateChanged(int)), this, SLOT(settingChanged(int))); +#endif + // Load the settings from the current .INI-file + loadSettings(); +} + +// +// Destructor for server-dialog +// +TrackerControls::~TrackerControls() { + qDebug() << "~TrackerControls() says: started"; +} + +// +// Initialize tracker-client-dialog +// +void TrackerControls::Initialize(QWidget *parent) { + + QPoint offsetpos(100, 100); + if (parent) { + this->move(parent->pos() + offsetpos); + } + show(); +} + +// +// OK clicked on server-dialog +// +void TrackerControls::doOK() { + save(); + this->close(); +} + +// override show event +void TrackerControls::showEvent ( QShowEvent * event ) { + loadSettings(); +} + +// +// Cancel clicked on server-dialog +// +void TrackerControls::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 TrackerControls::loadSettings() { + +// qDebug() << "loadSettings says: Starting "; + QSettings settings("opentrack"); // 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 ( "Hydra" ); + ui.chkEnableRoll->setChecked(iniFile.value ( "EnableRoll", 1 ).toBool()); + ui.chkEnablePitch->setChecked(iniFile.value ( "EnablePitch", 1 ).toBool()); + ui.chkEnableYaw->setChecked(iniFile.value ( "EnableYaw", 1 ).toBool()); + ui.chkEnableX->setChecked(iniFile.value ( "EnableX", 1 ).toBool()); + ui.chkEnableY->setChecked(iniFile.value ( "EnableY", 1 ).toBool()); + ui.chkEnableZ->setChecked(iniFile.value ( "EnableZ", 1 ).toBool()); + + iniFile.endGroup (); + + settingsDirty = false; +} + +// +// Save the current Settings to the currently 'active' INI-file. +// +void TrackerControls::save() { + QSettings settings("opentrack"); // 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 ( "Hydra" ); + iniFile.setValue ( "EnableRoll", ui.chkEnableRoll->isChecked() ); + iniFile.setValue ( "EnablePitch", ui.chkEnablePitch->isChecked() ); + iniFile.setValue ( "EnableYaw", ui.chkEnableYaw->isChecked() ); + iniFile.setValue ( "EnableX", ui.chkEnableX->isChecked() ); + iniFile.setValue ( "EnableY", ui.chkEnableY->isChecked() ); + iniFile.setValue ( "EnableZ", ui.chkEnableZ->isChecked() ); + iniFile.endGroup (); + + settingsDirty = false; +} +//////////////////////////////////////////////////////////////////////////////// +// Factory function that creates instances if the Tracker-settings dialog object. + +// Export both decorated and undecorated names. +// GetTrackerDialog - Undecorated name, which can be easily used with GetProcAddress +// Win32 API function. +// _GetTrackerDialog@0 - Common name decoration for __stdcall functions in C language. +//#pragma comment(linker, "/export:GetTrackerDialog=_GetTrackerDialog@0") + +extern "C" FTNOIR_TRACKER_BASE_EXPORT ITrackerDialog* CALLING_CONVENTION GetDialog( ) +{ + return new TrackerControls; +} diff --git a/ftnoir_tracker_hydra/ftnoir_tracker_hydra_dll.cpp b/ftnoir_tracker_hydra/ftnoir_tracker_hydra_dll.cpp new file mode 100644 index 00000000..4f5d8b10 --- /dev/null +++ b/ftnoir_tracker_hydra/ftnoir_tracker_hydra_dll.cpp @@ -0,0 +1,55 @@ +/* Copyright: "i couldn't care less what anyone does with the 5 lines of code i wrote" - mm0zct */ +#include "ftnoir_tracker_hydra.h" +#include +#include "facetracknoir/global-settings.h" + +FTNoIR_TrackerDll::FTNoIR_TrackerDll() { + //populate the description strings + trackerFullName = "Hydra"; + trackerShortName = "Hydra"; + trackerDescription = "Hydra"; +} + +FTNoIR_TrackerDll::~FTNoIR_TrackerDll() +{ + +} + +void FTNoIR_TrackerDll::Initialize() +{ + return; +} + +void FTNoIR_TrackerDll::getFullName(QString *strToBeFilled) +{ + *strToBeFilled = trackerFullName; +}; + +void FTNoIR_TrackerDll::getShortName(QString *strToBeFilled) +{ + *strToBeFilled = trackerShortName; +}; + +void FTNoIR_TrackerDll::getDescription(QString *strToBeFilled) +{ + *strToBeFilled = trackerDescription; +}; + +void FTNoIR_TrackerDll::getIcon(QIcon *icon) +{ + *icon = QIcon(":/images/facetracknoir.png"); +}; + +//////////////////////////////////////////////////////////////////////////////// +// Factory function that creates instances if the Tracker object. + +// Export both decorated and undecorated names. +// GetTrackerDll - Undecorated name, which can be easily used with GetProcAddress +// Win32 API function. +// _GetTrackerDll@0 - Common name decoration for __stdcall functions in C language. +//#pragma comment(linker, "/export:GetTrackerDll=_GetTrackerDll@0") + +extern "C" FTNOIR_TRACKER_BASE_EXPORT Metadata* CALLING_CONVENTION GetMetadata() +{ + return new FTNoIR_TrackerDll; +} -- cgit v1.2.3 From 78704527b51e753014911cb002a2d6efda04f0be Mon Sep 17 00:00:00 2001 From: mm0zct Date: Tue, 25 Jun 2013 00:55:25 +0100 Subject: Accidentally borked the CMakeList --- CMakeLists.txt | 3 ++- ftnoir_tracker_hydra/ftnoir_hydra_clientcontrols.ui | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c3355d16..8bf2b09e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,7 +17,8 @@ endif() IF(WIN32) SET(SDK_SM_FACEAPI_PATH "" CACHE PATH "SeeingMachines FaceAPI SDK path") SET(SDK_RIFT "" CACHE PATH "libOVR path") - SET(SDK_HYDRA "" CACHE PATH "libSixense path") SET(SDK_VJOY "" CACHE PATH "VJoy SDK path") + SET(SDK_HYDRA "" CACHE PATH "libSixense path") + SET(SDK_VJOY "" CACHE PATH "VJoy SDK path") ENDIF() file(GLOB opentrack-faceapi-wrapper-c "faceapi/*.cpp") diff --git a/ftnoir_tracker_hydra/ftnoir_hydra_clientcontrols.ui b/ftnoir_tracker_hydra/ftnoir_hydra_clientcontrols.ui index 1daf7a5b..0cee05f0 100644 --- a/ftnoir_tracker_hydra/ftnoir_hydra_clientcontrols.ui +++ b/ftnoir_tracker_hydra/ftnoir_hydra_clientcontrols.ui @@ -189,7 +189,7 @@ - + @@ -208,7 +208,7 @@ - + Z: @@ -216,7 +216,7 @@ - + -- cgit v1.2.3 From cdb407f7b789908e2fbe10e46462d45eced2625f Mon Sep 17 00:00:00 2001 From: mm0zct Date: Tue, 25 Jun 2013 01:44:10 +0100 Subject: Fixed rotation.h --- facetracknoir/facetracknoir.rc | 2 +- facetracknoir/rotation.h | 29 ++++++++++++++++++++--------- 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/facetracknoir/facetracknoir.rc b/facetracknoir/facetracknoir.rc index fcae12b3..655baa9d 100644 --- a/facetracknoir/facetracknoir.rc +++ b/facetracknoir/facetracknoir.rc @@ -1,2 +1,2 @@ -#include "resource.h" +#include IDI_ICON1 ICON "facetracknoir.ico" diff --git a/facetracknoir/rotation.h b/facetracknoir/rotation.h index 1a4e705b..a1500969 100644 --- a/facetracknoir/rotation.h +++ b/facetracknoir/rotation.h @@ -10,7 +10,7 @@ #include // ---------------------------------------------------------------------------- class Rotation { - friend Rotation operator*(const Rotation& A, const Rotation& B); + public: Rotation() : a(1.0),b(0.0),c(0.0),d(0.0) {} Rotation(double yaw, double pitch, double roll) { fromEuler(yaw, pitch, roll); } @@ -38,12 +38,30 @@ public: d = cos_phi*cos_the*sin_psi - sin_phi*sin_the*cos_psi; } - void Rotation::toEuler(double& yaw, double& pitch, double& roll) + void toEuler(double& yaw, double& pitch, double& roll) { roll = atan2(2.0*(a*b + c*d), 1.0 - 2.0*(b*b + c*c)); pitch = asin(2.0*(a*c - b*d)); yaw = atan2(2.0*(a*d + b*c), 1.0 - 2.0*(c*c + d*d)); } + +/* const Rotation operator*(const Rotation& A, const Rotation& B) + { + return Rotation(A.a*B.a - A.b*B.b - A.c*B.c - A.d*B.d, // quaternion multiplication + A.a*B.b + A.b*B.a + A.c*B.d - A.d*B.c, + A.a*B.c - A.b*B.d + A.c*B.a + A.d*B.b, + A.a*B.d + A.b*B.c - A.c*B.b + A.d*B.a); + }*/ + + + const Rotation operator*(const Rotation& B) + { + const Rotation& A = *this; + return Rotation(A.a*B.a - A.b*B.b - A.c*B.c - A.d*B.d, // quaternion multiplication + A.a*B.b + A.b*B.a + A.c*B.d - A.d*B.c, + A.a*B.c - A.b*B.d + A.c*B.a + A.d*B.b, + A.a*B.d + A.b*B.c - A.c*B.b + A.d*B.a); + } protected: double a,b,c,d; // quaternion coefficients @@ -51,11 +69,4 @@ protected: -Rotation operator*(const Rotation& A, const Rotation& B) -{ - return Rotation(A.a*B.a - A.b*B.b - A.c*B.c - A.d*B.d, // quaternion multiplication - A.a*B.b + A.b*B.a + A.c*B.d - A.d*B.c, - A.a*B.c - A.b*B.d + A.c*B.a + A.d*B.b, - A.a*B.d + A.b*B.c - A.c*B.b + A.d*B.a); -} #endif //ROTATION_H -- cgit v1.2.3 From d4e2f529a3e0c0c496eab4b7745fc320de8805c9 Mon Sep 17 00:00:00 2001 From: mm0zct Date: Wed, 26 Jun 2013 00:46:19 +0100 Subject: Various changes and refactoring. Rotation correct for the Hydra, mostly correct for the Rift, Rift looks better in OpenTrack, Hydra looks better in Dirt3. Also rewrote the Rotation code for Quaternions, although it seems broken with and without the changes. Will investigate. -Chris --- ftnoir_tracker_rift/ftnoir_tracker_rift.cpp | 97 ++++++++++++++++++++++++----- 1 file changed, 80 insertions(+), 17 deletions(-) diff --git a/ftnoir_tracker_rift/ftnoir_tracker_rift.cpp b/ftnoir_tracker_rift/ftnoir_tracker_rift.cpp index 9e985444..13336313 100644 --- a/ftnoir_tracker_rift/ftnoir_tracker_rift.cpp +++ b/ftnoir_tracker_rift/ftnoir_tracker_rift.cpp @@ -3,9 +3,20 @@ #include "facetracknoir/global-settings.h" #include "OVR.h" #include +#define SIXENSE_STATIC_LIB +#define SIXENSE_UTILS_STATIC_LIB +#include +#include +#ifdef WIN32 +#include +#endif +#include +#include +#include +#include + using namespace OVR; -bool Rift_Tracker::isInitialised = false; Rift_Tracker::Rift_Tracker() { @@ -27,11 +38,26 @@ Rift_Tracker::Rift_Tracker() Rift_Tracker::~Rift_Tracker() { + + sixenseExit(); pSensor.Clear(); pHMD.Clear(); pManager.Clear(); + System::Destroy(); } +/* +void controller_manager_setup_callback( sixenseUtils::ControllerManager::setup_step step ) { + + QMessageBox::warning(0,"OpenTrack Info", "controller manager callback",QMessageBox::Ok,QMessageBox::NoButton); + if( sixenseUtils::getTheControllerManager()->isMenuVisible() ) { + // Ask the controller manager what the next instruction string should be. + std::string controller_manager_text_string = sixenseUtils::getTheControllerManager()->getStepString(); + QMessageBox::warning(0,"OpenTrack Info", controller_manager_text_string.c_str(),QMessageBox::Ok,QMessageBox::NoButton); + // We could also load the supplied controllermanager textures using the filename: sixenseUtils::getTheControllerManager()->getTextureFileName(); + + } +}*/ void Rift_Tracker::StartTracker(QFrame* videoFrame) { @@ -40,11 +66,7 @@ void Rift_Tracker::StartTracker(QFrame* videoFrame) // // Startup the Oculus SDK device handling, use the first Rift sensor we find. // - if(!isInitialised){ - System::Init(Log::ConfigureDefaultLog(LogMask_All)); - isInitialised = true; - } - + System::Init(Log::ConfigureDefaultLog(LogMask_All)); pManager = *DeviceManager::Create(); DeviceEnumerator& enumerator = pManager->EnumerateDevices(); if (enumerator.IsAvailable()) @@ -58,34 +80,75 @@ void Rift_Tracker::StartTracker(QFrame* videoFrame) }else{ QMessageBox::warning(0,"FaceTrackNoIR Error", "Unable to find Rift tracker",QMessageBox::Ok,QMessageBox::NoButton); } - SFusion.SetYawCorrectionEnabled(true); - SFusion.SetMagReference(); - } + isCalibrated = false; + MagCal.BeginAutoCalibration(SFusion); + SFusion.SetMagReference(SFusion.GetOrientation()); + } + // Init sixense + //QMessageBox::warning(0,"OpenTrack Info", "sixense init",QMessageBox::Ok,QMessageBox::NoButton); + sixenseInit(); + //QMessageBox::warning(0,"OpenTrack Info", "sixense init complete, setting controller manager",QMessageBox::Ok,QMessageBox::NoButton); + // Init the controller manager. This makes sure the controllers are present, assigned to left and right hands, and that + // the hemisphere calibration is complete. + //sixenseUtils::getTheControllerManager()->setGameType( sixenseUtils::ControllerManager::ONE_PLAYER_TWO_CONTROLLER ); + //sixenseUtils::getTheControllerManager()->registerSetupCallback( controller_manager_setup_callback ); + //QMessageBox::warning(0,"OpenTrack Info", "controller manager callback registered",QMessageBox::Ok,QMessageBox::NoButton); return; } + bool Rift_Tracker::GiveHeadPoseData(double *data) { if (pHMD.GetPtr() != NULL) { + + if (SFusion.IsMagReady() && !isCalibrated ){ + SFusion.SetYawCorrectionEnabled(true); + QMessageBox::warning(0,"OpenTrack Info", "Calibrated magnetic sensor",QMessageBox::Ok,QMessageBox::NoButton); + }else{ + if(isCalibrated){ + isCalibrated = false; + QMessageBox::warning(0,"OpenTrack Info", "Lost magnetic calibration",QMessageBox::Ok,QMessageBox::NoButton); + } + } + + // Magnetometer calibration procedure + MagCal.UpdateAutoCalibration(SFusion); Quatf hmdOrient = SFusion.GetOrientation(); float yaw = 0.0f; float pitch = 0.0f; float roll = 0.0f; - hmdOrient.GetEulerAngles(&yaw, &pitch , &roll); + //hmdOrient.GetEulerAngles< Axis_X, Axis_Y, Axis_Z>(&pitch, &yaw, &roll); + //hmdOrient.GetEulerAngles< Axis_X, Axis_Z, Axis_Y>(&pitch, &roll, &yaw); + hmdOrient.GetEulerAngles< Axis_Y, Axis_X, Axis_Z>(&yaw, &pitch, &roll); + //hmdOrient.GetEulerAngles< Axis_Y, Axis_Z, Axis_X>(&yaw, &roll, &pitch); + //hmdOrient.GetEulerAngles< Axis_Z, Axis_X, Axis_Y>(&roll, &pitch, &yaw); + //hmdOrient.GetEulerAngles< Axis_Z, Axis_Y, Axis_X>(&roll, &yaw, &pitch); newHeadPose[RY] =pitch; newHeadPose[RZ] = roll; newHeadPose[RX] = yaw; -#if 0 - if (bEnableX) { + + + sixenseSetActiveBase(0); + sixenseAllControllerData acd; + sixenseGetAllNewestData( &acd ); + //sixenseUtils::getTheControllerManager()->update( &acd ); +#if 1 + sixenseControllerData cd; + + newHeadPose[TX] = acd.controllers[0].pos[0]/50.0f; + newHeadPose[TY] = acd.controllers[0].pos[1]/50.0f; + newHeadPose[TZ] = acd.controllers[0].pos[2]/50.0f; + + //if (bEnableX) { data[TX] = newHeadPose[TX]; - } - if (bEnableY) { + //} + //if (bEnableY) { data[TY] = newHeadPose[TY]; - } - if (bEnableY) { + //} + //if (bEnableY) { data[TZ] = newHeadPose[TZ]; - } + //} #endif if (bEnableYaw) { data[RX] = newHeadPose[RX] * 57.295781f; -- cgit v1.2.3