ViSP  2.9.0
vpHinkley.cpp
1 /****************************************************************************
2  *
3  * $Id: vpHinkley.cpp 4649 2014-02-07 14:57:11Z fspindle $
4  *
5  * This file is part of the ViSP software.
6  * Copyright (C) 2005 - 2014 by INRIA. All rights reserved.
7  *
8  * This software is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * ("GPL") version 2 as published by the Free Software Foundation.
11  * See the file LICENSE.txt at the root directory of this source
12  * distribution for additional information about the GNU GPL.
13  *
14  * For using ViSP with software that can not be combined with the GNU
15  * GPL, please contact INRIA about acquiring a ViSP Professional
16  * Edition License.
17  *
18  * See http://www.irisa.fr/lagadic/visp/visp.html for more information.
19  *
20  * This software was developed at:
21  * INRIA Rennes - Bretagne Atlantique
22  * Campus Universitaire de Beaulieu
23  * 35042 Rennes Cedex
24  * France
25  * http://www.irisa.fr/lagadic
26  *
27  * If you have questions regarding the use of this file, please contact
28  * INRIA at visp@inria.fr
29  *
30  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
31  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
32  *
33  *
34  * Description:
35  * Hinkley's cumulative sum test implementation.
36  *
37  * Authors:
38  * Fabien Spindler
39  *
40  *****************************************************************************/
41 
51 #include <visp/vpHinkley.h>
52 #include <visp/vpDebug.h>
53 #include <visp/vpIoTools.h>
54 #include <visp/vpMath.h>
55 
56 #include <stdio.h>
57 #include <stdlib.h>
58 #include <iostream>
59 #include <cmath> // std::fabs
60 #include <limits> // numeric_limits
61 
62 /* VP_DEBUG_MODE fixed by configure:
63  1:
64  2:
65  3: Print data
66 */
67 
68 
81  : dmin2(0.1), alpha(0.2), nsignal(0), mean(0), Sk(0), Mk(0), Tk(0), Nk(0)
82 {
83 }
84 
101 vpHinkley::vpHinkley(double alpha_val, double delta_val)
102  : dmin2(delta_val/2.), alpha(alpha_val), nsignal(0), mean(0), Sk(0), Mk(0), Tk(0), Nk(0)
103 {
104 }
105 
119 void
120 vpHinkley::init(double alpha_val, double delta_val)
121 {
122  init();
123 
124  setAlpha(alpha_val);
125  setDelta(delta_val);
126 }
127 
134 {
135 }
136 
144 {
145  nsignal = 0;
146  mean = 0.0;
147 
148  Sk = 0;
149  Mk = 0;
150 
151  Tk = 0;
152  Nk = 0;
153 }
154 
163 void vpHinkley::setDelta(double delta)
164 {
165  dmin2 = delta / 2;
166 }
167 
175 void vpHinkley::setAlpha(double alpha_val)
176 {
177  this->alpha = alpha_val;
178 }
179 
191 {
192 
193  vpHinkleyJumpType jump = noJump;
194 
195  nsignal ++; // Signal length
196 
197  if (nsignal == 1) mean = signal;
198 
199  // Calcul des variables cumulées
200  computeSk(signal);
201 
202  computeMk();
203 
204  vpCDEBUG(2) << "alpha: " << alpha << " dmin2: " << dmin2
205  << " signal: " << signal << " Sk: " << Sk << " Mk: " << Mk;
206 
207  // teste si les variables cumulées excèdent le seuil
208  if ((Mk - Sk) > alpha)
209  jump = downwardJump;
210 
211 #ifdef VP_DEBUG
212  if (VP_DEBUG_MODE >=2) {
213  switch(jump) {
214  case noJump:
215  std::cout << "noJump " << std::endl;
216  break;
217  case downwardJump:
218  std::cout << "downWardJump " << std::endl;
219  break;
220  case upwardJump:
221  std::cout << "upwardJump " << std::endl;
222  break;
223  }
224  }
225 #endif
226 
227  computeMean(signal);
228 
229  if (jump == downwardJump) {
230  vpCDEBUG(2) << "\n*** Reset the Hinkley test ***\n";
231 
232  Sk = 0; Mk = 0; nsignal = 0;
233  }
234 
235  return (jump);
236 }
237 
249 {
250 
251  vpHinkleyJumpType jump = noJump;
252 
253  nsignal ++; // Signal length
254 
255  if (nsignal == 1) mean = signal;
256 
257  // Calcul des variables cumulées
258  computeTk(signal);
259 
260  computeNk();
261 
262  vpCDEBUG(2) << "alpha: " << alpha << " dmin2: " << dmin2
263  << " signal: " << signal << " Tk: " << Tk << " Nk: " << Nk;
264 
265  // teste si les variables cumulées excèdent le seuil
266  if ((Tk - Nk) > alpha)
267  jump = upwardJump;
268 
269 #ifdef VP_DEBUG
270  if (VP_DEBUG_MODE >= 2) {
271  switch(jump) {
272  case noJump:
273  std::cout << "noJump " << std::endl;
274  break;
275  case downwardJump:
276  std::cout << "downWardJump " << std::endl;
277  break;
278  case upwardJump:
279  std::cout << "upWardJump " << std::endl;
280  break;
281  }
282  }
283 #endif
284  computeMean(signal);
285 
286  if (jump == upwardJump) {
287  vpCDEBUG(2) << "\n*** Reset the Hinkley test ***\n";
288 
289  Tk = 0; Nk = 0; nsignal = 0;
290  }
291 
292  return (jump);
293 }
294 
306 {
307 
308  vpHinkleyJumpType jump = noJump;
309 
310  nsignal ++; // Signal length
311 
312  if (nsignal == 1) mean = signal;
313 
314  // Calcul des variables cumulées
315  computeSk(signal);
316  computeTk(signal);
317 
318  computeMk();
319  computeNk();
320 
321  vpCDEBUG(2) << "alpha: " << alpha << " dmin2: " << dmin2
322  << " signal: " << signal
323  << " Sk: " << Sk << " Mk: " << Mk
324  << " Tk: " << Tk << " Nk: " << Nk << std::endl;
325 
326  // teste si les variables cumulées excèdent le seuil
327  if ((Mk - Sk) > alpha)
328  jump = downwardJump;
329  else if ((Tk - Nk) > alpha)
330  jump = upwardJump;
331 
332 #ifdef VP_DEBUG
333  if (VP_DEBUG_MODE >= 2) {
334  switch(jump) {
335  case noJump:
336  std::cout << "noJump " << std::endl;
337  break;
338  case downwardJump:
339  std::cout << "downWardJump " << std::endl;
340  break;
341  case upwardJump:
342  std::cout << "upwardJump " << std::endl;
343  break;
344  }
345  }
346 #endif
347 
348  computeMean(signal);
349 
350  if ((jump == upwardJump) || (jump == downwardJump)) {
351  vpCDEBUG(2) << "\n*** Reset the Hinkley test ***\n";
352 
353  Sk = 0; Mk = 0; Tk = 0; Nk = 0; nsignal = 0;
354  // Debut modif FS le 03/09/2003
355  mean = signal;
356  // Fin modif FS le 03/09/2003
357  }
358 
359  return (jump);
360 }
361 
370 void vpHinkley::computeMean(double signal)
371 {
372  // Debut modif FS le 03/09/2003
373  // Lors d'une chute ou d'une remontée lente du signal, pariculièrement
374  // après un saut, la moyenne a tendance à "dériver". Pour réduire ces
375  // dérives de la moyenne, elle n'est remise à jour avec la valeur
376  // courante du signal que si un début de saut potentiel n'est pas détecté.
377  //if ( ((Mk-Sk) == 0) && ((Tk-Nk) == 0) )
378  if ( ( std::fabs(Mk-Sk) <= std::fabs(vpMath::maximum(Mk,Sk))*std::numeric_limits<double>::epsilon() )
379  &&
380  ( std::fabs(Tk-Nk) <= std::fabs(vpMath::maximum(Tk,Nk))*std::numeric_limits<double>::epsilon() ) )
381  // Fin modif FS le 03/09/2003
382 
383  // Mise a jour de la moyenne.
384  mean = (mean * (nsignal - 1) + signal) / (nsignal);
385 
386 }
394 void vpHinkley::computeSk(double signal)
395 {
396 
397  // Calcul des variables cumulées
398  Sk += signal - mean + dmin2;
399 }
405 void vpHinkley::computeMk()
406 {
407  if (Sk > Mk) Mk = Sk;
408 }
415 void vpHinkley::computeTk(double signal)
416 {
417 
418  // Calcul des variables cumulées
419  Tk += signal - mean - dmin2;
420 }
426 void vpHinkley::computeNk()
427 {
428  if (Tk < Nk) Nk = Tk;
429 }
430 
432 {
433  switch(jump)
434  {
435  case noJump :
436  std::cout << " No jump detected " << std::endl ;
437  break ;
438  case downwardJump :
439  std::cout << " Jump downward detected " << std::endl ;
440  break ;
441  case upwardJump :
442  std::cout << " Jump upward detected " << std::endl ;
443  break ;
444  default:
445  std::cout << " Jump detected " << std::endl ;
446  break ;
447 
448  }
449 }
450 
vpHinkleyJumpType testDownUpwardJump(double signal)
Definition: vpHinkley.cpp:305
vpHinkleyJumpType
Definition: vpHinkley.h:106
vpHinkleyJumpType testUpwardJump(double signal)
Definition: vpHinkley.cpp:248
static Type maximum(const Type &a, const Type &b)
Definition: vpMath.h:137
static void print(vpHinkleyJumpType jump)
Definition: vpHinkley.cpp:431
void init()
Definition: vpHinkley.cpp:143
#define vpCDEBUG(level)
Definition: vpDebug.h:506
vpHinkleyJumpType testDownwardJump(double signal)
Definition: vpHinkley.cpp:190
void setAlpha(double alpha)
Definition: vpHinkley.cpp:175
void setDelta(double delta)
Definition: vpHinkley.cpp:163