Commit 7714bb2d authored by Alexis Girault's avatar Alexis Girault

ENH: Add scene API in SimulationManager

parent 66bb6b9b
......@@ -24,92 +24,105 @@
#include <iostream>
namespace imstk {
void Module::exec()
void
Module::start()
{
m_status = ModuleStatus::RUNNING;
if (m_status != ModuleStatus::INACTIVE)
{
std::cerr << "Can not start " << m_name << std::endl
<< "Module already/still active." << std::endl;
return;
}
// Init
m_status = ModuleStatus::STARTING;
this->initModule();
m_status = ModuleStatus::RUNNING;
// Keep active, wait for terminating call
while (m_status != ModuleStatus::TERMINATING)
{
if (m_status == ModuleStatus::RUNNING)
if (m_status == ModuleStatus::PAUSING)
{
m_status = ModuleStatus::PAUSED;
}
else if (m_status == ModuleStatus::RUNNING)
{
this->runModule();
std::this_thread::sleep_for(std::chrono::milliseconds(m_loopDelay));
}
}
// Cleanup
this->cleanUpModule();
m_status = ModuleStatus::INACTIVE;
}
void Module::run()
void
Module::run()
{
switch (m_status)
if (m_status != ModuleStatus::PAUSED)
{
case ModuleStatus::PAUSED:
m_status = ModuleStatus::RUNNING;
break;
case ModuleStatus::RUNNING:
std::cerr << "Can not run " << m_name << std::endl
<< "Module already running." << std::endl;
break;
default:
std::cerr << "Can not run " << m_name << std::endl
<< "Module terminating or not active."
<< "Run `module::exec()` to launch your module." << std::endl;
break;
<< "Module not paused." << std::endl;
return;
}
m_status = ModuleStatus::RUNNING;
}
void Module::pause()
void
Module::pause()
{
switch (m_status)
if (m_status != ModuleStatus::RUNNING)
{
case ModuleStatus::RUNNING:
m_status = ModuleStatus::PAUSED;
break;
case ModuleStatus::PAUSED:
std::cerr << "Can not pause " << m_name << std::endl
<< "Module already running." << std::endl;
break;
default:
std::cerr << "Can not pause " << m_name << std::endl
<< "Module terminating or not active."
<< "Run `module::exec()` to launch your module." << std::endl;
break;
<< "Module not running." << std::endl;
return;
}
m_status = ModuleStatus::PAUSING;
while (m_status != ModuleStatus::PAUSED) {}
}
void Module::terminate()
void
Module::end()
{
switch (m_status)
if ((m_status == ModuleStatus::INACTIVE) ||
(m_status == ModuleStatus::TERMINATING))
{
case ModuleStatus::TERMINATING:
std::cerr << "Can not terminate " << m_name << std::endl
<< "Module already terminating." << std::endl;
break;
case ModuleStatus::INACTIVE:
std::cerr << "Can not terminate " << m_name << std::endl
<< "Module not active."
<< "Run `module::exec()` to launch your module." << std::endl;
break;
default:
m_status = ModuleStatus::TERMINATING;
break;
std::cerr << "Can not end " << m_name << std::endl
<< "Module alreading inactive or terminating." << std::endl;
return;
}
m_status = ModuleStatus::TERMINATING;
while (m_status != ModuleStatus::INACTIVE) {}
}
const ModuleStatus& Module::getStatus() const
const ModuleStatus&
Module::getStatus() const
{
return m_status;
}
const std::string& Module::getName() const
const std::string&
Module::getName() const
{
return m_name;
}
const int&
Module::getLoopDelay() const
{
return m_loopDelay;
}
void
Module::setLoopDelay(int milliseconds)
{
m_loopDelay = milliseconds;
}
}
......@@ -23,14 +23,17 @@
#define imstkModule_h
#include <iostream>
#include <thread>
namespace imstk {
enum class ModuleStatus
{
INACTIVE,
STARTING,
RUNNING,
PAUSING,
PAUSED,
TERMINATING
TERMINATING,
INACTIVE
};
class Module
......@@ -39,13 +42,15 @@ public:
~Module() = default;
void exec();
void start();
void run();
void pause();
void terminate();
void end();
const ModuleStatus& getStatus() const;
const std::string & getName() const;
const int & getLoopDelay() const;
void setLoopDelay(int milliseconds);
protected:
......@@ -57,6 +62,7 @@ protected:
ModuleStatus m_status = ModuleStatus::INACTIVE;
std::string m_name;
int m_loopDelay = 0;
};
}
......
......@@ -21,19 +21,21 @@
#include "imstkScene.h"
#include <thread>
namespace imstk {
void Scene::initModule()
{
std::cout << std::endl << m_name << " : init" << std::endl;
std::cout << m_name << " : init" << std::endl;
}
void Scene::cleanUpModule()
{
std::cout << std::endl << m_name << " : cleanUp" << std::endl;
std::cout << m_name << " : cleanUp" << std::endl;
}
void Scene::runModule()
{
std::cout << "." << std::flush;
std::cout << m_name << " : running" << std::endl;
}
}
......@@ -21,4 +21,242 @@
#include "imstkSimulationManager.h"
namespace imstk {}
#include <string>
namespace imstk {
const
SimulationStatus& SimulationManager::getStatus() const
{
return m_status;
}
bool
SimulationManager::isSceneRegistered(std::string sceneName)
{
return !(m_sceneMap.find(sceneName) == m_sceneMap.end());
}
std::shared_ptr<Scene>
SimulationManager::getScene(std::string sceneName)
{
if (!this->isSceneRegistered(sceneName))
{
std::cerr << "No scene named '" << sceneName
<< "' was registered in this simulation." << std::endl;
return nullptr;
}
return m_sceneMap.at(sceneName);
}
std::shared_ptr<Scene>
SimulationManager::createNewScene(std::string newSceneName)
{
if (this->isSceneRegistered(newSceneName))
{
std::cerr << "Can not create new scene: '" << newSceneName
<< "' is already registered in this simulation." << std::endl
<< "You can create a new scene using an unique name." << std::endl;
return nullptr;
}
m_sceneMap[newSceneName] = std::make_shared<Scene>(newSceneName);
std::cout << "New scene added: " << newSceneName << std::endl;
return m_sceneMap.at(newSceneName);
}
std::shared_ptr<Scene>
SimulationManager::createNewScene()
{
int id = m_sceneMap.size() + 1;
std::string newSceneName = "Scene_" + std::to_string(id);
return this->createNewScene(newSceneName);
}
void
SimulationManager::addScene(std::shared_ptr<Scene>newScene)
{
std::string newSceneName = newScene->getName();
if (this->isSceneRegistered(newSceneName))
{
std::cerr << "Can not add scene: '" << newSceneName
<< "' is already registered in this simulation." << std::endl
<< "Set this scene name to a unique name first." << std::endl;
return;
}
m_sceneMap[newSceneName] = newScene;
std::cout << "Scene added: " << newSceneName << std::endl;
}
void
SimulationManager::removeScene(std::string sceneName)
{
if (!this->isSceneRegistered(sceneName))
{
std::cerr << "No scene named '" << sceneName
<< "' was registered in this simulation." << std::endl;
return;
}
m_sceneMap.erase(sceneName);
std::cout << "Scene removed: " << sceneName << std::endl;
}
void
SimulationManager::startSimulation(std::string sceneName)
{
std::cout << "Starting simulation." << std::endl;
if (m_status != SimulationStatus::INACTIVE)
{
std::cerr << "Simulation already active." << std::endl;
return;
}
std::shared_ptr<Scene> startingScene = this->getScene(sceneName);
if (!startingScene)
{
std::cerr << "Simulation canceled." << std::endl;
return;
}
if (startingScene->getStatus() != ModuleStatus::INACTIVE)
{
std::cerr << "Scene '" << sceneName << "' is already active." << std::endl
<< "Simulation canceled." << std::endl;
return;
}
// Start scene
this->startModuleInNewThread(startingScene);
m_currentSceneName = sceneName;
// Update simulation status
m_status = SimulationStatus::RUNNING;
}
void
SimulationManager::switchScene(std::string newSceneName, bool unloadCurrentScene)
{
std::cout << "Switching scene." << std::endl;
if ((m_status != SimulationStatus::RUNNING) &&
(m_status != SimulationStatus::PAUSED))
{
std::cerr << "Simulation not active, can not switch scenes." << std::endl;
return;
}
if (newSceneName == m_currentSceneName)
{
std::cerr << "Scene '" << newSceneName << "' is already running." << std::endl;
return;
}
std::shared_ptr<Scene> newScene = this->getScene(newSceneName);
if (!newScene)
{
std::cerr << "Can not switch scenes." << std::endl;
return;
}
if (unloadCurrentScene)
{
// Stop current scene
std::cout << "Unloading '" << m_currentSceneName << "'." << std::endl;
m_sceneMap.at(m_currentSceneName)->end();
m_threadMap.at(m_currentSceneName).join();
}
else
{
// Pause current scene
m_sceneMap.at(m_currentSceneName)->pause();
}
if (newScene->getStatus() == ModuleStatus::INACTIVE)
{
// Start new scene
this->startModuleInNewThread(newScene);
}
else if (newScene->getStatus() == ModuleStatus::PAUSED)
{
// Run new scene
newScene->run();
}
m_currentSceneName = newSceneName;
}
void
SimulationManager::runSimulation()
{
std::cout << "Running simulation." << std::endl;
if (m_status != SimulationStatus::PAUSED)
{
std::cerr << "Simulation not paused, can not run." << std::endl;
return;
}
m_sceneMap.at(m_currentSceneName)->run();
m_status = SimulationStatus::RUNNING;
}
void
SimulationManager::pauseSimulation()
{
std::cout << "Pausing simulation." << std::endl;
if (m_status != SimulationStatus::RUNNING)
{
std::cerr << "Simulation not running, can not pause." << std::endl;
return;
}
// Pause scene
m_sceneMap.at(m_currentSceneName)->pause();
// Update simulation status
m_status = SimulationStatus::PAUSED;
}
void
SimulationManager::endSimulation()
{
std::cout << "Ending simulation." << std::endl;
if ((m_status != SimulationStatus::RUNNING) &&
(m_status != SimulationStatus::PAUSED))
{
std::cerr << "Simulation already terminated." << std::endl;
return;
}
// End all scenes
for (auto pair : m_sceneMap)
{
std::string sceneName = pair.first;
ModuleStatus sceneStatus = m_sceneMap.at(sceneName)->getStatus();
if (sceneStatus != ModuleStatus::INACTIVE)
{
m_sceneMap.at(sceneName)->end();
m_threadMap.at(sceneName).join();
}
}
// Update simulation status
m_status = SimulationStatus::INACTIVE;
}
void
SimulationManager::startModuleInNewThread(std::shared_ptr<Module>module)
{
m_threadMap[module->getName()] = std::thread([module] { module->start(); });
}
}
......@@ -28,21 +28,42 @@
#include <imstkScene.h>
namespace imstk {
using SimulationStatus = ModuleStatus;
class SimulationManager
{
public:
SimulationManager() = default;
~SimulationManager() = default;
const SimulationStatus& getStatus() const;
// Scene
std::shared_ptr<Scene> createNewScene(std::string newSceneName);
std::shared_ptr<Scene> createNewScene();
void addScene(std::shared_ptr<Scene>newScene);
void removeScene(std::string sceneName);
std::shared_ptr<Scene> getScene(std::string sceneName);
bool isSceneRegistered(std::string sceneName);
// Simulation
void startSimulation(std::string sceneName);
void switchScene(std::string newSceneName,
bool unloadCurrentScene);
void runSimulation();
void pauseSimulation();
void endSimulation();
private:
SimulationManager() = default;
void startModuleInNewThread(std::shared_ptr<Module>module);
std::map<std::string, std::shared_ptr<Scene> > sceneMap;
std::size_t activeSceneID;
std::vector<std::thread> threads;
std::string m_currentSceneName;
std::map<std::string, std::shared_ptr<Scene> > m_sceneMap;
std::map<std::string, std::thread> m_threadMap;
SimulationStatus m_status = SimulationStatus::INACTIVE;
};
}
......
......@@ -27,5 +27,5 @@ add_executable(${PROJECT_NAME} main.cpp)
# Link libraries to executable
#-----------------------------------------------------------------------------
target_link_libraries(${PROJECT_NAME}
Scene
SimulationManager
)
......@@ -3,8 +3,7 @@
#include <memory>
#include <thread>
#include "imstkScene.h"
#include "imstkSimulationManager.h"
int main()
{
......@@ -12,22 +11,53 @@ int main()
<< "Starting Sandbox" << std::endl
<< "****************" << std::endl;
// Creating SimulationManager
std::shared_ptr<imstk::SimulationManager> sdk =
std::make_shared<imstk::SimulationManager>();
std::cout << "-- Test add scenes" << std::endl;
// Create scene and add it (scene1)
std::shared_ptr<imstk::Scene> scene1 =
std::make_shared<imstk::Scene>("Scene1");
std::make_shared<imstk::Scene>("scene1");
scene1->setLoopDelay(500);
sdk->addScene(scene1);
// Create new scene through sdk (scene2)
sdk->createNewScene("scene2");
std::shared_ptr<imstk::Scene> scene2 = sdk->getScene("scene2");
scene2->setLoopDelay(500);
// Create new scene through sdk (auto : "Scene_X")
std::shared_ptr<imstk::Scene> scene3 = sdk->createNewScene();
std::thread t1([scene1]{scene1->exec();});
// Remove scene3
sdk->removeScene("Scene_3");
std::this_thread::sleep_for(std::chrono::milliseconds(500));
scene1->pause();
// Test switch
std::cout << "-- Test scene switch" << std::endl;
sdk->startSimulation("scene1");
std::this_thread::sleep_for(std::chrono::seconds(2));
scene1->run();
std::this_thread::sleep_for(std::chrono::milliseconds(500));
scene1->pause();
sdk->switchScene("scene2", false);
std::this_thread::sleep_for(std::chrono::seconds(2));
scene1->terminate();
t1.join();
sdk->switchScene("scene1", true);
std::this_thread::sleep_for(std::chrono::seconds(2));
sdk->endSimulation();
// Test pause/run
std::cout << "-- Test simulation pause/run" << std::endl;
sdk->startSimulation("scene2");
std::this_thread::sleep_for(std::chrono::seconds(2));
sdk->pauseSimulation();
std::this_thread::sleep_for(std::chrono::seconds(2));
sdk->runSimulation();
std::this_thread::sleep_for(std::chrono::seconds(2));
sdk->pauseSimulation();
std::this_thread::sleep_for(std::chrono::seconds(2));
sdk->endSimulation();
// Quit
while (sdk->getStatus() != imstk::SimulationStatus::INACTIVE) {}
return 0;
}
......@@ -110,7 +110,7 @@ align_right_cmt_at_col=1
align_func_proto_span=3
nl_end_of_file_min=1
nl_func_var_def_blk=1
code_width=82
code_width=100
nl_max=3
nl_after_func_proto=0
nl_after_func_body=2
......@@ -240,4 +240,4 @@ mod_full_brace_for=remove
mod_full_brace_if=remove
mod_full_brace_while=remove
mod_paren_on_return=remove
pp_space=add
\ No newline at end of file
pp_space=add
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment