ViSP  2.6.2
vpMbTracker.cpp
1 /****************************************************************************
2  *
3  * $Id: vpMbTracker.cpp 3840 2012-07-06 13:25:21Z ayol $
4  *
5  * This file is part of the ViSP software.
6  * Copyright (C) 2005 - 2012 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/SoVRMLShape.h>
86 #endif
87 
88 
95 {
96  modelInitialised = false;
97  cameraInitialised = false;
98  coinUsed = false;
99  computeCovariance = false;
100 }
101 
107 {
108 #ifdef VISP_HAVE_COIN
109  if(coinUsed){
110 // SoDB::finish();
111  coinUsed = false;
112  }
113 #endif
114 }
115 
116 
138 void
139 vpMbTracker::initClick(const vpImage<unsigned char>& _I, const std::string& _initFile, const bool _displayHelp)
140 {
141  vpHomogeneousMatrix last_cMo;
142  vpPoseVector init_pos;
143  vpImagePoint ip;
145 
146  std::string ext = ".init";
147  std::string str_pose = "";
148  unsigned int pos = _initFile.rfind(ext);
149 
150  // Load the last poses from files
151  std::fstream finitpos ;
152  std::fstream finit ;
153  char s[FILENAME_MAX];
154  if(poseSavingFilename.empty()){
155  if( pos == _initFile.size()-ext.size() && pos != 0)
156  str_pose = _initFile.substr(0,pos) + ".0.pos";
157  else
158  str_pose = _initFile + ".0.pos";
159 
160  finitpos.open(str_pose.c_str() ,std::ios::in) ;
161  sprintf(s, "%s", str_pose.c_str());
162  }else{
163  finitpos.open(poseSavingFilename.c_str() ,std::ios::in) ;
164  sprintf(s, "%s", poseSavingFilename.c_str());
165  }
166  if(finitpos.fail() ){
167  std::cout << "cannot read " << s << std::endl << "cMo set to identity" << std::endl;
168  last_cMo.setIdentity();
169  }
170  else{
171  for (unsigned int i = 0; i < 6; i += 1){
172  finitpos >> init_pos[i];
173  }
174 
175  finitpos.close();
176  last_cMo.buildFrom(init_pos) ;
177 
178  std::cout <<"last_cMo : "<<std::endl << last_cMo <<std::endl;
179 
180  vpDisplay::display(_I);
181  display(_I, last_cMo, cam, vpColor::green);
182  vpDisplay::displayFrame(_I, last_cMo, cam, 0.05, vpColor::green);
183  vpDisplay::flush(_I);
184 
185  std::cout << "No modification : left click " << std::endl;
186  std::cout << "Modify initial pose : right click " << std::endl ;
187 
188  vpDisplay::displayCharString(_I, 15, 10,
189  "left click to validate, right click to modify initial pose",
190  vpColor::red);
191 
192  vpDisplay::flush(_I) ;
193 
194  while (!vpDisplay::getClick(_I, ip, button)) ;
195  }
196 
197 
198  if (!finitpos.fail() && button == vpMouseButton::button1){
199  cMo = last_cMo ;
200  }
201  else
202  {
203  vpDisplay::display(_I) ;
204  vpDisplay::flush(_I) ;
205 
206  vpPose pose ;
207 
208  pose.clearPoint() ;
209 
210  // file parser
211  // number of points
212  // X Y Z
213  // X Y Z
214 
215  double X,Y,Z ;
216 
217  if( pos == _initFile.size()-ext.size() && pos != 0)
218  sprintf(s,"%s", _initFile.c_str());
219  else
220  sprintf(s,"%s.init", _initFile.c_str());
221 
222  std::cout << "filename " << s << std::endl ;
223  finit.open(s,std::ios::in) ;
224  if (finit.fail()){
225  std::cout << "cannot read " << s << std::endl;
226  throw vpException(vpException::ioError, "cannot read init file");
227  }
228 
229  std::string dispF;
230  if( pos == _initFile.size()-ext.size() && pos != 0)
231  dispF = _initFile.substr(0,pos) + ".ppm";
232  else
233  dispF = _initFile + ".ppm";
234 
235  sprintf(s, "%s", dispF.c_str());
236 
237  vpImage<vpRGBa> Iref ;
238  //Display window creation and initialistation
239 #if defined VISP_HAVE_X11
240  vpDisplayX d;
241 #elif defined VISP_HAVE_GDI
242  vpDisplayGDI d;
243 #elif defined VISP_HAVE_OPENCV
244  vpDisplayOpenCV d;
245 #endif
246  try{
247  if(_displayHelp){
248  vpImageIo::readPPM(Iref,s) ;
249 #if defined(VISP_HAVE_X11) || defined(VISP_HAVE_GDI) || defined(VISP_HAVE_OPENCV)
250  d.init(Iref,10,500, "Where to initialize...") ;
251  vpDisplay::display(Iref) ;
252  vpDisplay::flush(Iref);
253 #endif
254  }
255  }
256  catch(...){}
257 
258  unsigned int n ;
259  finit >> n ;
260  std::cout << "number of points " << n << std::endl ;
261  vpPoint *P = new vpPoint [n] ;
262  for (unsigned int i=0 ; i < n ; i++){
263  finit >> X ;
264  finit >> Y ;
265  finit >> Z ;
266  P[i].setWorldCoordinates(X,Y,Z) ; // (X,Y,Z)
267  }
268 
269  finit.close();
270 
272  bool isWellInit = false;
273  while(!isWellInit)
274  {
276  for(unsigned int i=0 ; i< n ; i++)
277  {
278  std::cout << "Click on point " << i+1 << std::endl ;
279  double x=0,y=0;
280  vpDisplay::getClick(_I, ip) ;
282  vpDisplay::flush(_I) ;
284  P[i].set_x(x);
285  P[i].set_y(y);
286 
287  std::cout << "click sur point " << ip << std::endl;
288 
289  vpDisplay::displayPoint (_I, ip, vpColor::green); //display target point
290  pose.addPoint(P[i]) ; // and added to the pose computation point list
291  }
292  vpDisplay::flush(_I) ;
293 
294  vpHomogeneousMatrix cMo1, cMo2;
295  pose.computePose(vpPose::LAGRANGE, cMo1) ;
296  double d1 = pose.computeResidual(cMo1);
297  pose.computePose(vpPose::DEMENTHON, cMo2) ;
298  double d2 = pose.computeResidual(cMo2);
299 
300  if(d1 < d2){
301  cMo = cMo1;
302  }
303  else{
304  cMo = cMo2;
305  }
307 
308  display(_I, cMo, cam, vpColor::green);
309  vpDisplay::displayCharString(_I, 15, 10,
310  "left click to validate, right click to re initialize object",
311  vpColor::red);
312 
313  vpDisplay::flush(_I) ;
314 
316  while (!vpDisplay::getClick(_I, ip, button)) ;
317 
318 
319  if (button == vpMouseButton::button1)
320  {
321  isWellInit = true;
322  }
323  else
324  {
325  pose.clearPoint() ;
326  vpDisplay::display(_I) ;
327  vpDisplay::flush(_I) ;
328  }
329  }
332 
333  delete [] P;
334 
335  //save the pose into file
336  if(poseSavingFilename.empty())
337  savePose(str_pose);
338  else
340  }
341 
342  std::cout <<"cMo : "<<std::endl << cMo <<std::endl;
343 
344  init(_I);
345 }
346 
355 void vpMbTracker::initClick(const vpImage<unsigned char>& _I, const std::vector<vpPoint> &points3D_list, const std::string &displayFile)
356 {
357  vpDisplay::display(_I) ;
358  vpDisplay::flush(_I) ;
359 
360  vpPose pose ;
361  vpPoint *P = new vpPoint [points3D_list.size()] ;
362  for (unsigned int i=0 ; i < points3D_list.size() ; i++)
363  P[i].setWorldCoordinates(points3D_list[i].get_oX(),points3D_list[i].get_oY(),points3D_list[i].get_oZ()) ;
364 
365  vpImage<vpRGBa> Iref ;
366  //Display window creation and initialistation
367  #if defined VISP_HAVE_X11
368  vpDisplayX d;
369  #elif defined VISP_HAVE_GDI
370  vpDisplayGDI d;
371  #elif defined VISP_HAVE_OPENCV
372  vpDisplayOpenCV d;
373  #endif
374 
375  if(displayFile != ""){
376  try{
377  std::cout << displayFile.c_str() << std::endl;
378  vpImageIo::readPPM(Iref,displayFile.c_str()) ;
379  #if defined(VISP_HAVE_X11) || defined(VISP_HAVE_GDI) || defined(VISP_HAVE_OPENCV)
380  d.init(Iref,10,500, "Where to initialize...") ;
381  vpDisplay::display(Iref) ;
382  vpDisplay::flush(Iref);
383  #endif
384  }
385  catch(...){}
386  }
387 
388  vpImagePoint ip;
389  bool isWellInit = false;
390  while(!isWellInit)
391  {
392  for(unsigned int i=0 ; i< points3D_list.size() ; i++)
393  {
394  std::cout << "Click on point " << i+1 << std::endl ;
395  double x=0,y=0;
396  vpDisplay::getClick(_I, ip) ;
398  vpDisplay::flush(_I) ;
400  P[i].set_x(x);
401  P[i].set_y(y);
402 
403  std::cout << "Click on point " << ip << std::endl;
404 
405  vpDisplay::displayPoint (_I, ip, vpColor::green); //display target point
406  pose.addPoint(P[i]) ; // and added to the pose computation point list
407  }
408  vpDisplay::flush(_I) ;
409 
410  vpHomogeneousMatrix cMo1, cMo2;
411  pose.computePose(vpPose::LAGRANGE, cMo1) ;
412  double d1 = pose.computeResidual(cMo1);
413  pose.computePose(vpPose::DEMENTHON, cMo2) ;
414  double d2 = pose.computeResidual(cMo2);
415 
416  if(d1 < d2){
417  cMo = cMo1;
418  }
419  else{
420  cMo = cMo2;
421  }
423 
424  display(_I, cMo, cam, vpColor::green);
425  vpDisplay::displayCharString(_I, 15, 10,
426  "left click to validate, right click to re initialize object",
427  vpColor::red);
428 
429  vpDisplay::flush(_I) ;
430 
432  while (!vpDisplay::getClick(_I, ip, button)) ;
433 
434 
435  if (button == vpMouseButton::button1)
436  {
437  isWellInit = true;
438  }
439  else
440  {
441  pose.clearPoint() ;
442  vpDisplay::display(_I) ;
443  vpDisplay::flush(_I) ;
444  }
445  }
446 
448 
449  delete [] P;
450 
451  init(_I);
452 }
453 
471 void vpMbTracker::initFromPoints( const vpImage<unsigned char>& _I, const std::string& _initFile )
472 {
473  char s[FILENAME_MAX];
474  std::fstream finit ;
475 
476  std::string ext = ".init";
477  unsigned int pos = _initFile.rfind(ext);
478 
479  if( pos == _initFile.size()-ext.size() && pos != 0)
480  sprintf(s,"%s", _initFile.c_str());
481  else
482  sprintf(s,"%s.init", _initFile.c_str());
483 
484  std::cout << "filename " << s << std::endl ;
485  finit.open(s,std::ios::in) ;
486  if (finit.fail()){
487  std::cout << "cannot read " << s << std::endl;
488  throw vpException(vpException::ioError, "cannot read init file");
489  }
490 
491  unsigned int size;
492  double X, Y, Z;
493  finit >> size ;
494  std::cout << "number of points " << size << std::endl ;
495  vpPoint *P = new vpPoint [size];
496  vpPose pose ;
497 
498  for(unsigned int i=0 ; i< size ; i++)
499  {
500  finit >> X ;
501  finit >> Y ;
502  finit >> Z ;
503  P[i].setWorldCoordinates(X,Y,Z) ;
504  }
505 
506  unsigned int size2;
507  double x, y;
508  vpImagePoint ip;
509  finit >> size2 ;
510  if(size != size2)
511  vpERROR_TRACE( "vpMbTracker::initFromPoints(), Number of 2D points different to the number of 3D points." );
512 
513  for(unsigned int i=0 ; i< size ; i++)
514  {
515  finit >> x;
516  finit >> y;
517  ip = vpImagePoint(x,y);
519  P[i].set_x(x);
520  P[i].set_y(y);
521  pose.addPoint(P[i]);
522  }
523 
524  vpHomogeneousMatrix cMo1, cMo2;
525  pose.computePose(vpPose::LAGRANGE, cMo1) ;
526  double d1 = pose.computeResidual(cMo1);
527  pose.computePose(vpPose::DEMENTHON, cMo2) ;
528  double d2 = pose.computeResidual(cMo2);
529 
530  if(d1 < d2)
531  cMo = cMo1;
532  else
533  cMo = cMo2;
534 
536 
537  delete [] P;
538 
539  init(_I);
540 }
541 
550 void vpMbTracker::initFromPoints( const vpImage<unsigned char>& _I, const std::vector<vpImagePoint> &points2D_list, const std::vector<vpPoint> &points3D_list )
551 {
552  if(points2D_list.size() != points3D_list.size())
553  vpERROR_TRACE( "vpMbTracker::initFromPoints(), Number of 2D points different to the number of 3D points." );
554 
555  unsigned int size = points3D_list.size();
556  vpPoint *P = new vpPoint [size];
557  vpPose pose ;
558 
559  for(unsigned int i=0 ; i< size ; i++)
560  {
561  P[i].setWorldCoordinates(points3D_list[i].get_oX(),points3D_list[i].get_oY(),points3D_list[i].get_oZ()) ;
562  double x=0,y=0;
563  vpPixelMeterConversion::convertPoint(cam, points2D_list[i], x, y);
564  P[i].set_x(x);
565  P[i].set_y(y);
566  pose.addPoint(P[i]);
567  }
568 
569  vpHomogeneousMatrix cMo1, cMo2;
570  pose.computePose(vpPose::LAGRANGE, cMo1) ;
571  double d1 = pose.computeResidual(cMo1);
572  pose.computePose(vpPose::DEMENTHON, cMo2) ;
573  double d2 = pose.computeResidual(cMo2);
574 
575  if(d1 < d2)
576  cMo = cMo1;
577  else
578  cMo = cMo2;
579 
581 
582  delete [] P;
583 
584  init(_I);
585 }
586 
604 void vpMbTracker::initFromPose(const vpImage<unsigned char>& _I, const std::string &_initFile)
605 {
606  char s[FILENAME_MAX];
607  std::fstream finit ;
608  vpPoseVector init_pos;
609 
610  std::string ext = ".pos";
611  unsigned int pos = _initFile.rfind(ext);
612 
613  if( pos == _initFile.size()-ext.size() && pos != 0)
614  sprintf(s,"%s", _initFile.c_str());
615  else
616  sprintf(s,"%s.pos", _initFile.c_str());
617 
618  std::cout << "filename " << s << std::endl ;
619  finit.open(s,std::ios::in) ;
620  if (finit.fail()){
621  std::cout << "cannot read " << s << std::endl;
622  throw vpException(vpException::ioError, "cannot read init file");
623  }
624 
625  for (unsigned int i = 0; i < 6; i += 1){
626  finit >> init_pos[i];
627  }
628 
629  cMo.buildFrom(init_pos);
630  init(_I);
631 }
632 
640 {
641  cMo = _cMo;
642  init(_I);
643 }
644 
652 {
653  vpHomogeneousMatrix _cMo(cPo);
654  initFromPose(_I, _cMo);
655 }
656 
662 void vpMbTracker::savePose(const std::string &filename)
663 {
664  vpPoseVector init_pos;
665  std::fstream finitpos ;
666  char s[FILENAME_MAX];
667 
668  sprintf(s,"%s", filename.c_str());
669  finitpos.open(s, std::ios::out) ;
670 
671  init_pos.buildFrom(cMo);
672  finitpos << init_pos;
673  finitpos.close();
674 }
675 
686 void
687 vpMbTracker::loadModel(const std::string& _modelFile)
688 {
689  std::string::const_iterator it;
690 
691  if(vpIoTools::checkFilename(_modelFile)){
692  it = _modelFile.end();
693  if((*(it-1) == 'o' && *(it-2) == 'a' && *(it-3) == 'c' && *(it-4) == '.') ||
694  (*(it-1) == 'O' && *(it-2) == 'A' && *(it-3) == 'C' && *(it-4) == '.') ){
695  loadCAOModel(_modelFile);
696  }
697  else if((*(it-1) == 'l' && *(it-2) == 'r' && *(it-3) == 'w' && *(it-4) == '.') ||
698  (*(it-1) == 'L' && *(it-2) == 'R' && *(it-3) == 'W' && *(it-4) == '.') ){
699  loadVRMLModel(_modelFile);
700  }
701  else{
702  throw vpException(vpException::ioError, "file cannot be open");
703  }
704  }
705  else{
706  throw vpException(vpException::ioError, "file cannot be open");
707  }
708 
709  this->modelInitialised = true;
710  this->modelFileName = _modelFile;
711 }
712 
713 
733 void
734 vpMbTracker::loadVRMLModel(const std::string& _modelFile)
735 {
736 #ifdef VISP_HAVE_COIN
737  if(!coinUsed){
738  SoDB::init();
739  coinUsed = true;
740  }
741  SoInput in;
742  SbBool ok = in.openFile(_modelFile.c_str());
743  SoSeparator *sceneGraph;
744  SoVRMLGroup *sceneGraphVRML2;
745 
746  if (!ok) {
747  vpERROR_TRACE("can't open file to load model");
748  throw vpException(vpException::fatalError, "can't open file to load model");
749  }
750 
751  if(!in.isFileVRML2())
752  {
753  sceneGraph = SoDB::readAll(&in);
754  if (sceneGraph == NULL) { /*return -1;*/ }
755  sceneGraph->ref();
756 
757  SoToVRML2Action tovrml2;
758  tovrml2.apply(sceneGraph);
759  sceneGraphVRML2 =tovrml2.getVRML2SceneGraph();
760  sceneGraphVRML2->ref();
761  sceneGraph->unref();
762  }
763  else
764  {
765  sceneGraphVRML2 = SoDB::readAllVRML(&in);
766  if (sceneGraphVRML2 == NULL) { /*return -1;*/ }
767  sceneGraphVRML2->ref();
768  }
769 
770  in.closeFile();
771 
772  int nbShapes = sceneGraphVRML2->getNumChildren();
773 
774  SoNode * child;
775 
776  for (int i = 0; i < nbShapes; i++)
777  {
778  child = sceneGraphVRML2->getChild(i);
779  if (child->getTypeId() == SoVRMLShape::getClassTypeId())
780  {
781  SoChildList * child2list = child->getChildren();
782  for (int j = 0; j < child2list->getLength(); j++)
783  {
784  if (((SoNode*)child2list->get(j))->getTypeId() == SoVRMLIndexedFaceSet::getClassTypeId())
785  {
786  SoVRMLIndexedFaceSet * face_set;
787  face_set = (SoVRMLIndexedFaceSet*)child2list->get(j);
788  if(!strncmp(face_set->getName().getString(),"cyl",3)){
789  extractCylinders(face_set);
790  }else{
791  extractFaces(face_set);
792  }
793  }
794  if (((SoNode*)child2list->get(j))->getTypeId() == SoVRMLIndexedLineSet::getClassTypeId())
795  {
796  SoVRMLIndexedLineSet * line_set;
797  line_set = (SoVRMLIndexedLineSet*)child2list->get(j);
798  extractLines(line_set);
799  }
800  }
801  }
802  }
803 
804  sceneGraphVRML2->unref();
805 #else
806  vpERROR_TRACE("coin not detected with ViSP, cannot load model : %s", _modelFile.c_str());
807  throw vpException(vpException::fatalError, "coin not detected with ViSP, cannot load model");
808 #endif
809 }
810 
811 
838 void
839 vpMbTracker::loadCAOModel(const std::string& _modelFile)
840 {
841  std::ifstream file_id;
842  file_id.open (_modelFile.c_str(), std::ifstream::in);
843  if(file_id.fail()) {
844  std::cout << "cannot read CAO model file: " << _modelFile << std::endl;
845  throw vpException(vpException::ioError, "cannot read CAO model file");
846  }
847 
848 
849  char c;
850  // Extraction of the version (remove empty line and commented ones (comment
851  // line begin with the #)).
852  while( (file_id.get(c)!=NULL)&&(c == '#')) file_id.ignore(256,'\n');
853  file_id.unget();
854 
855  int caoVersion;
856  file_id.get(c);
857  if(c=='V'){
858  file_id >> caoVersion;
859  }
860  else{
861  std::cout <<"in vpMbEdgeTracker::loadCAOModel -> Bad parameter header file : use V0, V1, ...";
863  "in vpMbEdgeTracker::loadCAOModel -> Bad parameter header file : use V0, V1, ...");
864  }
865 
866  while( (file_id.get(c)!=NULL)&&(c!='\n')) ;
867  while( (file_id.get(c)!=NULL)&&(c == '#')) file_id.ignore(256,'\n') ;
868  file_id.unget();
869 
870  //Read the points
871  unsigned int caoNbrPoint;
872  file_id >> caoNbrPoint;
873  std::cout << "> " << caoNbrPoint << " points" << std::endl;
874  vpPoint *caoPoints = NULL;
875  if (caoNbrPoint > 0)
876  caoPoints = new vpPoint[caoNbrPoint];
877 
878  double x ; // 3D coordinates
879  double y ;
880  double z ;
881 
882  int i ; // image coordinate (used for matching)
883  int j ;
884 
885 
886  for(unsigned int k=0; k < caoNbrPoint; k++){
887  file_id >> x ;
888  file_id >> y ;
889  file_id >> z ;
890  if (caoVersion == 2){
891  file_id >> i ;
892  file_id >> j ;
893  }
894 
895  if(k != caoNbrPoint-1){// the rest of the line is removed (not the last one due to the need to remove possible comments).
896  file_id.ignore(256,'\n');
897  }
898  caoPoints[k].setWorldCoordinates(x, y, z) ;
899  }
900 
901  while( (file_id.get(c)!=NULL)&&(c!='\n')) ;
902  while( (file_id.get(c)!=NULL)&&(c == '#')) file_id.ignore(256,'\n');
903  file_id.unget();
904 
905  //Read the lines
906  unsigned int caoNbrLine;
907  file_id >> caoNbrLine;
908  unsigned int *caoLinePoints = NULL;
909  std::cout << "> " << caoNbrLine << " lines" << std::endl;
910  if (caoNbrLine > 0)
911  caoLinePoints = new unsigned int[2*caoNbrLine];
912 
913  unsigned int index1, index2;
914 
915  for(unsigned int k=0; k < caoNbrLine ; k++){
916  file_id >> index1 ;
917  file_id >> index2 ;
918 
919  caoLinePoints[2*k] = index1;
920  caoLinePoints[2*k+1] = index2;
921 
922  if(index1 < caoNbrPoint && index2 < caoNbrPoint){
923  std::vector<vpPoint> extremities;
924  extremities.push_back(caoPoints[index1]);
925  extremities.push_back(caoPoints[index2]);
926  initFaceFromCorners(extremities, k);
927  }
928  else{
929  vpTRACE(" line %d has wrong coordinates.", k);
930  }
931 
932  if(k != caoNbrLine-1){// the rest of the line is removed (not the last one due to the need to remove possible comments).
933  file_id.ignore(256,'\n');
934  }
935  }
936 
937  while( (file_id.get(c)!=NULL)&&(c!='\n')) ;
938  while( (file_id.get(c)!=NULL)&&(c == '#')) file_id.ignore(256,'\n');
939  file_id.unget();
940 
941 
942  /* Load polygon from the lines extracted earlier
943  (the first point of the line is used)*/
944  unsigned int caoNbrPolygonLine;
945  file_id >> caoNbrPolygonLine;
946  std::cout << "> " << caoNbrPolygonLine << " polygon line" << std::endl;
947  unsigned int index;
948  for(unsigned int k = 0;k < caoNbrPolygonLine; k++){
949  unsigned int nbLinePol;
950  file_id >> nbLinePol;
951  std::vector<vpPoint> corners;
952  for(unsigned int i = 0; i < nbLinePol; i++){
953  file_id >> index;
954  corners.push_back(caoPoints[caoLinePoints[2*index]]);
955  }
956  if(k != caoNbrPolygonLine-1){// the rest of the line is removed (not the last one due to the need to remove possible comments).
957  file_id.ignore(256,'\n');
958  }
959  initFaceFromCorners(corners, k);
960  }
961 
962  while( (file_id.get(c)!=NULL)&&(c!='\n')) ;
963  while( (file_id.get(c)!=NULL)&&(c == '#')) file_id.ignore(256,'\n');
964  file_id.unget();
965 
966  /* Extract the polygon using the point coordinates (top of the file) */
967  unsigned int caoNbrPolygonPoint;
968  file_id >> caoNbrPolygonPoint;
969  std::cout << "> " << caoNbrPolygonPoint << " polygon point" << std::endl;
970  for(unsigned int k = 0;k < caoNbrPolygonPoint; k++){
971  int nbPointPol;
972  file_id >> nbPointPol;
973  std::vector<vpPoint> corners;
974  for(int i = 0; i < nbPointPol; i++){
975  file_id >> index;
976  corners.push_back(caoPoints[index]);
977  }
978  if(k != caoNbrPolygonPoint-1){// the rest of the line is removed (not the last one due to the need to remove possible comments).
979  file_id.ignore(256,'\n');
980  }
981  initFaceFromCorners(corners, k);
982  }
983 
984 
985  while( (file_id.get(c)!=NULL)&&(c!='\n')) ;
986  while( (file_id.get(c)!=NULL)&&(c == '#')) file_id.ignore(256,'\n');
987  file_id.unget();
988 
989  if(file_id.eof()){// check if not at the end of the file (for old style files)
990  delete[] caoPoints;
991  delete[] caoLinePoints;
992  return ;
993  }
994 
995  /* Extract the cylinders */
996  try{
997  unsigned int caoNbCylinder;
998  file_id >> caoNbCylinder;
999  std::cout << "> " << caoNbCylinder << " cylinder" << std::endl;
1000  for(unsigned int k=0; k<caoNbCylinder; ++k){
1001  double radius;
1002  unsigned int indexP1, indexP2;
1003  file_id >> indexP1;
1004  file_id >> indexP2;
1005  file_id >> radius;
1006  initCylinder(caoPoints[indexP1], caoPoints[indexP2], radius);
1007  }
1008 
1009  }catch(...){
1010  std::cerr << "Cannot get the number of cylinder" << std::endl;
1011  }
1012 
1013  delete[] caoPoints;
1014  delete[] caoLinePoints;
1015 }
1016 
1017 
1018 
1019 
1020 #ifdef VISP_HAVE_COIN
1021 
1027 void
1028 vpMbTracker::extractFaces(SoVRMLIndexedFaceSet* _face_set)
1029 {
1030  std::vector<vpPoint> corners;
1031  corners.resize(0);
1032 
1033 // SoMFInt32 indexList = _face_set->coordIndex;
1034 // int indexListSize = indexList.getNum();
1035  int indexListSize = _face_set->coordIndex.getNum();
1036  SbVec3f point(0,0,0);
1037  vpPoint pt;
1038  SoVRMLCoordinate *coord;
1039 
1040  unsigned int indexFace = 0;
1041 
1042  for (int i = 0; i < indexListSize; i++)
1043  {
1044  if (_face_set->coordIndex[i] == -1)
1045  {
1046  if(corners.size() > 1)
1047  {
1048  initFaceFromCorners(corners, indexFace);
1049  indexFace++;
1050  corners.resize(0);
1051  }
1052  }
1053  else
1054  {
1055  coord = (SoVRMLCoordinate *)(_face_set->coord.getValue());
1056  int index = _face_set->coordIndex[i];
1057  point[0]=coord->point[index].getValue()[0];
1058  point[1]=coord->point[index].getValue()[1];
1059  point[2]=coord->point[index].getValue()[2];
1060  pt.setWorldCoordinates(point[0],point[1],point[2]);
1061  corners.push_back(pt);
1062  }
1063  }
1064 }
1065 
1077 void
1078 vpMbTracker::extractCylinders(SoVRMLIndexedFaceSet* _face_set)
1079 {
1080  std::vector<vpPoint> corners_c1, corners_c2;//points belonging to the first circle and to the second one.
1081  SoVRMLCoordinate* coords = (SoVRMLCoordinate *)_face_set->coord.getValue();
1082 
1083  unsigned int indexListSize = (unsigned int)coords->point.getNum();
1084 
1085  if(indexListSize % 2 == 1){
1086  std::cout << "Not an even number of points when extracting a cylinder." << std::endl;
1087  throw vpException(vpException::dimensionError, "Not an even number of points when extracting a cylinder.");
1088  }
1089  corners_c1.resize(indexListSize / 2);
1090  corners_c2.resize(indexListSize / 2);
1091  SbVec3f point(0,0,0);
1092  vpPoint pt;
1093 
1094 
1095  // extract all points and fill the two sets.
1096  for(int i=0; i<coords->point.getNum(); ++i){
1097  point[0]=coords->point[i].getValue()[0];
1098  point[1]=coords->point[i].getValue()[1];
1099  point[2]=coords->point[i].getValue()[2];
1100 
1101  pt.setWorldCoordinates(point[0], point[1], point[2]);
1102 
1103  if(i < (int)corners_c1.size()){
1104  corners_c1[(unsigned int)i] = pt;
1105  }else{
1106  corners_c2[(unsigned int)i-corners_c1.size()] = pt;
1107  }
1108  }
1109 
1110  vpPoint p1 = getGravityCenter(corners_c1);
1111  vpPoint p2 = getGravityCenter(corners_c2);
1112 
1113  vpColVector dist(3);
1114  dist[0] = p1.get_oX() - corners_c1[0].get_oX();
1115  dist[1] = p1.get_oY() - corners_c1[0].get_oY();
1116  dist[2] = p1.get_oZ() - corners_c1[0].get_oZ();
1117  double radius_c1 = sqrt(dist.sumSquare());
1118  dist[0] = p2.get_oX() - corners_c2[0].get_oX();
1119  dist[1] = p2.get_oY() - corners_c2[0].get_oY();
1120  dist[2] = p2.get_oZ() - corners_c2[0].get_oZ();
1121  double radius_c2 = sqrt(dist.sumSquare());
1122 
1123  if(std::fabs(radius_c1 - radius_c2) > (std::numeric_limits<double>::epsilon() * vpMath::maximum(radius_c1, radius_c2))){
1124  std::cout << "Radius from the two circles of the cylinders are different." << std::endl;
1125  throw vpException(vpException::badValue, "Radius from the two circles of the cylinders are different.");
1126  }
1127 
1128  initCylinder(p1, p2, radius_c1);
1129 
1130 }
1131 
1141 vpPoint
1142 vpMbTracker::getGravityCenter(const std::vector<vpPoint>& _pts)
1143 {
1144  if(_pts.empty()){
1145  std::cout << "Cannot extract center of gravity of empty set." << std::endl;
1146  throw vpException(vpException::dimensionError, "Cannot extract center of gravity of empty set.");
1147  }
1148  double oX = 0;
1149  double oY = 0;
1150  double oZ = 0;
1151  vpPoint G;
1152 
1153  for(unsigned int i=0; i<_pts.size(); ++i){
1154  oX += _pts[i].get_oX();
1155  oY += _pts[i].get_oY();
1156  oZ += _pts[i].get_oZ();
1157  }
1158 
1159  G.setWorldCoordinates(oX/_pts.size(), oY/_pts.size(), oZ/_pts.size());
1160  return G;
1161 }
1162 
1163 
1170 void
1171 vpMbTracker::extractLines(SoVRMLIndexedLineSet* _line_set)
1172 {
1173  std::vector<vpPoint> corners;
1174  corners.resize(0);
1175 
1176  int indexListSize = _line_set->coordIndex.getNum();
1177 
1178  SbVec3f point(0,0,0);
1179  vpPoint pt;
1180  SoVRMLCoordinate *coord;
1181 
1182  unsigned int indexFace = 0;
1183 
1184  for (int i = 0; i < indexListSize; i++)
1185  {
1186  if (_line_set->coordIndex[i] == -1)
1187  {
1188  if(corners.size() > 1)
1189  {
1190  initFaceFromCorners(corners, indexFace);
1191  indexFace++;
1192  corners.resize(0);
1193  }
1194  }
1195  else
1196  {
1197  coord = (SoVRMLCoordinate *)(_line_set->coord.getValue());
1198  int index = _line_set->coordIndex[i];
1199  point[0]=coord->point[index].getValue()[0];
1200  point[1]=coord->point[index].getValue()[1];
1201  point[2]=coord->point[index].getValue()[2];
1202 
1203  pt.setWorldCoordinates(point[0],point[1],point[2]);
1204  corners.push_back(pt);
1205  }
1206  }
1207 }
1208 
1209 #endif
1210 
1225 void
1226 vpMbTracker::computeJTR(const vpMatrix& _interaction, const vpColVector& _error, vpMatrix& _JTR)
1227 {
1228  if(_interaction.getRows() != _error.getRows() || _interaction.getCols() != 6 ){
1230  "Incorrect matrices size in computeJTR.");
1231  }
1232 
1233  _JTR.resize(6, 1);
1234  const unsigned int N = _interaction.getRows();
1235 
1236  for (unsigned int i = 0; i < 6; i += 1){
1237  double ssum = 0;
1238  for (unsigned int j = 0; j < N; j += 1){
1239  ssum += _interaction[j][i] * _error[j];
1240  }
1241  _JTR[i][0] = ssum;
1242  }
1243 }
1244 
1245 
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()
void resize(const unsigned int nrows, const unsigned int ncols, const bool nullify=true)
Definition: vpMatrix.cpp:174
virtual void loadModel(const std::string &_modelFile)
virtual void loadVRMLModel(const std::string &_modelFile)
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
#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:101
virtual void initFromPose(const vpImage< unsigned char > &_I, const std::string &_initFile)
void computeJTR(const vpMatrix &_J, const vpColVector &_R, vpMatrix &_JTR)
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:105
double get_oY() const
Get the point Y coordinate in the object frame.
Definition: vpPoint.h:136
void set_x(const double x)
Set the point x coordinate in the image plane.
Definition: vpPoint.h:183
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...
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:103
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:113
static const vpColor green
Definition: vpColor.h:168
static void flush(const vpImage< unsigned char > &I)
Definition: vpDisplay.cpp:1964
virtual void display(const vpImage< unsigned char > &_I, const vpHomogeneousMatrix &_cMo, const vpCameraParameters &_cam, const vpColor &_col, const unsigned int _l=1, const bool displayFullModel=false)=0
bool cameraInitialised
Flag used to ensure that the camera is set before the initialisation.
Definition: vpMbTracker.h:107
static const vpColor red
Definition: vpColor.h:165
Class that defines what is a point.
Definition: vpPoint.h:65
vpPoseVector buildFrom(const vpHomogeneousMatrix &M)
vpCameraParameters cam
The camera parameters.
Definition: vpMbTracker.h:99
static Type maximum(const Type &a, const Type &b)
Definition: vpMath.h:137
virtual void initClick(const vpImage< unsigned char > &_I, const std::string &_initFile, const bool _displayHelp=false)
static bool checkFilename(const char *filename)
Definition: vpIoTools.cpp:439
virtual void initFromPoints(const vpImage< unsigned char > &_I, const std::string &_initFile)
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
double computeResidual(vpHomogeneousMatrix &cMo)
Compute and return the residual expressed in meter for the pose matrix 'cMo'.
Definition: vpPose.cpp:255
double get_oZ() const
Get the point Z coordinate in the object frame.
Definition: vpPoint.h:138
virtual void extractFaces(SoVRMLIndexedFaceSet *_face_set)
void set_y(const double y)
Set the point y coordinate in the image plane.
Definition: vpPoint.h:185
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.
virtual void extractLines(SoVRMLIndexedLineSet *_line_set)
std::string poseSavingFilename
Filename used to save the initial pose computed using the initClick() method. It is also used to read...
Definition: vpMbTracker.h:111
virtual void initCylinder(const vpPoint &_p1, const vpPoint _p2, const double _radius, const unsigned int _indexCylinder=0)=0
double get_oX() const
Get the point X coordinate in the object frame.
Definition: vpPoint.h:134
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:109
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 init(const vpImage< unsigned char > &_I)=0
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
virtual void loadCAOModel(const std::string &_modelFile)
virtual void initFaceFromCorners(const std::vector< vpPoint > &_corners, const unsigned int _indexFace=-1)=0
void computePose(vpPoseMethodType methode, vpHomogeneousMatrix &cMo)
compute the pose for a given method
Definition: vpPose.cpp:298
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 extractCylinders(SoVRMLIndexedFaceSet *_face_set)
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:148
virtual void displayPoint(const vpImagePoint &ip, const vpColor &color)=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 clearPoint()
suppress all the point in the array of point
Definition: vpPose.cpp:126