Visual Servoing Platform  version 3.6.1 under development (2024-11-15)
tutorial-meandrift.cpp
1 /*
2  * ViSP, open source Visual Servoing Platform software.
3  * Copyright (C) 2005 - 2024 by Inria. All rights reserved.
4  *
5  * This software is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  * See the file LICENSE.txt at the root directory of this source
10  * distribution for additional information about the GNU GPL.
11  *
12  * For using ViSP with software that can not be combined with the GNU
13  * GPL, please contact Inria about acquiring a ViSP Professional
14  * Edition License.
15  *
16  * See https://visp.inria.fr for more information.
17  *
18  * This software was developed at:
19  * Inria Rennes - Bretagne Atlantique
20  * Campus Universitaire de Beaulieu
21  * 35042 Rennes Cedex
22  * France
23  *
24  * If you have questions regarding the use of this file, please contact
25  * Inria at visp@inria.fr
26  *
27  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
28  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29  */
30 
32 
33 #include <cstring> //std::memcpy
34 
35 #include <visp3/core/vpConfig.h>
36 #include <visp3/core/vpGaussRand.h>
37 #include <visp3/core/vpStatisticalTestEWMA.h>
38 #include <visp3/core/vpStatisticalTestHinkley.h>
39 #include <visp3/core/vpStatisticalTestMeanAdjustedCUSUM.h>
40 #include <visp3/core/vpStatisticalTestShewhart.h>
41 #include <visp3/core/vpStatisticalTestSigma.h>
42 #include <visp3/gui/vpPlot.h>
43 
44 #ifdef ENABLE_VISP_NAMESPACE
45 using namespace VISP_NAMESPACE_NAME;
46 #endif
47 
48 #if defined(VISP_HAVE_DISPLAY)
49 namespace TutorialMeanDrift
50 {
52 
56 typedef enum TypeTest
57 {
58  HINLKEY_TYPE_TEST = 0,
59  EWMA_TYPE_TEST = 1,
60  MEAN_ADJUSTED_CUSUM_TYPE_TEST = 2,
61  SHEWHART_TYPE_TEST = 3,
62  SIGMA_TYPE_TEST = 4,
63  COUNT_TYPE_TEST = 5,
64  UNKOWN_TYPE_TEST = COUNT_TYPE_TEST
65 }TypeTest;
67 
74 std::string typeTestToString(const TypeTest &type)
75 {
76  std::string result;
77  switch (type) {
78  case HINLKEY_TYPE_TEST:
79  result = "hinkley";
80  break;
81  case EWMA_TYPE_TEST:
82  result = "ewma";
83  break;
84  case MEAN_ADJUSTED_CUSUM_TYPE_TEST:
85  result = "cusum";
86  break;
87  case SHEWHART_TYPE_TEST:
88  result = "shewhart";
89  break;
90  case SIGMA_TYPE_TEST:
91  result = "sigma";
92  break;
93  case UNKOWN_TYPE_TEST:
94  default:
95  result = "unknown-type-test";
96  break;
97  }
98  return result;
99 }
100 
108 TypeTest typeTestFromString(const std::string &name)
109 {
110  TypeTest result = UNKOWN_TYPE_TEST;
111  unsigned int count = static_cast<unsigned int>(COUNT_TYPE_TEST);
112  unsigned int id = 0;
113  bool hasNotFound = true;
114  while ((id < count) && hasNotFound) {
115  TypeTest temp = static_cast<TypeTest>(id);
116  if (typeTestToString(temp) == name) {
117  result = temp;
118  hasNotFound = false;
119  }
120  ++id;
121  }
122  return result;
123 }
124 
133 std::string getAvailableTypeTest(const std::string &prefix = "<", const std::string &sep = " , ",
134  const std::string &suffix = ">")
135 {
136  std::string msg(prefix);
137  unsigned int count = static_cast<unsigned int>(COUNT_TYPE_TEST);
138  unsigned int lastId = count - 1;
139  for (unsigned int i = 0; i < lastId; i++) {
140  msg += typeTestToString(static_cast<TypeTest>(i)) + sep;
141  }
142  msg += typeTestToString(static_cast<TypeTest>(lastId)) + suffix;
143  return msg;
144 }
145 
153 template <typename T>
154 std::string numberToString(const T &number)
155 {
156  std::stringstream ss;
157  ss << number;
158  return ss.str();
159 }
160 
167 std::string boolToString(const bool &boolean)
168 {
169  if (boolean) {
170  return "true";
171  }
172  else {
173  return "false";
174  }
175 }
176 
186 std::string wecoRulesToString(const bool rules[vpStatisticalTestShewhart::COUNT_WECO - 1], const std::string &prefix = "[", const std::string &suffix = "]", const std::string &sep = " , ")
187 {
188  std::string rulesAsString = prefix;
189  for (unsigned int i = 0; i < vpStatisticalTestShewhart::COUNT_WECO - 2; ++i) {
190  if (rules[i]) {
191  rulesAsString += "ON";
192  }
193  else {
194  rulesAsString += "OFF";
195  }
196  rulesAsString += sep;
197  }
198  if (rules[vpStatisticalTestShewhart::COUNT_WECO - 2]) {
199  rulesAsString += "ON";
200  }
201  else {
202  rulesAsString += "OFF";
203  }
204  rulesAsString += suffix;
205  return rulesAsString;
206 }
207 
211 const bool CONST_ALL_ALARM_OFF[vpStatisticalTestAbstract::MEAN_DRIFT_COUNT] = { false, false, false, false };
212 
216 const bool CONST_ALL_ALARM_ON[vpStatisticalTestAbstract::MEAN_DRIFT_COUNT] = { true, true, true, true };
217 
225 void vectorOfStringToMeanDriftTypeArray(const std::vector<std::string> &names, bool array[vpStatisticalTestAbstract::MEAN_DRIFT_COUNT])
226 {
227  std::memcpy(array, CONST_ALL_ALARM_OFF, vpStatisticalTestAbstract::MEAN_DRIFT_COUNT * sizeof(bool));
228  size_t nbNames = names.size();
229  for (size_t i = 0; i < nbNames; ++i) {
231  std::cout << "alarm[" << names[i] << "] (i.e. " << static_cast<unsigned int>(alarmToActivate) << ") set to true" << std::endl;
232  array[static_cast<unsigned int>(alarmToActivate)] = true;
233  if (alarmToActivate == vpStatisticalTestAbstract::MEAN_DRIFT_BOTH) {
236  }
237  }
240  }
241 }
242 
250 std::vector<std::string> meanDriftArrayToVectorOfString(const bool array[vpStatisticalTestAbstract::MEAN_DRIFT_COUNT])
251 {
252  std::vector<std::string> listActivatedAlarms;
253  unsigned int nbTypeTests = static_cast<unsigned int>(vpStatisticalTestAbstract::MEAN_DRIFT_COUNT);
254  for (unsigned int id = 0; id < nbTypeTests; ++id) {
255  if (array[id]) {
257  std::string testName = vpStatisticalTestAbstract::vpMeanDriftTypeToString(test);
258  listActivatedAlarms.push_back(testName);
259  }
260  }
261  return listActivatedAlarms;
262 }
263 
274 std::string meanDriftArrayToString(const bool array[vpStatisticalTestAbstract::MEAN_DRIFT_COUNT],
275  const std::string &prefix = "[", const std::string &sep = " , ",
276  const std::string &suffix = "]")
277 {
278  std::vector<std::string> listActivatedAlarms = meanDriftArrayToVectorOfString(array);
279  std::string result = prefix;
280  size_t nbTestActivated = listActivatedAlarms.size();
281  if (nbTestActivated == 0) {
282  return prefix + " " + suffix;
283  }
284  for (size_t i = 0; i < nbTestActivated - 1; ++i) {
285  result += listActivatedAlarms[i] + sep;
286  }
287  result += listActivatedAlarms[nbTestActivated - 1] + suffix;
288  return result;
289 }
290 
297 unsigned int meanDriftArrayToNbActivated(const bool array[vpStatisticalTestAbstract::MEAN_DRIFT_COUNT])
298 {
299  unsigned int nbActivated = 0;
300  unsigned int nbTypeAlarms = static_cast<unsigned int>(vpStatisticalTestAbstract::MEAN_DRIFT_COUNT);
301  for (unsigned int id = 0; id < nbTypeAlarms; ++id) {
302  if (array[id]) {
303  ++nbActivated;
304  }
305  }
306  return nbActivated;
307 }
308 
309 #ifndef DOXYGEN_SHOULD_SKIP_THIS
311 
314 typedef struct ParametersForAlgo
315 {
316  unsigned int m_test_nbsamples;
317  bool m_test_activatedalarms[vpStatisticalTestAbstract::MEAN_DRIFT_COUNT];
318  unsigned int m_test_nbactivatedalarms;
319  float m_cusum_h;
320  float m_cusum_k;
321  float m_ewma_alpha;
322  float m_hinkley_alpha;
323  float m_hinkley_delta;
324  bool m_hinkley_computealphadelta;
325  float m_hinkley_h;
326  float m_hinkley_k;
327  bool m_shewhart_useWECO;
328  bool m_shewhart_rules[vpStatisticalTestShewhart::COUNT_WECO - 1];
329  float m_sigma_h;
331  ParametersForAlgo()
332  : m_test_nbsamples(30)
333  , m_cusum_h(4.76f)
334  , m_cusum_k(1.f)
335  , m_ewma_alpha(0.1f)
336  , m_hinkley_alpha(4.76f)
337  , m_hinkley_delta(1.f)
338  , m_hinkley_computealphadelta(false)
339  , m_hinkley_h(4.76f)
340  , m_hinkley_k(1.f)
341  , m_shewhart_useWECO(false)
342  , m_sigma_h(3.f)
343  {
344  std::memcpy(m_shewhart_rules, vpStatisticalTestShewhart::CONST_ALL_WECO_ACTIVATED, (vpStatisticalTestShewhart::COUNT_WECO - 1) * sizeof(bool));
345  memcpy(m_test_activatedalarms, CONST_ALL_ALARM_ON, vpStatisticalTestAbstract::MEAN_DRIFT_COUNT * sizeof(bool));
346  m_test_activatedalarms[vpStatisticalTestAbstract::MEAN_DRIFT_NONE] = false;
347  m_test_nbactivatedalarms = meanDriftArrayToNbActivated(m_test_activatedalarms);
348  }
349 }ParametersForAlgo;
351 }
352 #endif // DOXYGEN_SHOULD_SKIP_THIS
353 
354 int testOnSynthetic(const TutorialMeanDrift::TypeTest &type, const TutorialMeanDrift::ParametersForAlgo parameters,
355  const float &mean, const float &mean_drift, const float &stdev)
356 {
357  const float dt = 10.f; // Emulate a 10ms period
358 
360  vpPlot plotter(1);
361  plotter.initGraph(0, 1);
362  plotter.setTitle(0, "Evolution of the signal");
363  plotter.setUnitX(0, "Frame ID");
364  plotter.setUnitY(0, "No units");
366 
368  unsigned int idFrame = 0;
369  vpStatisticalTestAbstract *p_test = nullptr;
370  switch (type) {
371  case TutorialMeanDrift::EWMA_TYPE_TEST:
372  p_test = new vpStatisticalTestEWMA(parameters.m_ewma_alpha);
373  break;
374  case TutorialMeanDrift::HINLKEY_TYPE_TEST:
375  p_test = new vpStatisticalTestHinkley(parameters.m_hinkley_alpha, parameters.m_hinkley_delta, parameters.m_test_nbsamples);
376  break;
377  case TutorialMeanDrift::MEAN_ADJUSTED_CUSUM_TYPE_TEST:
378  p_test = new vpStatisticalTestMeanAdjustedCUSUM(parameters.m_cusum_h, parameters.m_cusum_k, parameters.m_test_nbsamples);
379  break;
380  case TutorialMeanDrift::SHEWHART_TYPE_TEST:
381  p_test = new vpStatisticalTestShewhart(parameters.m_shewhart_useWECO, parameters.m_shewhart_rules, parameters.m_test_nbsamples);
382  break;
383  case TutorialMeanDrift::SIGMA_TYPE_TEST:
384  p_test = new vpStatisticalTestSigma(parameters.m_sigma_h, parameters.m_test_nbsamples);
385  break;
386  default:
387  throw(vpException(vpException::badValue, TutorialMeanDrift::typeTestToString(type) + " is not handled."));
388  break;
389  }
390 
391  if ((type == TutorialMeanDrift::HINLKEY_TYPE_TEST) && parameters.m_hinkley_computealphadelta) {
392  // Initialization of Hinkley's test in automatic mode
393  delete p_test;
394  p_test = new vpStatisticalTestHinkley(parameters.m_hinkley_h, parameters.m_hinkley_k, true, parameters.m_test_nbsamples);
395  }
397 
398  float signal;
399 
401  // Initial computation of the mean and stdev of the input signal
402  for (unsigned int i = 0; i < parameters.m_test_nbsamples; ++i) {
403  vpGaussRand rndGen(stdev, mean, static_cast<long>(idFrame * dt));
404  signal = static_cast<float>(rndGen());
405  p_test->testDownUpwardMeanDrift(signal);
406  ++idFrame;
407  }
409 
410  std::cout << "Estimated mean of the input signal: " << p_test->getMean() << std::endl;
411  std::cout << "Estimated stdev of the input signal: " << p_test->getStdev() << std::endl;
412 
414  float mean_eff = mean;
415  bool hasToRun = true;
417  while (hasToRun) {
418  vpGaussRand rndGen(stdev, mean_eff, static_cast<long>(idFrame * dt));
419  signal = static_cast<float>(rndGen());
420  plotter.plot(0, 0, idFrame - parameters.m_test_nbsamples, signal);
421  drift_type = p_test->testDownUpwardMeanDrift(signal);
422  if ((drift_type != vpStatisticalTestAbstract::MEAN_DRIFT_NONE) && (parameters.m_test_activatedalarms[drift_type])) {
423  hasToRun = false;
424  }
425  else {
426  mean_eff += mean_drift;
427  ++idFrame;
428  }
429  }
431 
433  std::cout << "Test failed at frame: " << idFrame - parameters.m_test_nbsamples << std::endl;
434  std::cout << "Type of mean drift: " << vpStatisticalTestAbstract::vpMeanDriftTypeToString(drift_type) << std::endl;
435  std::cout << "Last signal value: " << signal << std::endl;
436  if (type == TutorialMeanDrift::EWMA_TYPE_TEST) {
437  vpStatisticalTestEWMA *p_testEwma = dynamic_cast<vpStatisticalTestEWMA *>(p_test);
438  std::cout << "\tw(t) = " << p_testEwma->getWt() << std::endl;
439  }
440  else if (type == TutorialMeanDrift::MEAN_ADJUSTED_CUSUM_TYPE_TEST) {
441  vpStatisticalTestMeanAdjustedCUSUM *p_testCusum = dynamic_cast<vpStatisticalTestMeanAdjustedCUSUM *>(p_test);
442  std::cout << "\tLower cusum = " << p_testCusum->getTestSignalMinus() << std::endl;
443  std::cout << "\tUpper cusum = " << p_testCusum->getTestSignalPlus() << std::endl;
444  }
445  else if (type==TutorialMeanDrift::SHEWHART_TYPE_TEST) {
446  vpStatisticalTestShewhart *p_testShewhart = dynamic_cast<vpStatisticalTestShewhart *>(p_test);
447  std::vector<float> signal = p_testShewhart->getSignals();
448  size_t nbSignal = signal.size();
449  std::cout << "Signal history = [ ";
450  for (size_t i = 0; i < nbSignal; ++i) {
451  std::cout << signal[i] << " ";
452  }
453  std::cout << "]" << std::endl;
454  std::cout << "\tWECO alarm type = " << vpStatisticalTestShewhart::vpWecoRulesAlarmToString(p_testShewhart->getAlarm()) << std::endl;
455  }
456  else if (type == TutorialMeanDrift::HINLKEY_TYPE_TEST) {
457  vpStatisticalTestHinkley *p_hinkley = dynamic_cast<vpStatisticalTestHinkley *>(p_test);
458  float Mk = p_hinkley->getMk();
459  float Nk = p_hinkley->getNk();
460  float Sk = p_hinkley->getSk();
461  float Tk = p_hinkley->getTk();
462  std::cout << "S+(t) = " << Tk - Nk <<std::endl;
463  std::cout << "S-(t) = " << Mk - Sk <<std::endl;
464  }
465  float limitDown = 0.f, limitUp = 0.f;
466  p_test->getLimits(limitDown, limitUp);
467  std::cout << "\tLimit down = " << limitDown << std::endl;
468  std::cout << "\tLimit up = " << limitUp << std::endl;
470  std::cout << "End of test on synthetic data. Press enter to leave." << std::endl;
471  std::cin.get();
472  delete p_test;
473  return EXIT_SUCCESS;
474 }
475 
476 int main(int argc, char *argv[])
477 {
478  TutorialMeanDrift::TypeTest opt_typeTest = TutorialMeanDrift::MEAN_ADJUSTED_CUSUM_TYPE_TEST;
479  TutorialMeanDrift::ParametersForAlgo parameters;
480  float opt_mean = 6.f;
481  float opt_meandrift = 0.f;
482  float opt_stdev = 2.f;
483 
484  int i = 1;
485  while (i < argc) {
486  if ((std::string(argv[i]) == "--test") && ((i + 1) < argc)) {
487  opt_typeTest = TutorialMeanDrift::typeTestFromString(argv[i + 1]);
488  ++i;
489  }
490  else if ((std::string(argv[i]) == "--nb-samples") && ((i + 1) < argc)) {
491  parameters.m_test_nbsamples = std::atoi(argv[i + 1]);
492  ++i;
493  }
494  else if ((std::string(argv[i]) == "--mean") && ((i + 1) < argc)) {
495  opt_mean = static_cast<float>(std::atof(argv[i + 1]));
496  ++i;
497  }
498  else if ((std::string(argv[i]) == "--mean-drift") && ((i + 1) < argc)) {
499  opt_meandrift = static_cast<float>(std::atof(argv[i + 1]));
500  ++i;
501  }
502  else if ((std::string(argv[i]) == "--stdev") && ((i + 1) < argc)) {
503  opt_stdev = static_cast<float>(std::atof(argv[i + 1]));
504  ++i;
505  }
506  else if ((std::string(argv[i]) == "--alarms")) {
507  unsigned int nbArguments = 0;
508  std::vector<std::string> alarmNames;
509  bool hasNotFoundNextParams = true;
510  for (int j = 1; ((i + j) < argc) && hasNotFoundNextParams; ++j) {
511  std::string candidate(argv[i+j]);
512  if (candidate.find("--") != std::string::npos) {
513  // This is the next command line parameter
514  hasNotFoundNextParams = false;
515  }
516  else {
517  // This is a name
518  alarmNames.push_back(candidate);
519  ++nbArguments;
520  }
521  }
522  TutorialMeanDrift::vectorOfStringToMeanDriftTypeArray(alarmNames, parameters.m_test_activatedalarms);
523  parameters.m_test_nbactivatedalarms = TutorialMeanDrift::meanDriftArrayToNbActivated(parameters.m_test_activatedalarms);
524  i += nbArguments;
525  }
526  else if ((std::string(argv[i]) == "--cusum-h") && ((i + 1) < argc)) {
527  parameters.m_cusum_h = static_cast<float>(std::atof(argv[i + 1]));
528  ++i;
529  }
530  else if ((std::string(argv[i]) == "--cusum-k") && ((i + 1) < argc)) {
531  parameters.m_cusum_k = static_cast<float>(std::atof(argv[i + 1]));
532  ++i;
533  }
534  else if ((std::string(argv[i]) == "--ewma-alpha") && ((i + 1) < argc)) {
535  parameters.m_ewma_alpha = static_cast<float>(std::atof(argv[i + 1]));
536  ++i;
537  }
538  else if ((std::string(argv[i]) == "--hinkley-alpha") && ((i + 1) < argc)) {
539  parameters.m_hinkley_alpha = static_cast<float>(std::atof(argv[i + 1]));
540  ++i;
541  }
542  else if ((std::string(argv[i]) == "--hinkley-delta") && ((i + 1) < argc)) {
543  parameters.m_hinkley_delta = static_cast<float>(std::atof(argv[i + 1]));
544  ++i;
545  }
546  else if (std::string(argv[i]) == "--hinkley-compute") {
547  parameters.m_hinkley_computealphadelta = true;
548  }
549  else if ((std::string(argv[i]) == "--hinkley-h") && ((i + 1) < argc)) {
550  parameters.m_hinkley_h = static_cast<float>(std::atof(argv[i + 1]));
551  ++i;
552  }
553  else if ((std::string(argv[i]) == "--hinkley-k") && ((i + 1) < argc)) {
554  parameters.m_hinkley_k = static_cast<float>(std::atof(argv[i + 1]));
555  ++i;
556  }
557  else if ((std::string(argv[i]) == "--shewhart-rules") && (i + vpStatisticalTestShewhart::COUNT_WECO - 1 < argc)) {
558  for (int j = 0; j < vpStatisticalTestShewhart::COUNT_WECO - 1; ++j) {
559  std::string argument = std::string(argv[i + 1 + j]);
560  if ((argument.find("on") != std::string::npos) || (argument.find("ON") != std::string::npos)) {
561  parameters.m_shewhart_rules[j] = true;
562  }
563  else {
564  parameters.m_shewhart_rules[j] = false;
565  }
566  }
568  }
569  else if (std::string(argv[i]) == "--shewhart-weco") {
570  parameters.m_shewhart_useWECO = true;
571  }
572  else if ((std::string(argv[i]) == "--sigma-h") && ((i + 1) < argc)) {
573  parameters.m_sigma_h = static_cast<float>(std::atof(argv[i + 1]));
574  ++i;
575  }
576  else if ((std::string(argv[i]) == "--help") || (std::string(argv[i]) == "-h")) {
577  std::cout << "\nSYNOPSIS " << std::endl
578  << argv[0]
579  << " [--test <type>]"
580  << " [--nb-samples <value>]"
581  << " [--alarms <name_1 ... name_n>]"
582  << " [--mean <value>]"
583  << " [--mean-drift <value>]"
584  << " [--stdev <value>]"
585  << " [--cusum-h <value>]"
586  << " [--cusum-k <value>]"
587  << " [--ewma-alpha <value ]0; 1[>]"
588  << " [--hinkley-alpha <]0; inf[>]"
589  << " [--hinkley-delta <]0; inf[>]"
590  << " [--hinkley-compute]"
591  << " [--hinkley-h <]0; inf[>]"
592  << " [--hinkley-k <]0; inf[>]"
593  << " [--shewhart-rules <3-sigma:{on|off} 2-sigma:{on|off} 1-sigma:{on|off} same-side:{on|off}>"
594  << " [--shewhart-weco]"
595  << " [--sigma-h <value>]"
596  << " [--help,-h]" << std::endl;
597  std::cout << "\nOPTIONS " << std::endl
598  << " --test <type-name>" << std::endl
599  << " Type of test to perform on the data." << std::endl
600  << " Available values: " << TutorialMeanDrift::getAvailableTypeTest() << std::endl
601  << std::endl
602  << " --nb-samples <value>" << std::endl
603  << " Number of samples to compute the mean and standard deviation of the monitored signal." << std::endl
604  << " Default: " << parameters.m_test_nbsamples << std::endl
605  << std::endl
606  << " --alarms <name_1 .. name_n>" << std::endl
607  << " Set the mean drift alarms to monitor." << std::endl
608  << " Default: " << TutorialMeanDrift::meanDriftArrayToString(parameters.m_test_activatedalarms) << std::endl
609  << " Available: " << vpStatisticalTestAbstract::getAvailableMeanDriftType() << std::endl
610  << std::endl
611  << " --mean <value>" << std::endl
612  << " Mean of the signal." << std::endl
613  << " Default: " << opt_mean<< std::endl
614  << std::endl
615  << " --mean-drift <value>" << std::endl
616  << " Mean drift for the synthetic data." << std::endl
617  << " Default: " << opt_meandrift << std::endl
618  << std::endl
619  << " --stdev <value>" << std::endl
620  << " Standard deviation of the signal." << std::endl
621  << " Default: " << opt_stdev << std::endl
622  << std::endl
623  << " --cusum-h <value>" << std::endl
624  << " The alarm factor that permits to the CUSUM test to determine when the process is out of control" << std::endl
625  << " from the standard deviation of the signal." << std::endl
626  << " Default: " << parameters.m_cusum_h << std::endl
627  << std::endl
628  << " --cusum-k <value>" << std::endl
629  << " The factor that permits to determine the slack of the CUSUM test, " << std::endl
630  << " i.e. the minimum value of the jumps we want to detect, from the standard deviation of the signal." << std::endl
631  << " Default: " << parameters.m_cusum_k << std::endl
632  << std::endl
633  << " --ewma-alpha <value ]0; 1[>" << std::endl
634  << " Forgetting factor for the Exponential Weighted Moving Average (EWMA)." << std::endl
635  << " Default: " << parameters.m_ewma_alpha << std::endl
636  << std::endl
637  << " --hinkley-alpha <value ]0; inf[>" << std::endl
638  << " The alarm threshold indicating that a mean drift occurs for the Hinkley's test." << std::endl
639  << " Default: " << parameters.m_hinkley_alpha << std::endl
640  << std::endl
641  << " --hinkley-delta <value>" << std::endl
642  << " Detection threshold indicating minimal magnitude we want to detect for the Hinkley's test." << std::endl
643  << " Default: " << parameters.m_hinkley_delta << std::endl
644  << std::endl
645  << " --hinkley-compute" << std::endl
646  << " If set, the Hinkley's test will compute the alarm and detection thresholds" << std::endl
647  << " from the standard deviation of the input signal." << std::endl
648  << " Default: disabled" << std::endl
649  << std::endl
650  << " --hinkley-h <value>" << std::endl
651  << " Alarm factor permitting to compute the alarm threshold for the Hinkley's test." << std::endl
652  << " Default: " << parameters.m_hinkley_h << std::endl
653  << std::endl
654  << " --hinkley-k <value>" << std::endl
655  << " Detection factor permitting to compute the Detection threshold for the Hinkley's test." << std::endl
656  << " Default: " << parameters.m_hinkley_k << std::endl
657  << std::endl
658  << " --shewhart-rules <3-sigma:{on|off} 2-sigma:{on|off} 1-sigma:{on|off} same-side:{on|off}>" << std::endl
659  << " Choose the WECO additionnal tests for the Shewhart's test to use. To activate them, --shewart-weco must be used." << std::endl
660  << " Default: ON ON ON ON" << std::endl
661  << std::endl
662  << " --shewhart-weco" << std::endl
663  << " Activate the WECO additionnal tests for the Shewhart's test." << std::endl
664  << " Default: deactivated" << std::endl
665  << std::endl
666  << " --sigma-h <value>" << std::endl
667  << " The alarm factor of the sigma test." << std::endl
668  << " Default: " << parameters.m_sigma_h << std::endl
669  << std::endl
670  << " --help, -h" << std::endl
671  << " Display this helper message." << std::endl
672  << std::endl;
673  return EXIT_SUCCESS;
674  }
675  else {
676  std::cout << "\nERROR " << std::endl << " Unknown option " << argv[i] << std::endl;
677  return EXIT_FAILURE;
678  }
679  ++i;
680  }
681 
682  if (parameters.m_test_nbactivatedalarms == 0) {
683  throw(vpException(vpException::badValue, "Error, at least one type of alarm must be monitored. See " + std::string(argv[0]) + " --help"));
684  return EXIT_FAILURE;
685  }
686 
687  std::cout << " Activated statistical test : " << TutorialMeanDrift::typeTestToString(opt_typeTest) << std::endl;
688  std::cout << " Activated alarms : " << TutorialMeanDrift::meanDriftArrayToString(parameters.m_test_activatedalarms) << std::endl;
689  std::cout << " Nb samples for statistics computation: " << parameters.m_test_nbsamples << std::endl;
690  std::cout << " Alarm factor CUSUM test : " << (opt_typeTest == TutorialMeanDrift::MEAN_ADJUSTED_CUSUM_TYPE_TEST ? TutorialMeanDrift::numberToString(parameters.m_cusum_h) : "N/A") << std::endl;
691  std::cout << " Detection factor CUSUM test : " << (opt_typeTest == TutorialMeanDrift::MEAN_ADJUSTED_CUSUM_TYPE_TEST ? TutorialMeanDrift::numberToString(parameters.m_cusum_k) : "N/A") << std::endl;
692  std::cout << " Forgetting factor EWMA test : " << (opt_typeTest == TutorialMeanDrift::EWMA_TYPE_TEST ? TutorialMeanDrift::numberToString(parameters.m_ewma_alpha) : "N/A") << std::endl;
693  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;
694  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;
695  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;
696  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;
697  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;
698  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;
699  std::cout << " Alarm factor Sigma test : " << (opt_typeTest == TutorialMeanDrift::SIGMA_TYPE_TEST ? TutorialMeanDrift::numberToString(parameters.m_sigma_h) : "N/A") << std::endl;
700  std::cout << " Actual mean of the input signal: " << opt_mean << std::endl;
701  std::cout << " Actual stdev of the input signal: " << opt_stdev << std::endl;
702  std::cout << " Mean drift of the input signal: " << opt_meandrift << std::endl;
703 
704  return testOnSynthetic(opt_typeTest, parameters, opt_mean, opt_meandrift, opt_stdev);
705 }
706 #else
707 int main()
708 {
709  std::cerr << "Recompile ViSP with display capabilities in order to use this tutorial." << std::endl;
710  return EXIT_FAILURE;
711 }
712 #endif
error that can be emitted by ViSP classes.
Definition: vpException.h:60
@ badValue
Used to indicate that a value is not in the allowed range.
Definition: vpException.h:73
Class for generating random number with normal probability density.
Definition: vpGaussRand.h:117
This class enables real time drawing of 2D or 3D graphics. An instance of the class open a window whi...
Definition: vpPlot.h:112
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.