Commit 432d0fbc authored by fmg005's avatar fmg005
Browse files

Implemented algorithm for controller 1

parent 03a04232
project(CMD_SIM)
cmake_minimum_required(VERSION 3.9.4)
project(cmd)
find_path(CONFIG++_INCLUDE_DIR libconfig.h++ /usr/include /usr/local/include)
find_library(CONFIG++_LIBRARY NAMES config++ PATH /usr/lib /usr/local/lib)
# header files
include_directories(include)
# source files directory -> handle multiple controllers
......@@ -19,51 +23,25 @@ set(MY_SOURCE_FILES
)
source_group("" FILES ${MY_SOURCE_FILES})
set(SOURCE ${MY_SOURCE_FILES})
add_executable(HowToDriver EXCLUDE_FROM_ALL ${SOURCE})
# Preprocessor Definitions and Include Paths
set(FLAGS)
target_include_directories(HowToDriver PRIVATE ${CMAKE_INSTALL_PREFIX}/include)
target_include_directories(HowToDriver PRIVATE ${CMAKE_INSTALL_PREFIX}/include/cdm)
target_include_directories(HowToDriver PRIVATE ${CMAKE_INSTALL_PREFIX}/include/bind)
set_target_properties(HowToDriver PROPERTIES COMPILE_FLAGS "${FLAGS}" PREFIX "")
# Dependent Libraries
if(WIN32)
set(lib_ext "lib")
set(log4cpp_prefix "")
else()
set(lib_ext "a")
set(log4cpp_prefix "lib")
endif()
set(D_LIB_FILES
${CMAKE_INSTALL_PREFIX}/lib/debug${EX_CONFIG}/PulseEngine.${lib_ext}
${CMAKE_INSTALL_PREFIX}/lib/debug${EX_CONFIG}/CommonDataModel.${lib_ext}
${CMAKE_INSTALL_PREFIX}/lib/debug${EX_CONFIG}/DataModelBindings.${lib_ext}
${CMAKE_INSTALL_PREFIX}/lib/debug${EX_CONFIG}/${log4cpp_prefix}log4cpp.${lib_ext}
${CMAKE_INSTALL_PREFIX}/lib/debug${EX_CONFIG}/libprotobufd.${lib_ext}
)
set(O_LIB_FILES
${CMAKE_INSTALL_PREFIX}/lib/release${EX_CONFIG}/PulseEngine.${lib_ext}
${CMAKE_INSTALL_PREFIX}/lib/release${EX_CONFIG}/CommonDataModel.${lib_ext}
${CMAKE_INSTALL_PREFIX}/lib/release${EX_CONFIG}/DataModelBindings.${lib_ext}
${CMAKE_INSTALL_PREFIX}/lib/release${EX_CONFIG}/${log4cpp_prefix}log4cpp.${lib_ext}
${CMAKE_INSTALL_PREFIX}/lib/release${EX_CONFIG}/libprotobuf.${lib_ext}
${CMAKE_INSTALL_PREFIX}/lib/release${EX_CONFIG}/libconfig++.${lib_ext}
)
add_executable(cmd ${MY_SOURCE_FILES})
## This is how you connect that executable to Pulse
# Find the Pulse package
# Again, set Pulse_DIR to the install directory with the PulseConfig.cmake file, or make the developer set this when building the code
find_package(Pulse REQUIRED NO_MODULE) # If you don't, CMake will halt here
# You will now have access to all the variables set in the PulseConfig.cmake in the Pulse install directory
# Go open it and look through to see what you have
target_include_directories(cmd PRIVATE ${Pulse_INCLUDE_DIRS})
target_include_directories(cmd PRIVATE ${CONFIG++_INCLUDE_DIR})
# Some debug libraries have different names than the release libs
target_link_libraries(cmd debug "${Pulse_DEBUG_LIBS}")
target_link_libraries(cmd optimized "${Pulse_LIBS}")
target_link_libraries(cmd optimized "${CONFIG++_LIBRARY}")
foreach(file ${D_LIB_FILES})
target_link_libraries(HowToDriver debug ${file})
endforeach()
foreach(file ${O_LIB_FILES})
target_link_libraries(HowToDriver optimized ${file})
endforeach()
add_custom_command(TARGET HowToDriver POST_BUILD
COMMAND ${CMAKE_COMMAND} -E make_directory ${INSTALL_BIN}/${CONFIGURATION}${EX_CONFIG}
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:HowToDriver> ${INSTALL_BIN}/${CONFIGURATION}${EX_CONFIG})
# That is it, your program is now linked to Pulse
install(TARGETS cmd RUNTIME DESTINATION ${Pulse_INSTALL}/bin)
......@@ -49,6 +49,45 @@ class Controller {
PhysiologyData* m_data;
std::map<string, Pump*> m_pumps;
double WAIT_10;
double WAIT_5;
unsigned long initialize_time_index;
unsigned long checkmap_time_index;
unsigned long ensure_map_time_index;
unsigned long maintain_map_time_index;
unsigned long else_maintain_map_time_index;
bool set_initialize_time_index;
bool set_checkmap_timeindex;
bool set_ensure_map_time_index;
bool set_maintain_map_time_index;
bool set_else_maintain_map_time_index;
bool INITIALIZED;
bool checkmap_initialized;
bool ensure_map_initialized;
bool maintain_map_initialized;
bool else_maintain_map_initialized;
bool DEACTIVATE_INIT;
bool WAIT_FOR_MAP_INCREASE;
bool ENSURE_MAP_DECREASE;
bool MAINTAIN_MAP_RANGE;
bool STAY_IN_2;
bool STAY_IN_3;
bool STAY_IN_4;
bool ELSE_STAY_IN_4;
double currentNorepiRate;
double SalineInfusionRate;
double maxNorepinephrineInfusionRate;
double percentOfRate;
double targetMAPRangeMax;
double targetMAPRangeMin;
double MAPIncreaseThreshold;
double MAP;
//function variable for functions to set pump rates
//void pumpSetRate; // assuming dictionary
......
......@@ -13,8 +13,11 @@
#include "PhysiologyData.h"
#include "patient/actions/SESubstanceCompoundInfusion.h"
#include "patient/actions/SESubstanceInfusion.h"
#include "substance/SESubstanceManager.h"
#include "substance/SESubstanceCompound.h"
#include "properties/SEScalarMassPerVolume.h"
#include "substance/SESubstance.h"
#include "properties/SEScalarVolume.h"
#include "properties/SEScalarVolumePerTime.h"
......@@ -42,13 +45,14 @@ class Pump : public MedicalDevice {
// rate, time_index
vector< pair<int, unsigned long> > pump_data;
vector< pair<double, unsigned long> > pump_data;
CMD::Environment* m_env;
PhysiologyData* m_data;
string m_substance;
SESubstanceCompoundInfusion* m_infusion;
SESubstanceInfusion* bpdrug_infusion;
public:
......@@ -60,7 +64,7 @@ class Pump : public MedicalDevice {
//Overload Constructor
Pump(CMD::Environment*, PhysiologyData*, string);
void ChangePumpRate(int, unsigned long);
void ChangePumpRate(double, unsigned long);
// Device logic will go in here
// This function uses the engine object to query required info
......@@ -69,10 +73,12 @@ class Pump : public MedicalDevice {
// Load all pump configurations
virtual void LoadConfig(std::unique_ptr<PhysiologyEngine>&, const char*);
void SetInfusionRate(std::unique_ptr<PhysiologyEngine>&, int);
void SetInfusionRate(std::unique_ptr<PhysiologyEngine>&, double);
void Stop();
void Clear();
// Destructor
~Pump();
};
......
......@@ -10,6 +10,7 @@ Controller::Controller(): MAX_RATE_Hz(50.0) {
Controller::Controller(CMD::Environment* env, PhysiologyData* data, std::map<string, Pump*>& pumps ) : m_env(env),
m_data(data), m_pumps(pumps), MAX_RATE_Hz(50.0) {
/*
srand(time(0)); // seed values using system time
// initialise array from which rates will be picked randomly
......@@ -17,6 +18,45 @@ Controller::Controller(CMD::Environment* env, PhysiologyData* data, std::map<str
array_rate[1] = 350;
array_rate[2] = 200;
//array_rate[3] = 50;
*/
currentNorepiRate = 0;
SalineInfusionRate = 50.0;
maxNorepinephrineInfusionRate = 112.5;
targetMAPRangeMax = 80.0;
targetMAPRangeMin = 65.0;
MAPIncreaseThreshold = 100;
percentOfRate = 0.5;
MAP = 0;
set_initialize_time_index = false;
set_checkmap_timeindex = false;
set_ensure_map_time_index = false;
set_maintain_map_time_index = false;
set_else_maintain_map_time_index = false;
INITIALIZED = false;
checkmap_initialized = false;
ensure_map_initialized = false;
maintain_map_initialized = false;
else_maintain_map_initialized = false;
STAY_IN_2 = true;
STAY_IN_3 = true;
STAY_IN_4 = true;
ELSE_STAY_IN_4 = true;
DEACTIVATE_INIT = false;
WAIT_FOR_MAP_INCREASE = false;
ENSURE_MAP_DECREASE = false;
MAINTAIN_MAP_RANGE = false;
initialize_time_index = 0;
checkmap_time_index = 0;
ensure_map_time_index = 0;
maintain_map_time_index = 0;
else_maintain_map_time_index = 0;
}
......@@ -24,87 +64,326 @@ Controller::Controller(CMD::Environment* env, PhysiologyData* data, std::map<str
void Controller::update(std::unique_ptr<PhysiologyEngine>& engine) {
// check controller input rate
if (m_env->time_index % input_period == 0) {
// check controller input rate
if (m_env->time_index % input_period == 0) {
cout<<"++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n";
cout<<"Controller receives data from Monitor at: "<<engine->
GetSimulationTime(TimeUnit::s)<<"s\n";
cout<<"++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n";
cout<<"Controller receives data from Monitor at: "<<engine->
GetSimulationTime(TimeUnit::s)<<"s\n";
// Gets data from Monitor
GetData();
// Gets data from Monitor
GetData();
m_env->logger->LogData(
engine->GetSimulationTime(TimeUnit::s),
"Controller",
"RECEIVE",
"Received data from Monitor BP",
patient_state.at(m_env->vector_index-1)
);
m_env->logger->LogData(engine->GetSimulationTime(TimeUnit::s),"Controller",
"RECEIVE","Received data from Monitor BP", patient_state.at(m_env->vector_index-1) );
/*
// why cant't I compare using patient value
double p = patient_state.at(m_env->vector_index-1).pressure;
/*
// why cant't I compare using patient value
double p = patient_state.at(m_env->vector_index-1).pressure;
double value = (int)(p*100 + .5);
double v = (double)value / 100;
double value = (int)(p*100 + .5);
double v = (double)value / 100;
bool x = (p > 95.07);
bool x = (p > 95.07);
cout <<x<<endl;
*/
//if ( x) doesn't work if x is not true for first loop
cout <<x<<endl;
*/
//if ( x) doesn't work if x is not true for first loop
/*
if ( m_env->time_index % 96 == 0 ) {
if ( m_env->time_index % 96 == 0 ) {
//new_rate = array_rate[rand() % 3];
new_rate = array_rate[rand() % 3];
m_env->logger->LogRate(
engine->GetSimulationTime(TimeUnit::s),
"Controller",
"RATE_CHANGE",
"Controller sends Command to saline Pump",
50
);
m_env->logger->LogRate(
engine->GetSimulationTime(TimeUnit::s),
"Controller",
"RATE_CHANGE",
"Controller sends Command to saline Pump",
new_rate
);
cout<< "Command SENT to saline PUMP: "<< engine->
GetSimulationTime(TimeUnit::s)<<"s\n";
cout<< "Command SENT to saline PUMP: "<< engine->
GetSimulationTime(TimeUnit::s)<<"s\n";
//Send information to pump (rate, time index)
//SetRate(new_rate, m_env->time_index);
//cout << "Invoking Change Pump rate command" << endl;
//cout << "new rate " << new_rate << endl;
//cout << "Controller time index " << m_env->time_index << endl;
//Send information to pump (rate, time index)
//SetRate(new_rate, m_env->time_index);
//cout << "Invoking Change Pump rate command" << endl;
//cout << "new rate " << new_rate << endl;
//cout << "Controller time index " << m_env->time_index << endl;
m_pumps["saline"]->ChangePumpRate(50, m_env->time_index);
m_pumps["saline"]->ChangePumpRate(new_rate, m_env->time_index);
/*
cout<< "Command SENT to bpdrug PUMP: "<< engine->
GetSimulationTime(TimeUnit::s)<<"s\n";
cout<< "Command SENT to bpdrug PUMP: "<< engine->
GetSimulationTime(TimeUnit::s)<<"s\n";
m_env->logger->LogRate(
engine->GetSimulationTime(TimeUnit::s),
"Controller",
"RATE_CHANGE",
"Controller sends Command to bpdrug Pump",
new_rate
);
m_env->logger->LogRate(
engine->GetSimulationTime(TimeUnit::s),
"Controller",
"RATE_CHANGE",
"Controller sends Command to bpdrug Pump",
40
);
//m_pumps["bpdrug"]->ChangePumpRate(new_rate, m_env->time_index);
m_pumps["bpdrug"]->ChangePumpRate(40, m_env->time_index);
//pumpSetRate['saline'](salinerate);
//pumpSetRate['BPdrug'](bprate);
*/
//pumpSetRate['saline'](salinerate);
//pumpSetRate['BPdrug'](bprate);
//m_env->pump_index++;
}
//cout << "wait 10 mins: "<< WAIT_10<< endl;
//cout << "wait 5 mins "<< WAIT_5 << endl;
} // End check input rate condition
//m_env->pump_index++;
}
*/
// Capture time index to be used later in the Wait Condition
if (!set_initialize_time_index){
initialize_time_index = m_env->time_index;
set_initialize_time_index = true;
}
// Run initialization only once
if(!INITIALIZED) {
//Log rate
m_env->logger->LogRate(engine->GetSimulationTime(TimeUnit::s),"Controller",
"RATE_CHANGE","Controller sends Command to saline Pump",SalineInfusionRate);
m_env->logger->LogRate(engine->GetSimulationTime(TimeUnit::s),"Controller",
"RATE_CHANGE","Controller sends Command to saline Pump",maxNorepinephrineInfusionRate);
m_pumps["saline"]->ChangePumpRate(SalineInfusionRate, m_env->time_index);
m_pumps["bpdrug"]->ChangePumpRate(maxNorepinephrineInfusionRate, m_env->time_index);
INITIALIZED = true;
}
// Handover from initialization to Wait for MAP increase state after 10 mins
if(!DEACTIVATE_INIT && m_env->time_index - initialize_time_index == WAIT_10) {
// Exit initialize state
DEACTIVATE_INIT = true;
// go to wait for MAP increase state
WAIT_FOR_MAP_INCREASE = true;
}
if (WAIT_FOR_MAP_INCREASE) {
// Capture time index
if(!set_checkmap_timeindex) {
checkmap_time_index = m_env->time_index;
set_checkmap_timeindex = true;
}
MAP = patient_state.at(m_env->vector_index-1).pressure;
if ( MAP > MAPIncreaseThreshold && STAY_IN_2 ){
if(!checkmap_initialized){
cout << endl << "INSIDE WAIT_FOR_MAP_INCREASE "<<endl;
currentNorepiRate = percentOfRate * maxNorepinephrineInfusionRate;
//Log rate
m_env->logger->LogRate(engine->GetSimulationTime(TimeUnit::s),"Controller",
"RATE_CHANGE","Controller sends Command to saline Pump",SalineInfusionRate);
m_env->logger->LogRate(engine->GetSimulationTime(TimeUnit::s),"Controller",
"RATE_CHANGE","Controller sends Command to saline Pump",currentNorepiRate);
m_pumps["saline"]->ChangePumpRate(SalineInfusionRate, m_env->time_index);
m_pumps["bpdrug"]->ChangePumpRate(currentNorepiRate, m_env->time_index);
// So that it is not called in subsequent time loops
checkmap_initialized = true;
}
//Wait for 10 minutes
if( m_env->time_index - checkmap_time_index == WAIT_10 ) {
cout << endl << "INSIDE WAIT_FOR_MAP_INCREASE WAIT_10 "<<endl;
// Exit wait for MAP to increase state
WAIT_FOR_MAP_INCREASE = false;
// go to enure MAP decrease state
ENSURE_MAP_DECREASE = true;
}
}
else {
cout << endl << "INSIDE WAIT_FOR_MAP_INCREASE ELSE "<<endl;
// Disable IF so that only ELSE is seen in the time loop --> 2
STAY_IN_2 = false;
// Wait for 5 minutes
if (m_env->time_index - checkmap_time_index == WAIT_5){
cout << endl << "INSIDE WAIT_FOR_MAP_INCREASE ELSE WAIT_5 "<<endl;
// go back to wait for MAP increase state
STAY_IN_2 = true;
checkmap_initialized = false; // To allow new rates to be sent to pumps
set_checkmap_timeindex = false; // Allow new time index to be stored
}
} // End else --> 2
}//END WAIT_FOR_MAP_INCREASE
if(ENSURE_MAP_DECREASE){
// Capture time index
if(!set_ensure_map_time_index) {
ensure_map_time_index = m_env->time_index;
set_ensure_map_time_index = true;
}
MAP = patient_state.at(m_env->vector_index-1).pressure;
if( MAP > MAPIncreaseThreshold && STAY_IN_3 ){
if(!ensure_map_initialized) {
cout << endl << "INSIDE ENSURE_MAP_DECREASE "<<endl;
currentNorepiRate *= percentOfRate;
// Log rate
m_env->logger->LogRate(engine->GetSimulationTime(TimeUnit::s),"Controller",
"RATE_CHANGE","Controller sends Command to saline Pump",SalineInfusionRate);
m_env->logger->LogRate(engine->GetSimulationTime(TimeUnit::s),"Controller",
"RATE_CHANGE","Controller sends Command to saline Pump",currentNorepiRate);
m_pumps["saline"]->ChangePumpRate(SalineInfusionRate, m_env->time_index);
m_pumps["bpdrug"]->ChangePumpRate(currentNorepiRate, m_env->time_index);
ensure_map_initialized = true;
}
// Wait for 10 minutes
if(m_env->time_index - ensure_map_time_index == WAIT_10) {
cout << endl << "INSIDE ENSURE_MAP_DECREASE IF WAIT_10 "<<endl;
// go back to 3
set_ensure_map_time_index = false;
ensure_map_initialized = false;
}
}
else {
cout << endl << "INSIDE ENSURE_MAP_DECREASE ELSE "<<endl;
//Disable IF so that only ELSE is seen in the time loop --> 3
STAY_IN_3 = false;
// Wait for 10 minutes
if( m_env->time_index - ensure_map_time_index == WAIT_10 ){
cout << endl << "INSIDE ENSURE_MAP_DECREASE ELSE WAIT_10 "<<endl;
// go to maintain MAP range state
MAINTAIN_MAP_RANGE = true;
// Exit ensure MAP decrease state
ENSURE_MAP_DECREASE = false;
}
} // End else -->3
}// End GOTO 3
if(MAINTAIN_MAP_RANGE){
// Capture time index
if(!set_maintain_map_time_index) {
maintain_map_time_index = m_env->time_index;
set_maintain_map_time_index = true;
}
MAP = patient_state.at(m_env->vector_index-1).pressure;
if( MAP > targetMAPRangeMax && STAY_IN_4) {
cout << endl << "INSIDE MAINTAIN_MAP_RANGE "<<endl;
if(!maintain_map_initialized) {
currentNorepiRate *= percentOfRate;
// Log rate
m_env->logger->LogRate(engine->GetSimulationTime(TimeUnit::s),"Controller",
"RATE_CHANGE","Controller sends Command to saline Pump",SalineInfusionRate);
m_env->logger->LogRate(engine->GetSimulationTime(TimeUnit::s),"Controller",
"RATE_CHANGE","Controller sends Command to saline Pump",currentNorepiRate);
m_pumps["saline"]->ChangePumpRate(SalineInfusionRate, m_env->time_index);
m_pumps["bpdrug"]->ChangePumpRate(currentNorepiRate, m_env->time_index);
maintain_map_initialized = true;
}
// Wait for 10 minutes
if(m_env->time_index - maintain_map_time_index == WAIT_10) {
// go back to 4
set_maintain_map_time_index = false;
maintain_map_initialized = false;
}
}
else if( MAP < targetMAPRangeMin && ELSE_STAY_IN_4 ) {
// Disable main IF so that only ELSE IF is seen in the time loop --> 4
STAY_IN_4 = false;
if(!set_else_maintain_map_time_index) {
else_maintain_map_time_index = m_env->time_index;
set_else_maintain_map_time_index = true;
}
cout << endl << "INSIDE MAINTAIN_MAP_RANGE ELSE IF "<<endl;
if(!else_maintain_map_initialized) {
currentNorepiRate = percentOfRate * maxNorepinephrineInfusionRate;
// Log rate
m_env->logger->LogRate(engine->GetSimulationTime(TimeUnit::s),"Controller",
"RATE_CHANGE","Controller sends Command to saline Pump",SalineInfusionRate);
m_env->logger->LogRate(engine->GetSimulationTime(TimeUnit::s),"Controller",
"RATE_CHANGE","Controller sends Command to saline Pump",currentNorepiRate);
m_pumps["saline"]->ChangePumpRate(SalineInfusionRate, m_env->time_index);
m_pumps["bpdrug"]->ChangePumpRate(currentNorepiRate, m_env->time_index);
else_maintain_map_initialized = true;
}
// Wait for 5 minutes
if(m_env->time_index - else_maintain_map_time_index == WAIT_5) {
// go back to main IF --> 4
STAY_IN_4 = true;
set_maintain_map_time_index = false;
maintain_map_initialized = false;
}
} /// End else if --> 4
else {
// Disable main IF and ELSE IF so that only ELSE is seen in the time loop--> 4
STAY_IN_4 = false;
ELSE_STAY_IN_4 = false;
// Wait for 10 minutes
if(m_env->time_index - maintain_map_time_index == WAIT_10) {
cout << endl << "INSIDE MAINTAIN_MAP_RANGE ELSE "<<endl;
//go back to min IF --> 4
STAY_IN_4 = true;
ELSE_STAY_IN_4 = true;
set_maintain_map_time_index = false;
maintain_map_initialized = false;
}
} // End else --> 4
}// End MAINTAIN_MAP_RANGE
} // End check input rate condition
}; // End Controller update()
......@@ -160,6 +439,12 @@ void Controller::LoadConfig(std::unique_ptr<PhysiologyEngine>& engine, const cha
time_step = engine->GetTimeStep(TimeUnit::s);
//MAX_RATE_Hz = 1/time_step;
WAIT_10 = cfg.lookup("controller.algorithm.wait_10");
WAIT_5 = cfg.lookup("controller.algorithm.wait_5");
WAIT_10 = (60 * WAIT_10)/time_step; // 10 min
WAIT_5 = (60 * WAIT_5)/time_step; // 5 min
// integer input rate for controller
input_period = (1/controller_rate_Hz) / time_step;
//is_input_multiple = fmod(MAX_RATE_Hz, controller_rate_Hz) == 0.0;
......