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
52 bool initializeShewhartTest(
const float &mean,
const float &stdev,
const bool &verbose,
const std::string &testName,
vpStatisticalTestShewhart &tester)
54 const bool activateWECOrules =
true;
62 isInitOK = (drift == EXPECTED_DRIFT_INIT);
69 std::cerr <<
"\t" << testName <<
" test initialization failed: " << std::endl;
70 std::cerr <<
"\t\ts(t) = " << tester.
getSignal() << std::endl;
71 float limitDown = 0.f, limitUp = 0.f;
73 std::cerr <<
"\t\tlim_- = " << limitDown << std::endl;
74 std::cerr <<
"\t\tlim_+ = " << limitUp << std::endl;
82 void usage(
const char *name)
84 std::cout <<
"SYNOPSIS " << std::endl;
85 std::cout << name <<
"[--mean <value>] [--stdev <value>] [-v, --verbose] [-h, --help]" << std::endl;
86 std::cout <<
"\nOPTIONS" << std::endl;
87 std::cout <<
" --mean" << std::endl;
88 std::cout <<
" Permits to set the mean of the input signal." << std::endl;
89 std::cout << std::endl;
90 std::cout <<
" --stdev" << std::endl;
91 std::cout <<
" Permits to set the standard deviation of the input signal." << std::endl;
92 std::cout << std::endl;
93 std::cout <<
" -v, --verbose" << std::endl;
94 std::cout <<
" Activate verbose mode." << std::endl;
95 std::cout << std::endl;
96 std::cout <<
" -h, --help" << std::endl;
97 std::cout <<
" Display the help." << std::endl;
98 std::cout << std::endl;
101 bool getOptions(
int argc,
const char **argv,
float &opt_mean,
float &opt_stdev,
bool &opt_verbose)
105 std::string argname(argv[i]);
106 if ((argname ==
"--mean") && ((i + 1) < argc)) {
107 opt_mean =
static_cast<float>(std::atof(argv[i + 1]));
110 else if ((argname ==
"--stdev") && ((i + 1) < argc)) {
111 opt_stdev =
static_cast<float>(std::atof(argv[i + 1]));
114 else if ((argname ==
"-v") || (argname ==
"--verbose")) {
117 else if ((argname ==
"-h") || (argname ==
"--help")) {
121 else if ((argname ==
"-c") || (argname ==
"-d")) {
126 std::cerr <<
"Error: unrecognised argument \"" << argv[i] <<
"\"" << std::endl;
134 int main(
int argc,
const char **argv)
136 float opt_mean = 0.f;
137 float opt_stdev = 1.f;
138 bool opt_verbose =
false;
140 bool isParsingOk = getOptions(argc, argv, opt_mean, opt_stdev, opt_verbose);
150 std::cout <<
"------ vpStatisticalTestEWMA tests ------" << std::endl;
152 const float alpha = 0.1f;
157 tester.
init(alpha, opt_mean, opt_stdev);
162 float signal = (1.f / alpha) * (alpha * opt_mean + 3.f * opt_stdev * std::sqrt(alpha / (2.f - alpha)));
168 std::cerr <<
"Upward drift test failed: " << std::endl;
169 std::cerr <<
"\tw(t) = " << tester.getWt() << std::endl;
170 float limitDown = 0.f, limitUp = 0.f;
172 std::cerr <<
"\tlimit_up = " << limitUp << std::endl;
175 else if (opt_verbose) {
176 std::cout <<
"Upward drift test succeeded." << std::endl;
182 tester.
init(alpha, opt_mean, opt_stdev);
186 float signal = (1.f / alpha) * (alpha * opt_mean - 3.f * opt_stdev * std::sqrt(alpha / (2.f - alpha)));
192 std::cerr <<
"Downward drift test failed: " << std::endl;
193 std::cerr <<
"\tw(t) = " << tester.getWt() << std::endl;
194 float limitDown = 0.f, limitUp = 0.f;
196 std::cerr <<
"\tlimit_down = " << limitDown << std::endl;
199 else if (opt_verbose) {
200 std::cout <<
"Downward drift test succeeded." << std::endl;
208 std::cout <<
"------ vpStatisticalTestHinkley tests ------" << std::endl;
211 const float h = 4.76f, k = 1.f;
213 const unsigned int HINKLEY_NB_DATA = 4;
214 const float HINKLEY_SAMPLE = 2.f * opt_stdev;
218 const float HINKLEY_DATA[HINKLEY_NB_DATA] = { HINKLEY_SAMPLE, HINKLEY_SAMPLE, HINKLEY_SAMPLE, HINKLEY_SAMPLE };
220 bool isTestOk =
true;
223 while ((
id < HINKLEY_NB_DATA) && isTestOk) {
225 isTestOk = (drift == HINKLEY_EXPECTED_RES[id]);
233 std::cerr <<
"Upward drift test failed: " << std::endl;
234 float Tk = tester.getTk(), Nk = tester.getNk();
235 std::cerr <<
"T(k) = " << Tk <<
" | N(k) = " << Nk <<
" => S+(k) = " << Tk - Nk << std::endl;
236 float limitDown = 0.f, limitUp = 0.f;
238 std::cerr <<
"lim_+ = " << limitUp << std::endl;
243 else if (opt_verbose) {
244 std::cout <<
"Upward drift test succeeded." << std::endl;
250 const float HINKLEY_DATA[HINKLEY_NB_DATA] = { -1.f * HINKLEY_SAMPLE, -1.f * HINKLEY_SAMPLE, -1.f * HINKLEY_SAMPLE, -1.f * HINKLEY_SAMPLE };
252 bool isTestOk =
true;
255 while ((
id < HINKLEY_NB_DATA) && isTestOk) {
257 isTestOk = (drift == HINKLEY_EXPECTED_RES[id]);
265 std::cerr <<
"Downward drift test failed: " << std::endl;
266 float Sk = tester.getSk(), Mk = tester.getMk();
267 std::cerr <<
"S(k) = " << Sk <<
" | M(k) = " << Mk <<
" => S+(k) = " << Mk - Sk << std::endl;
268 float limitDown = 0.f, limitUp = 0.f;
270 std::cerr <<
"lim_- = " << limitDown << std::endl;
275 else if (opt_verbose) {
276 std::cout <<
"Downward drift test succeeded." << std::endl;
284 std::cout <<
"------ vpStatisticalTestMeanAdjustedCUSUM tests ------" << std::endl;
287 const float h = 4.76f, k = 1.f;
289 tester.
init(h, k, opt_mean, opt_stdev);
290 const unsigned int CUSUM_NB_DATA = 4;
291 const float CUSUM_SAMPLE = 2.f * opt_stdev;
295 const float CUSUM_DATA[CUSUM_NB_DATA] = { CUSUM_SAMPLE, CUSUM_SAMPLE, CUSUM_SAMPLE, CUSUM_SAMPLE };
297 bool isTestOk =
true;
300 while ((
id < CUSUM_NB_DATA) && isTestOk) {
302 isTestOk = (drift == CUSUM_EXPECTED_RES[id]);
310 std::cerr <<
"Upward drift test failed: " << std::endl;
311 std::cerr <<
"\tS+(k) = " << tester.getTestSignalPlus() << std::endl;
312 float limitDown = 0.f, limitUp = 0.f;
314 std::cerr <<
"\tlim_+ = " << limitUp << std::endl;
319 else if (opt_verbose) {
320 std::cout <<
"Upward drift test succeeded." << std::endl;
326 const float CUSUM_DATA[CUSUM_NB_DATA] = { -1.f * CUSUM_SAMPLE, -1.f * CUSUM_SAMPLE, -1.f * CUSUM_SAMPLE, -1.f * CUSUM_SAMPLE };
328 bool isTestOk =
true;
331 while ((
id < CUSUM_NB_DATA) && isTestOk) {
333 isTestOk = (drift == CUSUM_EXPECTED_RES[id]);
341 std::cerr <<
"Downward drift test failed: " << std::endl;
342 std::cerr <<
"\tS-(k) = " << tester.getTestSignalMinus() << std::endl;
343 float limitDown = 0.f, limitUp = 0.f;
345 std::cerr <<
"\tlim_- = " << limitDown << std::endl;
350 else if (opt_verbose) {
351 std::cout <<
"Downward drift test succeeded." << std::endl;
359 std::cout <<
"------ vpStatisticalTestShewhart tests ------" << std::endl;
361 const bool activateWECOrules =
true;
367 std::cout <<
"Upward drift tests" << std::endl;
372 bool isInitOK = initializeShewhartTest(opt_mean, opt_stdev, opt_verbose,
"3-sigma", tester);
377 const float signal = 3.5f * opt_stdev;
382 if ((drift != EXPECTED_DRIFT) || (alarm != EXPECTED_ALARM)) {
385 std::cerr <<
"\t3-sigma test failed: " << std::endl;
387 std::cerr <<
"\t\ts(t) = [ ";
388 for (
size_t i = 0; i < s.size(); ++i) {
389 std::cerr << s[i] <<
" ";
391 std::cerr <<
"]" << std::endl;
392 float limitDown = 0.f, limitUp = 0.f;
394 std::cerr <<
"\t\tlim_+ = " << limitUp << std::endl;
401 else if (opt_verbose) {
402 std::cout <<
"\t3-sigma test succeeded " << std::endl;
409 bool isInitOK = initializeShewhartTest(opt_mean, opt_stdev, opt_verbose,
"2-sigma", tester);
414 const unsigned int NB_SAMPLES = 3;
415 const float DATA[NB_SAMPLES] = { 2.75f * opt_stdev, 1.5f * opt_stdev, 2.5f * opt_stdev };
421 bool isTestOk =
true;
422 while ((i < NB_SAMPLES) && isTestOk) {
425 isTestOk = ((drift == EXPECTED_DRIFT[i]) && (alarm == EXPECTED_ALARM[i]));
434 std::cerr <<
"\t2-sigma test failed: " << std::endl;
436 std::cerr <<
"\t\ts(t) = [ ";
437 for (
size_t j = 0; j < s.size(); ++j) {
438 std::cerr << s[j] <<
" ";
440 std::cerr <<
"]" << std::endl;
441 float limitDown = 0.f, limitUp = 0.f;
443 std::cerr <<
"\t\tlim_+ = " << limitUp << std::endl;
450 else if (opt_verbose) {
451 std::cout <<
"\t2-sigma test succeeded " << std::endl;
458 bool isInitOK = initializeShewhartTest(opt_mean, opt_stdev, opt_verbose,
"1-sigma", tester);
463 const unsigned int NB_SAMPLES = 5;
464 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 };
470 bool isTestOk =
true;
471 while ((i < NB_SAMPLES) && isTestOk) {
474 isTestOk = ((drift == EXPECTED_DRIFT[i]) && (alarm == EXPECTED_ALARM[i]));
483 std::cerr <<
"\t1-sigma test failed: " << std::endl;
485 std::cerr <<
"\t\ts(t) = [ ";
486 for (
size_t j = 0; j < s.size(); ++j) {
487 std::cerr << s[j] <<
" ";
489 std::cerr <<
"]" << std::endl;
490 float limitDown = 0.f, limitUp = 0.f;
492 std::cerr <<
"\t\tlim_+ = " << limitUp << std::endl;
499 else if (opt_verbose) {
500 std::cout <<
"\t1-sigma test succeeded " << std::endl;
507 bool isInitOK = initializeShewhartTest(opt_mean, opt_stdev, opt_verbose,
"Same-side", tester);
512 const unsigned int NB_SAMPLES = 8;
513 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 };
519 bool isTestOk =
true;
520 while ((i < NB_SAMPLES) && isTestOk) {
523 isTestOk = ((drift == EXPECTED_DRIFT[i]) && (alarm == EXPECTED_ALARM[i]));
532 std::cerr <<
"\tSame-side test failed: " << std::endl;
534 std::cerr <<
"\t\ts(t) = [ ";
535 for (
size_t j = 0; j < s.size(); ++j) {
536 std::cerr << s[j] <<
" ";
538 std::cerr <<
"]" << std::endl;
539 float limitDown = 0.f, limitUp = 0.f;
541 std::cerr <<
"\t\tlim_+ = " << limitUp << std::endl;
548 else if (opt_verbose) {
549 std::cout <<
"\tSame-side test succeeded " << std::endl;
558 std::cout <<
"Downward drift tests" << std::endl;
563 bool isInitOK = initializeShewhartTest(opt_mean, opt_stdev, opt_verbose,
"3-sigma", tester);
568 const float signal = -3.5f * opt_stdev;
573 if ((drift != EXPECTED_DRIFT) || (alarm != EXPECTED_ALARM)) {
576 std::cerr <<
"\t3-sigma test failed: " << std::endl;
578 std::cerr <<
"\t\ts(t) = [ ";
579 for (
size_t j = 0; j < s.size(); ++j) {
580 std::cerr << s[j] <<
" ";
582 std::cerr <<
"]" << std::endl;
583 float limitDown = 0.f, limitUp = 0.f;
585 std::cerr <<
"\t\tlim_- = " << limitDown << std::endl;
586 std::cerr <<
"\t\tlim_+ = " << limitUp << std::endl;
593 else if (opt_verbose) {
594 std::cout <<
"\t3-sigma test succeeded " << std::endl;
601 bool isInitOK = initializeShewhartTest(opt_mean, opt_stdev, opt_verbose,
"2-sigma", tester);
606 const unsigned int NB_SAMPLES = 3;
607 const float DATA[NB_SAMPLES] = { -2.75f * opt_stdev, -1.5f * opt_stdev, -2.5f * opt_stdev };
613 bool isTestOk =
true;
614 while ((i < NB_SAMPLES) && isTestOk) {
617 isTestOk = ((drift == EXPECTED_DRIFT[i]) && (alarm == EXPECTED_ALARM[i]));
626 std::cerr <<
"\t2-sigma test failed: " << std::endl;
628 std::cerr <<
"\t\ts(t) = [ ";
629 for (
size_t j = 0; j < s.size(); ++j) {
630 std::cerr << s[j] <<
" ";
632 std::cerr <<
"]" << std::endl;
633 float limitDown = 0.f, limitUp = 0.f;
635 std::cerr <<
"\t\tlim_- = " << limitDown << std::endl;
636 std::cerr <<
"\t\tlim_+ = " << limitUp << std::endl;
643 else if (opt_verbose) {
644 std::cout <<
"\t2-sigma test succeeded " << std::endl;
651 bool isInitOK = initializeShewhartTest(opt_mean, opt_stdev, opt_verbose,
"1-sigma", tester);
656 const unsigned int NB_SAMPLES = 5;
657 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 };
663 bool isTestOk =
true;
664 while ((i < NB_SAMPLES) && isTestOk) {
667 isTestOk = ((drift == EXPECTED_DRIFT[i]) && (alarm == EXPECTED_ALARM[i]));
676 std::cerr <<
"\t1-sigma test failed: " << std::endl;
678 std::cerr <<
"\t\ts(t) = [ ";
679 for (
size_t j = 0; j < s.size(); ++j) {
680 std::cerr << s[j] <<
" ";
682 std::cerr <<
"]" << std::endl;
683 float limitDown = 0.f, limitUp = 0.f;
685 std::cerr <<
"\t\tlim_- = " << limitDown << std::endl;
686 std::cerr <<
"\t\tlim_+ = " << limitUp << std::endl;
693 else if (opt_verbose) {
694 std::cout <<
"\t1-sigma test succeeded " << std::endl;
701 bool isInitOK = initializeShewhartTest(opt_mean, opt_stdev, opt_verbose,
"Same-side", tester);
706 const unsigned int NB_SAMPLES = 8;
707 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 };
713 bool isTestOk =
true;
714 while ((i < NB_SAMPLES) && isTestOk) {
717 isTestOk = ((drift == EXPECTED_DRIFT[i]) && (alarm == EXPECTED_ALARM[i]));
726 std::cerr <<
"\tSame-side test failed: " << std::endl;
728 std::cerr <<
"\t\ts(t) = [ ";
729 for (
size_t j = 0; j < s.size(); ++j) {
730 std::cerr << s[j] <<
" ";
732 std::cerr <<
"]" << std::endl;
733 float limitDown = 0.f, limitUp = 0.f;
735 std::cerr <<
"\t\tlim_+ = " << limitUp << std::endl;
736 std::cerr <<
"\t\tlim_- = " << limitDown << std::endl;
743 else if (opt_verbose) {
744 std::cout <<
"\tSame-side test succeeded " << std::endl;
754 std::cout <<
"------ vpStatisticalTestSigma tests ------" << std::endl;
761 const float signal = 3.5f * opt_stdev;
764 if (drift != EXPECTED_DRIFT) {
767 std::cerr <<
"Upward drift test failed: " << std::endl;
768 std::cerr <<
"\ts(t) = " << tester.
getSignal() << std::endl;
769 float limitDown = 0.f, limitUp = 0.f;
771 std::cerr <<
"\tlim_+ = " << limitUp << std::endl;
776 else if (opt_verbose) {
777 std::cout <<
"Upward drift test succeeded " << std::endl;
783 const float signal = -3.5f * opt_stdev;
786 if (drift != EXPECTED_DRIFT) {
789 std::cerr <<
"Downward drift test failed: " << std::endl;
790 std::cerr <<
"\ts(t) = " << tester.
getSignal() << std::endl;
791 float limitDown = 0.f, limitUp = 0.f;
793 std::cerr <<
"\tlim_- = " << limitDown << std::endl;
798 else if (opt_verbose) {
799 std::cout <<
"Downward drift test succeeded " << std::endl;
805 std::cout <<
"Test succeed" << std::endl;
808 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.
static const unsigned int NB_DATA_SIGNAL
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 -...
void init(const bool &activateWECOrules, const bool activatedRules[COUNT_WECO - 1]=CONST_ALL_WECO_ACTIVATED, const unsigned int &nbSamplesForStats=30)
(Re)Initialize the test.
virtual float getSignal() const override
Get the last value of the 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.