Page MenuHomePhorge

No OneTemporary

Size
13 KB
Referenced Files
None
Subscribers
None
diff --git a/examples/deluxe-interface/deluxe-interface.cpp b/examples/deluxe-interface/deluxe-interface.cpp
index f465933..82621ac 100755
--- a/examples/deluxe-interface/deluxe-interface.cpp
+++ b/examples/deluxe-interface/deluxe-interface.cpp
@@ -1,178 +1,272 @@
//===-- 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-2019
///
/// \brief A simple example on the \c rosa::deluxe::DeluxeContext and related
/// classes.
//===----------------------------------------------------------------------===//
#include "rosa/config/version.h"
#include "rosa/deluxe/DeluxeContext.hpp"
#include <algorithm>
#include <cmath>
#include <vector>
using namespace rosa;
using namespace rosa::deluxe;
using namespace rosa::terminal;
/// How many cycles of simulation to perform.
const size_t NumberOfSimulationCycles = 16;
-/// Helper function creating a deluxe agent for logging and forwarding values.
-///
-/// Received values are dumped to \c LOG_INFO_STREAM and then returned as
-/// result.
-///
-/// \tparam T type of values to handle
-///
-/// \param C the deluxe context to create the agent in
-/// \param Name name of the new agent
-///
-/// \return handle for the new agent
-template <typename T>
-AgentHandle createLowLevelAgent(std::unique_ptr<DeluxeContext> &C,
- const std::string &Name) {
- using handler = std::function<Optional<T>(std::pair<T, bool>)>;
- using result = Optional<T>;
- return C->createAgent(
- Name, handler([&, Name](std::pair<T, bool> I) -> result {
- LOG_INFO_STREAM << "\n******\n"
- << Name << " " << (I.second ? "<New>" : "<Old>")
- << " value: " << I.first << "\n******\n";
- return {I.first};
- }));
-}
-
int main(void) {
LOG_INFO_STREAM << '\n'
<< library_string() << " -- " << Color::Red
<< "deluxe-interface example" << Color::Default << '\n';
std::unique_ptr<DeluxeContext> 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
+ // with the default value of the last argument. That, however, requires the
// data type to be explicitly defined. This is good for simulation only.
+
+ // The first and second sensors do not receive master-input.
+ AgentHandle BoolSensor = C->createSensor<bool>("BoolSensor");
AgentHandle IntSensor = C->createSensor<int32_t>("IntSensor");
- AgentHandle FloatSensor = C->createSensor<float>("FloatSensor");
+
+ // This sensor receives master-input and dumps it to \c LOG_INFO_STREAM.
+ const std::string FloatSensorName = "FloatSensor";
+ AgentHandle FloatSensor = C->createSensor<uint32_t, float>(
+ FloatSensorName, [&FloatSensorName](std::pair<uint32_t, bool> I) {
+ LOG_INFO_STREAM << "\n******\n"
+ << FloatSensorName
+ << " master-input " << (I.second ? "<New>" : "<Old>")
+ << " value: " << I.first << "\n******\n";
+ });
//
// Create low-level deluxe agents with \c createLowLevelAgent.
//
LOG_INFO("Creating low-level agents.");
- AgentHandle IntAgent = createLowLevelAgent<int32_t>(C, "IntAgent");
- AgentHandle FloatAgent = createLowLevelAgent<float>(C, "FloatAgent");
+ // All agents below dump their received values to \c LOG_INFO_STREAM on each
+ // triggering.
+
+ // This agent does not receive master-input and does not produce
+ // master-output. It results in the value it received.
+ const std::string BoolAgentName = "BoolAgent";
+ using BoolResult = Optional<bool>;
+ using BoolHandler = std::function<BoolResult(std::pair<bool, bool>)>;
+ AgentHandle BoolAgent = C->createAgent(
+ BoolAgentName,
+ BoolHandler([&BoolAgentName](std::pair<bool, bool> I) -> BoolResult {
+ LOG_INFO_STREAM << "\n******\n"
+ << BoolAgentName << " "
+ << (I.second ? "<New>" : "<Old>")
+ << " value: " << I.first << "\n******\n";
+ return {I.first};
+ }));
+
+ // This agent receives master-input but does not produce master-output. The
+ // agent maintains a state in \c IntAgentOffset. The master-input handler
+ // updates \c IntAgentOffset according to each received (new) value from its
+ // master. The slave-input handler results in the sum of the received value
+ // and the actual value of \c IntAgentOffset.
+ const std::string IntAgentName = "IntAgent";
+ using IntMasterHandler = std::function<void(std::pair<uint32_t, bool>)>;
+ using IntResult = Optional<int32_t>;
+ using IntHandler = std::function<IntResult(std::pair<int32_t, bool>)>;
+ uint32_t IntAgentOffset = 0;
+ AgentHandle IntAgent = C->createAgent(
+ IntAgentName,
+ // Master-input handler.
+ IntMasterHandler([&IntAgentName,
+ &IntAgentOffset](std::pair<uint32_t, bool> I) {
+ LOG_INFO_STREAM << "\n******\n"
+ << IntAgentName
+ << " master-input " << (I.second ? "<New>" : "<Old>")
+ << " value: " << I.first << "\n******\n";
+ if (I.second) {
+ IntAgentOffset = I.first;
+ }
+ }),
+ // Slave-input handler.
+ IntHandler([&IntAgentName,
+ &IntAgentOffset](std::pair<int32_t, bool> I) -> IntResult {
+ LOG_INFO_STREAM << "\n******\n"
+ << IntAgentName << " " << (I.second ? "<New>" : "<Old>")
+ << " value: " << I.first << "\n******\n";
+ return {I.first + IntAgentOffset};
+ }));
+
+ // This agent receives master-input and produces master-output. The
+ // master-input handler propagaates each received (new) value to its slave as
+ // master-output. The slave-input handler results in the value it received and
+ // produces no actual master-output.
+ const std::string FloatAgentName = "FloatAgent";
+ using FloatMasterResult = std::tuple<Optional<uint32_t>>;
+ using FloatMasterHandler =
+ std::function<FloatMasterResult(std::pair<uint32_t, bool>)>;
+ using FloatResult = std::tuple<Optional<float>, Optional<uint32_t>>;
+ using FloatHandler = std::function<FloatResult(std::pair<float, bool>)>;
+ AgentHandle FloatAgent = C->createAgent(
+ FloatAgentName,
+ // Master-input handler.
+ FloatMasterHandler([&FloatAgentName](
+ std::pair<uint32_t, bool> I) -> FloatMasterResult {
+ LOG_INFO_STREAM << "\n******\n"
+ << FloatAgentName
+ << " master-input " << (I.second ? "<New>" : "<Old>")
+ << " value: " << I.first << "\n******\n";
+ const auto Output =
+ I.second ? Optional<uint32_t>(I.first) : Optional<uint32_t>();
+ return {Output};
+ }),
+ // Slave-input handler.
+ FloatHandler([&FloatAgentName](std::pair<float, bool> I) -> FloatResult {
+ LOG_INFO_STREAM << "\n******\n"
+ << FloatAgentName << " "
+ << (I.second ? "<New>" : "<Old>")
+ << " value: " << I.first << "\n******\n";
+ return {{I.first}, {}};
+ }));
//
// Connect sensors to low-level agents.
//
LOG_INFO("Connect sensors to their corresponding low-level agents.");
+ C->connectSensor(BoolAgent, 0, BoolSensor, "Bool 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.
+ // This agent does not receive master-input but produces master-output for its
+ // slaves at positions `1` and `2` but not for that at position `0`. The agent
+ // maintains a state in \c SumAgentState. The handler increments \c
+ // SumAgentState upon each received (new) `true` value from its slave at
+ // position `0`. Whenever \c SumAgentState has been updated, it is sent to the
+ // slaves at positions `1` and `2`. The handler results in the sum of the
+ // values received from slaves at positions `1` and `2`.
+ using SumResult = std::tuple<Optional<double>, Optional<unit_t>,
+ Optional<uint32_t>, Optional<uint32_t>>;
+ using SumHandler = std::function<SumResult(
+ std::pair<bool, bool>, std::pair<int32_t, bool>, std::pair<float, bool>)>;
+ uint32_t SumAgentState = 0;
AgentHandle SumAgent = C->createAgent(
- "Sum Agent", std::function<Optional<double>(std::pair<int32_t, bool>,
- std::pair<float, bool>)>(
- [](std::pair<int32_t, bool> I1,
- std::pair<float, bool> I2) -> Optional<double> {
- LOG_INFO_STREAM
- << "\n*******\nSum Agent triggered with values:\n"
- << (I1.second ? "<New>" : "<Old>")
- << " int value: " << I1.first << "\n"
- << (I2.second ? "<New>" : "<Old>")
- << " float value: " << I2.first << "\n******\n";
- return {I1.first + I2.first};
- }));
+ "Sum Agent",
+ SumHandler([&SumAgentState](std::pair<bool, bool> I0,
+ std::pair<int32_t, bool> I1,
+ std::pair<float, bool> I2) -> SumResult {
+ LOG_INFO_STREAM << "\n*******\nSum Agent triggered with values:\n"
+ << (I0.second ? "<New>" : "<Old>")
+ << " bool value: " << I0.first << "\n"
+ << (I1.second ? "<New>" : "<Old>")
+ << " int value: " << I1.first << "\n"
+ << (I2.second ? "<New>" : "<Old>")
+ << " float value: " << I2.first << "\n******\n";
+ if (I0.second && I0.first) {
+ ++SumAgentState;
+ }
+ const auto MasterOutput = I0.second && I0.first
+ ? Optional<uint32_t>(SumAgentState)
+ : Optional<uint32_t>();
+ const auto Output = I1.first + I2.first;
+ return {{Output}, {}, {MasterOutput}, {MasterOutput}};
+ }));
//
// Connect low-level agents to the high-level agent.
//
LOG_INFO("Connect low-level agents to the high-level agent.");
- C->connectAgents(SumAgent, 0, IntAgent, "Int Agent Channel");
- C->connectAgents(SumAgent, 1, FloatAgent, "Float Agent Channel");
+ C->connectAgents(SumAgent, 0, BoolAgent, "Bool Agent Channel");
+ C->connectAgents(SumAgent, 1, IntAgent, "Int Agent Channel");
+ C->connectAgents(SumAgent, 2, FloatAgent, "Float Agent Channel");
//
// For simulation output, create a logger agent writing the output of the
// high-level agent into a log stream.
//
LOG_INFO("Create a logger agent.");
- // The agent logs each new input value and produces nothing.
+ // The agent dumps each received (new) value to \c LOG_INFO_STREAM and
+ // produces nothing; does not receive mater-input and does not produce
+ // master-output.
AgentHandle LoggerAgent =
C->createAgent("Logger Agent",
std::function<Optional<unit_t>(std::pair<double, bool>)>(
[](std::pair<double, bool> Sum) -> Optional<unit_t> {
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, SumAgent, "Sum Agent Channel");
//
// Do simulation.
//
LOG_INFO("Setting up and performing simulation.");
//
// Initialize deluxe context for simulation.
//
C->initializeSimulation();
//
// Create some vectors and register them for their corresponding sensors.
//
+ std::vector<bool> BoolValues(NumberOfSimulationCycles);
+ std::generate(BoolValues.begin(), BoolValues.end(),
+ [i = 0](void) mutable -> bool { return (++i % 4) == 0; });
+ C->registerSensorValues(BoolSensor, BoolValues.begin(), BoolValues.end());
+
std::vector<int32_t> IntValues(NumberOfSimulationCycles);
std::generate(IntValues.begin(), IntValues.end(),
[i = 0](void) mutable { return ++i; });
C->registerSensorValues(IntSensor, IntValues.begin(), IntValues.end());
std::vector<float> 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;
}

File Metadata

Mime Type
text/x-diff
Expires
Sat, Mar 15, 7:49 PM (15 h, 9 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
129097
Default Alt Text
(13 KB)

Event Timeline