Commit 619dac43 authored by Alexis Girault's avatar Alexis Girault

BUG: Fix two omnis issue

Co-authored by: Nicholas Milef <milefn@rpi.edu>

1) DeviceClient : not a module anymore, only stores device info
and holds callbacks

2) VRPNDeviceClient : subclasses DeviceClient AND Module, to
conserve the ability to run multiple clients in parallel with
a VRPN server

3) HDAPIDeviceServer : new module that manages the HDAPIDevice
clients execution, which need to be made sequentially. Also helps
managing a unique hdScheduler.

4) HDAPIDeviceClient : lets the HDAPIDeviceServer handle the
hdScheduler. Also makes use of hdMakeCurrentDevice.

5) SimulationManager : refactor to run modules instead of
deviceservers or deviceclients

6) Sandbox : use new simulationManager API to add modules
parent 9bfa04f3
......@@ -38,6 +38,18 @@ DeviceClient::setIp(const std::string& ip)
m_ip = ip;
}
const std::string&
DeviceClient::getDeviceName()
{
return m_deviceName;
}
void
DeviceClient::setDeviceName(const std::string& deviceName)
{
m_deviceName = deviceName;
}
const bool&
DeviceClient::getTrackingEnabled() const
{
......@@ -47,12 +59,6 @@ DeviceClient::getTrackingEnabled() const
void
DeviceClient::setTrackingEnabled(const bool& status)
{
if (this->getStatus() != ModuleStatus::INACTIVE)
{
LOG(WARNING) << "DeviceClient::setTrackingEnabled error: can not change listeners for"
<< this->getName() << " while the device is active.";
return;
}
m_trackingEnabled = status;
}
......@@ -65,12 +71,6 @@ DeviceClient::getAnalogicEnabled() const
void
DeviceClient::setAnalogicEnabled(const bool& status)
{
if (this->getStatus() != ModuleStatus::INACTIVE)
{
LOG(WARNING) << "DeviceClient::setAnalogicEnabled error: can not change listeners for"
<< this->getName() << " while the device is active.";
return;
}
m_analogicEnabled = status;
}
......@@ -83,12 +83,6 @@ DeviceClient::getButtonsEnabled() const
void
DeviceClient::setButtonsEnabled(const bool& status)
{
if (this->getStatus() != ModuleStatus::INACTIVE)
{
LOG(WARNING) << "DeviceClient::setButtonsEnabled error: can not change listeners for"
<< this->getName() << " while the device is active.";
return;
}
m_buttonsEnabled = status;
}
......@@ -101,12 +95,6 @@ DeviceClient::getForceEnabled() const
void
DeviceClient::setForceEnabled(const bool& status)
{
if (this->getStatus() != ModuleStatus::INACTIVE)
{
LOG(WARNING) << "DeviceClient::setForceEnabled error: can not change listeners for"
<< this->getName() << " while the device is active.";
return;
}
m_forceEnabled = status;
}
......
......@@ -24,7 +24,6 @@
#include <map>
#include "imstkModule.h"
#include "imstkMath.h"
namespace imstk
......@@ -34,7 +33,7 @@ namespace imstk
/// \class DeviceClient
/// \brief Base class for any device client
///
class DeviceClient : public Module
class DeviceClient
{
public:
......@@ -49,6 +48,12 @@ public:
const std::string& getIp();
void setIp(const std::string& ip);
///
/// \brief Get/Set the device name
///
const std::string& getDeviceName();
void setDeviceName(const std::string& deviceName);
///
/// \brief Get/Set what listeners to enable on the device: tracking, analogic, force, buttons.
///
......@@ -98,11 +103,12 @@ protected:
/// \brief Constructor
///
DeviceClient(std::string name, std::string ip):
Module(name),
m_deviceName(name),
m_ip(ip)
{}
std::string m_ip; ///< Connection device IP
std::string m_deviceName; ///< Device Name
std::string m_ip; ///< Connection device IP
bool m_trackingEnabled = true; ///< Tracking enabled if true
bool m_analogicEnabled = true; ///< Analogic enabled if true
......
......@@ -32,46 +32,37 @@ namespace imstk
{
void
HDAPIDeviceClient::initModule()
HDAPIDeviceClient::init()
{
// Open Device
m_handle = hdInitDevice(this->getName().c_str());
m_handle = hdInitDevice(this->getDeviceName().c_str());
// If failed
HDErrorInfo error;
if (HD_DEVICE_ERROR(error = hdGetError()))
{
LOG(FATAL) << "Failed to initialize Phantom Omni " << this->getName();
LOG(FATAL) << "Failed to initialize Phantom Omni " << this->getDeviceName();
m_handle = -1;
return;
}
// Calibration
if (hdCheckCalibration() != HD_CALIBRATION_OK)
{
LOG(INFO) << "Move " << this->getName() << " in its dock to calibrate it.";
while (hdCheckCalibration() != HD_CALIBRATION_OK)
{
}
}
// Success
LOG(INFO) << this->getName() << " successfully initialized.";
// Enable forces
hdEnable(HD_FORCE_OUTPUT);
hdEnable(HD_FORCE_RAMPING);
hdStartScheduler();
// Success
LOG(INFO) << this->getDeviceName() << " successfully initialized.";
}
void
HDAPIDeviceClient::runModule()
HDAPIDeviceClient::run()
{
hdScheduleSynchronous(hapticCallback, this, HD_MAX_SCHEDULER_PRIORITY);
}
void
HDAPIDeviceClient::cleanUpModule()
HDAPIDeviceClient::cleanUp()
{
hdStopScheduler();
hdDisableDevice(m_handle);
}
......@@ -83,13 +74,12 @@ HDAPIDeviceClient::hapticCallback(void* pData)
auto state = client->m_state;
hdBeginFrame(handle);
hdMakeCurrentDevice(handle);
hdSetDoublev(HD_CURRENT_FORCE, client->m_force.data());
hdGetDoublev(HD_CURRENT_POSITION, state.pos);
hdGetDoublev(HD_CURRENT_VELOCITY, state.vel);
hdGetDoublev(HD_CURRENT_TRANSFORM, state.trans);
hdGetIntegerv(HD_CURRENT_BUTTONS, &state.buttons);
hdEndFrame(handle);
client->m_position << state.pos[0], state.pos[1], state.pos[2];
......@@ -100,7 +90,7 @@ HDAPIDeviceClient::hapticCallback(void* pData)
client->m_buttons[2] = state.buttons & HD_DEVICE_BUTTON_3;
client->m_buttons[3] = state.buttons & HD_DEVICE_BUTTON_4;
return HD_CALLBACK_CONTINUE;
return HD_CALLBACK_DONE;
}
} // imstk
......
......@@ -58,9 +58,10 @@ public:
protected:
void initModule() override;
void runModule() override;
void cleanUpModule() override;
friend class HDAPIDeviceServer;
void init();
void run();
void cleanUp();
private:
......
/*=========================================================================
Library: iMSTK
Copyright (c) Kitware, Inc. & Center for Modeling, Simulation,
& 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.txt
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.
=========================================================================*/
#ifdef iMSTK_USE_OPENHAPTICS
#include "imstkHDAPIDeviceServer.h"
#include <HD/hd.h>
#include "g3log/g3log.hpp"
namespace imstk
{
void
HDAPIDeviceServer::addDeviceClient(std::shared_ptr<HDAPIDeviceClient> client)
{
m_deviceClients.push_back(client);
}
void
HDAPIDeviceServer::initModule()
{
for(const auto& client : m_deviceClients)
{
client->init();
}
hdStartScheduler();
}
void
HDAPIDeviceServer::runModule()
{
for(const auto& client : m_deviceClients)
{
client->run();
}
}
void
HDAPIDeviceServer::cleanUpModule()
{
hdStopScheduler();
for(const auto& client : m_deviceClients)
{
client->cleanUp();
}
}
} // imstk
#endif // ifdef iMSTK_USE_OMNI
/*=========================================================================
Library: iMSTK
Copyright (c) Kitware, Inc. & Center for Modeling, Simulation,
& 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.txt
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.
=========================================================================*/
#ifdef iMSTK_USE_OPENHAPTICS
#ifndef imstkHDAPIDeviceServer_h
#define imstkHDAPIDeviceServer_h
#include <vector>
#include <map>
#include <typeinfo>
// imstk
#include "imstkModule.h"
#include "imstkHDAPIDeviceClient.h"
namespace imstk
{
///
/// \class HDAPIDeviceServer
/// \brief Devices server using HDAPI
///
class HDAPIDeviceServer : public Module
{
public:
///
/// \brief Constructor
///
HDAPIDeviceServer(): Module("HDAPIDeviceServer")
{}
///
/// \brief Destructor
///
virtual ~HDAPIDeviceServer() {}
///
/// \brief Add device client
///
void addDeviceClient(std::shared_ptr<HDAPIDeviceClient> client);
protected:
///
/// \brief Initialize the server module
///
void initModule() override;
///
/// \brief Run the server module
///
void runModule() override;
///
/// \brief Clean the server module
///
void cleanUpModule() override;
private:
std::vector<std::shared_ptr<HDAPIDeviceClient>> m_deviceClients; ///< list of OpenHaptics
};
} // imstk
#endif // ifndef imstkHDAPIDeviceServer_h
#endif // ifdef iMSTK_USE_OMNI
......@@ -29,14 +29,14 @@ namespace imstk
void
VRPNDeviceClient::initModule()
{
std::string fullDeviceIp = this->getName() + "@" + this->getIp();
auto fullDeviceIp = this->getName().c_str();
m_offsetSet = false;
m_vrpnTracker = std::make_shared<vrpn_Tracker_Remote>(fullDeviceIp.c_str());
m_vrpnAnalog = std::make_shared<vrpn_Analog_Remote>(fullDeviceIp.c_str());
m_vrpnButton = std::make_shared<vrpn_Button_Remote>(fullDeviceIp.c_str());
m_vrpnForceDevice = std::make_shared<vrpn_ForceDevice_Remote>(fullDeviceIp.c_str());
m_vrpnTracker = std::make_shared<vrpn_Tracker_Remote>(fullDeviceIp);
m_vrpnAnalog = std::make_shared<vrpn_Analog_Remote>(fullDeviceIp);
m_vrpnButton = std::make_shared<vrpn_Button_Remote>(fullDeviceIp);
m_vrpnForceDevice = std::make_shared<vrpn_ForceDevice_Remote>(fullDeviceIp);
m_vrpnTracker->register_change_handler(this, trackerChangeHandler);
m_vrpnTracker->register_change_handler(this, velocityChangeHandler);
......@@ -154,7 +154,7 @@ VRPNDeviceClient::forceChangeHandler(void *userData, const _vrpn_FORCECB f)
{
auto deviceClient = reinterpret_cast<VRPNDeviceClient*>(userData);
deviceClient->m_force << f.force[0], f.force[1], f.force[2];
//LOG(DEBUG) << "forceDevice: force = " << deviceClient->m_force;
LOG(DEBUG) << "forceDevice: force = " << deviceClient->m_force;
}
} // imstk
......@@ -25,6 +25,7 @@
#include <map>
#include "imstkDeviceClient.h"
#include "imstkModule.h"
#include <memory>
......@@ -41,14 +42,16 @@ namespace imstk
/// \class VRPNDeviceClient
/// \brief Subclass of DeviceClient using VRPN
///
class VRPNDeviceClient : public DeviceClient
class VRPNDeviceClient : public DeviceClient, public Module
{
public:
///
/// \brief Constructor
///
VRPNDeviceClient(std::string name, std::string ip):DeviceClient(name, ip)
VRPNDeviceClient(std::string deviceName, std::string ip):
DeviceClient(deviceName, ip),
Module(deviceName+"@"+ip)
{}
///
......
......@@ -117,102 +117,51 @@ SimulationManager::removeScene(std::string sceneName)
}
bool
SimulationManager::isDeviceServerRegistered(std::string serverName) const
SimulationManager::isModuleRegistered(std::string moduleName) const
{
return m_deviceServerMap.find(serverName) != m_deviceServerMap.end();
return m_modulesMap.find(moduleName) != m_modulesMap.end();
}
std::shared_ptr<VRPNDeviceServer>
SimulationManager::getDeviceServer(std::string serverName) const
std::shared_ptr<Module>
SimulationManager::getModule(std::string moduleName) const
{
if (!this->isDeviceServerRegistered(serverName))
if (!this->isModuleRegistered(moduleName))
{
LOG(WARNING) << "No device server at '" << serverName
LOG(WARNING) << "No module named '" << moduleName
<< "' was registered in this simulation";
return nullptr;
}
return m_deviceServerMap.at(serverName);
return m_modulesMap.at(moduleName);
}
void
SimulationManager::addDeviceServer(std::shared_ptr<VRPNDeviceServer> newServer)
SimulationManager::addModule(std::shared_ptr<Module> newModule)
{
std::string newServerName = newServer->getName();
std::string newModuleName = newModule->getName();
if (this->isDeviceServerRegistered(newServerName))
if (this->isModuleRegistered(newModuleName))
{
LOG(WARNING) << "Can not add device server: '" << newServerName
<< "' is already registered in this simulation\n"
<< "Set this server address to a unique ip:port first";
LOG(WARNING) << "Can not addmodule: '" << newModuleName
<< "' is already registered in this simulation\n";
return;
}
m_deviceServerMap[newServerName] = newServer;
LOG(INFO) << "Device server added: " << newServerName;
m_modulesMap[newModuleName] = newModule;
LOG(INFO) << "Module added: " << newModuleName;
}
void
SimulationManager::removeDeviceServer(std::string serverName)
SimulationManager::removeModule(std::string moduleName)
{
if (!this->isDeviceServerRegistered(serverName))
if (!this->isModuleRegistered(moduleName))
{
LOG(WARNING) << "No device server at '" << serverName
LOG(WARNING) << "No module named '" << moduleName
<< "' was registered in this simulation";
return;
}
m_deviceServerMap.erase(serverName);
LOG(INFO) << "Device server removed: " << serverName;
}
bool
SimulationManager::isDeviceClientRegistered(std::string deviceClientName) const
{
return m_deviceClientMap.find(deviceClientName) != m_deviceClientMap.end();
}
std::shared_ptr<DeviceClient>
SimulationManager::getDeviceClient(std::string deviceClientName) const
{
if (!this->isDeviceClientRegistered(deviceClientName))
{
LOG(WARNING) << "No device client named '" << deviceClientName
<< "' was registered in this simulation";
return nullptr;
}
return m_deviceClientMap.at(deviceClientName);
}
void
SimulationManager::addDeviceClient(std::shared_ptr<DeviceClient> newDeviceClient)
{
std::string newDeviceClientName = newDeviceClient->getName();
if (this->isDeviceClientRegistered(newDeviceClientName))
{
LOG(WARNING) << "Can not add device client: '" << newDeviceClientName
<< "' is already registered in this simulation\n"
<< "Set this device name to a unique name first";
return;
}
m_deviceClientMap[newDeviceClientName] = newDeviceClient;
LOG(INFO) << "Device client added: " << newDeviceClientName;
}
void
SimulationManager::removeDeviceClient(std::string deviceClientName)
{
if (!this->isDeviceClientRegistered(deviceClientName))
{
LOG(WARNING) << "No device client named '" << deviceClientName
<< "' was registered in this simulation";
return;
}
m_deviceClientMap.erase(deviceClientName);
LOG(INFO) << "Device client removed: " << deviceClientName;
m_modulesMap.erase(moduleName);
LOG(INFO) << "Module removed: " << moduleName;
}
std::shared_ptr<Viewer>
......@@ -317,14 +266,8 @@ SimulationManager::startSimulation(bool debug)
LOG(INFO) << "Starting simulation";
m_viewer->setRenderingMode(Renderer::Mode::SIMULATION);
// Start device servers
for(const auto& pair : m_deviceServerMap)
{
this->startModuleInNewThread(pair.second);
}
// Start device clients
for(const auto& pair : m_deviceClientMap)
// Start modules
for(const auto& pair : m_modulesMap)
{
this->startModuleInNewThread(pair.second);
}
......@@ -369,14 +312,8 @@ SimulationManager::runSimulation()
// Run scene
m_sceneManagerMap.at(m_currentSceneName)->run();
// Run device servers
for(const auto& pair : m_deviceServerMap)
{
(pair.second)->run();
}
// Run device clients
for(const auto& pair : m_deviceClientMap)
// Run modules
for(const auto& pair : m_modulesMap)
{
(pair.second)->run();
}
......@@ -399,14 +336,8 @@ SimulationManager::pauseSimulation()
// Pause scene
m_sceneManagerMap.at(m_currentSceneName)->pause();
// Pause device clients
for(const auto& pair : m_deviceClientMap)
{
(pair.second)->pause();
}
// Pause device servers
for(const auto& pair : m_deviceServerMap)
// Pause modules
for(const auto& pair : m_modulesMap)
{
(pair.second)->pause();
}
......@@ -430,15 +361,8 @@ SimulationManager::endSimulation()
// Update Renderer
m_viewer->setRenderingMode(Renderer::Mode::DEBUG);
// End device clients
for(const auto& pair : m_deviceClientMap)
{
(pair.second)->end();
m_threadMap.at(pair.first).join();
}
// Pause device servers
for(const auto& pair : m_deviceServerMap)
// End modules
for(const auto& pair : m_modulesMap)
{
(pair.second)->end();
m_threadMap.at(pair.first).join();
......@@ -467,4 +391,4 @@ SimulationManager::startModuleInNewThread(std::shared_ptr<Module>module)
m_threadMap[module->getName()] = std::thread([module] { module->start(); });
}
} // imstk
\ No newline at end of file
} // imstk
......@@ -28,8 +28,7 @@
#include <memory>
#include "imstkScene.h"
#include "imstkVRPNDeviceServer.h"
#include "imstkDeviceClient.h"
#include "imstkModule.h"
#include "imstkSceneManager.h"
#include "imstkViewer.h"
#include "imstkLogger.h"
......@@ -103,49 +102,27 @@ public:
///
void removeScene(std::string sceneName);
// Device Server
// Modules
///
/// \brief
///
bool isDeviceServerRegistered(std::string serverName) const;
bool isModuleRegistered(std::string moduleName) const;
///
/// \brief
///
std::shared_ptr<VRPNDeviceServer> getDeviceServer(std::string serverName) const;
std::shared_ptr<Module> getModule(std::string moduleName) const;
///
/// \brief
///
void addDeviceServer(std::shared_ptr<VRPNDeviceServer> newServer);
void addModule(std::shared_ptr<Module> newModule);
///
/// \brief
///
void removeDeviceServer(std::string serverName);
// Device Client
///
/// \brief
///
bool isDeviceClientRegistered(std::string deviceClientName) const;
///
/// \brief
///
std::shared_ptr<DeviceClient> getDeviceClient(std::string deviceClientName) const;
///
/// \brief
///
void addDeviceClient(std::shared_ptr<DeviceClient> newDeviceClient);
///
/// \brief
///
void removeDeviceClient(std::string deviceClientName);
void removeModule(std::string moduleName);
// Viewer
std::shared_ptr<Viewer> getViewer() const;
......@@ -185,8 +162,7 @@ private:
std::string m_currentSceneName = "";
std::unordered_map<std::string, std::shared_ptr<SceneManager>> m_sceneManagerMap;
std::unordered_map<std::string, std::shared_ptr<VRPNDeviceServer>> m_deviceServerMap;
std::unordered_map<std::string, std::shared_ptr<DeviceClient>> m_deviceClientMap;
std::unordered_map<std::string, std::shared_ptr<Module>> m_modulesMap;
std::unordered_map<std::string, std::thread> m_threadMap;
......
......@@ -41,6 +41,7 @@
// Devices
#include "imstkHDAPIDeviceClient.h"
#include "imstkHDAPIDeviceServer.h"
#include "imstkVRPNDeviceClient.h"
#include "imstkVRPNDeviceServer.h"
#include "imstkCameraController.h"
......@@ -103,8 +104,8 @@ int main()
//testMultiTextures();
//testMeshCCD();
//testPenaltyRigidCollision();
//testTwoFalcons();
//testPenaltyRigidCollision();
//testTwoFalcons();
//testObjectController();
//testCameraController();
//testViewer();
......@@ -119,20 +120,21 @@ int main()
//testDeformableBody();
//testVTKTexture();