43 #include <visp3/core/vpStatisticalTestEWMA.h>
44 #include <visp3/core/vpStatisticalTestHinkley.h>
45 #include <visp3/core/vpStatisticalTestMeanAdjustedCUSUM.h>
46 #include <visp3/core/vpStatisticalTestShewhart.h>
47 #include <visp3/core/vpStatisticalTestSigma.h>
49 bool initializeShewhartTest(
const float &mean,
const float &stdev,
const bool &verbose,
const std::string &testName,
vpStatisticalTestShewhart &tester)
51 const bool activateWECOrules =
true;
59 isInitOK = (drift == EXPECTED_DRIFT_INIT);
66 std::cerr <<
"\t" << testName <<
" test initialization failed: " << std::endl;
67 std::cerr <<
"\t\ts(t) = " << tester.
getSignal() << std::endl;
68 float limitDown = 0.f, limitUp = 0.f;
70 std::cerr <<
"\t\tlim_- = " << limitDown << std::endl;
71 std::cerr <<
"\t\tlim_+ = " << limitUp << std::endl;
79 void usage(
const char *name)
81 std::cout <<
"SYNOPSIS " << std::endl;
82 std::cout << name <<
"[--mean <value>] [--stdev <value>] [-v, --verbose] [-h, --help]" << std::endl;
83 std::cout <<
"\nOPTIONS" << std::endl;
84 std::cout <<
" --mean" << std::endl;
85 std::cout <<
" Permits to set the mean of the input signal." << std::endl;
86 std::cout << std::endl;
87 std::cout <<
" --stdev" << std::endl;
88 std::cout <<
" Permits to set the standard deviation of the input signal." << std::endl;
89 std::cout << std::endl;
90 std::cout <<
" -v, --verbose" << std::endl;
91 std::cout <<
" Activate verbose mode." << std::endl;
92 std::cout << std::endl;
93 std::cout <<
" -h, --help" << std::endl;
94 std::cout <<
" Display the help." << std::endl;
95 std::cout << std::endl;
98 bool getOptions(
int argc,
const char **argv,
float &opt_mean,
float &opt_stdev,
bool &opt_verbose)
102 std::string argname(argv[i]);
103 if ((argname ==
"--mean") && ((i + 1) < argc)) {
104 opt_mean =
static_cast<float>(std::atof(argv[i + 1]));
107 else if ((argname ==
"--stdev") && ((i + 1) < argc)) {
108 opt_stdev =
static_cast<float>(std::atof(argv[i + 1]));
111 else if ((argname ==
"-v") || (argname ==
"--verbose")) {
114 else if ((argname ==
"-h") || (argname ==
"--help")) {
118 else if ((argname ==
"-c") || (argname ==
"-d")) {
123 std::cerr <<
"Error: unrecognised argument \"" << argv[i] <<
"\"" << std::endl;
131 int main(
int argc,
const char **argv)
133 float opt_mean = 0.f;
134 float opt_stdev = 1.f;
135 bool opt_verbose =
false;
137 bool isParsingOk = getOptions(argc, argv, opt_mean, opt_stdev, opt_verbose);
147 std::cout <<
"------ vpStatisticalTestEWMA tests ------" << std::endl;
149 const float alpha = 0.1f;
154 tester.
init(alpha, opt_mean, opt_stdev);
159 float signal = (1.f / alpha) * (alpha * opt_mean + 3.f * opt_stdev * std::sqrt(alpha / (2.f - alpha)));
165 std::cerr <<
"Upward drift test failed: " << std::endl;
166 std::cerr <<
"\tw(t) = " << tester.getWt() << std::endl;
167 float limitDown = 0.f, limitUp = 0.f;
169 std::cerr <<
"\tlimit_up = " << limitUp << std::endl;
172 else if (opt_verbose) {
173 std::cout <<
"Upward drift test succeeded." << std::endl;
179 tester.
init(alpha, opt_mean, opt_stdev);
183 float signal = (1.f / alpha) * (alpha * opt_mean - 3.f * opt_stdev * std::sqrt(alpha / (2.f - alpha)));
189 std::cerr <<
"Downward drift test failed: " << std::endl;
190 std::cerr <<
"\tw(t) = " << tester.getWt() << std::endl;
191 float limitDown = 0.f, limitUp = 0.f;
193 std::cerr <<
"\tlimit_down = " << limitDown << std::endl;
196 else if (opt_verbose) {
197 std::cout <<
"Downward drift test succeeded." << std::endl;
205 std::cout <<
"------ vpStatisticalTestHinkley tests ------" << std::endl;
208 const float h = 4.76f, k = 1.f;
210 const unsigned int HINKLEY_NB_DATA = 4;
211 const float HINKLEY_SAMPLE = 2.f * opt_stdev;
215 const float HINKLEY_DATA[HINKLEY_NB_DATA] = { HINKLEY_SAMPLE, HINKLEY_SAMPLE, HINKLEY_SAMPLE, HINKLEY_SAMPLE };
217 bool isTestOk =
true;
220 while ((
id < HINKLEY_NB_DATA) && isTestOk) {
222 isTestOk = (drift == HINKLEY_EXPECTED_RES[id]);
230 std::cerr <<
"Upward drift test failed: " << std::endl;
231 float Tk = tester.getTk(), Nk = tester.getNk();
232 std::cerr <<
"T(k) = " << Tk <<
" | N(k) = " << Nk <<
" => S+(k) = " << Tk - Nk << std::endl;
233 float limitDown = 0.f, limitUp = 0.f;
235 std::cerr <<
"lim_+ = " << limitUp << std::endl;
240 else if (opt_verbose) {
241 std::cout <<
"Upward drift test succeeded." << std::endl;
247 const float HINKLEY_DATA[HINKLEY_NB_DATA] = { -1.f * HINKLEY_SAMPLE, -1.f * HINKLEY_SAMPLE, -1.f * HINKLEY_SAMPLE, -1.f * HINKLEY_SAMPLE };
249 bool isTestOk =
true;
252 while ((
id < HINKLEY_NB_DATA) && isTestOk) {
254 isTestOk = (drift == HINKLEY_EXPECTED_RES[id]);
262 std::cerr <<
"Downward drift test failed: " << std::endl;
263 float Sk = tester.getSk(), Mk = tester.getMk();
264 std::cerr <<
"S(k) = " << Sk <<
" | M(k) = " << Mk <<
" => S+(k) = " << Mk - Sk << std::endl;
265 float limitDown = 0.f, limitUp = 0.f;
267 std::cerr <<
"lim_- = " << limitDown << std::endl;
272 else if (opt_verbose) {
273 std::cout <<
"Downward drift test succeeded." << std::endl;
281 std::cout <<
"------ vpStatisticalTestMeanAdjustedCUSUM tests ------" << std::endl;
284 const float h = 4.76f, k = 1.f;
286 tester.
init(h, k, opt_mean, opt_stdev);
287 const unsigned int CUSUM_NB_DATA = 4;
288 const float CUSUM_SAMPLE = 2.f * opt_stdev;
292 const float CUSUM_DATA[CUSUM_NB_DATA] = { CUSUM_SAMPLE, CUSUM_SAMPLE, CUSUM_SAMPLE, CUSUM_SAMPLE };
294 bool isTestOk =
true;
297 while ((
id < CUSUM_NB_DATA) && isTestOk) {
299 isTestOk = (drift == CUSUM_EXPECTED_RES[id]);
307 std::cerr <<
"Upward drift test failed: " << std::endl;
308 std::cerr <<
"\tS+(k) = " << tester.getTestSignalPlus() << std::endl;
309 float limitDown = 0.f, limitUp = 0.f;
311 std::cerr <<
"\tlim_+ = " << limitUp << std::endl;
316 else if (opt_verbose) {
317 std::cout <<
"Upward drift test succeeded." << std::endl;
323 const float CUSUM_DATA[CUSUM_NB_DATA] = { -1.f * CUSUM_SAMPLE, -1.f * CUSUM_SAMPLE, -1.f * CUSUM_SAMPLE, -1.f * CUSUM_SAMPLE };
325 bool isTestOk =
true;
328 while ((
id < CUSUM_NB_DATA) && isTestOk) {
330 isTestOk = (drift == CUSUM_EXPECTED_RES[id]);
338 std::cerr <<
"Downward drift test failed: " << std::endl;
339 std::cerr <<
"\tS-(k) = " << tester.getTestSignalMinus() << std::endl;
340 float limitDown = 0.f, limitUp = 0.f;
342 std::cerr <<
"\tlim_- = " << limitDown << std::endl;
347 else if (opt_verbose) {
348 std::cout <<
"Downward drift test succeeded." << std::endl;
356 std::cout <<
"------ vpStatisticalTestShewhart tests ------" << std::endl;
358 const bool activateWECOrules =
true;
364 std::cout <<
"Upward drift tests" << std::endl;
369 bool isInitOK = initializeShewhartTest(opt_mean, opt_stdev, opt_verbose,
"3-sigma", tester);
374 const float signal = 3.5f * opt_stdev;
379 if ((drift != EXPECTED_DRIFT) || (alarm != EXPECTED_ALARM)) {
382 std::cerr <<
"\t3-sigma test failed: " << std::endl;
384 std::cerr <<
"\t\ts(t) = [ ";
385 for (
size_t i = 0; i < s.size(); ++i) {
386 std::cerr << s[i] <<
" ";
388 std::cerr <<
"]" << std::endl;
389 float limitDown = 0.f, limitUp = 0.f;
391 std::cerr <<
"\t\tlim_+ = " << limitUp << std::endl;
398 else if (opt_verbose) {
399 std::cout <<
"\t3-sigma test succeeded " << std::endl;
406 bool isInitOK = initializeShewhartTest(opt_mean, opt_stdev, opt_verbose,
"2-sigma", tester);
411 const unsigned int NB_SAMPLES = 3;
412 const float DATA[NB_SAMPLES] = { 2.75f * opt_stdev, 1.5f * opt_stdev, 2.5f * opt_stdev };
418 bool isTestOk =
true;
419 while ((i < NB_SAMPLES) && isTestOk) {
422 isTestOk = ((drift == EXPECTED_DRIFT[i]) && (alarm == EXPECTED_ALARM[i]));
431 std::cerr <<
"\t2-sigma test failed: " << std::endl;
433 std::cerr <<
"\t\ts(t) = [ ";
434 for (
size_t i = 0; i < s.size(); ++i) {
435 std::cerr << s[i] <<
" ";
437 std::cerr <<
"]" << std::endl;
438 float limitDown = 0.f, limitUp = 0.f;
440 std::cerr <<
"\t\tlim_+ = " << limitUp << std::endl;
447 else if (opt_verbose) {
448 std::cout <<
"\t2-sigma test succeeded " << std::endl;
455 bool isInitOK = initializeShewhartTest(opt_mean, opt_stdev, opt_verbose,
"1-sigma", tester);
460 const unsigned int NB_SAMPLES = 5;
461 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 };
467 bool isTestOk =
true;
468 while ((i < NB_SAMPLES) && isTestOk) {
471 isTestOk = ((drift == EXPECTED_DRIFT[i]) && (alarm == EXPECTED_ALARM[i]));
480 std::cerr <<
"\t1-sigma test failed: " << std::endl;
482 std::cerr <<
"\t\ts(t) = [ ";
483 for (
size_t i = 0; i < s.size(); ++i) {
484 std::cerr << s[i] <<
" ";
486 std::cerr <<
"]" << std::endl;
487 float limitDown = 0.f, limitUp = 0.f;
489 std::cerr <<
"\t\tlim_+ = " << limitUp << std::endl;
496 else if (opt_verbose) {
497 std::cout <<
"\t1-sigma test succeeded " << std::endl;
504 bool isInitOK = initializeShewhartTest(opt_mean, opt_stdev, opt_verbose,
"Same-side", tester);
509 const unsigned int NB_SAMPLES = 8;
510 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 };
516 bool isTestOk =
true;
517 while ((i < NB_SAMPLES) && isTestOk) {
520 isTestOk = ((drift == EXPECTED_DRIFT[i]) && (alarm == EXPECTED_ALARM[i]));
529 std::cerr <<
"\tSame-side test failed: " << std::endl;
531 std::cerr <<
"\t\ts(t) = [ ";
532 for (
size_t i = 0; i < s.size(); ++i) {
533 std::cerr << s[i] <<
" ";
535 std::cerr <<
"]" << std::endl;
536 float limitDown = 0.f, limitUp = 0.f;
538 std::cerr <<
"\t\tlim_+ = " << limitUp << std::endl;
545 else if (opt_verbose) {
546 std::cout <<
"\tSame-side test succeeded " << std::endl;
555 std::cout <<
"Downward drift tests" << std::endl;
560 bool isInitOK = initializeShewhartTest(opt_mean, opt_stdev, opt_verbose,
"3-sigma", tester);
565 const float signal = -3.5f * opt_stdev;
570 if ((drift != EXPECTED_DRIFT) || (alarm != EXPECTED_ALARM)) {
573 std::cerr <<
"\t3-sigma test failed: " << std::endl;
575 std::cerr <<
"\t\ts(t) = [ ";
576 for (
size_t i = 0; i < s.size(); ++i) {
577 std::cerr << s[i] <<
" ";
579 std::cerr <<
"]" << std::endl;
580 float limitDown = 0.f, limitUp = 0.f;
582 std::cerr <<
"\t\tlim_- = " << limitDown << std::endl;
583 std::cerr <<
"\t\tlim_+ = " << limitUp << std::endl;
590 else if (opt_verbose) {
591 std::cout <<
"\t3-sigma test succeeded " << std::endl;
598 bool isInitOK = initializeShewhartTest(opt_mean, opt_stdev, opt_verbose,
"2-sigma", tester);
603 const unsigned int NB_SAMPLES = 3;
604 const float DATA[NB_SAMPLES] = { -2.75f * opt_stdev, -1.5f * opt_stdev, -2.5f * opt_stdev };
610 bool isTestOk =
true;
611 while ((i < NB_SAMPLES) && isTestOk) {
614 isTestOk = ((drift == EXPECTED_DRIFT[i]) && (alarm == EXPECTED_ALARM[i]));
623 std::cerr <<
"\t2-sigma test failed: " << std::endl;
625 std::cerr <<
"\t\ts(t) = [ ";
626 for (
size_t i = 0; i < s.size(); ++i) {
627 std::cerr << s[i] <<
" ";
629 std::cerr <<
"]" << std::endl;
630 float limitDown = 0.f, limitUp = 0.f;
632 std::cerr <<
"\t\tlim_- = " << limitDown << std::endl;
633 std::cerr <<
"\t\tlim_+ = " << limitUp << std::endl;
640 else if (opt_verbose) {
641 std::cout <<
"\t2-sigma test succeeded " << std::endl;
648 bool isInitOK = initializeShewhartTest(opt_mean, opt_stdev, opt_verbose,
"1-sigma", tester);
653 const unsigned int NB_SAMPLES = 5;
654 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 };
660 bool isTestOk =
true;
661 while ((i < NB_SAMPLES) && isTestOk) {
664 isTestOk = ((drift == EXPECTED_DRIFT[i]) && (alarm == EXPECTED_ALARM[i]));
673 std::cerr <<
"\t1-sigma test failed: " << std::endl;
675 std::cerr <<
"\t\ts(t) = [ ";
676 for (
size_t i = 0; i < s.size(); ++i) {
677 std::cerr << s[i] <<
" ";
679 std::cerr <<
"]" << std::endl;
680 float limitDown = 0.f, limitUp = 0.f;
682 std::cerr <<
"\t\tlim_- = " << limitDown << std::endl;
683 std::cerr <<
"\t\tlim_+ = " << limitUp << std::endl;
690 else if (opt_verbose) {
691 std::cout <<
"\t1-sigma test succeeded " << std::endl;
698 bool isInitOK = initializeShewhartTest(opt_mean, opt_stdev, opt_verbose,
"Same-side", tester);
703 const unsigned int NB_SAMPLES = 8;
704 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 };
710 bool isTestOk =
true;
711 while ((i < NB_SAMPLES) && isTestOk) {
714 isTestOk = ((drift == EXPECTED_DRIFT[i]) && (alarm == EXPECTED_ALARM[i]));
723 std::cerr <<
"\tSame-side test failed: " << std::endl;
725 std::cerr <<
"\t\ts(t) = [ ";
726 for (
size_t i = 0; i < s.size(); ++i) {
727 std::cerr << s[i] <<
" ";
729 std::cerr <<
"]" << std::endl;
730 float limitDown = 0.f, limitUp = 0.f;
732 std::cerr <<
"\t\tlim_+ = " << limitUp << std::endl;
733 std::cerr <<
"\t\tlim_- = " << limitDown << std::endl;
740 else if (opt_verbose) {
741 std::cout <<
"\tSame-side test succeeded " << std::endl;
751 std::cout <<
"------ vpStatisticalTestSigma tests ------" << std::endl;
758 const float signal = 3.5f * opt_stdev;
761 if (drift != EXPECTED_DRIFT) {
764 std::cerr <<
"Upward drift test failed: " << std::endl;
765 std::cerr <<
"\ts(t) = " << tester.
getSignal() << std::endl;
766 float limitDown = 0.f, limitUp = 0.f;
768 std::cerr <<
"\tlim_+ = " << limitUp << std::endl;
773 else if (opt_verbose) {
774 std::cout <<
"Upward drift test succeeded " << std::endl;
780 const float signal = -3.5f * opt_stdev;
783 if (drift != EXPECTED_DRIFT) {
786 std::cerr <<
"Downward drift test failed: " << std::endl;
787 std::cerr <<
"\ts(t) = " << tester.
getSignal() << std::endl;
788 float limitDown = 0.f, limitUp = 0.f;
790 std::cerr <<
"\tlim_- = " << limitDown << std::endl;
795 else if (opt_verbose) {
796 std::cout <<
"Downward drift test succeeded " << std::endl;
802 std::cout <<
"Test succeed" << std::endl;
805 std::cout <<
"Test failed" << std::endl;
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.
static std::string vpMeanDriftTypeToString(const vpMeanDriftType &type)
Cast a vpMeanDriftType into a string.
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.
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 const int NB_DATA_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.