Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F340468
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Size
48 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/apps/ccam/ccam.cpp b/apps/ccam/ccam.cpp
index e11ff21..a2488dd 100644
--- a/apps/ccam/ccam.cpp
+++ b/apps/ccam/ccam.cpp
@@ -1,617 +1,620 @@
//===-- apps/ccam/ccam.cpp --------------------------------------*- C++ -*-===//
//
// The RoSA Framework -- Application CCAM
//
// Distributed under the terms and conditions of the Boost Software
/// License 1.0.
// See accompanying file LICENSE.
//
// If you did not receive a copy of the license file, see
// http://www.boost.org/LICENSE_1_0.txt.
//
//===----------------------------------------------------------------------===//
///
/// \file apps/ccam/ccam.cpp
///
/// \author Maximilian Goetzinger (maximilian.goetzinger@tuwien.ac.at)
/// \author Benedikt Tutzer (benedikt.tutzer@tuwien.ac.at)
///
/// \date 2019
///
/// \brief The application CCAM implements the case study from the paper:
/// M. Goetzinger, N. TaheriNejad, H. A. Kholerdi, A. Jantsch, E. Willegger,
/// T. Glatzl, A.M. Rahmani, T.Sauter, P. Liljeberg: Model - Free Condition
/// Monitoring with Confidence
///
/// \todo Clean up source files of this app: add standard RoSA header comment
/// for own files and do something with 3rd party files...
//===----------------------------------------------------------------------===//
#include "rosa/agent/Abstraction.hpp"
#include "rosa/agent/Confidence.hpp"
#include "rosa/agent/DistanceMetrics.hpp"
#include "rosa/agent/FunctionAbstractions.hpp"
#include <iostream>
#include "rosa/config/version.h"
#include "rosa/agent/SignalStateDetector.hpp"
#include "rosa/agent/SystemStateDetector.hpp"
#include "rosa/app/Application.hpp"
#include "rosa/support/csv/CSVReader.hpp"
#include "rosa/support/csv/CSVWriter.hpp"
#include "rosa/support/mqtt/MQTTReader.hpp"
#include "rosa/app/AppTuple.hpp"
#include <fstream>
#include <limits>
#include <memory>
#include <streambuf>
#include <string>
#include "configuration.h"
#include "statehandlerutils.h"
using namespace rosa;
using namespace rosa::agent;
using namespace rosa::app;
using namespace rosa::terminal;
using namespace rosa::mqtt;
const std::string AppName = "CCAM";
int main(int argc, char **argv) {
LOG_INFO_STREAM << '\n'
<< library_string() << " -- " << Color::Red << AppName
<< "app" << Color::Default << '\n';
//
// Read the filepath of the config file of the observed system. The filepath
// is in the first argument passed to the application. Fuzzy functions etc.
// are described in this file.
//
if (argc < 2) {
LOG_ERROR("Specify config File!\nUsage:\n\tccam config.json");
return 1;
}
std::string ConfigPath = argv[1];
//
// Load config file and read in all parameters. Fuzzy functions etc. are
// described in this file.
//
if (!readConfigFile(ConfigPath)) {
LOG_ERROR_STREAM << "Could not read config from \"" << ConfigPath << "\"\n";
return 2;
}
//
// Create a CCAM context.
//
LOG_INFO("Creating Context");
std::unique_ptr<Application> AppCCAM = Application::create(AppName);
//
// Create following function which shall give information if the time gap
// between changed input(s) and changed output(s) shows already a malfunction
// of the system.
//
// ____________
// /
// /
// __________/
//
std::shared_ptr<PartialFunction<uint32_t, float>> BrokenDelayFunction(
new PartialFunction<uint32_t, float>(
{{{0, AppConfig.BrokenCounter},
std::make_shared<LinearFunction<uint32_t, float>>(
0, 0.f, AppConfig.BrokenCounter, 1.f)},
{{AppConfig.BrokenCounter, std::numeric_limits<uint32_t>::max()},
std::make_shared<LinearFunction<uint32_t, float>>(1.f, 0.f)}},
0.f));
//
// Create following function which shall give information if the time gap
// between changed input(s) and changed output(s) still shows a
// well-functioning system.
//
// ____________
// \
// \
// \__________
//
std::shared_ptr<PartialFunction<uint32_t, float>> OkDelayFunction(
new PartialFunction<uint32_t, float>(
{{{0, AppConfig.BrokenCounter},
std::make_shared<LinearFunction<uint32_t, float>>(
0, 1.f, AppConfig.BrokenCounter, 0.f)},
{{AppConfig.BrokenCounter, std::numeric_limits<uint32_t>::max()},
std::make_shared<LinearFunction<uint32_t, float>>(0.f, 0.f)}},
1.f));
//
// Create a AppAgent with SystemStateDetector functionality.
//
LOG_INFO("Create SystemStateDetector agent.");
AgentHandle SystemStateDetectorAgent = createSystemStateDetectorAgent(
AppCCAM, "SystemStateDetector", AppConfig.SignalConfigurations.size(),
BrokenDelayFunction, OkDelayFunction);
//
// Set policy of SystemStateDetectorAgent that it wait for all
// SignalStateDetectorAgents
//
std::set<size_t> pos;
for (size_t i = 0; i < AppConfig.SignalConfigurations.size(); ++i)
pos.insert(pos.end(), i);
AppCCAM->setExecutionPolicy(SystemStateDetectorAgent,
AppExecutionPolicy::awaitAll(pos));
//
// Create Vectors for all sensors, all signal related fuzzy functions, all
// signal state detectors, all signal state agents, and all input data files.
//
LOG_INFO("Creating sensors, SignalStateDetector functionalities and their "
"Abstractions.");
std::vector<AgentHandle> Sensors;
std::vector<std::shared_ptr<Abstraction<std::pair<float, float>, float>>> DistanceMetrics;
std::vector<std::shared_ptr<PartialFunction<float, float>>>
SampleMatchesFunctions;
std::vector<std::shared_ptr<PartialFunction<float, float>>>
SampleMismatchesFunctions;
std::vector<std::shared_ptr<PartialFunction<float, float>>>
SignalIsStableFunctions;
std::vector<std::shared_ptr<PartialFunction<float, float>>>
SignalIsDriftingFunctions;
// SAVE CHANGES
std::vector<std::shared_ptr<PartialFunction<uint32_t, float>>>
SignalConditionLookBackFunctions;
std::vector<std::shared_ptr<PartialFunction<uint32_t, float>>>
SignalConditionHistoryDesicionFunctions;
// - SAVE CHANGES
std::vector<std::shared_ptr<StepFunction<float, float>>>
NumOfSamplesMatchFunctions;
std::vector<std::shared_ptr<StepFunction<float, float>>>
NumOfSamplesMismatchFunctions;
std::vector<std::shared_ptr<PartialFunction<float, float>>>
SampleValidFunctions;
std::vector<std::shared_ptr<PartialFunction<float, float>>>
SampleInvalidFunctions;
std::vector<std::shared_ptr<StepFunction<float, float>>>
NumOfSamplesValidFunctions;
std::vector<std::shared_ptr<StepFunction<float, float>>>
NumOfSamplesInvalidFunctions;
std::vector<std::shared_ptr<
SignalStateDetector<float, float, float, HistoryPolicy::FIFO>>>
SignalStateDetectors;
std::vector<AgentHandle> SignalStateDetectorAgents;
std::vector<std::ifstream> DataFiles;
//
// Go through all signal state configurations (number of signals), and create
// functionalities for SignalStateDetector.
//
for (auto SignalConfiguration : AppConfig.SignalConfigurations) {
//
// Create application sensors.
//
Sensors.emplace_back(
AppCCAM->createSensor<float>(SignalConfiguration.Name + "_Sensor"));
//
// Create following function(s) which shall give information whether one
// sample matches another one (based on the relative distance between them).
//
// ____________
// / \
// / \
// __________/ \__________
//
//
if (std::strcmp(SignalConfiguration.DistanceMetric.c_str(), "absolute") == 0 ) {
DistanceMetrics.emplace_back(new AbsoluteDistance<float, float>());
} else if (std::strcmp(SignalConfiguration.DistanceMetric.c_str(), "daniel1") == 0 ) {
DistanceMetrics.emplace_back(new DanielsDistance1<float, float>());
} else if (std::strcmp(SignalConfiguration.DistanceMetric.c_str(), "daniel2") == 0 ) {
DistanceMetrics.emplace_back(new DanielsDistance2<float, float>());
} else if (std::strcmp(SignalConfiguration.DistanceMetric.c_str(), "daniel3") == 0 ) {
DistanceMetrics.emplace_back(new DanielsDistance3<float, float>());
} else if (std::strcmp(SignalConfiguration.DistanceMetric.c_str(), "maxi1") == 0 ) {
DistanceMetrics.emplace_back(new MaxisDistance1<float, float>());
} else {
//default is relative distance
DistanceMetrics.emplace_back(new RelativeDistance<float, float>());
}
SampleMatchesFunctions.emplace_back(new PartialFunction<float, float>(
{
{{-SignalConfiguration.OuterBound, -SignalConfiguration.InnerBound},
std::make_shared<LinearFunction<float, float>>(
-SignalConfiguration.OuterBound, 0.f,
-SignalConfiguration.InnerBound, 1.f)},
{{-SignalConfiguration.InnerBound, SignalConfiguration.InnerBound},
std::make_shared<LinearFunction<float, float>>(1.f, 0.f)},
{{SignalConfiguration.InnerBound, SignalConfiguration.OuterBound},
std::make_shared<LinearFunction<float, float>>(
SignalConfiguration.InnerBound, 1.f,
SignalConfiguration.OuterBound, 0.f)},
},
0));
//
// Create following function(s) which shall give information whether one
// sample mismatches another one (based on the relative distance between
// them).
//
// ____________ ____________
// \ /
// \ /
// \__________/
//
//
SampleMismatchesFunctions.emplace_back(new PartialFunction<float, float>(
{
{{-SignalConfiguration.OuterBound, -SignalConfiguration.InnerBound},
std::make_shared<LinearFunction<float, float>>(
-SignalConfiguration.OuterBound, 1.f,
-SignalConfiguration.InnerBound, 0.f)},
{{-SignalConfiguration.InnerBound, SignalConfiguration.InnerBound},
std::make_shared<LinearFunction<float, float>>(0.f, 0.f)},
{{SignalConfiguration.InnerBound, SignalConfiguration.OuterBound},
std::make_shared<LinearFunction<float, float>>(
SignalConfiguration.InnerBound, 0.f,
SignalConfiguration.OuterBound, 1.f)},
},
1));
//
// Create following function(s) which shall give information whether a
// signal is stable.
//
// ____________
// / \
// / \
// __________/ \__________
//
//
SignalIsStableFunctions.emplace_back(new PartialFunction<float, float>(
{
{{-SignalConfiguration.OuterBoundDrift,
-SignalConfiguration.InnerBoundDrift},
std::make_shared<LinearFunction<float, float>>(
-SignalConfiguration.OuterBoundDrift, 0.f,
-SignalConfiguration.InnerBoundDrift, 1.f)},
{{-SignalConfiguration.InnerBoundDrift,
SignalConfiguration.InnerBoundDrift},
std::make_shared<LinearFunction<float, float>>(1.f, 0.f)},
{{SignalConfiguration.InnerBoundDrift,
SignalConfiguration.OuterBoundDrift},
std::make_shared<LinearFunction<float, float>>(
SignalConfiguration.InnerBoundDrift, 1.f,
SignalConfiguration.OuterBoundDrift, 0.f)},
},
0));
//
// Create following function(s) which shall give information whether a
// signal is drifting.
//
// ____________ ____________
// \ /
// \ /
// \__________/
//
//
SignalIsDriftingFunctions.emplace_back(new PartialFunction<float, float>(
{
{{-SignalConfiguration.OuterBoundDrift,
-SignalConfiguration.InnerBoundDrift},
std::make_shared<LinearFunction<float, float>>(
-SignalConfiguration.OuterBoundDrift, 1.f,
-SignalConfiguration.InnerBoundDrift, 0.f)},
{{-SignalConfiguration.InnerBoundDrift,
SignalConfiguration.InnerBoundDrift},
std::make_shared<LinearFunction<float, float>>(0.f, 0.f)},
{{SignalConfiguration.InnerBoundDrift,
SignalConfiguration.OuterBoundDrift},
std::make_shared<LinearFunction<float, float>>(
SignalConfiguration.InnerBoundDrift, 0.f,
SignalConfiguration.OuterBoundDrift, 1.f)},
},
1));
// SAVE CHANGES
SignalConditionLookBackFunctions.emplace_back(
new PartialFunction<uint32_t, float>(
{{{1, SignalConfiguration.DriftLookbackRange + 1},
std::make_shared<LinearFunction<uint32_t, float>>(
1, 1.f, SignalConfiguration.DriftLookbackRange + 1, 0.f)},
{{SignalConfiguration.DriftLookbackRange + 1,
std::numeric_limits<uint32_t>::max()},
std::make_shared<LinearFunction<uint32_t, float>>(0.f, 0.f)}},
1.f));
SignalConditionHistoryDesicionFunctions.emplace_back(
new PartialFunction<uint32_t, float>(
{{{0, SignalConfiguration.DriftLookbackRange},
std::make_shared<LinearFunction<uint32_t, float>>(
0, 0.f, SignalConfiguration.DriftLookbackRange, 1.f)},
{{SignalConfiguration.DriftLookbackRange,
std::numeric_limits<uint32_t>::max()},
std::make_shared<LinearFunction<uint32_t, float>>(1.f, 0.f)}},
0.f));
// - SAVE CHANGES
//
// Create following function(s) which shall give information how many
// history samples match another sample.
//
// ____________
// /
// /
// __________/
//
NumOfSamplesMatchFunctions.emplace_back(new StepFunction<float, float>(
1.0f / SignalConfiguration.SampleHistorySize, StepDirection::StepUp));
//
// Create following function(s) which shall give information how many
// history samples mismatch another sample.
//
// ____________
// \
// \
// \__________
//
NumOfSamplesMismatchFunctions.emplace_back(new StepFunction<float, float>(
1.0f / SignalConfiguration.SampleHistorySize, StepDirection::StepDown));
//
// Create following function(s) which shall give information how good all
// samples in a state match each other.
//
// ____________
// / \
// / \
// __________/ \__________
//
//
SampleValidFunctions.emplace_back(new PartialFunction<float, float>(
{
{{-SignalConfiguration.OuterBound, -SignalConfiguration.InnerBound},
std::make_shared<LinearFunction<float, float>>(
-SignalConfiguration.OuterBound, 0.f,
-SignalConfiguration.InnerBound, 1.f)},
{{-SignalConfiguration.InnerBound, SignalConfiguration.InnerBound},
std::make_shared<LinearFunction<float, float>>(1.f, 0.f)},
{{SignalConfiguration.InnerBound, SignalConfiguration.OuterBound},
std::make_shared<LinearFunction<float, float>>(
SignalConfiguration.InnerBound, 1.f,
SignalConfiguration.OuterBound, 0.f)},
},
0));
//
// Create following function(s) which shall give information how good all
// samples in a state mismatch each other.
//
// ____________ ____________
// \ /
// \ /
// \__________/
//
//
SampleInvalidFunctions.emplace_back(new PartialFunction<float, float>(
{
{{-SignalConfiguration.OuterBound, -SignalConfiguration.InnerBound},
std::make_shared<LinearFunction<float, float>>(
-SignalConfiguration.OuterBound, 1.f,
-SignalConfiguration.InnerBound, 0.f)},
{{-SignalConfiguration.InnerBound, SignalConfiguration.InnerBound},
std::make_shared<LinearFunction<float, float>>(0.f, 0.f)},
{{SignalConfiguration.InnerBound, SignalConfiguration.OuterBound},
std::make_shared<LinearFunction<float, float>>(
SignalConfiguration.InnerBound, 0.f,
SignalConfiguration.OuterBound, 1.f)},
},
1));
//
// Create following function(s) which shall give information how many
// history samples match each other.
//
// ____________
// /
// /
// __________/
//
NumOfSamplesValidFunctions.emplace_back(new StepFunction<float, float>(
1.0f / SignalConfiguration.SampleHistorySize, StepDirection::StepUp));
//
// Create following function(s) which shall give information how many
// history samples mismatch each other.
//
// ____________
// \
// \
// \__________
//
NumOfSamplesInvalidFunctions.emplace_back(new StepFunction<float, float>(
1.0f / SignalConfiguration.SampleHistorySize, StepDirection::StepDown));
//
// Create SignalStateDetector functionality
//
SignalStateDetectors.emplace_back(
new SignalStateDetector<float, float, float, HistoryPolicy::FIFO>(
SignalConfiguration.Output ? SignalProperties::OUTPUT
: SignalProperties::INPUT,
std::numeric_limits<int>::max(), DistanceMetrics.back(), SampleMatchesFunctions.back(),
SampleMismatchesFunctions.back(), NumOfSamplesMatchFunctions.back(),
NumOfSamplesMismatchFunctions.back(), SampleValidFunctions.back(),
SampleInvalidFunctions.back(), NumOfSamplesValidFunctions.back(),
NumOfSamplesInvalidFunctions.back(),
SignalIsDriftingFunctions.back(), SignalIsStableFunctions.back(),
// SAVE CHANGES
SignalConditionLookBackFunctions.back(),
SignalConditionHistoryDesicionFunctions.back(),
SignalConfiguration.DriftLookbackRange,
// - SAVE CHANGES
SignalConfiguration.SampleHistorySize, SignalConfiguration.DABSize,
SignalConfiguration.DABHistorySize));
//
// Create low-level application agents
//
SignalStateDetectorAgents.push_back(createSignalStateDetectorAgent(
AppCCAM, SignalConfiguration.Name, SignalStateDetectors.back()));
AppCCAM->setExecutionPolicy(
SignalStateDetectorAgents.back(),
AppExecutionPolicy::decimation(AppConfig.DownsamplingRate));
//
// Connect sensors to low-level agents.
//
LOG_INFO("Connect sensors to their corresponding low-level agents.");
AppCCAM->connectSensor(SignalStateDetectorAgents.back(), 0, Sensors.back(),
SignalConfiguration.Name + "_Sensor ->" +
SignalConfiguration.Name +
"_SignalStateDetector_Agent-Channel");
AppCCAM->connectAgents(
SystemStateDetectorAgent, SignalStateDetectors.size() - 1,
SignalStateDetectorAgents.back(),
SignalConfiguration.Name +
"_SignalStateDetector_Agent->SystemStateDetector_Agent_Channel");
}
//
// For simulation output, create a logger agent writing the output of the
// high-level agent into a CSV file.
//
LOG_INFO("Create a logger agent.");
// Create CSV writer.
std::ofstream OutputCSV(AppConfig.OutputFilePath);
//for (auto SignalConfiguration : AppConfig.SignalConfigurations) {
// OutputCSV << SignalConfiguration.Name + ",";
//}
//OutputCSV << "StateID,";
//OutputCSV << "Confidence State Valid,";
//OutputCSV << "Confidence State Invalid,";
//OutputCSV << "Confidence Inputs Matching,";
//OutputCSV << "Confidence Outputs Matching,";
//OutputCSV << "Confidence Inputs Mismatching,";
//OutputCSV << "Confidence Outputs Mismatching,";
OutputCSV << "State Condition,";
//OutputCSV << "Confidence System Functioning,";
//OutputCSV << "Confidence System Malfunctioning,";
- //OutputCSV << "Overall Confidence,";
+ OutputCSV << "Confidence Drift,";
+ OutputCSV << "Confidence Drift Up,";
+ OutputCSV << "Confidence Drift Down,";
+ OutputCSV << "Overall Confidence,";
OutputCSV << "\n";
// The agent writes each new input value into a CSV file and produces
// nothing.
using Input = std::pair<SystemStateTuple, bool>;
using Result = Optional<AppTuple<unit_t>>;
using Handler = std::function<Result(Input)>;
std::string Name = "Logger Agent";
AgentHandle LoggerAgent = AppCCAM->createAgent(
"Logger Agent", Handler([&OutputCSV](Input I) -> Result {
const SystemStateTuple &T = I.first;
OutputCSV << std::get<0>(
static_cast<const std::tuple<std::string> &>(T))
<< std::endl;
return Result();
}));
//
// Connect the high-level agent to the logger agent.
//
LOG_INFO("Connect the high-level agent to the logger agent.");
AppCCAM->connectAgents(LoggerAgent, 0, SystemStateDetectorAgent,
"SystemStateDetector Channel");
//
// Only log if the SystemStateDetector actually ran
//
AppCCAM->setExecutionPolicy(LoggerAgent, AppExecutionPolicy::awaitAll({0}));
//
// Do simulation.
//
LOG_INFO("Setting up and performing simulation.");
//
// Initialize application for simulation.
//
AppCCAM->initializeSimulation();
//
// Open CSV files and register them for their corresponding sensors.
//
// Make sure DataFiles will not change capacity while adding elements to it.
// Changing capacity moves elements away, which invalidates references
// captured by CSVIterator.
DataFiles.reserve(AppConfig.SignalConfigurations.size());
uint32_t i = 0;
bool hasMQTT = false;
for (auto SignalConfiguration : AppConfig.SignalConfigurations) {
switch (SignalConfiguration.DataInterfaceType) {
case DataInterfaceTypes::CSV:
DataFiles.emplace_back(SignalConfiguration.InputPath);
if (!DataFiles.at(i)) {
LOG_ERROR_STREAM << "Cannot open Input File \""
<< SignalConfiguration.InputPath << "\" for Signal \""
<< SignalConfiguration.Name << "\"" << std::endl;
return 3;
}
AppCCAM->registerSensorValues(Sensors.at(i),
csv::CSVIterator<float>(DataFiles.at(i)),
csv::CSVIterator<float>());
LOG_INFO_STREAM << "Sensor " << SignalConfiguration.Name
<< " is fed by csv file " << SignalConfiguration.InputPath
<< std::endl;
break;
case DataInterfaceTypes::MQTT: {
hasMQTT = true;
auto it = MQTTIterator<float>(SignalConfiguration.MQTTTopic);
AppCCAM->registerSensorValues(Sensors.at(i), std::move(it),
MQTTIterator<float>());
LOG_INFO_STREAM << "Sensor " << SignalConfiguration.Name
<< " is fed by MQTT topic "
<< SignalConfiguration.MQTTTopic << std::endl;
break;
}
default:
LOG_ERROR_STREAM << "No data source for " << SignalConfiguration.Name
<< std::endl;
break;
}
i++;
}
//
// Start simulation.
//
auto &log = LOG_WARNING_STREAM;
log << "Simulation starting.";
if (hasMQTT) {
log << " Publishing MQTT messages may start.";
}
log << std::endl;
AppCCAM->simulate(AppConfig.NumberOfSimulationCycles);
return 0;
}
diff --git a/apps/ccam/statehandlerutils.h b/apps/ccam/statehandlerutils.h
index dc40d6c..60620d4 100644
--- a/apps/ccam/statehandlerutils.h
+++ b/apps/ccam/statehandlerutils.h
@@ -1,274 +1,277 @@
#ifndef STATEHANDLERUTILS_H
#define STATEHANDLERUTILS_H
#include "rosa/agent/Abstraction.hpp"
#include "rosa/agent/Confidence.hpp"
#include "rosa/agent/FunctionAbstractions.hpp"
#include <functional>
#include <iostream>
#include <tuple>
#include <vector>
#include "rosa/config/version.h"
#include "rosa/agent/SignalStateDetector.hpp"
#include "rosa/agent/SystemStateDetector.hpp"
#include "rosa/app/Application.hpp"
#include "rosa/support/csv/CSVReader.hpp"
#include "rosa/support/csv/CSVWriter.hpp"
#include <fstream>
#include <limits>
#include <memory>
#include <streambuf>
using namespace rosa;
using namespace rosa::agent;
using namespace rosa::app;
using namespace rosa::terminal;
// For the convinience to write a shorter data type name
using SignalStateTuple =
AppTuple<float, uint32_t, uint8_t, float, float, float, float, float, float,
uint8_t, uint32_t, uint8_t>;
AgentHandle createSignalStateDetectorAgent(
std::unique_ptr<Application> &C, const std::string &Name,
std::shared_ptr<
SignalStateDetector<float, float, float, HistoryPolicy::FIFO>>
SigSD) {
using Input = std::pair<AppTuple<float>, bool>;
using Result = Optional<SignalStateTuple>;
using Handler = std::function<Result(Input)>;
return C->createAgent(
Name, Handler([&, Name, SigSD](Input I) -> Result {
LOG_INFO_STREAM << "\n******\n"
<< Name << " " << (I.second ? "<New>" : "<Old>")
<< " value: "
<< std::get<0>(
static_cast<std::tuple<float> &>(I.first))
<< "\n******\n";
auto StateInfo = SigSD->detectSignalState(
std::get<0>(static_cast<std::tuple<float> &>(I.first)));
if (I.second) {
SignalStateTuple Res = {
std::get<0>(static_cast<std::tuple<float> &>(I.first)),
StateInfo.StateID,
StateInfo.SignalProperty,
StateInfo.ConfidenceOfMatchingState,
StateInfo.ConfidenceOfMismatchingState,
StateInfo.ConfidenceStateIsValid,
StateInfo.ConfidenceStateIsInvalid,
StateInfo.ConfidenceStateIsStable,
StateInfo.ConfidenceStateIsDrifting,
StateInfo.StateCondition,
StateInfo.NumberOfInsertedSamplesAfterEntrance,
static_cast<uint8_t>(
(StateInfo.StateIsValid ? 4 : 0) +
(StateInfo.StateJustGotValid ? 2 : 0) +
(StateInfo.StateIsValidAfterReentrance ? 1 : 0))};
return Result(Res);
}
return Result();
}));
}
// System State
using SystemStateTuple = AppTuple<std::string>;
template <std::size_t size, typename ret, typename functype, typename... A>
struct Handler_helper;
template <typename B, typename func, typename A, typename... As>
struct function_helper {
static_assert(std::conjunction_v<std::is_same<A, As>...>,
"All types need to be identical");
static B function(A valA, As... valAs) {
std::vector<A> ar({valA, valAs...});
return func()(ar);
}
};
template <typename ret, typename typeA, typename functype, typename... B>
struct Handler_helper<0, ret, functype, typeA, B...> {
using handler = function_helper<ret, functype, B...>;
};
template <std::size_t size, typename ret, typename typeA, typename functype,
typename... B>
struct Handler_helper<size, ret, functype, typeA, B...> {
using handler =
typename Handler_helper<size - 1, ret, functype, typeA,
std::pair<typeA, bool>, B...>::handler;
};
template <std::size_t size, typename ret, typename functype, typename typeA>
using Handler = typename Handler_helper<size, ret, functype, typeA>::handler;
// TODO: Change it from global to local variable if possible
std::shared_ptr<
SystemStateDetector<uint32_t, float, float, HistoryPolicy::FIFO>>
SysSD;
template <typename ret, typename A> struct function {
ret operator()(A a) {
std::vector<SignalStateInformation<float>> SignalStateInfos;
std::stringstream OutString;
for (auto _SignalStateTuple : a) {
// convert tuple to info struct out.push_back({});
//OutString << std::get<0>(_SignalStateTuple.first) << ",";
SignalStateInformation<float> Info;
Info.StateID = std::get<1>(_SignalStateTuple.first);
Info.SignalProperty =
static_cast<SignalProperties>(std::get<2>(_SignalStateTuple.first));
Info.ConfidenceOfMatchingState = std::get<3>(_SignalStateTuple.first);
Info.ConfidenceOfMismatchingState = std::get<4>(_SignalStateTuple.first);
Info.ConfidenceStateIsValid = std::get<5>(_SignalStateTuple.first);
Info.ConfidenceStateIsInvalid = std::get<6>(_SignalStateTuple.first);
Info.ConfidenceStateIsStable = std::get<7>(_SignalStateTuple.first);
Info.ConfidenceStateIsDrifting = std::get<8>(_SignalStateTuple.first);
Info.StateCondition =
static_cast<StateConditions>(std::get<9>(_SignalStateTuple.first));
Info.NumberOfInsertedSamplesAfterEntrance =
std::get<10>(_SignalStateTuple.first);
Info.StateIsValid = (std::get<11>(_SignalStateTuple.first) & 4) > 0;
Info.StateJustGotValid = (std::get<11>(_SignalStateTuple.first) & 2) > 0;
Info.StateIsValidAfterReentrance =
(std::get<11>(_SignalStateTuple.first) & 1) > 0;
SignalStateInfos.push_back(Info);
}
SystemStateInformation<float> SystemStateInfo =
SysSD->detectSystemState(SignalStateInfos);
//OutString << SystemStateInfo.StateID << ",";
//OutString << SystemStateInfo.ConfidenceStateIsValid << ",";
//OutString << SystemStateInfo.ConfidenceStateIsInvalid << ",";
//OutString << SystemStateInfo.ConfidenceOfInputsMatchingState << ",";
//OutString << SystemStateInfo.ConfidenceOfInputsMismatchingState << ",";
//OutString << SystemStateInfo.ConfidenceOfOutputsMatchingState << ",";
//OutString << SystemStateInfo.ConfidenceOfOutputsMismatchingState << ",";
OutString << SystemStateInfo.StateCondition << ",";
//OutString << SystemStateInfo.ConfidenceSystemIsFunctioning << ",";
//OutString << SystemStateInfo.ConfidenceSystemIsMalfunctioning << ",";
- //OutString << SystemStateInfo.ConfidenceOfAllDecisions << ",";
+ OutString << SystemStateInfo.ConfidenceStateIsDrifting << ",";
+ OutString << SystemStateInfo.ConfidenceStateIsDriftingUp << ",";
+ OutString << SystemStateInfo.ConfidenceStateIsDriftingDown << ",";
+ OutString << SystemStateInfo.ConfidenceOfAllDecisions << ",";
return ret(std::make_tuple<std::string>(OutString.str()));
}
};
using arr = std::vector<std::pair<SignalStateTuple, bool>>;
template <size_t NumOfSlaves>
AgentHandle createSystemStateDetectorAgent(
std::unique_ptr<Application> &C, const std::string &Name,
std::shared_ptr<PartialFunction<uint32_t, float>> BrokenDelayFunction,
std::shared_ptr<PartialFunction<uint32_t, float>> OkDelayFunction) {
LOG_TRACE("Creating fixed SystemStateDetectorAgent");
using Input = SignalStateTuple;
using Result = Optional<SystemStateTuple>;
std::shared_ptr<
SystemStateDetector<uint32_t, float, float, HistoryPolicy::FIFO>>
_SysSD(
new SystemStateDetector<uint32_t, float, float, HistoryPolicy::FIFO>(
std::numeric_limits<uint32_t>::max(), NumOfSlaves,
BrokenDelayFunction, OkDelayFunction));
SysSD = _SysSD;
auto HandlerFunction =
Handler<NumOfSlaves, Result, function<Optional<SystemStateTuple>, arr>,
Input>::function;
return C->createAgent(Name, std::function(HandlerFunction));
}
AgentHandle createSystemStateDetectorAgent(
std::unique_ptr<Application> &C, const std::string &Name,
size_t NumOfSlaves,
std::shared_ptr<PartialFunction<uint32_t, float>> BrokenDelayFunction,
std::shared_ptr<PartialFunction<uint32_t, float>> OkDelayFunction) {
LOG_TRACE("Creating dynamic SystemStateDetectorAgent");
switch (NumOfSlaves) {
// clang-format off
case 2: return createSystemStateDetectorAgent< 2>(C, Name, BrokenDelayFunction, OkDelayFunction);
case 3: return createSystemStateDetectorAgent< 3>(C, Name, BrokenDelayFunction, OkDelayFunction);
case 4: return createSystemStateDetectorAgent< 4>(C, Name, BrokenDelayFunction, OkDelayFunction);
case 5: return createSystemStateDetectorAgent< 5>(C, Name, BrokenDelayFunction, OkDelayFunction);
case 6: return createSystemStateDetectorAgent< 6>(C, Name, BrokenDelayFunction, OkDelayFunction);
case 7: return createSystemStateDetectorAgent< 7>(C, Name, BrokenDelayFunction, OkDelayFunction);
case 8: return createSystemStateDetectorAgent< 8>(C, Name, BrokenDelayFunction, OkDelayFunction);
case 9: return createSystemStateDetectorAgent< 9>(C, Name, BrokenDelayFunction, OkDelayFunction);
case 10: return createSystemStateDetectorAgent<10>(C, Name, BrokenDelayFunction, OkDelayFunction);
case 11: return createSystemStateDetectorAgent<11>(C, Name, BrokenDelayFunction, OkDelayFunction);
case 12: return createSystemStateDetectorAgent<12>(C, Name, BrokenDelayFunction, OkDelayFunction);
case 13: return createSystemStateDetectorAgent<13>(C, Name, BrokenDelayFunction, OkDelayFunction);
case 14: return createSystemStateDetectorAgent<14>(C, Name, BrokenDelayFunction, OkDelayFunction);
case 15: return createSystemStateDetectorAgent<15>(C, Name, BrokenDelayFunction, OkDelayFunction);
case 16: return createSystemStateDetectorAgent<16>(C, Name, BrokenDelayFunction, OkDelayFunction);
case 17: return createSystemStateDetectorAgent<17>(C, Name, BrokenDelayFunction, OkDelayFunction);
case 18: return createSystemStateDetectorAgent<18>(C, Name, BrokenDelayFunction, OkDelayFunction);
case 19: return createSystemStateDetectorAgent<19>(C, Name, BrokenDelayFunction, OkDelayFunction);
case 20: return createSystemStateDetectorAgent<20>(C, Name, BrokenDelayFunction, OkDelayFunction);
case 21: return createSystemStateDetectorAgent<21>(C, Name, BrokenDelayFunction, OkDelayFunction);
case 22: return createSystemStateDetectorAgent<22>(C, Name, BrokenDelayFunction, OkDelayFunction);
case 23: return createSystemStateDetectorAgent<23>(C, Name, BrokenDelayFunction, OkDelayFunction);
case 24: return createSystemStateDetectorAgent<24>(C, Name, BrokenDelayFunction, OkDelayFunction);
case 25: return createSystemStateDetectorAgent<25>(C, Name, BrokenDelayFunction, OkDelayFunction);
case 1:
default: return createSystemStateDetectorAgent<1>(C, Name, BrokenDelayFunction, OkDelayFunction);
// clang-format on
}
}
// template <typename T, typename>
// AgentHandle createMQTTSensor(std::string MQTTTopic) {
// using Input = void;
// using Result = Optional<T>;
// using Handler = std::function<Result(Input)>;
// return C->createAgent(
// Name, Handler([&, Name, SigSD](Input I) -> Result {
// LOG_INFO_STREAM << "\n******\n"
// << Name << " " << (I.second ? "<New>" : "<Old>")
// << " value: "
// << std::get<0>(
// static_cast<std::tuple<float> &>(I.first))
// << "\n******\n";
// auto StateInfo = SigSD->detectSignalState(
// std::get<0>(static_cast<std::tuple<float> &>(I.first)));
// if (I.second) {
// SignalStateTuple Res = {
// std::get<0>(static_cast<std::tuple<float> &>(I.first)),
// StateInfo.StateID,
// StateInfo.SignalProperty,
// StateInfo.ConfidenceOfMatchingState,
// StateInfo.ConfidenceOfMismatchingState,
// StateInfo.ConfidenceStateIsValid,
// StateInfo.ConfidenceStateIsInvalid,
// StateInfo.ConfidenceStateIsStable,
// StateInfo.ConfidenceStateIsDrifting,
// StateInfo.StateCondition,
// StateInfo.NumberOfInsertedSamplesAfterEntrance,
// static_cast<uint8_t>(
// (StateInfo.StateIsValid ? 4 : 0) +
// (StateInfo.StateJustGotValid ? 2 : 0) +
// (StateInfo.StateIsValidAfterReentrance ? 1 : 0))};
// return Result(Res);
// }
// return Result();
// }));
// }
#endif // STATEHANDLERUTILS_H
diff --git a/include/rosa/agent/SystemState.hpp b/include/rosa/agent/SystemState.hpp
index a9f0565..d9e3ce5 100644
--- a/include/rosa/agent/SystemState.hpp
+++ b/include/rosa/agent/SystemState.hpp
@@ -1,304 +1,312 @@
//===-- rosa/agent/SystemState.hpp ------------------------------*- C++ -*-===//
//
// The RoSA Framework
//
// Distributed under the terms and conditions of the Boost Software License 1.0.
// See accompanying file LICENSE.
//
// If you did not receive a copy of the license file, see
// http://www.boost.org/LICENSE_1_0.txt.
//
//===----------------------------------------------------------------------===//
///
/// \file rosa/agent/SystemState.hpp
///
/// \author Maximilian Götzinger (maximilian.goetzinger@tuwien.ac.at)
///
/// \date 2019
///
/// \brief Definition of *system state* *functionality*.
///
//===----------------------------------------------------------------------===//
#ifndef ROSA_AGENT_SYSTEMSTATE_HPP
#define ROSA_AGENT_SYSTEMSTATE_HPP
#include "rosa/agent/Functionality.h"
#include "rosa/agent/SignalState.hpp"
#include "rosa/agent/State.hpp"
#include "rosa/support/debug.hpp"
#include <vector>
namespace rosa {
namespace agent {
enum class SystemStateRelation : uint8_t {
STATEISMATCHING = 0, ///< The system state is matching
ONLYINPUTISMATCHING = 1, ///< Only inputs of the system state are matching
ONLYOUTPUTISMATCHING = 2, ///< Only outputs of the system state are matching
STATEISMISMATCHING = 3 ///< The system state is mismatching
};
/// TODO: write description
template <typename CONFDATATYPE>
struct SystemStateInformation : StateInformation<CONFDATATYPE> {
/// TODO: describe
CONFDATATYPE ConfidenceOfInputsMatchingState;
CONFDATATYPE ConfidenceOfInputsMismatchingState;
CONFDATATYPE ConfidenceOfOutputsMatchingState;
CONFDATATYPE ConfidenceOfOutputsMismatchingState;
CONFDATATYPE ConfidenceSystemIsFunctioning;
CONFDATATYPE ConfidenceSystemIsMalfunctioning;
CONFDATATYPE ConfidenceOfAllDecisions;
public:
SystemStateInformation() = default;
SystemStateInformation(unsigned int _SystemStateID,
StateConditions _StateCondition) {
this->StateID = _SystemStateID;
this->StateCondition = _StateCondition;
this->StateIsValid = false;
this->StateJustGotValid = false;
this->StateIsValidAfterReentrance = false;
this->ConfidenceOfInputsMatchingState = 0;
this->ConfidenceOfInputsMismatchingState = 0;
this->ConfidenceOfOutputsMatchingState = 0;
this->ConfidenceOfOutputsMismatchingState = 0;
this->ConfidenceSystemIsFunctioning = 0;
this->ConfidenceSystemIsMalfunctioning = 0;
this->ConfidenceOfAllDecisions = 0;
}
};
// todo: do we need PROCDATATYPE?
/// TODO TEXT
template <typename INDATATYPE, typename CONFDATATYPE, typename PROCDATATYPE>
class SystemState : public State<INDATATYPE, CONFDATATYPE, PROCDATATYPE> {
// Make sure the actual type arguments are matching our expectations.
STATIC_ASSERT(std::is_arithmetic<INDATATYPE>::value,
"input data type is not to arithmetic");
STATIC_ASSERT(std::is_arithmetic<CONFDATATYPE>::value,
"confidence abstraction type is not to arithmetic");
STATIC_ASSERT(std::is_arithmetic<PROCDATATYPE>::value,
"process data type is not to arithmetic");
private:
/// SignalStateInfo is a struct of SignalStateInformation that contains
/// information about the current signal state.
SystemStateInformation<CONFDATATYPE> SystemStateInfo;
std::vector<SignalStateInformation<CONFDATATYPE>> SignalStateInfos;
uint32_t NumberOfSignals;
public:
/// TODO: write description
SystemState(uint32_t StateID, uint32_t NumberOfSignals) noexcept
: SystemStateInfo(StateID, StateConditions::UNKNOWN),
NumberOfSignals(NumberOfSignals) {
SignalStateInfos.resize(NumberOfSignals);
}
/// Destroys \p this object.
~SystemState(void) = default;
/// TODO: write description
SystemStateInformation<CONFDATATYPE> insertSignalStateInformation(
const std::vector<SignalStateInformation<CONFDATATYPE>>
_SignalStateInfos) noexcept {
ASSERT(_SignalStateInfos.size() == NumberOfSignals);
bool AllSignalsAreValid = true;
bool AtLeastOneSignalJustGotValid = false;
bool AllSignalsAreValidAfterReentrance = true;
bool AtLeastOneSignalIsUnknown = false;
bool AllSignalsAreStable = true;
uint32_t DriftDnCounter = 0;
uint32_t DriftUpCounter = 0;
// TODO: change this
SystemStateInfo.ConfidenceOfInputsMatchingState = 1;
SystemStateInfo.ConfidenceOfInputsMismatchingState = 0;
SystemStateInfo.ConfidenceOfOutputsMatchingState = 1;
SystemStateInfo.ConfidenceOfOutputsMismatchingState = 0;
SystemStateInfo.ConfidenceStateIsValid = 1;
SystemStateInfo.ConfidenceStateIsInvalid = 0;
SystemStateInfo.ConfidenceStateIsStable = 1;
SystemStateInfo.ConfidenceStateIsDrifting = 0;
+ SystemStateInfo.ConfidenceStateIsDriftingUp = 0;
+ SystemStateInfo.ConfidenceStateIsDriftingDown = 0;
std::size_t counter = 0;
for (auto SSI : _SignalStateInfos) {
if (!SSI.StateIsValid)
AllSignalsAreValid = false;
if (SSI.StateJustGotValid)
AtLeastOneSignalJustGotValid = true;
if (!SSI.StateIsValidAfterReentrance)
AllSignalsAreValidAfterReentrance = false;
if (SSI.StateCondition == StateConditions::UNKNOWN)
AtLeastOneSignalIsUnknown = true;
if (SSI.StateCondition == StateConditions::DRIFTING_DN) {
AllSignalsAreStable = false;
DriftDnCounter++;
}
if (SSI.StateCondition == StateConditions::DRIFTING_UP) {
AllSignalsAreStable = false;
DriftUpCounter++;
}
if (SSI.SignalProperty == SignalProperties::INPUT) {
SystemStateInfo.ConfidenceOfInputsMatchingState =
fuzzyAND(SystemStateInfo.ConfidenceOfInputsMatchingState,
SSI.ConfidenceOfMatchingState);
SystemStateInfo.ConfidenceOfInputsMismatchingState =
fuzzyOR(SystemStateInfo.ConfidenceOfInputsMismatchingState,
SSI.ConfidenceOfMismatchingState);
} else {
SystemStateInfo.ConfidenceOfOutputsMatchingState =
fuzzyAND(SystemStateInfo.ConfidenceOfOutputsMatchingState,
SSI.ConfidenceOfMatchingState);
SystemStateInfo.ConfidenceOfOutputsMismatchingState =
fuzzyOR(SystemStateInfo.ConfidenceOfOutputsMismatchingState,
SSI.ConfidenceOfMismatchingState);
}
SystemStateInfo.ConfidenceStateIsValid = fuzzyAND(
SystemStateInfo.ConfidenceStateIsValid, SSI.ConfidenceStateIsValid);
SystemStateInfo.ConfidenceStateIsInvalid =
fuzzyOR(SystemStateInfo.ConfidenceStateIsInvalid,
SSI.ConfidenceStateIsInvalid);
SystemStateInfo.ConfidenceStateIsStable = fuzzyAND(
SystemStateInfo.ConfidenceStateIsStable, SSI.ConfidenceStateIsStable);
SystemStateInfo.ConfidenceStateIsDrifting =
fuzzyOR(SystemStateInfo.ConfidenceStateIsDrifting,
SSI.ConfidenceStateIsDrifting);
+ SystemStateInfo.ConfidenceStateIsDriftingUp =
+ fuzzyOR(SystemStateInfo.ConfidenceStateIsDriftingUp,
+ SSI.ConfidenceStateIsDriftingUp);
+ SystemStateInfo.ConfidenceStateIsDriftingDown =
+ fuzzyOR(SystemStateInfo.ConfidenceStateIsDriftingDown,
+ SSI.ConfidenceStateIsDriftingDown);
this->SignalStateInfos.at(counter) = SSI;
counter++;
}
SystemStateInfo.StateIsValid = AllSignalsAreValid;
SystemStateInfo.StateJustGotValid =
AllSignalsAreValid && AtLeastOneSignalJustGotValid;
SystemStateInfo.StateIsValidAfterReentrance =
AllSignalsAreValidAfterReentrance;
if (AtLeastOneSignalIsUnknown)
SystemStateInfo.StateCondition = StateConditions::UNKNOWN;
else if (AllSignalsAreStable)
SystemStateInfo.StateCondition = StateConditions::STABLE;
else {
if (DriftDnCounter > DriftUpCounter)
SystemStateInfo.StateCondition = StateConditions::DRIFTING_DN;
else if (DriftDnCounter < DriftUpCounter)
SystemStateInfo.StateCondition = StateConditions::DRIFTING_UP;
else {
SystemStateInfo.StateCondition = StateConditions::DRIFTING;
}
}
return SystemStateInfo;
}
/// TODO: write description
// TODO (future): think about saving the state information in a history
SystemStateRelation compareSignalStateInformation(
const std::vector<SignalStateInformation<CONFDATATYPE>>
_SignalStateInfos) noexcept {
bool inputsAreMatching = true;
bool outputsAreMatching = true;
std::size_t counter = 0;
for (auto SSI : _SignalStateInfos) {
if (this->SignalStateInfos.at(counter).StateID != SSI.StateID) {
if (SSI.SignalProperty == SignalProperties::INPUT)
inputsAreMatching = false;
else // SignalProperties::OUTPUT
outputsAreMatching = false;
}
counter++;
}
if (inputsAreMatching && outputsAreMatching)
return SystemStateRelation::STATEISMATCHING;
else if (inputsAreMatching && !outputsAreMatching)
return SystemStateRelation::ONLYINPUTISMATCHING;
else if (!inputsAreMatching && outputsAreMatching)
return SystemStateRelation::ONLYOUTPUTISMATCHING;
else
return SystemStateRelation::STATEISMISMATCHING;
}
#ifdef ADDITIONAL_FUNCTIONS
/// TODO: write description
template <std::size_t size>
void insertSignalStateInformation(
const std::array<SystemStateInformation<CONFDATATYPE>, size>
&Data) noexcept {
ASSERT(size <= NumberOfSignals);
std::size_t counter = 0;
for (auto tmp : Data) {
Signals.at(counter) = tmp;
counter++;
}
}
/// TODO: write description
template <typename... Types>
std::enable_if_t<std::conjunction_v<std::is_same<
Types, SystemStateInformation<CONFDATATYPE>>...>,
void>
insertSignalStateInformation(Types... Data) {
// TODO (future): think about saving the state information in a history
insertSignalStateInfos(
std::array<SystemStateInformation<CONFDATATYPE>, sizeof...(Data)>(
{Data...}));
}
// returns true if they are identical
/// TODO: write description
template <std::size_t size>
bool compareSignalStateInformation(
const std::array<SystemStateInformation<CONFDATATYPE>, size>
&Data) noexcept {
// TODO (future): think about saving the state information in a history
std::size_t counter = 0;
for (auto tmp : Data) {
if (Signals.at(counter) != tmp)
return false;
counter++;
}
return true;
}
// checks only the given amount
/// TODO: write description
template <typename... Types>
std::enable_if_t<std::conjunction_v<std::is_same<
Types, SystemStateInformation<CONFDATATYPE>>...>,
bool>
compareSignalStateInformation(Types... Data) {
return compareSignalStateInfos(
std::array<SystemStateInformation<CONFDATATYPE>, sizeof...(Data)>(
{Data...}));
}
#endif
/// Gives information about the current signal state.
///
/// \return a struct SignalStateInformation that contains information about
/// the current signal state.
SystemStateInformation<CONFDATATYPE> systemStateInformation(void) noexcept {
return SystemStateInfo;
}
};
} // End namespace agent
} // End namespace rosa
#endif // ROSA_AGENT_SYSTEMSTATE_HPP
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sun, Apr 27, 12:43 PM (1 d, 13 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
134497
Default Alt Text
(48 KB)
Attached To
Mode
R20 SoC_Rosa_repo
Attached
Detach File
Event Timeline
Log In to Comment