ViSP  2.9.0
vpMbEdgeTracker.cpp
1 /****************************************************************************
2  *
3  * $Id: vpMbEdgeTracker.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  * Make the complete tracking of an object by using its CAD model
36  *
37  * Authors:
38  * Nicolas Melchior
39  * Romain Tallonneau
40  * Eric Marchand
41  *
42  *****************************************************************************/
43 
49 #include <visp/vpDebug.h>
50 #include <visp/vpPose.h>
51 #include <visp/vpExponentialMap.h>
52 #include <visp/vpPixelMeterConversion.h>
53 #include <visp/vpImageIo.h>
54 #include <visp/vpRobust.h>
55 #include <visp/vpDisplayOpenCV.h>
56 #include <visp/vpDisplayX.h>
57 #include <visp/vpDisplayGDI.h>
58 #include <visp/vpMatrixException.h>
59 #include <visp/vpMath.h>
60 #include <visp/vpException.h>
61 #include <visp/vpTrackingException.h>
62 #include <visp/vpMbEdgeTracker.h>
63 #include <visp/vpMbtDistanceLine.h>
64 #include <visp/vpMbtXmlParser.h>
65 #include <visp/vpMbtPolygon.h>
66 
67 #include <limits>
68 #include <string>
69 #include <sstream>
70 #include <float.h>
71 
72 bool samePoint(const vpPoint &P1, const vpPoint &P2, double threshold);
73 
78  : compute_interaction(1), lambda(1), me(), lines(1), cylinders(1), nline(0), ncylinder(0),
79  index_polygon(0), faces(), nbvisiblepolygone(0), percentageGdPt(0.4), scales(1),
80  Ipyramid(0), scaleLevel(0), useOgre(false),
81  angleAppears( vpMath::rad(89) ), angleDisappears( vpMath::rad(89) ),
82  distNearClip(0.001), distFarClip(100), clippingFlag(vpMbtPolygon::NO_CLIPPING)
83 {
84  scales[0] = true;
85 
86 #ifdef VISP_HAVE_OGRE
87  faces.getOgreContext()->setWindowName("MBT Edge");
88 #endif
89 }
90 
95 {
98 
99  for (unsigned int i = 0; i < lines.size(); i += 1){
100  if(scales[i]){
101  for(std::list<vpMbtDistanceLine*>::const_iterator it=lines[i].begin(); it!=lines[i].end(); ++it){
102  l = *it;
103  if (l!=NULL){
104  delete l ;
105  }
106  l = NULL ;
107  }
108 
109  for(std::list<vpMbtDistanceCylinder*>::const_iterator it=cylinders[i].begin(); it!=cylinders[i].end(); ++it){
110  c = *it;
111  if (c!=NULL){
112  delete c ;
113  }
114  c = NULL ;
115  }
116 
117  lines[i].clear();
118  cylinders[i].clear();
119  }
120  }
122 }
123 
129 void
131 {
132  this->me = p_me;
133 
134  for (unsigned int i = 0; i < scales.size(); i += 1){
135  if(scales[i]){
136  for(std::list<vpMbtDistanceLine*>::const_iterator it=lines[i].begin(); it!=lines[i].end(); ++it){
137  (*it)->setMovingEdge(&(this->me)) ;
138  }
139 
141  for(std::list<vpMbtDistanceCylinder*>::const_iterator it=cylinders[i].begin(); it!=cylinders[i].end(); ++it){
142  cy = *it;
143  cy->setMovingEdge(&(this->me)) ;
144  }
145  }
146  }
147 }
148 
156 void
158 {
159  useOgre = v;
160  if(useOgre){
161 #ifndef VISP_HAVE_OGRE
162  useOgre = false;
163  std::cout << "WARNING: ViSP doesn't have Ogre3D, basic visibility test will be used. setOgreVisibilityTest() set to false." << std::endl;
164 #endif
165  }
166 }
167 
176 void
178 {
179  double residu_1 =1e3;
180  double r =1e3-1;
181  vpMatrix LTL;
182  vpColVector LTR;
183 
184  // compute the interaction matrix and its pseudo inverse
185  vpMbtDistanceLine *l ;
187 
188  vpColVector w;
189  vpColVector weighted_error;
190  vpColVector factor;
191 
192  unsigned int iter = 0;
193 
194  //Nombre de moving edges
195  unsigned int nbrow = 0;
196  unsigned int nberrors_lines = 0;
197  unsigned int nberrors_cylinders = 0;
198 
199  for(std::list<vpMbtDistanceLine*>::const_iterator it=lines[scaleLevel].begin(); it!=lines[scaleLevel].end(); ++it){
200  l = *it;
201  nbrow += l->nbFeature ;
202  nberrors_lines+=l->nbFeature;
204  }
205 
206  for(std::list<vpMbtDistanceCylinder*>::const_iterator it=cylinders[scaleLevel].begin(); it!=cylinders[scaleLevel].end(); ++it){
207  cy = *it;
208  nbrow += cy->nbFeature ;
209  nberrors_cylinders += cy->nbFeature ;
211  }
212 
213  if (nbrow==0){
214  vpERROR_TRACE("\n\t\t Error-> not enough data in the interaction matrix...") ;
215  throw vpTrackingException(vpTrackingException::notEnoughPointError, "\n\t\t Error-> not enough data in the interaction matrix...");
216  }
217 
218  vpMatrix L(nbrow,6), Lp;
219 
220  // compute the error vector
221  vpColVector error(nbrow);
222  unsigned int nerror = error.getRows();
223  vpColVector v ;
224 
225  double limite = 3; //Une limite de 3 pixels
226  limite = limite / cam.get_px(); //Transformation limite pixel en limite metre.
227 
228  //Parametre pour la premiere phase d'asservissement
229  double e_prev = 0, e_cur, e_next;
230  bool reloop = true;
231  double count = 0;
232 
233  /*** First phase ***/
234  while ( reloop == true && iter<10)
235  {
236  if(iter==0)
237  {
238  weighted_error.resize(nerror) ;
239  w.resize(nerror);
240  w = 0;
241  factor.resize(nerror);
242  factor = 1;
243  }
244 
245  count = 0;
246 
247  unsigned int n = 0;
248  reloop = false;
249  for(std::list<vpMbtDistanceLine*>::const_iterator it=lines[scaleLevel].begin(); it!=lines[scaleLevel].end(); ++it){
250  l = *it;
252 
253  double fac = 1;
254  if (iter == 0)
255  {
256  for(std::list<int>::const_iterator itindex = l->Lindex_polygon.begin(); itindex!=l->Lindex_polygon.end(); ++itindex){
257  int index = *itindex;
258  if (l->hiddenface->isAppearing((unsigned int)index))
259  {
260  fac = 0.2;
261  break;
262  }
263  if(l->closeToImageBorder(_I, 10))
264  {
265  fac = 0.1;
266  break;
267  }
268  }
269  }
270 
271  std::list<vpMeSite>::const_iterator itListLine;
272  if (iter == 0 && l->meline != NULL)
273  itListLine = l->meline->getMeList().begin();
274 
275  for (unsigned int i=0 ; i < l->nbFeature ; i++)
276  {
277  for (unsigned int j=0; j < 6 ; j++)
278  {
279  L[n+i][j] = l->L[i][j]; //On remplit la matrice d'interaction globale
280  }
281  error[n+i] = l->error[i]; //On remplit la matrice d'erreur
282 
283  if (error[n+i] <= limite) count = count+1.0; //Si erreur proche de 0 on incremente cur
284 
285  w[n+i] = 0;
286 
287  if (iter == 0)
288  {
289  factor[n+i] = fac;
290  vpMeSite site = *itListLine;
291  if (site.getState() != vpMeSite::NO_SUPPRESSION) factor[n+i] = 0.2;
292  ++itListLine;
293  }
294 
295  //If pour la premiere extremite des moving edges
296  if (i == 0)
297  {
298  e_cur = l->error[0];
299  if (l->nbFeature > 1)
300  {
301  e_next = l->error[1];
302  if ( fabs(e_cur - e_next) < limite && vpMath::sign(e_cur) == vpMath::sign(e_next) )
303  {
304  w[n+i] = 1/*0.5*/;
305  }
306  e_prev = e_cur;
307  }
308  else w[n+i] = 1;
309  }
310 
311  //If pour la derniere extremite des moving edges
312  else if(i == l->nbFeature-1)
313  {
314  e_cur = l->error[i];
315  if ( fabs(e_cur - e_prev) < limite && vpMath::sign(e_cur) == vpMath::sign(e_prev) )
316  {
317  w[n+i] += 1/*0.5*/;
318  }
319  }
320 
321  else
322  {
323  e_cur = l->error[i];
324  e_next = l->error[i+1];
325  if ( fabs(e_cur - e_prev) < limite )
326  {
327  w[n+i] += 0.5;
328  }
329  if ( fabs(e_cur - e_next) < limite )
330  {
331  w[n+i] += 0.5;
332  }
333  e_prev = e_cur;
334  }
335  }
336 
337  n+= l->nbFeature ;
338  }
339 
340 
341  for(std::list<vpMbtDistanceCylinder*>::const_iterator it=cylinders[scaleLevel].begin(); it!=cylinders[scaleLevel].end(); ++it){
342  cy = *it;
344  double fac = 1.0;
345 
346  std::list<vpMeSite>::const_iterator itCyl1;
347  std::list<vpMeSite>::const_iterator itCyl2;
348  if (iter == 0 && (cy->meline1 != NULL || cy->meline2 != NULL)){
349  itCyl1 = cy->meline1->getMeList().begin();
350  itCyl2 = cy->meline2->getMeList().begin();
351  }
352 
353  for(unsigned int i=0 ; i < cy->nbFeature ; i++){
354  for(unsigned int j=0; j < 6 ; j++){
355  L[n+i][j] = cy->L[i][j]; //On remplit la matrice d'interaction globale
356  }
357  error[n+i] = cy->error[i]; //On remplit la matrice d'erreur
358 
359  if (error[n+i] <= limite) count = count+1.0; //Si erreur proche de 0 on incremente cur
360 
361  w[n+i] = 0;
362 
363  if (iter == 0)
364  {
365  factor[n+i] = fac;
366  vpMeSite site;
367  if(i<cy->nbFeaturel1) {
368  site= *itCyl1;
369  ++itCyl1;
370  }
371  else{
372  site= *itCyl2;
373  ++itCyl2;
374  }
375  if (site.getState() != vpMeSite::NO_SUPPRESSION) factor[n+i] = 0.2;
376  }
377 
378  //If pour la premiere extremite des moving edges
379  if (i == 0)
380  {
381  e_cur = cy->error[0];
382  if (cy->nbFeature > 1)
383  {
384  e_next = cy->error[1];
385  if ( fabs(e_cur - e_next) < limite && vpMath::sign(e_cur) == vpMath::sign(e_next) )
386  {
387  w[n+i] = 1/*0.5*/;
388  }
389  e_prev = e_cur;
390  }
391  else w[n+i] = 1;
392  }
393  if (i == cy->nbFeaturel1)
394  {
395  e_cur = cy->error[i];
396  if (cy->nbFeaturel2 > 1)
397  {
398  e_next = cy->error[i+1];
399  if ( fabs(e_cur - e_next) < limite && vpMath::sign(e_cur) == vpMath::sign(e_next) )
400  {
401  w[n+i] = 1/*0.5*/;
402  }
403  e_prev = e_cur;
404  }
405  else w[n+i] = 1;
406  }
407 
408  //If pour la derniere extremite des moving edges
409  else if(i == cy->nbFeaturel1-1)
410  {
411  e_cur = cy->error[i];
412  if ( fabs(e_cur - e_prev) < limite && vpMath::sign(e_cur) == vpMath::sign(e_prev) )
413  {
414  w[n+i] += 1/*0.5*/;
415  }
416  }
417  //If pour la derniere extremite des moving edges
418  else if(i == cy->nbFeature-1)
419  {
420  e_cur = cy->error[i];
421  if ( fabs(e_cur - e_prev) < limite && vpMath::sign(e_cur) == vpMath::sign(e_prev) )
422  {
423  w[n+i] += 1/*0.5*/;
424  }
425  }
426 
427  else
428  {
429  e_cur = cy->error[i];
430  e_next = cy->error[i+1];
431  if ( fabs(e_cur - e_prev) < limite ){
432  w[n+i] += 0.5;
433  }
434  if ( fabs(e_cur - e_next) < limite ){
435  w[n+i] += 0.5;
436  }
437  e_prev = e_cur;
438  }
439  }
440 
441  n+= cy->nbFeature ;
442  }
443 
444  count = count / (double)nbrow;
445  if (count < 0.85){
446  reloop = true;
447  }
448 
449  double num=0;
450  double den=0;
451 
452  double wi ; double eri ;
453  for(unsigned int i = 0; i < nerror; i++){
454  wi = w[i]*factor[i];
455  eri = error[i];
456  num += wi*vpMath::sqr(eri);
457  den += wi ;
458 
459  weighted_error[i] = wi*eri ;
460  }
461 
462  if((iter==0) || compute_interaction){
463  for (unsigned int i=0 ; i < nerror ; i++){
464  for (unsigned int j=0 ; j < 6 ; j++){
465  L[i][j] = w[i]*factor[i]*L[i][j] ;
466  }
467  }
468  }
469 
470  LTL = L.AtA();
471  computeJTR(L, weighted_error, LTR);
472  v = -0.7*LTL.pseudoInverse(LTL.getRows()*DBL_EPSILON)*LTR;
474 
475  iter++;
476  }
477 // cout << "\t First minimization in " << iter << " iteration " << endl ;
478 
479 /*** Second phase ***/
480 
481  vpRobust robust_lines(nberrors_lines);
482  vpRobust robust_cylinders(nberrors_cylinders);
483  robust_lines.setIteration(0) ;
484  robust_cylinders.setIteration(0) ;
485  iter = 0;
486  vpColVector w_lines(nberrors_lines);
487  vpColVector w_cylinders(nberrors_cylinders);
488  vpColVector error_lines(nberrors_lines);
489  vpColVector error_cylinders(nberrors_cylinders);
490 
491  vpColVector error_vec;
492  vpColVector W_true;
493  vpMatrix L_true;
494 
495  while ( ((int)((residu_1 - r)*1e8) !=0 ) && (iter<30))
496  {
497  unsigned int n = 0 ;
498  unsigned int nlines = 0;
499  unsigned int ncylinders = 0;
500  for(std::list<vpMbtDistanceLine*>::const_iterator it=lines[scaleLevel].begin(); it!=lines[scaleLevel].end(); ++it){
501  l = *it;
503  for (unsigned int i=0 ; i < l->nbFeature ; i++){
504  for (unsigned int j=0; j < 6 ; j++){
505  L[n+i][j] = l->L[i][j];
506  error[n+i] = l->error[i];
507  error_lines[nlines+i] = error[n+i];
508  }
509  }
510  n+= l->nbFeature;
511  nlines+= l->nbFeature;
512  }
513 
514  for(std::list<vpMbtDistanceCylinder*>::const_iterator it=cylinders[scaleLevel].begin(); it!=cylinders[scaleLevel].end(); ++it){
515  cy = *it;
517  for(unsigned int i=0 ; i < cy->nbFeature ; i++){
518  for(unsigned int j=0; j < 6 ; j++){
519  L[n+i][j] = cy->L[i][j];
520  error[n+i] = cy->error[i];
521  error_cylinders[ncylinders+i] = error[n+i];
522  }
523  }
524 
525  n+= cy->nbFeature ;
526  ncylinders+= cy->nbFeature ;
527  }
528 
529  if(iter==0)
530  {
531  weighted_error.resize(nerror);
532  w.resize(nerror);
533  w = 1;
534  w_lines.resize(nberrors_lines);
535  w_lines = 1;
536  w_cylinders.resize(nberrors_cylinders);
537  w_cylinders = 1;
538 
539  robust_lines.setThreshold(2/cam.get_px());
540  robust_cylinders.setThreshold(2/cam.get_px());
541  if(nberrors_lines > 0)
542  robust_lines.MEstimator(vpRobust::TUKEY, error_lines,w_lines);
543  if(nberrors_cylinders > 0){
544  robust_cylinders.MEstimator(vpRobust::TUKEY, error_cylinders,w_cylinders);
545  }
546  }
547  else
548  {
549  robust_lines.setIteration(iter);
550  robust_cylinders.setIteration(iter);
551  if(nberrors_lines > 0)
552  robust_lines.MEstimator(vpRobust::TUKEY, error_lines, w_lines);
553  if(nberrors_cylinders > 0){
554  robust_cylinders.MEstimator(vpRobust::TUKEY, error_cylinders,w_cylinders);
555  }
556  }
557 
558  unsigned int cpt = 0;
559  while(cpt<nbrow){
560  if(cpt<nberrors_lines){
561  w[cpt] = w_lines[cpt];
562  }
563  else{
564  w[cpt] = w_cylinders[cpt-nberrors_lines];
565  }
566  cpt++;
567  }
568 
569  residu_1 = r;
570 
571  double num=0;
572  double den=0;
573  double wi;
574  double eri;
575 
576  L_true = L;
577  W_true = vpColVector(nerror);
578 
579  for(unsigned int i=0; i<nerror; i++){
580  wi = w[i]*factor[i];
581  W_true[i] = wi*wi;
582  eri = error[i];
583  num += wi*vpMath::sqr(eri);
584  den += wi;
585 
586  weighted_error[i] = wi*eri ;
587  }
588 
589  r = sqrt(num/den); //Le critere d'arret prend en compte le poids
590 
591  if((iter==0)|| compute_interaction){
592  for (unsigned int i=0 ; i < nerror ; i++){
593  for (unsigned int j=0 ; j < 6 ; j++){
594  L[i][j] = w[i]*factor[i]*L[i][j];
595  }
596  }
597  }
598 
599  LTL = L.AtA();
600  computeJTR(L, weighted_error, LTR);
601  v = -lambda*LTL.pseudoInverse(LTL.getRows()*DBL_EPSILON)*LTR;
603 
604  iter++;
605  }
606 
607  if(computeCovariance){
608  vpMatrix D; //Should be the M.diag(wi) * M.diag(wi).transpose() = (M.diag(wi^2)) which is more efficient
609  D.diag(W_true);
611  }
612 
613  unsigned int n =0 ;
614  for(std::list<vpMbtDistanceLine*>::const_iterator it=lines[scaleLevel].begin(); it!=lines[scaleLevel].end(); ++it){
615  l = *it;
616  {
617  double wmean = 0 ;
618  std::list<vpMeSite>::iterator itListLine;
619  if (l->nbFeature > 0) itListLine = l->meline->getMeList().begin();
620 
621  for (unsigned int i=0 ; i < l->nbFeature ; i++){
622  wmean += w[n+i] ;
623  vpMeSite p = *itListLine;
624  if (w[n+i] < 0.5){
626 
627  *itListLine = p;
628  }
629 
630  ++itListLine;
631  }
632  n+= l->nbFeature ;
633 
634  if (l->nbFeature!=0)
635  wmean /= l->nbFeature ;
636  else
637  wmean = 1;
638 
639  l->setMeanWeight(wmean);
640 
641  if (wmean < 0.8)
642  l->Reinit = true;
643  }
644  }
645 
646 
647  // Same thing with cylinders as with lines
648  for(std::list<vpMbtDistanceCylinder*>::const_iterator it=cylinders[scaleLevel].begin(); it!=cylinders[scaleLevel].end(); ++it){
649  cy = *it;
650  double wmean = 0 ;
651  std::list<vpMeSite>::iterator itListCyl1;
652  std::list<vpMeSite>::iterator itListCyl2;
653  if (cy->nbFeature > 0){
654  itListCyl1 = cy->meline1->getMeList().begin();
655  itListCyl2 = cy->meline2->getMeList().begin();
656  }
657 
658  wmean = 0;
659  for(unsigned int i=0 ; i < cy->nbFeaturel1 ; i++){
660  wmean += w[n+i] ;
661  vpMeSite p = *itListCyl1;
662  if (w[n+i] < 0.5){
664 
665  *itListCyl1 = p;
666  }
667 
668  ++itListCyl1;
669  }
670 
671  if (cy->nbFeaturel1!=0)
672  wmean /= cy->nbFeaturel1 ;
673  else
674  wmean = 1;
675 
676  cy->setMeanWeight1(wmean);
677 
678  if (wmean < 0.8){
679  cy->Reinit = true;
680  }
681 
682  wmean = 0;
683  for(unsigned int i=cy->nbFeaturel1 ; i < cy->nbFeature ; i++){
684  wmean += w[n+i] ;
685  vpMeSite p = *itListCyl2;
686  if (w[n+i] < 0.5){
688 
689  *itListCyl2 = p;
690  }
691 
692  ++itListCyl2;
693  }
694 
695  if (cy->nbFeaturel2!=0)
696  wmean /= cy->nbFeaturel2 ;
697  else
698  wmean = 1;
699 
700  cy->setMeanWeight2(wmean);
701 
702  if (wmean < 0.8){
703  cy->Reinit = true;
704  }
705 
706  n+= cy->nbFeature ;
707  }
708 }
709 
715 void
717 {
718  int nbExpectedPoint = 0;
719  int nbGoodPoint = 0;
720  int nbBadPoint = 0;
721 
722  vpMbtDistanceLine *l ;
723  for(std::list<vpMbtDistanceLine*>::const_iterator it=lines[scaleLevel].begin(); it!=lines[scaleLevel].end(); ++it){
724  l = *it;
725  if (l->isVisible() && l->meline != NULL)
726  {
727  nbExpectedPoint += (int)l->meline->expecteddensity;
728  for(std::list<vpMeSite>::const_iterator itme=l->meline->getMeList().begin(); itme!=l->meline->getMeList().end(); ++itme){
729  vpMeSite pix = *itme;
730  if (pix.getState() == vpMeSite::NO_SUPPRESSION) nbGoodPoint++;
731  else nbBadPoint++;
732  }
733  }
734  }
735 
736 
738  for(std::list<vpMbtDistanceCylinder*>::const_iterator it=cylinders[scaleLevel].begin(); it!=cylinders[scaleLevel].end(); ++it){
739  cy = *it;
740  if (cy->meline1 !=NULL && cy->meline2 != NULL)
741  {
742  nbExpectedPoint += (int)cy->meline1->expecteddensity;
743  for(std::list<vpMeSite>::const_iterator itme1=cy->meline1->getMeList().begin(); itme1!=cy->meline1->getMeList().end(); ++itme1){
744  vpMeSite pix = *itme1;
745  if (pix.getState() == vpMeSite::NO_SUPPRESSION) nbGoodPoint++;
746  else nbBadPoint++;
747  }
748  nbExpectedPoint += (int)cy->meline2->expecteddensity;
749  for(std::list<vpMeSite>::const_iterator itme2=cy->meline2->getMeList().begin(); itme2!=cy->meline2->getMeList().end(); ++itme2){
750  vpMeSite pix = *itme2;
751  if (pix.getState() == vpMeSite::NO_SUPPRESSION) nbGoodPoint++;
752  else nbBadPoint++;
753  }
754  }
755  }
756 
757  //if (nbGoodPoint < percentageGdPt *(nbGoodPoint+nbBadPoint) || nbExpectedPoint < 2)
758  // Compare the number of good points with the min between the number of expected points and number of points that are tracked
759  if ( ( (nbGoodPoint < percentageGdPt *nbExpectedPoint) && (nbGoodPoint < percentageGdPt *(nbGoodPoint+nbBadPoint)) ) // Modif FS
760  || nbExpectedPoint < 2)
761  {
762  throw vpTrackingException(vpTrackingException::fatalError, "Not enough points to track the object");
763  }
764 }
765 
766 
774 void
776 {
777  initPyramid(I, Ipyramid);
778 
779 // for (int lvl = ((int)scales.size()-1); lvl >= 0; lvl -= 1)
780  unsigned int lvl = (unsigned int)scales.size();
781  do{
782  lvl--;
783  if(scales[lvl]){
784  vpHomogeneousMatrix cMo_1 = cMo;
785  try
786  {
787  downScale(lvl);
788 
789  try
790  {
791  trackMovingEdge(*Ipyramid[lvl]);
792  }
793  catch(...)
794  {
795  vpTRACE("Error in moving edge tracking") ;
796  throw ;
797  }
798 
799  // initialize the vector that contains the error and the matrix that contains
800  // the interaction matrix
801  vpMbtDistanceLine *l ;
802  for(std::list<vpMbtDistanceLine*>::const_iterator it=lines[lvl].begin(); it!=lines[lvl].end(); ++it){
803  l = *it;
804  if (l->isVisible()){
806  }
807  }
808 
810  for(std::list<vpMbtDistanceCylinder*>::const_iterator it=cylinders[lvl].begin(); it!=cylinders[lvl].end(); ++it){
811  cy = *it;
813  }
814 
815  try
816  {
817  computeVVS(*Ipyramid[lvl]);
818  }
819  catch(...)
820  {
821  vpTRACE("Error in computeVVS") ;
822  throw vpException(vpException::fatalError, "Error in computeVVS");
823  }
824 
825  try
826  {
827  testTracking();
828  }
829  catch(...)
830  {
831  throw vpTrackingException(vpTrackingException::fatalError, "test Tracking fail");
832  }
833 
834  if (displayFeatures)
835  {
836  if(lvl == 0){
837  for(std::list<vpMbtDistanceLine*>::const_iterator it=lines[lvl].begin(); it!=lines[lvl].end(); ++it){
838  l = *it;
839  if (l->isVisible()){
840  l->displayMovingEdges(I);
841  }
842  }
843 
844  for(std::list<vpMbtDistanceCylinder*>::const_iterator it=cylinders[lvl].begin(); it!=cylinders[lvl].end(); ++it){
845  cy = *it;
846  cy->displayMovingEdges(I);
847  }
848  }
849  }
850 
851  try
852  {
853  updateMovingEdge(I);
854  }
855  catch(...)
856  {
857  vpTRACE("Error in moving edge updating") ;
858  throw ;
859  }
860 
861  // Looking for new visible face
862  bool newvisibleface = false ;
863  visibleFace(I, cMo, newvisibleface) ;
864  initMovingEdge(I,cMo) ;
865 
866  // Reinit the moving edge for the lines which need it.
868  upScale(lvl);
869  }
870  catch(...)
871  {
872  if(lvl != 0){
873  cMo = cMo_1;
874  reInitLevel(lvl);
875  upScale(lvl);
876  }
877  else{
878  upScale(lvl);
879  throw ;
880  }
881  }
882  }
883  } while(lvl != 0);
884 
886 }
887 
894 {
895  bool a = false;
896 
897 #ifdef VISP_HAVE_OGRE
898  if(useOgre){
899  if(!faces.isOgreInitialised())
901  faces.initOgre(cam);
902  }
903 #endif
904 
905 
906  initPyramid(I, Ipyramid);
907  visibleFace(I, cMo, a);
908  unsigned int i = (unsigned int)scales.size();
909 
910  do {
911  i--;
912  if(scales[i]){
913  downScale(i);
915  upScale(i);
916  }
917  } while(i != 0);
918 
920 }
921 
931 void
933 {
934  cMo = cdMo;
935 
937  lines[scaleLevel].front() ;
938  for(std::list<vpMbtDistanceLine*>::const_iterator it=lines[scaleLevel].begin(); it!=lines[scaleLevel].end(); ++it){
939  l = *it;
940  if(l->meline != NULL){
941  delete l->meline;
942  l->meline = NULL;
943  }
944  }
945 
946  init(I);
947 }
948 
960 void
961 vpMbEdgeTracker::loadConfigFile(const std::string& configFile)
962 {
963  vpMbEdgeTracker::loadConfigFile(configFile.c_str());
964 }
965 
1016 void
1017 vpMbEdgeTracker::loadConfigFile(const char* configFile)
1018 {
1019 #ifdef VISP_HAVE_XML2
1020  vpMbtXmlParser xmlp;
1021 
1022  xmlp.setCameraParameters(cam);
1025  xmlp.setMovingEdge(me);
1026 
1027  try{
1028  std::cout << " *********** Parsing XML for Mb Edge Tracker ************ " << std::endl;
1029  xmlp.parse(configFile);
1030  }
1031  catch(...){
1032  vpERROR_TRACE("Can't open XML file \"%s\"\n ", configFile);
1033  throw vpException(vpException::ioError, "problem to parse configuration file.");
1034  }
1035 
1036  vpCameraParameters camera;
1037  vpMe meParser;
1038  xmlp.getCameraParameters(camera);
1039  xmlp.getMe(meParser);
1040 
1041  setCameraParameters(camera);
1042  setMovingEdge(meParser);
1045 
1046  if(xmlp.hasNearClippingDistance())
1048 
1049  if(xmlp.hasFarClippingDistance())
1051 
1052  if(xmlp.getFovClipping())
1054 
1055 #else
1056  vpTRACE("You need the libXML2 to read the config file %s", configFile);
1057 #endif
1058 }
1059 
1060 
1071 void
1073  const vpCameraParameters &camera, const vpColor& col,
1074  const unsigned int thickness, const bool displayFullModel)
1075 {
1076  vpMbtDistanceLine *l ;
1077 
1078  for (unsigned int i = 0; i < scales.size(); i += 1){
1079  if(scales[i]){
1080  for(std::list<vpMbtDistanceLine*>::const_iterator it=lines[scaleLevel].begin(); it!=lines[scaleLevel].end(); ++it){
1081  l = *it;
1082  l->display(I,cMo_, camera, col, thickness, displayFullModel);
1083  }
1084 
1085  for(std::list<vpMbtDistanceCylinder*>::const_iterator it=cylinders[scaleLevel].begin(); it!=cylinders[scaleLevel].end(); ++it){
1086  (*it)->display(I, cMo_, camera, col, thickness);
1087  }
1088 
1089  break ; //displaying model on one scale only
1090  }
1091  }
1092 
1093 #ifdef VISP_HAVE_OGRE
1094  if(useOgre)
1095  faces.displayOgre(cMo_);
1096 #endif
1097 }
1098 
1109 void
1111  const vpCameraParameters &camera, const vpColor& col,
1112  const unsigned int thickness, const bool displayFullModel)
1113 {
1114  vpMbtDistanceLine *l ;
1115 
1116  for (unsigned int i = 0; i < scales.size(); i += 1){
1117  if(scales[i]){
1118  for(std::list<vpMbtDistanceLine*>::const_iterator it=lines[scaleLevel].begin(); it!=lines[scaleLevel].end(); ++it){
1119  l = *it;
1120  l->display(I, cMo_, camera, col, thickness, displayFullModel) ;
1121  }
1122 
1123  for(std::list<vpMbtDistanceCylinder*>::const_iterator it=cylinders[scaleLevel].begin(); it!=cylinders[scaleLevel].end(); ++it){
1124  (*it)->display(I, cMo_, camera, col, thickness) ;
1125  }
1126 
1127  break ; //displaying model on one scale only
1128  }
1129  }
1130 
1131 #ifdef VISP_HAVE_OGRE
1132  if(useOgre)
1133  faces.displayOgre(cMo_);
1134 #endif
1135 }
1136 
1137 
1145 void
1147 {
1148  vpMbtDistanceLine *l ;
1149 
1150  lines[scaleLevel].front() ;
1151  for(std::list<vpMbtDistanceLine*>::const_iterator it=lines[scaleLevel].begin(); it!=lines[scaleLevel].end(); ++it){
1152  l = *it;
1153  bool isvisible = false ;
1154 
1155  for(std::list<int>::const_iterator itindex=l->Lindex_polygon.begin(); itindex!=l->Lindex_polygon.end(); ++itindex){
1156  int index = *itindex;
1157  if (index ==-1) isvisible =true ;
1158  else
1159  {
1160  if (l->hiddenface->isVisible((unsigned int)index)) isvisible = true ;
1161  }
1162  }
1163 
1164  //Si la ligne n'appartient a aucune face elle est tout le temps visible
1165  if (l->Lindex_polygon.empty()) isvisible = true;
1166 
1167  if (isvisible)
1168  {
1169  l->setVisible(true) ;
1170  if (l->meline==NULL)
1171  {
1172 // std::cout << "init me line "<< l->getIndex() << std::endl ;
1173  l->initMovingEdge(I, _cMo) ;
1174  }
1175  }
1176  else
1177  {
1178  l->setVisible(false) ;
1179  if (l->meline!=NULL) delete l->meline;
1180  l->meline=NULL;
1181  }
1182  }
1183 
1184 
1185  vpMbtDistanceCylinder *cy ;
1186  for(std::list<vpMbtDistanceCylinder*>::const_iterator it=cylinders[scaleLevel].begin(); it!=cylinders[scaleLevel].end(); ++it){
1187  cy = *it;
1188  if (cy->meline1==NULL || cy->meline2==NULL){
1189  cy->initMovingEdge(I, _cMo) ;
1190  }
1191  }
1192 }
1193 
1194 
1200 void
1202 {
1203  vpMbtDistanceLine *l ;
1204  for(std::list<vpMbtDistanceLine*>::const_iterator it=lines[scaleLevel].begin(); it!=lines[scaleLevel].end(); ++it){
1205  l = *it;
1206  if(l->isVisible() == true){
1207  if(l->meline == NULL){
1208  l->initMovingEdge(I, cMo);
1209  }
1210  l->trackMovingEdge(I, cMo) ;
1211  }
1212  }
1213 
1215  for(std::list<vpMbtDistanceCylinder*>::const_iterator it=cylinders[scaleLevel].begin(); it!=cylinders[scaleLevel].end(); ++it){
1216  cy = *it;
1217  if(cy->meline1 == NULL || cy->meline2 == NULL){
1218  cy->initMovingEdge(I, cMo);
1219  }
1220  cy->trackMovingEdge(I, cMo) ;
1221  }
1222 }
1223 
1224 
1230 void
1232 {
1233  vpMbtDistanceLine *l ;
1234  for(std::list<vpMbtDistanceLine*>::const_iterator it=lines[scaleLevel].begin(); it!=lines[scaleLevel].end(); ++it){
1235  l = *it;
1236  l->updateMovingEdge(I, cMo) ;
1237  if (l->nbFeature == 0 && l->isVisible()){
1238  l->Reinit = true;
1239  }
1240  }
1241 
1242 
1243  vpMbtDistanceCylinder *cy ;
1244  for(std::list<vpMbtDistanceCylinder*>::const_iterator it=cylinders[scaleLevel].begin(); it!=cylinders[scaleLevel].end(); ++it){
1245  cy = *it;
1246  cy->updateMovingEdge(I, cMo) ;
1247  if(cy->nbFeaturel1 == 0 || cy->nbFeaturel2 == 0){
1248  cy->Reinit = true;
1249  }
1250  }
1251 }
1252 
1253 
1262 void
1264 {
1265  vpMbtDistanceLine *l ;
1266  for(std::list<vpMbtDistanceLine*>::const_iterator it=lines[scaleLevel].begin(); it!=lines[scaleLevel].end(); ++it){
1267  l = *it;
1268  if (l->Reinit && l->isVisible())
1269  l->reinitMovingEdge(I, _cMo);
1270  }
1271 
1273  for(std::list<vpMbtDistanceCylinder*>::const_iterator it=cylinders[scaleLevel].begin(); it!=cylinders[scaleLevel].end(); ++it){
1274  cy = *it;
1275  if (cy->Reinit)
1276  cy->reinitMovingEdge(I, _cMo);
1277  }
1278 }
1279 
1280 
1290 bool samePoint(const vpPoint &P1, const vpPoint &P2, double threshold=1e-5)
1291 {
1292  double d = vpMath::sqr(P1.get_oX() - P2.get_oX())+
1293  vpMath::sqr(P1.get_oY() - P2.get_oY())+
1294  vpMath::sqr(P1.get_oZ() - P2.get_oZ()) ;
1295  if (d < threshold)
1296  return true ;
1297  else
1298  return false ;
1299 }
1300 
1301 
1312 void
1313 vpMbEdgeTracker::addLine(vpPoint &P1, vpPoint &P2, int polygone, std::string name)
1314 {
1315  //suppress line already in the model
1316 
1317  bool already_here = false ;
1318  vpMbtDistanceLine *l ;
1319 
1320  for (unsigned int i = 0; i < scales.size(); i += 1){
1321  if(scales[i]){
1322  downScale(i);
1323  for(std::list<vpMbtDistanceLine*>::const_iterator it=lines[i].begin(); it!=lines[i].end(); ++it){
1324  l = *it;
1325  if((samePoint(*(l->p1),P1) && samePoint(*(l->p2),P2)) ||
1326  (samePoint(*(l->p1),P2) && samePoint(*(l->p2),P1)) ){
1327  already_here = true ;
1328  l->Lindex_polygon.push_back(polygone);
1329  l->hiddenface = &faces ;
1330  }
1331  }
1332 
1333  if (!already_here){
1334  l = new vpMbtDistanceLine ;
1335 
1336  l->setCameraParameters(cam) ;
1337  l->buildFrom(P1,P2) ;
1338  l->Lindex_polygon.push_back(polygone);
1339  l->setMovingEdge(&me) ;
1340  l->hiddenface = &faces ;
1341  l->setIndex(nline) ;
1342  l->setName(name);
1343 
1346 
1347  if((clippingFlag & vpMbtPolygon::NEAR_CLIPPING) == vpMbtPolygon::NEAR_CLIPPING)
1349 
1350  if((clippingFlag & vpMbtPolygon::FAR_CLIPPING) == vpMbtPolygon::FAR_CLIPPING)
1352 
1353  nline +=1 ;
1354  lines[i].push_back(l);
1355  }
1356  upScale(i);
1357  }
1358  }
1359 }
1360 
1366 void
1367 vpMbEdgeTracker::removeLine(const std::string& name)
1368 {
1369  vpMbtDistanceLine *l;
1370 
1371  for(unsigned int i=0; i<scales.size(); i++){
1372  if(scales[i]){
1373  for(std::list<vpMbtDistanceLine*>::iterator it=lines[i].begin(); it!=lines[i].end(); ++it){
1374  l = *it;
1375  if (name.compare(l->getName()) == 0){
1376  lines[i].erase(it);
1377  break;
1378  }
1379  }
1380  }
1381  }
1382 }
1383 
1384 
1385 
1386 
1395 void
1396 vpMbEdgeTracker::addCylinder(const vpPoint &P1, const vpPoint &P2, const double r, const std::string& name)
1397 {
1398  bool already_here = false ;
1399  vpMbtDistanceCylinder *cy ;
1400 
1401  for (unsigned int i = 0; i < scales.size(); i += 1){
1402  if(scales[i]){
1403  downScale(i);
1404  for(std::list<vpMbtDistanceCylinder*>::const_iterator it=cylinders[i].begin(); it!=cylinders[i].end(); ++it){
1405  cy = *it;
1406  if((samePoint(*(cy->p1),P1) && samePoint(*(cy->p2),P2)) ||
1407  (samePoint(*(cy->p1),P2) && samePoint(*(cy->p2),P1)) ){
1408  already_here = (std::fabs(cy->radius - r) < std::numeric_limits<double>::epsilon() * vpMath::maximum(cy->radius, r));
1409  }
1410  }
1411 
1412  if (!already_here){
1413  cy = new vpMbtDistanceCylinder ;
1414 
1415  cy->setCameraParameters(cam);
1416  cy->buildFrom(P1, P2, r);
1417  cy->setMovingEdge(&me);
1418  cy->setIndex(ncylinder);
1419  cy->setName(name);
1420  ncylinder +=1;
1421  cylinders[i].push_back(cy);
1422  }
1423  upScale(i);
1424  }
1425  }
1426 }
1427 
1428 
1434 void
1435 vpMbEdgeTracker::removeCylinder(const std::string& name)
1436 {
1438 
1439  for(unsigned int i=0; i<scales.size(); i++){
1440  if(scales[i]){
1441  for(std::list<vpMbtDistanceCylinder*>::iterator it=cylinders[i].begin(); it!=cylinders[i].end(); ++it){
1442  cy = *it;
1443  if (name.compare(cy->getName()) == 0){
1444  cylinders[i].erase(it);
1445  break;
1446  }
1447  }
1448  }
1449  }
1450 }
1451 
1457 void
1459 {
1460  p.setIndex(index_polygon) ;
1461  faces.addPolygon(&p) ;
1462 
1463  unsigned int nbpt = p.getNbPoint() ;
1464  if(nbpt > 0){
1465  for (unsigned int i=0 ; i < nbpt-1 ; i++)
1466  addLine(p.p[i], p.p[i+1], index_polygon) ;
1467  addLine(p.p[nbpt-1], p.p[0], index_polygon) ;
1468  }
1469 
1470  index_polygon++ ;
1471 }
1472 
1473 
1474 #ifdef VISP_BUILD_DEPRECATED_FUNCTIONS
1475 
1486 void
1487 vpMbEdgeTracker::visibleFace(const vpHomogeneousMatrix &_cMo, bool &newvisibleline)
1488 {
1489  unsigned int n ;
1490 
1491  if(!useOgre)
1492  n = faces.setVisible(_cMo) ;
1493  else{
1494 #ifdef VISP_HAVE_OGRE
1495  bool changed = false;
1496  n = faces.setVisibleOgre(_cMo, vpMath::rad(70), vpMath::rad(70), changed);
1497 #else
1498  n = faces.setVisible(_cMo) ;
1499 #endif
1500  }
1501 
1502 // cout << "visible face " << n << endl ;
1503  if (n > nbvisiblepolygone)
1504  {
1505  //cout << "une nouvelle face est visible " << endl ;
1506  newvisibleline = true ;
1507  }
1508  else
1509  newvisibleline = false ;
1510 
1511  nbvisiblepolygone= n ;
1512 }
1513 #endif //VISP_BUILD_DEPRECATED_FUNCTIONS
1514 
1525 void
1527  const vpHomogeneousMatrix &_cMo, bool &newvisibleline)
1528 {
1529  unsigned int n ;
1530  bool changed = false;
1531 
1532  if(!useOgre) {
1533  //n = faces.setVisible(_I, cam, _cMo, vpMath::rad(89), vpMath::rad(89), changed) ;
1534  n = faces.setVisible(_I, cam, _cMo, angleAppears, angleDisappears, changed) ;
1535  }
1536  else{
1537 #ifdef VISP_HAVE_OGRE
1538  n = faces.setVisibleOgre(_I, cam, _cMo, angleAppears, angleDisappears, changed);
1539 #else
1540  n = faces.setVisible(_I, cam, _cMo, angleAppears, angleDisappears, changed) ;
1541 #endif
1542  }
1543 
1544 // cout << "visible face " << n << endl ;
1545  if (n > nbvisiblepolygone)
1546  {
1547  //cout << "une nouvelle face est visible " << endl ;
1548  newvisibleline = true ;
1549  }
1550  else
1551  newvisibleline = false ;
1552 
1553  nbvisiblepolygone= n ;
1554 }
1555 
1556 
1565 void
1567 {
1568  std::string model(file);
1569  vpMbTracker::loadModel(model);
1570 }
1571 
1580 void
1581 vpMbEdgeTracker::loadModel(const std::string &file)
1582 {
1583  vpMbTracker::loadModel(file);
1584 }
1585 
1594 void
1595 vpMbEdgeTracker::initFaceFromCorners(const std::vector<vpPoint>& _corners, const unsigned int _indexFace)
1596 {
1597  vpMbtPolygon *polygon = NULL;
1598  polygon = new vpMbtPolygon;
1599  polygon->setNbPoint((unsigned int)_corners.size());
1600  polygon->setIndex((int)_indexFace);
1601  for(unsigned int j = 0; j < _corners.size(); j++) {
1602  polygon->addPoint(j, _corners[j]);
1603  }
1604  addPolygon(*polygon);
1605 
1606  delete polygon;
1607  polygon = NULL;
1608 }
1609 
1619 void
1620 vpMbEdgeTracker::initCylinder(const vpPoint& p1, const vpPoint &p2, const double radius, const unsigned int indexCylinder)
1621 {
1622  if(indexCylinder != 0){
1623  ncylinder = indexCylinder;
1624  }
1625  addCylinder(p1, p2, radius);
1626 }
1627 
1633 void
1635 {
1636  this->cMo.setIdentity();
1637  vpMbtDistanceLine *l;
1639 
1640  for (unsigned int i = 0; i < scales.size(); i += 1){
1641  if(scales[i]){
1642  for(std::list<vpMbtDistanceLine*>::const_iterator it=lines[i].begin(); it!=lines[i].end(); ++it){
1643  l = *it;
1644  if (l!=NULL) delete l ;
1645  l = NULL ;
1646  }
1647 
1648  for(std::list<vpMbtDistanceCylinder*>::const_iterator it=cylinders[i].begin(); it!=cylinders[i].end(); ++it){
1649  cy = *it;
1650  if (cy!=NULL) delete cy;
1651  cy = NULL;
1652  }
1653  lines[i].clear();
1654  cylinders[i].clear();
1655  }
1656  }
1657 
1658  faces.reset();
1659 
1660  index_polygon =0;
1662  nline = 0;
1663  ncylinder = 0;
1664  lambda = 1;
1665  nbvisiblepolygone = 0;
1666  percentageGdPt = 0.4;
1667 
1668  angleAppears = vpMath::rad(89);
1671 
1672  // reinitialization of the scales.
1673  this->setScales(scales);
1674 }
1675 
1676 
1677 
1685 void
1687  const vpHomogeneousMatrix& cMo_)
1688 {
1689  this->cMo.setIdentity();
1690  vpMbtDistanceLine *l;
1692 
1693  for (unsigned int i = 0; i < scales.size(); i += 1){
1694  if(scales[i]){
1695  for(std::list<vpMbtDistanceLine*>::const_iterator it=lines[i].begin(); it!=lines[i].end(); ++it){
1696  l = *it;
1697  if (l!=NULL) delete l ;
1698  l = NULL ;
1699  }
1700 
1701  for(std::list<vpMbtDistanceCylinder*>::const_iterator it=cylinders[i].begin(); it!=cylinders[i].end(); ++it){
1702  cy = *it;
1703  if (cy!=NULL) delete cy;
1704  cy = NULL;
1705  }
1706  lines[i].clear();
1707  cylinders[i].clear();
1708  }
1709  }
1710 
1711  faces.reset();
1712 
1713  index_polygon =0;
1714  //compute_interaction=1;
1715  nline = 0;
1716  ncylinder = 0;
1717  //lambda = 1;
1718  nbvisiblepolygone = 0;
1719 
1720  loadModel(cad_name);
1721  initFromPose(I, cMo_);
1722 }
1723 
1734 unsigned int
1735 vpMbEdgeTracker::getNbPoints(const unsigned int level) const
1736 {
1737  if((level > scales.size()) || !scales[level]){
1738  throw vpException(vpException::dimensionError, "Level is not used");
1739  }
1740 
1741  unsigned int nbGoodPoints = 0;
1742  vpMbtDistanceLine *l ;
1743  for(std::list<vpMbtDistanceLine*>::const_iterator it=lines[level].begin(); it!=lines[level].end(); ++it){
1744  l = *it;
1745  if (l->isVisible() && l->meline != NULL)
1746  {
1747  for(std::list<vpMeSite>::const_iterator itme=l->meline->getMeList().begin(); itme!=l->meline->getMeList().end(); ++itme){
1748  if (itme->getState() == vpMeSite::NO_SUPPRESSION) nbGoodPoints++;
1749  }
1750  }
1751  }
1752 
1753  vpMbtDistanceCylinder *cy ;
1754  for(std::list<vpMbtDistanceCylinder*>::const_iterator it=cylinders[level].begin(); it!=cylinders[level].end(); ++it){
1755  cy = *it;
1756  if (cy->meline1 != NULL || cy->meline2 != NULL)
1757  {
1758  for(std::list<vpMeSite>::const_iterator itme1=cy->meline1->getMeList().begin(); itme1!=cy->meline1->getMeList().end(); ++itme1){
1759  if (itme1->getState() == vpMeSite::NO_SUPPRESSION) nbGoodPoints++;
1760  }
1761  for(std::list<vpMeSite>::const_iterator itme2=cy->meline2->getMeList().begin(); itme2!=cy->meline2->getMeList().end(); ++itme2){
1762  if (itme2->getState() == vpMeSite::NO_SUPPRESSION) nbGoodPoints++;
1763  }
1764  }
1765  }
1766 
1767  return nbGoodPoints;
1768 }
1769 
1770 
1780 vpMbtPolygon*
1781 vpMbEdgeTracker::getPolygon(const unsigned int index)
1782 {
1783  if(index >= static_cast<unsigned int>(faces.size()) ){
1784  throw vpException(vpException::dimensionError, "index out of range");
1785  }
1786 
1787  return faces[index];
1788 }
1789 
1795 unsigned int
1797 {
1798  return static_cast<unsigned int>(faces.size());
1799 }
1800 
1821 void
1822 vpMbEdgeTracker::setScales(const std::vector<bool>& scale)
1823 {
1824  unsigned int nbActivatedLevels = 0;
1825  for (unsigned int i = 0; i < scale.size(); i += 1){
1826  if(scale[i]){
1827  nbActivatedLevels++;
1828  }
1829  }
1830  if((scale.size() < 1) || (nbActivatedLevels == 0)){
1831  vpERROR_TRACE(" !! WARNING : must use at least one level for the tracking. Use the global one");
1832  this->scales.resize(0);
1833  this->scales.push_back(true);
1834  lines.resize(1);
1835  lines[0].clear();
1836  cylinders.resize(1);
1837  cylinders[0].clear();
1838  }
1839  else{
1840  this->scales = scale;
1841  lines.resize(scale.size());
1842  cylinders.resize(scale.size());
1843  for (unsigned int i = 0; i < lines.size(); i += 1){
1844  lines[i].clear();
1845  cylinders[i].clear();
1846  }
1847  }
1848 }
1849 
1855 void
1857 {
1858  if( (clippingFlag & vpMbtPolygon::NEAR_CLIPPING) == vpMbtPolygon::NEAR_CLIPPING && dist <= distNearClip)
1859  vpTRACE("Far clipping value cannot be inferior than near clipping value. Far clipping won't be considered.");
1860  else if ( dist < 0 )
1861  vpTRACE("Far clipping value cannot be inferior than 0. Far clipping won't be considered.");
1862  else{
1863  distFarClip = dist;
1865  vpMbtDistanceLine *l;
1866 
1867  for (unsigned int i = 0; i < scales.size(); i += 1){
1868  if(scales[i]){
1869  for(std::list<vpMbtDistanceLine*>::const_iterator it=lines[i].begin(); it!=lines[i].end(); ++it){
1870  l = *it;
1872  }
1873  }
1874  }
1875  }
1876 }
1877 
1883 void
1885 {
1886  if( (clippingFlag & vpMbtPolygon::FAR_CLIPPING) == vpMbtPolygon::FAR_CLIPPING && dist >= distFarClip)
1887  vpTRACE("Near clipping value cannot be superior than far clipping value. Near clipping won't be considered.");
1888  else if ( dist < 0 )
1889  vpTRACE("Near clipping value cannot be inferior than 0. Near clipping won't be considered.");
1890  else{
1891  distNearClip = dist;
1893  vpMbtDistanceLine *l;
1894 
1895  for (unsigned int i = 0; i < scales.size(); i += 1){
1896  if(scales[i]){
1897  for(std::list<vpMbtDistanceLine*>::const_iterator it=lines[i].begin(); it!=lines[i].end(); ++it){
1898  l = *it;
1900  }
1901  }
1902  }
1903  }
1904 }
1905 
1913 void
1914 vpMbEdgeTracker::setClipping(const unsigned int &flags)
1915 {
1916  clippingFlag = flags;
1917 
1918  vpMbtDistanceLine *l;
1919 
1920  for (unsigned int i = 0; i < scales.size(); i += 1){
1921  if(scales[i]){
1922  for(std::list<vpMbtDistanceLine*>::const_iterator it=lines[i].begin(); it!=lines[i].end(); ++it){
1923  l = *it;
1925  }
1926  }
1927  }
1928 }
1929 
1944 void
1946 {
1947  _pyramid.resize(scales.size());
1948 
1949  if(scales[0]){
1950  _pyramid[0] = &_I;
1951  }
1952  else{
1953  _pyramid[0] = NULL;
1954  }
1955 
1956  for(unsigned int i=1; i<_pyramid.size(); i += 1){
1957  if(scales[i]){
1958  unsigned int cScale = static_cast<unsigned int>(pow(2., (int)i));
1959  vpImage<unsigned char>* I = new vpImage<unsigned char>(_I.getHeight() / cScale, _I.getWidth() / cScale);
1960 #ifdef VISP_HAVE_OPENCV
1961  IplImage* vpI0 = cvCreateImageHeader(cvSize((int)_I.getWidth(), (int)_I.getHeight()), IPL_DEPTH_8U, 1);
1962  vpI0->imageData = (char*)(_I.bitmap);
1963  IplImage* vpI = cvCreateImage(cvSize((int)(_I.getWidth() / cScale), (int)(_I.getHeight() / cScale)), IPL_DEPTH_8U, 1);
1964  cvResize(vpI0, vpI, CV_INTER_NN);
1965  vpImageConvert::convert(vpI, *I);
1966  cvReleaseImage(&vpI);
1967  vpI0->imageData = NULL;
1968  cvReleaseImageHeader(&vpI0);
1969 #else
1970  for (unsigned int k = 0, ii = 0; k < I->getHeight(); k += 1, ii += cScale){
1971  for (unsigned int l = 0, jj = 0; l < I->getWidth(); l += 1, jj += cScale){
1972  (*I)[k][l] = _I[ii][jj];
1973  }
1974  }
1975 #endif
1976  _pyramid[i] = I;
1977  }
1978  else{
1979  _pyramid[i] = NULL;
1980  }
1981  }
1982 }
1983 
1990 void
1992 {
1993  if(_pyramid.size() > 0){
1994  _pyramid[0] = NULL;
1995  for (unsigned int i = 1; i < _pyramid.size(); i += 1){
1996  if(_pyramid[i] != NULL){
1997  delete _pyramid[i];
1998  _pyramid[i] = NULL;
1999  }
2000  }
2001  _pyramid.resize(0);
2002  }
2003 }
2004 
2015 void
2016 vpMbEdgeTracker::getLline(std::list<vpMbtDistanceLine *>& linesList, const unsigned int level)
2017 {
2018  if(level > scales.size() || !scales[level]){
2019  std::ostringstream oss;
2020  oss << level;
2021  std::string errorMsg = "level " + oss.str() + " is not used, cannot get its distance lines.";
2022  throw vpException(vpException::dimensionError, errorMsg);
2023  }
2024 
2025  linesList = lines[level];
2026 }
2027 
2028 
2039 void
2040 vpMbEdgeTracker::getLcylinder(std::list<vpMbtDistanceCylinder *>& cylindersList, const unsigned int level)
2041 {
2042  if(level > scales.size() || !scales[level]){
2043  std::ostringstream oss;
2044  oss << level;
2045  std::string errorMsg = "level " + oss.str() + " is not used, cannot get its distance lines.";
2046  throw vpException(vpException::dimensionError, errorMsg);
2047  }
2048 
2049  cylindersList = cylinders[level];
2050 }
2051 
2052 
2059 void
2060 vpMbEdgeTracker::downScale(const unsigned int _scale)
2061 {
2062  const double ratio = pow(2., (int)_scale);
2063  scaleLevel = _scale;
2064 
2065  vpMatrix K = cam.get_K();
2066 
2067  K[0][0] /= ratio;
2068  K[1][1] /= ratio;
2069  K[0][2] /= ratio;
2070  K[1][2] /= ratio;
2071 
2073 }
2074 
2081 void
2082 vpMbEdgeTracker::upScale(const unsigned int _scale)
2083 {
2084  const double ratio = pow(2., (int)_scale);
2085  scaleLevel = 0;
2086 
2087  vpMatrix K = cam.get_K();
2088 
2089  K[0][0] *= ratio;
2090  K[1][1] *= ratio;
2091  K[0][2] *= ratio;
2092  K[1][2] *= ratio;
2093 
2095 }
2096 
2104 void
2105 vpMbEdgeTracker::reInitLevel(const unsigned int _lvl)
2106 {
2107  unsigned int scaleLevel_1 = scaleLevel;
2108  scaleLevel = _lvl;
2109 
2110  vpMbtDistanceLine *l;
2111  for(std::list<vpMbtDistanceLine*>::const_iterator it=lines[scaleLevel].begin(); it!=lines[scaleLevel].end(); ++it){
2112  l = *it;
2113  l->reinitMovingEdge(*Ipyramid[_lvl], cMo);
2114  }
2115 
2116 
2118  for(std::list<vpMbtDistanceCylinder*>::const_iterator it=cylinders[scaleLevel].begin(); it!=cylinders[scaleLevel].end(); ++it){
2119  cy = *it;
2120  cy->reinitMovingEdge(*Ipyramid[_lvl], cMo);
2121  }
2122 
2123  trackMovingEdge(*Ipyramid[_lvl]);
2124  updateMovingEdge(*Ipyramid[_lvl]);
2125  scaleLevel = scaleLevel_1;
2126 }
2127 
void setWindowName(const Ogre::String &n)
Definition: vpAROgre.h:234
double distFarClip
Distance for near clipping.
unsigned int ncylinder
Index of the cylinder to add, and total number of polygon extracted so far.
Definition of the vpMatrix class.
Definition: vpMatrix.h:98
void displayMovingEdges(const vpImage< unsigned char > &I)
vpMatrix covarianceMatrix
Covariance matrix.
Definition: vpMbTracker.h:118
void initFromCalibrationMatrix(const vpMatrix &_K)
void updateMovingEdge(const vpImage< unsigned char > &I, const vpHomogeneousMatrix &cMo)
void setFarClippingDistance(const double &dist)
Definition: vpMbtPolygon.h:208
void setMovingEdge(const vpMe &me)
void setClipping(const unsigned int &flags)
Definition: vpMbtPolygon.h:201
void setVisible(bool _isvisible)
void trackMovingEdge(const vpImage< unsigned char > &I, const vpHomogeneousMatrix &cMo)
void upScale(const unsigned int _scale)
std::string getName() const
void updateMovingEdge(const vpImage< unsigned char > &I, const vpHomogeneousMatrix &cMo)
void MEstimator(const vpRobustEstimatorType method, const vpColVector &residues, vpColVector &weights)
Compute the weights according a residue vector and a PsiFunction.
Definition: vpRobust.cpp:136
bool isAppearing(const unsigned int i)
unsigned int getWidth() const
Definition: vpImage.h:159
static void convert(const vpImage< unsigned char > &src, vpImage< vpRGBa > &dest)
void getCameraParameters(vpCameraParameters &_cam) const
bool Reinit
Indicates if the line has to be reinitialized.
void setMeanWeight2(const double wmean)
void computeVVS(const vpImage< unsigned char > &_I)
The class provides a data structure for the homogeneous matrices as well as a set of operations on th...
#define vpERROR_TRACE
Definition: vpDebug.h:395
void init(const vpImage< unsigned char > &I)
void track(const vpImage< unsigned char > &I)
#define vpTRACE
Definition: vpDebug.h:418
double lambda
The gain of the virtual visual servoing stage.
unsigned int scaleLevel
Current scale level used. This attribute must not be modified outside of the downScale() and upScale(...
std::list< int > Lindex_polygon
Index of the faces which contain the line.
Type * bitmap
points toward the bitmap
Definition: vpImage.h:120
void setCameraParameters(const vpCameraParameters &camera)
void setIdentity()
Basic initialisation (identity)
Performs search in a given direction(normal) for a given distance(pixels) for a given 'site'...
Definition: vpMeSite.h:76
Class to define colors available for display functionnalities.
Definition: vpColor.h:125
Parse an Xml file to extract configuration parameters of a mbtConfig object.Data parser for the model...
void trackMovingEdge(const vpImage< unsigned char > &I, const vpHomogeneousMatrix &cMo)
void setBackgroundSizeOgre(const unsigned int &h, const unsigned int &w)
vpHomogeneousMatrix cMo
The current pose.
Definition: vpMbTracker.h:108
vpPoint * p1
The first extremity.
double distNearClip
Distance for near clipping.
void displayMovingEdges(const vpImage< unsigned char > &I)
double getNearClippingDistance() const
virtual ~vpMbEdgeTracker()
double get_oY() const
Get the point Y coordinate in the object frame.
Definition: vpPoint.h:129
void getMe(vpMe &_ecm) const
error that can be emited by ViSP classes.
Definition: vpException.h:76
void computeJTR(const vpMatrix &J, const vpColVector &R, vpMatrix &JTR)
Manage a cylinder used in the model-based tracker.
void reInitLevel(const unsigned int _lvl)
Contains predetermined masks for sites and holds moving edges tracking parameters.
Definition: vpMe.h:70
Manage the line of a polygon used in the model-based tracker.
unsigned int nbFeature
The number of moving edges.
Provides simple mathematics computation tools that are not available in the C mathematics library (ma...
Definition: vpMath.h:83
virtual void setPose(const vpImage< unsigned char > &I, const vpHomogeneousMatrix &cdMo)
std::vector< const vpImage< unsigned char > * > Ipyramid
Pyramid of image associated to the current image. This pyramid is computed in the init() and in the t...
virtual void initCylinder(const vpPoint &p1, const vpPoint &p2, const double radius, const unsigned int indexCylinder=0)
void getLcylinder(std::list< vpMbtDistanceCylinder * > &cylindersList, const unsigned int level=0)
void setIndex(const unsigned int i)
virtual void setCameraParameters(const vpCameraParameters &camera)
virtual void initFromPose(const vpImage< unsigned char > &I, const std::string &initFile)
unsigned int setVisibleOgre(const vpImage< unsigned char > &I, const vpCameraParameters &cam, const vpHomogeneousMatrix &cMo, const double &angleAppears, const double &angleDisappears, bool &changed)
void removeCylinder(const std::string &name)
vpMbtPolygon & getPolygon()
bool computeCovariance
Flag used to specify if the covariance matrix has to be computed or not.
Definition: vpMbTracker.h:116
double angleDisappears
Angle used to detect a face disappearance.
void loadConfigFile(const std::string &configFile)
vpMe me
The moving edges parameters.
void updateMovingEdge(const vpImage< unsigned char > &I)
std::vector< std::list< vpMbtDistanceLine * > > lines
Vector of list of all the lines tracked (each line is linked to a list of moving edges). Each element of the vector is for a scale (element 0 = level 0 = no subsampling).
unsigned int getNbPoints(const unsigned int level=0) const
void setNearClippingDistance(const double &dist)
Definition: vpMbtPolygon.h:223
vpPoint * p1
The first extremity on the axe.
static vpMatrix computeCovarianceMatrix(const vpMatrix &A, const vpColVector &x, const vpColVector &b)
bool useOgre
Use Ogre3d for visibility tests.
unsigned int nbFeature
The number of moving edges.
void downScale(const unsigned int _scale)
bool hasNearClippingDistance() const
Class that defines what is a point.
Definition: vpPoint.h:65
double expecteddensity
Definition: vpMbtMeLine.h:74
vpMatrix L
The interaction matrix.
vpMeSiteState getState() const
Definition: vpMeSite.h:202
void display(const vpImage< unsigned char > &I, const vpHomogeneousMatrix &cMo, const vpCameraParameters &cam, const vpColor col, const unsigned int thickness=1, const bool displayFullModel=false)
void addLine(vpPoint &p1, vpPoint &p2, int polygone=-1, std::string name="")
vpCameraParameters cam
The camera parameters.
Definition: vpMbTracker.h:106
unsigned int setVisible(const vpImage< unsigned char > &I, const vpCameraParameters &cam, const vpHomogeneousMatrix &cMo, const double &angle, bool &changed)
static Type maximum(const Type &a, const Type &b)
Definition: vpMath.h:137
virtual void setNearClippingDistance(const double &dist)
double getFarClippingDistance() const
void initOgre(const vpCameraParameters &cam=vpCameraParameters())
unsigned int nbFeaturel1
The number of moving edges on line 1.
bool hasFarClippingDistance() const
int index_polygon
Index of the polygon to add, and total number of polygon extracted so far. Cannot be unsigned because...
void addPoint(const unsigned int n, const vpPoint &P)
vpAROgre * getOgreContext()
void reinitMovingEdge(const vpImage< unsigned char > &I, const vpHomogeneousMatrix &cMo)
std::vector< bool > scales
Vector of scale level to use for the multi-scale tracking.
void getLline(std::list< vpMbtDistanceLine * > &linesList, const unsigned int level=0)
Error that can be emited by the vpTracker class and its derivates.
double getAngleDisappear() const
Implementation of a polygon of the model used by the model-based tracker.
Definition: vpMbtPolygon.h:67
void initMovingEdge(const vpImage< unsigned char > &I, const vpHomogeneousMatrix &_cMo)
vpPoint * p2
The second extremity.
void reinitMovingEdge(const vpImage< unsigned char > &I, const vpHomogeneousMatrix &cMo)
static double sqr(double x)
Definition: vpMath.h:106
void setAngleDisappear(const double &adisappear)
vpColVector error
The error vector.
bool isVisible() const
Generic class defining intrinsic camera parameters.
virtual void loadModel(const std::string &modelFile)
double get_oZ() const
Get the point Z coordinate in the object frame.
Definition: vpPoint.h:131
void setIndex(const unsigned int i)
double percentageGdPt
Percentage of good points over total number of points below which tracking is supposed to have failed...
void initPyramid(const vpImage< unsigned char > &_I, std::vector< const vpImage< unsigned char > * > &_pyramid)
void cleanPyramid(std::vector< const vpImage< unsigned char > * > &_pyramid)
vpMbtMeLine * meline1
The moving edge containers (first line of the cylinder)
double angleAppears
Angle used to detect a face appearance.
virtual void setFarClippingDistance(const double &dist)
virtual void initFaceFromCorners(const std::vector< vpPoint > &_corners, const unsigned int _indexFace=-1)
std::list< vpMeSite > & getMeList()
Definition: vpMeTracker.h:161
void reInitModel(const vpImage< unsigned char > &I, const char *cad_name, const vpHomogeneousMatrix &cMo)
void setCameraParameters(const vpCameraParameters &_cam)
void addPolygon(PolygonType *p)
void setState(const vpMeSiteState &flag)
Definition: vpMeSite.h:189
void reinitMovingEdge(const vpImage< unsigned char > &I, const vpHomogeneousMatrix &_cMo)
double get_px() const
static double rad(double deg)
Definition: vpMath.h:100
void parse(const char *filename)
void setMeanWeight1(const double wmean)
void diag(const vpColVector &A)
Definition: vpMatrix.cpp:2572
virtual void setOgreVisibilityTest(const bool &v)
unsigned int size() const
void setScales(const std::vector< bool > &_scales)
vpPoint * p2
The second extremity on the axe.
void setCameraParameters(const vpCameraParameters &camera)
double get_oX() const
Get the point X coordinate in the object frame.
Definition: vpPoint.h:127
bool closeToImageBorder(const vpImage< unsigned char > &I, const unsigned int threshold)
vpMatrix get_K() const
static double deg(double rad)
Definition: vpMath.h:93
bool displayFeatures
If true, the features are displayed.
Definition: vpMbTracker.h:120
void initMovingEdge(const vpImage< unsigned char > &I, const vpHomogeneousMatrix &cMo)
void buildFrom(const vpPoint &_p1, const vpPoint &_p2, const double r)
Class that provides a data structure for the column vectors as well as a set of operations on these v...
Definition: vpColVector.h:72
std::vector< std::list< vpMbtDistanceCylinder * > > cylinders
Vector of the tracked cylinders.
void setAngleAppear(const double &aappear)
void setMovingEdge(vpMe *Me)
void computeInteractionMatrixError(const vpHomogeneousMatrix &cMo)
vpHomogeneousMatrix inverse() const
vpMbHiddenFaces< vpMbtPolygon > * hiddenface
Pointer to the list of faces.
static vpHomogeneousMatrix direct(const vpColVector &v)
void addCylinder(const vpPoint &P1, const vpPoint &P2, const double r, const std::string &name="")
bool isVisible(const unsigned int i)
Contains an M-Estimator and various influence function.
Definition: vpRobust.h:63
unsigned int nbvisiblepolygone
Number of polygon (face) currently visible.
void display(const vpImage< unsigned char > &I, const vpHomogeneousMatrix &cMo, const vpCameraParameters &cam, const vpColor &col, const unsigned int thickness=1, const bool displayFullModel=false)
void visibleFace(const vpImage< unsigned char > &_I, const vpHomogeneousMatrix &_cMo, bool &newvisibleline)
unsigned int getHeight() const
Definition: vpImage.h:150
unsigned int getNbPolygon() const
void setMeanWeight(const double w_mean)
vpColVector error
The error vector.
vpMatrix pseudoInverse(double svThreshold=1e-6) const
Compute the pseudo inverse of the matrix using the SVD.
Definition: vpMatrix.cpp:1861
bool Reinit
Indicates if the line has to be reinitialized.
vpMbHiddenFaces< vpMbtPolygon > faces
Set of faces describing the object.
double radius
The radius of the cylinder.
unsigned int getNbPoint() const
Definition: vpMbtPolygon.h:156
unsigned int nline
Index of the polygon to add, and total number of polygon extracted so far.
void addPolygon(vpMbtPolygon &p)
void setName(const std::string line_name)
void trackMovingEdge(const vpImage< unsigned char > &I)
void displayOgre(const vpHomogeneousMatrix &cMo)
unsigned int clippingFlag
Flags specifying which clipping to used.
void loadModel(const std::string &cad_name)
double getAngleAppear() const
virtual void setClipping(const unsigned int &flags)
unsigned int nbFeaturel2
The number of moving edges on line 2.
void setThreshold(const double noise_threshold)
Definition: vpRobust.h:128
unsigned int getRows() const
Return the number of rows of the matrix.
Definition: vpMatrix.h:161
void initMovingEdge(const vpImage< unsigned char > &I, const vpHomogeneousMatrix &cMo)
void setName(const std::string &cyl_name)
static int sign(double x)
Definition: vpMath.h:248
virtual void setNbPoint(const unsigned int nb)
vpMbtMeLine * meline2
The moving edge containers (second line of the cylinder)
void removeLine(const std::string &name)
bool getFovClipping() const
void setIteration(const unsigned int iter)
Set iteration.
Definition: vpRobust.h:122
vpMatrix L
The interaction matrix.
void computeInteractionMatrixError(const vpHomogeneousMatrix &cMo, const vpImage< unsigned char > &I)
void setMovingEdge(const vpMe &_ecm)
std::string getName() const
vpMbtMeLine * meline
The moving edge container.
vpMbtPolygon * getPolygon(const unsigned int index)
void buildFrom(vpPoint &_p1, vpPoint &_p2)
void resize(const unsigned int i, const bool flagNullify=true)
Definition: vpColVector.h:94
virtual void setIndex(const int i)
Definition: vpMbtPolygon.h:215
vpPoint * p
corners in the object frame
Definition: vpMbtPolygon.h:95