ViSP  2.9.0
vpMbTracker.cpp
1 /****************************************************************************
2  *
3  * $Id: vpMbTracker.cpp 4649 2014-02-07 14:57:11Z fspindle $
4  *
5  * This file is part of the ViSP software.
6  * Copyright (C) 2005 - 2014 by INRIA. All rights reserved.
7  *
8  * This software is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * ("GPL") version 2 as published by the Free Software Foundation.
11  * See the file LICENSE.txt at the root directory of this source
12  * distribution for additional information about the GNU GPL.
13  *
14  * For using ViSP with software that can not be combined with the GNU
15  * GPL, please contact INRIA about acquiring a ViSP Professional
16  * Edition License.
17  *
18  * See http://www.irisa.fr/lagadic/visp/visp.html for more information.
19  *
20  * This software was developed at:
21  * INRIA Rennes - Bretagne Atlantique
22  * Campus Universitaire de Beaulieu
23  * 35042 Rennes Cedex
24  * France
25  * http://www.irisa.fr/lagadic
26  *
27  * If you have questions regarding the use of this file, please contact
28  * INRIA at visp@inria.fr
29  *
30  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
31  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
32  *
33  * 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  : cam(), cMo(), modelFileName(), modelInitialised(false),
97  poseSavingFilename(), computeCovariance(false), covarianceMatrix(), displayFeatures(false)
98 {
99 }
100 
105 {
106 }
107 
108 
130 void
131 vpMbTracker::initClick(const vpImage<unsigned char>& I, const std::string& initFile, const bool displayHelp)
132 {
133  vpHomogeneousMatrix last_cMo;
134  vpPoseVector init_pos;
135  vpImagePoint ip;
137 
138  std::string ext = ".init";
139  std::string str_pose = "";
140  size_t pos = (unsigned int)initFile.rfind(ext);
141 
142  // Load the last poses from files
143  std::fstream finitpos ;
144  std::fstream finit ;
145  char s[FILENAME_MAX];
146  if(poseSavingFilename.empty()){
147  if( pos == initFile.size()-ext.size() && pos != 0)
148  str_pose = initFile.substr(0,pos) + ".0.pos";
149  else
150  str_pose = initFile + ".0.pos";
151 
152  finitpos.open(str_pose.c_str() ,std::ios::in) ;
153  sprintf(s, "%s", str_pose.c_str());
154  }else{
155  finitpos.open(poseSavingFilename.c_str() ,std::ios::in) ;
156  sprintf(s, "%s", poseSavingFilename.c_str());
157  }
158  if(finitpos.fail() ){
159  std::cout << "cannot read " << s << std::endl << "cMo set to identity" << std::endl;
160  last_cMo.setIdentity();
161  }
162  else{
163  for (unsigned int i = 0; i < 6; i += 1){
164  finitpos >> init_pos[i];
165  }
166 
167  finitpos.close();
168  last_cMo.buildFrom(init_pos) ;
169 
170  std::cout <<"last_cMo : "<<std::endl << last_cMo <<std::endl;
171 
173  display(I, last_cMo, cam, vpColor::green, 1, true);
174  vpDisplay::displayFrame(I, last_cMo, cam, 0.05, vpColor::green);
175  vpDisplay::flush(I);
176 
177  std::cout << "No modification : left click " << std::endl;
178  std::cout << "Modify initial pose : right click " << std::endl ;
179 
181  "left click to validate, right click to modify initial pose",
182  vpColor::red);
183 
184  vpDisplay::flush(I) ;
185 
186  while (!vpDisplay::getClick(I, ip, button)) ;
187  }
188 
189 
190  if (!finitpos.fail() && button == vpMouseButton::button1){
191  cMo = last_cMo ;
192  }
193  else
194  {
195  vpDisplay::display(I) ;
196  vpDisplay::flush(I) ;
197 
198  vpPose pose ;
199 
200  pose.clearPoint() ;
201 
202  // file parser
203  // number of points
204  // X Y Z
205  // X Y Z
206 
207  double X,Y,Z ;
208 
209  if( pos == initFile.size()-ext.size() && pos != 0)
210  sprintf(s,"%s", initFile.c_str());
211  else
212  sprintf(s,"%s.init", initFile.c_str());
213 
214  std::cout << "filename " << s << std::endl ;
215  finit.open(s,std::ios::in) ;
216  if (finit.fail()){
217  std::cout << "cannot read " << s << std::endl;
218  throw vpException(vpException::ioError, "cannot read init file");
219  }
220 
221  std::string dispF;
222  if( pos == initFile.size()-ext.size() && pos != 0)
223  dispF = initFile.substr(0,pos) + ".ppm";
224  else
225  dispF = initFile + ".ppm";
226 
227  sprintf(s, "%s", dispF.c_str());
228 
229  vpImage<vpRGBa> Iref ;
230  //Display window creation and initialistation
231 #if defined VISP_HAVE_X11
232  vpDisplayX d;
233 #elif defined VISP_HAVE_GDI
234  vpDisplayGDI d;
235 #elif defined VISP_HAVE_OPENCV
236  vpDisplayOpenCV d;
237 #endif
238  try{
239  if(displayHelp){
240  vpImageIo::read(Iref,s) ;
241 #if defined(VISP_HAVE_X11) || defined(VISP_HAVE_GDI) || defined(VISP_HAVE_OPENCV)
242  d.init(Iref,10,500, "Where to initialize...") ;
243  vpDisplay::display(Iref) ;
244  vpDisplay::flush(Iref);
245 #endif
246  }
247  }
248  catch(...){}
249 
250  unsigned int n ;
251  finit >> n ;
252  std::cout << "number of points " << n << std::endl ;
253  if (n > 100000) {
255  "Exceed the max number of points.");
256  }
257 
258  vpPoint *P = new vpPoint [n] ;
259  for (unsigned int i=0 ; i < n ; i++){
260  finit >> X ;
261  finit >> Y ;
262  finit >> Z ;
263  P[i].setWorldCoordinates(X,Y,Z) ; // (X,Y,Z)
264  }
265 
266  finit.close();
267 
269  bool isWellInit = false;
270  while(!isWellInit)
271  {
273  for(unsigned int i=0 ; i< n ; i++)
274  {
275  std::cout << "Click on point " << i+1 << std::endl ;
276  double x=0,y=0;
277  vpDisplay::getClick(I, ip) ;
279  vpDisplay::flush(I) ;
281  P[i].set_x(x);
282  P[i].set_y(y);
283 
284  std::cout << "click sur point " << ip << std::endl;
285 
286  vpDisplay::displayPoint (I, ip, vpColor::green); //display target point
287  pose.addPoint(P[i]) ; // and added to the pose computation point list
288  }
289  vpDisplay::flush(I) ;
290 
291  vpHomogeneousMatrix cMo1, cMo2;
292  pose.computePose(vpPose::LAGRANGE, cMo1) ;
293  double d1 = pose.computeResidual(cMo1);
294  pose.computePose(vpPose::DEMENTHON, cMo2) ;
295  double d2 = pose.computeResidual(cMo2);
296 
297  if(d1 < d2){
298  cMo = cMo1;
299  }
300  else{
301  cMo = cMo2;
302  }
304 
305  display(I, cMo, cam, vpColor::green, 1, true);
307  "left click to validate, right click to re initialize object",
308  vpColor::red);
309 
310  vpDisplay::flush(I) ;
311 
312  button = vpMouseButton::button1;
313  while (!vpDisplay::getClick(I, ip, button)) ;
314 
315 
316  if (button == vpMouseButton::button1)
317  {
318  isWellInit = true;
319  }
320  else
321  {
322  pose.clearPoint() ;
323  vpDisplay::display(I) ;
324  vpDisplay::flush(I) ;
325  }
326  }
329 
330  delete [] P;
331 
332  //save the pose into file
333  if(poseSavingFilename.empty())
334  savePose(str_pose);
335  else
337  }
338 
339  std::cout <<"cMo : "<<std::endl << cMo <<std::endl;
340 
341  init(I);
342 }
343 
352 void vpMbTracker::initClick(const vpImage<unsigned char>& I, const std::vector<vpPoint> &points3D_list,
353  const std::string &displayFile)
354 {
355  vpDisplay::display(I) ;
356  vpDisplay::flush(I) ;
357 
358  vpPose pose ;
359  vpPoint *P = NULL; P = new vpPoint [points3D_list.size()] ;
360  for (unsigned int i=0 ; i < points3D_list.size() ; i++)
361  P[i].setWorldCoordinates(points3D_list[i].get_oX(),points3D_list[i].get_oY(),points3D_list[i].get_oZ()) ;
362 
363  vpImage<vpRGBa> Iref ;
364  //Display window creation and initialistation
365  #if defined VISP_HAVE_X11
366  vpDisplayX d;
367  #elif defined VISP_HAVE_GDI
368  vpDisplayGDI d;
369  #elif defined VISP_HAVE_OPENCV
370  vpDisplayOpenCV d;
371  #endif
372 
373  if(displayFile != ""){
374  try{
375  std::cout << displayFile.c_str() << std::endl;
376  vpImageIo::read(Iref,displayFile.c_str()) ;
377  #if defined(VISP_HAVE_X11) || defined(VISP_HAVE_GDI) || defined(VISP_HAVE_OPENCV)
378  d.init(Iref,10,500, "Where to initialize...") ;
379  vpDisplay::display(Iref) ;
380  vpDisplay::flush(Iref);
381  #endif
382  }
383  catch(...){}
384  }
385 
386  vpImagePoint ip;
387  bool isWellInit = false;
388  while(!isWellInit)
389  {
390  for(unsigned int i=0 ; i< points3D_list.size() ; i++)
391  {
392  std::cout << "Click on point " << i+1 << std::endl ;
393  double x=0,y=0;
394  vpDisplay::getClick(I, ip) ;
396  vpDisplay::flush(I) ;
398  P[i].set_x(x);
399  P[i].set_y(y);
400 
401  std::cout << "Click on point " << ip << std::endl;
402 
403  vpDisplay::displayPoint (I, ip, vpColor::green); //display target point
404  pose.addPoint(P[i]) ; // and added to the pose computation point list
405  }
406  vpDisplay::flush(I) ;
407 
408  vpHomogeneousMatrix cMo1, cMo2;
409  pose.computePose(vpPose::LAGRANGE, cMo1) ;
410  double d1 = pose.computeResidual(cMo1);
411  pose.computePose(vpPose::DEMENTHON, cMo2) ;
412  double d2 = pose.computeResidual(cMo2);
413 
414  if(d1 < d2){
415  cMo = cMo1;
416  }
417  else{
418  cMo = cMo2;
419  }
421 
422  display(I, cMo, cam, vpColor::green, 1, true);
424  "left click to validate, right click to re initialize object",
425  vpColor::red);
426 
427  vpDisplay::flush(I) ;
428 
430  while (!vpDisplay::getClick(I, ip, button)) ;
431 
432 
433  if (button == vpMouseButton::button1)
434  {
435  isWellInit = true;
436  }
437  else
438  {
439  pose.clearPoint() ;
440  vpDisplay::display(I) ;
441  vpDisplay::flush(I) ;
442  }
443  }
444 
446 
447  delete [] P;
448 
449  init(I);
450 }
451 
469 void vpMbTracker::initFromPoints( const vpImage<unsigned char>& I, const std::string& initFile )
470 {
471  char s[FILENAME_MAX];
472  std::fstream finit ;
473 
474  std::string ext = ".init";
475  size_t pos = initFile.rfind(ext);
476 
477  if( pos == initFile.size()-ext.size() && pos != 0)
478  sprintf(s,"%s", initFile.c_str());
479  else
480  sprintf(s,"%s.init", initFile.c_str());
481 
482  std::cout << "filename " << s << std::endl ;
483  finit.open(s,std::ios::in) ;
484  if (finit.fail()){
485  std::cout << "cannot read " << s << std::endl;
486  throw vpException(vpException::ioError, "cannot read init file");
487  }
488 
489  unsigned int size;
490  double X, Y, Z;
491  finit >> size ;
492  std::cout << "number of points " << size << std::endl ;
493 
494  if (size > 100000) {
496  "Exceed the max number of points.");
497  }
498 
499  vpPoint *P = new vpPoint [size];
500  vpPose pose ;
501 
502  for(unsigned int i=0 ; i< size ; i++)
503  {
504  finit >> X ;
505  finit >> Y ;
506  finit >> Z ;
507  P[i].setWorldCoordinates(X,Y,Z) ;
508  }
509 
510  unsigned int size2;
511  double x, y;
512  vpImagePoint ip;
513  finit >> size2 ;
514  if(size != size2)
515  vpERROR_TRACE( "vpMbTracker::initFromPoints(), Number of 2D points different to the number of 3D points." );
516 
517  for(unsigned int i=0 ; i< size ; i++)
518  {
519  finit >> x;
520  finit >> y;
521  ip = vpImagePoint(x,y);
523  P[i].set_x(x);
524  P[i].set_y(y);
525  pose.addPoint(P[i]);
526  }
527 
528  vpHomogeneousMatrix cMo1, cMo2;
529  pose.computePose(vpPose::LAGRANGE, cMo1) ;
530  double d1 = pose.computeResidual(cMo1);
531  pose.computePose(vpPose::DEMENTHON, cMo2) ;
532  double d2 = pose.computeResidual(cMo2);
533 
534  if(d1 < d2)
535  cMo = cMo1;
536  else
537  cMo = cMo2;
538 
540 
541  delete [] P;
542 
543  init(I);
544 }
545 
554 void vpMbTracker::initFromPoints( const vpImage<unsigned char>& I, const std::vector<vpImagePoint> &points2D_list,
555  const std::vector<vpPoint> &points3D_list )
556 {
557  if(points2D_list.size() != points3D_list.size())
558  vpERROR_TRACE( "vpMbTracker::initFromPoints(), Number of 2D points different to the number of 3D points." );
559 
560  size_t size = points3D_list.size();
561  vpPoint *P = new vpPoint [size];
562  vpPose pose ;
563 
564  for(size_t i=0 ; i< size ; i++)
565  {
566  P[i].setWorldCoordinates(points3D_list[i].get_oX(),points3D_list[i].get_oY(),points3D_list[i].get_oZ()) ;
567  double x=0,y=0;
568  vpPixelMeterConversion::convertPoint(cam, points2D_list[i], x, y);
569  P[i].set_x(x);
570  P[i].set_y(y);
571  pose.addPoint(P[i]);
572  }
573 
574  vpHomogeneousMatrix cMo1, cMo2;
575  pose.computePose(vpPose::LAGRANGE, cMo1) ;
576  double d1 = pose.computeResidual(cMo1);
577  pose.computePose(vpPose::DEMENTHON, cMo2) ;
578  double d2 = pose.computeResidual(cMo2);
579 
580  if(d1 < d2)
581  cMo = cMo1;
582  else
583  cMo = cMo2;
584 
586 
587  delete [] P;
588 
589  init(I);
590 }
591 
609 void vpMbTracker::initFromPose(const vpImage<unsigned char>& I, const std::string &initFile)
610 {
611  char s[FILENAME_MAX];
612  std::fstream finit ;
613  vpPoseVector init_pos;
614 
615  std::string ext = ".pos";
616  size_t pos = initFile.rfind(ext);
617 
618  if( pos == initFile.size()-ext.size() && pos != 0)
619  sprintf(s,"%s", initFile.c_str());
620  else
621  sprintf(s,"%s.pos", initFile.c_str());
622 
623  std::cout << "filename " << s << std::endl ;
624  finit.open(s,std::ios::in) ;
625  if (finit.fail()){
626  std::cout << "cannot read " << s << std::endl;
627  throw vpException(vpException::ioError, "cannot read init file");
628  }
629 
630  for (unsigned int i = 0; i < 6; i += 1){
631  finit >> init_pos[i];
632  }
633 
634  cMo.buildFrom(init_pos);
635  init(I);
636 }
637 
645 {
646  this->cMo = cMo_;
647  init(I);
648 }
649 
657 {
658  vpHomogeneousMatrix _cMo(cPo);
659  initFromPose(I, _cMo);
660 }
661 
667 void vpMbTracker::savePose(const std::string &filename)
668 {
669  vpPoseVector init_pos;
670  std::fstream finitpos ;
671  char s[FILENAME_MAX];
672 
673  sprintf(s,"%s", filename.c_str());
674  finitpos.open(s, std::ios::out) ;
675 
676  init_pos.buildFrom(cMo);
677  finitpos << init_pos;
678  finitpos.close();
679 }
680 
704 void
705 vpMbTracker::loadModel(const std::string& modelFile)
706 {
707  std::string::const_iterator it;
708 
709  if(vpIoTools::checkFilename(modelFile)){
710  it = modelFile.end();
711  if((*(it-1) == 'o' && *(it-2) == 'a' && *(it-3) == 'c' && *(it-4) == '.') ||
712  (*(it-1) == 'O' && *(it-2) == 'A' && *(it-3) == 'C' && *(it-4) == '.') ){
713  loadCAOModel(modelFile);
714  }
715  else if((*(it-1) == 'l' && *(it-2) == 'r' && *(it-3) == 'w' && *(it-4) == '.') ||
716  (*(it-1) == 'L' && *(it-2) == 'R' && *(it-3) == 'W' && *(it-4) == '.') ){
717  loadVRMLModel(modelFile);
718  }
719  else{
720  throw vpException(vpException::ioError, "file cannot be open");
721  }
722  }
723  else{
724  throw vpException(vpException::ioError, "file cannot be open");
725  }
726 
727  this->modelInitialised = true;
728  this->modelFileName = modelFile;
729 }
730 
731 
762 void
763 vpMbTracker::loadVRMLModel(const std::string& modelFile)
764 {
765 #ifdef VISP_HAVE_COIN
766  SoDB::init(); // Call SoDD::finish() before ending the program.
767 
768  SoInput in;
769  SbBool ok = in.openFile(modelFile.c_str());
770  SoSeparator *sceneGraph;
771  SoVRMLGroup *sceneGraphVRML2;
772 
773  if (!ok) {
774  vpERROR_TRACE("can't open file to load model");
775  throw vpException(vpException::fatalError, "can't open file to load model");
776  }
777 
778  if(!in.isFileVRML2())
779  {
780  sceneGraph = SoDB::readAll(&in);
781  if (sceneGraph == NULL) { /*return -1;*/ }
782  sceneGraph->ref();
783 
784  SoToVRML2Action tovrml2;
785  tovrml2.apply(sceneGraph);
786 
787  sceneGraphVRML2 =tovrml2.getVRML2SceneGraph();
788  sceneGraphVRML2->ref();
789  sceneGraph->unref();
790  }
791  else
792  {
793  sceneGraphVRML2 = SoDB::readAllVRML(&in);
794  if (sceneGraphVRML2 == NULL) { /*return -1;*/ }
795  sceneGraphVRML2->ref();
796  }
797 
798  in.closeFile();
799 
800  vpHomogeneousMatrix transform;
801  unsigned int indexFace = 0;
802  extractGroup(sceneGraphVRML2, transform, indexFace);
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 
837 void
838 vpMbTracker::loadCAOModel(const std::string& modelFile)
839 {
840  std::ifstream fileId;
841  fileId.exceptions ( std::ifstream::failbit | std::ifstream::eofbit );
842  fileId.open (modelFile.c_str(), std::ifstream::in);
843  if(fileId.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  try{
849  char c;
850  // Extraction of the version (remove empty line and commented ones (comment
851  // line begin with the #)).
852  //while ((fileId.get(c) != NULL) && (c == '#')) fileId.ignore(256, '\n');
853  fileId.get(c);
854  while (!fileId.fail() && (c == '#'))
855  {
856  fileId.ignore(256, '\n');
857  fileId.get(c);
858  }
859  fileId.unget();
860 
861  int caoVersion;
862  fileId.get(c);
863  if(c=='V'){
864  fileId >> caoVersion;
865  }
866  else{
867  std::cout <<"in vpMbTracker::loadCAOModel() -> Bad parameter header file : use V0, V1, ...";
869  "in vpMbTracker::loadCAOModel() -> Bad parameter header file : use V0, V1, ...");
870  }
871 
872  //while( (fileId.get(c)!=NULL)&&(c!='\n')) ;
873  fileId.get(c);
874  while (!fileId.fail() && (c != '\n'))
875  {
876  fileId.get(c);
877  }
878 
879  //while ((fileId.get(c) != NULL) && (c == '#')) fileId.ignore(256, '\n');
880  fileId.get(c);
881  while (!fileId.fail() && (c == '#'))
882  {
883  fileId.ignore(256, '\n');
884  fileId.get(c);
885  }
886  fileId.unget();
887 
888  //Read the points
889  unsigned int caoNbrPoint;
890  fileId >> caoNbrPoint;
891  std::cout << "> " << caoNbrPoint << " points" << std::endl;
892  if (caoNbrPoint > 100000) {
894  "Exceed the max number of points in the CAO model.");
895  }
896 
897  if (caoNbrPoint == 0) {
899  "in vpMbTracker::loadCAOModel() -> no points are defined");
900 
901  }
902  vpPoint *caoPoints = new vpPoint[caoNbrPoint];
903 
904  double x ; // 3D coordinates
905  double y ;
906  double z ;
907 
908  int i ; // image coordinate (used for matching)
909  int j ;
910 
911  for(unsigned int k=0; k < caoNbrPoint; k++){
912  fileId >> x ;
913  fileId >> y ;
914  fileId >> z ;
915  if (caoVersion == 2){
916  fileId >> i ;
917  fileId >> j ;
918  }
919 
920  if(k != caoNbrPoint-1){// the rest of the line is removed (not the last one due to the need to remove possible comments).
921  fileId.ignore(256,'\n');
922  }
923  caoPoints[k].setWorldCoordinates(x, y, z) ;
924  }
925 
926  //while( (fileId.get(c)!=NULL)&&(c!='\n')) ;
927  fileId.get(c);
928  while (!fileId.fail() && (c != '\n'))
929  {
930  fileId.get(c);
931  }
932 
933  //while ((fileId.get(c) != NULL) && (c == '#')) fileId.ignore(256, '\n');
934  fileId.get(c);
935  while (!fileId.fail() && (c == '#'))
936  {
937  fileId.ignore(256, '\n');
938  fileId.get(c);
939  }
940  fileId.unget();
941 
942  //Read the lines
943  unsigned int caoNbrLine;
944  fileId >> caoNbrLine;
945  unsigned int *caoLinePoints = NULL;
946  std::cout << "> " << caoNbrLine << " lines" << std::endl;
947 
948  if (caoNbrLine > 100000) {
949  delete [] caoPoints;
951  "Exceed the max number of lines in the CAO model.");
952  }
953 
954  if (caoNbrLine > 0)
955  caoLinePoints = new unsigned int[2*caoNbrLine];
956 
957  unsigned int index1, index2;
958 
959  for(unsigned int k=0; k < caoNbrLine ; k++){
960  fileId >> index1 ;
961  fileId >> index2 ;
962 
963  caoLinePoints[2*k] = index1;
964  caoLinePoints[2*k+1] = index2;
965 
966  if(index1 < caoNbrPoint && index2 < caoNbrPoint){
967  std::vector<vpPoint> extremities;
968  extremities.push_back(caoPoints[index1]);
969  extremities.push_back(caoPoints[index2]);
970  initFaceFromCorners(extremities, k);
971  }
972  else{
973  vpTRACE(" line %d has wrong coordinates.", k);
974  }
975 
976  if(k != caoNbrLine-1){// the rest of the line is removed (not the last one due to the need to remove possible comments).
977  fileId.ignore(256,'\n');
978  }
979  }
980 
981  //while( (fileId.get(c)!=NULL)&&(c!='\n')) ;
982  fileId.get(c);
983  while (!fileId.fail() && (c != '\n'))
984  {
985  fileId.get(c);
986  }
987 
988  //while ((fileId.get(c) != NULL) && (c == '#')) fileId.ignore(256, '\n');
989  fileId.get(c);
990  while (!fileId.fail() && (c == '#'))
991  {
992  fileId.ignore(256, '\n');
993  fileId.get(c);
994  }
995  fileId.unget();
996 
997  /* Load polygon from the lines extracted earlier
998  (the first point of the line is used)*/
999  unsigned int caoNbrPolygonLine;
1000  fileId >> caoNbrPolygonLine;
1001  std::cout << "> " << caoNbrPolygonLine << " polygon line" << std::endl;
1002  if (caoNbrPolygonLine > 100000) {
1003  delete [] caoPoints;
1004  delete [] caoLinePoints;
1005  throw vpException(vpException::badValue, "Exceed the max number of polygon lines.");
1006  }
1007 
1008  unsigned int index;
1009  for(unsigned int k = 0;k < caoNbrPolygonLine; k++){
1010  unsigned int nbLinePol;
1011  fileId >> nbLinePol;
1012  std::vector<vpPoint> corners;
1013  if (nbLinePol > 100000) {
1014  throw vpException(vpException::badValue, "Exceed the max number of lines.");
1015  }
1016 
1017  for(unsigned int n = 0; n < nbLinePol; n++){
1018  fileId >> index;
1019  if (2*index > 2*caoNbrLine-1) {
1020  throw vpException(vpException::badValue, "Exceed the max number of lines.");
1021  }
1022 
1023  corners.push_back(caoPoints[caoLinePoints[2*index]]);
1024  }
1025  if(k != caoNbrPolygonLine-1){// the rest of the line is removed (not the last one due to the need to remove possible comments).
1026  fileId.ignore(256,'\n');
1027  }
1028  initFaceFromCorners(corners, k);
1029  }
1030 
1031  //while( (fileId.get(c)!=NULL)&&(c!='\n')) ;
1032  fileId.get(c);
1033  while (!fileId.fail() && (c != '\n'))
1034  {
1035  fileId.get(c);
1036  }
1037 
1038  //while ((fileId.get(c) != NULL) && (c == '#')) fileId.ignore(256, '\n');
1039  fileId.get(c);
1040  while (!fileId.fail() && (c == '#'))
1041  {
1042  fileId.ignore(256, '\n');
1043  fileId.get(c);
1044  }
1045  fileId.unget();
1046 
1047  /* Extract the polygon using the point coordinates (top of the file) */
1048  unsigned int caoNbrPolygonPoint;
1049  fileId >> caoNbrPolygonPoint;
1050  std::cout << "> " << caoNbrPolygonPoint << " polygon point" << std::endl;
1051 
1052  if (caoNbrPolygonPoint > 100000) {
1053  throw vpException(vpException::badValue, "Exceed the max number of polygon point.");
1054  }
1055 
1056  for(unsigned int k = 0;k < caoNbrPolygonPoint; k++){
1057  unsigned int nbPointPol;
1058  fileId >> nbPointPol;
1059  if (nbPointPol > 100000) {
1060  throw vpException(vpException::badValue, "Exceed the max number of points.");
1061  }
1062 
1063  std::vector<vpPoint> corners;
1064  for(unsigned int n = 0; n < nbPointPol; n++){
1065  fileId >> index;
1066  if (index > caoNbrPoint-1) {
1067  throw vpException(vpException::badValue, "Exceed the max number of points.");
1068  }
1069  corners.push_back(caoPoints[index]);
1070  }
1071  if(k != caoNbrPolygonPoint-1){// the rest of the line is removed (not the last one due to the need to remove possible comments).
1072  fileId.ignore(256,'\n');
1073  }
1074  initFaceFromCorners(corners, k);
1075  }
1076 
1077  unsigned int caoNbCylinder;
1078  try{
1079  //while( (fileId.get(c)!=NULL)&&(c!='\n')) ;
1080  fileId.get(c);
1081  while (!fileId.fail() && (c != '\n'))
1082  {
1083  fileId.get(c);
1084  }
1085 
1086  //while ((fileId.get(c) != NULL) && (c == '#')) fileId.ignore(256, '\n');
1087  fileId.get(c);
1088  while (!fileId.fail() && (c == '#'))
1089  {
1090  fileId.ignore(256, '\n');
1091  fileId.get(c);
1092  } fileId.unget();
1093 
1094  if(fileId.eof()){// check if not at the end of the file (for old style files)
1095  delete[] caoPoints;
1096  delete[] caoLinePoints;
1097  return ;
1098  }
1099 
1100  /* Extract the cylinders */
1101 
1102 
1103  fileId >> caoNbCylinder;
1104  std::cout << "> " << caoNbCylinder << " cylinder" << std::endl;
1105  if (caoNbCylinder > 100000) {
1106  throw vpException(vpException::badValue, "Exceed the max number of cylinders.");
1107  }
1108 
1109  for(unsigned int k=0; k<caoNbCylinder; ++k){
1110  double radius;
1111  unsigned int indexP1, indexP2;
1112  fileId >> indexP1;
1113  fileId >> indexP2;
1114  fileId >> radius;
1115  initCylinder(caoPoints[indexP1], caoPoints[indexP2], radius);
1116  }
1117 
1118  }catch(...){
1119  std::cerr << "Cannot get the number of cylinders. Defaulting to zero." << std::endl;
1120  caoNbCylinder = 0;
1121  }
1122 
1123  delete[] caoPoints;
1124  delete[] caoLinePoints;
1125  }catch(std::ifstream::failure e){
1126  std::cerr << "Cannot read line!" << std::endl;
1127  throw vpException(vpException::ioError, "cannot read line");
1128  }
1129 
1130 }
1131 
1132 #ifdef VISP_HAVE_COIN
1133 
1140 void
1141 vpMbTracker::extractGroup(SoVRMLGroup *sceneGraphVRML2, vpHomogeneousMatrix &transform, unsigned int &indexFace)
1142 {
1143  vpHomogeneousMatrix transformCur;
1144  SoVRMLTransform *sceneGraphVRML2Trasnform = dynamic_cast<SoVRMLTransform *>(sceneGraphVRML2);
1145  if(sceneGraphVRML2Trasnform){
1146  float rx, ry, rz, rw;
1147  sceneGraphVRML2Trasnform->rotation.getValue().getValue(rx,ry,rz,rw);
1148  vpRotationMatrix rotMat(vpQuaternionVector(rx,ry,rz,rw));
1149 // std::cout << "Rotation: " << rx << " " << ry << " " << rz << " " << rw << std::endl;
1150 
1151  float tx, ty, tz;
1152  tx = sceneGraphVRML2Trasnform->translation.getValue()[0];
1153  ty = sceneGraphVRML2Trasnform->translation.getValue()[1];
1154  tz = sceneGraphVRML2Trasnform->translation.getValue()[2];
1155  vpTranslationVector transVec(tx,ty,tz);
1156 // std::cout << "Translation: " << tx << " " << ty << " " << tz << std::endl;
1157 
1158  float sx, sy, sz;
1159  sx = sceneGraphVRML2Trasnform->scale.getValue()[0];
1160  sy = sceneGraphVRML2Trasnform->scale.getValue()[1];
1161  sz = sceneGraphVRML2Trasnform->scale.getValue()[2];
1162 // std::cout << "Scale: " << sx << " " << sy << " " << sz << std::endl;
1163 
1164  for(unsigned int i = 0 ; i < 3 ; i++)
1165  rotMat[0][i] *= sx;
1166  for(unsigned int i = 0 ; i < 3 ; i++)
1167  rotMat[1][i] *= sy;
1168  for(unsigned int i = 0 ; i < 3 ; i++)
1169  rotMat[2][i] *= sz;
1170 
1171  transformCur = vpHomogeneousMatrix(transVec,rotMat);
1172  transform = transform * transformCur;
1173  }
1174 
1175  int nbShapes = sceneGraphVRML2->getNumChildren();
1176 // std::cout << sceneGraphVRML2->getTypeId().getName().getString() << std::endl;
1177 // std::cout << "Nb object in VRML : " << nbShapes << std::endl;
1178 
1179  SoNode * child;
1180 
1181  for (int i = 0; i < nbShapes; i++)
1182  {
1183  vpHomogeneousMatrix transform_recursive(transform);
1184  child = sceneGraphVRML2->getChild(i);
1185 
1186  if (child->getTypeId() == SoVRMLGroup::getClassTypeId()){
1187  extractGroup((SoVRMLGroup*)child, transform_recursive, indexFace);
1188  }
1189 
1190  if (child->getTypeId() == SoVRMLTransform::getClassTypeId()){
1191  extractGroup((SoVRMLTransform*)child, transform_recursive, indexFace);
1192  }
1193 
1194  if (child->getTypeId() == SoVRMLShape::getClassTypeId()){
1195  SoChildList * child2list = child->getChildren();
1196  for (int j = 0; j < child2list->getLength(); j++)
1197  {
1198  if (((SoNode*)child2list->get(j))->getTypeId() == SoVRMLIndexedFaceSet::getClassTypeId())
1199  {
1200  SoVRMLIndexedFaceSet * face_set;
1201  face_set = (SoVRMLIndexedFaceSet*)child2list->get(j);
1202  if(!strncmp(face_set->getName().getString(),"cyl",3)){
1203  extractCylinders(face_set, transform);
1204  }else{
1205  extractFaces(face_set, transform, indexFace);
1206  }
1207  }
1208  if (((SoNode*)child2list->get(j))->getTypeId() == SoVRMLIndexedLineSet::getClassTypeId())
1209  {
1210  SoVRMLIndexedLineSet * line_set;
1211  line_set = (SoVRMLIndexedLineSet*)child2list->get(j);
1212  extractLines(line_set);
1213  }
1214  }
1215  }
1216  }
1217 }
1218 
1227 void
1228 vpMbTracker::extractFaces(SoVRMLIndexedFaceSet* face_set, vpHomogeneousMatrix &transform, unsigned int &indexFace)
1229 {
1230  std::vector<vpPoint> corners;
1231  corners.resize(0);
1232 
1233 // SoMFInt32 indexList = _face_set->coordIndex;
1234 // int indexListSize = indexList.getNum();
1235  int indexListSize = face_set->coordIndex.getNum();
1236 
1237  vpColVector pointTransformed(4);
1238  vpPoint pt;
1239  SoVRMLCoordinate *coord;
1240 
1241  for (int i = 0; i < indexListSize; i++)
1242  {
1243  if (face_set->coordIndex[i] == -1)
1244  {
1245  if(corners.size() > 1)
1246  {
1247  initFaceFromCorners(corners, indexFace);
1248  indexFace++;
1249  corners.resize(0);
1250  }
1251  }
1252  else
1253  {
1254  coord = (SoVRMLCoordinate *)(face_set->coord.getValue());
1255  int index = face_set->coordIndex[i];
1256  pointTransformed[0]=coord->point[index].getValue()[0];
1257  pointTransformed[1]=coord->point[index].getValue()[1];
1258  pointTransformed[2]=coord->point[index].getValue()[2];
1259  pointTransformed[3] = 1.0;
1260 
1261  pointTransformed = transform * pointTransformed;
1262 
1263  pt.setWorldCoordinates(pointTransformed[0],pointTransformed[1],pointTransformed[2]);
1264  corners.push_back(pt);
1265  }
1266  }
1267 }
1268 
1281 void
1282 vpMbTracker::extractCylinders(SoVRMLIndexedFaceSet* face_set, vpHomogeneousMatrix &transform)
1283 {
1284  std::vector<vpPoint> corners_c1, corners_c2;//points belonging to the first circle and to the second one.
1285  SoVRMLCoordinate* coords = (SoVRMLCoordinate *)face_set->coord.getValue();
1286 
1287  unsigned int indexListSize = (unsigned int)coords->point.getNum();
1288 
1289  if(indexListSize % 2 == 1){
1290  std::cout << "Not an even number of points when extracting a cylinder." << std::endl;
1291  throw vpException(vpException::dimensionError, "Not an even number of points when extracting a cylinder.");
1292  }
1293  corners_c1.resize(indexListSize / 2);
1294  corners_c2.resize(indexListSize / 2);
1295  vpColVector pointTransformed(4);
1296  vpPoint pt;
1297 
1298 
1299  // extract all points and fill the two sets.
1300  for(int i=0; i<coords->point.getNum(); ++i){
1301  pointTransformed[0]=coords->point[i].getValue()[0];
1302  pointTransformed[1]=coords->point[i].getValue()[1];
1303  pointTransformed[2]=coords->point[i].getValue()[2];
1304  pointTransformed[3] = 1.0;
1305 
1306  pointTransformed = transform * pointTransformed;
1307 
1308  pt.setWorldCoordinates(pointTransformed[0],pointTransformed[1],pointTransformed[2]);
1309 
1310  if(i < (int)corners_c1.size()){
1311  corners_c1[(unsigned int)i] = pt;
1312  }else{
1313  corners_c2[(unsigned int)i-corners_c1.size()] = pt;
1314  }
1315  }
1316 
1317  vpPoint p1 = getGravityCenter(corners_c1);
1318  vpPoint p2 = getGravityCenter(corners_c2);
1319 
1320  vpColVector dist(3);
1321  dist[0] = p1.get_oX() - corners_c1[0].get_oX();
1322  dist[1] = p1.get_oY() - corners_c1[0].get_oY();
1323  dist[2] = p1.get_oZ() - corners_c1[0].get_oZ();
1324  double radius_c1 = sqrt(dist.sumSquare());
1325  dist[0] = p2.get_oX() - corners_c2[0].get_oX();
1326  dist[1] = p2.get_oY() - corners_c2[0].get_oY();
1327  dist[2] = p2.get_oZ() - corners_c2[0].get_oZ();
1328  double radius_c2 = sqrt(dist.sumSquare());
1329 
1330  if(std::fabs(radius_c1 - radius_c2) > (std::numeric_limits<double>::epsilon() * vpMath::maximum(radius_c1, radius_c2))){
1331  std::cout << "Radius from the two circles of the cylinders are different." << std::endl;
1332  throw vpException(vpException::badValue, "Radius from the two circles of the cylinders are different.");
1333  }
1334 
1335  initCylinder(p1, p2, radius_c1);
1336 
1337 }
1338 
1348 vpPoint
1349 vpMbTracker::getGravityCenter(const std::vector<vpPoint>& pts)
1350 {
1351  if(pts.empty()){
1352  std::cout << "Cannot extract center of gravity of empty set." << std::endl;
1353  throw vpException(vpException::dimensionError, "Cannot extract center of gravity of empty set.");
1354  }
1355  double oX = 0;
1356  double oY = 0;
1357  double oZ = 0;
1358  vpPoint G;
1359 
1360  for(unsigned int i=0; i<pts.size(); ++i){
1361  oX += pts[i].get_oX();
1362  oY += pts[i].get_oY();
1363  oZ += pts[i].get_oZ();
1364  }
1365 
1366  G.setWorldCoordinates(oX/pts.size(), oY/pts.size(), oZ/pts.size());
1367  return G;
1368 }
1369 
1370 
1377 void
1378 vpMbTracker::extractLines(SoVRMLIndexedLineSet* line_set)
1379 {
1380  std::vector<vpPoint> corners;
1381  corners.resize(0);
1382 
1383  int indexListSize = line_set->coordIndex.getNum();
1384 
1385  SbVec3f point(0,0,0);
1386  vpPoint pt;
1387  SoVRMLCoordinate *coord;
1388 
1389  unsigned int indexFace = 0;
1390 
1391  for (int i = 0; i < indexListSize; i++)
1392  {
1393  if (line_set->coordIndex[i] == -1)
1394  {
1395  if(corners.size() > 1)
1396  {
1397  initFaceFromCorners(corners, indexFace);
1398  indexFace++;
1399  corners.resize(0);
1400  }
1401  }
1402  else
1403  {
1404  coord = (SoVRMLCoordinate *)(line_set->coord.getValue());
1405  int index = line_set->coordIndex[i];
1406  point[0]=coord->point[index].getValue()[0];
1407  point[1]=coord->point[index].getValue()[1];
1408  point[2]=coord->point[index].getValue()[2];
1409 
1410  pt.setWorldCoordinates(point[0],point[1],point[2]);
1411  corners.push_back(pt);
1412  }
1413  }
1414 }
1415 
1416 #endif
1417 
1432 void
1433 vpMbTracker::computeJTR(const vpMatrix& interaction, const vpColVector& error, vpMatrix& JTR)
1434 {
1435  if(interaction.getRows() != error.getRows() || interaction.getCols() != 6 ){
1437  "Incorrect matrices size in computeJTR.");
1438  }
1439 
1440  JTR.resize(6, 1);
1441  const unsigned int N = interaction.getRows();
1442 
1443  for (unsigned int i = 0; i < 6; i += 1){
1444  double ssum = 0;
1445  for (unsigned int j = 0; j < N; j += 1){
1446  ssum += interaction[j][i] * error[j];
1447  }
1448  JTR[i][0] = ssum;
1449  }
1450 }
1451 
1452 
void init(vpImage< unsigned char > &I, int winx=-1, int winy=-1, const char *title=NULL)
Definition of the vpMatrix class.
Definition: vpMatrix.h:98
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:183
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:395
virtual void initFaceFromCorners(const std::vector< vpPoint > &corners, const unsigned int indexFace=-1)=0
#define vpTRACE
Definition: vpDebug.h:418
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: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
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:809
static const vpColor green
Definition: vpColor.h:170
static void flush(const vpImage< unsigned char > &I)
Definition: vpDisplay.cpp:1994
static const vpColor red
Definition: vpColor.h:167
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:206
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:78
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 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:371
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:114
double get_oX() const
Get the point X coordinate in the object frame.
Definition: vpPoint.h:127
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:163
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:386
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)
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
void addPoint(const vpPoint &P)
Add a new point in this array.
Definition: vpPose.cpp:155
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:344
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
virtual void initCylinder(const vpPoint &p1, const vpPoint &p2, const double radius, const unsigned int indexCylinder=0)=0
void clearPoint()
suppress all the point in the array of point
Definition: vpPose.cpp:133
virtual void extractGroup(SoVRMLGroup *sceneGraphVRML2, vpHomogeneousMatrix &transform, unsigned int &indexFace)