ViSP  2.10.0
vpMbTracker.cpp
1 /****************************************************************************
2  *
3  * $Id: vpMbTracker.cpp 5285 2015-02-09 14:32:54Z 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  * Contact visp@irisa.fr if any conditions of this licensing are
34  * not clear to you.
35  *
36  * Description:
37  * Generic model based tracker
38  *
39  * Authors:
40  * Romain Tallonneau
41  * Aurelien Yol
42  * Eric Marchand
43  *
44  *****************************************************************************/
45 
51 #include <iostream>
52 #include <limits>
53 #include <algorithm>
54 #include <map>
55 
56 #include <visp/vpMatrix.h>
57 #include <visp/vpMath.h>
58 #include <visp/vpColVector.h>
59 #include <visp/vpPoint.h>
60 #include <visp/vpPose.h>
61 #include <visp/vpDisplay.h>
62 #include <visp/vpDisplayOpenCV.h>
63 #include <visp/vpDisplayX.h>
64 #include <visp/vpDisplayGDI.h>
65 #include <visp/vpPixelMeterConversion.h>
66 #include <visp/vpCameraParameters.h>
67 #include <visp/vpColor.h>
68 #include <visp/vpIoTools.h>
69 #include <visp/vpException.h>
70 #include <visp/vpImageIo.h>
71 #include <visp/vpMbTracker.h>
72 #include <visp/vpMatrixException.h>
73 #include <visp/vpIoTools.h>
74 
75 #ifdef VISP_HAVE_COIN
76 //Inventor includes
77 #include <Inventor/nodes/SoSeparator.h>
78 #include <Inventor/VRMLnodes/SoVRMLIndexedFaceSet.h>
79 #include <Inventor/VRMLnodes/SoVRMLIndexedLineSet.h>
80 #include <Inventor/VRMLnodes/SoVRMLCoordinate.h>
81 #include <Inventor/actions/SoWriteAction.h>
82 #include <Inventor/actions/SoSearchAction.h>
83 #include <Inventor/misc/SoChildList.h>
84 #include <Inventor/actions/SoGetMatrixAction.h>
85 #include <Inventor/actions/SoGetPrimitiveCountAction.h>
86 #include <Inventor/actions/SoToVRML2Action.h>
87 #include <Inventor/VRMLnodes/SoVRMLGroup.h>
88 #include <Inventor/VRMLnodes/SoVRMLTransform.h>
89 #include <Inventor/VRMLnodes/SoVRMLShape.h>
90 #endif
91 
92 
93 
94 
98 struct SegmentInfo {
100 
101  std::vector<vpPoint> extremities;
102  std::string name;
103  bool useLod;
105 };
106 
112  PolygonFaceInfo(const double dist, const vpPolygon &poly, const std::vector<vpPoint> &corners)
113 : distanceToCamera(dist), polygon(poly), faceCorners(corners) {}
114 
115  bool operator<(const PolygonFaceInfo &pfi) const {
116  return distanceToCamera < pfi.distanceToCamera;
117  }
118 
121  std::vector<vpPoint> faceCorners;
122 };
123 
130 : cam(), cMo(), oJo(6,6), isoJoIdentity(true), modelFileName(), modelInitialised(false),
131  poseSavingFilename(), computeCovariance(false), covarianceMatrix(), displayFeatures(false),
132  m_w(), m_error(), faces(), angleAppears( vpMath::rad(89) ), angleDisappears( vpMath::rad(89) ),
133  distNearClip(0.001), distFarClip(100), clippingFlag(vpMbtPolygon::NO_CLIPPING), useOgre(false),
134  nbPoints(0), nbLines(0), nbPolygonLines(0), nbPolygonPoints(0), nbCylinders(0), nbCircles(0),
135  useLodGeneral(false), applyLodSettingInConfig(false), minLineLengthThresholdGeneral(50.0),
136  minPolygonAreaThresholdGeneral(2500.0), mapOfParameterNames()
137 {
138  oJo.setIdentity();
139  //Map used to parse additional information in CAO model files,
140  //like name of faces or LOD setting
141  mapOfParameterNames["name"] = "string";
142  mapOfParameterNames["minPolygonAreaThreshold"] = "number";
143  mapOfParameterNames["minLineLengthThreshold"] = "number";
144  mapOfParameterNames["useLod"] = "boolean";
145 }
146 
151 {
152 }
153 
175 void
176 vpMbTracker::initClick(const vpImage<unsigned char>& I, const std::string& initFile, const bool displayHelp)
177 {
178  vpHomogeneousMatrix last_cMo;
179  vpPoseVector init_pos;
180  vpImagePoint ip;
182 
183  std::string ext = ".init";
184  std::string str_pose = "";
185  size_t pos = (unsigned int)initFile.rfind(ext);
186 
187  // Load the last poses from files
188  std::fstream finitpos ;
189  std::fstream finit ;
190  char s[FILENAME_MAX];
191  if(poseSavingFilename.empty()){
192  if( pos == initFile.size()-ext.size() && pos != 0)
193  str_pose = initFile.substr(0,pos) + ".0.pos";
194  else
195  str_pose = initFile + ".0.pos";
196 
197  finitpos.open(str_pose.c_str() ,std::ios::in) ;
198  sprintf(s, "%s", str_pose.c_str());
199  }else{
200  finitpos.open(poseSavingFilename.c_str() ,std::ios::in) ;
201  sprintf(s, "%s", poseSavingFilename.c_str());
202  }
203  if(finitpos.fail() ){
204  std::cout << "cannot read " << s << std::endl << "cMo set to identity" << std::endl;
205  last_cMo.setIdentity();
206  }
207  else{
208  for (unsigned int i = 0; i < 6; i += 1){
209  finitpos >> init_pos[i];
210  }
211 
212  finitpos.close();
213  last_cMo.buildFrom(init_pos) ;
214 
215  std::cout <<"last_cMo : "<<std::endl << last_cMo <<std::endl;
216 
218  display(I, last_cMo, cam, vpColor::green, 1, true);
219  vpDisplay::displayFrame(I, last_cMo, cam, 0.05, vpColor::green);
220  vpDisplay::flush(I);
221 
222  std::cout << "No modification : left click " << std::endl;
223  std::cout << "Modify initial pose : right click " << std::endl ;
224 
225  vpDisplay::displayText(I, 15, 10,
226  "left click to validate, right click to modify initial pose",
227  vpColor::red);
228 
229  vpDisplay::flush(I) ;
230 
231  while (!vpDisplay::getClick(I, ip, button)) ;
232  }
233 
234 
235  if (!finitpos.fail() && button == vpMouseButton::button1){
236  cMo = last_cMo ;
237  }
238  else
239  {
240  vpDisplay *d_help = NULL;
241 
242  vpDisplay::display(I) ;
243  vpDisplay::flush(I) ;
244 
245  vpPose pose ;
246 
247  pose.clearPoint() ;
248 
249  // file parser
250  // number of points
251  // X Y Z
252  // X Y Z
253 
254  double X,Y,Z ;
255 
256  if( pos == initFile.size()-ext.size() && pos != 0)
257  sprintf(s,"%s", initFile.c_str());
258  else
259  sprintf(s,"%s.init", initFile.c_str());
260 
261  std::cout << "Load 3D points from: " << s << std::endl ;
262  finit.open(s,std::ios::in) ;
263  if (finit.fail()){
264  std::cout << "cannot read " << s << std::endl;
265  throw vpException(vpException::ioError, "cannot read init file");
266  }
267 
268  //Display window creation and initialisation
269  try{
270  if(displayHelp){
271  std::string dispF;
272  if( pos == initFile.size()-ext.size() && pos != 0)
273  dispF = initFile.substr(0,pos) + ".ppm";
274  else
275  dispF = initFile + ".ppm";
276 
277  if (vpIoTools::checkFilename(dispF)) {
278  std::cout << "Load image to help initialization: " << dispF << std::endl;
279 #if defined VISP_HAVE_X11
280  d_help = new vpDisplayX ;
281 #elif defined VISP_HAVE_GDI
282  d_help = new vpDisplayGDI;
283 #elif defined VISP_HAVE_OPENCV
284  d_help = new vpDisplayOpenCV;
285 #endif
286 
287  vpImage<vpRGBa> Iref ;
288  vpImageIo::read(Iref, dispF) ;
289 #if defined(VISP_HAVE_X11) || defined(VISP_HAVE_GDI) || defined(VISP_HAVE_OPENCV)
290  d_help->init(Iref, I.display->getWindowXPosition()+(int)I.getWidth()+80, I.display->getWindowYPosition(),
291  "Where to initialize...") ;
292  vpDisplay::display(Iref) ;
293  vpDisplay::flush(Iref);
294 #endif
295  }
296  }
297  }
298  catch(...) {
299  if(d_help != NULL) {
300  delete d_help;
301  d_help = NULL;
302  }
303  }
304 
305  char c;
306  // skip lines starting with # as comment
307  finit.get(c);
308  while (!finit.fail() && (c == '#')) {
309  finit.ignore(256, '\n');
310  finit.get(c);
311  }
312  finit.unget();
313 
314  unsigned int n ;
315  finit >> n ;
316  finit.ignore(256, '\n'); // skip the rest of the line
317  std::cout << "Number of 3D points " << n << std::endl ;
318  if (n > 100000) {
320  "Exceed the max number of points.");
321  }
322 
323  vpPoint *P = new vpPoint [n] ;
324  for (unsigned int i=0 ; i < n ; i++){
325  // skip lines starting with # as comment
326  finit.get(c);
327  while (!finit.fail() && (c == '#')) {
328  finit.ignore(256, '\n');
329  finit.get(c);
330  }
331  finit.unget();
332 
333  finit >> X ;
334  finit >> Y ;
335  finit >> Z ;
336  finit.ignore(256, '\n'); // skip the rest of the line
337 
338  std::cout << "Point " << i+1 << " with 3D coordinates: " << X << " " << Y << " " << Z << std::endl;
339  P[i].setWorldCoordinates(X,Y,Z) ; // (X,Y,Z)
340  }
341 
342  finit.close();
343 
345  bool isWellInit = false;
346  while(!isWellInit)
347  {
349  std::vector<vpImagePoint> mem_ip;
350  for(unsigned int i=0 ; i< n ; i++)
351  {
352  std::ostringstream text;
353  text << "Click on point " << i+1;
355  vpDisplay::displayText(I, 15, 10, text.str(), vpColor::red);
356  for (unsigned int k=0; k<mem_ip.size(); k++) {
357  vpDisplay::displayCross(I, mem_ip[k], 10, vpColor::green, 2) ;
358  }
359  vpDisplay::flush(I) ;
360 
361  std::cout << "Click on point " << i+1 << " ";
362  double x=0,y=0;
363  vpDisplay::getClick(I, ip) ;
364  mem_ip.push_back(ip);
365  vpDisplay::flush(I) ;
367  P[i].set_x(x);
368  P[i].set_y(y);
369 
370  std::cout << "with 2D coordinates: " << ip << std::endl;
371 
372  pose.addPoint(P[i]) ; // and added to the pose computation point list
373  }
374  vpDisplay::flush(I) ;
375  vpDisplay::display(I) ;
376 
377  vpHomogeneousMatrix cMo1, cMo2;
378  pose.computePose(vpPose::LAGRANGE, cMo1) ;
379  double d1 = pose.computeResidual(cMo1);
380  pose.computePose(vpPose::DEMENTHON, cMo2) ;
381  double d2 = pose.computeResidual(cMo2);
382 
383  if(d1 < d2){
384  cMo = cMo1;
385  }
386  else{
387  cMo = cMo2;
388  }
390 
391  display(I, cMo, cam, vpColor::green, 1, true);
392  vpDisplay::displayText(I, 15, 10,
393  "left click to validate, right click to re initialize object",
394  vpColor::red);
395 
396  vpDisplay::flush(I) ;
397 
398  button = vpMouseButton::button1;
399  while (!vpDisplay::getClick(I, ip, button)) ;
400 
401 
402  if (button == vpMouseButton::button1)
403  {
404  isWellInit = true;
405  }
406  else
407  {
408  pose.clearPoint() ;
409  vpDisplay::display(I) ;
410  vpDisplay::flush(I) ;
411  }
412  }
415 
416  delete [] P;
417 
418  //save the pose into file
419  if(poseSavingFilename.empty())
420  savePose(str_pose);
421  else
423 
424  if(d_help != NULL) {
425  delete d_help;
426  d_help = NULL;
427  }
428  }
429 
430  std::cout <<"cMo : "<<std::endl << cMo <<std::endl;
431 
432  init(I);
433 }
434 
443 void vpMbTracker::initClick(const vpImage<unsigned char>& I, const std::vector<vpPoint> &points3D_list,
444  const std::string &displayFile)
445 {
446  vpDisplay::display(I) ;
447  vpDisplay::flush(I) ;
448  vpDisplay *d_help = NULL;
449 
450  vpPose pose ;
451  vpPoint *P = NULL; P = new vpPoint [points3D_list.size()] ;
452  for (unsigned int i=0 ; i < points3D_list.size() ; i++)
453  P[i].setWorldCoordinates(points3D_list[i].get_oX(),points3D_list[i].get_oY(),points3D_list[i].get_oZ()) ;
454 
455  vpImage<vpRGBa> Iref ;
456  //Display window creation and initialisation
457  if(vpIoTools::checkFilename(displayFile)){
458  try{
459  std::cout << "Load image to help initialization: " << displayFile << std::endl;
460 #if defined VISP_HAVE_X11
461  d_help = new vpDisplayX ;
462 #elif defined VISP_HAVE_GDI
463  d_help = new vpDisplayGDI;
464 #elif defined VISP_HAVE_OPENCV
465  d_help = new vpDisplayOpenCV;
466 #endif
467 
468  vpImageIo::read(Iref, displayFile) ;
469 #if defined(VISP_HAVE_X11) || defined(VISP_HAVE_GDI) || defined(VISP_HAVE_OPENCV)
470  d_help->init(Iref, I.display->getWindowXPosition()+(int)I.getWidth()+80, I.display->getWindowYPosition(),
471  "Where to initialize...") ;
472  vpDisplay::display(Iref) ;
473  vpDisplay::flush(Iref);
474 #endif
475  }
476  catch(...) {
477  if(d_help != NULL) {
478  delete d_help;
479  d_help = NULL;
480  }
481  }
482  }
483 
484  vpImagePoint ip;
485  bool isWellInit = false;
486  while(!isWellInit)
487  {
488  for(unsigned int i=0 ; i< points3D_list.size() ; i++)
489  {
490  std::cout << "Click on point " << i+1 << std::endl ;
491  double x=0,y=0;
492  vpDisplay::getClick(I, ip) ;
494  vpDisplay::flush(I) ;
496  P[i].set_x(x);
497  P[i].set_y(y);
498 
499  std::cout << "Click on point " << ip << std::endl;
500 
501  vpDisplay::displayPoint (I, ip, vpColor::green); //display target point
502  pose.addPoint(P[i]) ; // and added to the pose computation point list
503  }
504  vpDisplay::flush(I) ;
505 
506  vpHomogeneousMatrix cMo1, cMo2;
507  pose.computePose(vpPose::LAGRANGE, cMo1) ;
508  double d1 = pose.computeResidual(cMo1);
509  pose.computePose(vpPose::DEMENTHON, cMo2) ;
510  double d2 = pose.computeResidual(cMo2);
511 
512  if(d1 < d2){
513  cMo = cMo1;
514  }
515  else{
516  cMo = cMo2;
517  }
519 
520  display(I, cMo, cam, vpColor::green, 1, true);
521  vpDisplay::displayText(I, 15, 10,
522  "left click to validate, right click to re initialize object",
523  vpColor::red);
524 
525  vpDisplay::flush(I) ;
526 
528  while (!vpDisplay::getClick(I, ip, button)) ;
529 
530 
531  if (button == vpMouseButton::button1)
532  {
533  isWellInit = true;
534  }
535  else
536  {
537  pose.clearPoint() ;
538  vpDisplay::display(I) ;
539  vpDisplay::flush(I) ;
540  }
541  }
542 
544 
545  delete [] P;
546  if(d_help != NULL) {
547  delete d_help;
548  d_help = NULL;
549  }
550 
551  init(I);
552 }
553 
571 void vpMbTracker::initFromPoints( const vpImage<unsigned char>& I, const std::string& initFile )
572 {
573  char s[FILENAME_MAX];
574  std::fstream finit ;
575 
576  std::string ext = ".init";
577  size_t pos = initFile.rfind(ext);
578 
579  if( pos == initFile.size()-ext.size() && pos != 0)
580  sprintf(s,"%s", initFile.c_str());
581  else
582  sprintf(s,"%s.init", initFile.c_str());
583 
584  std::cout << "filename " << s << std::endl ;
585  finit.open(s,std::ios::in) ;
586  if (finit.fail()){
587  std::cout << "cannot read " << s << std::endl;
588  throw vpException(vpException::ioError, "cannot read init file");
589  }
590 
591  unsigned int size;
592  double X, Y, Z;
593  finit >> size ;
594  std::cout << "number of points " << size << std::endl ;
595 
596  if (size > 100000) {
598  "Exceed the max number of points.");
599  }
600 
601  vpPoint *P = new vpPoint [size];
602  vpPose pose ;
603 
604  for(unsigned int i=0 ; i< size ; i++)
605  {
606  finit >> X ;
607  finit >> Y ;
608  finit >> Z ;
609  P[i].setWorldCoordinates(X,Y,Z) ;
610  }
611 
612  unsigned int size2;
613  double x, y;
614  vpImagePoint ip;
615  finit >> size2 ;
616  if(size != size2)
617  vpERROR_TRACE( "vpMbTracker::initFromPoints(), Number of 2D points different to the number of 3D points." );
618 
619  for(unsigned int i=0 ; i< size ; i++)
620  {
621  finit >> x;
622  finit >> y;
623  ip = vpImagePoint(x,y);
625  P[i].set_x(x);
626  P[i].set_y(y);
627  pose.addPoint(P[i]);
628  }
629 
630  vpHomogeneousMatrix cMo1, cMo2;
631  pose.computePose(vpPose::LAGRANGE, cMo1) ;
632  double d1 = pose.computeResidual(cMo1);
633  pose.computePose(vpPose::DEMENTHON, cMo2) ;
634  double d2 = pose.computeResidual(cMo2);
635 
636  if(d1 < d2)
637  cMo = cMo1;
638  else
639  cMo = cMo2;
640 
642 
643  delete [] P;
644 
645  init(I);
646 }
647 
656 void vpMbTracker::initFromPoints( const vpImage<unsigned char>& I, const std::vector<vpImagePoint> &points2D_list,
657  const std::vector<vpPoint> &points3D_list )
658 {
659  if(points2D_list.size() != points3D_list.size())
660  vpERROR_TRACE( "vpMbTracker::initFromPoints(), Number of 2D points different to the number of 3D points." );
661 
662  size_t size = points3D_list.size();
663  vpPoint *P = new vpPoint [size];
664  vpPose pose ;
665 
666  for(size_t i=0 ; i< size ; i++)
667  {
668  P[i].setWorldCoordinates(points3D_list[i].get_oX(),points3D_list[i].get_oY(),points3D_list[i].get_oZ()) ;
669  double x=0,y=0;
670  vpPixelMeterConversion::convertPoint(cam, points2D_list[i], x, y);
671  P[i].set_x(x);
672  P[i].set_y(y);
673  pose.addPoint(P[i]);
674  }
675 
676  vpHomogeneousMatrix cMo1, cMo2;
677  pose.computePose(vpPose::LAGRANGE, cMo1) ;
678  double d1 = pose.computeResidual(cMo1);
679  pose.computePose(vpPose::DEMENTHON, cMo2) ;
680  double d2 = pose.computeResidual(cMo2);
681 
682  if(d1 < d2)
683  cMo = cMo1;
684  else
685  cMo = cMo2;
686 
688 
689  delete [] P;
690 
691  init(I);
692 }
693 
711 void vpMbTracker::initFromPose(const vpImage<unsigned char>& I, const std::string &initFile)
712 {
713  char s[FILENAME_MAX];
714  std::fstream finit ;
715  vpPoseVector init_pos;
716 
717  std::string ext = ".pos";
718  size_t pos = initFile.rfind(ext);
719 
720  if( pos == initFile.size()-ext.size() && pos != 0)
721  sprintf(s,"%s", initFile.c_str());
722  else
723  sprintf(s,"%s.pos", initFile.c_str());
724 
725  std::cout << "filename " << s << std::endl ;
726  finit.open(s,std::ios::in) ;
727  if (finit.fail()){
728  std::cout << "cannot read " << s << std::endl;
729  throw vpException(vpException::ioError, "cannot read init file");
730  }
731 
732  for (unsigned int i = 0; i < 6; i += 1){
733  finit >> init_pos[i];
734  }
735 
736  cMo.buildFrom(init_pos);
737  init(I);
738 }
739 
747 {
748  this->cMo = cMo_;
749  init(I);
750 }
751 
759 {
760  vpHomogeneousMatrix _cMo(cPo);
761  initFromPose(I, _cMo);
762 }
763 
769 void vpMbTracker::savePose(const std::string &filename)
770 {
771  vpPoseVector init_pos;
772  std::fstream finitpos ;
773  char s[FILENAME_MAX];
774 
775  sprintf(s,"%s", filename.c_str());
776  finitpos.open(s, std::ios::out) ;
777 
778  init_pos.buildFrom(cMo);
779  finitpos << init_pos;
780  finitpos.close();
781 }
782 
783 
784 void vpMbTracker::addPolygon(const std::vector<vpPoint>& corners, const int idFace, const std::string &polygonName,
785  const bool useLod, const double minPolygonAreaThreshold, const double minLineLengthThreshold)
786 {
787  std::vector<vpPoint> corners_without_duplicates;
788  corners_without_duplicates.push_back(corners[0]);
789  for (unsigned int i=0; i < corners.size()-1; i++) {
790  if (std::fabs(corners[i].get_oX() - corners[i+1].get_oX()) > std::fabs(corners[i].get_oX())*std::numeric_limits<double>::epsilon()
791  || std::fabs(corners[i].get_oY() - corners[i+1].get_oY()) > std::fabs(corners[i].get_oY())*std::numeric_limits<double>::epsilon()
792  || std::fabs(corners[i].get_oZ() - corners[i+1].get_oZ()) > std::fabs(corners[i].get_oZ())*std::numeric_limits<double>::epsilon()) {
793  corners_without_duplicates.push_back(corners[i+1]);
794  }
795  }
796 
797  vpMbtPolygon polygon;
798  polygon.setNbPoint((unsigned int)corners_without_duplicates.size());
799  polygon.setIndex((int)idFace);
800  polygon.setName(polygonName);
801  polygon.setLod(useLod);
802 
803 // //if(minPolygonAreaThreshold != -1.0) {
804 // if(std::fabs(minPolygonAreaThreshold + 1.0) > std::fabs(minPolygonAreaThreshold)*std::numeric_limits<double>::epsilon()) {
805 // polygon.setMinPolygonAreaThresh(minPolygonAreaThreshold);
806 // }
807 //
808 // //if(minLineLengthThreshold != -1.0) {
809 // if(std::fabs(minLineLengthThreshold + 1.0) > std::fabs(minLineLengthThreshold)*std::numeric_limits<double>::epsilon()) {
810 // polygon.setMinLineLengthThresh(minLineLengthThreshold);
811 // }
812 
813  polygon.setMinPolygonAreaThresh(minPolygonAreaThreshold);
814  polygon.setMinLineLengthThresh(minLineLengthThreshold);
815 
816  for(unsigned int j = 0; j < corners_without_duplicates.size(); j++) {
817  polygon.addPoint(j, corners_without_duplicates[j]);
818  }
819 
820  faces.addPolygon(&polygon);
821 
823  faces.getPolygon().back()->setClipping(clippingFlag);
824 
825  if((clippingFlag & vpMbtPolygon::NEAR_CLIPPING) == vpMbtPolygon::NEAR_CLIPPING)
826  faces.getPolygon().back()->setNearClippingDistance(distNearClip);
827 
828  if((clippingFlag & vpMbtPolygon::FAR_CLIPPING) == vpMbtPolygon::FAR_CLIPPING)
829  faces.getPolygon().back()->setFarClippingDistance(distFarClip);
830 }
831 
832 void vpMbTracker::addPolygon(const vpPoint& p1, const vpPoint &p2, const vpPoint &p3, const double radius,
833  const int idFace, const std::string &polygonName, const bool useLod, const double minPolygonAreaThreshold)
834 {
835  vpMbtPolygon polygon;
836  polygon.setNbPoint(4);
837  polygon.setName(polygonName);
838  polygon.setLod(useLod);
839 
840 // //if(minPolygonAreaThreshold != -1.0) {
841 // if(std::fabs(minPolygonAreaThreshold + 1.0) > std::fabs(minPolygonAreaThreshold)*std::numeric_limits<double>::epsilon()) {
842 // polygon.setMinPolygonAreaThresh(minPolygonAreaThreshold);
843 // }
844  polygon.setMinPolygonAreaThresh(minPolygonAreaThreshold);
845  //Non sense to set minLineLengthThreshold for circle
846  //but used to be coherent when applying LOD settings for all polygons
848 
849  {
850  // Create the 4 points of the circle bounding box
851  vpPlane plane(p1, p2, p3, vpPlane::object_frame);
852 
853  // Matrice de passage entre world et circle frame
854  double norm_X = sqrt(vpMath::sqr(p2.get_oX()-p1.get_oX())
855  + vpMath::sqr(p2.get_oY()-p1.get_oY())
856  + vpMath::sqr(p2.get_oZ()-p1.get_oZ()));
857  double norm_Y = sqrt(vpMath::sqr(plane.getA())
858  + vpMath::sqr(plane.getB())
859  + vpMath::sqr(plane.getC()));
860  vpRotationMatrix wRc;
861  vpColVector x(3),y(3),z(3);
862  // X axis is P2-P1
863  x[0] = (p2.get_oX()-p1.get_oX()) / norm_X;
864  x[1] = (p2.get_oY()-p1.get_oY()) / norm_X;
865  x[2] = (p2.get_oZ()-p1.get_oZ()) / norm_X;
866  // Y axis is the normal of the plane
867  y[0] = plane.getA() / norm_Y;
868  y[1] = plane.getB() / norm_Y;
869  y[2] = plane.getC() / norm_Y;
870  // Z axis = X ^ Y
871  z = vpColVector::crossProd(x, y);
872  for (unsigned int i=0; i< 3; i++) {
873  wRc[i][0] = x[i];
874  wRc[i][1] = y[i];
875  wRc[i][2] = z[i];
876  }
877 
878  vpTranslationVector wtc(p1.get_oX(), p1.get_oY(), p1.get_oZ());
879  vpHomogeneousMatrix wMc(wtc, wRc);
880 
881  vpColVector c_p(4); // A point in the circle frame that is on the bbox
882  c_p[0] = radius;
883  c_p[1] = 0;
884  c_p[2] = radius;
885  c_p[3] = 1;
886 
887  // Matrix to rotate a point by 90 deg around Y in the circle frame
888  for(unsigned int i=0; i<4; i++) {
889  vpColVector w_p(4); // A point in the word frame
891  w_p = wMc * cMc_90 * c_p;
892 
893  vpPoint w_P;
894  w_P.setWorldCoordinates(w_p[0], w_p[1], w_p[2]);
895 
896  polygon.addPoint(i,w_P);
897  }
898  }
899 
900  polygon.setIndex(idFace);
901  faces.addPolygon(&polygon);
902 
904  faces.getPolygon().back()->setClipping(clippingFlag);
905 
906  if((clippingFlag & vpMbtPolygon::NEAR_CLIPPING) == vpMbtPolygon::NEAR_CLIPPING)
907  faces.getPolygon().back()->setNearClippingDistance(distNearClip);
908 
909  if((clippingFlag & vpMbtPolygon::FAR_CLIPPING) == vpMbtPolygon::FAR_CLIPPING)
910  faces.getPolygon().back()->setFarClippingDistance(distFarClip);
911 }
912 
913 void vpMbTracker::addPolygon(const vpPoint& p1, const vpPoint &p2, const int idFace, const std::string &polygonName,
914  const bool useLod, const double minLineLengthThreshold)
915 {
916  // A polygon as a single line that corresponds to the revolution axis of the cylinder
917  vpMbtPolygon polygon;
918  polygon.setNbPoint(2);
919 
920  polygon.addPoint(0, p1);
921  polygon.addPoint(1, p2);
922 
923  polygon.setIndex(idFace) ;
924  polygon.setName(polygonName);
925  polygon.setLod(useLod);
926 
927 // //if(minLineLengthThreshold != -1.0) {
928 // if(std::fabs(minLineLengthThreshold + 1.0) > std::fabs(minLineLengthThreshold)*std::numeric_limits<double>::epsilon()) {
929 // polygon.setMinLineLengthThresh(minLineLengthThreshold);
930 // }
931  polygon.setMinLineLengthThresh(minLineLengthThreshold);
932  //Non sense to set minPolygonAreaThreshold for cylinder
933  //but used to be coherent when applying LOD settings for all polygons
935 
936  faces.addPolygon(&polygon) ;
937 
939  faces.getPolygon().back()->setClipping(clippingFlag);
940 
941  if((clippingFlag & vpMbtPolygon::NEAR_CLIPPING) == vpMbtPolygon::NEAR_CLIPPING)
942  faces.getPolygon().back()->setNearClippingDistance(distNearClip);
943 
944  if((clippingFlag & vpMbtPolygon::FAR_CLIPPING) == vpMbtPolygon::FAR_CLIPPING)
945  faces.getPolygon().back()->setFarClippingDistance(distFarClip);
946 }
947 
973 void
974 vpMbTracker::loadModel(const char *modelFile, const bool verbose)
975 {
976  loadModel( std::string(modelFile), verbose );
977 }
978 
1004 void
1005 vpMbTracker::loadModel(const std::string& modelFile, const bool verbose)
1006 {
1007  std::string::const_iterator it;
1008 
1009  if(vpIoTools::checkFilename(modelFile)) {
1010  it = modelFile.end();
1011  if((*(it-1) == 'o' && *(it-2) == 'a' && *(it-3) == 'c' && *(it-4) == '.') ||
1012  (*(it-1) == 'O' && *(it-2) == 'A' && *(it-3) == 'C' && *(it-4) == '.') ){
1013  std::vector<std::string> vectorOfModelFilename;
1014  int startIdFace = 0;
1015  nbPoints = 0;
1016  nbLines = 0;
1017  nbPolygonLines = 0;
1018  nbPolygonPoints = 0;
1019  nbCylinders = 0;
1020  nbCircles = 0;
1021  loadCAOModel(modelFile, vectorOfModelFilename, startIdFace, verbose, true);
1022  }
1023  else if((*(it-1) == 'l' && *(it-2) == 'r' && *(it-3) == 'w' && *(it-4) == '.') ||
1024  (*(it-1) == 'L' && *(it-2) == 'R' && *(it-3) == 'W' && *(it-4) == '.') ){
1025  loadVRMLModel(modelFile);
1026  }
1027  else{
1028  throw vpException(vpException::ioError, "file cannot be open");
1029  }
1030  }
1031  else{
1032  throw vpException(vpException::ioError, "file cannot be open");
1033  }
1034 
1035  this->modelInitialised = true;
1036  this->modelFileName = modelFile;
1037 }
1038 
1039 
1070 void
1071 vpMbTracker::loadVRMLModel(const std::string& modelFile)
1072 {
1073 #ifdef VISP_HAVE_COIN
1074  SoDB::init(); // Call SoDB::finish() before ending the program.
1075 
1076  SoInput in;
1077  SbBool ok = in.openFile(modelFile.c_str());
1078  SoSeparator *sceneGraph;
1079  SoVRMLGroup *sceneGraphVRML2;
1080 
1081  if (!ok) {
1082  vpERROR_TRACE("can't open file to load model");
1083  throw vpException(vpException::fatalError, "can't open file to load model");
1084  }
1085 
1086  if(!in.isFileVRML2())
1087  {
1088  sceneGraph = SoDB::readAll(&in);
1089  if (sceneGraph == NULL) { /*return -1;*/ }
1090  sceneGraph->ref();
1091 
1092  SoToVRML2Action tovrml2;
1093  tovrml2.apply(sceneGraph);
1094 
1095  sceneGraphVRML2 =tovrml2.getVRML2SceneGraph();
1096  sceneGraphVRML2->ref();
1097  sceneGraph->unref();
1098  }
1099  else
1100  {
1101  sceneGraphVRML2 = SoDB::readAllVRML(&in);
1102  if (sceneGraphVRML2 == NULL) { /*return -1;*/ }
1103  sceneGraphVRML2->ref();
1104  }
1105 
1106  in.closeFile();
1107 
1108  vpHomogeneousMatrix transform;
1109  int indexFace = 0;
1110  extractGroup(sceneGraphVRML2, transform, indexFace);
1111 
1112  sceneGraphVRML2->unref();
1113 #else
1114  vpERROR_TRACE("coin not detected with ViSP, cannot load model : %s", modelFile.c_str());
1115  throw vpException(vpException::fatalError, "coin not detected with ViSP, cannot load model");
1116 #endif
1117 }
1118 
1119 void vpMbTracker::removeComment(std::ifstream& fileId) {
1120  char c;
1121 
1122  fileId.get(c);
1123  while (!fileId.fail() && (c == '#')) {
1124  fileId.ignore(256, '\n');
1125  fileId.get(c);
1126  }
1127  fileId.unget();
1128 }
1129 
1130 std::map<std::string, std::string> vpMbTracker::parseParameters(std::string& endLine) {
1131  std::map<std::string, std::string> mapOfParams;
1132 
1133  bool exit = false;
1134  while (!endLine.empty() && !exit) {
1135  exit = true;
1136 
1137  for (std::map<std::string, std::string>::const_iterator it =
1138  mapOfParameterNames.begin(); it != mapOfParameterNames.end();
1139  ++it) {
1140  endLine = trim(endLine);
1141  // std::cout << "endLine=" << endLine << std::endl;
1142  std::string param(it->first + "=");
1143 
1144  //Compare with a potential parameter
1145  if (endLine.compare(0, param.size(), param) == 0) {
1146  exit = false;
1147  endLine = endLine.substr(param.size());
1148 
1149  bool parseQuote = false;
1150  if (it->second == "string") {
1151  //Check if the string is between quotes
1152  if (endLine.size() > 2 && endLine[0] == '"') {
1153  parseQuote = true;
1154  endLine = endLine.substr(1);
1155  size_t pos = endLine.find_first_of('"');
1156 
1157  if (pos != std::string::npos) {
1158  mapOfParams[it->first] = endLine.substr(0, pos);
1159  endLine = endLine.substr(pos + 1);
1160  } else {
1161  parseQuote = false;
1162  }
1163  }
1164  }
1165 
1166  if (!parseQuote) {
1167  //Deal with space or tabulation after parameter value to substring
1168  // to the next sequence
1169  size_t pos1 = endLine.find_first_of(' ');
1170  size_t pos2 = endLine.find_first_of('\t');
1171  size_t pos = pos1 < pos2 ? pos1 : pos2;
1172 
1173  mapOfParams[it->first] = endLine.substr(0, pos);
1174  endLine = endLine.substr(pos + 1);
1175  }
1176  }
1177  }
1178  }
1179 
1180 // for(std::map<std::string, std::string>::const_iterator it = mapOfParams.begin(); it != mapOfParams.end(); ++it) {
1181 // std::cout << it->first << "=" << it->second << std::endl;
1182 // }
1183 
1184  return mapOfParams;
1185 }
1186 
1232 void
1233 vpMbTracker::loadCAOModel(const std::string& modelFile,
1234  std::vector<std::string>& vectorOfModelFilename, int& startIdFace,
1235  const bool verbose, const bool parent) {
1236  std::ifstream fileId;
1237  fileId.exceptions(std::ifstream::failbit | std::ifstream::eofbit);
1238  fileId.open(modelFile.c_str(), std::ifstream::in);
1239  if (fileId.fail()) {
1240  std::cout << "cannot read CAO model file: " << modelFile << std::endl;
1241  throw vpException(vpException::ioError, "cannot read CAO model file");
1242  }
1243 
1244  if(verbose) {
1245  std::cout << "Model file : " << modelFile << std::endl;
1246  }
1247  vectorOfModelFilename.push_back(modelFile);
1248 
1249  try {
1250  char c;
1251  // Extraction of the version (remove empty line and commented ones (comment
1252  // line begin with the #)).
1253  //while ((fileId.get(c) != NULL) && (c == '#')) fileId.ignore(256, '\n');
1254  removeComment(fileId);
1255 
1257  int caoVersion;
1258  fileId.get(c);
1259  if (c == 'V') {
1260  fileId >> caoVersion;
1261  fileId.ignore(256, '\n'); // skip the rest of the line
1262  } else {
1263  std::cout
1264  << "in vpMbTracker::loadCAOModel() -> Bad parameter header file : use V0, V1, ...";
1266  "in vpMbTracker::loadCAOModel() -> Bad parameter header file : use V0, V1, ...");
1267  }
1268 
1269  removeComment(fileId);
1270 
1271 
1273  std::string line;
1274  std::string prefix = "load";
1275 
1276  fileId.get(c);
1277  fileId.unget();
1278  bool header = false;
1279  while(c == 'l' || c == 'L') {
1280  header = true;
1281 
1282  getline(fileId, line);
1283  if(!line.compare(0, prefix.size(), prefix)) {
1284 
1285  //Get the loaded model pathname
1286  std::string headerPathname = line.substr(6);
1287  size_t firstIndex = headerPathname.find_first_of("\")");
1288  headerPathname = headerPathname.substr(0, firstIndex);
1289 
1290  std::string headerPath = headerPathname;
1291  if(!vpIoTools::isAbsolutePathname(headerPathname)) {
1292  std::string parentDirectory = vpIoTools::getParent(modelFile);
1293  headerPath = vpIoTools::createFilePath(parentDirectory, headerPathname);
1294  }
1295 
1296  bool cyclic = false;
1297  std::string headerModelFilename = vpIoTools::getName(headerPath);
1298  if (!headerModelFilename.compare(vpIoTools::getName(modelFile))) {
1299  cyclic = true;
1300  }
1301 
1302  for (std::vector<std::string>::const_iterator it =
1303  vectorOfModelFilename.begin();
1304  it != vectorOfModelFilename.end() - 1 && !cyclic;
1305  ++it) {
1306  std::string loadedModelFilename = vpIoTools::getName(*it);
1307  if (!headerModelFilename.compare(loadedModelFilename)) {
1308  cyclic = true;
1309  }
1310  }
1311 
1312  if (!cyclic) {
1313  if (vpIoTools::checkFilename(modelFile)) {
1314  loadCAOModel(headerPath, vectorOfModelFilename, startIdFace, verbose, false);
1315  } else {
1317  "file cannot be open");
1318  }
1319  } else {
1320  std::cout << "WARNING Cyclic dependency detected with file "
1321  << headerPath << " declared in " << modelFile << std::endl;
1322  }
1323  } else {
1324  header = false;
1325  }
1326 
1327  removeComment(fileId);
1328  fileId.get(c);
1329  fileId.unget();
1330  }
1331 
1332 
1334  unsigned int caoNbrPoint;
1335  fileId >> caoNbrPoint;
1336  fileId.ignore(256, '\n'); // skip the rest of the line
1337 
1338  nbPoints += caoNbrPoint;
1339  if(verbose || vectorOfModelFilename.size() == 1) {
1340  std::cout << "> " << caoNbrPoint << " points" << std::endl;
1341  }
1342 
1343  if (caoNbrPoint > 100000) {
1345  "Exceed the max number of points in the CAO model.");
1346  }
1347 
1348  if (caoNbrPoint == 0 && !header) {
1350  "in vpMbTracker::loadCAOModel() -> no points are defined");
1351  }
1352  vpPoint *caoPoints = new vpPoint[caoNbrPoint];
1353 
1354  double x; // 3D coordinates
1355  double y;
1356  double z;
1357 
1358  int i; // image coordinate (used for matching)
1359  int j;
1360 
1361  for (unsigned int k = 0; k < caoNbrPoint; k++) {
1362  removeComment(fileId);
1363 
1364  fileId >> x;
1365  fileId >> y;
1366  fileId >> z;
1367  fileId.ignore(256, '\n'); // skip the rest of the line
1368 
1369  if (caoVersion == 2) {
1370  fileId >> i;
1371  fileId >> j;
1372  }
1373 
1374  caoPoints[k].setWorldCoordinates(x, y, z);
1375  }
1376 
1377 
1378  removeComment(fileId);
1379 
1380 
1382  //Store in a map the potential segments to add
1383  std::map<std::pair<unsigned int, unsigned int>, SegmentInfo > segmentTemporaryMap;
1384  unsigned int caoNbrLine;
1385  fileId >> caoNbrLine;
1386  fileId.ignore(256, '\n'); // skip the rest of the line
1387 
1388  nbLines += caoNbrLine;
1389  unsigned int *caoLinePoints = NULL;
1390  if(verbose || vectorOfModelFilename.size() == 1) {
1391  std::cout << "> " << caoNbrLine << " lines" << std::endl;
1392  }
1393 
1394  if (caoNbrLine > 100000) {
1395  delete[] caoPoints;
1397  "Exceed the max number of lines in the CAO model.");
1398  }
1399 
1400  if (caoNbrLine > 0)
1401  caoLinePoints = new unsigned int[2 * caoNbrLine];
1402 
1403  unsigned int index1, index2;
1404  //Initialization of idFace with startIdFace for dealing with recursive load in header
1405  int idFace = startIdFace;
1406 
1407  for (unsigned int k = 0; k < caoNbrLine; k++) {
1408  removeComment(fileId);
1409 
1410  fileId >> index1;
1411  fileId >> index2;
1412 
1414  //Get the end of the line
1415  char buffer[256];
1416  fileId.getline(buffer, 256);
1417  std::string endLine(buffer);
1418  std::map<std::string, std::string> mapOfParams = parseParameters(endLine);
1419 
1420 // fileId.ignore(256, '\n'); // skip the rest of the line
1421 
1422  std::string segmentName = "";
1423  double minLineLengthThresh = !applyLodSettingInConfig ? minLineLengthThresholdGeneral : 50.0;
1424  bool useLod = !applyLodSettingInConfig ? useLodGeneral : false;
1425  if(mapOfParams.find("name") != mapOfParams.end()) {
1426  segmentName = mapOfParams["name"];
1427  }
1428  if(mapOfParams.find("minLineLengthThreshold") != mapOfParams.end()) {
1429  minLineLengthThresh = std::atof(mapOfParams["minLineLengthThreshold"].c_str());
1430  }
1431  if(mapOfParams.find("useLod") != mapOfParams.end()) {
1432  useLod = parseBoolean(mapOfParams["useLod"]);
1433  }
1434 
1435  SegmentInfo segmentInfo;
1436  segmentInfo.name = segmentName;
1437  segmentInfo.useLod = useLod;
1438  segmentInfo.minLineLengthThresh = minLineLengthThresh;
1439 
1440  caoLinePoints[2 * k] = index1;
1441  caoLinePoints[2 * k + 1] = index2;
1442 
1443  if (index1 < caoNbrPoint && index2 < caoNbrPoint) {
1444  std::vector<vpPoint> extremities;
1445  extremities.push_back(caoPoints[index1]);
1446  extremities.push_back(caoPoints[index2]);
1447  segmentInfo.extremities = extremities;
1448 
1449  std::pair<unsigned int, unsigned int> key(index1, index2);
1450 
1451  segmentTemporaryMap[key] = segmentInfo;
1452 // addPolygon(extremities, idFace++);
1453 // initFaceFromCorners(*(faces.getPolygon().back())); // Init from the last polygon that was added
1454  } else {
1455  vpTRACE(" line %d has wrong coordinates.", k);
1456  }
1457  }
1458 
1459  removeComment(fileId);
1460 
1461 
1463  /* Load polygon from the lines extracted earlier (the first point of the line is used)*/
1464  //Store in a vector the indexes of the segments added in the face segment case
1465  std::vector<std::pair<unsigned int, unsigned int> > faceSegmentKeyVector;
1466  unsigned int caoNbrPolygonLine;
1467  fileId >> caoNbrPolygonLine;
1468  fileId.ignore(256, '\n'); // skip the rest of the line
1469 
1470  nbPolygonLines += caoNbrPolygonLine;
1471  if(verbose || vectorOfModelFilename.size() == 1) {
1472  std::cout << "> " << caoNbrPolygonLine << " polygon lines" << std::endl;
1473  }
1474 
1475  if (caoNbrPolygonLine > 100000) {
1476  delete[] caoPoints;
1477  delete[] caoLinePoints;
1479  "Exceed the max number of polygon lines.");
1480  }
1481 
1482  unsigned int index;
1483  for (unsigned int k = 0; k < caoNbrPolygonLine; k++) {
1484  removeComment(fileId);
1485 
1486  unsigned int nbLinePol;
1487  fileId >> nbLinePol;
1488  std::vector<vpPoint> corners;
1489  if (nbLinePol > 100000) {
1490  throw vpException(vpException::badValue, "Exceed the max number of lines.");
1491  }
1492 
1493  for (unsigned int n = 0; n < nbLinePol; n++) {
1494  fileId >> index;
1495 // if (2 * index > 2 * caoNbrLine - 1) {
1496  if(index >= caoNbrLine) {
1497  throw vpException(vpException::badValue, "Exceed the max number of lines.");
1498  }
1499  corners.push_back(caoPoints[caoLinePoints[2 * index]]);
1500  corners.push_back(caoPoints[caoLinePoints[2 * index + 1]]);
1501 
1502  std::pair<unsigned int, unsigned int> key(caoLinePoints[2 * index], caoLinePoints[2 * index + 1]);
1503  faceSegmentKeyVector.push_back(key);
1504  }
1505 
1506 
1508  //Get the end of the line
1509  char buffer[256];
1510  fileId.getline(buffer, 256);
1511  std::string endLine(buffer);
1512  std::map<std::string, std::string> mapOfParams = parseParameters(endLine);
1513 
1514 // fileId.ignore(256, '\n'); // skip the rest of the line
1515 
1516  std::string polygonName = "";
1517  bool useLod = !applyLodSettingInConfig ? useLodGeneral : false;
1518  double minPolygonAreaThreshold = !applyLodSettingInConfig ? minPolygonAreaThresholdGeneral : 2500.0;
1519  if(mapOfParams.find("name") != mapOfParams.end()) {
1520  polygonName = mapOfParams["name"];
1521  }
1522  if(mapOfParams.find("minPolygonAreaThreshold") != mapOfParams.end()) {
1523  minPolygonAreaThreshold = std::atof(mapOfParams["minPolygonAreaThreshold"].c_str());
1524  }
1525  if(mapOfParams.find("useLod") != mapOfParams.end()) {
1526  useLod = parseBoolean(mapOfParams["useLod"]);
1527  }
1528 
1529  addPolygon(corners, idFace++, polygonName, useLod, minPolygonAreaThreshold, minLineLengthThresholdGeneral);
1530  // initFaceFromCorners(*(faces.getPolygon().back())); // Init from the last polygon that was added
1531  initFaceFromLines(*(faces.getPolygon().back())); // Init from the last polygon that was added
1532  }
1533 
1534  //Add the segments which were not already added in the face segment case
1535  for(std::map<std::pair<unsigned int, unsigned int>, SegmentInfo >::const_iterator it =
1536  segmentTemporaryMap.begin(); it != segmentTemporaryMap.end(); ++it) {
1537  if(std::find(faceSegmentKeyVector.begin(), faceSegmentKeyVector.end(), it->first) == faceSegmentKeyVector.end()) {
1538  addPolygon(it->second.extremities, idFace++, it->second.name, it->second.useLod, minPolygonAreaThresholdGeneral,
1539  it->second.minLineLengthThresh);
1540  initFaceFromCorners(*(faces.getPolygon().back())); // Init from the last polygon that was added
1541  }
1542  }
1543 
1544  removeComment(fileId);
1545 
1546 
1548  /* Extract the polygon using the point coordinates (top of the file) */
1549  unsigned int caoNbrPolygonPoint;
1550  fileId >> caoNbrPolygonPoint;
1551  fileId.ignore(256, '\n'); // skip the rest of the line
1552 
1553  nbPolygonPoints += caoNbrPolygonPoint;
1554  if(verbose || vectorOfModelFilename.size() == 1) {
1555  std::cout << "> " << caoNbrPolygonPoint << " polygon points"
1556  << std::endl;
1557  }
1558 
1559  if (caoNbrPolygonPoint > 100000) {
1561  "Exceed the max number of polygon point.");
1562  }
1563 
1564  for (unsigned int k = 0; k < caoNbrPolygonPoint; k++) {
1565  removeComment(fileId);
1566 
1567  unsigned int nbPointPol;
1568  fileId >> nbPointPol;
1569  if (nbPointPol > 100000) {
1571  "Exceed the max number of points.");
1572  }
1573  std::vector<vpPoint> corners;
1574  for (unsigned int n = 0; n < nbPointPol; n++) {
1575  fileId >> index;
1576  if (index > caoNbrPoint - 1) {
1578  "Exceed the max number of points.");
1579  }
1580  corners.push_back(caoPoints[index]);
1581  }
1582 
1583 
1585  //Get the end of the line
1586  char buffer[256];
1587  fileId.getline(buffer, 256);
1588  std::string endLine(buffer);
1589  std::map<std::string, std::string> mapOfParams = parseParameters(endLine);
1590 
1591 // fileId.ignore(256, '\n'); // skip the rest of the line
1592 
1593  std::string polygonName = "";
1594  bool useLod = !applyLodSettingInConfig ? useLodGeneral : false;
1595  double minPolygonAreaThreshold = !applyLodSettingInConfig ? minPolygonAreaThresholdGeneral : 2500.0;
1596  if(mapOfParams.find("name") != mapOfParams.end()) {
1597  polygonName = mapOfParams["name"];
1598  }
1599  if(mapOfParams.find("minPolygonAreaThreshold") != mapOfParams.end()) {
1600  minPolygonAreaThreshold = std::atof(mapOfParams["minPolygonAreaThreshold"].c_str());
1601  }
1602  if(mapOfParams.find("useLod") != mapOfParams.end()) {
1603  useLod = parseBoolean(mapOfParams["useLod"]);
1604  }
1605 
1606 
1607  addPolygon(corners, idFace++, polygonName, useLod, minPolygonAreaThreshold, minLineLengthThresholdGeneral);
1608  initFaceFromCorners(*(faces.getPolygon().back())); // Init from the last polygon that was added
1609  }
1610 
1612  unsigned int caoNbCylinder;
1613  try {
1614  removeComment(fileId);
1615 
1616  if (fileId.eof()) { // check if not at the end of the file (for old style files)
1617  delete[] caoPoints;
1618  delete[] caoLinePoints;
1619  return;
1620  }
1621 
1622  /* Extract the cylinders */
1623  fileId >> caoNbCylinder;
1624  fileId.ignore(256, '\n'); // skip the rest of the line
1625 
1626  nbCylinders += caoNbCylinder;
1627  if(verbose || vectorOfModelFilename.size() == 1) {
1628  std::cout << "> " << caoNbCylinder << " cylinders" << std::endl;
1629  }
1630 
1631  if (caoNbCylinder > 100000) {
1633  "Exceed the max number of cylinders.");
1634  }
1635 
1636  for (unsigned int k = 0; k < caoNbCylinder; ++k) {
1637  removeComment(fileId);
1638 
1639  double radius;
1640  unsigned int indexP1, indexP2;
1641  fileId >> indexP1;
1642  fileId >> indexP2;
1643  fileId >> radius;
1644 
1646  //Get the end of the line
1647  char buffer[256];
1648  fileId.getline(buffer, 256);
1649  std::string endLine(buffer);
1650  std::map<std::string, std::string> mapOfParams = parseParameters(endLine);
1651 
1652 // fileId.ignore(256, '\n'); // skip the rest of the line
1653 
1654  std::string polygonName = "";
1655  bool useLod = !applyLodSettingInConfig ? useLodGeneral : false;
1656  double minLineLengthThreshold = !applyLodSettingInConfig ? minLineLengthThresholdGeneral : 50.0;
1657  if(mapOfParams.find("name") != mapOfParams.end()) {
1658  polygonName = mapOfParams["name"];
1659  }
1660  if(mapOfParams.find("minLineLengthThreshold") != mapOfParams.end()) {
1661  minLineLengthThreshold = std::atof(mapOfParams["minLineLengthThreshold"].c_str());
1662  }
1663  if(mapOfParams.find("useLod") != mapOfParams.end()) {
1664  useLod = parseBoolean(mapOfParams["useLod"]);
1665  }
1666 
1667  addPolygon(caoPoints[indexP1], caoPoints[indexP2], idFace, polygonName, useLod, minLineLengthThreshold);
1668  initCylinder(caoPoints[indexP1], caoPoints[indexP2], radius, idFace++, polygonName);
1669  }
1670 
1671  } catch (...) {
1672  std::cerr
1673  << "Cannot get the number of cylinders. Defaulting to zero."
1674  << std::endl;
1675  caoNbCylinder = 0;
1676  }
1677 
1678 
1680  unsigned int caoNbCircle;
1681  try {
1682  removeComment(fileId);
1683 
1684  if (fileId.eof()) { // check if not at the end of the file (for old style files)
1685  delete[] caoPoints;
1686  delete[] caoLinePoints;
1687  return;
1688  }
1689 
1690  /* Extract the circles */
1691  fileId >> caoNbCircle;
1692  fileId.ignore(256, '\n'); // skip the rest of the line
1693 
1694  nbCircles += caoNbCircle;
1695  if(verbose || vectorOfModelFilename.size() == 1) {
1696  std::cout << "> " << caoNbCircle << " circles" << std::endl;
1697  }
1698 
1699  if (caoNbCircle > 100000) {
1701  "Exceed the max number of cicles.");
1702  }
1703 
1704  for (unsigned int k = 0; k < caoNbCircle; ++k) {
1705  removeComment(fileId);
1706 
1707  double radius;
1708  unsigned int indexP1, indexP2, indexP3;
1709  fileId >> radius;
1710  fileId >> indexP1;
1711  fileId >> indexP2;
1712  fileId >> indexP3;
1713 
1715  //Get the end of the line
1716  char buffer[256];
1717  fileId.getline(buffer, 256);
1718  std::string endLine(buffer);
1719  std::map<std::string, std::string> mapOfParams = parseParameters(endLine);
1720 
1721 // fileId.ignore(256, '\n'); // skip the rest of the line
1722 
1723  std::string polygonName = "";
1724  bool useLod = !applyLodSettingInConfig ? useLodGeneral : false;
1725  double minPolygonAreaThreshold = !applyLodSettingInConfig ? minPolygonAreaThresholdGeneral : 2500.0;
1726  if(mapOfParams.find("name") != mapOfParams.end()) {
1727  polygonName = mapOfParams["name"];
1728  }
1729  if(mapOfParams.find("minPolygonAreaThreshold") != mapOfParams.end()) {
1730  minPolygonAreaThreshold = std::atof(mapOfParams["minPolygonAreaThreshold"].c_str());
1731  }
1732  if(mapOfParams.find("useLod") != mapOfParams.end()) {
1733  useLod = parseBoolean(mapOfParams["useLod"]);
1734  }
1735 
1736  addPolygon(caoPoints[indexP1], caoPoints[indexP2],
1737  caoPoints[indexP3], radius, idFace, polygonName, useLod, minPolygonAreaThreshold);
1738 
1739  initCircle(caoPoints[indexP1], caoPoints[indexP2],
1740  caoPoints[indexP3], radius, idFace++, polygonName);
1741  }
1742 
1743  } catch (...) {
1744  std::cerr << "Cannot get the number of circles. Defaulting to zero."
1745  << std::endl;
1746  caoNbCircle = 0;
1747  }
1748 
1749  startIdFace = idFace;
1750 
1751  delete[] caoPoints;
1752  delete[] caoLinePoints;
1753 
1754  if(vectorOfModelFilename.size() > 1 && parent) {
1755  if(verbose) {
1756  std::cout << "Global information for " << vpIoTools::getName(modelFile) << " :" << std::endl;
1757  std::cout << "Total nb of points : " << nbPoints << std::endl;
1758  std::cout << "Total nb of lines : " << nbLines << std::endl;
1759  std::cout << "Total nb of polygon lines : " << nbPolygonLines << std::endl;
1760  std::cout << "Total nb of polygon points : " << nbPolygonPoints << std::endl;
1761  std::cout << "Total nb of cylinders : " << nbCylinders << std::endl;
1762  std::cout << "Total nb of circles : " << nbCircles << std::endl;
1763  } else {
1764  std::cout << "> " << nbPoints << " points" << std::endl;
1765  std::cout << "> " << nbLines << " lines" << std::endl;
1766  std::cout << "> " << nbPolygonLines << " polygon lines" << std::endl;
1767  std::cout << "> " << nbPolygonPoints << " polygon points" << std::endl;
1768  std::cout << "> " << nbCylinders << " cylinders" << std::endl;
1769  std::cout << "> " << nbCircles << " circles" << std::endl;
1770  }
1771  }
1772  } catch (...) {
1773  std::cerr << "Cannot read line!" << std::endl;
1774  throw vpException(vpException::ioError, "cannot read line");
1775  }
1776 }
1777 
1778 #ifdef VISP_HAVE_COIN
1779 
1786 void
1787 vpMbTracker::extractGroup(SoVRMLGroup *sceneGraphVRML2, vpHomogeneousMatrix &transform, int &idFace)
1788 {
1789  vpHomogeneousMatrix transformCur;
1790  SoVRMLTransform *sceneGraphVRML2Trasnform = dynamic_cast<SoVRMLTransform *>(sceneGraphVRML2);
1791  if(sceneGraphVRML2Trasnform){
1792  float rx, ry, rz, rw;
1793  sceneGraphVRML2Trasnform->rotation.getValue().getValue(rx,ry,rz,rw);
1794  vpRotationMatrix rotMat(vpQuaternionVector(rx,ry,rz,rw));
1795 // std::cout << "Rotation: " << rx << " " << ry << " " << rz << " " << rw << std::endl;
1796 
1797  float tx, ty, tz;
1798  tx = sceneGraphVRML2Trasnform->translation.getValue()[0];
1799  ty = sceneGraphVRML2Trasnform->translation.getValue()[1];
1800  tz = sceneGraphVRML2Trasnform->translation.getValue()[2];
1801  vpTranslationVector transVec(tx,ty,tz);
1802 // std::cout << "Translation: " << tx << " " << ty << " " << tz << std::endl;
1803 
1804  float sx, sy, sz;
1805  sx = sceneGraphVRML2Trasnform->scale.getValue()[0];
1806  sy = sceneGraphVRML2Trasnform->scale.getValue()[1];
1807  sz = sceneGraphVRML2Trasnform->scale.getValue()[2];
1808 // std::cout << "Scale: " << sx << " " << sy << " " << sz << std::endl;
1809 
1810  for(unsigned int i = 0 ; i < 3 ; i++)
1811  rotMat[0][i] *= sx;
1812  for(unsigned int i = 0 ; i < 3 ; i++)
1813  rotMat[1][i] *= sy;
1814  for(unsigned int i = 0 ; i < 3 ; i++)
1815  rotMat[2][i] *= sz;
1816 
1817  transformCur = vpHomogeneousMatrix(transVec,rotMat);
1818  transform = transform * transformCur;
1819  }
1820 
1821  int nbShapes = sceneGraphVRML2->getNumChildren();
1822 // std::cout << sceneGraphVRML2->getTypeId().getName().getString() << std::endl;
1823 // std::cout << "Nb object in VRML : " << nbShapes << std::endl;
1824 
1825  SoNode * child;
1826 
1827  for (int i = 0; i < nbShapes; i++)
1828  {
1829  vpHomogeneousMatrix transform_recursive(transform);
1830  child = sceneGraphVRML2->getChild(i);
1831 
1832  if (child->getTypeId() == SoVRMLGroup::getClassTypeId()){
1833  extractGroup((SoVRMLGroup*)child, transform_recursive, idFace);
1834  }
1835 
1836  if (child->getTypeId() == SoVRMLTransform::getClassTypeId()){
1837  extractGroup((SoVRMLTransform*)child, transform_recursive, idFace);
1838  }
1839 
1840  if (child->getTypeId() == SoVRMLShape::getClassTypeId()){
1841  SoChildList * child2list = child->getChildren();
1842  for (int j = 0; j < child2list->getLength(); j++)
1843  {
1844  if (((SoNode*)child2list->get(j))->getTypeId() == SoVRMLIndexedFaceSet::getClassTypeId())
1845  {
1846  SoVRMLIndexedFaceSet * face_set;
1847  face_set = (SoVRMLIndexedFaceSet*)child2list->get(j);
1848  if(!strncmp(face_set->getName().getString(),"cyl",3)){
1849  extractCylinders(face_set, transform, idFace);
1850  }else{
1851  extractFaces(face_set, transform, idFace);
1852  }
1853  }
1854  if (((SoNode*)child2list->get(j))->getTypeId() == SoVRMLIndexedLineSet::getClassTypeId())
1855  {
1856  SoVRMLIndexedLineSet * line_set;
1857  line_set = (SoVRMLIndexedLineSet*)child2list->get(j);
1858  extractLines(line_set, idFace);
1859  }
1860  }
1861  }
1862  }
1863 }
1864 
1873 void
1874 vpMbTracker::extractFaces(SoVRMLIndexedFaceSet* face_set, vpHomogeneousMatrix &transform, int &idFace)
1875 {
1876  std::vector<vpPoint> corners;
1877  corners.resize(0);
1878 
1879 // SoMFInt32 indexList = _face_set->coordIndex;
1880 // int indexListSize = indexList.getNum();
1881  int indexListSize = face_set->coordIndex.getNum();
1882 
1883  vpColVector pointTransformed(4);
1884  vpPoint pt;
1885  SoVRMLCoordinate *coord;
1886 
1887  for (int i = 0; i < indexListSize; i++)
1888  {
1889  if (face_set->coordIndex[i] == -1)
1890  {
1891  if(corners.size() > 1)
1892  {
1893  addPolygon(corners, idFace++);
1894  initFaceFromCorners(*(faces.getPolygon().back())); // Init from the last polygon that was added
1895  corners.resize(0);
1896  }
1897  }
1898  else
1899  {
1900  coord = (SoVRMLCoordinate *)(face_set->coord.getValue());
1901  int index = face_set->coordIndex[i];
1902  pointTransformed[0]=coord->point[index].getValue()[0];
1903  pointTransformed[1]=coord->point[index].getValue()[1];
1904  pointTransformed[2]=coord->point[index].getValue()[2];
1905  pointTransformed[3] = 1.0;
1906 
1907  pointTransformed = transform * pointTransformed;
1908 
1909  pt.setWorldCoordinates(pointTransformed[0],pointTransformed[1],pointTransformed[2]);
1910  corners.push_back(pt);
1911  }
1912  }
1913 }
1914 
1928 void
1929 vpMbTracker::extractCylinders(SoVRMLIndexedFaceSet* face_set, vpHomogeneousMatrix &transform, int &idFace)
1930 {
1931  std::vector<vpPoint> corners_c1, corners_c2;//points belonging to the first circle and to the second one.
1932  SoVRMLCoordinate* coords = (SoVRMLCoordinate *)face_set->coord.getValue();
1933 
1934  unsigned int indexListSize = (unsigned int)coords->point.getNum();
1935 
1936  if(indexListSize % 2 == 1){
1937  std::cout << "Not an even number of points when extracting a cylinder." << std::endl;
1938  throw vpException(vpException::dimensionError, "Not an even number of points when extracting a cylinder.");
1939  }
1940  corners_c1.resize(indexListSize / 2);
1941  corners_c2.resize(indexListSize / 2);
1942  vpColVector pointTransformed(4);
1943  vpPoint pt;
1944 
1945 
1946  // extract all points and fill the two sets.
1947  for(int i=0; i<coords->point.getNum(); ++i){
1948  pointTransformed[0]=coords->point[i].getValue()[0];
1949  pointTransformed[1]=coords->point[i].getValue()[1];
1950  pointTransformed[2]=coords->point[i].getValue()[2];
1951  pointTransformed[3] = 1.0;
1952 
1953  pointTransformed = transform * pointTransformed;
1954 
1955  pt.setWorldCoordinates(pointTransformed[0],pointTransformed[1],pointTransformed[2]);
1956 
1957  if(i < (int)corners_c1.size()){
1958  corners_c1[(unsigned int)i] = pt;
1959  }else{
1960  corners_c2[(unsigned int)i-corners_c1.size()] = pt;
1961  }
1962  }
1963 
1964  vpPoint p1 = getGravityCenter(corners_c1);
1965  vpPoint p2 = getGravityCenter(corners_c2);
1966 
1967  vpColVector dist(3);
1968  dist[0] = p1.get_oX() - corners_c1[0].get_oX();
1969  dist[1] = p1.get_oY() - corners_c1[0].get_oY();
1970  dist[2] = p1.get_oZ() - corners_c1[0].get_oZ();
1971  double radius_c1 = sqrt(dist.sumSquare());
1972  dist[0] = p2.get_oX() - corners_c2[0].get_oX();
1973  dist[1] = p2.get_oY() - corners_c2[0].get_oY();
1974  dist[2] = p2.get_oZ() - corners_c2[0].get_oZ();
1975  double radius_c2 = sqrt(dist.sumSquare());
1976 
1977  if(std::fabs(radius_c1 - radius_c2) > (std::numeric_limits<double>::epsilon() * vpMath::maximum(radius_c1, radius_c2))){
1978  std::cout << "Radius from the two circles of the cylinders are different." << std::endl;
1979  throw vpException(vpException::badValue, "Radius from the two circles of the cylinders are different.");
1980  }
1981 
1982  addPolygon(p1, p2, idFace);
1983  initCylinder(p1, p2, radius_c1, idFace++);
1984 }
1985 
1993 void
1994 vpMbTracker::extractLines(SoVRMLIndexedLineSet* line_set, int &idFace)
1995 {
1996  std::vector<vpPoint> corners;
1997  corners.resize(0);
1998 
1999  int indexListSize = line_set->coordIndex.getNum();
2000 
2001  SbVec3f point(0,0,0);
2002  vpPoint pt;
2003  SoVRMLCoordinate *coord;
2004 
2005  for (int i = 0; i < indexListSize; i++)
2006  {
2007  if (line_set->coordIndex[i] == -1)
2008  {
2009  if(corners.size() > 1)
2010  {
2011  addPolygon(corners, idFace++);
2012  initFaceFromCorners(*(faces.getPolygon().back())); // Init from the last polygon that was added
2013  corners.resize(0);
2014  }
2015  }
2016  else
2017  {
2018  coord = (SoVRMLCoordinate *)(line_set->coord.getValue());
2019  int index = line_set->coordIndex[i];
2020  point[0]=coord->point[index].getValue()[0];
2021  point[1]=coord->point[index].getValue()[1];
2022  point[2]=coord->point[index].getValue()[2];
2023 
2024  pt.setWorldCoordinates(point[0],point[1],point[2]);
2025  corners.push_back(pt);
2026  }
2027  }
2028 }
2029 
2030 #endif // VISP_HAVE_COIN
2031 
2041 vpPoint
2042 vpMbTracker::getGravityCenter(const std::vector<vpPoint>& pts)
2043 {
2044  if(pts.empty()){
2045  std::cout << "Cannot extract center of gravity of empty set." << std::endl;
2046  throw vpException(vpException::dimensionError, "Cannot extract center of gravity of empty set.");
2047  }
2048  double oX = 0;
2049  double oY = 0;
2050  double oZ = 0;
2051  vpPoint G;
2052 
2053  for(unsigned int i=0; i<pts.size(); ++i){
2054  oX += pts[i].get_oX();
2055  oY += pts[i].get_oY();
2056  oZ += pts[i].get_oZ();
2057  }
2058 
2059  G.setWorldCoordinates(oX/pts.size(), oY/pts.size(), oZ/pts.size());
2060  return G;
2061 }
2062 
2072 std::pair<std::vector<vpPolygon>, std::vector<std::vector<vpPoint> > >
2073 vpMbTracker::getPolygonFaces(const bool orderPolygons, const bool useVisibility)
2074 {
2077  getPose(cMo);
2078  getCameraParameters(cam);
2079 
2080  //Temporary variable to permit to order polygons by distance
2081  std::vector<vpPolygon> polygonsTmp;
2082  std::vector<std::vector<vpPoint> > roisPtTmp;
2083 
2084  //Pair containing the list of vpPolygon and the list of face corners
2085  std::pair<std::vector<vpPolygon>, std::vector<std::vector<vpPoint> > > pairOfPolygonFaces;
2086 
2087  for (unsigned int i = 0; i < getNbPolygon(); i++) {
2088  std::vector<vpImagePoint> roi;
2089  std::vector<vpPoint> roiPt;
2090  //A face has at least three points
2091  if (getPolygon(i)->nbpt >= 3) {
2092  if((useVisibility && getPolygon(i)->isvisible) || !useVisibility) {
2093  for (unsigned int j = 0; j < getPolygon(i)->nbpt; j++) {
2094  vpPoint pt(getPolygon(i)->p[j]);
2095  pt.project(cMo);
2096  double u = 0, v = 0;
2097  vpMeterPixelConversion::convertPoint(cam, pt.get_x(), pt.get_y(), u, v);
2098  roi.push_back(vpImagePoint(v, u));
2099  roiPt.push_back(pt);
2100  }
2101 
2102  polygonsTmp.push_back(vpPolygon(roi));
2103  roisPtTmp.push_back(roiPt);
2104  }
2105  }
2106  }
2107 
2108  if(orderPolygons) {
2109  //Order polygons by distance (near to far)
2110  std::vector<PolygonFaceInfo> listOfPolygonFaces;
2111  for(unsigned int i = 0; i < polygonsTmp.size(); i++) {
2112  double x_centroid = 0.0, y_centroid = 0.0, z_centroid = 0.0;
2113  for(unsigned int j = 0; j < roisPtTmp[i].size(); j++) {
2114  x_centroid += roisPtTmp[i][j].get_X();
2115  y_centroid += roisPtTmp[i][j].get_Y();
2116  z_centroid += roisPtTmp[i][j].get_Z();
2117  }
2118 
2119  x_centroid /= roisPtTmp[i].size();
2120  y_centroid /= roisPtTmp[i].size();
2121  z_centroid /= roisPtTmp[i].size();
2122 
2123  double squared_dist = x_centroid*x_centroid + y_centroid*y_centroid + z_centroid*z_centroid;
2124  listOfPolygonFaces.push_back(PolygonFaceInfo(squared_dist, polygonsTmp[i], roisPtTmp[i]));
2125  }
2126 
2127  //Sort the list of polygon faces
2128  std::sort(listOfPolygonFaces.begin(), listOfPolygonFaces.end());
2129 
2130  polygonsTmp.resize(listOfPolygonFaces.size());
2131  roisPtTmp.resize(listOfPolygonFaces.size());
2132 
2133  size_t cpt = 0;
2134  for(std::vector<PolygonFaceInfo>::const_iterator it = listOfPolygonFaces.begin(); it != listOfPolygonFaces.end();
2135  ++it, cpt++) {
2136  polygonsTmp[cpt] = it->polygon;
2137  roisPtTmp[cpt] = it->faceCorners;
2138  }
2139 
2140  pairOfPolygonFaces.first = polygonsTmp;
2141  pairOfPolygonFaces.second = roisPtTmp;
2142  } else {
2143  pairOfPolygonFaces.first = polygonsTmp;
2144  pairOfPolygonFaces.second = roisPtTmp;
2145  }
2146 
2147  return pairOfPolygonFaces;
2148 }
2149 
2157 void
2159 {
2160  useOgre = v;
2161  if(useOgre){
2162 #ifndef VISP_HAVE_OGRE
2163  useOgre = false;
2164  std::cout << "WARNING: ViSP doesn't have Ogre3D, basic visibility test will be used. setOgreVisibilityTest() set to false." << std::endl;
2165 #endif
2166  }
2167 }
2168 
2174 void
2176 {
2177  if( (clippingFlag & vpMbtPolygon::NEAR_CLIPPING) == vpMbtPolygon::NEAR_CLIPPING && dist <= distNearClip)
2178  vpTRACE("Far clipping value cannot be inferior than near clipping value. Far clipping won't be considered.");
2179  else if ( dist < 0 )
2180  vpTRACE("Far clipping value cannot be inferior than 0. Far clipping won't be considered.");
2181  else{
2183  distFarClip = dist;
2184  for (unsigned int i = 0; i < faces.size(); i ++){
2185  faces[i]->setFarClippingDistance(distFarClip);
2186  }
2187 #ifdef VISP_HAVE_OGRE
2189 #endif
2190  }
2191 }
2192 
2202 void
2203 vpMbTracker::setLod(const bool useLod, const std::string &name)
2204 {
2205  for (unsigned int i = 0; i < faces.size(); i++)
2206  {
2207  if(name.empty() || faces[i]->name == name) {
2208  faces[i]->setLod(useLod);
2209  }
2210  }
2211 }
2212 
2221 void
2222 vpMbTracker::setMinLineLengthThresh(const double minLineLengthThresh, const std::string &name)
2223 {
2224  for (unsigned int i = 0; i < faces.size(); i++)
2225  {
2226  if(name.empty() || faces[i]->name == name) {
2227  faces[i]->setMinLineLengthThresh(minLineLengthThresh);
2228  }
2229  }
2230 }
2231 
2240 void
2241 vpMbTracker::setMinPolygonAreaThresh(const double minPolygonAreaThresh, const std::string &name)
2242 {
2243  for (unsigned int i = 0; i < faces.size(); i++)
2244  {
2245  if(name.empty() || faces[i]->name == name) {
2246  faces[i]->setMinPolygonAreaThresh(minPolygonAreaThresh);
2247  }
2248  }
2249 }
2250 
2256 void
2258 {
2259  if( (clippingFlag & vpMbtPolygon::FAR_CLIPPING) == vpMbtPolygon::FAR_CLIPPING && dist >= distFarClip)
2260  vpTRACE("Near clipping value cannot be superior than far clipping value. Near clipping won't be considered.");
2261  else if ( dist < 0 )
2262  vpTRACE("Near clipping value cannot be inferior than 0. Near clipping won't be considered.");
2263  else{
2265  distNearClip = dist;
2266  for (unsigned int i = 0; i < faces.size(); i ++){
2267  faces[i]->setNearClippingDistance(distNearClip);
2268  }
2269 #ifdef VISP_HAVE_OGRE
2271 #endif
2272  }
2273 }
2274 
2282 void
2283 vpMbTracker::setClipping(const unsigned int &flags)
2284 {
2285  clippingFlag = flags;
2286  for (unsigned int i = 0; i < faces.size(); i ++)
2288 }
2289 
2290 
2291 void
2292 vpMbTracker::computeCovarianceMatrix(const vpHomogeneousMatrix &cMoPrev, const vpColVector &deltaS, const vpMatrix &Ls, const vpMatrix &W)
2293 {
2294  //building Lp
2295  vpMatrix LpInv(6,6);
2296  LpInv = 0;
2297  LpInv[0][0] = -1.0;
2298  LpInv[1][1] = -1.0;
2299  LpInv[2][2] = -1.0;
2300 
2301  vpTranslationVector ctoInit;
2302 
2303  cMoPrev.extract(ctoInit);
2304  vpMatrix ctoInitSkew = ctoInit.skew();
2305 
2306  vpThetaUVector thetau;
2307  cMoPrev.extract(thetau);
2308 
2309  vpColVector tu(3);
2310  for(unsigned int i = 0 ; i < 3 ; i++)
2311  tu[i] = thetau[i];
2312 
2313  double theta = sqrt(tu.sumSquare()) ;
2314 
2315 // vpMatrix Lthetau(3,3);
2316  vpMatrix LthetauInvAnalytic(3,3);
2317  vpMatrix I3(3,3);
2318  I3.setIdentity();
2319 // Lthetau = -I3;
2320  LthetauInvAnalytic = -I3;
2321 
2322  if(theta / (2.0 * M_PI) > std::numeric_limits<double>::epsilon())
2323  {
2324  // Computing [theta/2 u]_x
2325  vpColVector theta2u(3) ;
2326  for (unsigned int i=0 ; i < 3 ; i++) {
2327  theta2u[i] = tu[i]/2.0 ;
2328  }
2329  vpMatrix theta2u_skew = vpColVector::skew(theta2u);
2330 
2331  vpColVector u(3) ;
2332  for (unsigned int i=0 ; i < 3 ; i++) {
2333  u[i] = tu[i]/theta ;
2334  }
2335  vpMatrix u_skew = vpColVector::skew(u);
2336 
2337 // Lthetau += (theta2u_skew - (1.0-vpMath::sinc(theta)/vpMath::sqr(vpMath::sinc(theta/2.0)))*u_skew*u_skew);
2338  LthetauInvAnalytic += -(vpMath::sqr(vpMath::sinc(theta/2.0)) * theta2u_skew - (1.0-vpMath::sinc(theta))*u_skew*u_skew);
2339  }
2340 
2341 // vpMatrix LthetauInv = Lthetau.inverseByLU();
2342 
2343  ctoInitSkew = ctoInitSkew * LthetauInvAnalytic;
2344 
2345  for(unsigned int a = 0 ; a < 3 ; a++)
2346  for(unsigned int b = 0 ; b < 3 ; b++)
2347  LpInv[a][b+3] = ctoInitSkew[a][b];
2348 
2349  for(unsigned int a = 0 ; a < 3 ; a++)
2350  for(unsigned int b = 0 ; b < 3 ; b++)
2351  LpInv[a+3][b+3] = LthetauInvAnalytic[a][b];
2352 
2353  // Building Js
2354  vpMatrix Js = Ls * LpInv;
2355 
2356  // building deltaP
2357  vpColVector deltaP = (Js).pseudoInverse(Js.getRows()*std::numeric_limits<double>::epsilon()) * deltaS;
2358 
2360 }
2361 
2376 void
2377 vpMbTracker::computeJTR(const vpMatrix& interaction, const vpColVector& error, vpMatrix& JTR)
2378 {
2379  if(interaction.getRows() != error.getRows() || interaction.getCols() != 6 ){
2381  "Incorrect matrices size in computeJTR.");
2382  }
2383 
2384  JTR.resize(6, 1);
2385  const unsigned int N = interaction.getRows();
2386 
2387  for (unsigned int i = 0; i < 6; i += 1){
2388  double ssum = 0;
2389  for (unsigned int j = 0; j < N; j += 1){
2390  ssum += interaction[j][i] * error[j];
2391  }
2392  JTR[i][0] = ssum;
2393  }
2394 }
2395 
2409 {
2410  vpColVector v(6);
2411  for(unsigned int i = 0 ; i < 6 ; i++)
2412  v[i] = oJo[i][i];
2413  return v;
2414 }
2415 
2426 void
2428 {
2429  if(v.getRows() == 6)
2430  {
2431  isoJoIdentity = true;
2432  for(unsigned int i = 0 ; i < 6 ; i++){
2433  // if(v[i] != 0){
2434  if(std::fabs(v[i]) > std::numeric_limits<double>::epsilon()){
2435  oJo[i][i] = 1.0;
2436  }
2437  else{
2438  oJo[i][i] = 0.0;
2439  isoJoIdentity = false;
2440  }
2441  }
2442  }
2443 }
2444 
2445 
vpDisplay * display
Definition: vpImage.h:121
Definition of the vpMatrix class.
Definition: vpMatrix.h:98
vpMatrix covarianceMatrix
Covariance matrix.
Definition: vpMbTracker.h:126
virtual ~vpMbTracker()
bool parseBoolean(std::string &input)
Definition: vpMbTracker.h:548
std::string & trim(std::string &s)
Definition: vpMbTracker.h:570
virtual void init(vpImage< unsigned char > &I, int x=-1, int y=-1, const char *title=NULL)=0
Class that defines generic functionnalities for display.
Definition: vpDisplay.h:174
void resize(const unsigned int nrows, const unsigned int ncols, const bool nullify=true)
Definition: vpMatrix.cpp:199
unsigned int nbLines
Number of lines in CAO model.
Definition: vpMbTracker.h:151
unsigned int getWidth() const
Definition: vpImage.h:161
std::map< std::string, std::string > parseParameters(std::string &endLine)
static bool isAbsolutePathname(const std::string &pathname)
Definition: vpIoTools.cpp:1291
unsigned int nbCircles
Number of circles in CAO model.
Definition: vpMbTracker.h:159
vpMbHiddenFaces< vpMbtPolygon > faces
Set of faces describing the object.
Definition: vpMbTracker.h:135
void setNearClippingDistance(const double &dist)
Definition: vpAROgre.h:208
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
virtual void extractGroup(SoVRMLGroup *sceneGraphVRML2, vpHomogeneousMatrix &transform, int &idFace)
std::map< std::string, std::string > mapOfParameterNames
Map with [map.first]=parameter_names and [map.second]=type (string, number or boolean) ...
Definition: vpMbTracker.h:169
#define vpTRACE
Definition: vpDebug.h:418
unsigned int nbCylinders
Number of cylinders in CAO model.
Definition: vpMbTracker.h:157
void setIdentity()
Basic initialisation (identity)
static void convertPoint(const vpCameraParameters &cam, const double &x, const double &y, double &u, double &v)
Point coordinates conversion from normalized coordinates in meter to pixel coordinates ...
double minLineLengthThresh
unsigned int nbPoints
Number of points in CAO model.
Definition: vpMbTracker.h:149
Display for windows using GDI (available on any windows 32 platform).
Definition: vpDisplayGDI.h:132
vpPoint getGravityCenter(const std::vector< vpPoint > &_pts)
vpHomogeneousMatrix cMo
The current pose.
Definition: vpMbTracker.h:112
virtual void initCircle(const vpPoint &p1, const vpPoint &p2, const vpPoint &p3, const double radius, const int idFace=0, const std::string &name="")=0
static void displayText(const vpImage< unsigned char > &I, const vpImagePoint &ip, const std::string &s, const vpColor &color)
Definition: vpDisplay.cpp:887
Define the X11 console to display images.
Definition: vpDisplayX.h:152
bool modelInitialised
Flag used to ensure that the CAD model is loaded before the initialisation.
Definition: vpMbTracker.h:120
double get_oY() const
Get the point Y coordinate in the object frame.
Definition: vpPoint.h:129
vpHomogeneousMatrix getPose() const
Definition: vpMbTracker.h:337
void setMinPolygonAreaThresh(const double min_polygon_area)
Definition: vpMbtPolygon.h:260
error that can be emited by ViSP classes.
Definition: vpException.h:76
void computeJTR(const vpMatrix &J, const vpColVector &R, vpMatrix &JTR)
void set_x(const double x)
Set the point x coordinate in the image plane.
Definition: vpPoint.h:194
virtual void loadCAOModel(const std::string &modelFile, std::vector< std::string > &vectorOfModelFilename, int &startIdFace, const bool verbose=false, const bool parent=true)
std::vector< vpPoint > faceCorners
static void convertPoint(const vpCameraParameters &cam, const double &u, const double &v, double &x, double &y)
Point coordinates conversion from pixel coordinates to normalized coordinates in meter...
void setName(const std::string &face_name)
Definition: vpMbtPolygon.h:269
Provides simple mathematics computation tools that are not available in the C mathematics library (ma...
Definition: vpMath.h:83
unsigned int nbpt
Number of points used to define the polygon.
Definition: vpMbtPolygon.h:87
bool useOgre
Use Ogre3d for visibility tests.
Definition: vpMbTracker.h:147
double get_y() const
Get the point y coordinate in the image plane.
Definition: vpPoint.h:138
std::string modelFileName
The name of the file containing the model (it is used to create a file name.0.pos used to store the c...
Definition: vpMbTracker.h:118
virtual void setEstimatedDoF(const vpColVector &v)
virtual void initFromPose(const vpImage< unsigned char > &I, const std::string &initFile)
static std::string getParent(const std::string &pathname)
Definition: vpIoTools.cpp:1220
double sumSquare() const
Definition: vpMatrix.cpp:868
static const vpColor green
Definition: vpColor.h:170
virtual void extractLines(SoVRMLIndexedLineSet *line_set, int &idFace)
static void flush(const vpImage< unsigned char > &I)
Definition: vpDisplay.cpp:2232
static vpMatrix computeCovarianceMatrix(const vpMatrix &A, const vpColVector &x, const vpColVector &b)
void setFarClippingDistance(const double &dist)
Definition: vpAROgre.h:198
static double sinc(double x)
Definition: vpMath.h:301
static const vpColor red
Definition: vpColor.h:167
Class that defines what is a point.
Definition: vpPoint.h:65
vpPoseVector buildFrom(const vpHomogeneousMatrix &M)
vpCameraParameters cam
The camera parameters.
Definition: vpMbTracker.h:110
static Type maximum(const Type &a, const Type &b)
Definition: vpMath.h:137
The vpRotationMatrix considers the particular case of a rotation matrix.
virtual void init(const vpImage< unsigned char > &I)=0
double distFarClip
Distance for near clipping.
Definition: vpMbTracker.h:143
static bool checkFilename(const char *filename)
Definition: vpIoTools.cpp:465
std::vector< vpPoint > extremities
void addPoint(const unsigned int n, const vpPoint &P)
vpAROgre * getOgreContext()
Defines a generic 2D polygon.
Definition: vpPolygon.h:102
virtual void setMinPolygonAreaThresh(const double minPolygonAreaThresh, const std::string &name="")
virtual 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)=0
vpMatrix oJo
The Degrees of Freedom to estimate.
Definition: vpMbTracker.h:114
void setIdentity(const double &val=1.0)
Definition: vpMatrix.cpp:1230
virtual void extractCylinders(SoVRMLIndexedFaceSet *face_set, vpHomogeneousMatrix &transform, int &idFace)
Implementation of a polygon of the model used by the model-based tracker.
Definition: vpMbtPolygon.h:67
bool operator<(const PolygonFaceInfo &pfi) const
static double sqr(double x)
Definition: vpMath.h:106
void savePose(const std::string &filename)
double minLineLengthThresholdGeneral
Minimum line length threshold for LOD mode (general setting)
Definition: vpMbTracker.h:165
static std::string createFilePath(const std::string &parent, const std::string child)
Definition: vpIoTools.cpp:1245
bool computePose(vpPoseMethodType methode, vpHomogeneousMatrix &cMo, bool(*func)(vpHomogeneousMatrix *)=NULL)
compute the pose for a given method
Definition: vpPose.cpp:386
static void display(const vpImage< unsigned char > &I)
Definition: vpDisplay.cpp:210
The vpDisplayOpenCV allows to display image using the opencv library.
virtual void displayCross(const vpImagePoint &ip, unsigned int size, const vpColor &color, unsigned int thickness=1)=0
virtual void getCameraParameters(vpCameraParameters &camera) const
Definition: vpMbTracker.h:213
Class used for pose computation from N points (pose from point only).
Definition: vpPose.h:78
virtual void initFaceFromCorners(vpMbtPolygon &polygon)=0
Generic class defining intrinsic camera parameters.
double get_oZ() const
Get the point Z coordinate in the object frame.
Definition: vpPoint.h:131
void set_y(const double y)
Set the point y coordinate in the image plane.
Definition: vpPoint.h:196
void extract(vpRotationMatrix &R) const
virtual void loadVRMLModel(const std::string &modelFile)
Defines a quaternion and its basic operations.
double get_x() const
Get the point x coordinate in the image plane.
Definition: vpPoint.h:136
static void displayFrame(const vpImage< unsigned char > &I, const vpHomogeneousMatrix &cMo, const vpCameraParameters &cam, double size, const vpColor &color=vpColor::none, unsigned int thickness=1)
Definition: vpDisplay.cpp:375
unsigned int nbPolygonLines
Number of polygon lines in CAO model.
Definition: vpMbTracker.h:153
void addPolygon(PolygonType *p)
virtual void initClick(const vpImage< unsigned char > &I, const std::string &initFile, const bool displayHelp=false)
void buildFrom(const vpTranslationVector &t, const vpRotationMatrix &R)
Construction from translation vector and rotation matrix.
virtual void extractFaces(SoVRMLIndexedFaceSet *face_set, vpHomogeneousMatrix &transform, int &idFace)
static std::string getName(const std::string &pathname)
Definition: vpIoTools.cpp:1185
static double rad(double deg)
Definition: vpMath.h:100
virtual void setMinLineLengthThresh(const double minLineLengthThresh, const std::string &name="")
virtual vpColVector getEstimatedDoF()
std::string poseSavingFilename
Filename used to save the initial pose computed using the initClick() method. It is also used to read...
Definition: vpMbTracker.h:122
unsigned int size() const
void computeCovarianceMatrix(const vpHomogeneousMatrix &cMoPrev, const vpColVector &deltaS, const vpMatrix &Ls, const vpMatrix &W)
double get_oX() const
Get the point X coordinate in the object frame.
Definition: vpPoint.h:127
unsigned int nbPolygonPoints
Number of polygon points in CAO model.
Definition: vpMbTracker.h:155
double minPolygonAreaThresholdGeneral
Minimum polygon area threshold for LOD mode (general setting)
Definition: vpMbTracker.h:167
virtual void setOgreVisibilityTest(const bool &v)
virtual void loadModel(const char *modelFile, const bool verbose=false)
int getWindowYPosition() const
Definition: vpDisplay.h:365
std::string name
bool applyLodSettingInConfig
True if the CAO model is loaded before the call to loadConfigFile, (deduced by the number of polygons...
Definition: vpMbTracker.h:163
Class that provides a data structure for the column vectors as well as a set of operations on these v...
Definition: vpColVector.h:72
void setLod(const bool use_lod)
virtual void initFaceFromLines(vpMbtPolygon &polygon)=0
The pose is a complete representation of every rigid motion in the euclidian space.
Definition: vpPoseVector.h:92
unsigned int getCols() const
Return the number of columns of the matrix.
Definition: vpMatrix.h:163
double getB() const
Definition: vpPlane.h:117
virtual vpMbtPolygon * getPolygon(const unsigned int index)
Definition: vpMbTracker.h:310
error that can be emited by the vpMatrix class and its derivates
virtual unsigned int getNbPolygon() const
Definition: vpMbTracker.h:290
double getA() const
Definition: vpPlane.h:115
static vpMatrix skew(const vpColVector &v)
virtual void setClipping(const unsigned int &flags)
double getC() const
Definition: vpPlane.h:119
virtual bool getClick(bool blocking=true)=0
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition: vpImagePoint.h:93
void addPolygon(const std::vector< vpPoint > &corners, const int idFace=-1, const std::string &polygonName="", const bool useLod=false, const double minPolygonAreaThreshold=2500.0, const double minLineLengthThreshold=50.0)
static vpColVector crossProd(const vpColVector &a, const vpColVector &b)
Compute the cross product of two vectors C = a x b.
This class defines the container for a plane geometrical structure.
Definition: vpPlane.h:67
unsigned int clippingFlag
Flags specifying which clipping to used.
Definition: vpMbTracker.h:145
PolygonFaceInfo(const double dist, const vpPolygon &poly, const std::vector< vpPoint > &corners)
virtual void initFromPoints(const vpImage< unsigned char > &I, const std::string &initFile)
static void read(vpImage< unsigned char > &I, const char *filename)
Definition: vpImageIo.cpp:278
unsigned int getRows() const
Return the number of rows of the matrix.
Definition: vpMatrix.h:161
vpPolygon polygon
virtual void setFarClippingDistance(const double &dist)
virtual void setNbPoint(const unsigned int nb)
virtual std::pair< std::vector< vpPolygon >, std::vector< std::vector< vpPoint > > > getPolygonFaces(const bool orderPolygons=true, const bool useVisibility=true)
void addPoint(const vpPoint &P)
Add a new point in this array.
Definition: vpPose.cpp:155
double distNearClip
Distance for near clipping.
Definition: vpMbTracker.h:141
bool useLodGeneral
True if LOD mode is enabled.
Definition: vpMbTracker.h:161
Class that consider the case of a translation vector.
Class that consider the case of the parameterization for the rotation.
virtual void displayPoint(const vpImagePoint &ip, const vpColor &color)=0
bool isoJoIdentity
Boolean to know if oJo is identity (for fast computation)
Definition: vpMbTracker.h:116
void removeComment(std::ifstream &fileId)
double computeResidual(const vpHomogeneousMatrix &cMo) const
Compute and return the residual expressed in meter for the pose matrix 'cMo'.
Definition: vpPose.cpp:344
virtual void initCylinder(const vpPoint &p1, const vpPoint &p2, const double radius, const int idFace=0, const std::string &name="")=0
void setWorldCoordinates(const double ox, const double oy, const double oz)
Set the point world coordinates. We mean here the coordinates of the point in the object frame...
Definition: vpPoint.cpp:74
void setMinLineLengthThresh(const double min_line_length)
Definition: vpMbtPolygon.h:247
double distanceToCamera
int getWindowXPosition() const
Definition: vpDisplay.h:360
std::vector< PolygonType * > & getPolygon()
virtual void setIndex(const int i)
Definition: vpMbtPolygon.h:233
void clearPoint()
suppress all the point in the array of point
Definition: vpPose.cpp:133
virtual void setLod(const bool useLod, const std::string &name="")
virtual void setNearClippingDistance(const double &dist)