diff --git a/CMake/FindVRPN.cmake b/CMake/FindVRPN.cmake new file mode 100644 index 0000000000000000000000000000000000000000..e9091b9d1b007273a9f3e46c492cec43ea3b8ded --- /dev/null +++ b/CMake/FindVRPN.cmake @@ -0,0 +1,37 @@ +find_path(VRPN_INCLUDE_DIR + NAMES + vrpn_Configure.h + ) + +find_library(VRPN_LIBRARY + NAMES + vrpn + vrpnd) + +find_library(VRPN_QUAT_LIBRARY + NAMES + quat + quatd) + +set(VRPN_INCLUDE_DIRS "${VRPN_INCLUDE_DIR}") +set(VRPN_LIBRARIES "${VRPN_LIBRARY} ${VRPN_QUAT_LIBRARY}") + +include(FindPackageHandleStandardArgs) + +find_package_handle_standard_args(VRPN + REQUIRED_VARS + VRPN_INCLUDE_DIR + VRPN_LIBRARY + VRPN_QUAT_LIBRARY) + +mark_as_advanced( + VRPN_INCLUDE_DIR + VRPN_LIBRARY + VRPN_QUAT_LIBRARY) + +if(VRPN_FOUND AND NOT TARGET vrpn::vrpn) + add_library(vrpn::vrpn INTERFACE IMPORTED) + set_target_properties(vrpn::vrpn PROPERTIES + INTERFACE_LINK_LIBRARIES "${VRPN_LIBRARY};${VRPN_QUAT_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES "${VRPN_INCLUDE_DIR}") +endif() diff --git a/CMake/SuperBuild/External_VRPN.cmake b/CMake/SuperBuild/External_VRPN.cmake index e6945d55d9975d189abe9ef1df2c35f272e4d1b4..f7c700d6e5f0424605d199e6d54c2a2f666b2a1c 100644 --- a/CMake/SuperBuild/External_VRPN.cmake +++ b/CMake/SuperBuild/External_VRPN.cmake @@ -2,7 +2,7 @@ # Copyright 2015 by Kitware and RPI. See toplevel LICENSE.txt for details. ########################################################################### -set(VRPN_TAG 47ce887dfcf4d9a517c2416a9dcdf7bf5fdd0cb4) +set(VRPN_TAG f733f16b7f978ffdcc722a453a0ed55e8c634cd7) set(VRPN_REPOSITORY https://github.com/sradigan/vrpn.git) # Make sure this file is included only once @@ -37,20 +37,6 @@ if(NOT DEFINED ${proj}_DIR) ) endif() - set(CMAKE_GENERAL_EXTERNAL_PROJECT_ARGS) - if(SimMedTK_USE_PHANTOM_OMNI) - simmedtk_find_package(OpenHaptics QUIET) - if(OPENHAPTICS_FOUND) - list(APPEND CMAKE_GENERAL_EXTERNAL_PROJECT_ARGS - -DVRPN_USE_PHANTOM_SERVER:BOOL=ON - -DOpenHaptics_DIR:PATH=${OpenHaptics_DIR} - -DVRPN_GPL_SERVER:BOOL=ON - -DVRPN_USE_HDAPI:BOOL=ON - -DVRPN_USE_HID:BOOL=ON - ) - endif(OPENHAPTICS_FOUND) - endif() - # message(STATUS "Adding project:${proj}") ExternalProject_Add(${proj} SOURCE_DIR ${CMAKE_BINARY_DIR}/SuperBuild/${proj} @@ -65,10 +51,13 @@ if(NOT DEFINED ${proj}_DIR) -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE} -DCMAKE_CXX_FLAGS:STRING=${ep_common_cxx_flags} -DCMAKE_C_FLAGS:STRING=${ep_common_c_flags} - -DBUILD_SHARED_LIBS:BOOL=${SimMedTK_BUILD_SHARED_LIBS} + -DBUILD_SHARED_LIBS:BOOL=OFF + -DVRPN_USE_SHARED_LIBRARY:BOOL=OFF -DCMAKE_INCLUDE_PATH:STRING=${SimMedTK_CMAKE_INCLUDE_PATH} -DCMAKE_LIBRARY_PATH:STRING=${SimMedTK_CMAKE_LIBRARY_PATH} -DVRPN_SUBPROJECT_BUILD:BOOL=ON + -DVRPN_BUILD_CLIENT_LIBRARY:BOOL=ON + -DVRPN_BUILD_SERVER_LIBRARY:BOOL=ON -DVRPN_INSTALL:BOOL=OFF -DVRPN_BUILD_PYTHON:BOOL=OFF -DVRPN_USE_GPM_MOUSE:BOOL=OFF diff --git a/CMakeLists.txt b/CMakeLists.txt index 1d0dff3ae0208784d6f24825acbb44f6c712c3b7..952b9df9817dd9e2a546af5705c6828862eb17be 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -209,6 +209,12 @@ if(SimMedTK_USE_PHANTOM_OMNI) find_package(OpenHaptics) endif() +if(SimMedTK_USE_PHANTOM_OMNI) + find_package(VRPN REQUIRED) + include_directories(SYSTEM ${VRPN_INCLUDE_DIR}) + include_directories(SYSTEM VRPN_PHANTOM_INCLUDE_DIR) +endif() + if(SimMedTK_USE_ADU) find_package(ADU REQUIRED) include_directories(SYSTEM "${ADU_INCLUDE_DIR}") diff --git a/Core/BaseMesh.cpp b/Core/BaseMesh.cpp index 66810634b1c01d2bf69795ad2b5fdabf699ab1fb..4f2a26d23ed40d1e07e76fb98726b83b97de6bdc 100644 --- a/Core/BaseMesh.cpp +++ b/Core/BaseMesh.cpp @@ -127,7 +127,7 @@ void BaseMesh::scale ( const Eigen::UniformScaling<double>& scaling ) v = scaling*v; } ); } -void BaseMesh::rotate ( const Quaterniond& rotation ) +void BaseMesh::rotate ( const core::Quaterniond& rotation ) { std::for_each ( std::begin(vertices),std::end(vertices), [rotation] ( core::Vec3d &v ) diff --git a/Core/BaseMesh.h b/Core/BaseMesh.h index b5d146c7b8467a49fcc5fe6da57204229ace51d2..6686196837b5664089fdc19abd0c82ec02ee2bf0 100644 --- a/Core/BaseMesh.h +++ b/Core/BaseMesh.h @@ -148,7 +148,7 @@ public: /// /// \brief Apply a rotation to the vertices /// - void rotate(const Quaterniond &rotation); + void rotate(const core::Quaterniond &rotation); /// /// \brief Apply any affine tranformation to the vertices. diff --git a/Core/ErrorLog.h b/Core/ErrorLog.h index bb2e7ac6ba723dd7d807b61a1b82424887f441c5..b8ad832df71c7e28628944b7b8fd57b08fb6166f 100644 --- a/Core/ErrorLog.h +++ b/Core/ErrorLog.h @@ -48,7 +48,7 @@ private: std::vector<std::string> errors; ///< error messages std::vector<int> timeStamps; ///< time stamps for errors std::mutex logLock; ///< mutex to sync access to logs - Timer time; ///< Timer for timestamps + core::Timer time; ///< Timer for timestamps bool consoleOutput; ///< Flag to print errors to stdout public: diff --git a/Core/Light.cpp b/Core/Light.cpp index 69862d9f3aa0f0c15736a9f20c6458d08024b77b..6cf8b39233d0042378dc706ae9f5b4f0a51cc1d3 100644 --- a/Core/Light.cpp +++ b/Core/Light.cpp @@ -37,7 +37,7 @@ void Light::updateDirection() angle = std::acos(dirNorm.dot(defaultDir)); core::Vec3d axisOfRot = dirNorm.cross(defaultDir).normalized(); - Quaterniond rot = getRotationQuaternion(-angle,axisOfRot); + core::Quaterniond rot = getRotationQuaternion(-angle,axisOfRot); upVector = rot*defaultUpDir; transverseDir = rot*defaultTransDir; diff --git a/Core/ObjectSimulator.h b/Core/ObjectSimulator.h index 1dfff76f45cf8b5e3e1f81165d20c06180b0e3fc..7f0374a86455ccbefe10a1ac30ae3753e0e393ff 100644 --- a/Core/ObjectSimulator.h +++ b/Core/ObjectSimulator.h @@ -64,7 +64,7 @@ protected: std::shared_ptr<ErrorLog> log; bool isObjectSimInitialized; ThreadPriority threadPriority; - Timer timer; + core::Timer timer; long double timerPerFrame; long double FPS; unsigned int frameCounter; diff --git a/Core/Quaternion.h b/Core/Quaternion.h index d344805f53d422e484f372f542f34add75b73c14..2324d119124ef78f20d0f9e0d127faee5ff2ce50 100644 --- a/Core/Quaternion.h +++ b/Core/Quaternion.h @@ -34,11 +34,14 @@ template<typename T> using Quaternion = Eigen::Quaternion<T>; +namespace core +{ /// A quaternion of floats. using Quaternionf = Quaternion<float>; /// A quaternion of doubles. using Quaterniond = Quaternion<double>; +} //core /// Create a quaternion rotation corresponding to the specified angle (in radians) and axis. /// \tparam T the numeric data type. diff --git a/Core/SDK.cpp b/Core/SDK.cpp index 10ed417f83d499ee3f5fe2cb8ae8d12343f87fc3..d3eb7b98d8ac34cb8545039bde9d36ff1d29c7a1 100644 --- a/Core/SDK.cpp +++ b/Core/SDK.cpp @@ -174,12 +174,23 @@ void SDK::run() runRegisteredModules(); - this->viewer->exec(); + if (nullptr != this->viewer) + { + this->viewer->exec(); - // Now wait for other modules to shut down - while (this->viewer->isValid() && !shutdown) + // Now wait for other modules to shut down + while (this->viewer->isValid() && !shutdown) + { + std::this_thread::sleep_for(std::chrono::seconds(1)); + } + } + else { - std::this_thread::sleep_for(std::chrono::seconds(1)); + // Now wait for other modules to shut down + while (!shutdown) + { + std::this_thread::sleep_for(std::chrono::seconds(1)); + } } // Tell framework threads to shutdown diff --git a/Core/Timer.cpp b/Core/Timer.cpp index e5f82921137f2de116580bc5322514d3afff110a..187ef170ffd65f1876963d21f6de8aded4a392b5 100644 --- a/Core/Timer.cpp +++ b/Core/Timer.cpp @@ -23,6 +23,7 @@ // SimMedTK includes #include "Core/Timer.h" +using namespace core; Timer::Timer() { diff --git a/Core/Timer.h b/Core/Timer.h index b2caf4f5344a427876915adc8ed3f62c3f197dc8..c1bd3d4739ca573764022670ae2a7d851a128f17 100644 --- a/Core/Timer.h +++ b/Core/Timer.h @@ -31,6 +31,8 @@ #include "Core/Config.h" #include "Core/CoreClass.h" +namespace core { + /// \brief timer class class Timer: public CoreClass { @@ -55,4 +57,6 @@ private: TimePointType begin; }; +} //core + #endif diff --git a/Devices/CMakeLists.txt b/Devices/CMakeLists.txt index 1e05214d8db85e512810438df49419564f170267..27c76e65040bb5032fc647c862abe199e095ee40 100644 --- a/Devices/CMakeLists.txt +++ b/Devices/CMakeLists.txt @@ -2,23 +2,23 @@ set(EXTERNAL_DEVICES_SOURCES) set(EXTERNAL_DEVICES_TARGET_LIBRARIES) -if(SIMMEDTK_USE_PHANTOM_OMNI) +if(SimMedTK_USE_PHANTOM_OMNI) list(APPEND EXTERNAL_DEVICES_SOURCES HapticInterface.cpp - PhantomInterface.cpp +# PhantomInterface.cpp + VRPNPhantomDevice.cpp ) list(APPEND EXTERNAL_DEVICES_TARGET_LIBRARIES - OH::HD - OH::HDU + vrpn::vrpn ) endif() -if(SIMMEDTK_USE_ADU) +if(SimMedTK_USE_ADU) list(APPEND EXTERNAL_DEVICES_SOURCES ADUInterface.cpp) endif() -if(SIMMEDTK_USE_NIUSB6008) +if(SimMedTK_USE_NIUSB6008) list(APPEND EXTERNAL_DEVICES_SOURCES NIUSB6008Interface.cpp) endif() @@ -35,6 +35,7 @@ simmedtk_add_library(Devices Audio.h NIUSB6008Interface.h PhantomInterface.h + VRPNPhantomDevice.h ) target_link_libraries(Devices diff --git a/Devices/HapticInterface.h b/Devices/HapticInterface.h index 239a27326402ac720922ced3a079f58cd5e566e3..30c4e9ce1a2629ff876f2cc47dc96ad5b4bf0101 100644 --- a/Devices/HapticInterface.h +++ b/Devices/HapticInterface.h @@ -24,7 +24,9 @@ #ifndef SM_HAPTIC_INTERFACE_H #define SM_HAPTIC_INTERFACE_H -#include "External/DeviceInterface.h" +#include "Devices/DeviceInterface.h" + +#include "Core/Matrix.h" #define SM_MAX_BUTTONS 4 @@ -36,7 +38,7 @@ struct hapticDeviceData_t core::Vec3d position; core::Vec3d velocity; core::Vec3d angles; - Matrix44 transform; + Matrix44d transform; bool buttonState[SM_MAX_BUTTONS]; }; @@ -53,49 +55,49 @@ public: virtual ~HapticInterface() {}; /// \brief open haptic device - virtual int openDevice() + virtual Message openDevice() { return Message::Unknown; } /// \brief close haptic device - virtual int closeDevice() + virtual Message closeDevice() { return Message::Unknown; } /// \brief start the haptic device - virtual int startDevice() + virtual Message startDevice() { return Message::Unknown; } /// \brief get the position of the end effector the haptic device - virtual int getPosition(core::Vec3d & d_pos) + virtual Message getPosition(core::Vec3d & d_pos) { return Message::Unknown; } /// \brief get the orientation of the end effector the haptic device - virtual int getOreintation(Matrix33 *d_rot) + virtual Message getOreintation(Matrix33d *d_rot) { return Message::Unknown; } /// \brief get the transform (position + orientation) of the end effector the haptic device - virtual int getDeviceTransform(Matrix44 *d_transform) + virtual Message getDeviceTransform(Matrix44d *d_transform) { return Message::Unknown; } /// \brief set force to the haptic device - virtual int setForce(core::Vec3d & force) + virtual Message setForce(core::Vec3d & force) { return Message::Unknown; } /// \brief set torque to the haptic device - virtual int setForceandTorque(core::Vec3 & force, core::Vec3 & torque) + virtual Message setForceandTorque(core::Vec3d & force, core::Vec3d & torque) { return Message::Unknown; } diff --git a/Devices/VRPNPhantomDevice.cpp b/Devices/VRPNPhantomDevice.cpp index 872b98c5b845cd83fe2d1d51c2b25c57b67057f1..c92e7c74e383723a7c73666fb17442e9a81ee013 100644 --- a/Devices/VRPNPhantomDevice.cpp +++ b/Devices/VRPNPhantomDevice.cpp @@ -1,10 +1,8 @@ #include "VRPNPhantomDevice.h" -#include <vrpn_Connection.h> #include <vrpn_Button.h> #include <vrpn_ForceDevice.h> #include <vrpn_Tracker.h> -#include <server_src/vrpn_Phantom.h> #include <chrono> #include <thread> @@ -12,8 +10,7 @@ #include <algorithm> VRPNPhantomDevice::VRPNPhantomDevice() - : terminate{false}, - deviceURL("Phantom0@localhost"), + : deviceURL("Phantom0@localhost"), delay(std::chrono::milliseconds(100)) { @@ -24,52 +21,69 @@ VRPNPhantomDevice::~VRPNPhantomDevice() } -Device::Message VRPNPhantomDevice::open() +DeviceInterface::Message VRPNPhantomDevice::openDevice() { - vrpnButton = std::make_shared<vrpn_Button_Remote>(this->deviceURL); - vrpnForce = std::make_shared<vrpn_ForceDevice_Remote>(this->deviceURL); - vrpnTracker = std::make_shared<vrpn_Tracker_Remote>(this->deviceURL); - //need try/catch incase the memory couldn't be allocated, the return + vrpnButton = std::make_shared<vrpn_Button_Remote>(this->deviceURL.c_str()); + vrpnForce = std::make_shared<vrpn_ForceDevice_Remote>(this->deviceURL.c_str()); + vrpnTracker = std::make_shared<vrpn_Tracker_Remote>(this->deviceURL.c_str()); + //need try/catch incase the memory couldn't be allocated, then return // Message::Failure; - vrpnButton->register_change_handler( this, ButtonChangeHandler ); - vrpnForce->register_force_change_handler( this, ForceChangeHandler ); - vrpnTracker->register_change_handler( this, TrackerChangeHandler ); + vrpnButton->register_change_handler(this, buttonChangeHandler); + vrpnForce->register_force_change_handler(this, forceChangeHandler); + vrpnTracker->register_change_handler(this, trackerChangeHandler); - return Device::Message::Success; + return DeviceInterface::Message::Success; } -Device::Message VRPNPhantomDevice::close() +DeviceInterface::Message VRPNPhantomDevice::closeDevice() { - terminate = true; - return Device::Message::Success; + this->terminate(); + return DeviceInterface::Message::Success; +} + +void VRPNPhantomDevice::init() +{ + buttonTimers[0].start(); + buttonTimers[1].start(); + forceTimer.start(); + posTimer.start(); + quatTimer.start(); } void VRPNPhantomDevice::exec() { - while(!terminate) + while(!terminateExecution) { processChanges(); std::this_thread::sleep_for(delay); } } -void VRPNPhantomDevice::setDeviceURL(const string s) +void VRPNPhantomDevice::beginFrame() +{ +} + +void VRPNPhantomDevice::endFrame() +{ +} + +void VRPNPhantomDevice::setDeviceURL(const std::string s) { deviceURL = s; } -const std::string VRPNPhantomDevice::getDeviceURL() +std::string VRPNPhantomDevice::getDeviceURL() { return deviceURL; } -void VRPNPhantomDevice::setPollDelay(const std::chrono::duration d) +void VRPNPhantomDevice::setPollDelay(const std::chrono::milliseconds d) { delay = d; } -const std::chrono::duration VRPNPhantomDevice::getPollDelay() +std::chrono::milliseconds VRPNPhantomDevice::getPollDelay() { return delay; } @@ -81,94 +95,80 @@ void VRPNPhantomDevice::processChanges() vrpnTracker->mainloop(); } -void VRPN_CALLBACK -VRPNPhantomDevice::buttonChangeHandler(void *userData, const vrpn_BUTTONCB b) +core::Vec3d VRPNPhantomDevice::getForce() { - VRPNPhantomDevice *handler = reinterpret_cast<VRPNPhantomDevice*>(userData); - - if (b.button < handler->buttons.size()) - { - buttons[b.button] = (1 == b.state); - //Should also handle time stamps - }//else the button isn't accounted for, as far as we know, it didn't exist + return force; } -void VRPN_CALLBACK -VRPNPhantomDevice::forceChangeHandler(void *userData, const vrpn_FORCECB f) +core::Vec3d VRPNPhantomDevice::getPosition() { - VRPNPhantomDevice *handler = reinterpret_cast<VRPNPhantomDevice*>(userData); - - std::copy(std::begin(f.force), std::end(f.force), std::begin(handler->force)); - //Should also handle time stamps + return pos; } -void VRPN_CALLBACK -VRPNPhantomDevice::trackerChangeHandler(void *userData, const vrpn_TRACKERCB t) +core::Quaterniond VRPNPhantomDevice::getOrientation() { - VRPNPhantomDevice *handler = reinterpret_cast<VRPNPhantomDevice*>(userData); - - std::copy(std::begin(t.pos), std::end(t.pos), std::begin(handler->pos)); - std::copy(std::begin(t.quat), std::end(t.quat), std::begin(handler->quat)); - //Should also handle time stamps + return quat; } - - - -VRPNPhantomDeviceServer::VRPNPhantomDeviceServer() - : terminate{false}, - deviceName("Phantom0"), - delay(std::chrono::milliseconds(100)) +bool VRPNPhantomDevice::getButton(size_t i) { - + if (i < 2) + return buttons[i]; + else + return false; } -VRPNPhantomDeviceServer::~VRPNPhantomDeviceServer() +long double VRPNPhantomDevice::getForceETime() { - delete connection; + return forceTimer.elapsed(); } -Device::Message VRPNPhantomDeviceServer::open() +long double VRPNPhantomDevice::getPositionETime() { - connection = vrpn_create_server_connection(); - phantom = std::make_shared<vrpn_Phantom>(deviceName, connection, 60.0f); - //need try/catch incase the memory couldn't be allocated, the return - // Message::Failure; - return Device::Message::Success; + return posTimer.elapsed(); } -Device::Message VRPNPhantomDeviceServer::close() +long double VRPNPhantomDevice::getOrientationETime() { - terminate = true; - return Device::Message::Success; + return quatTimer.elapsed(); } -void VRPNPhantomDeviceServer::exec() +long double VRPNPhantomDevice::getButtonETime(size_t i) { - while(!terminate) - { - phantom->mainloop(); - connection->mainloop(); - std::this_thread::sleep_for(delay); - } + if (i < 2) + return buttonTimers[i].elapsed(); + else + return -1; } -void VRPNPhantomDeviceServer::setDeviceName(const string s) -{ - deviceName = s; -} -const std::string VRPNPhantomDeviceServer::getDeviceName() +void VRPN_CALLBACK +VRPNPhantomDevice::buttonChangeHandler(void *userData, const vrpn_BUTTONCB b) { - return deviceName; + VRPNPhantomDevice *handler = reinterpret_cast<VRPNPhantomDevice*>(userData); + + if (b.button < handler->buttons.size()) + { + handler->buttons[b.button] = (1 == b.state); + handler->buttonTimers[b.button].start(); + }//else the button isn't accounted for, as far as we know, it didn't exist } -void VRPNPhantomDeviceServer::setPollDelay(const std::chrono::duration d) +void VRPN_CALLBACK +VRPNPhantomDevice::forceChangeHandler(void *userData, const vrpn_FORCECB f) { - delay = d; + VRPNPhantomDevice *handler = reinterpret_cast<VRPNPhantomDevice*>(userData); + + handler->force = Eigen::Map<const core::Vec3d>(f.force); + handler->forceTimer.start(); } -const std::chrono::duration VRPNPhantomDeviceServer::getPollDelay() +void VRPN_CALLBACK +VRPNPhantomDevice::trackerChangeHandler(void *userData, const vrpn_TRACKERCB t) { - return delay; + VRPNPhantomDevice *handler = reinterpret_cast<VRPNPhantomDevice*>(userData); + handler->pos = Eigen::Map<const core::Vec3d>(t.pos); + handler->posTimer.start(); + handler->quat = Eigen::Map<const core::Quaterniond>(t.quat); + handler->quatTimer.start(); } diff --git a/Devices/VRPNPhantomDevice.h b/Devices/VRPNPhantomDevice.h index 4faaadc41a11048787fdf1d1cc8291f967a1ba8d..52a39183e42cd7991a0b21321640d5604daa9dde 100644 --- a/Devices/VRPNPhantomDevice.h +++ b/Devices/VRPNPhantomDevice.h @@ -24,77 +24,70 @@ #ifndef SM_VRPNPHANTOMDEVICE_H #define SM_VRPNPHANTOMDEVICE_H -#include "Device.h" +#include "Core/Vector.h" +#include "Core/Quaternion.h" +#include "Core/Timer.h" +#include "Devices/DeviceInterface.h" -#include <vrpn_Connection.h> +#include <vrpn_Types.h> #include <vrpn_Button.h> #include <vrpn_ForceDevice.h> #include <vrpn_Tracker.h> -#include <server_src/vrpn_Phantom.h> #include <string> #include <memory> #include <chrono> #include <array> -class VRPNPhantomDevice : Device +class VRPNPhantomDevice : public DeviceInterface { public: VRPNPhantomDevice(); virtual ~VRPNPhantomDevice(); - Device::Message open() override; - Device::Message close() override; - void exec() override; + DeviceInterface::Message openDevice() override; + DeviceInterface::Message closeDevice() override; - void setDeviceURL(const string s); - const std::string getDeviceURL(); - void setPollDelay(const std::chrono::duration d); - const std::chrono::duration getPollDelay(); + void init() override; + void exec() override; + void beginFrame() override; + void endFrame() override; + + void setDeviceURL(const std::string s); + std::string getDeviceURL(); + void setPollDelay(const std::chrono::milliseconds d); + std::chrono::milliseconds getPollDelay(); + core::Vec3d getForce(); + core::Vec3d getPosition(); + core::Quaterniond getOrientation(); + bool getButton(size_t i); + long double getForceETime(); + long double getPositionETime(); + long double getOrientationETime(); + long double getButtonETime(size_t i); private: - bool terminate; std::string deviceURL; - std::chrono::duration delay; + std::chrono::milliseconds delay; - //Need getters and setters for these std::array<bool, 2> buttons; //< Buttons: true = pressed/false = not pressed - std::array<vprn_float64, 3> force; //this should really be a vec3 or something - std::array<vprn_float64, 3> pos; //this should really be a vec3 or something - std::array<vprn_float64, 4> quat; //this should really be a quat or something + core::Vec3d force; //this should really be a vec3 or something + core::Vec3d pos; //this should really be a vec3 or something + core::Quaterniond quat; //this should really be a quat or something + + std::array<core::Timer, 2> buttonTimers; + core::Timer forceTimer; + core::Timer posTimer; + core::Timer quatTimer; std::shared_ptr<vrpn_Button_Remote> vrpnButton; std::shared_ptr<vrpn_ForceDevice_Remote> vrpnForce; std::shared_ptr<vrpn_Tracker_Remote> vrpnTracker; void processChanges(); - void VRPN_CALLBACK buttonChangeHandler(void *userData, const vrpn_BUTTONCB b); - void VRPN_CALLBACK forceChangeHandler(void *userData, const vrpn_FORCECB f); - void VRPN_CALLBACK trackerChangeHandler(void *userData, const vrpn_TRACKERCB b); -}; - - -class VRPNPhantomDeviceServer : Device -{ -public: - VRPNPhantomDeviceServer(); - virtual ~VRPNPhantomDeviceServer(); - - Device::Message open() override; - Device::Message close() override; - void exec() override; - - void setDeviceName(const string s); - const std::string getDeviceName(); - void setPollDelay(const std::chrono::duration d); - const std::chrono::duration getPollDelay(); - -private: - bool terminate; - std::string deviceName; - std::chrono::duration delay; - vrpn_Connection connection; - std::shared_ptr<vrpn_Phantom> phantom; + static void VRPN_CALLBACK buttonChangeHandler(void *userData, const vrpn_BUTTONCB b); + static void VRPN_CALLBACK forceChangeHandler(void *userData, const vrpn_FORCECB f); + static void VRPN_CALLBACK trackerChangeHandler(void *userData, const vrpn_TRACKERCB b); }; #endif diff --git a/Event/CameraEvent.h b/Event/CameraEvent.h index 212d61c9b9f0a3490b7b5d08a219aed31ede5556..9a0c5699f605d1070a707ad6d313986f8d1dc518 100644 --- a/Event/CameraEvent.h +++ b/Event/CameraEvent.h @@ -51,7 +51,7 @@ public: const core::Vec3d &getUpDirection(); - void applyRotation(const Quaterniond &quat) + void applyRotation(const core::Quaterniond &quat) { direction = quat*direction; upDirection = quat*upDirection; diff --git a/Examples/CMakeLists.txt b/Examples/CMakeLists.txt index 833bd8918355daf2eee79058617cca74644394c3..f354a013c5c231515d97d51647beccc8d7941992 100644 --- a/Examples/CMakeLists.txt +++ b/Examples/CMakeLists.txt @@ -25,9 +25,9 @@ endfunction() # add_subdirectory(common) -if(SIMMEDTK_USE_PHANTOM_OMNI) - add_subdirectory(AlphaMap) -endif(SIMMEDTK_USE_PHANTOM_OMNI) +if(SimMedTK_USE_PHANTOM_OMNI) + add_subdirectory(vrpnPhantomTest) +endif(SimMedTK_USE_PHANTOM_OMNI) if(SimMedTK_USE_OCULUS) add_subdirectory(renderCubeOculus) diff --git a/Examples/common/vrpnPhantomObjectController.cpp b/Examples/common/vrpnPhantomObjectController.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1c4e18caac09f32b9fd73996f79768012eb771a1 --- /dev/null +++ b/Examples/common/vrpnPhantomObjectController.cpp @@ -0,0 +1,111 @@ +// This file is part of the SimMedTK project. +// Copyright (c) Center for Modeling, Simulation, and Imaging in Medicine, +// Rensselaer Polytechnic Institute +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//--------------------------------------------------------------------------- +// +// Authors: +// +// Contact: +//--------------------------------------------------------------------------- + +#include "vrpnPhantomObjectController.h" + +#include "Core/RenderDelegate.h" + +#include <thread> + +namespace mstk { +namespace Examples { +namespace Common { + +vrpnPhantomObjectController::vrpnPhantomObjectController( + std::shared_ptr<VRPNPhantomDevice> p, std::shared_ptr<Core::BaseMesh> m) + : phantom(p), + mesh(m), + scalingFactor(1.0), + delay(std::chrono::milliseconds(100)) +{ +} + +void vrpnPhantomObjectController::init() +{ +} + +void vrpnPhantomObjectController::beginFrame() +{ +} + +void vrpnPhantomObjectController::endFrame() +{ +} + +void vrpnPhantomObjectController::exec() +{ + assert(phantom); + assert(mesh); + + while(!terminateExecution) + { + //calculate new transformation + Eigen::Transform<double,3,Eigen::Affine> trans; + + trans.rotate(phantom->getOrientation()); + trans.translate(phantom->getPosition() * scalingFactor); + + mesh->transform(prevTrans.inverse()); //inverse previous transformation + mesh->transform(trans); //apply new transformation + mesh->getRenderDelegate()->modified(); + + prevTrans = trans; //track most recent transform + + std::this_thread::sleep_for(delay); + } +} + +void vrpnPhantomObjectController::setPollDelay(const std::chrono::milliseconds d) +{ + delay = d; +} + +std::chrono::milliseconds vrpnPhantomObjectController::getPollDelay() +{ + return delay; +} + +void vrpnPhantomObjectController::setScalingFactor(double s) +{ + scalingFactor = s; +} + +double vrpnPhantomObjectController::getScalingFactor() +{ + return scalingFactor; +} + +void vrpnPhantomObjectController::setPhantom(std::shared_ptr<VRPNPhantomDevice> p) +{ + phantom = p; +} + +void vrpnPhantomObjectController::setMesh(std::shared_ptr<Core::BaseMesh> m) +{ + mesh = m; +} + + +} //Common +} //Examples +} //mstk \ No newline at end of file diff --git a/Examples/common/vrpnPhantomObjectController.h b/Examples/common/vrpnPhantomObjectController.h new file mode 100644 index 0000000000000000000000000000000000000000..c20f9461b288d76d2fe13f6ea9fdd8ebe4c950bb --- /dev/null +++ b/Examples/common/vrpnPhantomObjectController.h @@ -0,0 +1,65 @@ +// This file is part of the SimMedTK project. +// Copyright (c) Center for Modeling, Simulation, and Imaging in Medicine, +// Rensselaer Polytechnic Institute +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//--------------------------------------------------------------------------- +// +// Authors: +// +// Contact: +//--------------------------------------------------------------------------- + +#include "Core/BaseMesh.h" +#include "Core/Module.h" +#include "Devices/VRPNPhantomDevice.h" + +#include <memory> +#include <chrono> + +namespace mstk { +namespace Examples { +namespace Common { + +class vrpnPhantomObjectController : public Module +{ +public: + vrpnPhantomObjectController(std::shared_ptr<VRPNPhantomDevice> p = nullptr, + std::shared_ptr<Core::BaseMesh> m = nullptr); + + void setPhantom(std::shared_ptr<VRPNPhantomDevice> p); + void setMesh(std::shared_ptr<Core::BaseMesh> m); + + void setPollDelay(const std::chrono::milliseconds d); + std::chrono::milliseconds getPollDelay(); + + void setScalingFactor(double s); + double getScalingFactor(); + + void init() override; + void beginFrame() override; + void endFrame() override; + void exec() override; + +private: + std::shared_ptr<VRPNPhantomDevice> phantom; + std::shared_ptr<Core::BaseMesh> mesh; + std::chrono::milliseconds delay; + Eigen::Transform<double,3,Eigen::Affine> prevTrans; + double scalingFactor; +}; + +} //Common +} //Examples +} //mstk \ No newline at end of file diff --git a/Examples/vrpnPhantomTest/CMakeLists.txt b/Examples/vrpnPhantomTest/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..42d1fc8b1957bedb8979cbbe53ea146b82e58537 --- /dev/null +++ b/Examples/vrpnPhantomTest/CMakeLists.txt @@ -0,0 +1,15 @@ + +add_executable(vrpnPhantomTest main.cpp) +target_link_libraries(vrpnPhantomTest + Core + VTKRendering + Rendering + RenderDelegates + IO + Mesh + Event + Collision + ExamplesCommon + Geometry + Devices + ) diff --git a/Examples/vrpnPhantomTest/main.cpp b/Examples/vrpnPhantomTest/main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..08cacadd6aa7d49b45d8bf7cb5f9b9ed30a45b6e --- /dev/null +++ b/Examples/vrpnPhantomTest/main.cpp @@ -0,0 +1,123 @@ +// This file is part of the SimMedTK project. +// Copyright (c) Center for Modeling, Simulation, and Imaging in Medicine, +// Rensselaer Polytechnic Institute +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//--------------------------------------------------------------------------- +// +// Authors: +// +// Contact: +//--------------------------------------------------------------------------- + +#include <string> +#include <chrono> +#include <thread> + +#include "Examples/common/vrpnPhantomObjectController.h" +#include "Examples/common/ExampleCube.h" + +#include "Core/SDK.h" +#include "Core/Factory.h" +#include "Core/ViewerBase.h" +#include "Devices/VRPNPhantomDevice.h" +#include "IO/initIO.h" +#include "RenderDelegates/initRenderDelegates.h" +#include "VTKRendering/initVTKRendering.h" + +int main() +{ + using vrpnPhantomObjectController = mstk::Examples::Common::vrpnPhantomObjectController; + using ExampleCube = mstk::Examples::Common::ExampleCube; + + initRenderDelegates(); + initVTKRendering(); + initIODelegates(); + const bool useVTKRenderer = true; // VTK is the default viewer. + + ExampleCube cube; + std::string input = ""; + + auto sdk = SDK::getInstance(); + auto phantom = std::make_shared<VRPNPhantomDevice>(); + //auto listener = std::make_shared<vrpnPhantomListener>(phantom); + auto controller = std::make_shared<vrpnPhantomObjectController>(); + + sdk->registerModule(phantom); + sdk->registerModule(controller); + + //get some user input and setup device url and stuff like that + std::cout << "Enter the VRPN device URL(" << phantom->getDeviceURL() << "): "; + std::getline(std::cin, input); + if(!input.empty()) + { + phantom->setDeviceURL(input); + } + + auto scene = std::make_shared<Scene>(); + + // Create a viewer + std::shared_ptr<ViewerBase> viewer + = Factory<ViewerBase>::createSubclassForGroup("ViewerBase",RenderDelegate::VTK); + if(!useVTKRenderer) + { + viewer.reset(); + viewer + = Factory<ViewerBase>::createSubclassForGroup("ViewerBase",RenderDelegate::Other); + } + + cube.useVTKRenderer(useVTKRenderer); + cube.setup(); + + // Add the cube to the scene to be rendered + scene->addSceneObject(cube.getStaticSceneObject()); + + // Register the scene with the viewer, and setup render target + viewer->registerScene(scene, SMRENDERTARGET_SCREEN, ""); + + // Setup the window title in the window manager + viewer->setWindowTitle("SimMedTK RENDER TEST"); + + // Set some viewer properties + viewer->setScreenResolution(800, 640); + + // Setup Scene lighting + if(!useVTKRenderer) + { + auto light = Light::getDefaultLighting(); + assert(light); + scene->addLight(light); + + // Camera setup + auto sceneCamera = Camera::getDefaultCamera(); + assert(sceneCamera); + sceneCamera->setPos(3, 3, 5); + sceneCamera->setFocus(0, 0, -1); + sceneCamera->genProjMat(); + sceneCamera->genViewMat(); + scene->addCamera(sceneCamera); + } + + viewer->exec(); + + + phantom->openDevice(); + + controller->setPhantom(phantom); + controller->setMesh(cube.getStaticSceneObject()->getModel()->getMesh()); + + sdk->run(); + + return 0; +} diff --git a/Rendering/Camera.cpp b/Rendering/Camera.cpp index 8bcc8df3dad519cb04e9f6495f426ffef68cb2cf..7b21b94790e1132b9478ef0cf45f7812f52dcc6a 100644 --- a/Rendering/Camera.cpp +++ b/Rendering/Camera.cpp @@ -146,7 +146,7 @@ void Camera::setFarClipDist(const float d) this->projDirty.store(true); } -void Camera::setOrientation(const Quaternionf q) +void Camera::setOrientation(const core::Quaternionf q) { { //scoped for mutex release std::lock_guard<std::mutex> lock(orientationLock); @@ -167,10 +167,10 @@ void Camera::setOrientFromDir(const core::Vec3f d) camAxes.col(2) = (-d).normalized(); camAxes.col(0) = tempUp.cross( camAxes.col(2) ).normalized(); camAxes.col(1) = camAxes.col(2).cross( camAxes.col(0) ).normalized(); - setOrientation(Quaternionf(camAxes)); + setOrientation(core::Quaternionf(camAxes)); } -Quaternionf Camera::getOrientation() +core::Quaternionf Camera::getOrientation() { if (true == this->orientDirty.load()) { @@ -237,7 +237,7 @@ void Camera::zoom(const float d) void Camera::rotateLocal(const float angle, const core::Vec3f axis) { float dist = (getPos() - getFocus()).norm(); - Quaternionf q; + core::Quaternionf q; q = Eigen::AngleAxisf(angle, axis.normalized()); setOrientation(getOrientation() * q); @@ -247,7 +247,7 @@ void Camera::rotateLocal(const float angle, const core::Vec3f axis) void Camera::rotateFocus(const float angle, const core::Vec3f axis) { float dist = (getFocus() - getPos()).norm(); - Quaternionf q; + core::Quaternionf q; q = Eigen::AngleAxisf(angle, axis.normalized()); setOrientation(getOrientation() * q); diff --git a/Rendering/Camera.h b/Rendering/Camera.h index ab6fa41c15f479724a49164a70c06b1fc5400ef7..59a50cadccbfefe8847c0de3c1abbe24bfce27f3 100644 --- a/Rendering/Camera.h +++ b/Rendering/Camera.h @@ -301,6 +301,11 @@ public: return zoomValue; } + /// \brief Replaces the internal quaternion with the one provided + /// + /// \param q New internal orientation quaternion + void setOrientation(const core::Quaternionf q); + /// \brief Returns the orientation of the camera /// /// \return The orientation of the camera as a quaternion @@ -312,7 +317,7 @@ private: std::mutex posLock; //< Controls access to the pos variable core::Vec3f fp; ///< focal point of the camera std::mutex fpLock; //< Controls access to the fp variable - Quaternionf orientation; ///< orientation of the camera + core::Quaternionf orientation; ///< orientation of the camera std::mutex orientationLock; //< Controls access to the orientation variable Matrix44f view; ///< View matrix for OpenGL std::mutex viewLock; //< Controls access to the view variable @@ -351,11 +356,6 @@ private: /// /// \param d Directional vector to orient the camera with void setOrientFromDir(const core::Vec3f d); - - /// \brief Replaces the internal quaternion with the one provided - /// - /// \param q New internal orientation quaternion - void setOrientation(const Quaternionf q); }; #endif diff --git a/Rendering/OculusViewer.cpp b/Rendering/OculusViewer.cpp index 6cdcd23eee9f4957f59f8801d5c531c6fe82b99a..7bf7a90f95a37ea679ab050cec36b0b8c046433a 100644 --- a/Rendering/OculusViewer.cpp +++ b/Rendering/OculusViewer.cpp @@ -177,7 +177,7 @@ void OculusViewer::renderToScreen(const RenderOperation &p_rop) //retrieve the orientation quaternion and // convert it to a rotation matrix - viewRotation = Quaternionf(-pose[eye].Orientation.w, + viewRotation = core::Quaternionf(-pose[eye].Orientation.w, pose[eye].Orientation.x, pose[eye].Orientation.y, pose[eye].Orientation.z); diff --git a/Rendering/OpenGLRenderer.cpp b/Rendering/OpenGLRenderer.cpp index 365e3a728bf9c39875fdaca3e69f139c6bff93b7..0e576434dd7349d3234867fdb8ac9aba1af8febb 100644 --- a/Rendering/OpenGLRenderer.cpp +++ b/Rendering/OpenGLRenderer.cpp @@ -556,7 +556,7 @@ void OpenGLRenderer::draw(Plane &p_plane, float p_scale, Color p_color) axisOfRot = normal.cross(defaultDir); axisOfRot.normalize(); - Quaterniond rot = getRotationQuaternion(-angle,axisOfRot); + core::Quaterniond rot = getRotationQuaternion(-angle,axisOfRot); glDisable(GL_LIGHTING); glBegin(GL_QUADS); diff --git a/Rendering/OpenGLViewer.h b/Rendering/OpenGLViewer.h index 04a37ddbc22d52f3d5ab0b29589a524029ee54cf..cc61668c24f3a0f4f273aad7c0c8ad7d7b3296b4 100644 --- a/Rendering/OpenGLViewer.h +++ b/Rendering/OpenGLViewer.h @@ -57,6 +57,11 @@ public: void setWindowTitle(const std::string &str) override; /// \brief enable/disable VSync virtual void setVSync(bool sync) override; + virtual void addFBO(const std::string &p_fboName, + Texture *p_colorTex, + Texture *p_depthTex, + unsigned int p_width, + unsigned int p_height) override; protected: virtual void initRenderingCapabilities() override; diff --git a/Rendering/Shader.h b/Rendering/Shader.h index 9c970f6e73c722b67d36698fa0ccb0e69e06d88b..778ee72270d2f47572ffb97712a3fc5115a8fbfe 100644 --- a/Rendering/Shader.h +++ b/Rendering/Shader.h @@ -283,7 +283,7 @@ private: std::vector<std::string> fragmentShaderParamsString; // stores the parameters for fragment shader std::vector<std::string> geometryShaderParamsString; // stores the parameters for geometry shader std::vector<std::string> attribParamsString; // stores the attribute parameters - Timer time; // time for periodically checnking the shader + core::Timer time; // time for periodically checnking the shader GLint projectionMatrix; // holds the unitform location for projection matrix. That is needed in newer versions of GLSL GLint modelViewMatrix; // holds the unitform location for modelview matrix. That is needed in newer versions of GLSL diff --git a/Simulators/MyStylus.cpp b/Simulators/MyStylus.cpp index f7328f167e6d86f22beed263d15183fe824af44c..9f107415d94793053873171b30a7c5ffa0d878e1 100644 --- a/Simulators/MyStylus.cpp +++ b/Simulators/MyStylus.cpp @@ -36,7 +36,7 @@ MyStylus::MyStylus(const std::string& p_shaft, const std::string& p_lower, const std::string& p_upper) { angle = 0; - Quaterniond rot; + core::Quaterniond rot; rot = Eigen::AngleAxisd(-M_PI_2, core::Vec3d::UnitX()); SurfaceMesh *mesh = new SurfaceMesh(Core::BaseMesh::MeshType::Rigid, nullptr); @@ -185,7 +185,7 @@ void MyStylus::handleEvent (std::shared_ptr<core::Event> p_event) HookCautery::HookCautery(const std::string& p_pivot) { - Quaterniond rot; + core::Quaterniond rot; rot = Eigen::AngleAxisd(-M_PI_2, core::Vec3d::UnitX()).matrix(); SurfaceMesh *mesh = new SurfaceMesh(Core::BaseMesh::MeshType::Rigid, nullptr); diff --git a/VirtualTools/CurvedGrasper.cpp b/VirtualTools/CurvedGrasper.cpp index f32bcd522daf363036d2a08643303efa15182127..b5dd5cbad151db6aa1e9fb5f4e29c0737e672d93 100644 --- a/VirtualTools/CurvedGrasper.cpp +++ b/VirtualTools/CurvedGrasper.cpp @@ -41,7 +41,7 @@ CurvedGrasper::CurvedGrasper(size_t p_PhantomID, maxangle = 10 * 3.14 / 360; this->phantomID = p_PhantomID; - Quaterniond rot; + core::Quaterniond rot; mesh_pivot = new SurfaceMesh(Core::BaseMesh::MeshType::Rigid, nullptr); mesh_pivot->loadMesh(p_pivotModelFileName, Core::BaseMesh::MeshFileType::ThreeDS); Eigen::UniformScaling<double> scaling(0.5);