Visual Servoing Platform version 3.7.0
Loading...
Searching...
No Matches
vpStatisticalTestShewhart.cpp
1/*
2 * ViSP, open source Visual Servoing Platform software.
3 * Copyright (C) 2005 - 2025 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
38
39#include <visp3/core/vpStatisticalTestShewhart.h>
40
41#include<cstring>
42#include<sstream>
43
44#include <visp3/core/vpException.h>
45#include <visp3/core/vpMath.h>
46
49
50#if (VISP_CXX_STANDARD < VISP_CXX_STANDARD_17)
51const std::vector<bool> vpStatisticalTestShewhart::CONST_ALL_WECO_ACTIVATED = std::vector<bool>(vpStatisticalTestShewhart::COUNT_WECO -1, true);
52#endif
53
55{
56 std::string name;
57 switch (alarm) {
59 name = "3-sigma alarm";
60 break;
61 case TWO_SIGMA_WECO:
62 name = "2-sigma alarm";
63 break;
64 case ONE_SIGMA_WECO:
65 name = "1-sigma alarm";
66 break;
67 case SAME_SIDE_WECO:
68 name = "Same-side alarm";
69 break;
70 case NONE_WECO:
71 name = "No alarm";
72 break;
73 case COUNT_WECO:
74 default:
75 name = "Unknown WECO alarm";
76 }
77 return name;
78}
79
90
92{
95 }
99 }
100 if (!m_activateWECOrules) {
102 }
105 unsigned int i = 0;
106 unsigned int nbAboveMean = 0;
107 unsigned int nbAbove2SigmaLimit = 0;
108 unsigned int nbAbove1SigmaLimit = 0;
109 while (i < NB_DATA_SIGNAL) {
110 // Reinit for next iteration
111 nbAbove2SigmaLimit = 0;
112 nbAbove1SigmaLimit = 0;
114 // Single-side test
115 ++nbAboveMean;
116 }
117 if (i > 3 && m_activatedWECOrules[TWO_SIGMA_WECO]) {
118 // Two sigma test
119 for (unsigned int idPrev = vpMath::modulo(id - 2, NB_DATA_SIGNAL); idPrev != id; idPrev = vpMath::modulo(idPrev + 1, NB_DATA_SIGNAL)) {
120 if (m_signal_vec[idPrev] <= m_twoSigmaNegLim) {
121 ++nbAbove2SigmaLimit;
122 }
123 }
124 if (m_signal_vec[id] <= m_twoSigmaNegLim) {
125 ++nbAbove2SigmaLimit;
126 }
127 if (nbAbove2SigmaLimit >= 2) {
128 break;
129 }
130 }
131 if (i > 5 && m_activatedWECOrules[ONE_SIGMA_WECO]) {
132 // One sigma test
133 for (unsigned int idPrev = vpMath::modulo(id - 4, NB_DATA_SIGNAL); idPrev != id; idPrev = vpMath::modulo(idPrev + 1, NB_DATA_SIGNAL)) {
134 if (m_signal_vec[idPrev] <= m_oneSigmaNegLim) {
135 ++nbAbove1SigmaLimit;
136 }
137 }
138 if (m_signal_vec[id] <= m_oneSigmaNegLim) {
139 ++nbAbove1SigmaLimit;
140 }
141 if (nbAbove1SigmaLimit >= 4) {
142 break;
143 }
144 }
145 id = vpMath::modulo(id + 1, NB_DATA_SIGNAL);
146 ++i;
147 }
148 if (nbAboveMean == NB_DATA_SIGNAL) {
150 result = MEAN_DRIFT_DOWNWARD;
151 }
152 else if (nbAbove2SigmaLimit >= 2) {
154 result = MEAN_DRIFT_DOWNWARD;
155 }
156 else if (nbAbove1SigmaLimit >= 4) {
158 result = MEAN_DRIFT_DOWNWARD;
159 }
160 return result;
161}
162
164{
167 }
171 }
172 if (!m_activateWECOrules) {
174 }
177 unsigned int i = 0;
178 unsigned int nbAboveMean = 0;
179 unsigned int nbAbove2SigmaLimit = 0;
180 unsigned int nbAbove1SigmaLimit = 0;
181 while (i < NB_DATA_SIGNAL) {
182 // Reinit for next iteration
183 nbAbove2SigmaLimit = 0;
184 nbAbove1SigmaLimit = 0;
186 // Single-side test
187 ++nbAboveMean;
188 }
189 if (i > 3 && m_activatedWECOrules[TWO_SIGMA_WECO]) {
190 // Two sigma test
191 for (unsigned int idPrev = vpMath::modulo(id - 2, NB_DATA_SIGNAL); idPrev != id; idPrev = vpMath::modulo(idPrev + 1, NB_DATA_SIGNAL)) {
192 if (m_signal_vec[idPrev] >= m_twoSigmaPosLim) {
193 ++nbAbove2SigmaLimit;
194 }
195 }
196 if (m_signal_vec[id] >= m_twoSigmaPosLim) {
197 ++nbAbove2SigmaLimit;
198 }
199 if (nbAbove2SigmaLimit >= 2) {
200 break;
201 }
202 }
203 if (i > 5 && m_activatedWECOrules[ONE_SIGMA_WECO]) {
204 // One sigma test
205 for (unsigned int idPrev = vpMath::modulo(id - 4, NB_DATA_SIGNAL); idPrev != id; idPrev = vpMath::modulo(idPrev + 1, NB_DATA_SIGNAL)) {
206 if (m_signal_vec[idPrev] >= m_oneSigmaPosLim) {
207 ++nbAbove1SigmaLimit;
208 }
209 }
210 if (m_signal_vec[id] >= m_oneSigmaPosLim) {
211 ++nbAbove1SigmaLimit;
212 }
213 if (nbAbove1SigmaLimit >= 4) {
214 break;
215 }
216 }
217 id = vpMath::modulo(id + 1, NB_DATA_SIGNAL);
218 ++i;
219 }
220 if (nbAboveMean == NB_DATA_SIGNAL) {
222 result = MEAN_DRIFT_UPWARD;
223 }
224 else if (nbAbove2SigmaLimit >= 2) {
226 result = MEAN_DRIFT_UPWARD;
227 }
228 else if (nbAbove1SigmaLimit >= 4) {
230 result = MEAN_DRIFT_UPWARD;
231 }
232 return result;
233}
234
236{
237 bool areStatsAvailable = vpStatisticalTestAbstract::updateStatistics(signal);
238 updateTestSignals(signal); // Store the signal in the circular buffer too.
239 if (areStatsAvailable) {
241 }
242 return areStatsAvailable;
243}
244
253
254vpStatisticalTestShewhart::vpStatisticalTestShewhart(const bool &activateWECOrules, const std::vector<bool> &activatedRules, const unsigned int &nbSamplesForStats)
255 : vpStatisticalTestSigma(3, nbSamplesForStats)
257 , m_activateWECOrules(activateWECOrules)
258 , m_idCurrentData(0)
260 , m_oneSigmaNegLim(0.f)
261 , m_oneSigmaPosLim(0.f)
262 , m_twoSigmaNegLim(0.f)
263 , m_twoSigmaPosLim(0.f)
264{
265 init(activateWECOrules, activatedRules, nbSamplesForStats);
266}
267
268vpStatisticalTestShewhart::vpStatisticalTestShewhart(const bool &activateWECOrules, const std::vector<bool> &activatedRules, const float &mean, const float &stdev)
271 , m_activateWECOrules(activateWECOrules)
272 , m_idCurrentData(0)
274 , m_oneSigmaNegLim(0.f)
275 , m_oneSigmaPosLim(0.f)
276 , m_twoSigmaNegLim(0.f)
277 , m_twoSigmaPosLim(0.f)
278{
279 init(activateWECOrules, activatedRules, mean, stdev);
280}
281
283{
284 std::vector<float> signals;
285 for (unsigned int i = 0; i < NB_DATA_SIGNAL; ++i) {
286 unsigned int id = vpMath::modulo(m_idCurrentData - (NB_DATA_SIGNAL - i - 1), NB_DATA_SIGNAL);
287 signals.push_back(m_signal_vec[id]);
288 }
289 return signals;
290}
291
292void vpStatisticalTestShewhart::init(const bool &activateWECOrules, const std::vector<bool> &activatedRules, const unsigned int &nbSamplesForStats)
293{
294 vpStatisticalTestSigma::init(3.f, nbSamplesForStats);
296 memset(m_signal_vec, 0, NB_DATA_SIGNAL * sizeof(float));
297 m_activateWECOrules = activateWECOrules;
298 if (activatedRules.size() != COUNT_WECO - 1) {
299 std::stringstream errMsg;
300 errMsg << "Error: the expected number of rules is " << COUNT_WECO -1 << ", the number given to the method is " << activatedRules.size() << std::endl;
301 throw(vpException(vpException::dimensionError, errMsg.str()));
302 }
303 m_activatedWECOrules = activatedRules;
304 m_idCurrentData = 0;
306 m_oneSigmaNegLim = 0.f;
307 m_oneSigmaPosLim = 0.f;
308 m_twoSigmaNegLim = 0.f;
309 m_twoSigmaPosLim = 0.f;
310}
311
312void vpStatisticalTestShewhart::init(const bool &activateWECOrules, const std::vector<bool> &activatedRules, const float &mean, const float &stdev)
313{
314 vpStatisticalTestShewhart::init(activateWECOrules, activatedRules, 30);
315 m_mean = mean;
316 m_stdev = stdev;
319}
320END_VISP_NAMESPACE
error that can be emitted by ViSP classes.
Definition vpException.h:60
@ dimensionError
Bad dimension.
Definition vpException.h:71
static float modulo(const float &value, const float &modulo)
Gives the rest of value divided by modulo when the quotient can only be an integer.
Definition vpMath.h:177
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...
vpStatisticalTestShewhart(const bool &activateWECOrules=true, const std::vector< bool > &activatedRules=CONST_ALL_WECO_ACTIVATED, const unsigned int &nbSamplesForStats=30)
Construct a new vpStatisticalTestShewhart object.
virtual bool updateStatistics(const float &signal) VP_OVERRIDE
Update m_s and if enough values are available, compute the mean, the standard deviation and the limit...
static const unsigned int NB_DATA_SIGNAL
virtual vpMeanDriftType detectUpwardMeanDrift() VP_OVERRIDE
Detects if an upward mean drift occurred on the mean.
static VP_ATTRIBUTE_NO_DESTROY const std::vector< bool > CONST_ALL_WECO_ACTIVATED
virtual vpMeanDriftType detectDownwardMeanDrift() VP_OVERRIDE
Detects if a downward mean drift occurred.
virtual void updateTestSignals(const float &signal) VP_OVERRIDE
Update the test signals.
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 void computeLimits() VP_OVERRIDE
Compute the upper and lower limits of the test signal.
static std::string vpWecoRulesAlarmToString(const vpWecoRulesAlarm &alarm)
vpStatisticalTestSigma(const float &h=3.f, const unsigned int &nbSamplesForStats=30)
Construct a new vpStatisticalTestSigma object.