Visual Servoing Platform  version 3.6.1 under development (2024-05-03)
vpStatisticalTestHinkley.cpp
1 /****************************************************************************
2  *
3  * ViSP, open source Visual Servoing Platform software.
4  * Copyright (C) 2005 - 2024 by Inria. All rights reserved.
5  *
6  * This software is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  * See the file LICENSE.txt at the root directory of this source
11  * distribution for additional information about the GNU GPL.
12  *
13  * For using ViSP with software that can not be combined with the GNU
14  * GPL, please contact Inria about acquiring a ViSP Professional
15  * Edition License.
16  *
17  * See https://visp.inria.fr for more information.
18  *
19  * This software was developed at:
20  * Inria Rennes - Bretagne Atlantique
21  * Campus Universitaire de Beaulieu
22  * 35042 Rennes Cedex
23  * France
24  *
25  * If you have questions regarding the use of this file, please contact
26  * Inria at visp@inria.fr
27  *
28  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
29  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
30  */
31 
40 #include <visp3/core/vpStatisticalTestHinkley.h>
41 #include <visp3/core/vpMath.h>
42 
43 #include <cmath> // std::fabs
44 #include <iostream>
45 #include <limits> // numeric_limits
46 #include <stdio.h>
47 #include <stdlib.h>
48 
51  , m_dmin2(0.1f)
52  , m_alpha(0.2f)
53  , m_Sk(0.f)
54  , m_Mk(0.f)
55  , m_Tk(0.f)
56  , m_Nk(0.f)
57  , m_computeDeltaAndAlpha(false)
58  , m_h(4.76f)
59  , m_k(1.f)
60 {
61  init();
62 }
63 
64 vpStatisticalTestHinkley::vpStatisticalTestHinkley(const float &alpha, const float &delta_val, const unsigned int &nbSamplesForInit)
66  , m_dmin2(delta_val / 2.f)
67  , m_alpha(alpha)
68  , m_Sk(0.f)
69  , m_Mk(0.f)
70  , m_Tk(0.f)
71  , m_Nk(0.f)
72  , m_computeDeltaAndAlpha(false)
73  , m_h(4.76f)
74  , m_k(1.f)
75 {
76  init(alpha, delta_val, nbSamplesForInit);
77 }
78 
79 vpStatisticalTestHinkley::vpStatisticalTestHinkley(const float &h, const float &k, const bool &computeAlphaDeltaFromStdev, const unsigned int &nbSamplesForInit)
81 {
82  init(h, k, computeAlphaDeltaFromStdev, nbSamplesForInit);
83 }
84 
85 vpStatisticalTestHinkley::vpStatisticalTestHinkley(const float &h, const float &k, const float &mean, const float &stdev)
87 {
88  init(h, k, mean, stdev);
89 }
90 
92 {
96 
97  m_Sk = 0.f;
98  m_Mk = 0.f;
99 
100  m_Tk = 0.f;
101  m_Nk = 0.f;
102 
103  m_computeDeltaAndAlpha = false;
104 }
105 
106 void vpStatisticalTestHinkley::init(const float &alpha, const float &delta_val, const unsigned int &nbSamplesForInit)
107 {
108  init();
109  setNbSamplesForStat(nbSamplesForInit);
110  setAlpha(alpha);
111  setDelta(delta_val);
112  m_computeDeltaAndAlpha = false;
113 }
114 
115 void vpStatisticalTestHinkley::init(const float &alpha, const float &delta_val, const float &mean)
116 {
117  init();
118  setAlpha(alpha);
119  setDelta(delta_val);
120  m_mean = mean;
121  m_computeDeltaAndAlpha = false;
123 }
124 
125 void vpStatisticalTestHinkley::init(const float &h, const float &k, const bool &computeAlphaDeltaFromStdev, const unsigned int &nbSamples)
126 {
127  if (!computeAlphaDeltaFromStdev) {
128  throw(vpException(vpException::badValue, "computeAlphaDeltaFromStdev must be true, or use another init function"));
129  }
130  init();
131  setNbSamplesForStat(nbSamples);
132  m_h = h;
133  m_k = k;
134  m_computeDeltaAndAlpha = true;
135 }
136 
137 void vpStatisticalTestHinkley::init(const float &h, const float &k, const float &mean, const float &stdev)
138 {
139  init();
140  m_mean = mean;
141  m_stdev = stdev;
142  m_h = h;
143  m_k = k;
144  m_computeDeltaAndAlpha = true;
147 }
148 
150 
151 void vpStatisticalTestHinkley::setDelta(const float &delta) { m_dmin2 = delta / 2.f; }
152 
153 void vpStatisticalTestHinkley::setAlpha(const float &alpha)
154 {
155  this->m_alpha = alpha;
157  m_limitUp = m_alpha;
158 }
159 
161 {
162  float delta = m_k * m_stdev;
163  setDelta(delta);
164  float alpha = m_h * m_stdev;
165  setAlpha(alpha);
166 }
167 
169 {
170  // When the mean slowly increases or decreases, especially after an abrupt change of the mean,
171  // the means tends to drift. To reduce the drift of the mean
172  // it is updated with the current value of the signal only if
173  // a beginning of a mean drift is not detected,
174  // i.e. if ( ((m_Mk-m_Sk) == 0) && ((m_Tk-m_Nk) == 0) )
175  if ((std::fabs(m_Mk - m_Sk) <= std::fabs(vpMath::maximum(m_Mk, m_Sk)) * std::numeric_limits<double>::epsilon()) &&
176  (std::fabs(m_Tk - m_Nk) <= std::fabs(vpMath::maximum(m_Tk, m_Nk)) * std::numeric_limits<double>::epsilon())) {
177  m_mean = (m_mean * (m_count - 1) + static_cast<float>(signal)) / (m_count);
178  }
179 }
180 
182 {
183  m_Sk += static_cast<float>(signal) - m_mean + m_dmin2;
184 }
185 
187 {
188  if (m_Sk > m_Mk) {
189  m_Mk = m_Sk;
190  }
191 }
192 
194 {
195  m_Tk += static_cast<float>(signal) - m_mean - m_dmin2;
196 }
197 
199 {
200  if (m_Tk < m_Nk) {
201  m_Nk = m_Tk;
202  }
203 }
204 
206 {
208  if ((m_Mk - m_Sk) > m_alpha) {
209  shift = MEAN_DRIFT_DOWNWARD;
210  }
211  return shift;
212 }
213 
215 {
217  if ((m_Tk - m_Nk) > m_alpha) {
218  shift = MEAN_DRIFT_UPWARD;
219  }
220  return shift;
221 }
222 
224 {
225  bool updateStats = vpStatisticalTestAbstract::updateStatistics(signal);
227  // If needed, compute alpha and delta
230  }
231  // Initialize the test signals
232  m_Mk = 0.f;
233  m_Nk = 0.f;
234  m_Sk = 0.f;
235  m_Tk = 0.f;
236  }
237  return updateStats;
238 }
239 
241 {
242  computeSk(signal);
243  computeTk(signal);
244 
245  computeMk();
246  computeNk();
247 
248  ++m_count;
249  computeMean(signal);
250 }
error that can be emitted by ViSP classes.
Definition: vpException.h:59
@ badValue
Used to indicate that a value is not in the allowed range.
Definition: vpException.h:85
static Type maximum(const Type &a, const Type &b)
Definition: vpMath.h:252
Base class for methods detecting the drift of the mean of a process.
vpMeanDriftType
Enum that indicates if a drift of the mean occurred.
void init()
(Re)Initialize the algorithm.
virtual bool updateStatistics(const float &signal)
Update m_s and if enough values are available, compute the mean, the standard deviation and the limit...
void setNbSamplesForStat(const unsigned int &nbSamples)
Set the number of samples required to compute the mean and standard deviation of the signal and alloc...
void setAlpha(const float &alpha)
The threshold indicating that a mean drift occurs.
virtual ~vpStatisticalTestHinkley()
Destroy the vpStatisticalTestHinkley object.
virtual vpMeanDriftType detectDownwardMeanDrift() override
Detects if a downward mean drift occurred.
virtual void computeAlphaDelta()
Compute and from the standard deviation of the signal.
void setDelta(const float &delta)
Set the drift minimal magnitude that we want to detect.
void computeTk(double signal)
Compute .
void computeMk()
Compute , the maximum value of .
void computeNk()
Compute , the minimum value of .
virtual void updateTestSignals(const float &signal) override
Update the test signals.
void computeSk(double signal)
Compute .
virtual vpMeanDriftType detectUpwardMeanDrift() override
Detects if an upward mean drift occured on the mean.
void init()
Initialise the Hinkley's test by setting the mean signal value to zero as well as .
void computeMean(double signal)
Compute the mean value of the signal. The mean value must be computed before the mean drift is estim...
virtual bool updateStatistics(const float &signal) override
Update m_s and if enough values are available, compute the mean, the standard deviation and the limit...
vpStatisticalTestHinkley()
Construct a new vpStatisticalTestHinkley object. Call init() to initialise the Hinkley's test and set...