Commit 7f693f54 authored by fmg005's avatar fmg005

Added realtime capability v2.0

parent 617b5c11
......@@ -8,34 +8,47 @@ my_serial, CLA::LOGGER* logger):m_serial(my_serial), m_logger(logger) {
HardwareSimulator::HardwareSimulator(serial::Serial*
my_serial, CLA::LOGGER* logger, CLA::Environment* env):m_serial(my_serial), m_logger(logger), m_env(env) {
nextUpdateTime = 0;
respondToData = &HardwareSimulator::SetInitialIBP;
}
void HardwareSimulator::update(std::unique_ptr<PhysiologyEngine>& engine) {
((this)->*respondToData)(engine);
}
void HardwareSimulator::SetInitialIBP(std::unique_ptr<PhysiologyEngine>& engine) {
void HardwareSimulator::update(std::unique_ptr<PhysiologyEngine>& engine) {
/*
synchronize simulation time to real clock
i.e., 1s of Simulation = 1s of real-time
*/
m_start = system_clock::now();
engine->AdvanceModelTime(advance_time, TimeUnit::s);
m_end = system_clock::now();
m_command_start = system_clock::now();
systolic_pressure = engine->GetCardiovascularSystem()->GetSystolicArterialPressure(PressureUnit::mmHg);
diastolic_pressure = engine->GetCardiovascularSystem()->GetDiastolicArterialPressure(PressureUnit::mmHg);
double hr = engine->GetCardiovascularSystem()->GetHeartRate(FrequencyUnit::Per_min);
SetIBP(1, systolic_pressure, diastolic_pressure);
nextUpdateTime = m_env->time_index + DELAY_5_SECONDS;
//cout<< engine->GetSimulationTime(TimeUnit::s)<<endl;
respondToData = &HardwareSimulator::updateIBP;
}
SetHeartRate(hr);
m_command_end = system_clock::now();
void HardwareSimulator::updateIBP(std::unique_ptr<PhysiologyEngine>& engine) {
if(m_env->time_index == nextUpdateTime) {
systolic_pressure = engine->GetCardiovascularSystem()->GetSystolicArterialPressure(PressureUnit::mmHg);
diastolic_pressure = engine->GetCardiovascularSystem()->GetDiastolicArterialPressure(PressureUnit::mmHg);
/* start time for the next execution */
duration<double> m_next_start(real_time); // seconds
m_real_time = system_clock::to_time_t(m_start) + m_next_start.count();
SetIBP(1, systolic_pressure, diastolic_pressure);
nextUpdateTime = m_env->time_index + DELAY_5_SECONDS;
//cout<< engine->GetSimulationTime(TimeUnit::s)<<endl;
respondToData = &HardwareSimulator::updateIBP;
m_advance_duration_ms = duration_cast<milliseconds>(m_end - m_start).count();
m_command_duration_ms = duration_cast<milliseconds>(m_command_end - m_command_start).count();
m_real_time_duration_ms = duration_cast<milliseconds>(m_next_start).count();
/* checking if simulation will take longer than allotted 'time' */
if (m_advance_duration_ms + m_command_duration_ms > m_real_time_duration_ms)
m_logger->error("Simulation too slow");
/* wait until start time of next execution is reached i.e., time:s of real-time */
while(true) {
m_delta = m_real_time - system_clock::to_time_t(system_clock::now());
if (m_delta <= 0)
break;
std::this_thread::sleep_for(milliseconds(m_delta));
}
/* track data */
engine->GetEngineTracker()->TrackData(engine->GetSimulationTime(TimeUnit::s));
}
void HardwareSimulator::LoadConfig(const char* file_path) {
......@@ -48,9 +61,8 @@ void HardwareSimulator::LoadConfig(const char* file_path) {
catch(const ParseException &pex) {
m_logger->error("Error parsing configuration file");
}
DELAY_5_SECONDS = cfg.lookup("prosim.delay_5_sec");
DELAY_5_SECONDS = DELAY_5_SECONDS/m_env->engine_timestep; // 5 seconds delay
advance_time = cfg.lookup("pulse.advance_time");
real_time = cfg.lookup("prosim.real_time");
}
bool HardwareSimulator::isOpen() {
......@@ -59,12 +71,17 @@ bool HardwareSimulator::isOpen() {
/* HR range: 10-360 */
void HardwareSimulator::SetHeartRate(double rate) {
if (rate >= 10 && rate <= 360) {
SendCommand("NSRA=0"+std::to_string(rate));
m_logger->info("Heart rate set to "+to_string(rate)+" bpm");
int heart_rate = static_cast<int>(rate);
if (rate >= 10 && rate < 100) {
SendCommand("NSRA=0"+to_string(heart_rate));
m_logger->info("Heart rate set to "+to_string(heart_rate)+" bpm");
}
else if (rate > 100 ) {
SendCommand("NSRA="+to_string(heart_rate));
m_logger->info("Heart rate set to "+to_string(heart_rate)+" bpm");
}
else {
m_logger->warning("Heart rate value: "+to_string(rate)+" not within acceptable range 10-360");
m_logger->warning("Heart rate value: "+to_string(heart_rate)+" not within acceptable range 10-360");
}
}
......@@ -164,7 +181,7 @@ string HardwareSimulator::GetCurrentMode() {
size_t HardwareSimulator::SendCommand(string command) {
size_t bytes_sent = m_serial->write(command+"\r\n");
usleep(100); // sleep for 100ms
std::this_thread::sleep_for(milliseconds(100));
return bytes_sent;
}
......
#include "Realtime.h"
using namespace CLA;
Realtime::Realtime(std::unique_ptr<PhysiologyEngine>& engine, CLA::LOGGER*
logger): m_engine(engine), m_logger(logger) {
}
void Realtime::AdvanceModelTime(double time) {
/*
synchronize simulation time to real clock
i.e., 1s of Simulation = 1s of real-time
*/
m_start = clock();
m_engine->AdvanceModelTime(1.0, TimeUnit::s);
m_end = clock();
/* start time for the next execution */
m_next_start = CLOCKS_PER_SEC * time;
m_real_time = m_start + m_next_start;
/* checking if simulation will take longer than allotted 'time' */
if ((m_end - m_start) > m_next_start)
m_logger->error("Simulation too slow");
/* wait until start time of next execution is reached i.e., 1s of real-time */
while(true) {
m_delta = m_real_time - clock();
if (m_delta <= 0)
break;
m_delta_secs = long(((double)m_delta)/CLOCKS_PER_SEC);
std::this_thread::sleep_for(std::chrono::seconds(m_delta_secs));
}
/* track data */
m_engine->GetEngineTracker()->TrackData(m_engine->GetSimulationTime(TimeUnit::s));
}
Realtime::~Realtime() {
}
......@@ -4,13 +4,12 @@
#include <vector>
#include <map>
#include <libconfig.h++>
#include <time.h> /* clock_t, clock, CLOCKS_PER_SEC */
#include "serial/serial.h"
#include "HardwareSimulator.h"
#include "CLA_Logger.h"
#include "SimulationEngine.h"
#include "Realtime.h"
#include "Timer.h"
// Include the various types you will be using in your code
#include "scenario/SEDataRequestManager.h"
......@@ -36,13 +35,13 @@
using namespace libconfig;
int main(){
int main() {
CLA::Timer timer;
auto cf = std::make_shared<Config>();
string f_path = prosim_config_dir+"scenario.cfg";
const char* filepath = f_path.c_str();
Simulation("Hassan", cf, filepath);
Simulation("Cynthia", cf, filepath);
}
void Simulation(const string patient_name, const std::shared_ptr<Config>& cfg, const char* filepath )
......@@ -62,7 +61,7 @@ void Simulation(const string patient_name, const std::shared_ptr<Config>& cfg, c
pe->GetEngineTracker()->GetDataRequestManager().SetResultsFilename(prosim_results_dir+"PulseSimEngine_"+patient_name+".txt");
SEHemorrhage hemorrhageLeg;
double initialMAP = 76.0;
double initialMAP = 70.0;
double currentMAP;
CLA::Environment sim_env;
Global_LoadConfig(pe, cfg, filepath, &sim_env);
......@@ -85,18 +84,17 @@ void Simulation(const string patient_name, const std::shared_ptr<Config>& cfg, c
bool STOP = false; // Execute stop hemmorrhage only once; without this it be executed for each timestep
bool DEVICES_START = false;
CLA::Realtime rt(pe, &logger);
prosim.SetRemoteMode();
// stop when the set time is reached
while (sim_env.time_index <= sim_env.simulation_timesteps) {
// event_hemorrage_start
if(sim_env.time_index == sim_env.simulation_injury_start_timestep) {
cout<< "The time_index "<<sim_env.time_index;
// Hemorrhage Starts - instantiate a hemorrhage action and have the engine process it
cout<<"\nHemorrhage Started at: "<<pe->GetSimulationTime(TimeUnit::s)<<endl;
hemorrhageLeg.SetCompartment(pulse::VascularCompartment::RightLeg);
//the rate of hemorrhage
hemorrhageLeg.GetRate().SetValue(150,VolumePerTimeUnit::mL_Per_min);
hemorrhageLeg.GetRate().SetValue(350,VolumePerTimeUnit::mL_Per_min);
pe->ProcessAction(hemorrhageLeg);
STOP = true;
}
......@@ -109,18 +107,9 @@ void Simulation(const string patient_name, const std::shared_ptr<Config>& cfg, c
hemorrhageLeg.GetRate().SetValue(0,VolumePerTimeUnit::mL_Per_min);
pe->ProcessAction(hemorrhageLeg);
STOP = false;
DEVICES_START = true; // instruct devices to start
cout << "START DEVICES" << endl;
}
if(DEVICES_START) {
/* We both track data and advance engine inside the update method */
prosim.update(pe);
}
// track patient data
//pe->GetEngineTracker()->TrackData(pe->GetSimulationTime(TimeUnit::s));
//pe->AdvanceModelTime();
rt.AdvanceModelTime(1.0);//Advance Engine at 1s in real time
sim_env.time_index++;
}// End while looop
}// End Simulation function
......@@ -140,9 +129,8 @@ void Global_LoadConfig(std::unique_ptr<PhysiologyEngine>& engine, const std::sha
env->simulation_injury_start = cf->lookup("simulation.time.injury_start");
env->simulation_injury_stop = cf->lookup("simulation.time.injury_stop");
env->time_index = 0; // initialize the time index
//env->engine_timestep = engine->GetTimeStep(TimeUnit::s);
env->engine_timestep = 1.0;
env->simulation_timesteps = env->simulation_time / env->engine_timestep;
env->engine_timestep = cf->lookup("pulse.advance_time");
env->simulation_timesteps = env->simulation_time/env->engine_timestep;
env->simulation_injury_start_timestep = env->simulation_injury_start/env->engine_timestep;
env->simulation_injury_stop_timestep = env->simulation_injury_stop/env->engine_timestep;
}// End Global_LoadConfig
......@@ -5,6 +5,8 @@
#include <iostream>
#include <cstdio>
#include <unistd.h>
#include <chrono>
#include <thread>
#include <libconfig.h++>
#include "serial/serial.h"
#include "CLA_Logger.h"
......@@ -14,10 +16,13 @@
#include "PulsePhysiologyEngine.h"
#include "properties/SEScalarTime.h"
#include "properties/SEScalarPressure.h"
#include "properties/SEScalarFrequency.h"
#include "engine/SEEngineTracker.h"
#include "system/physiology/SECardiovascularSystem.h"
using namespace std;
using namespace libconfig;
using namespace std::chrono;
class HardwareSimulator {
......@@ -30,10 +35,20 @@ private:
string GetResponse();
double systolic_pressure;
double diastolic_pressure;
double nextUpdateTime;
double DELAY_5_SECONDS;
double advance_time;
double real_time;
Config cfg; // API for accessing configuration files
string mode;
/* chrono */
system_clock::time_point m_start;
system_clock::time_point m_end;
system_clock::time_point m_command_start;
system_clock::time_point m_command_end;
time_t m_delta;
time_t m_real_time;
time_t m_advance_duration_ms;
time_t m_command_duration_ms;
time_t m_real_time_duration_ms;
public:
HardwareSimulator(serial::Serial*, CLA::LOGGER*, CLA::Environment*);
......@@ -47,9 +62,6 @@ public:
void SetRemoteMode();
void SetLocalMode();
string GetCurrentMode();
void updateIBP(std::unique_ptr<PhysiologyEngine>&);
void SetInitialIBP(std::unique_ptr<PhysiologyEngine>&);
void (HardwareSimulator::*respondToData)(std::unique_ptr<PhysiologyEngine>&);
void update(std::unique_ptr<PhysiologyEngine>&);
void LoadConfig(const char*);
};
......
#ifndef REALTIME2_H
#define REALTIME2_H
#include <time.h>
#include <string>
#include <chrono>
#include <thread>
#include <libconfig.h++>
#include "CLA_Logger.h"
#include "PulsePhysiologyEngine.h"
#include "engine/SEEngineTracker.h"
#include "scenario/SEDataRequest.h"
#include "properties/SEScalarTime.h"
using namespace libconfig;
using namespace std;
namespace CLA {
class Realtime {
private:
std::unique_ptr<PhysiologyEngine>& m_engine;
CLA::LOGGER* m_logger;
Config m_cfg;
clock_t m_real_time, real_start, m_delta, m_start, m_end;
clock_t m_next_start;
long m_delta_secs;
public:
Realtime(std::unique_ptr<PhysiologyEngine>&, CLA::LOGGER*);
~Realtime();
void AdvanceModelTime(double);
};
}
#endif
......@@ -61,7 +61,7 @@ set( my_srcs
CLA_Logger.cpp
#example.cpp
SimulationEngine.cpp
Realtime.cpp
Timer.cpp
)
add_executable(prosim ${my_srcs})
......
......@@ -5,13 +5,14 @@ pulse = {
}
prosim = {
real_time = 5.0; # Real time -> seconds
real_time = 1.0; # Real time -> seconds
}
simulation = {
time = {
run = 60.0; # Time -> Seconds How long should simulation run
injury_start = 5.0; # When should injury be introduced to patient
run = 180.0; # Time -> Seconds How long should simulation run
injury_start = 60.0; # When should injury be introduced to patient
injury_stop = 700.0; # When should injury be stopped
}
}
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