42#include <visp3/core/vpStatisticalTestEWMA.h>
43#include <visp3/core/vpStatisticalTestHinkley.h>
44#include <visp3/core/vpStatisticalTestMeanAdjustedCUSUM.h>
45#include <visp3/core/vpStatisticalTestShewhart.h>
46#include <visp3/core/vpStatisticalTestSigma.h>
48#ifdef ENABLE_VISP_NAMESPACE
52bool initializeShewhartTest(
const float &mean,
const float &stdev,
const bool &verbose,
const std::string &testName,
vpStatisticalTestShewhart &tester);
53void usage(
const char *name);
54bool getOptions(
int argc,
const char **argv,
float &opt_mean,
float &opt_stdev,
bool &opt_verbose);
56bool initializeShewhartTest(
const float &mean,
const float &stdev,
const bool &verbose,
const std::string &testName,
vpStatisticalTestShewhart &tester)
58 const bool activateWECOrules =
true;
66 isInitOK = (drift == EXPECTED_DRIFT_INIT);
73 std::cerr <<
"\t" << testName <<
" test initialization failed: " << std::endl;
74 std::cerr <<
"\t\ts(t) = " << tester.
getSignal() << std::endl;
75 float limitDown = 0.f, limitUp = 0.f;
77 std::cerr <<
"\t\tlim_- = " << limitDown << std::endl;
78 std::cerr <<
"\t\tlim_+ = " << limitUp << std::endl;
86void usage(
const char *name)
88 std::cout <<
"SYNOPSIS " << std::endl;
89 std::cout << name <<
"[--mean <value>] [--stdev <value>] [-v, --verbose] [-h, --help]" << std::endl;
90 std::cout <<
"\nOPTIONS" << std::endl;
91 std::cout <<
" --mean" << std::endl;
92 std::cout <<
" Permits to set the mean of the input signal." << std::endl;
93 std::cout << std::endl;
94 std::cout <<
" --stdev" << std::endl;
95 std::cout <<
" Permits to set the standard deviation of the input signal." << std::endl;
96 std::cout << std::endl;
97 std::cout <<
" -v, --verbose" << std::endl;
98 std::cout <<
" Activate verbose mode." << std::endl;
99 std::cout << std::endl;
100 std::cout <<
" -h, --help" << std::endl;
101 std::cout <<
" Display the help." << std::endl;
102 std::cout << std::endl;
105bool getOptions(
int argc,
const char **argv,
float &opt_mean,
float &opt_stdev,
bool &opt_verbose)
109 std::string argname(argv[i]);
110 if ((argname ==
"--mean") && ((i + 1) < argc)) {
111 opt_mean =
static_cast<float>(std::atof(argv[i + 1]));
114 else if ((argname ==
"--stdev") && ((i + 1) < argc)) {
115 opt_stdev =
static_cast<float>(std::atof(argv[i + 1]));
118 else if ((argname ==
"-v") || (argname ==
"--verbose")) {
121 else if ((argname ==
"-h") || (argname ==
"--help")) {
125 else if ((argname ==
"-c") || (argname ==
"-d")) {
130 std::cerr <<
"Error: unrecognised argument \"" << argv[
i] <<
"\"" << std::endl;
138int main(
int argc,
const char **argv)
140 float opt_mean = 0.f;
141 float opt_stdev = 1.f;
142 bool opt_verbose =
false;
144 bool isParsingOk = getOptions(argc, argv, opt_mean, opt_stdev, opt_verbose);
154 std::cout <<
"------ vpStatisticalTestEWMA tests ------" << std::endl;
156 const float alpha = 0.1f;
161 tester.
init(alpha, opt_mean, opt_stdev);
166 float signal = (1.f / alpha) * (alpha * opt_mean + 3.f * opt_stdev * std::sqrt(alpha / (2.f - alpha)));
172 std::cerr <<
"Upward drift test failed: " << std::endl;
173 std::cerr <<
"\tw(t) = " << tester.getWt() << std::endl;
174 float limitDown = 0.f, limitUp = 0.f;
176 std::cerr <<
"\tlimit_up = " << limitUp << std::endl;
179 else if (opt_verbose) {
180 std::cout <<
"Upward drift test succeeded." << std::endl;
186 tester.
init(alpha, opt_mean, opt_stdev);
190 float signal = (1.f / alpha) * (alpha * opt_mean - 3.f * opt_stdev * std::sqrt(alpha / (2.f - alpha)));
196 std::cerr <<
"Downward drift test failed: " << std::endl;
197 std::cerr <<
"\tw(t) = " << tester.getWt() << std::endl;
198 float limitDown = 0.f, limitUp = 0.f;
200 std::cerr <<
"\tlimit_down = " << limitDown << std::endl;
203 else if (opt_verbose) {
204 std::cout <<
"Downward drift test succeeded." << std::endl;
212 std::cout <<
"------ vpStatisticalTestHinkley tests ------" << std::endl;
215 const float h = 4.76f, k = 1.f;
217 const unsigned int HINKLEY_NB_DATA = 4;
218 const float HINKLEY_SAMPLE = 2.f * opt_stdev;
222 const float HINKLEY_DATA[HINKLEY_NB_DATA] = { HINKLEY_SAMPLE, HINKLEY_SAMPLE, HINKLEY_SAMPLE, HINKLEY_SAMPLE };
224 bool isTestOk =
true;
227 while ((
id < HINKLEY_NB_DATA) && isTestOk) {
229 isTestOk = (drift == HINKLEY_EXPECTED_RES[id]);
237 std::cerr <<
"Upward drift test failed: " << std::endl;
238 float Tk = tester.getTk(), Nk = tester.getNk();
239 std::cerr <<
"T(k) = " << Tk <<
" | N(k) = " << Nk <<
" => S+(k) = " << Tk - Nk << std::endl;
240 float limitDown = 0.f, limitUp = 0.f;
242 std::cerr <<
"lim_+ = " << limitUp << std::endl;
247 else if (opt_verbose) {
248 std::cout <<
"Upward drift test succeeded." << std::endl;
254 const float HINKLEY_DATA[HINKLEY_NB_DATA] = { -1.f * HINKLEY_SAMPLE, -1.f * HINKLEY_SAMPLE, -1.f * HINKLEY_SAMPLE, -1.f * HINKLEY_SAMPLE };
256 bool isTestOk =
true;
259 while ((
id < HINKLEY_NB_DATA) && isTestOk) {
261 isTestOk = (drift == HINKLEY_EXPECTED_RES[id]);
269 std::cerr <<
"Downward drift test failed: " << std::endl;
270 float Sk = tester.getSk(), Mk = tester.getMk();
271 std::cerr <<
"S(k) = " << Sk <<
" | M(k) = " << Mk <<
" => S+(k) = " << Mk - Sk << std::endl;
272 float limitDown = 0.f, limitUp = 0.f;
274 std::cerr <<
"lim_- = " << limitDown << std::endl;
279 else if (opt_verbose) {
280 std::cout <<
"Downward drift test succeeded." << std::endl;
288 std::cout <<
"------ vpStatisticalTestMeanAdjustedCUSUM tests ------" << std::endl;
291 const float h = 4.76f, k = 1.f;
293 tester.
init(h, k, opt_mean, opt_stdev);
294 const unsigned int CUSUM_NB_DATA = 4;
295 const float CUSUM_SAMPLE = 2.f * opt_stdev;
299 const float CUSUM_DATA[CUSUM_NB_DATA] = { CUSUM_SAMPLE, CUSUM_SAMPLE, CUSUM_SAMPLE, CUSUM_SAMPLE };
301 bool isTestOk =
true;
304 while ((
id < CUSUM_NB_DATA) && isTestOk) {
306 isTestOk = (drift == CUSUM_EXPECTED_RES[id]);
314 std::cerr <<
"Upward drift test failed: " << std::endl;
315 std::cerr <<
"\tS+(k) = " << tester.getTestSignalPlus() << std::endl;
316 float limitDown = 0.f, limitUp = 0.f;
318 std::cerr <<
"\tlim_+ = " << limitUp << std::endl;
323 else if (opt_verbose) {
324 std::cout <<
"Upward drift test succeeded." << std::endl;
330 const float CUSUM_DATA[CUSUM_NB_DATA] = { -1.f * CUSUM_SAMPLE, -1.f * CUSUM_SAMPLE, -1.f * CUSUM_SAMPLE, -1.f * CUSUM_SAMPLE };
332 bool isTestOk =
true;
335 while ((
id < CUSUM_NB_DATA) && isTestOk) {
337 isTestOk = (drift == CUSUM_EXPECTED_RES[id]);
345 std::cerr <<
"Downward drift test failed: " << std::endl;
346 std::cerr <<
"\tS-(k) = " << tester.getTestSignalMinus() << std::endl;
347 float limitDown = 0.f, limitUp = 0.f;
349 std::cerr <<
"\tlim_- = " << limitDown << std::endl;
354 else if (opt_verbose) {
355 std::cout <<
"Downward drift test succeeded." << std::endl;
363 std::cout <<
"------ vpStatisticalTestShewhart tests ------" << std::endl;
365 const bool activateWECOrules =
true;
371 std::cout <<
"Upward drift tests" << std::endl;
376 bool isInitOK = initializeShewhartTest(opt_mean, opt_stdev, opt_verbose,
"3-sigma", tester);
381 const float signal = 3.5f * opt_stdev;
386 if ((drift != EXPECTED_DRIFT) || (alarm != EXPECTED_ALARM)) {
389 std::cerr <<
"\t3-sigma test failed: " << std::endl;
391 std::cerr <<
"\t\ts(t) = [ ";
392 for (
size_t i = 0;
i <
s.size(); ++
i) {
393 std::cerr <<
s[
i] <<
" ";
395 std::cerr <<
"]" << std::endl;
396 float limitDown = 0.f, limitUp = 0.f;
398 std::cerr <<
"\t\tlim_+ = " << limitUp << std::endl;
405 else if (opt_verbose) {
406 std::cout <<
"\t3-sigma test succeeded " << std::endl;
413 bool isInitOK = initializeShewhartTest(opt_mean, opt_stdev, opt_verbose,
"2-sigma", tester);
418 const unsigned int NB_SAMPLES = 3;
419 const float DATA[NB_SAMPLES] = { 2.75f * opt_stdev, 1.5f * opt_stdev, 2.5f * opt_stdev };
425 bool isTestOk =
true;
426 while ((i < NB_SAMPLES) && isTestOk) {
429 isTestOk = ((drift == EXPECTED_DRIFT[
i]) && (alarm == EXPECTED_ALARM[
i]));
438 std::cerr <<
"\t2-sigma test failed: " << std::endl;
440 std::cerr <<
"\t\ts(t) = [ ";
441 for (
size_t j = 0;
j <
s.size(); ++
j) {
442 std::cerr <<
s[
j] <<
" ";
444 std::cerr <<
"]" << std::endl;
445 float limitDown = 0.f, limitUp = 0.f;
447 std::cerr <<
"\t\tlim_+ = " << limitUp << std::endl;
454 else if (opt_verbose) {
455 std::cout <<
"\t2-sigma test succeeded " << std::endl;
462 bool isInitOK = initializeShewhartTest(opt_mean, opt_stdev, opt_verbose,
"1-sigma", tester);
467 const unsigned int NB_SAMPLES = 5;
468 const float DATA[NB_SAMPLES] = { 2.75f * opt_stdev, 1.5f * opt_stdev, 0.5f * opt_stdev, 1.5f * opt_stdev, 2.5f * opt_stdev };
474 bool isTestOk =
true;
475 while ((i < NB_SAMPLES) && isTestOk) {
478 isTestOk = ((drift == EXPECTED_DRIFT[
i]) && (alarm == EXPECTED_ALARM[
i]));
487 std::cerr <<
"\t1-sigma test failed: " << std::endl;
489 std::cerr <<
"\t\ts(t) = [ ";
490 for (
size_t j = 0;
j <
s.size(); ++
j) {
491 std::cerr <<
s[
j] <<
" ";
493 std::cerr <<
"]" << std::endl;
494 float limitDown = 0.f, limitUp = 0.f;
496 std::cerr <<
"\t\tlim_+ = " << limitUp << std::endl;
503 else if (opt_verbose) {
504 std::cout <<
"\t1-sigma test succeeded " << std::endl;
511 bool isInitOK = initializeShewhartTest(opt_mean, opt_stdev, opt_verbose,
"Same-side", tester);
516 const unsigned int NB_SAMPLES = 8;
517 const float DATA[NB_SAMPLES] = { 2.75f * opt_stdev, 0.5f * opt_stdev, 1.5f * opt_stdev, 0.5f * opt_stdev, 2.75f * opt_stdev, 0.5f * opt_stdev, 1.5f * opt_stdev, 0.5f * opt_stdev };
523 bool isTestOk =
true;
524 while ((i < NB_SAMPLES) && isTestOk) {
527 isTestOk = ((drift == EXPECTED_DRIFT[
i]) && (alarm == EXPECTED_ALARM[
i]));
536 std::cerr <<
"\tSame-side test failed: " << std::endl;
538 std::cerr <<
"\t\ts(t) = [ ";
539 for (
size_t j = 0;
j <
s.size(); ++
j) {
540 std::cerr <<
s[
j] <<
" ";
542 std::cerr <<
"]" << std::endl;
543 float limitDown = 0.f, limitUp = 0.f;
545 std::cerr <<
"\t\tlim_+ = " << limitUp << std::endl;
552 else if (opt_verbose) {
553 std::cout <<
"\tSame-side test succeeded " << std::endl;
562 std::cout <<
"Downward drift tests" << std::endl;
567 bool isInitOK = initializeShewhartTest(opt_mean, opt_stdev, opt_verbose,
"3-sigma", tester);
572 const float signal = -3.5f * opt_stdev;
577 if ((drift != EXPECTED_DRIFT) || (alarm != EXPECTED_ALARM)) {
580 std::cerr <<
"\t3-sigma test failed: " << std::endl;
582 std::cerr <<
"\t\ts(t) = [ ";
583 for (
size_t j = 0;
j <
s.size(); ++
j) {
584 std::cerr <<
s[
j] <<
" ";
586 std::cerr <<
"]" << std::endl;
587 float limitDown = 0.f, limitUp = 0.f;
589 std::cerr <<
"\t\tlim_- = " << limitDown << std::endl;
590 std::cerr <<
"\t\tlim_+ = " << limitUp << std::endl;
597 else if (opt_verbose) {
598 std::cout <<
"\t3-sigma test succeeded " << std::endl;
605 bool isInitOK = initializeShewhartTest(opt_mean, opt_stdev, opt_verbose,
"2-sigma", tester);
610 const unsigned int NB_SAMPLES = 3;
611 const float DATA[NB_SAMPLES] = { -2.75f * opt_stdev, -1.5f * opt_stdev, -2.5f * opt_stdev };
617 bool isTestOk =
true;
618 while ((i < NB_SAMPLES) && isTestOk) {
621 isTestOk = ((drift == EXPECTED_DRIFT[
i]) && (alarm == EXPECTED_ALARM[
i]));
630 std::cerr <<
"\t2-sigma test failed: " << std::endl;
632 std::cerr <<
"\t\ts(t) = [ ";
633 for (
size_t j = 0;
j <
s.size(); ++
j) {
634 std::cerr <<
s[
j] <<
" ";
636 std::cerr <<
"]" << std::endl;
637 float limitDown = 0.f, limitUp = 0.f;
639 std::cerr <<
"\t\tlim_- = " << limitDown << std::endl;
640 std::cerr <<
"\t\tlim_+ = " << limitUp << std::endl;
647 else if (opt_verbose) {
648 std::cout <<
"\t2-sigma test succeeded " << std::endl;
655 bool isInitOK = initializeShewhartTest(opt_mean, opt_stdev, opt_verbose,
"1-sigma", tester);
660 const unsigned int NB_SAMPLES = 5;
661 const float DATA[NB_SAMPLES] = { -2.75f * opt_stdev, -1.5f * opt_stdev, 1.5f * opt_stdev, -1.5f * opt_stdev, -2.5f * opt_stdev };
667 bool isTestOk =
true;
668 while ((i < NB_SAMPLES) && isTestOk) {
671 isTestOk = ((drift == EXPECTED_DRIFT[
i]) && (alarm == EXPECTED_ALARM[
i]));
680 std::cerr <<
"\t1-sigma test failed: " << std::endl;
682 std::cerr <<
"\t\ts(t) = [ ";
683 for (
size_t j = 0;
j <
s.size(); ++
j) {
684 std::cerr <<
s[
j] <<
" ";
686 std::cerr <<
"]" << std::endl;
687 float limitDown = 0.f, limitUp = 0.f;
689 std::cerr <<
"\t\tlim_- = " << limitDown << std::endl;
690 std::cerr <<
"\t\tlim_+ = " << limitUp << std::endl;
697 else if (opt_verbose) {
698 std::cout <<
"\t1-sigma test succeeded " << std::endl;
705 bool isInitOK = initializeShewhartTest(opt_mean, opt_stdev, opt_verbose,
"Same-side", tester);
710 const unsigned int NB_SAMPLES = 8;
711 const float DATA[NB_SAMPLES] = { -2.75f * opt_stdev, -0.5f * opt_stdev, -1.5f * opt_stdev, -0.5f * opt_stdev, -2.75f * opt_stdev, -0.5f * opt_stdev, -1.5f * opt_stdev, -0.5f * opt_stdev };
717 bool isTestOk =
true;
718 while ((i < NB_SAMPLES) && isTestOk) {
721 isTestOk = ((drift == EXPECTED_DRIFT[
i]) && (alarm == EXPECTED_ALARM[
i]));
730 std::cerr <<
"\tSame-side test failed: " << std::endl;
732 std::cerr <<
"\t\ts(t) = [ ";
733 for (
size_t j = 0;
j <
s.size(); ++
j) {
734 std::cerr <<
s[
j] <<
" ";
736 std::cerr <<
"]" << std::endl;
737 float limitDown = 0.f, limitUp = 0.f;
739 std::cerr <<
"\t\tlim_+ = " << limitUp << std::endl;
740 std::cerr <<
"\t\tlim_- = " << limitDown << std::endl;
747 else if (opt_verbose) {
748 std::cout <<
"\tSame-side test succeeded " << std::endl;
758 std::cout <<
"------ vpStatisticalTestSigma tests ------" << std::endl;
765 const float signal = 3.5f * opt_stdev;
768 if (drift != EXPECTED_DRIFT) {
771 std::cerr <<
"Upward drift test failed: " << std::endl;
772 std::cerr <<
"\ts(t) = " << tester.
getSignal() << std::endl;
773 float limitDown = 0.f, limitUp = 0.f;
775 std::cerr <<
"\tlim_+ = " << limitUp << std::endl;
780 else if (opt_verbose) {
781 std::cout <<
"Upward drift test succeeded " << std::endl;
787 const float signal = -3.5f * opt_stdev;
790 if (drift != EXPECTED_DRIFT) {
793 std::cerr <<
"Downward drift test failed: " << std::endl;
794 std::cerr <<
"\ts(t) = " << tester.
getSignal() << std::endl;
795 float limitDown = 0.f, limitUp = 0.f;
797 std::cerr <<
"\tlim_- = " << limitDown << std::endl;
802 else if (opt_verbose) {
803 std::cout <<
"Downward drift test succeeded " << std::endl;
809 std::cout <<
"Test succeed" << std::endl;
812 std::cout <<
"Test failed" << std::endl;
static std::string vpMeanDriftTypeToString(const vpMeanDriftType &type)
Cast a vpMeanDriftType into a string.
vpMeanDriftType
Enum that indicates if a drift of the mean occurred.
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.
Class that permits to perform Exponentially Weighted Moving Average mean drft tests.
This class implements the Hinkley's cumulative sum test.
Class that permits to perform a mean adjusted Cumulative Sum test.
Class that permits a Shewhart's test.
void init(const bool &activateWECOrules, const std::vector< bool > &activatedRules=CONST_ALL_WECO_ACTIVATED, const unsigned int &nbSamplesForStats=30)
(Re)Initialize the test.
static const unsigned int NB_DATA_SIGNAL
static VP_ATTRIBUTE_NO_DESTROY const std::vector< bool > CONST_ALL_WECO_ACTIVATED
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 -...
virtual float getSignal() const override
Get the last value of the signal.
static std::string vpWecoRulesAlarmToString(const vpWecoRulesAlarm &alarm)
Class that permits a simple test comparing the current value to the standard deviation of the signal.