Visual Servoing Platform version 3.7.0
Loading...
Searching...
No Matches
vpHinkley.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 * Description:
31 * Hinkley's cumulative sum test implementation.
32 */
33
40
41#include <visp3/core/vpHinkley.h>
42#if defined(VISP_BUILD_DEPRECATED_FUNCTIONS)
43#include <visp3/core/vpDebug.h>
44#include <visp3/core/vpMath.h>
45
46#include <cmath> // std::fabs
47#include <iostream>
48#include <limits> // numeric_limits
49#include <stdio.h>
50#include <stdlib.h>
51
53/* VP_DEBUG_MODE fixed by configure:
54 1:
55 2:
56 3: Print data
57*/
58
70vpHinkley::vpHinkley() : dmin2(0.1), alpha(0.2), nsignal(0), mean(0), Sk(0), Mk(0), Tk(0), Nk(0) { }
71
87
88vpHinkley::vpHinkley(double alpha_val, double delta_val)
89 : dmin2(delta_val / 2.), alpha(alpha_val), nsignal(0), mean(0), Sk(0), Mk(0), Tk(0), Nk(0)
90{ }
91
105void vpHinkley::init(double alpha_val, double delta_val)
106{
107 init();
108
109 setAlpha(alpha_val);
110 setDelta(delta_val);
111}
112
120{
121 nsignal = 0;
122 mean = 0.0;
123
124 Sk = 0;
125 Mk = 0;
126
127 Tk = 0;
128 Nk = 0;
129}
130
139void vpHinkley::setDelta(double delta) { dmin2 = delta / 2; }
140
148void vpHinkley::setAlpha(double alpha_val) { this->alpha = alpha_val; }
149
161{
162
164
165 nsignal++; // Signal length
166
167 if (nsignal == 1)
168 mean = signal;
169
170 // Calcul des variables cumulees
171 computeSk(signal);
172
173 computeMk();
174
175 vpCDEBUG(2) << "alpha: " << alpha << " dmin2: " << dmin2 << " signal: " << signal << " Sk: " << Sk << " Mk: " << Mk;
176
177 // teste si les variables cumulees excedent le seuil
178 if ((Mk - Sk) > alpha)
179 jump = downwardJump;
180
181#ifdef VP_DEBUG
182 if (VP_DEBUG_MODE >= 2) {
183 switch (jump) {
184 case noJump:
185 std::cout << "noJump " << std::endl;
186 break;
187 case downwardJump:
188 std::cout << "downWardJump " << std::endl;
189 break;
190 case upwardJump:
191 std::cout << "upwardJump " << std::endl;
192 break;
193 }
194 }
195#endif
196
197 computeMean(signal);
198
199 if (jump == downwardJump) {
200 vpCDEBUG(2) << "\n*** Reset the Hinkley test ***\n";
201
202 Sk = 0;
203 Mk = 0;
204 nsignal = 0;
205 }
206
207 return (jump);
208}
209
221{
222
224
225 nsignal++; // Signal length
226
227 if (nsignal == 1)
228 mean = signal;
229
230 // Calcul des variables cumulees
231 computeTk(signal);
232
233 computeNk();
234
235 vpCDEBUG(2) << "alpha: " << alpha << " dmin2: " << dmin2 << " signal: " << signal << " Tk: " << Tk << " Nk: " << Nk;
236
237 // teste si les variables cumulees excedent le seuil
238 if ((Tk - Nk) > alpha)
239 jump = upwardJump;
240
241#ifdef VP_DEBUG
242 if (VP_DEBUG_MODE >= 2) {
243 switch (jump) {
244 case noJump:
245 std::cout << "noJump " << std::endl;
246 break;
247 case downwardJump:
248 std::cout << "downWardJump " << std::endl;
249 break;
250 case upwardJump:
251 std::cout << "upWardJump " << std::endl;
252 break;
253 }
254 }
255#endif
256 computeMean(signal);
257
258 if (jump == upwardJump) {
259 vpCDEBUG(2) << "\n*** Reset the Hinkley test ***\n";
260
261 Tk = 0;
262 Nk = 0;
263 nsignal = 0;
264 }
265
266 return (jump);
267}
268
280{
281
283
284 nsignal++; // Signal length
285
286 if (nsignal == 1)
287 mean = signal;
288
289 // Calcul des variables cumulees
290 computeSk(signal);
291 computeTk(signal);
292
293 computeMk();
294 computeNk();
295
296 vpCDEBUG(2) << "alpha: " << alpha << " dmin2: " << dmin2 << " signal: " << signal << " Sk: " << Sk << " Mk: " << Mk
297 << " Tk: " << Tk << " Nk: " << Nk << std::endl;
298
299// teste si les variables cumulees excedent le seuil
300 if ((Mk - Sk) > alpha)
301 jump = downwardJump;
302 else if ((Tk - Nk) > alpha)
303 jump = upwardJump;
304
305#ifdef VP_DEBUG
306 if (VP_DEBUG_MODE >= 2) {
307 switch (jump) {
308 case noJump:
309 std::cout << "noJump " << std::endl;
310 break;
311 case downwardJump:
312 std::cout << "downWardJump " << std::endl;
313 break;
314 case upwardJump:
315 std::cout << "upwardJump " << std::endl;
316 break;
317 }
318 }
319#endif
320
321 computeMean(signal);
322
323 if ((jump == upwardJump) || (jump == downwardJump)) {
324 vpCDEBUG(2) << "\n*** Reset the Hinkley test ***\n";
325
326 Sk = 0;
327 Mk = 0;
328 Tk = 0;
329 Nk = 0;
330 nsignal = 0;
331 // Debut modif FS le 03/09/2003
332 mean = signal;
333 // Fin modif FS le 03/09/2003
334 }
335
336 return (jump);
337}
338
347void vpHinkley::computeMean(double signal)
348{
349 // Debut modif FS le 03/09/2003
350 // Lors d'une chute ou d'une remontee lente du signal, pariculierement
351 // apres un saut, la moyenne a tendance a "deriver". Pour reduire ces
352 // derives de la moyenne, elle n'est remise a jour avec la valeur
353 // courante du signal que si un debut de saut potentiel n'est pas detecte.
354 // if ( ((Mk-Sk) == 0) && ((Tk-Nk) == 0) )
355 if ((std::fabs(Mk - Sk) <= std::fabs(vpMath::maximum(Mk, Sk)) * std::numeric_limits<double>::epsilon()) &&
356 (std::fabs(Tk - Nk) <= std::fabs(vpMath::maximum(Tk, Nk)) * std::numeric_limits<double>::epsilon()))
357 // Fin modif FS le 03/09/2003
358
359 // Mise a jour de la moyenne.
360 mean = (mean * (nsignal - 1) + signal) / (nsignal);
361}
369void vpHinkley::computeSk(double signal)
370{
371
372 // Calcul des variables cumulees
373 Sk += signal - mean + dmin2;
374}
380void vpHinkley::computeMk()
381{
382 if (Sk > Mk)
383 Mk = Sk;
384}
391void vpHinkley::computeTk(double signal)
392{
393
394 // Calcul des variables cumulees
395 Tk += signal - mean - dmin2;
396}
402void vpHinkley::computeNk()
403{
404 if (Tk < Nk)
405 Nk = Tk;
406}
407
409{
410 switch (jump) {
411 case noJump:
412 std::cout << " No jump detected " << std::endl;
413 break;
414 case downwardJump:
415 std::cout << " Jump downward detected " << std::endl;
416 break;
417 case upwardJump:
418 std::cout << " Jump upward detected " << std::endl;
419 break;
420 default: {
421 throw(vpException(vpException::fatalError, "Unsupported jump type in vpHinkley::print()"));
422 }
423 }
424}
425END_VISP_NAMESPACE
426#elif !defined(VISP_BUILD_SHARED_LIBS)
427 // Work around to avoid warning: libvisp_core.a(vpHinkley.cpp.o) has no symbols
428void dummy_vpRHinkley() { }
429#endif
error that can be emitted by ViSP classes.
Definition vpException.h:60
@ fatalError
Fatal error.
Definition vpException.h:72
void init()
void setDelta(double delta)
VP_DEPRECATED vpHinkley()
Definition vpHinkley.cpp:70
vpHinkleyJumpType testDownwardJump(double signal)
void setAlpha(double alpha)
static void print(vpHinkleyJumpType jump)
vpHinkleyJumpType testUpwardJump(double signal)
vpHinkleyJumpType testDownUpwardJump(double signal)
static Type maximum(const Type &a, const Type &b)
Definition vpMath.h:257
#define vpCDEBUG(level)
Definition vpDebug.h:554