diff --git a/examples/deluxe-interface/deluxe-interface.cpp b/examples/deluxe-interface/deluxe-interface.cpp index 5e569ba..d50396e 100755 --- a/examples/deluxe-interface/deluxe-interface.cpp +++ b/examples/deluxe-interface/deluxe-interface.cpp @@ -1,312 +1,177 @@ //===-- examples/deluxe-interface/deluxe-interface.cpp ----------*- C++ -*-===// // // The RoSA Framework // //===----------------------------------------------------------------------===// /// /// \file examples/deluxe-interface/deluxe-interface.cpp /// /// \author David Juhasz (david.juhasz@tuwien.ac.at) /// /// \date 2017 /// /// \brief A simple example on the \c rosa::deluxe::DeluxeContext and related /// classes. //===----------------------------------------------------------------------===// -#include "rosa/agent/Abstraction.hpp" -#include "rosa/agent/Confidence.hpp" - #include "rosa/config/version.h" #include "rosa/deluxe/DeluxeContext.hpp" -#include "rosa/support/csv/CSVReader.hpp" -#include "rosa/support/csv/CSVWriter.hpp" - -#include +#include +#include +#include using namespace rosa; -using namespace rosa::agent; using namespace rosa::deluxe; using namespace rosa::terminal; -/// Paths for the CSV files for simulation. -/// -///@{ -const std::string HRCSVPath = "HR.csv"; -const std::string BRCSVPath = "BR.csv"; -const std::string SpO2CSVPath = "SpO2.csv"; -const std::string BPSysCSVPath = "BPSys.csv"; -const std::string BodyTempCSVPath = "BodyTemp.csv"; -const std::string ScoreCSVPath = "Score.csv"; -///@} - /// How many cycles of simulation to perform. const size_t NumberOfSimulationCycles = 16; -/// Warning levels for abstraction. -enum WarningScore { No = 0, Low = 1, High = 2, Emergency = 3 }; - -/// Helper function creating a deluxe agent for pre-processing sensory values. -/// -/// Received values are first validated for confidence. Values which the -/// validator does not mark confident are ignored. Confident values are -/// abstracted into a \c WarningScore value, which is the result of the -/// processing function. +/// Helper function creating a deluxe agent for logging and forwarding values. /// -/// \note The result, \c WarningScore, is returned as \c uint32_t because -/// enumeration types are not integrated into built-in types. Hence, a master -/// to these agents receives its input as \c uint32_t values, and may cast them -/// to \c WarningScore explicitly. +/// Received values are dumped to \c LOG_INFO_STREAM and then returned as +/// result. /// -/// \tparam T type of values to receive from the sensor +/// \tparam T type of values to handle /// /// \param C the deluxe context to create the agent in /// \param Name name of the new agent -/// \param CC confidence validator to use -/// \param A abstraction to use /// /// \return handle for the new agent template AgentHandle createLowLevelAgent(std::unique_ptr &C, - const std::string &Name, - const Confidence &CC, - const Abstraction &A) { - using handler = DeluxeAgent::D; - using result = Optional; + const std::string &Name) { + using handler = DeluxeAgent::D; + using result = Optional; return C->createAgent( Name, handler([&, Name](std::pair I) -> result { LOG_INFO_STREAM << "\n******\n" << Name << " " << (I.second ? "" : "") << " value: " << I.first << "\n******\n"; - return (I.second && CC(I.first)) ? result(A(I.first)) : result(); + return {I.first}; })); } int main(void) { - LOG_INFO_STREAM - << '\n' - << library_string() << " -- " << Color::Red << "deluxe-interface example" - << Color::Default << '\n' - << Color::Yellow - << "CSV files are read from and written to the current working directory." - << Color::Default << '\n'; + LOG_INFO_STREAM << '\n' + << library_string() << " -- " << Color::Red + << "deluxe-interface example" << Color::Default << '\n'; std::unique_ptr C = DeluxeContext::create("Deluxe"); // // Create deluxe sensors. // LOG_INFO("Creating sensors."); // All sensors are created without defining a normal generator function, but // with the default value of the second argument. That, however, requires the // data type to be explicitly defined. This is good for simulation only. - AgentHandle HRSensor = C->createSensor("HR Sensor"); - AgentHandle BRSensor = C->createSensor("BR Sensor"); - AgentHandle SpO2Sensor = C->createSensor("SpO2 Sensor"); - AgentHandle BPSysSensor = C->createSensor("BPSys Sensor"); - AgentHandle BodyTempSensor = C->createSensor("BodyTemp Sensor"); - - // - // Create functionalities. - // - LOG_INFO("Creating Functionalities for Agents."); - - // - // Define confidence validators. - // - // Lower bounds are inclusive and upper bounds are exclusive. - - Confidence HRConfidence(0, 501); - Confidence BRConfidence(0, 301); - Confidence SpO2Confidence(0, 101); - Confidence BPSysConfidence(0,501); - Confidence BodyTempConfidence(-60, - nextRepresentableFloatingPoint(50.0f)); - - // - // Define abstractions. - // - - RangeAbstraction HRAbstraction( - {{{0, 40}, Emergency}, - {{40, 51}, High}, - {{51, 60}, Low}, - {{60, 100}, No}, - {{100, 110}, Low}, - {{110, 129}, High}, - {{129, 200}, Emergency}}, - Emergency); - - RangeAbstraction BRAbstraction({{{0, 9}, High}, - {{9, 14}, No}, - {{14, 20}, Low}, - {{20, 29}, High}, - {{29, 50}, Emergency}}, - Emergency); - - RangeAbstraction SpO2Abstraction({{{1, 85}, Emergency}, - {{85, 90}, High}, - {{90, 95}, Low}, - {{95, 100}, No}}, - Emergency); - - RangeAbstraction BPSysAbstraction( - {{{0, 70}, Emergency}, - {{70, 81}, High}, - {{81, 101}, Low}, - {{101, 149}, No}, - {{149, 169}, Low}, - {{169, 179}, High}, - {{179, 200}, Emergency}}, - Emergency); - - RangeAbstraction BodyTempAbstraction( - {{{0.f, 28.f}, Emergency}, - {{28.f, 32.f}, High}, - {{32.f, 35.f}, Low}, - {{35.f, 38.f}, No}, - {{38.f, 39.5f}, High}, - {{39.5f, 100.f}, Emergency}}, - Emergency); + AgentHandle IntSensor = C->createSensor("IntSensor"); + AgentHandle FloatSensor = C->createSensor("FloatSensor"); // // Create low-level deluxe agents with \c createLowLevelAgent. // LOG_INFO("Creating low-level agents."); - AgentHandle HRAgent = - createLowLevelAgent(C, "HR Agent", HRConfidence, HRAbstraction); - AgentHandle BRAgent = - createLowLevelAgent(C, "BR Agent", BRConfidence, BRAbstraction); - AgentHandle SpO2Agent = - createLowLevelAgent(C, "SpO2 Agent", SpO2Confidence, SpO2Abstraction); - AgentHandle BPSysAgent = - createLowLevelAgent(C, "BPSys Agent", BPSysConfidence, BPSysAbstraction); - AgentHandle BodyTempAgent = createLowLevelAgent( - C, "BodyTemp Agent", BodyTempConfidence, BodyTempAbstraction); + AgentHandle IntAgent = createLowLevelAgent(C, "IntAgent"); + AgentHandle FloatAgent = createLowLevelAgent(C, "FloatAgent"); // // Connect sensors to low-level agents. // LOG_INFO("Connect sensors to their corresponding low-level agents."); - C->connectSensor(HRAgent, 0, HRSensor, "HR Sensor Channel"); - C->connectSensor(BRAgent, 0, BRSensor, "BR Sensor Channel"); - C->connectSensor(SpO2Agent, 0, SpO2Sensor, "SpO2 Sensor Channel"); - C->connectSensor(BPSysAgent, 0, BPSysSensor, "BPSys Sensor Channel"); - C->connectSensor(BodyTempAgent, 0, BodyTempSensor, "BodyTemp Sensor Channel"); + C->connectSensor(IntAgent, 0, IntSensor, "Int Sensor Channel"); + C->connectSensor(FloatAgent, 0, FloatSensor, "Float Sensor Channel"); // // Create a high-level deluxe agent. // LOG_INFO("Create high-level agent."); // The new agent logs its input values and results in the the sum of them. - AgentHandle BodyAgent = C->createAgent( - "Body Agent", - DeluxeAgent::D( - [](std::pair HR, std::pair BR, - std::pair SpO2, std::pair BPSys, - std::pair BodyTemp) -> Optional { - LOG_INFO_STREAM << "\n*******\nBody Agent trigged with values:\n" - << (HR.second ? "" : "") - << " HR warning score: " << HR.first << "\n" - << (BR.second ? "" : "") - << " BR warning score: " << BR.first << "\n" - << (SpO2.second ? "" : "") - << " SpO2 warning score: " << SpO2.first << "\n" - << (BPSys.second ? "" : "") - << " BPSys warning score: " << BPSys.first << "\n" - << (BodyTemp.second ? "" : "") - << " BodyTemp warning score: " << BodyTemp.first - << "\n******\n"; - return {HR.first + BR.first + SpO2.first + BPSys.first + - BodyTemp.first}; - })); + AgentHandle SumAgent = C->createAgent( + "Sum Agent", DeluxeAgent::D( + [](std::pair I1, + std::pair I2) -> Optional { + LOG_INFO_STREAM + << "\n*******\nSum Agent triggered with values:\n" + << (I1.second ? "" : "") + << " int value: " << I1.first << "\n" + << (I2.second ? "" : "") + << " float value: " << I2.first << "\n******\n"; + return {I1.first + I2.first}; + })); // // Connect low-level agents to the high-level agent. // LOG_INFO("Connect low-level agents to the high-level agent."); - C->connectAgents(BodyAgent, 0, HRAgent, "HR Agent Channel"); - C->connectAgents(BodyAgent, 1, BRAgent, "BR Agent Channel"); - C->connectAgents(BodyAgent, 2, SpO2Agent, "SpO2 Agent Channel"); - C->connectAgents(BodyAgent, 3, BPSysAgent, "BPSys Agent Channel"); - C->connectAgents(BodyAgent, 4, BodyTempAgent, "BodyTemp Agent Channel"); + C->connectAgents(SumAgent, 0, IntAgent, "Int Agent Channel"); + C->connectAgents(SumAgent, 1, FloatAgent, "Float Agent Channel"); // // For simulation output, create a logger agent writing the output of the - // high-level agent into a CSV file. + // high-level agent into a log stream. // LOG_INFO("Create a logger agent."); - // Create CSV writer. - std::ofstream ScoreCSV(ScoreCSVPath); - csv::CSVWriter ScoreWriter(ScoreCSV); - - // The agent writes each new input value into a CSV file and produces nothing. - AgentHandle LoggerAgent = C->createAgent( - "Logger Agent", - DeluxeAgent::D( - [&ScoreWriter](std::pair Score) -> Optional { - if (Score.second) { - // The state of \p ScoreWriter is not checked, expecting good. - ScoreWriter << Score.first; - } - return {}; - })); + // The agent logs each new input value and produces nothing. + AgentHandle LoggerAgent = + C->createAgent("Logger Agent", + DeluxeAgent::D( + [](std::pair Sum) -> Optional { + if (Sum.second) { + LOG_INFO_STREAM << "Result: " << Sum.first << "\n"; + } + return {}; + })); // // Connect the high-level agent to the logger agent. // LOG_INFO("Connect the high-level agent to the logger agent."); - C->connectAgents(LoggerAgent, 0, BodyAgent, "Body Agent Channel"); + C->connectAgents(LoggerAgent, 0, SumAgent, "Sum Agent Channel"); // // Do simulation. // LOG_INFO("Setting up and performing simulation."); // // Initialize deluxe context for simulation. // C->initializeSimulation(); // - // Open CSV files and register them for their corresponding sensors. + // Create some vectors and register them for their corresponding sensors. // - // Type aliases for iterators. - using CSVInt = csv::CSVFlatIterator; - using CSVFloat = csv::CSVFlatIterator; - - std::ifstream HRCSV(HRCSVPath); - C->registerSensorValues(HRSensor, CSVInt(HRCSV), CSVInt()); - - std::ifstream BRCSV(BRCSVPath); - C->registerSensorValues(BRSensor, CSVInt(BRCSV), CSVInt()); - - std::ifstream SpO2CSV(SpO2CSVPath); - C->registerSensorValues(SpO2Sensor, CSVInt(SpO2CSV), CSVInt()); - - std::ifstream BPSysCSV(BPSysCSVPath); - C->registerSensorValues(BPSysSensor, CSVInt(BPSysCSV), CSVInt()); + std::vector IntValues(NumberOfSimulationCycles); + std::generate(IntValues.begin(), IntValues.end(), + [i = 0](void) mutable { return ++i; }); + C->registerSensorValues(IntSensor, IntValues.begin(), IntValues.end()); - std::ifstream BodyTempCSV(BodyTempCSVPath); - C->registerSensorValues(BodyTempSensor, CSVFloat(BodyTempCSV), CSVFloat()); + std::vector FloatValues(NumberOfSimulationCycles); + std::generate(FloatValues.begin(), FloatValues.end(), + [f = 0.5f](void) mutable { + f += 0.3f; + return std::floor(f) + 0.5f; + }); + C->registerSensorValues(FloatSensor, FloatValues.begin(), FloatValues.end()); // // Simulate. // C->simulate(NumberOfSimulationCycles); return 0; }