ViSP  2.7.0
vpMbTracker.cpp
1 /****************************************************************************
2  *
3  * $Id: vpMbTracker.cpp 4122 2013-02-08 10:45:54Z ayol $
4  *
5  * This file is part of the ViSP software.
6  * Copyright (C) 2005 - 2013 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 
52 #include <visp/vpMatrix.h>
53 #include <visp/vpMath.h>
54 #include <visp/vpColVector.h>
55 #include <visp/vpPoint.h>
56 #include <visp/vpPose.h>
57 #include <visp/vpDisplay.h>
58 #include <visp/vpDisplayOpenCV.h>
59 #include <visp/vpDisplayX.h>
60 #include <visp/vpDisplayGDI.h>
61 #include <visp/vpPixelMeterConversion.h>
62 #include <visp/vpCameraParameters.h>
63 #include <visp/vpColor.h>
64 #include <visp/vpIoTools.h>
65 #include <visp/vpException.h>
66 #include <visp/vpImageIo.h>
67 #include <visp/vpMbTracker.h>
68 #include <visp/vpMatrixException.h>
69 #include <visp/vpIoTools.h>
70 #include <iostream>
71 #include <limits>
72 #ifdef VISP_HAVE_COIN
73 //Inventor includes
74 #include <Inventor/nodes/SoSeparator.h>
75 #include <Inventor/VRMLnodes/SoVRMLIndexedFaceSet.h>
76 #include <Inventor/VRMLnodes/SoVRMLIndexedLineSet.h>
77 #include <Inventor/VRMLnodes/SoVRMLCoordinate.h>
78 #include <Inventor/actions/SoWriteAction.h>
79 #include <Inventor/actions/SoSearchAction.h>
80 #include <Inventor/misc/SoChildList.h>
81 #include <Inventor/actions/SoGetMatrixAction.h>
82 #include <Inventor/actions/SoGetPrimitiveCountAction.h>
83 #include <Inventor/actions/SoToVRML2Action.h>
84 #include <Inventor/VRMLnodes/SoVRMLGroup.h>
85 #include <Inventor/VRMLnodes/SoVRMLTransform.h>
86 #include <Inventor/VRMLnodes/SoVRMLShape.h>
87 #endif
88 
89 
96 {
97  modelInitialised = false;
98  coinUsed = false;
99  computeCovariance = false;
100  displayFeatures = false;
101 }
102 
108 {
109 #ifdef VISP_HAVE_COIN
110  if(coinUsed){
111  std::string version = COIN_VERSION;
112  unsigned int major, minor, patch;
113  vpIoTools::getVersion(version, major, minor, patch);
114 
115  if ( (major << 16 | minor << 8 | patch) >= (2 << 16 | 4 << 8 | 0) )
116  SoDB::finish();
117  else if ( (major << 16 | minor << 8 | patch) >= (2 << 16 | 0 << 8 | 0) )
118  SoDB::cleanup();
119 
120  coinUsed = false;
121  }
122 #endif
123 }
124 
125 
147 void
148 vpMbTracker::initClick(const vpImage<unsigned char>& I, const std::string& initFile, const bool displayHelp)
149 {
150  vpHomogeneousMatrix last_cMo;
151  vpPoseVector init_pos;
152  vpImagePoint ip;
154 
155  std::string ext = ".init";
156  std::string str_pose = "";
157  unsigned int pos = initFile.rfind(ext);
158 
159  // Load the last poses from files
160  std::fstream finitpos ;
161  std::fstream finit ;
162  char s[FILENAME_MAX];
163  if(poseSavingFilename.empty()){
164  if( pos == initFile.size()-ext.size() && pos != 0)
165  str_pose = initFile.substr(0,pos) + ".0.pos";
166  else
167  str_pose = initFile + ".0.pos";
168 
169  finitpos.open(str_pose.c_str() ,std::ios::in) ;
170  sprintf(s, "%s", str_pose.c_str());
171  }else{
172  finitpos.open(poseSavingFilename.c_str() ,std::ios::in) ;
173  sprintf(s, "%s", poseSavingFilename.c_str());
174  }
175  if(finitpos.fail() ){
176  std::cout << "cannot read " << s << std::endl << "cMo set to identity" << std::endl;
177  last_cMo.setIdentity();
178  }
179  else{
180  for (unsigned int i = 0; i < 6; i += 1){
181  finitpos >> init_pos[i];
182  }
183 
184  finitpos.close();
185  last_cMo.buildFrom(init_pos) ;
186 
187  std::cout <<"last_cMo : "<<std::endl << last_cMo <<std::endl;
188 
190  display(I, last_cMo, cam, vpColor::green, 1, true);
191  vpDisplay::displayFrame(I, last_cMo, cam, 0.05, vpColor::green);
192  vpDisplay::flush(I);
193 
194  std::cout << "No modification : left click " << std::endl;
195  std::cout << "Modify initial pose : right click " << std::endl ;
196 
198  "left click to validate, right click to modify initial pose",
199  vpColor::red);
200 
201  vpDisplay::flush(I) ;
202 
203  while (!vpDisplay::getClick(I, ip, button)) ;
204  }
205 
206 
207  if (!finitpos.fail() && button == vpMouseButton::button1){
208  cMo = last_cMo ;
209  }
210  else
211  {
212  vpDisplay::display(I) ;
213  vpDisplay::flush(I) ;
214 
215  vpPose pose ;
216 
217  pose.clearPoint() ;
218 
219  // file parser
220  // number of points
221  // X Y Z
222  // X Y Z
223 
224  double X,Y,Z ;
225 
226  if( pos == initFile.size()-ext.size() && pos != 0)
227  sprintf(s,"%s", initFile.c_str());
228  else
229  sprintf(s,"%s.init", initFile.c_str());
230 
231  std::cout << "filename " << s << std::endl ;
232  finit.open(s,std::ios::in) ;
233  if (finit.fail()){
234  std::cout << "cannot read " << s << std::endl;
235  throw vpException(vpException::ioError, "cannot read init file");
236  }
237 
238  std::string dispF;
239  if( pos == initFile.size()-ext.size() && pos != 0)
240  dispF = initFile.substr(0,pos) + ".ppm";
241  else
242  dispF = initFile + ".ppm";
243 
244  sprintf(s, "%s", dispF.c_str());
245 
246  vpImage<vpRGBa> Iref ;
247  //Display window creation and initialistation
248 #if defined VISP_HAVE_X11
249  vpDisplayX d;
250 #elif defined VISP_HAVE_GDI
251  vpDisplayGDI d;
252 #elif defined VISP_HAVE_OPENCV
253  vpDisplayOpenCV d;
254 #endif
255  try{
256  if(displayHelp){
257  vpImageIo::readPPM(Iref,s) ;
258 #if defined(VISP_HAVE_X11) || defined(VISP_HAVE_GDI) || defined(VISP_HAVE_OPENCV)
259  d.init(Iref,10,500, "Where to initialize...") ;
260  vpDisplay::display(Iref) ;
261  vpDisplay::flush(Iref);
262 #endif
263  }
264  }
265  catch(...){}
266 
267  unsigned int n ;
268  finit >> n ;
269  std::cout << "number of points " << n << std::endl ;
270  vpPoint *P = new vpPoint [n] ;
271  for (unsigned int i=0 ; i < n ; i++){
272  finit >> X ;
273  finit >> Y ;
274  finit >> Z ;
275  P[i].setWorldCoordinates(X,Y,Z) ; // (X,Y,Z)
276  }
277 
278  finit.close();
279 
281  bool isWellInit = false;
282  while(!isWellInit)
283  {
285  for(unsigned int i=0 ; i< n ; i++)
286  {
287  std::cout << "Click on point " << i+1 << std::endl ;
288  double x=0,y=0;
289  vpDisplay::getClick(I, ip) ;
291  vpDisplay::flush(I) ;
293  P[i].set_x(x);
294  P[i].set_y(y);
295 
296  std::cout << "click sur point " << ip << std::endl;
297 
298  vpDisplay::displayPoint (I, ip, vpColor::green); //display target point
299  pose.addPoint(P[i]) ; // and added to the pose computation point list
300  }
301  vpDisplay::flush(I) ;
302 
303  vpHomogeneousMatrix cMo1, cMo2;
304  pose.computePose(vpPose::LAGRANGE, cMo1) ;
305  double d1 = pose.computeResidual(cMo1);
306  pose.computePose(vpPose::DEMENTHON, cMo2) ;
307  double d2 = pose.computeResidual(cMo2);
308 
309  if(d1 < d2){
310  cMo = cMo1;
311  }
312  else{
313  cMo = cMo2;
314  }
316 
317  display(I, cMo, cam, vpColor::green, 1, true);
319  "left click to validate, right click to re initialize object",
320  vpColor::red);
321 
322  vpDisplay::flush(I) ;
323 
325  while (!vpDisplay::getClick(I, ip, button)) ;
326 
327 
328  if (button == vpMouseButton::button1)
329  {
330  isWellInit = true;
331  }
332  else
333  {
334  pose.clearPoint() ;
335  vpDisplay::display(I) ;
336  vpDisplay::flush(I) ;
337  }
338  }
341 
342  delete [] P;
343 
344  //save the pose into file
345  if(poseSavingFilename.empty())
346  savePose(str_pose);
347  else
349  }
350 
351  std::cout <<"cMo : "<<std::endl << cMo <<std::endl;
352 
353  init(I);
354 }
355 
364 void vpMbTracker::initClick(const vpImage<unsigned char>& I, const std::vector<vpPoint> &points3D_list,
365  const std::string &displayFile)
366 {
367  vpDisplay::display(I) ;
368  vpDisplay::flush(I) ;
369 
370  vpPose pose ;
371  vpPoint *P = NULL; P = new vpPoint [points3D_list.size()] ;
372  for (unsigned int i=0 ; i < points3D_list.size() ; i++)
373  P[i].setWorldCoordinates(points3D_list[i].get_oX(),points3D_list[i].get_oY(),points3D_list[i].get_oZ()) ;
374 
375  vpImage<vpRGBa> Iref ;
376  //Display window creation and initialistation
377  #if defined VISP_HAVE_X11
378  vpDisplayX d;
379  #elif defined VISP_HAVE_GDI
380  vpDisplayGDI d;
381  #elif defined VISP_HAVE_OPENCV
382  vpDisplayOpenCV d;
383  #endif
384 
385  if(displayFile != ""){
386  try{
387  std::cout << displayFile.c_str() << std::endl;
388  vpImageIo::readPPM(Iref,displayFile.c_str()) ;
389  #if defined(VISP_HAVE_X11) || defined(VISP_HAVE_GDI) || defined(VISP_HAVE_OPENCV)
390  d.init(Iref,10,500, "Where to initialize...") ;
391  vpDisplay::display(Iref) ;
392  vpDisplay::flush(Iref);
393  #endif
394  }
395  catch(...){}
396  }
397 
398  vpImagePoint ip;
399  bool isWellInit = false;
400  while(!isWellInit)
401  {
402  for(unsigned int i=0 ; i< points3D_list.size() ; i++)
403  {
404  std::cout << "Click on point " << i+1 << std::endl ;
405  double x=0,y=0;
406  vpDisplay::getClick(I, ip) ;
408  vpDisplay::flush(I) ;
410  P[i].set_x(x);
411  P[i].set_y(y);
412 
413  std::cout << "Click on point " << ip << std::endl;
414 
415  vpDisplay::displayPoint (I, ip, vpColor::green); //display target point
416  pose.addPoint(P[i]) ; // and added to the pose computation point list
417  }
418  vpDisplay::flush(I) ;
419 
420  vpHomogeneousMatrix cMo1, cMo2;
421  pose.computePose(vpPose::LAGRANGE, cMo1) ;
422  double d1 = pose.computeResidual(cMo1);
423  pose.computePose(vpPose::DEMENTHON, cMo2) ;
424  double d2 = pose.computeResidual(cMo2);
425 
426  if(d1 < d2){
427  cMo = cMo1;
428  }
429  else{
430  cMo = cMo2;
431  }
433 
434  display(I, cMo, cam, vpColor::green, 1, true);
436  "left click to validate, right click to re initialize object",
437  vpColor::red);
438 
439  vpDisplay::flush(I) ;
440 
442  while (!vpDisplay::getClick(I, ip, button)) ;
443 
444 
445  if (button == vpMouseButton::button1)
446  {
447  isWellInit = true;
448  }
449  else
450  {
451  pose.clearPoint() ;
452  vpDisplay::display(I) ;
453  vpDisplay::flush(I) ;
454  }
455  }
456 
458 
459  delete [] P;
460 
461  init(I);
462 }
463 
481 void vpMbTracker::initFromPoints( const vpImage<unsigned char>& I, const std::string& initFile )
482 {
483  char s[FILENAME_MAX];
484  std::fstream finit ;
485 
486  std::string ext = ".init";
487  unsigned int pos = initFile.rfind(ext);
488 
489  if( pos == initFile.size()-ext.size() && pos != 0)
490  sprintf(s,"%s", initFile.c_str());
491  else
492  sprintf(s,"%s.init", initFile.c_str());
493 
494  std::cout << "filename " << s << std::endl ;
495  finit.open(s,std::ios::in) ;
496  if (finit.fail()){
497  std::cout << "cannot read " << s << std::endl;
498  throw vpException(vpException::ioError, "cannot read init file");
499  }
500 
501  unsigned int size;
502  double X, Y, Z;
503  finit >> size ;
504  std::cout << "number of points " << size << std::endl ;
505  vpPoint *P = new vpPoint [size];
506  vpPose pose ;
507 
508  for(unsigned int i=0 ; i< size ; i++)
509  {
510  finit >> X ;
511  finit >> Y ;
512  finit >> Z ;
513  P[i].setWorldCoordinates(X,Y,Z) ;
514  }
515 
516  unsigned int size2;
517  double x, y;
518  vpImagePoint ip;
519  finit >> size2 ;
520  if(size != size2)
521  vpERROR_TRACE( "vpMbTracker::initFromPoints(), Number of 2D points different to the number of 3D points." );
522 
523  for(unsigned int i=0 ; i< size ; i++)
524  {
525  finit >> x;
526  finit >> y;
527  ip = vpImagePoint(x,y);
529  P[i].set_x(x);
530  P[i].set_y(y);
531  pose.addPoint(P[i]);
532  }
533 
534  vpHomogeneousMatrix cMo1, cMo2;
535  pose.computePose(vpPose::LAGRANGE, cMo1) ;
536  double d1 = pose.computeResidual(cMo1);
537  pose.computePose(vpPose::DEMENTHON, cMo2) ;
538  double d2 = pose.computeResidual(cMo2);
539 
540  if(d1 < d2)
541  cMo = cMo1;
542  else
543  cMo = cMo2;
544 
546 
547  delete [] P;
548 
549  init(I);
550 }
551 
560 void vpMbTracker::initFromPoints( const vpImage<unsigned char>& I, const std::vector<vpImagePoint> &points2D_list,
561  const std::vector<vpPoint> &points3D_list )
562 {
563  if(points2D_list.size() != points3D_list.size())
564  vpERROR_TRACE( "vpMbTracker::initFromPoints(), Number of 2D points different to the number of 3D points." );
565 
566  unsigned int size = points3D_list.size();
567  vpPoint *P = new vpPoint [size];
568  vpPose pose ;
569 
570  for(unsigned int i=0 ; i< size ; i++)
571  {
572  P[i].setWorldCoordinates(points3D_list[i].get_oX(),points3D_list[i].get_oY(),points3D_list[i].get_oZ()) ;
573  double x=0,y=0;
574  vpPixelMeterConversion::convertPoint(cam, points2D_list[i], x, y);
575  P[i].set_x(x);
576  P[i].set_y(y);
577  pose.addPoint(P[i]);
578  }
579 
580  vpHomogeneousMatrix cMo1, cMo2;
581  pose.computePose(vpPose::LAGRANGE, cMo1) ;
582  double d1 = pose.computeResidual(cMo1);
583  pose.computePose(vpPose::DEMENTHON, cMo2) ;
584  double d2 = pose.computeResidual(cMo2);
585 
586  if(d1 < d2)
587  cMo = cMo1;
588  else
589  cMo = cMo2;
590 
592 
593  delete [] P;
594 
595  init(I);
596 }
597 
615 void vpMbTracker::initFromPose(const vpImage<unsigned char>& I, const std::string &initFile)
616 {
617  char s[FILENAME_MAX];
618  std::fstream finit ;
619  vpPoseVector init_pos;
620 
621  std::string ext = ".pos";
622  unsigned int pos = initFile.rfind(ext);
623 
624  if( pos == initFile.size()-ext.size() && pos != 0)
625  sprintf(s,"%s", initFile.c_str());
626  else
627  sprintf(s,"%s.pos", initFile.c_str());
628 
629  std::cout << "filename " << s << std::endl ;
630  finit.open(s,std::ios::in) ;
631  if (finit.fail()){
632  std::cout << "cannot read " << s << std::endl;
633  throw vpException(vpException::ioError, "cannot read init file");
634  }
635 
636  for (unsigned int i = 0; i < 6; i += 1){
637  finit >> init_pos[i];
638  }
639 
640  cMo.buildFrom(init_pos);
641  init(I);
642 }
643 
651 {
652  this->cMo = cMo;
653  init(I);
654 }
655 
663 {
664  vpHomogeneousMatrix _cMo(cPo);
665  initFromPose(I, _cMo);
666 }
667 
673 void vpMbTracker::savePose(const std::string &filename)
674 {
675  vpPoseVector init_pos;
676  std::fstream finitpos ;
677  char s[FILENAME_MAX];
678 
679  sprintf(s,"%s", filename.c_str());
680  finitpos.open(s, std::ios::out) ;
681 
682  init_pos.buildFrom(cMo);
683  finitpos << init_pos;
684  finitpos.close();
685 }
686 
697 void
698 vpMbTracker::loadModel(const std::string& modelFile)
699 {
700  std::string::const_iterator it;
701 
702  if(vpIoTools::checkFilename(modelFile)){
703  it = modelFile.end();
704  if((*(it-1) == 'o' && *(it-2) == 'a' && *(it-3) == 'c' && *(it-4) == '.') ||
705  (*(it-1) == 'O' && *(it-2) == 'A' && *(it-3) == 'C' && *(it-4) == '.') ){
706  loadCAOModel(modelFile);
707  }
708  else if((*(it-1) == 'l' && *(it-2) == 'r' && *(it-3) == 'w' && *(it-4) == '.') ||
709  (*(it-1) == 'L' && *(it-2) == 'R' && *(it-3) == 'W' && *(it-4) == '.') ){
710  loadVRMLModel(modelFile);
711  }
712  else{
713  throw vpException(vpException::ioError, "file cannot be open");
714  }
715  }
716  else{
717  throw vpException(vpException::ioError, "file cannot be open");
718  }
719 
720  this->modelInitialised = true;
721  this->modelFileName = modelFile;
722 }
723 
724 
744 void
745 vpMbTracker::loadVRMLModel(const std::string& modelFile)
746 {
747 #ifdef VISP_HAVE_COIN
748  if(!coinUsed){
749  SoDB::init();
750  coinUsed = true;
751  }
752  SoInput in;
753  SbBool ok = in.openFile(modelFile.c_str());
754  SoSeparator *sceneGraph;
755  SoVRMLGroup *sceneGraphVRML2;
756 
757  if (!ok) {
758  vpERROR_TRACE("can't open file to load model");
759  throw vpException(vpException::fatalError, "can't open file to load model");
760  }
761 
762  if(!in.isFileVRML2())
763  {
764  sceneGraph = SoDB::readAll(&in);
765  if (sceneGraph == NULL) { /*return -1;*/ }
766  sceneGraph->ref();
767 
768  SoToVRML2Action tovrml2;
769  tovrml2.apply(sceneGraph);
770 
771  sceneGraphVRML2 =tovrml2.getVRML2SceneGraph();
772  sceneGraphVRML2->ref();
773  sceneGraph->unref();
774  }
775  else
776  {
777  sceneGraphVRML2 = SoDB::readAllVRML(&in);
778  if (sceneGraphVRML2 == NULL) { /*return -1;*/ }
779  sceneGraphVRML2->ref();
780  }
781 
782  in.closeFile();
783 
784  vpHomogeneousMatrix transform;
785  unsigned int indexFace = 0;
786  extractGroup(sceneGraphVRML2, transform, indexFace);
787 
788  sceneGraphVRML2->unref();
789 #else
790  vpERROR_TRACE("coin not detected with ViSP, cannot load model : %s", modelFile.c_str());
791  throw vpException(vpException::fatalError, "coin not detected with ViSP, cannot load model");
792 #endif
793 }
794 
821 void
822 vpMbTracker::loadCAOModel(const std::string& modelFile)
823 {
824  std::ifstream fileId;
825  fileId.exceptions ( std::ifstream::failbit | std::ifstream::eofbit );
826  fileId.open (modelFile.c_str(), std::ifstream::in);
827  if(fileId.fail()) {
828  std::cout << "cannot read CAO model file: " << modelFile << std::endl;
829  throw vpException(vpException::ioError, "cannot read CAO model file");
830  }
831 
832  try{
833  char c;
834  // Extraction of the version (remove empty line and commented ones (comment
835  // line begin with the #)).
836  while( (fileId.get(c)!=NULL)&&(c == '#')) fileId.ignore(256,'\n');
837  fileId.unget();
838 
839  int caoVersion;
840  fileId.get(c);
841  if(c=='V'){
842  fileId >> caoVersion;
843  }
844  else{
845  std::cout <<"in vpMbEdgeTracker::loadCAOModel -> Bad parameter header file : use V0, V1, ...";
847  "in vpMbEdgeTracker::loadCAOModel -> Bad parameter header file : use V0, V1, ...");
848  }
849 
850  while( (fileId.get(c)!=NULL)&&(c!='\n')) ;
851  while( (fileId.get(c)!=NULL)&&(c == '#')) fileId.ignore(256,'\n') ;
852  fileId.unget();
853 
854  //Read the points
855  unsigned int caoNbrPoint;
856  fileId >> caoNbrPoint;
857  std::cout << "> " << caoNbrPoint << " points" << std::endl;
858  vpPoint *caoPoints = NULL;
859  if (caoNbrPoint > 0)
860  caoPoints = new vpPoint[caoNbrPoint];
861 
862  double x ; // 3D coordinates
863  double y ;
864  double z ;
865 
866  int i ; // image coordinate (used for matching)
867  int j ;
868 
869 
870  for(unsigned int k=0; k < caoNbrPoint; k++){
871  fileId >> x ;
872  fileId >> y ;
873  fileId >> z ;
874  if (caoVersion == 2){
875  fileId >> i ;
876  fileId >> j ;
877  }
878 
879  if(k != caoNbrPoint-1){// the rest of the line is removed (not the last one due to the need to remove possible comments).
880  fileId.ignore(256,'\n');
881  }
882  caoPoints[k].setWorldCoordinates(x, y, z) ;
883  }
884 
885  while( (fileId.get(c)!=NULL)&&(c!='\n')) ;
886  while( (fileId.get(c)!=NULL)&&(c == '#')) fileId.ignore(256,'\n');
887  fileId.unget();
888 
889  //Read the lines
890  unsigned int caoNbrLine;
891  fileId >> caoNbrLine;
892  unsigned int *caoLinePoints = NULL;
893  std::cout << "> " << caoNbrLine << " lines" << std::endl;
894  if (caoNbrLine > 0)
895  caoLinePoints = new unsigned int[2*caoNbrLine];
896 
897  unsigned int index1, index2;
898 
899  for(unsigned int k=0; k < caoNbrLine ; k++){
900  fileId >> index1 ;
901  fileId >> index2 ;
902 
903  caoLinePoints[2*k] = index1;
904  caoLinePoints[2*k+1] = index2;
905 
906  if(index1 < caoNbrPoint && index2 < caoNbrPoint){
907  std::vector<vpPoint> extremities;
908  extremities.push_back(caoPoints[index1]);
909  extremities.push_back(caoPoints[index2]);
910  initFaceFromCorners(extremities, k);
911  }
912  else{
913  vpTRACE(" line %d has wrong coordinates.", k);
914  }
915 
916  if(k != caoNbrLine-1){// the rest of the line is removed (not the last one due to the need to remove possible comments).
917  fileId.ignore(256,'\n');
918  }
919  }
920 
921  while( (fileId.get(c)!=NULL)&&(c!='\n')) ;
922  while( (fileId.get(c)!=NULL)&&(c == '#')) fileId.ignore(256,'\n');
923  fileId.unget();
924 
925 
926  /* Load polygon from the lines extracted earlier
927  (the first point of the line is used)*/
928  unsigned int caoNbrPolygonLine;
929  fileId >> caoNbrPolygonLine;
930  std::cout << "> " << caoNbrPolygonLine << " polygon line" << std::endl;
931  unsigned int index;
932  for(unsigned int k = 0;k < caoNbrPolygonLine; k++){
933  unsigned int nbLinePol;
934  fileId >> nbLinePol;
935  std::vector<vpPoint> corners;
936  for(unsigned int i = 0; i < nbLinePol; i++){
937  fileId >> index;
938  corners.push_back(caoPoints[caoLinePoints[2*index]]);
939  }
940  if(k != caoNbrPolygonLine-1){// the rest of the line is removed (not the last one due to the need to remove possible comments).
941  fileId.ignore(256,'\n');
942  }
943  initFaceFromCorners(corners, k);
944  }
945 
946  while( (fileId.get(c)!=NULL)&&(c!='\n')) ;
947  while( (fileId.get(c)!=NULL)&&(c == '#')) fileId.ignore(256,'\n');
948  fileId.unget();
949 
950  /* Extract the polygon using the point coordinates (top of the file) */
951  unsigned int caoNbrPolygonPoint;
952  fileId >> caoNbrPolygonPoint;
953  std::cout << "> " << caoNbrPolygonPoint << " polygon point" << std::endl;
954  for(unsigned int k = 0;k < caoNbrPolygonPoint; k++){
955  int nbPointPol;
956  fileId >> nbPointPol;
957  std::vector<vpPoint> corners;
958  for(int i = 0; i < nbPointPol; i++){
959  fileId >> index;
960  corners.push_back(caoPoints[index]);
961  }
962  if(k != caoNbrPolygonPoint-1){// the rest of the line is removed (not the last one due to the need to remove possible comments).
963  fileId.ignore(256,'\n');
964  }
965  initFaceFromCorners(corners, k);
966  }
967 
968  unsigned int caoNbCylinder;
969  try{
970  while( (fileId.get(c)!=NULL)&&(c!='\n')) ;
971  while( (fileId.get(c)!=NULL)&&(c == '#')) fileId.ignore(256,'\n');
972  fileId.unget();
973 
974  if(fileId.eof()){// check if not at the end of the file (for old style files)
975  delete[] caoPoints;
976  delete[] caoLinePoints;
977  return ;
978  }
979 
980  /* Extract the cylinders */
981 
982 
983  fileId >> caoNbCylinder;
984  std::cout << "> " << caoNbCylinder << " cylinder" << std::endl;
985  for(unsigned int k=0; k<caoNbCylinder; ++k){
986  double radius;
987  unsigned int indexP1, indexP2;
988  fileId >> indexP1;
989  fileId >> indexP2;
990  fileId >> radius;
991  initCylinder(caoPoints[indexP1], caoPoints[indexP2], radius);
992  }
993 
994  }catch(...){
995  std::cerr << "Cannot get the number of cylinders. Defaulting to zero." << std::endl;
996  caoNbCylinder = 0;
997  }
998 
999  delete[] caoPoints;
1000  delete[] caoLinePoints;
1001  }catch(std::ifstream::failure e){
1002  std::cerr << "Cannot read line!" << std::endl;
1003  throw vpException(vpException::ioError, "cannot read line");
1004  }
1005 
1006 }
1007 
1008 
1009 
1010 
1011 #ifdef VISP_HAVE_COIN
1012 
1019 void
1020 vpMbTracker::extractGroup(SoVRMLGroup *sceneGraphVRML2, vpHomogeneousMatrix &transform, unsigned int &indexFace)
1021 {
1022  vpHomogeneousMatrix transformCur;
1023  SoVRMLTransform *sceneGraphVRML2Trasnform = dynamic_cast<SoVRMLTransform *>(sceneGraphVRML2);
1024  if(sceneGraphVRML2Trasnform){
1025  float rx, ry, rz, rw;
1026  sceneGraphVRML2Trasnform->rotation.getValue().getValue(rx,ry,rz,rw);
1027  vpRotationMatrix rotMat(vpQuaternionVector(rx,ry,rz,rw));
1028 // std::cout << "Rotation: " << rx << " " << ry << " " << rz << " " << rw << std::endl;
1029 
1030  float tx, ty, tz;
1031  tx = sceneGraphVRML2Trasnform->translation.getValue()[0];
1032  ty = sceneGraphVRML2Trasnform->translation.getValue()[1];
1033  tz = sceneGraphVRML2Trasnform->translation.getValue()[2];
1034  vpTranslationVector transVec(tx,ty,tz);
1035 // std::cout << "Translation: " << tx << " " << ty << " " << tz << std::endl;
1036 
1037  float sx, sy, sz;
1038  sx = sceneGraphVRML2Trasnform->scale.getValue()[0];
1039  sy = sceneGraphVRML2Trasnform->scale.getValue()[1];
1040  sz = sceneGraphVRML2Trasnform->scale.getValue()[2];
1041 // std::cout << "Scale: " << sx << " " << sy << " " << sz << std::endl;
1042 
1043  for(unsigned int i = 0 ; i < 3 ; i++)
1044  rotMat[0][i] *= sx;
1045  for(unsigned int i = 0 ; i < 3 ; i++)
1046  rotMat[1][i] *= sy;
1047  for(unsigned int i = 0 ; i < 3 ; i++)
1048  rotMat[2][i] *= sz;
1049 
1050  transformCur = vpHomogeneousMatrix(transVec,rotMat);
1051  transform = transform * transformCur;
1052  }
1053 
1054  int nbShapes = sceneGraphVRML2->getNumChildren();
1055 // std::cout << sceneGraphVRML2->getTypeId().getName().getString() << std::endl;
1056 // std::cout << "Nb object in VRML : " << nbShapes << std::endl;
1057 
1058  SoNode * child;
1059 
1060  for (int i = 0; i < nbShapes; i++)
1061  {
1062  vpHomogeneousMatrix transform_recursive(transform);
1063  child = sceneGraphVRML2->getChild(i);
1064 
1065  if (child->getTypeId() == SoVRMLGroup::getClassTypeId()){
1066  extractGroup((SoVRMLGroup*)child, transform_recursive, indexFace);
1067  }
1068 
1069  if (child->getTypeId() == SoVRMLTransform::getClassTypeId()){
1070  extractGroup((SoVRMLTransform*)child, transform_recursive, indexFace);
1071  }
1072 
1073  if (child->getTypeId() == SoVRMLShape::getClassTypeId()){
1074  SoChildList * child2list = child->getChildren();
1075  for (int j = 0; j < child2list->getLength(); j++)
1076  {
1077  if (((SoNode*)child2list->get(j))->getTypeId() == SoVRMLIndexedFaceSet::getClassTypeId())
1078  {
1079  SoVRMLIndexedFaceSet * face_set;
1080  face_set = (SoVRMLIndexedFaceSet*)child2list->get(j);
1081  if(!strncmp(face_set->getName().getString(),"cyl",3)){
1082  extractCylinders(face_set, transform);
1083  }else{
1084  extractFaces(face_set, transform, indexFace);
1085  }
1086  }
1087  if (((SoNode*)child2list->get(j))->getTypeId() == SoVRMLIndexedLineSet::getClassTypeId())
1088  {
1089  SoVRMLIndexedLineSet * line_set;
1090  line_set = (SoVRMLIndexedLineSet*)child2list->get(j);
1091  extractLines(line_set);
1092  }
1093  }
1094  }
1095  }
1096 }
1097 
1106 void
1107 vpMbTracker::extractFaces(SoVRMLIndexedFaceSet* face_set, vpHomogeneousMatrix &transform, unsigned int &indexFace)
1108 {
1109  std::vector<vpPoint> corners;
1110  corners.resize(0);
1111 
1112 // SoMFInt32 indexList = _face_set->coordIndex;
1113 // int indexListSize = indexList.getNum();
1114  int indexListSize = face_set->coordIndex.getNum();
1115 
1116  vpColVector pointTransformed(4);
1117  vpPoint pt;
1118  SoVRMLCoordinate *coord;
1119 
1120  for (int i = 0; i < indexListSize; i++)
1121  {
1122  if (face_set->coordIndex[i] == -1)
1123  {
1124  if(corners.size() > 1)
1125  {
1126  initFaceFromCorners(corners, indexFace);
1127  indexFace++;
1128  corners.resize(0);
1129  }
1130  }
1131  else
1132  {
1133  coord = (SoVRMLCoordinate *)(face_set->coord.getValue());
1134  int index = face_set->coordIndex[i];
1135  pointTransformed[0]=coord->point[index].getValue()[0];
1136  pointTransformed[1]=coord->point[index].getValue()[1];
1137  pointTransformed[2]=coord->point[index].getValue()[2];
1138  pointTransformed[3] = 1.0;
1139 
1140  pointTransformed = transform * pointTransformed;
1141 
1142  pt.setWorldCoordinates(pointTransformed[0],pointTransformed[1],pointTransformed[2]);
1143  corners.push_back(pt);
1144  }
1145  }
1146 }
1147 
1160 void
1161 vpMbTracker::extractCylinders(SoVRMLIndexedFaceSet* face_set, vpHomogeneousMatrix &transform)
1162 {
1163  std::vector<vpPoint> corners_c1, corners_c2;//points belonging to the first circle and to the second one.
1164  SoVRMLCoordinate* coords = (SoVRMLCoordinate *)face_set->coord.getValue();
1165 
1166  unsigned int indexListSize = (unsigned int)coords->point.getNum();
1167 
1168  if(indexListSize % 2 == 1){
1169  std::cout << "Not an even number of points when extracting a cylinder." << std::endl;
1170  throw vpException(vpException::dimensionError, "Not an even number of points when extracting a cylinder.");
1171  }
1172  corners_c1.resize(indexListSize / 2);
1173  corners_c2.resize(indexListSize / 2);
1174  vpColVector pointTransformed(4);
1175  vpPoint pt;
1176 
1177 
1178  // extract all points and fill the two sets.
1179  for(int i=0; i<coords->point.getNum(); ++i){
1180  pointTransformed[0]=coords->point[i].getValue()[0];
1181  pointTransformed[1]=coords->point[i].getValue()[1];
1182  pointTransformed[2]=coords->point[i].getValue()[2];
1183  pointTransformed[3] = 1.0;
1184 
1185  pointTransformed = transform * pointTransformed;
1186 
1187  pt.setWorldCoordinates(pointTransformed[0],pointTransformed[1],pointTransformed[2]);
1188 
1189  if(i < (int)corners_c1.size()){
1190  corners_c1[(unsigned int)i] = pt;
1191  }else{
1192  corners_c2[(unsigned int)i-corners_c1.size()] = pt;
1193  }
1194  }
1195 
1196  vpPoint p1 = getGravityCenter(corners_c1);
1197  vpPoint p2 = getGravityCenter(corners_c2);
1198 
1199  vpColVector dist(3);
1200  dist[0] = p1.get_oX() - corners_c1[0].get_oX();
1201  dist[1] = p1.get_oY() - corners_c1[0].get_oY();
1202  dist[2] = p1.get_oZ() - corners_c1[0].get_oZ();
1203  double radius_c1 = sqrt(dist.sumSquare());
1204  dist[0] = p2.get_oX() - corners_c2[0].get_oX();
1205  dist[1] = p2.get_oY() - corners_c2[0].get_oY();
1206  dist[2] = p2.get_oZ() - corners_c2[0].get_oZ();
1207  double radius_c2 = sqrt(dist.sumSquare());
1208 
1209  if(std::fabs(radius_c1 - radius_c2) > (std::numeric_limits<double>::epsilon() * vpMath::maximum(radius_c1, radius_c2))){
1210  std::cout << "Radius from the two circles of the cylinders are different." << std::endl;
1211  throw vpException(vpException::badValue, "Radius from the two circles of the cylinders are different.");
1212  }
1213 
1214  initCylinder(p1, p2, radius_c1);
1215 
1216 }
1217 
1227 vpPoint
1228 vpMbTracker::getGravityCenter(const std::vector<vpPoint>& pts)
1229 {
1230  if(pts.empty()){
1231  std::cout << "Cannot extract center of gravity of empty set." << std::endl;
1232  throw vpException(vpException::dimensionError, "Cannot extract center of gravity of empty set.");
1233  }
1234  double oX = 0;
1235  double oY = 0;
1236  double oZ = 0;
1237  vpPoint G;
1238 
1239  for(unsigned int i=0; i<pts.size(); ++i){
1240  oX += pts[i].get_oX();
1241  oY += pts[i].get_oY();
1242  oZ += pts[i].get_oZ();
1243  }
1244 
1245  G.setWorldCoordinates(oX/pts.size(), oY/pts.size(), oZ/pts.size());
1246  return G;
1247 }
1248 
1249 
1256 void
1257 vpMbTracker::extractLines(SoVRMLIndexedLineSet* line_set)
1258 {
1259  std::vector<vpPoint> corners;
1260  corners.resize(0);
1261 
1262  int indexListSize = line_set->coordIndex.getNum();
1263 
1264  SbVec3f point(0,0,0);
1265  vpPoint pt;
1266  SoVRMLCoordinate *coord;
1267 
1268  unsigned int indexFace = 0;
1269 
1270  for (int i = 0; i < indexListSize; i++)
1271  {
1272  if (line_set->coordIndex[i] == -1)
1273  {
1274  if(corners.size() > 1)
1275  {
1276  initFaceFromCorners(corners, indexFace);
1277  indexFace++;
1278  corners.resize(0);
1279  }
1280  }
1281  else
1282  {
1283  coord = (SoVRMLCoordinate *)(line_set->coord.getValue());
1284  int index = line_set->coordIndex[i];
1285  point[0]=coord->point[index].getValue()[0];
1286  point[1]=coord->point[index].getValue()[1];
1287  point[2]=coord->point[index].getValue()[2];
1288 
1289  pt.setWorldCoordinates(point[0],point[1],point[2]);
1290  corners.push_back(pt);
1291  }
1292  }
1293 }
1294 
1295 #endif
1296 
1311 void
1312 vpMbTracker::computeJTR(const vpMatrix& interaction, const vpColVector& error, vpMatrix& JTR)
1313 {
1314  if(interaction.getRows() != error.getRows() || interaction.getCols() != 6 ){
1316  "Incorrect matrices size in computeJTR.");
1317  }
1318 
1319  JTR.resize(6, 1);
1320  const unsigned int N = interaction.getRows();
1321 
1322  for (unsigned int i = 0; i < 6; i += 1){
1323  double ssum = 0;
1324  for (unsigned int j = 0; j < N; j += 1){
1325  ssum += interaction[j][i] * error[j];
1326  }
1327  JTR[i][0] = ssum;
1328  }
1329 }
1330 
1331 
void init(vpImage< unsigned char > &I, int winx=-1, int winy=-1, const char *title=NULL)
Definition of the vpMatrix class.
Definition: vpMatrix.h:96
virtual ~vpMbTracker()
virtual void extractCylinders(SoVRMLIndexedFaceSet *face_set, vpHomogeneousMatrix &transform)
void resize(const unsigned int nrows, const unsigned int ncols, const bool nullify=true)
Definition: vpMatrix.cpp:174
virtual void extractLines(SoVRMLIndexedLineSet *line_set)
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:379
static void getVersion(const std::string &version, unsigned int &major, unsigned int &minor, unsigned int &patch)
Definition: vpIoTools.cpp:288
virtual void initFaceFromCorners(const std::vector< vpPoint > &corners, const unsigned int indexFace=-1)=0
#define vpTRACE
Definition: vpDebug.h:401
void setIdentity()
Basic initialisation (identity)
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:108
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:112
double get_oY() const
Get the point Y coordinate in the object frame.
Definition: vpPoint.h:129
error that can be emited by ViSP classes.
Definition: vpException.h:75
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
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...
virtual void extractFaces(SoVRMLIndexedFaceSet *face_set, vpHomogeneousMatrix &transform, unsigned int &indexFace)
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:110
virtual void initFromPose(const vpImage< unsigned char > &I, const std::string &initFile)
double sumSquare() const
return sum of the Aij^2 (for all i, for all j)
Definition: vpMatrix.cpp:758
bool computeCovariance
Flag used to specify if the covariance matrix has to be computed or not.
Definition: vpMbTracker.h:118
static const vpColor green
Definition: vpColor.h:168
static void flush(const vpImage< unsigned char > &I)
Definition: vpDisplay.cpp:1964
static const vpColor red
Definition: vpColor.h:165
Class that defines what is a point.
Definition: vpPoint.h:65
virtual void loadCAOModel(const std::string &modelFile)
vpPoseVector buildFrom(const vpHomogeneousMatrix &M)
vpCameraParameters cam
The camera parameters.
Definition: vpMbTracker.h:106
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
static bool checkFilename(const char *filename)
Definition: vpIoTools.cpp:485
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
void savePose(const std::string &filename)
static void display(const vpImage< unsigned char > &I)
Definition: vpDisplay.cpp:186
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
Class used for pose computation from N points (pose from point only).
Definition: vpPose.h:80
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 set_y(const double y)
Set the point y coordinate in the image plane.
Definition: vpPoint.h:196
virtual void initCylinder(const vpPoint &p1, const vpPoint p2, const double radius, const unsigned int indexCylinder=0)=0
virtual void loadVRMLModel(const std::string &modelFile)
Defines a quaternion and its basic operations.
virtual void initClick(const vpImage< unsigned char > &I, const std::string &initFile, const bool displayHelp=false)
static void displayFrame(const vpImage< unsigned char > &I, const vpHomogeneousMatrix &cMo, const vpCameraParameters &cam, double size, const vpColor &color, unsigned int thickness=1)
Definition: vpDisplay.cpp:346
void buildFrom(const vpTranslationVector &t, const vpRotationMatrix &R)
Construction from translation vector and rotation matrix.
std::string poseSavingFilename
Filename used to save the initial pose computed using the initClick() method. It is also used to read...
Definition: vpMbTracker.h:116
double get_oX() const
Get the point X coordinate in the object frame.
Definition: vpPoint.h:127
bool coinUsed
Flag used to specify that the Coin library has been loaded in order to load a vrml model (used to fre...
Definition: vpMbTracker.h:114
bool displayFeatures
If true, the features are displayed.
Definition: vpMbTracker.h:122
Class that provides a data structure for the column vectors as well as a set of operations on these v...
Definition: vpColVector.h:72
virtual void displayCharString(const vpImagePoint &ip, const char *text, const vpColor &color=vpColor::green)=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:159
static void readPPM(vpImage< unsigned char > &I, const char *filename)
Definition: vpImageIo.cpp:1029
error that can be emited by the vpMatrix class and its derivates
void computePose(vpPoseMethodType methode, vpHomogeneousMatrix &cMo)
compute the pose for a given method
Definition: vpPose.cpp:382
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:92
virtual void initFromPoints(const vpImage< unsigned char > &I, const std::string &initFile)
unsigned int getRows() const
Return the number of rows of the matrix.
Definition: vpMatrix.h:157
void addPoint(const vpPoint &P)
Add a new point in this array.
Definition: vpPose.cpp:150
Class that consider the case of a translation vector.
virtual void displayPoint(const vpImagePoint &ip, const vpColor &color)=0
double computeResidual(const vpHomogeneousMatrix &cMo) const
Compute and return the residual expressed in meter for the pose matrix 'cMo'.
Definition: vpPose.cpp:339
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 clearPoint()
suppress all the point in the array of point
Definition: vpPose.cpp:128
virtual void extractGroup(SoVRMLGroup *sceneGraphVRML2, vpHomogeneousMatrix &transform, unsigned int &indexFace)