#include <cstring>
#include <visp3/core/vpConfig.h>
#include <visp3/core/vpGaussRand.h>
#include <visp3/core/vpStatisticalTestEWMA.h>
#include <visp3/core/vpStatisticalTestHinkley.h>
#include <visp3/core/vpStatisticalTestMeanAdjustedCUSUM.h>
#include <visp3/core/vpStatisticalTestShewhart.h>
#include <visp3/core/vpStatisticalTestSigma.h>
#include <visp3/gui/vpPlot.h>
#ifdef ENABLE_VISP_NAMESPACE
#endif
#if defined(VISP_HAVE_DISPLAY)
namespace TutorialMeanDrift
{
typedef enum TypeTest
{
HINLKEY_TYPE_TEST = 0,
EWMA_TYPE_TEST = 1,
MEAN_ADJUSTED_CUSUM_TYPE_TEST = 2,
SHEWHART_TYPE_TEST = 3,
SIGMA_TYPE_TEST = 4,
COUNT_TYPE_TEST = 5,
UNKOWN_TYPE_TEST = COUNT_TYPE_TEST
}TypeTest;
std::string typeTestToString(const TypeTest &type)
{
std::string result;
switch (type) {
case HINLKEY_TYPE_TEST:
result = "hinkley";
break;
case EWMA_TYPE_TEST:
result = "ewma";
break;
case MEAN_ADJUSTED_CUSUM_TYPE_TEST:
result = "cusum";
break;
case SHEWHART_TYPE_TEST:
result = "shewhart";
break;
case SIGMA_TYPE_TEST:
result = "sigma";
break;
case UNKOWN_TYPE_TEST:
default:
result = "unknown-type-test";
break;
}
return result;
}
TypeTest typeTestFromString(const std::string &name)
{
TypeTest result = UNKOWN_TYPE_TEST;
unsigned int count = static_cast<unsigned int>(COUNT_TYPE_TEST);
unsigned int id = 0;
bool hasNotFound = true;
while ((id < count) && hasNotFound) {
TypeTest temp = static_cast<TypeTest>(id);
if (typeTestToString(temp) == name) {
result = temp;
hasNotFound = false;
}
++id;
}
return result;
}
std::string getAvailableTypeTest(const std::string &prefix = "<", const std::string &sep = " , ",
const std::string &suffix = ">")
{
std::string msg(prefix);
unsigned int count = static_cast<unsigned int>(COUNT_TYPE_TEST);
unsigned int lastId = count - 1;
for (unsigned int i = 0; i < lastId; i++) {
msg += typeTestToString(static_cast<TypeTest>(i)) + sep;
}
msg += typeTestToString(static_cast<TypeTest>(lastId)) + suffix;
return msg;
}
template <typename T>
std::string numberToString(const T &number)
{
std::stringstream ss;
ss << number;
return ss.str();
}
std::string boolToString(const bool &boolean)
{
if (boolean) {
return "true";
}
else {
return "false";
}
}
std::string wecoRulesToString(
const bool rules[
vpStatisticalTestShewhart::COUNT_WECO - 1],
const std::string &prefix =
"[",
const std::string &suffix =
"]",
const std::string &sep =
" , ")
{
std::string rulesAsString = prefix;
if (rules[i]) {
rulesAsString += "ON";
}
else {
rulesAsString += "OFF";
}
rulesAsString += sep;
}
rulesAsString += "ON";
}
else {
rulesAsString += "OFF";
}
rulesAsString += suffix;
return rulesAsString;
}
{
size_t nbNames = names.size();
for (size_t i = 0; i < nbNames; ++i) {
std::cout << "alarm[" << names[i] << "] (i.e. " << static_cast<unsigned int>(alarmToActivate) << ") set to true" << std::endl;
array[static_cast<unsigned int>(alarmToActivate)] = true;
}
}
}
}
{
std::vector<std::string> listActivatedAlarms;
for (unsigned int id = 0; id < nbTypeTests; ++id) {
if (array[id]) {
listActivatedAlarms.push_back(testName);
}
}
return listActivatedAlarms;
}
const std::string &prefix = "[", const std::string &sep = " , ",
const std::string &suffix = "]")
{
std::vector<std::string> listActivatedAlarms = meanDriftArrayToVectorOfString(array);
std::string result = prefix;
size_t nbTestActivated = listActivatedAlarms.size();
if (nbTestActivated == 0) {
return prefix + " " + suffix;
}
for (size_t i = 0; i < nbTestActivated - 1; ++i) {
result += listActivatedAlarms[i] + sep;
}
result += listActivatedAlarms[nbTestActivated - 1] + suffix;
return result;
}
{
unsigned int nbActivated = 0;
for (unsigned int id = 0; id < nbTypeAlarms; ++id) {
if (array[id]) {
++nbActivated;
}
}
return nbActivated;
}
#ifndef DOXYGEN_SHOULD_SKIP_THIS
typedef struct ParametersForAlgo
{
unsigned int m_test_nbsamples;
unsigned int m_test_nbactivatedalarms;
float m_cusum_h;
float m_cusum_k;
float m_ewma_alpha;
float m_hinkley_alpha;
float m_hinkley_delta;
bool m_hinkley_computealphadelta;
float m_hinkley_h;
float m_hinkley_k;
bool m_shewhart_useWECO;
float m_sigma_h;
ParametersForAlgo()
: m_test_nbsamples(30)
, m_cusum_h(4.76f)
, m_cusum_k(1.f)
, m_ewma_alpha(0.1f)
, m_hinkley_alpha(4.76f)
, m_hinkley_delta(1.f)
, m_hinkley_computealphadelta(false)
, m_hinkley_h(4.76f)
, m_hinkley_k(1.f)
, m_shewhart_useWECO(false)
, m_sigma_h(3.f)
{
m_test_nbactivatedalarms = meanDriftArrayToNbActivated(m_test_activatedalarms);
}
}ParametersForAlgo;
}
#endif
int testOnSynthetic(const TutorialMeanDrift::TypeTest &type, const TutorialMeanDrift::ParametersForAlgo parameters,
const float &mean, const float &mean_drift, const float &stdev)
{
const float dt = 10.f;
plotter.initGraph(0, 1);
plotter.setTitle(0, "Evolution of the signal");
plotter.setUnitX(0, "Frame ID");
plotter.setUnitY(0, "No units");
unsigned int idFrame = 0;
switch (type) {
case TutorialMeanDrift::EWMA_TYPE_TEST:
break;
case TutorialMeanDrift::HINLKEY_TYPE_TEST:
p_test =
new vpStatisticalTestHinkley(parameters.m_hinkley_alpha, parameters.m_hinkley_delta, parameters.m_test_nbsamples);
break;
case TutorialMeanDrift::MEAN_ADJUSTED_CUSUM_TYPE_TEST:
break;
case TutorialMeanDrift::SHEWHART_TYPE_TEST:
p_test =
new vpStatisticalTestShewhart(parameters.m_shewhart_useWECO, parameters.m_shewhart_rules, parameters.m_test_nbsamples);
break;
case TutorialMeanDrift::SIGMA_TYPE_TEST:
break;
default:
break;
}
if ((type == TutorialMeanDrift::HINLKEY_TYPE_TEST) && parameters.m_hinkley_computealphadelta) {
delete p_test;
p_test =
new vpStatisticalTestHinkley(parameters.m_hinkley_h, parameters.m_hinkley_k,
true, parameters.m_test_nbsamples);
}
float signal;
for (unsigned int i = 0; i < parameters.m_test_nbsamples; ++i) {
vpGaussRand rndGen(stdev, mean,
static_cast<long>(idFrame * dt));
signal = static_cast<float>(rndGen());
++idFrame;
}
std::cout <<
"Estimated mean of the input signal: " << p_test->
getMean() << std::endl;
std::cout <<
"Estimated stdev of the input signal: " << p_test->
getStdev() << std::endl;
float mean_eff = mean;
bool hasToRun = true;
while (hasToRun) {
vpGaussRand rndGen(stdev, mean_eff,
static_cast<long>(idFrame * dt));
signal = static_cast<float>(rndGen());
plotter.plot(0, 0, idFrame - parameters.m_test_nbsamples, signal);
hasToRun = false;
}
else {
mean_eff += mean_drift;
++idFrame;
}
}
std::cout << "Test failed at frame: " << idFrame - parameters.m_test_nbsamples << std::endl;
std::cout << "Last signal value: " << signal << std::endl;
if (type == TutorialMeanDrift::EWMA_TYPE_TEST) {
std::cout <<
"\tw(t) = " << p_testEwma->
getWt() << std::endl;
}
else if (type == TutorialMeanDrift::MEAN_ADJUSTED_CUSUM_TYPE_TEST) {
}
else if (type==TutorialMeanDrift::SHEWHART_TYPE_TEST) {
std::vector<float> signal = p_testShewhart->
getSignals();
size_t nbSignal = signal.size();
std::cout << "Signal history = [ ";
for (size_t i = 0; i < nbSignal; ++i) {
std::cout << signal[i] << " ";
}
std::cout << "]" << std::endl;
}
else if (type == TutorialMeanDrift::HINLKEY_TYPE_TEST) {
float Mk = p_hinkley->
getMk();
float Nk = p_hinkley->
getNk();
float Sk = p_hinkley->
getSk();
float Tk = p_hinkley->
getTk();
std::cout << "S+(t) = " << Tk - Nk <<std::endl;
std::cout << "S-(t) = " << Mk - Sk <<std::endl;
}
float limitDown = 0.f, limitUp = 0.f;
std::cout << "\tLimit down = " << limitDown << std::endl;
std::cout << "\tLimit up = " << limitUp << std::endl;
std::cout << "End of test on synthetic data. Press enter to leave." << std::endl;
std::cin.get();
delete p_test;
return EXIT_SUCCESS;
}
int main(int argc, char *argv[])
{
TutorialMeanDrift::TypeTest opt_typeTest = TutorialMeanDrift::MEAN_ADJUSTED_CUSUM_TYPE_TEST;
TutorialMeanDrift::ParametersForAlgo parameters;
float opt_mean = 6.f;
float opt_meandrift = 0.f;
float opt_stdev = 2.f;
int i = 1;
while (i < argc) {
if ((std::string(argv[i]) == "--test") && ((i + 1) < argc)) {
opt_typeTest = TutorialMeanDrift::typeTestFromString(argv[i + 1]);
++i;
}
else if ((std::string(argv[i]) == "--nb-samples") && ((i + 1) < argc)) {
parameters.m_test_nbsamples = std::atoi(argv[i + 1]);
++i;
}
else if ((std::string(argv[i]) == "--mean") && ((i + 1) < argc)) {
opt_mean = static_cast<float>(std::atof(argv[i + 1]));
++i;
}
else if ((std::string(argv[i]) == "--mean-drift") && ((i + 1) < argc)) {
opt_meandrift = static_cast<float>(std::atof(argv[i + 1]));
++i;
}
else if ((std::string(argv[i]) == "--stdev") && ((i + 1) < argc)) {
opt_stdev = static_cast<float>(std::atof(argv[i + 1]));
++i;
}
else if ((std::string(argv[i]) == "--alarms")) {
unsigned int nbArguments = 0;
std::vector<std::string> alarmNames;
bool hasNotFoundNextParams = true;
for (int j = 1; ((i + j) < argc) && hasNotFoundNextParams; ++j) {
std::string candidate(argv[i+j]);
if (candidate.find("--") != std::string::npos) {
hasNotFoundNextParams = false;
}
else {
alarmNames.push_back(candidate);
++nbArguments;
}
}
TutorialMeanDrift::vectorOfStringToMeanDriftTypeArray(alarmNames, parameters.m_test_activatedalarms);
parameters.m_test_nbactivatedalarms = TutorialMeanDrift::meanDriftArrayToNbActivated(parameters.m_test_activatedalarms);
i += nbArguments;
}
else if ((std::string(argv[i]) == "--cusum-h") && ((i + 1) < argc)) {
parameters.m_cusum_h = static_cast<float>(std::atof(argv[i + 1]));
++i;
}
else if ((std::string(argv[i]) == "--cusum-k") && ((i + 1) < argc)) {
parameters.m_cusum_k = static_cast<float>(std::atof(argv[i + 1]));
++i;
}
else if ((std::string(argv[i]) == "--ewma-alpha") && ((i + 1) < argc)) {
parameters.m_ewma_alpha = static_cast<float>(std::atof(argv[i + 1]));
++i;
}
else if ((std::string(argv[i]) == "--hinkley-alpha") && ((i + 1) < argc)) {
parameters.m_hinkley_alpha = static_cast<float>(std::atof(argv[i + 1]));
++i;
}
else if ((std::string(argv[i]) == "--hinkley-delta") && ((i + 1) < argc)) {
parameters.m_hinkley_delta = static_cast<float>(std::atof(argv[i + 1]));
++i;
}
else if (std::string(argv[i]) == "--hinkley-compute") {
parameters.m_hinkley_computealphadelta = true;
}
else if ((std::string(argv[i]) == "--hinkley-h") && ((i + 1) < argc)) {
parameters.m_hinkley_h = static_cast<float>(std::atof(argv[i + 1]));
++i;
}
else if ((std::string(argv[i]) == "--hinkley-k") && ((i + 1) < argc)) {
parameters.m_hinkley_k = static_cast<float>(std::atof(argv[i + 1]));
++i;
}
std::string argument = std::string(argv[i + 1 + j]);
if ((argument.find("on") != std::string::npos) || (argument.find("ON") != std::string::npos)) {
parameters.m_shewhart_rules[j] = true;
}
else {
parameters.m_shewhart_rules[j] = false;
}
}
}
else if (std::string(argv[i]) == "--shewhart-weco") {
parameters.m_shewhart_useWECO = true;
}
else if ((std::string(argv[i]) == "--sigma-h") && ((i + 1) < argc)) {
parameters.m_sigma_h = static_cast<float>(std::atof(argv[i + 1]));
++i;
}
else if ((std::string(argv[i]) == "--help") || (std::string(argv[i]) == "-h")) {
std::cout << "\nSYNOPSIS " << std::endl
<< argv[0]
<< " [--test <type>]"
<< " [--nb-samples <value>]"
<< " [--alarms <name_1 ... name_n>]"
<< " [--mean <value>]"
<< " [--mean-drift <value>]"
<< " [--stdev <value>]"
<< " [--cusum-h <value>]"
<< " [--cusum-k <value>]"
<< " [--ewma-alpha <value ]0; 1[>]"
<< " [--hinkley-alpha <]0; inf[>]"
<< " [--hinkley-delta <]0; inf[>]"
<< " [--hinkley-compute]"
<< " [--hinkley-h <]0; inf[>]"
<< " [--hinkley-k <]0; inf[>]"
<< " [--shewhart-rules <3-sigma:{on|off} 2-sigma:{on|off} 1-sigma:{on|off} same-side:{on|off}>"
<< " [--shewhart-weco]"
<< " [--sigma-h <value>]"
<< " [--help,-h]" << std::endl;
std::cout << "\nOPTIONS " << std::endl
<< " --test <type-name>" << std::endl
<< " Type of test to perform on the data." << std::endl
<< " Available values: " << TutorialMeanDrift::getAvailableTypeTest() << std::endl
<< std::endl
<< " --nb-samples <value>" << std::endl
<< " Number of samples to compute the mean and standard deviation of the monitored signal." << std::endl
<< " Default: " << parameters.m_test_nbsamples << std::endl
<< std::endl
<< " --alarms <name_1 .. name_n>" << std::endl
<< " Set the mean drift alarms to monitor." << std::endl
<< " Default: " << TutorialMeanDrift::meanDriftArrayToString(parameters.m_test_activatedalarms) << std::endl
<< std::endl
<< " --mean <value>" << std::endl
<< " Mean of the signal." << std::endl
<< " Default: " << opt_mean<< std::endl
<< std::endl
<< " --mean-drift <value>" << std::endl
<< " Mean drift for the synthetic data." << std::endl
<< " Default: " << opt_meandrift << std::endl
<< std::endl
<< " --stdev <value>" << std::endl
<< " Standard deviation of the signal." << std::endl
<< " Default: " << opt_stdev << std::endl
<< std::endl
<< " --cusum-h <value>" << std::endl
<< " The alarm factor that permits to the CUSUM test to determine when the process is out of control" << std::endl
<< " from the standard deviation of the signal." << std::endl
<< " Default: " << parameters.m_cusum_h << std::endl
<< std::endl
<< " --cusum-k <value>" << std::endl
<< " The factor that permits to determine the slack of the CUSUM test, " << std::endl
<< " i.e. the minimum value of the jumps we want to detect, from the standard deviation of the signal." << std::endl
<< " Default: " << parameters.m_cusum_k << std::endl
<< std::endl
<< " --ewma-alpha <value ]0; 1[>" << std::endl
<< " Forgetting factor for the Exponential Weighted Moving Average (EWMA)." << std::endl
<< " Default: " << parameters.m_ewma_alpha << std::endl
<< std::endl
<< " --hinkley-alpha <value ]0; inf[>" << std::endl
<< " The alarm threshold indicating that a mean drift occurs for the Hinkley's test." << std::endl
<< " Default: " << parameters.m_hinkley_alpha << std::endl
<< std::endl
<< " --hinkley-delta <value>" << std::endl
<< " Detection threshold indicating minimal magnitude we want to detect for the Hinkley's test." << std::endl
<< " Default: " << parameters.m_hinkley_delta << std::endl
<< std::endl
<< " --hinkley-compute" << std::endl
<< " If set, the Hinkley's test will compute the alarm and detection thresholds" << std::endl
<< " from the standard deviation of the input signal." << std::endl
<< " Default: disabled" << std::endl
<< std::endl
<< " --hinkley-h <value>" << std::endl
<< " Alarm factor permitting to compute the alarm threshold for the Hinkley's test." << std::endl
<< " Default: " << parameters.m_hinkley_h << std::endl
<< std::endl
<< " --hinkley-k <value>" << std::endl
<< " Detection factor permitting to compute the Detection threshold for the Hinkley's test." << std::endl
<< " Default: " << parameters.m_hinkley_k << std::endl
<< std::endl
<< " --shewhart-rules <3-sigma:{on|off} 2-sigma:{on|off} 1-sigma:{on|off} same-side:{on|off}>" << std::endl
<< " Choose the WECO additionnal tests for the Shewhart's test to use. To activate them, --shewart-weco must be used." << std::endl
<< " Default: ON ON ON ON" << std::endl
<< std::endl
<< " --shewhart-weco" << std::endl
<< " Activate the WECO additionnal tests for the Shewhart's test." << std::endl
<< " Default: deactivated" << std::endl
<< std::endl
<< " --sigma-h <value>" << std::endl
<< " The alarm factor of the sigma test." << std::endl
<< " Default: " << parameters.m_sigma_h << std::endl
<< std::endl
<< " --help, -h" << std::endl
<< " Display this helper message." << std::endl
<< std::endl;
return EXIT_SUCCESS;
}
else {
std::cout << "\nERROR " << std::endl << " Unknown option " << argv[i] << std::endl;
return EXIT_FAILURE;
}
++i;
}
if (parameters.m_test_nbactivatedalarms == 0) {
return EXIT_FAILURE;
}
std::cout << " Activated statistical test : " << TutorialMeanDrift::typeTestToString(opt_typeTest) << std::endl;
std::cout << " Activated alarms : " << TutorialMeanDrift::meanDriftArrayToString(parameters.m_test_activatedalarms) << std::endl;
std::cout << " Nb samples for statistics computation: " << parameters.m_test_nbsamples << std::endl;
std::cout << " Alarm factor CUSUM test : " << (opt_typeTest == TutorialMeanDrift::MEAN_ADJUSTED_CUSUM_TYPE_TEST ? TutorialMeanDrift::numberToString(parameters.m_cusum_h) : "N/A") << std::endl;
std::cout << " Detection factor CUSUM test : " << (opt_typeTest == TutorialMeanDrift::MEAN_ADJUSTED_CUSUM_TYPE_TEST ? TutorialMeanDrift::numberToString(parameters.m_cusum_k) : "N/A") << std::endl;
std::cout << " Forgetting factor EWMA test : " << (opt_typeTest == TutorialMeanDrift::EWMA_TYPE_TEST ? TutorialMeanDrift::numberToString(parameters.m_ewma_alpha) : "N/A") << std::endl;
std::cout << " Alarm threshold Hinkley's test : " << ((opt_typeTest == TutorialMeanDrift::HINLKEY_TYPE_TEST) && (!parameters.m_hinkley_computealphadelta) ? TutorialMeanDrift::numberToString(parameters.m_hinkley_alpha) : "N/A") << std::endl;
std::cout << " Detection threshold Hinkley's test : " << ((opt_typeTest == TutorialMeanDrift::HINLKEY_TYPE_TEST) && (!parameters.m_hinkley_computealphadelta) ? TutorialMeanDrift::numberToString(parameters.m_hinkley_delta) : "N/A") << std::endl;
std::cout << " Alarm factor Hinkley's test : " << ((opt_typeTest == TutorialMeanDrift::HINLKEY_TYPE_TEST) && parameters.m_hinkley_computealphadelta ? TutorialMeanDrift::numberToString(parameters.m_hinkley_h) : "N/A") << std::endl;
std::cout << " Detection factor Hinkley's test : " << ((opt_typeTest == TutorialMeanDrift::HINLKEY_TYPE_TEST) && parameters.m_hinkley_computealphadelta ? TutorialMeanDrift::numberToString(parameters.m_hinkley_k) : "N/A") << std::endl;
std::cout << " Shewhart's test set of WECO rules : " << (parameters.m_shewhart_useWECO && (opt_typeTest == TutorialMeanDrift::SHEWHART_TYPE_TEST) ? TutorialMeanDrift::wecoRulesToString(parameters.m_shewhart_rules) : "N/A") << std::endl;
std::cout << " Shewhart's test use WECO rules : " << (opt_typeTest == TutorialMeanDrift::SHEWHART_TYPE_TEST ? TutorialMeanDrift::boolToString(parameters.m_shewhart_useWECO && (opt_typeTest == TutorialMeanDrift::SHEWHART_TYPE_TEST)) : "N/A") << std::endl;
std::cout << " Alarm factor Sigma test : " << (opt_typeTest == TutorialMeanDrift::SIGMA_TYPE_TEST ? TutorialMeanDrift::numberToString(parameters.m_sigma_h) : "N/A") << std::endl;
std::cout << " Actual mean of the input signal: " << opt_mean << std::endl;
std::cout << " Actual stdev of the input signal: " << opt_stdev << std::endl;
std::cout << " Mean drift of the input signal: " << opt_meandrift << std::endl;
return testOnSynthetic(opt_typeTest, parameters, opt_mean, opt_meandrift, opt_stdev);
}
#else
int main()
{
std::cerr << "Recompile ViSP with display capabilities in order to use this tutorial." << std::endl;
return EXIT_FAILURE;
}
#endif
error that can be emitted by ViSP classes.
@ badValue
Used to indicate that a value is not in the allowed range.
Class for generating random number with normal probability density.
This class enables real time drawing of 2D or 3D graphics. An instance of the class open a window whi...
Base class for methods detecting the drift of the mean of a process.
static std::string vpMeanDriftTypeToString(const vpMeanDriftType &type)
Cast a vpMeanDriftType into a string.
vpMeanDriftType
Enum that indicates if a drift of the mean occurred.
static vpMeanDriftType vpMeanDriftTypeFromString(const std::string &name)
Cast a string into a vpMeanDriftType.
void getLimits(float &limitDown, float &limitUp) const
Get the upper and lower limits of the test signal.
vpMeanDriftType testDownUpwardMeanDrift(const float &signal)
Test if a downward or an upward mean drift occurred according to the new value of the signal.
float getMean() const
Get the mean used as reference.
float getStdev() const
Get the standard deviation used as reference.
static std::string getAvailableMeanDriftType(const std::string &prefix="<", const std::string &sep=" , ", const std::string &suffix=">")
Get the list of available vpMeanDriftType objects that are handled.
Class that permits to perform Exponentially Weighted Moving Average mean drft tests.
float getWt() const
Get the current value of the test signal.
This class implements the Hinkley's cumulative sum test.
float getNk() const
Get the minimum of the test signal for upward mean drift .
float getTk() const
Get the test signal for upward mean drift..
float getSk() const
Get the test signal for downward mean drift.
float getMk() const
Get the maximum of the test signal for downward mean drift .
Class that permits to perform a mean adjusted Cumulative Sum test.
float getTestSignalMinus() const
Get the latest value of the test signal for downward jumps of the mean.
float getTestSignalPlus() const
Get the latest value of the test signal for upward jumps of the mean.
Class that permits a Shewhart's test.
vpWecoRulesAlarm getAlarm() const
Get the alarm raised by the last test due to the WECO's rules.
std::vector< float > getSignals() const
Get the NB_DATA_SIGNAL last signal values, sorted from the latest [0] to the newest [NB_DATA_SIGNAL -...
static const bool CONST_ALL_WECO_ACTIVATED[COUNT_WECO - 1]
static std::string vpWecoRulesAlarmToString(const vpWecoRulesAlarm &alarm)
Class that permits a simple test comparing the current value to the standard deviation of the signal.