Visual Servoing Platform  version 3.1.0
vpMbTracker.cpp
1 /****************************************************************************
2  *
3  * This file is part of the ViSP software.
4  * Copyright (C) 2005 - 2017 by Inria. All rights reserved.
5  *
6  * This software is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  * See the file LICENSE.txt at the root directory of this source
11  * distribution for additional information about the GNU GPL.
12  *
13  * For using ViSP with software that can not be combined with the GNU
14  * GPL, please contact Inria about acquiring a ViSP Professional
15  * Edition License.
16  *
17  * See http://visp.inria.fr for more information.
18  *
19  * This software was developed at:
20  * Inria Rennes - Bretagne Atlantique
21  * Campus Universitaire de Beaulieu
22  * 35042 Rennes Cedex
23  * France
24  *
25  * If you have questions regarding the use of this file, please contact
26  * Inria at visp@inria.fr
27  *
28  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
29  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
30  *
31  * Description:
32  * Generic model based tracker
33  *
34  * Authors:
35  * Romain Tallonneau
36  * Aurelien Yol
37  * Eric Marchand
38  *
39  *****************************************************************************/
40 
46 #include <algorithm>
47 #include <iostream>
48 #include <limits>
49 #include <map>
50 
51 #include <visp3/core/vpColVector.h>
52 #include <visp3/core/vpDisplay.h>
53 #include <visp3/core/vpMath.h>
54 #include <visp3/core/vpMatrix.h>
55 #include <visp3/core/vpPoint.h>
56 #include <visp3/vision/vpPose.h>
57 #ifdef VISP_HAVE_MODULE_GUI
58 #include <visp3/gui/vpDisplayGDI.h>
59 #include <visp3/gui/vpDisplayOpenCV.h>
60 #include <visp3/gui/vpDisplayX.h>
61 #endif
62 #include <visp3/core/vpCameraParameters.h>
63 #include <visp3/core/vpColor.h>
64 #include <visp3/core/vpException.h>
65 #include <visp3/core/vpIoTools.h>
66 #include <visp3/core/vpPixelMeterConversion.h>
67 #ifdef VISP_HAVE_MODULE_IO
68 #include <visp3/io/vpImageIo.h>
69 #endif
70 #include <visp3/core/vpCPUFeatures.h>
71 #include <visp3/core/vpIoTools.h>
72 #include <visp3/core/vpMatrixException.h>
73 #include <visp3/core/vpTrackingException.h>
74 #include <visp3/mbt/vpMbTracker.h>
75 
76 #ifdef VISP_HAVE_COIN3D
77 // Inventor includes
78 #include <Inventor/VRMLnodes/SoVRMLCoordinate.h>
79 #include <Inventor/VRMLnodes/SoVRMLGroup.h>
80 #include <Inventor/VRMLnodes/SoVRMLIndexedFaceSet.h>
81 #include <Inventor/VRMLnodes/SoVRMLIndexedLineSet.h>
82 #include <Inventor/VRMLnodes/SoVRMLShape.h>
83 #include <Inventor/VRMLnodes/SoVRMLTransform.h>
84 #include <Inventor/actions/SoGetMatrixAction.h>
85 #include <Inventor/actions/SoGetPrimitiveCountAction.h>
86 #include <Inventor/actions/SoSearchAction.h>
87 #include <Inventor/actions/SoToVRML2Action.h>
88 #include <Inventor/actions/SoWriteAction.h>
89 #include <Inventor/misc/SoChildList.h>
90 #include <Inventor/nodes/SoSeparator.h>
91 #endif
92 
93 #if defined __SSE2__ || defined _M_X64 || (defined _M_IX86_FP && _M_IX86_FP >= 2)
94 #include <emmintrin.h>
95 #define VISP_HAVE_SSE2 1
96 #endif
97 
98 #ifndef DOXYGEN_SHOULD_SKIP_THIS
99 
100 namespace
101 {
105 struct SegmentInfo {
106  SegmentInfo() : extremities(), name(), useLod(false), minLineLengthThresh(0.) {}
107 
108  std::vector<vpPoint> extremities;
109  std::string name;
110  bool useLod;
111  double minLineLengthThresh;
112 };
113 
118 struct PolygonFaceInfo {
119  PolygonFaceInfo(const double dist, const vpPolygon &poly, const std::vector<vpPoint> &corners)
120  : distanceToCamera(dist), polygon(poly), faceCorners(corners)
121  {
122  }
123 
124  bool operator<(const PolygonFaceInfo &pfi) const { return distanceToCamera < pfi.distanceToCamera; }
125 
126  double distanceToCamera;
127  vpPolygon polygon;
128  std::vector<vpPoint> faceCorners;
129 };
130 }
131 #endif // DOXYGEN_SHOULD_SKIP_THIS
132 
139  : cam(), cMo(), oJo(6, 6), isoJoIdentity(true), modelFileName(), modelInitialised(false), poseSavingFilename(),
140  computeCovariance(false), covarianceMatrix(), computeProjError(false), projectionError(90.0),
141  displayFeatures(false), m_optimizationMethod(vpMbTracker::GAUSS_NEWTON_OPT), faces(), angleAppears(vpMath::rad(89)),
142  angleDisappears(vpMath::rad(89)), distNearClip(0.001), distFarClip(100), clippingFlag(vpPolygon3D::NO_CLIPPING),
143  useOgre(false), ogreShowConfigDialog(false), useScanLine(false), nbPoints(0), nbLines(0), nbPolygonLines(0),
144  nbPolygonPoints(0), nbCylinders(0), nbCircles(0), useLodGeneral(false), applyLodSettingInConfig(false),
145  minLineLengthThresholdGeneral(50.0), minPolygonAreaThresholdGeneral(2500.0), mapOfParameterNames(),
146  m_computeInteraction(true), m_lambda(1.0), m_maxIter(30), m_stopCriteriaEpsilon(1e-8), m_initialMu(0.01)
147 {
148  oJo.eye();
149  // Map used to parse additional information in CAO model files,
150  // like name of faces or LOD setting
151  mapOfParameterNames["name"] = "string";
152  mapOfParameterNames["minPolygonAreaThreshold"] = "number";
153  mapOfParameterNames["minLineLengthThreshold"] = "number";
154  mapOfParameterNames["useLod"] = "boolean";
155 }
156 
161 
162 #ifdef VISP_HAVE_MODULE_GUI
163 
193 void vpMbTracker::initClick(const vpImage<unsigned char> &I, const std::string &initFile, const bool displayHelp)
194 {
195  vpHomogeneousMatrix last_cMo;
196  vpPoseVector init_pos;
197  vpImagePoint ip;
199 
200  std::string ext = ".init";
201  std::string str_pose = "";
202  size_t pos = (unsigned int)initFile.rfind(ext);
203 
204  // Load the last poses from files
205  std::fstream finitpos;
206  std::fstream finit;
207  char s[FILENAME_MAX];
208  if (poseSavingFilename.empty()) {
209  if (pos == initFile.size() - ext.size() && pos != 0)
210  str_pose = initFile.substr(0, pos) + ".0.pos";
211  else
212  str_pose = initFile + ".0.pos";
213 
214  finitpos.open(str_pose.c_str(), std::ios::in);
215  sprintf(s, "%s", str_pose.c_str());
216  } else {
217  finitpos.open(poseSavingFilename.c_str(), std::ios::in);
218  sprintf(s, "%s", poseSavingFilename.c_str());
219  }
220  if (finitpos.fail()) {
221  std::cout << "cannot read " << s << std::endl << "cMo set to identity" << std::endl;
222  last_cMo.eye();
223  } else {
224  for (unsigned int i = 0; i < 6; i += 1) {
225  finitpos >> init_pos[i];
226  }
227 
228  finitpos.close();
229  last_cMo.buildFrom(init_pos);
230 
231  std::cout << "last_cMo : " << std::endl << last_cMo << std::endl;
232 
234  display(I, last_cMo, cam, vpColor::green, 1, true);
235  vpDisplay::displayFrame(I, last_cMo, cam, 0.05, vpColor::green);
236  vpDisplay::flush(I);
237 
238  std::cout << "No modification : left click " << std::endl;
239  std::cout << "Modify initial pose : right click " << std::endl;
240 
241  vpDisplay::displayText(I, 15, 10, "left click to validate, right click to modify initial pose", vpColor::red);
242 
243  vpDisplay::flush(I);
244 
245  while (!vpDisplay::getClick(I, ip, button))
246  ;
247  }
248 
249  if (!finitpos.fail() && button == vpMouseButton::button1) {
250  cMo = last_cMo;
251  } else {
252  vpDisplay *d_help = NULL;
253 
255  vpDisplay::flush(I);
256 
257  vpPose pose;
258 
259  pose.clearPoint();
260 
261  // file parser
262  // number of points
263  // X Y Z
264  // X Y Z
265  if (pos == initFile.size() - ext.size() && pos != 0)
266  sprintf(s, "%s", initFile.c_str());
267  else
268  sprintf(s, "%s.init", initFile.c_str());
269 
270  std::cout << "Load 3D points from: " << s << std::endl;
271  finit.open(s, std::ios::in);
272  if (finit.fail()) {
273  std::cout << "cannot read " << s << std::endl;
274  throw vpException(vpException::ioError, "Cannot open model-based tracker init file %s", s);
275  }
276 
277 #ifdef VISP_HAVE_MODULE_IO
278  // Display window creation and initialisation
279  try {
280  if (displayHelp) {
281  std::string dispF;
282  if (pos == initFile.size() - ext.size() && pos != 0)
283  dispF = initFile.substr(0, pos) + ".ppm";
284  else
285  dispF = initFile + ".ppm";
286 
287  if (vpIoTools::checkFilename(dispF)) {
288  std::cout << "Load image to help initialization: " << dispF << std::endl;
289 #if defined VISP_HAVE_X11
290  d_help = new vpDisplayX;
291 #elif defined VISP_HAVE_GDI
292  d_help = new vpDisplayGDI;
293 #elif defined VISP_HAVE_OPENCV
294  d_help = new vpDisplayOpenCV;
295 #endif
296 
297  vpImage<vpRGBa> Iref;
298  vpImageIo::read(Iref, dispF);
299 #if defined(VISP_HAVE_X11) || defined(VISP_HAVE_GDI) || defined(VISP_HAVE_OPENCV)
300  d_help->init(Iref, I.display->getWindowXPosition() + (int)I.getWidth() + 80, I.display->getWindowYPosition(),
301  "Where to initialize...");
302  vpDisplay::display(Iref);
303  vpDisplay::flush(Iref);
304 #endif
305  }
306  }
307  } catch (...) {
308  if (d_help != NULL) {
309  delete d_help;
310  d_help = NULL;
311  }
312  }
313 #else //#ifdef VISP_HAVE_MODULE_IO
314  (void)(displayHelp);
315 #endif //#ifdef VISP_HAVE_MODULE_IO
316  char c;
317  // skip lines starting with # as comment
318  finit.get(c);
319  while (!finit.fail() && (c == '#')) {
320  finit.ignore(256, '\n');
321  finit.get(c);
322  }
323  finit.unget();
324 
325  unsigned int n3d;
326  finit >> n3d;
327  finit.ignore(256, '\n'); // skip the rest of the line
328  std::cout << "Number of 3D points " << n3d << std::endl;
329  if (n3d > 100000) {
330  throw vpException(vpException::badValue, "In %s file, the number of 3D points exceed the max allowed", s);
331  }
332 
333  vpPoint *P = new vpPoint[n3d];
334  for (unsigned int i = 0; i < n3d; i++) {
335  // skip lines starting with # as comment
336  finit.get(c);
337  while (!finit.fail() && (c == '#')) {
338  finit.ignore(256, '\n');
339  finit.get(c);
340  }
341  finit.unget();
342  double X, Y, Z;
343 
344  finit >> X;
345  finit >> Y;
346  finit >> Z;
347  finit.ignore(256, '\n'); // skip the rest of the line
348 
349  std::cout << "Point " << i + 1 << " with 3D coordinates: " << X << " " << Y << " " << Z << std::endl;
350  P[i].setWorldCoordinates(X, Y, Z); // (X,Y,Z)
351  }
352 
353  finit.close();
354 
355  bool isWellInit = false;
356  while (!isWellInit) {
357  std::vector<vpImagePoint> mem_ip;
358  for (unsigned int i = 0; i < n3d; i++) {
359  std::ostringstream text;
360  text << "Click on point " << i + 1;
362  vpDisplay::displayText(I, 15, 10, text.str(), vpColor::red);
363  for (unsigned int k = 0; k < mem_ip.size(); k++) {
364  vpDisplay::displayCross(I, mem_ip[k], 10, vpColor::green, 2);
365  }
366  vpDisplay::flush(I);
367 
368  std::cout << "Click on point " << i + 1 << " ";
369  double x = 0, y = 0;
370  vpDisplay::getClick(I, ip);
371  mem_ip.push_back(ip);
372  vpDisplay::flush(I);
374  P[i].set_x(x);
375  P[i].set_y(y);
376 
377  std::cout << "with 2D coordinates: " << ip << std::endl;
378 
379  pose.addPoint(P[i]); // and added to the pose computation point list
380  }
381  vpDisplay::flush(I);
383 
384  vpHomogeneousMatrix cMo1, cMo2;
385  pose.computePose(vpPose::LAGRANGE, cMo1);
386  double d1 = pose.computeResidual(cMo1);
387  pose.computePose(vpPose::DEMENTHON, cMo2);
388  double d2 = pose.computeResidual(cMo2);
389 
390  if (d1 < d2) {
391  cMo = cMo1;
392  } else {
393  cMo = cMo2;
394  }
396 
397  display(I, cMo, cam, vpColor::green, 1, true);
398  vpDisplay::displayText(I, 15, 10, "left click to validate, right click to re initialize object", vpColor::red);
399 
400  vpDisplay::flush(I);
401 
402  button = vpMouseButton::button1;
403  while (!vpDisplay::getClick(I, ip, button))
404  ;
405 
406  if (button == vpMouseButton::button1) {
407  isWellInit = true;
408  } else {
409  pose.clearPoint();
411  vpDisplay::flush(I);
412  }
413  }
415 
416  delete[] P;
417 
418  // save the pose into file
419  if (poseSavingFilename.empty())
420  savePose(str_pose);
421  else
423 
424  if (d_help != NULL) {
425  delete d_help;
426  d_help = NULL;
427  }
428  }
429 
430  std::cout << "cMo : " << std::endl << cMo << std::endl;
431 
432  init(I);
433 }
434 
445 void vpMbTracker::initClick(const vpImage<unsigned char> &I, const std::vector<vpPoint> &points3D_list,
446  const std::string &displayFile)
447 {
449  vpDisplay::flush(I);
450  vpDisplay *d_help = NULL;
451 
452  vpPose pose;
453  std::vector<vpPoint> P;
454  for (unsigned int i = 0; i < points3D_list.size(); i++)
455  P.push_back(vpPoint(points3D_list[i].get_oX(), points3D_list[i].get_oY(), points3D_list[i].get_oZ()));
456 
457 #ifdef VISP_HAVE_MODULE_IO
458  vpImage<vpRGBa> Iref;
459  // Display window creation and initialisation
460  if (vpIoTools::checkFilename(displayFile)) {
461  try {
462  std::cout << "Load image to help initialization: " << displayFile << std::endl;
463 #if defined VISP_HAVE_X11
464  d_help = new vpDisplayX;
465 #elif defined VISP_HAVE_GDI
466  d_help = new vpDisplayGDI;
467 #elif defined VISP_HAVE_OPENCV
468  d_help = new vpDisplayOpenCV;
469 #endif
470 
471  vpImageIo::read(Iref, displayFile);
472 #if defined(VISP_HAVE_X11) || defined(VISP_HAVE_GDI) || defined(VISP_HAVE_OPENCV)
473  d_help->init(Iref, I.display->getWindowXPosition() + (int)I.getWidth() + 80, I.display->getWindowYPosition(),
474  "Where to initialize...");
475  vpDisplay::display(Iref);
476  vpDisplay::flush(Iref);
477 #endif
478  } catch (...) {
479  if (d_help != NULL) {
480  delete d_help;
481  d_help = NULL;
482  }
483  }
484  }
485 #else //#ifdef VISP_HAVE_MODULE_IO
486  (void)(displayFile);
487 #endif //#ifdef VISP_HAVE_MODULE_IO
488 
489  vpImagePoint ip;
490  bool isWellInit = false;
491  while (!isWellInit) {
492  for (unsigned int i = 0; i < points3D_list.size(); i++) {
493  std::cout << "Click on point " << i + 1 << std::endl;
494  double x = 0, y = 0;
495  vpDisplay::getClick(I, ip);
497  vpDisplay::flush(I);
499  P[i].set_x(x);
500  P[i].set_y(y);
501 
502  std::cout << "Click on point " << ip << std::endl;
503 
504  vpDisplay::displayPoint(I, ip, vpColor::green); // display target point
505  pose.addPoint(P[i]); // and added to the pose computation point list
506  }
507  vpDisplay::flush(I);
508 
509  vpHomogeneousMatrix cMo1, cMo2;
510  pose.computePose(vpPose::LAGRANGE, cMo1);
511  double d1 = pose.computeResidual(cMo1);
512  pose.computePose(vpPose::DEMENTHON, cMo2);
513  double d2 = pose.computeResidual(cMo2);
514 
515  if (d1 < d2) {
516  cMo = cMo1;
517  } else {
518  cMo = cMo2;
519  }
521 
522  display(I, cMo, cam, vpColor::green, 1, true);
523  vpDisplay::displayText(I, 15, 10, "left click to validate, right click to re initialize object", vpColor::red);
524 
525  vpDisplay::flush(I);
526 
528  while (!vpDisplay::getClick(I, ip, button)) {
529  };
530 
531  if (button == vpMouseButton::button1) {
532  isWellInit = true;
533  } else {
534  pose.clearPoint();
536  vpDisplay::flush(I);
537  }
538  }
539 
541 
542  if (d_help != NULL) {
543  delete d_help;
544  d_help = NULL;
545  }
546 
547  init(I);
548 }
549 #endif //#ifdef VISP_HAVE_MODULE_GUI
550 
575 void vpMbTracker::initFromPoints(const vpImage<unsigned char> &I, const std::string &initFile)
576 {
577  char s[FILENAME_MAX];
578  std::fstream finit;
579 
580  std::string ext = ".init";
581  size_t pos = initFile.rfind(ext);
582 
583  if (pos == initFile.size() - ext.size() && pos != 0)
584  sprintf(s, "%s", initFile.c_str());
585  else
586  sprintf(s, "%s.init", initFile.c_str());
587 
588  std::cout << "Load 2D/3D points from: " << s << std::endl;
589  finit.open(s, std::ios::in);
590  if (finit.fail()) {
591  std::cout << "cannot read " << s << std::endl;
592  throw vpException(vpException::ioError, "Cannot open model-based tracker init file %s", s);
593  }
594 
595  //********
596  // Read 3D points coordinates
597  //********
598  char c;
599  // skip lines starting with # as comment
600  finit.get(c);
601  while (!finit.fail() && (c == '#')) {
602  finit.ignore(256, '\n');
603  finit.get(c);
604  }
605  finit.unget();
606 
607  unsigned int n3d;
608  finit >> n3d;
609  finit.ignore(256, '\n'); // skip the rest of the line
610  std::cout << "Number of 3D points " << n3d << std::endl;
611  if (n3d > 100000) {
612  throw vpException(vpException::badValue, "In %s file, the number of 3D points exceed the max allowed", s);
613  }
614 
615  vpPoint *P = new vpPoint[n3d];
616  for (unsigned int i = 0; i < n3d; i++) {
617  // skip lines starting with # as comment
618  finit.get(c);
619  while (!finit.fail() && (c == '#')) {
620  finit.ignore(256, '\n');
621  finit.get(c);
622  }
623  finit.unget();
624  double X, Y, Z;
625  finit >> X;
626  finit >> Y;
627  finit >> Z;
628  finit.ignore(256, '\n'); // skip the rest of the line
629 
630  std::cout << "Point " << i + 1 << " with 3D coordinates: " << X << " " << Y << " " << Z << std::endl;
631  P[i].setWorldCoordinates(X, Y, Z); // (X,Y,Z)
632  }
633 
634  //********
635  // Read 3D points coordinates
636  //********
637  // skip lines starting with # as comment
638  finit.get(c);
639  while (!finit.fail() && (c == '#')) {
640  finit.ignore(256, '\n');
641  finit.get(c);
642  }
643  finit.unget();
644 
645  unsigned int n2d;
646  finit >> n2d;
647  finit.ignore(256, '\n'); // skip the rest of the line
648  std::cout << "Number of 2D points " << n2d << std::endl;
649  if (n2d > 100000) {
650  delete[] P;
651  throw vpException(vpException::badValue, "In %s file, the number of 2D points exceed the max allowed", s);
652  }
653 
654  if (n3d != n2d) {
655  delete[] P;
657  "In %s file, number of 2D points %d and number of 3D "
658  "points %d are not equal",
659  s, n2d, n3d);
660  }
661 
662  vpPose pose;
663  for (unsigned int i = 0; i < n2d; i++) {
664  // skip lines starting with # as comment
665  finit.get(c);
666  while (!finit.fail() && (c == '#')) {
667  finit.ignore(256, '\n');
668  finit.get(c);
669  }
670  finit.unget();
671  double u, v, x = 0, y = 0;
672  finit >> v;
673  finit >> u;
674  finit.ignore(256, '\n'); // skip the rest of the line
675 
676  vpImagePoint ip(v, u);
677  std::cout << "Point " << i + 1 << " with 2D coordinates: " << ip << std::endl;
679  P[i].set_x(x);
680  P[i].set_y(y);
681  pose.addPoint(P[i]);
682  }
683 
684  finit.close();
685 
686  vpHomogeneousMatrix cMo1, cMo2;
687  pose.computePose(vpPose::LAGRANGE, cMo1);
688  double d1 = pose.computeResidual(cMo1);
689  pose.computePose(vpPose::DEMENTHON, cMo2);
690  double d2 = pose.computeResidual(cMo2);
691 
692  if (d1 < d2)
693  cMo = cMo1;
694  else
695  cMo = cMo2;
696 
698 
699  delete[] P;
700 
701  init(I);
702 }
703 
712 void vpMbTracker::initFromPoints(const vpImage<unsigned char> &I, const std::vector<vpImagePoint> &points2D_list,
713  const std::vector<vpPoint> &points3D_list)
714 {
715  if (points2D_list.size() != points3D_list.size())
716  vpERROR_TRACE("vpMbTracker::initFromPoints(), Number of 2D points "
717  "different to the number of 3D points.");
718 
719  size_t size = points3D_list.size();
720  std::vector<vpPoint> P;
721  vpPose pose;
722 
723  for (size_t i = 0; i < size; i++) {
724  P.push_back(vpPoint(points3D_list[i].get_oX(), points3D_list[i].get_oY(), points3D_list[i].get_oZ()));
725  double x = 0, y = 0;
726  vpPixelMeterConversion::convertPoint(cam, points2D_list[i], x, y);
727  P[i].set_x(x);
728  P[i].set_y(y);
729  pose.addPoint(P[i]);
730  }
731 
732  vpHomogeneousMatrix cMo1, cMo2;
733  pose.computePose(vpPose::LAGRANGE, cMo1);
734  double d1 = pose.computeResidual(cMo1);
735  pose.computePose(vpPose::DEMENTHON, cMo2);
736  double d2 = pose.computeResidual(cMo2);
737 
738  if (d1 < d2)
739  cMo = cMo1;
740  else
741  cMo = cMo2;
742 
744 
745  init(I);
746 }
747 
765 void vpMbTracker::initFromPose(const vpImage<unsigned char> &I, const std::string &initFile)
766 {
767  char s[FILENAME_MAX];
768  std::fstream finit;
769  vpPoseVector init_pos;
770 
771  std::string ext = ".pos";
772  size_t pos = initFile.rfind(ext);
773 
774  if (pos == initFile.size() - ext.size() && pos != 0)
775  sprintf(s, "%s", initFile.c_str());
776  else
777  sprintf(s, "%s.pos", initFile.c_str());
778 
779  finit.open(s, std::ios::in);
780  if (finit.fail()) {
781  std::cout << "cannot read " << s << std::endl;
782  throw vpException(vpException::ioError, "cannot read init file");
783  }
784 
785  for (unsigned int i = 0; i < 6; i += 1) {
786  finit >> init_pos[i];
787  }
788 
789  cMo.buildFrom(init_pos);
790 
791  init(I);
792 }
793 
801 {
802  this->cMo = cMo_;
803  init(I);
804 }
805 
813 {
814  vpHomogeneousMatrix _cMo(cPo);
815  initFromPose(I, _cMo);
816 }
817 
823 void vpMbTracker::savePose(const std::string &filename) const
824 {
825  vpPoseVector init_pos;
826  std::fstream finitpos;
827  char s[FILENAME_MAX];
828 
829  sprintf(s, "%s", filename.c_str());
830  finitpos.open(s, std::ios::out);
831 
832  init_pos.buildFrom(cMo);
833  finitpos << init_pos;
834  finitpos.close();
835 }
836 
837 void vpMbTracker::addPolygon(const std::vector<vpPoint> &corners, const int idFace, const std::string &polygonName,
838  const bool useLod, const double minPolygonAreaThreshold,
839  const double minLineLengthThreshold)
840 {
841  std::vector<vpPoint> corners_without_duplicates;
842  corners_without_duplicates.push_back(corners[0]);
843  for (unsigned int i = 0; i < corners.size() - 1; i++) {
844  if (std::fabs(corners[i].get_oX() - corners[i + 1].get_oX()) >
845  std::fabs(corners[i].get_oX()) * std::numeric_limits<double>::epsilon() ||
846  std::fabs(corners[i].get_oY() - corners[i + 1].get_oY()) >
847  std::fabs(corners[i].get_oY()) * std::numeric_limits<double>::epsilon() ||
848  std::fabs(corners[i].get_oZ() - corners[i + 1].get_oZ()) >
849  std::fabs(corners[i].get_oZ()) * std::numeric_limits<double>::epsilon()) {
850  corners_without_duplicates.push_back(corners[i + 1]);
851  }
852  }
853 
854  vpMbtPolygon polygon;
855  polygon.setNbPoint((unsigned int)corners_without_duplicates.size());
856  polygon.setIndex((int)idFace);
857  polygon.setName(polygonName);
858  polygon.setLod(useLod);
859 
860  // //if(minPolygonAreaThreshold != -1.0) {
861  // if(std::fabs(minPolygonAreaThreshold + 1.0) >
862  // std::fabs(minPolygonAreaThreshold)*std::numeric_limits<double>::epsilon())
863  // {
864  // polygon.setMinPolygonAreaThresh(minPolygonAreaThreshold);
865  // }
866  //
867  // //if(minLineLengthThreshold != -1.0) {
868  // if(std::fabs(minLineLengthThreshold + 1.0) >
869  // std::fabs(minLineLengthThreshold)*std::numeric_limits<double>::epsilon())
870  // {
871  // polygon.setMinLineLengthThresh(minLineLengthThreshold);
872  // }
873 
874  polygon.setMinPolygonAreaThresh(minPolygonAreaThreshold);
875  polygon.setMinLineLengthThresh(minLineLengthThreshold);
876 
877  for (unsigned int j = 0; j < corners_without_duplicates.size(); j++) {
878  polygon.addPoint(j, corners_without_duplicates[j]);
879  }
880 
881  faces.addPolygon(&polygon);
882 
884  faces.getPolygon().back()->setClipping(clippingFlag);
885 
886  if ((clippingFlag & vpPolygon3D::NEAR_CLIPPING) == vpPolygon3D::NEAR_CLIPPING)
887  faces.getPolygon().back()->setNearClippingDistance(distNearClip);
888 
889  if ((clippingFlag & vpPolygon3D::FAR_CLIPPING) == vpPolygon3D::FAR_CLIPPING)
890  faces.getPolygon().back()->setFarClippingDistance(distFarClip);
891 }
892 
893 void vpMbTracker::addPolygon(const vpPoint &p1, const vpPoint &p2, const vpPoint &p3, const double radius,
894  const int idFace, const std::string &polygonName, const bool useLod,
895  const double minPolygonAreaThreshold)
896 {
897  vpMbtPolygon polygon;
898  polygon.setNbPoint(4);
899  polygon.setName(polygonName);
900  polygon.setLod(useLod);
901 
902  // //if(minPolygonAreaThreshold != -1.0) {
903  // if(std::fabs(minPolygonAreaThreshold + 1.0) >
904  // std::fabs(minPolygonAreaThreshold)*std::numeric_limits<double>::epsilon())
905  // {
906  // polygon.setMinPolygonAreaThresh(minPolygonAreaThreshold);
907  // }
908  polygon.setMinPolygonAreaThresh(minPolygonAreaThreshold);
909  // Non sense to set minLineLengthThreshold for circle
910  // but used to be coherent when applying LOD settings for all polygons
912 
913  {
914  // Create the 4 points of the circle bounding box
915  vpPlane plane(p1, p2, p3, vpPlane::object_frame);
916 
917  // Matrice de passage entre world et circle frame
918  double norm_X = sqrt(vpMath::sqr(p2.get_oX() - p1.get_oX()) + vpMath::sqr(p2.get_oY() - p1.get_oY()) +
919  vpMath::sqr(p2.get_oZ() - p1.get_oZ()));
920  double norm_Y = sqrt(vpMath::sqr(plane.getA()) + vpMath::sqr(plane.getB()) + vpMath::sqr(plane.getC()));
921  vpRotationMatrix wRc;
922  vpColVector x(3), y(3), z(3);
923  // X axis is P2-P1
924  x[0] = (p2.get_oX() - p1.get_oX()) / norm_X;
925  x[1] = (p2.get_oY() - p1.get_oY()) / norm_X;
926  x[2] = (p2.get_oZ() - p1.get_oZ()) / norm_X;
927  // Y axis is the normal of the plane
928  y[0] = plane.getA() / norm_Y;
929  y[1] = plane.getB() / norm_Y;
930  y[2] = plane.getC() / norm_Y;
931  // Z axis = X ^ Y
932  z = vpColVector::crossProd(x, y);
933  for (unsigned int i = 0; i < 3; i++) {
934  wRc[i][0] = x[i];
935  wRc[i][1] = y[i];
936  wRc[i][2] = z[i];
937  }
938 
939  vpTranslationVector wtc(p1.get_oX(), p1.get_oY(), p1.get_oZ());
940  vpHomogeneousMatrix wMc(wtc, wRc);
941 
942  vpColVector c_p(4); // A point in the circle frame that is on the bbox
943  c_p[0] = radius;
944  c_p[1] = 0;
945  c_p[2] = radius;
946  c_p[3] = 1;
947 
948  // Matrix to rotate a point by 90 deg around Y in the circle frame
949  for (unsigned int i = 0; i < 4; i++) {
950  vpColVector w_p(4); // A point in the word frame
952  w_p = wMc * cMc_90 * c_p;
953 
954  vpPoint w_P;
955  w_P.setWorldCoordinates(w_p[0], w_p[1], w_p[2]);
956 
957  polygon.addPoint(i, w_P);
958  }
959  }
960 
961  polygon.setIndex(idFace);
962  faces.addPolygon(&polygon);
963 
965  faces.getPolygon().back()->setClipping(clippingFlag);
966 
967  if ((clippingFlag & vpPolygon3D::NEAR_CLIPPING) == vpPolygon3D::NEAR_CLIPPING)
968  faces.getPolygon().back()->setNearClippingDistance(distNearClip);
969 
970  if ((clippingFlag & vpPolygon3D::FAR_CLIPPING) == vpPolygon3D::FAR_CLIPPING)
971  faces.getPolygon().back()->setFarClippingDistance(distFarClip);
972 }
973 
974 void vpMbTracker::addPolygon(const vpPoint &p1, const vpPoint &p2, const int idFace, const std::string &polygonName,
975  const bool useLod, const double minLineLengthThreshold)
976 {
977  // A polygon as a single line that corresponds to the revolution axis of the
978  // cylinder
979  vpMbtPolygon polygon;
980  polygon.setNbPoint(2);
981 
982  polygon.addPoint(0, p1);
983  polygon.addPoint(1, p2);
984 
985  polygon.setIndex(idFace);
986  polygon.setName(polygonName);
987  polygon.setLod(useLod);
988 
989  // //if(minLineLengthThreshold != -1.0) {
990  // if(std::fabs(minLineLengthThreshold + 1.0) >
991  // std::fabs(minLineLengthThreshold)*std::numeric_limits<double>::epsilon())
992  // {
993  // polygon.setMinLineLengthThresh(minLineLengthThreshold);
994  // }
995  polygon.setMinLineLengthThresh(minLineLengthThreshold);
996  // Non sense to set minPolygonAreaThreshold for cylinder
997  // but used to be coherent when applying LOD settings for all polygons
999 
1000  faces.addPolygon(&polygon);
1001 
1003  faces.getPolygon().back()->setClipping(clippingFlag);
1004 
1005  if ((clippingFlag & vpPolygon3D::NEAR_CLIPPING) == vpPolygon3D::NEAR_CLIPPING)
1006  faces.getPolygon().back()->setNearClippingDistance(distNearClip);
1007 
1008  if ((clippingFlag & vpPolygon3D::FAR_CLIPPING) == vpPolygon3D::FAR_CLIPPING)
1009  faces.getPolygon().back()->setFarClippingDistance(distFarClip);
1010 }
1011 
1012 void vpMbTracker::addPolygon(const std::vector<std::vector<vpPoint> > &listFaces, const int idFace,
1013  const std::string &polygonName, const bool useLod, const double minLineLengthThreshold)
1014 {
1015  int id = idFace;
1016  for (unsigned int i = 0; i < listFaces.size(); i++) {
1017  vpMbtPolygon polygon;
1018  polygon.setNbPoint((unsigned int)listFaces[i].size());
1019  for (unsigned int j = 0; j < listFaces[i].size(); j++)
1020  polygon.addPoint(j, listFaces[i][j]);
1021 
1022  polygon.setIndex(id);
1023  polygon.setName(polygonName);
1024  polygon.setIsPolygonOriented(false);
1025  polygon.setLod(useLod);
1026  polygon.setMinLineLengthThresh(minLineLengthThreshold);
1028 
1029  faces.addPolygon(&polygon);
1030 
1032  faces.getPolygon().back()->setClipping(clippingFlag);
1033 
1034  if ((clippingFlag & vpPolygon3D::NEAR_CLIPPING) == vpPolygon3D::NEAR_CLIPPING)
1035  faces.getPolygon().back()->setNearClippingDistance(distNearClip);
1036 
1037  if ((clippingFlag & vpPolygon3D::FAR_CLIPPING) == vpPolygon3D::FAR_CLIPPING)
1038  faces.getPolygon().back()->setFarClippingDistance(distFarClip);
1039 
1040  id++;
1041  }
1042 }
1043 
1069 void vpMbTracker::loadModel(const char *modelFile, const bool verbose) { loadModel(std::string(modelFile), verbose); }
1070 
1096 void vpMbTracker::loadModel(const std::string &modelFile, const bool verbose)
1097 {
1098  std::string::const_iterator it;
1099 
1100  if (vpIoTools::checkFilename(modelFile)) {
1101  it = modelFile.end();
1102  if ((*(it - 1) == 'o' && *(it - 2) == 'a' && *(it - 3) == 'c' && *(it - 4) == '.') ||
1103  (*(it - 1) == 'O' && *(it - 2) == 'A' && *(it - 3) == 'C' && *(it - 4) == '.')) {
1104  std::vector<std::string> vectorOfModelFilename;
1105  int startIdFace = (int)faces.size();
1106  nbPoints = 0;
1107  nbLines = 0;
1108  nbPolygonLines = 0;
1109  nbPolygonPoints = 0;
1110  nbCylinders = 0;
1111  nbCircles = 0;
1112  loadCAOModel(modelFile, vectorOfModelFilename, startIdFace, verbose, true);
1113  } else if ((*(it - 1) == 'l' && *(it - 2) == 'r' && *(it - 3) == 'w' && *(it - 4) == '.') ||
1114  (*(it - 1) == 'L' && *(it - 2) == 'R' && *(it - 3) == 'W' && *(it - 4) == '.')) {
1115  loadVRMLModel(modelFile);
1116  } else {
1117  throw vpException(vpException::ioError, "Error: File %s doesn't contain a cao or wrl model", modelFile.c_str());
1118  }
1119  } else {
1120  throw vpException(vpException::ioError, "Error: File %s doesn't exist", modelFile.c_str());
1121  }
1122 
1123  this->modelInitialised = true;
1124  this->modelFileName = modelFile;
1125 }
1126 
1157 void vpMbTracker::loadVRMLModel(const std::string &modelFile)
1158 {
1159 #ifdef VISP_HAVE_COIN3D
1160  SoDB::init(); // Call SoDB::finish() before ending the program.
1161 
1162  SoInput in;
1163  SbBool ok = in.openFile(modelFile.c_str());
1164  SoVRMLGroup *sceneGraphVRML2;
1165 
1166  if (!ok) {
1167  vpERROR_TRACE("can't open file to load model");
1168  throw vpException(vpException::fatalError, "can't open file to load model");
1169  }
1170 
1171  if (!in.isFileVRML2()) {
1172  SoSeparator *sceneGraph = SoDB::readAll(&in);
1173  if (sceneGraph == NULL) { /*return -1;*/
1174  }
1175  sceneGraph->ref();
1176 
1177  SoToVRML2Action tovrml2;
1178  tovrml2.apply(sceneGraph);
1179 
1180  sceneGraphVRML2 = tovrml2.getVRML2SceneGraph();
1181  sceneGraphVRML2->ref();
1182  sceneGraph->unref();
1183  } else {
1184  sceneGraphVRML2 = SoDB::readAllVRML(&in);
1185  if (sceneGraphVRML2 == NULL) { /*return -1;*/
1186  }
1187  sceneGraphVRML2->ref();
1188  }
1189 
1190  in.closeFile();
1191 
1192  vpHomogeneousMatrix transform;
1193  int indexFace = (int)faces.size();
1194  extractGroup(sceneGraphVRML2, transform, indexFace);
1195 
1196  sceneGraphVRML2->unref();
1197 #else
1198  vpERROR_TRACE("coin not detected with ViSP, cannot load model : %s", modelFile.c_str());
1199  throw vpException(vpException::fatalError, "coin not detected with ViSP, cannot load model");
1200 #endif
1201 }
1202 
1203 void vpMbTracker::removeComment(std::ifstream &fileId)
1204 {
1205  char c;
1206 
1207  fileId.get(c);
1208  while (!fileId.fail() && (c == '#')) {
1209  fileId.ignore(256, '\n');
1210  fileId.get(c);
1211  }
1212  if (fileId.fail()) {
1213  throw(vpException(vpException::ioError, "Reached end of file"));
1214  }
1215  fileId.unget();
1216 }
1217 
1218 std::map<std::string, std::string> vpMbTracker::parseParameters(std::string &endLine)
1219 {
1220  std::map<std::string, std::string> mapOfParams;
1221 
1222  bool exit = false;
1223  while (!endLine.empty() && !exit) {
1224  exit = true;
1225 
1226  for (std::map<std::string, std::string>::const_iterator it = mapOfParameterNames.begin();
1227  it != mapOfParameterNames.end(); ++it) {
1228  endLine = trim(endLine);
1229  // std::cout << "endLine=" << endLine << std::endl;
1230  std::string param(it->first + "=");
1231 
1232  // Compare with a potential parameter
1233  if (endLine.compare(0, param.size(), param) == 0) {
1234  exit = false;
1235  endLine = endLine.substr(param.size());
1236 
1237  bool parseQuote = false;
1238  if (it->second == "string") {
1239  // Check if the string is between quotes
1240  if (endLine.size() > 2 && endLine[0] == '"') {
1241  parseQuote = true;
1242  endLine = endLine.substr(1);
1243  size_t pos = endLine.find_first_of('"');
1244 
1245  if (pos != std::string::npos) {
1246  mapOfParams[it->first] = endLine.substr(0, pos);
1247  endLine = endLine.substr(pos + 1);
1248  } else {
1249  parseQuote = false;
1250  }
1251  }
1252  }
1253 
1254  if (!parseQuote) {
1255  // Deal with space or tabulation after parameter value to substring
1256  // to the next sequence
1257  size_t pos1 = endLine.find_first_of(' ');
1258  size_t pos2 = endLine.find_first_of('\t');
1259  size_t pos = pos1 < pos2 ? pos1 : pos2;
1260 
1261  mapOfParams[it->first] = endLine.substr(0, pos);
1262  endLine = endLine.substr(pos + 1);
1263  }
1264  }
1265  }
1266  }
1267 
1268  return mapOfParams;
1269 }
1270 
1318 void vpMbTracker::loadCAOModel(const std::string &modelFile, std::vector<std::string> &vectorOfModelFilename,
1319  int &startIdFace, const bool verbose, const bool parent)
1320 {
1321  std::ifstream fileId;
1322  fileId.exceptions(std::ifstream::failbit | std::ifstream::eofbit);
1323  fileId.open(modelFile.c_str(), std::ifstream::in);
1324  if (fileId.fail()) {
1325  std::cout << "cannot read CAO model file: " << modelFile << std::endl;
1326  throw vpException(vpException::ioError, "cannot read CAO model file");
1327  }
1328 
1329  if (verbose) {
1330  std::cout << "Model file : " << modelFile << std::endl;
1331  }
1332  vectorOfModelFilename.push_back(modelFile);
1333 
1334  try {
1335  char c;
1336  // Extraction of the version (remove empty line and commented ones
1337  // (comment line begin with the #)).
1338  // while ((fileId.get(c) != NULL) && (c == '#')) fileId.ignore(256, '\n');
1339  removeComment(fileId);
1340 
1343  int caoVersion;
1344  fileId.get(c);
1345  if (c == 'V') {
1346  fileId >> caoVersion;
1347  fileId.ignore(256, '\n'); // skip the rest of the line
1348  } else {
1349  std::cout << "in vpMbTracker::loadCAOModel() -> Bad parameter header "
1350  "file : use V0, V1, ...";
1351  throw vpException(vpException::badValue, "in vpMbTracker::loadCAOModel() -> Bad parameter "
1352  "header file : use V0, V1, ...");
1353  }
1354 
1355  removeComment(fileId);
1356 
1359  std::string line;
1360  std::string prefix = "load";
1361 
1362  fileId.get(c);
1363  fileId.unget();
1364  bool header = false;
1365  while (c == 'l' || c == 'L') {
1366  header = true;
1367 
1368  getline(fileId, line);
1369  if (!line.compare(0, prefix.size(), prefix)) {
1370 
1371  // Get the loaded model pathname
1372  std::string headerPathRead = line.substr(6);
1373  size_t firstIndex = headerPathRead.find_first_of("\")");
1374  headerPathRead = headerPathRead.substr(0, firstIndex);
1375 
1376  std::string headerPath = headerPathRead;
1377  if (!vpIoTools::isAbsolutePathname(headerPathRead)) {
1378  std::string parentDirectory = vpIoTools::getParent(modelFile);
1379  headerPath = vpIoTools::createFilePath(parentDirectory, headerPathRead);
1380  }
1381 
1382  // Normalize path
1383  headerPath = vpIoTools::path(headerPath);
1384 
1385  // Get real path
1386  headerPath = vpIoTools::getAbsolutePathname(headerPath);
1387 
1388  bool cyclic = false;
1389  for (std::vector<std::string>::const_iterator it = vectorOfModelFilename.begin();
1390  it != vectorOfModelFilename.end() && !cyclic; ++it) {
1391  if (headerPath == *it) {
1392  cyclic = true;
1393  }
1394  }
1395 
1396  if (!cyclic) {
1397  if (vpIoTools::checkFilename(headerPath)) {
1398  loadCAOModel(headerPath, vectorOfModelFilename, startIdFace, verbose, false);
1399  } else {
1400  throw vpException(vpException::ioError, "file cannot be open");
1401  }
1402  } else {
1403  std::cout << "WARNING Cyclic dependency detected with file " << headerPath << " declared in " << modelFile
1404  << std::endl;
1405  }
1406  } else {
1407  header = false;
1408  }
1409 
1410  removeComment(fileId);
1411  fileId.get(c);
1412  fileId.unget();
1413  }
1414 
1417  unsigned int caoNbrPoint;
1418  fileId >> caoNbrPoint;
1419  fileId.ignore(256, '\n'); // skip the rest of the line
1420 
1421  nbPoints += caoNbrPoint;
1422  if (verbose || vectorOfModelFilename.size() == 1) {
1423  std::cout << "> " << caoNbrPoint << " points" << std::endl;
1424  }
1425 
1426  if (caoNbrPoint > 100000) {
1427  throw vpException(vpException::badValue, "Exceed the max number of points in the CAO model.");
1428  }
1429 
1430  if (caoNbrPoint == 0 && !header) {
1431  throw vpException(vpException::badValue, "in vpMbTracker::loadCAOModel() -> no points are defined");
1432  }
1433  vpPoint *caoPoints = new vpPoint[caoNbrPoint];
1434 
1435  double x; // 3D coordinates
1436  double y;
1437  double z;
1438 
1439  int i; // image coordinate (used for matching)
1440  int j;
1441 
1442  for (unsigned int k = 0; k < caoNbrPoint; k++) {
1443  removeComment(fileId);
1444 
1445  fileId >> x;
1446  fileId >> y;
1447  fileId >> z;
1448 
1449  if (caoVersion == 2) {
1450  fileId >> i;
1451  fileId >> j;
1452  }
1453 
1454  fileId.ignore(256, '\n'); // skip the rest of the line
1455 
1456  caoPoints[k].setWorldCoordinates(x, y, z);
1457  }
1458 
1459  removeComment(fileId);
1460 
1463  // Store in a map the potential segments to add
1464  std::map<std::pair<unsigned int, unsigned int>, SegmentInfo> segmentTemporaryMap;
1465  unsigned int caoNbrLine;
1466  fileId >> caoNbrLine;
1467  fileId.ignore(256, '\n'); // skip the rest of the line
1468 
1469  nbLines += caoNbrLine;
1470  unsigned int *caoLinePoints = NULL;
1471  if (verbose || vectorOfModelFilename.size() == 1) {
1472  std::cout << "> " << caoNbrLine << " lines" << std::endl;
1473  }
1474 
1475  if (caoNbrLine > 100000) {
1476  delete[] caoPoints;
1477  throw vpException(vpException::badValue, "Exceed the max number of lines in the CAO model.");
1478  }
1479 
1480  if (caoNbrLine > 0)
1481  caoLinePoints = new unsigned int[2 * caoNbrLine];
1482 
1483  unsigned int index1, index2;
1484  // Initialization of idFace with startIdFace for dealing with recursive
1485  // load in header
1486  int idFace = startIdFace;
1487 
1488  for (unsigned int k = 0; k < caoNbrLine; k++) {
1489  removeComment(fileId);
1490 
1491  fileId >> index1;
1492  fileId >> index2;
1493 
1496  // Get the end of the line
1497  char buffer[256];
1498  fileId.getline(buffer, 256);
1499  std::string endLine(buffer);
1500  std::map<std::string, std::string> mapOfParams = parseParameters(endLine);
1501 
1502  std::string segmentName = "";
1503  double minLineLengthThresh = !applyLodSettingInConfig ? minLineLengthThresholdGeneral : 50.0;
1504  bool useLod = !applyLodSettingInConfig ? useLodGeneral : false;
1505  if (mapOfParams.find("name") != mapOfParams.end()) {
1506  segmentName = mapOfParams["name"];
1507  }
1508  if (mapOfParams.find("minLineLengthThreshold") != mapOfParams.end()) {
1509  minLineLengthThresh = std::atof(mapOfParams["minLineLengthThreshold"].c_str());
1510  }
1511  if (mapOfParams.find("useLod") != mapOfParams.end()) {
1512  useLod = parseBoolean(mapOfParams["useLod"]);
1513  }
1514 
1515  SegmentInfo segmentInfo;
1516  segmentInfo.name = segmentName;
1517  segmentInfo.useLod = useLod;
1518  segmentInfo.minLineLengthThresh = minLineLengthThresh;
1519 
1520  caoLinePoints[2 * k] = index1;
1521  caoLinePoints[2 * k + 1] = index2;
1522 
1523  if (index1 < caoNbrPoint && index2 < caoNbrPoint) {
1524  std::vector<vpPoint> extremities;
1525  extremities.push_back(caoPoints[index1]);
1526  extremities.push_back(caoPoints[index2]);
1527  segmentInfo.extremities = extremities;
1528 
1529  std::pair<unsigned int, unsigned int> key(index1, index2);
1530 
1531  segmentTemporaryMap[key] = segmentInfo;
1532  } else {
1533  vpTRACE(" line %d has wrong coordinates.", k);
1534  }
1535  }
1536 
1537  removeComment(fileId);
1538 
1541  /* Load polygon from the lines extracted earlier (the first point of the
1542  * line is used)*/
1543  // Store in a vector the indexes of the segments added in the face segment
1544  // case
1545  std::vector<std::pair<unsigned int, unsigned int> > faceSegmentKeyVector;
1546  unsigned int caoNbrPolygonLine;
1547  fileId >> caoNbrPolygonLine;
1548  fileId.ignore(256, '\n'); // skip the rest of the line
1549 
1550  nbPolygonLines += caoNbrPolygonLine;
1551  if (verbose || vectorOfModelFilename.size() == 1) {
1552  std::cout << "> " << caoNbrPolygonLine << " polygon lines" << std::endl;
1553  }
1554 
1555  if (caoNbrPolygonLine > 100000) {
1556  delete[] caoPoints;
1557  delete[] caoLinePoints;
1558  throw vpException(vpException::badValue, "Exceed the max number of polygon lines.");
1559  }
1560 
1561  unsigned int index;
1562  for (unsigned int k = 0; k < caoNbrPolygonLine; k++) {
1563  removeComment(fileId);
1564 
1565  unsigned int nbLinePol;
1566  fileId >> nbLinePol;
1567  std::vector<vpPoint> corners;
1568  if (nbLinePol > 100000) {
1569  throw vpException(vpException::badValue, "Exceed the max number of lines.");
1570  }
1571 
1572  for (unsigned int n = 0; n < nbLinePol; n++) {
1573  fileId >> index;
1574 
1575  if (index >= caoNbrLine) {
1576  throw vpException(vpException::badValue, "Exceed the max number of lines.");
1577  }
1578  corners.push_back(caoPoints[caoLinePoints[2 * index]]);
1579  corners.push_back(caoPoints[caoLinePoints[2 * index + 1]]);
1580 
1581  std::pair<unsigned int, unsigned int> key(caoLinePoints[2 * index], caoLinePoints[2 * index + 1]);
1582  faceSegmentKeyVector.push_back(key);
1583  }
1584 
1587  // Get the end of the line
1588  char buffer[256];
1589  fileId.getline(buffer, 256);
1590  std::string endLine(buffer);
1591  std::map<std::string, std::string> mapOfParams = parseParameters(endLine);
1592 
1593  std::string polygonName = "";
1594  bool useLod = !applyLodSettingInConfig ? useLodGeneral : false;
1595  double minPolygonAreaThreshold = !applyLodSettingInConfig ? minPolygonAreaThresholdGeneral : 2500.0;
1596  if (mapOfParams.find("name") != mapOfParams.end()) {
1597  polygonName = mapOfParams["name"];
1598  }
1599  if (mapOfParams.find("minPolygonAreaThreshold") != mapOfParams.end()) {
1600  minPolygonAreaThreshold = std::atof(mapOfParams["minPolygonAreaThreshold"].c_str());
1601  }
1602  if (mapOfParams.find("useLod") != mapOfParams.end()) {
1603  useLod = parseBoolean(mapOfParams["useLod"]);
1604  }
1605 
1606  addPolygon(corners, idFace++, polygonName, useLod, minPolygonAreaThreshold, minLineLengthThresholdGeneral);
1607  initFaceFromLines(*(faces.getPolygon().back())); // Init from the last polygon that was added
1608  }
1609 
1610  // Add the segments which were not already added in the face segment case
1611  for (std::map<std::pair<unsigned int, unsigned int>, SegmentInfo>::const_iterator it = segmentTemporaryMap.begin();
1612  it != segmentTemporaryMap.end(); ++it) {
1613  if (std::find(faceSegmentKeyVector.begin(), faceSegmentKeyVector.end(), it->first) ==
1614  faceSegmentKeyVector.end()) {
1615  addPolygon(it->second.extremities, idFace++, it->second.name, it->second.useLod, minPolygonAreaThresholdGeneral,
1616  it->second.minLineLengthThresh);
1617  initFaceFromCorners(*(faces.getPolygon().back())); // Init from the last polygon that was added
1618  }
1619  }
1620 
1621  removeComment(fileId);
1622 
1625  /* Extract the polygon using the point coordinates (top of the file) */
1626  unsigned int caoNbrPolygonPoint;
1627  fileId >> caoNbrPolygonPoint;
1628  fileId.ignore(256, '\n'); // skip the rest of the line
1629 
1630  nbPolygonPoints += caoNbrPolygonPoint;
1631  if (verbose || vectorOfModelFilename.size() == 1) {
1632  std::cout << "> " << caoNbrPolygonPoint << " polygon points" << std::endl;
1633  }
1634 
1635  if (caoNbrPolygonPoint > 100000) {
1636  throw vpException(vpException::badValue, "Exceed the max number of polygon point.");
1637  }
1638 
1639  for (unsigned int k = 0; k < caoNbrPolygonPoint; k++) {
1640  removeComment(fileId);
1641 
1642  unsigned int nbPointPol;
1643  fileId >> nbPointPol;
1644  if (nbPointPol > 100000) {
1645  throw vpException(vpException::badValue, "Exceed the max number of points.");
1646  }
1647  std::vector<vpPoint> corners;
1648  for (unsigned int n = 0; n < nbPointPol; n++) {
1649  fileId >> index;
1650  if (index > caoNbrPoint - 1) {
1651  throw vpException(vpException::badValue, "Exceed the max number of points.");
1652  }
1653  corners.push_back(caoPoints[index]);
1654  }
1655 
1658  // Get the end of the line
1659  char buffer[256];
1660  fileId.getline(buffer, 256);
1661  std::string endLine(buffer);
1662  std::map<std::string, std::string> mapOfParams = parseParameters(endLine);
1663 
1664  std::string polygonName = "";
1665  bool useLod = !applyLodSettingInConfig ? useLodGeneral : false;
1666  double minPolygonAreaThreshold = !applyLodSettingInConfig ? minPolygonAreaThresholdGeneral : 2500.0;
1667  if (mapOfParams.find("name") != mapOfParams.end()) {
1668  polygonName = mapOfParams["name"];
1669  }
1670  if (mapOfParams.find("minPolygonAreaThreshold") != mapOfParams.end()) {
1671  minPolygonAreaThreshold = std::atof(mapOfParams["minPolygonAreaThreshold"].c_str());
1672  }
1673  if (mapOfParams.find("useLod") != mapOfParams.end()) {
1674  useLod = parseBoolean(mapOfParams["useLod"]);
1675  }
1676 
1677  addPolygon(corners, idFace++, polygonName, useLod, minPolygonAreaThreshold, minLineLengthThresholdGeneral);
1678  initFaceFromCorners(*(faces.getPolygon().back())); // Init from the last polygon that was added
1679  }
1680 
1683  unsigned int caoNbCylinder;
1684  try {
1685  removeComment(fileId);
1686 
1687  if (fileId.eof()) { // check if not at the end of the file (for old
1688  // style files)
1689  delete[] caoPoints;
1690  delete[] caoLinePoints;
1691  return;
1692  }
1693 
1694  /* Extract the cylinders */
1695  fileId >> caoNbCylinder;
1696  fileId.ignore(256, '\n'); // skip the rest of the line
1697 
1698  nbCylinders += caoNbCylinder;
1699  if (verbose || vectorOfModelFilename.size() == 1) {
1700  std::cout << "> " << caoNbCylinder << " cylinders" << std::endl;
1701  }
1702 
1703  if (caoNbCylinder > 100000) {
1704  throw vpException(vpException::badValue, "Exceed the max number of cylinders.");
1705  }
1706 
1707  for (unsigned int k = 0; k < caoNbCylinder; ++k) {
1708  removeComment(fileId);
1709 
1710  double radius;
1711  unsigned int indexP1, indexP2;
1712  fileId >> indexP1;
1713  fileId >> indexP2;
1714  fileId >> radius;
1715 
1718  // Get the end of the line
1719  char buffer[256];
1720  fileId.getline(buffer, 256);
1721  std::string endLine(buffer);
1722  std::map<std::string, std::string> mapOfParams = parseParameters(endLine);
1723 
1724  std::string polygonName = "";
1725  bool useLod = !applyLodSettingInConfig ? useLodGeneral : false;
1726  double minLineLengthThreshold = !applyLodSettingInConfig ? minLineLengthThresholdGeneral : 50.0;
1727  if (mapOfParams.find("name") != mapOfParams.end()) {
1728  polygonName = mapOfParams["name"];
1729  }
1730  if (mapOfParams.find("minLineLengthThreshold") != mapOfParams.end()) {
1731  minLineLengthThreshold = std::atof(mapOfParams["minLineLengthThreshold"].c_str());
1732  }
1733  if (mapOfParams.find("useLod") != mapOfParams.end()) {
1734  useLod = parseBoolean(mapOfParams["useLod"]);
1735  }
1736 
1737  int idRevolutionAxis = idFace;
1738  addPolygon(caoPoints[indexP1], caoPoints[indexP2], idFace++, polygonName, useLod, minLineLengthThreshold);
1739 
1740  std::vector<std::vector<vpPoint> > listFaces;
1741  createCylinderBBox(caoPoints[indexP1], caoPoints[indexP2], radius, listFaces);
1742  addPolygon(listFaces, idFace, polygonName, useLod, minLineLengthThreshold);
1743  idFace += 4;
1744 
1745  initCylinder(caoPoints[indexP1], caoPoints[indexP2], radius, idRevolutionAxis, polygonName);
1746  }
1747 
1748  } catch (...) {
1749  std::cerr << "Cannot get the number of cylinders. Defaulting to zero." << std::endl;
1750  caoNbCylinder = 0;
1751  }
1752 
1755  unsigned int caoNbCircle;
1756  try {
1757  removeComment(fileId);
1758 
1759  if (fileId.eof()) { // check if not at the end of the file (for old
1760  // style files)
1761  delete[] caoPoints;
1762  delete[] caoLinePoints;
1763  return;
1764  }
1765 
1766  /* Extract the circles */
1767  fileId >> caoNbCircle;
1768  fileId.ignore(256, '\n'); // skip the rest of the line
1769 
1770  nbCircles += caoNbCircle;
1771  if (verbose || vectorOfModelFilename.size() == 1) {
1772  std::cout << "> " << caoNbCircle << " circles" << std::endl;
1773  }
1774 
1775  if (caoNbCircle > 100000) {
1776  throw vpException(vpException::badValue, "Exceed the max number of cicles.");
1777  }
1778 
1779  for (unsigned int k = 0; k < caoNbCircle; ++k) {
1780  removeComment(fileId);
1781 
1782  double radius;
1783  unsigned int indexP1, indexP2, indexP3;
1784  fileId >> radius;
1785  fileId >> indexP1;
1786  fileId >> indexP2;
1787  fileId >> indexP3;
1788 
1791  // Get the end of the line
1792  char buffer[256];
1793  fileId.getline(buffer, 256);
1794  std::string endLine(buffer);
1795  std::map<std::string, std::string> mapOfParams = parseParameters(endLine);
1796 
1797  std::string polygonName = "";
1798  bool useLod = !applyLodSettingInConfig ? useLodGeneral : false;
1799  double minPolygonAreaThreshold = !applyLodSettingInConfig ? minPolygonAreaThresholdGeneral : 2500.0;
1800  if (mapOfParams.find("name") != mapOfParams.end()) {
1801  polygonName = mapOfParams["name"];
1802  }
1803  if (mapOfParams.find("minPolygonAreaThreshold") != mapOfParams.end()) {
1804  minPolygonAreaThreshold = std::atof(mapOfParams["minPolygonAreaThreshold"].c_str());
1805  }
1806  if (mapOfParams.find("useLod") != mapOfParams.end()) {
1807  useLod = parseBoolean(mapOfParams["useLod"]);
1808  }
1809 
1810  addPolygon(caoPoints[indexP1], caoPoints[indexP2], caoPoints[indexP3], radius, idFace, polygonName, useLod,
1811  minPolygonAreaThreshold);
1812 
1813  initCircle(caoPoints[indexP1], caoPoints[indexP2], caoPoints[indexP3], radius, idFace++, polygonName);
1814  }
1815 
1816  } catch (...) {
1817  std::cerr << "Cannot get the number of circles. Defaulting to zero." << std::endl;
1818  caoNbCircle = 0;
1819  }
1820 
1821  startIdFace = idFace;
1822 
1823  delete[] caoPoints;
1824  delete[] caoLinePoints;
1825 
1826  if (vectorOfModelFilename.size() > 1 && parent) {
1827  if (verbose) {
1828  std::cout << "Global information for " << vpIoTools::getName(modelFile) << " :" << std::endl;
1829  std::cout << "Total nb of points : " << nbPoints << std::endl;
1830  std::cout << "Total nb of lines : " << nbLines << std::endl;
1831  std::cout << "Total nb of polygon lines : " << nbPolygonLines << std::endl;
1832  std::cout << "Total nb of polygon points : " << nbPolygonPoints << std::endl;
1833  std::cout << "Total nb of cylinders : " << nbCylinders << std::endl;
1834  std::cout << "Total nb of circles : " << nbCircles << std::endl;
1835  } else {
1836  std::cout << "> " << nbPoints << " points" << std::endl;
1837  std::cout << "> " << nbLines << " lines" << std::endl;
1838  std::cout << "> " << nbPolygonLines << " polygon lines" << std::endl;
1839  std::cout << "> " << nbPolygonPoints << " polygon points" << std::endl;
1840  std::cout << "> " << nbCylinders << " cylinders" << std::endl;
1841  std::cout << "> " << nbCircles << " circles" << std::endl;
1842  }
1843  }
1844  } catch (...) {
1845  std::cerr << "Cannot read line!" << std::endl;
1846  throw vpException(vpException::ioError, "cannot read line");
1847  }
1848 }
1849 
1850 #ifdef VISP_HAVE_COIN3D
1851 
1858 void vpMbTracker::extractGroup(SoVRMLGroup *sceneGraphVRML2, vpHomogeneousMatrix &transform, int &idFace)
1859 {
1860  vpHomogeneousMatrix transformCur;
1861  SoVRMLTransform *sceneGraphVRML2Trasnform = dynamic_cast<SoVRMLTransform *>(sceneGraphVRML2);
1862  if (sceneGraphVRML2Trasnform) {
1863  float rx, ry, rz, rw;
1864  sceneGraphVRML2Trasnform->rotation.getValue().getValue(rx, ry, rz, rw);
1865  vpRotationMatrix rotMat(vpQuaternionVector(rx, ry, rz, rw));
1866  // std::cout << "Rotation: " << rx << " " << ry << " " << rz << " " <<
1867  // rw << std::endl;
1868 
1869  float tx, ty, tz;
1870  tx = sceneGraphVRML2Trasnform->translation.getValue()[0];
1871  ty = sceneGraphVRML2Trasnform->translation.getValue()[1];
1872  tz = sceneGraphVRML2Trasnform->translation.getValue()[2];
1873  vpTranslationVector transVec(tx, ty, tz);
1874  // std::cout << "Translation: " << tx << " " << ty << " " << tz <<
1875  // std::endl;
1876 
1877  float sx, sy, sz;
1878  sx = sceneGraphVRML2Trasnform->scale.getValue()[0];
1879  sy = sceneGraphVRML2Trasnform->scale.getValue()[1];
1880  sz = sceneGraphVRML2Trasnform->scale.getValue()[2];
1881  // std::cout << "Scale: " << sx << " " << sy << " " << sz <<
1882  // std::endl;
1883 
1884  for (unsigned int i = 0; i < 3; i++)
1885  rotMat[0][i] *= sx;
1886  for (unsigned int i = 0; i < 3; i++)
1887  rotMat[1][i] *= sy;
1888  for (unsigned int i = 0; i < 3; i++)
1889  rotMat[2][i] *= sz;
1890 
1891  transformCur = vpHomogeneousMatrix(transVec, rotMat);
1892  transform = transform * transformCur;
1893  }
1894 
1895  int nbShapes = sceneGraphVRML2->getNumChildren();
1896  // std::cout << sceneGraphVRML2->getTypeId().getName().getString() <<
1897  // std::endl; std::cout << "Nb object in VRML : " << nbShapes <<
1898  // std::endl;
1899 
1900  SoNode *child;
1901 
1902  for (int i = 0; i < nbShapes; i++) {
1903  vpHomogeneousMatrix transform_recursive(transform);
1904  child = sceneGraphVRML2->getChild(i);
1905 
1906  if (child->getTypeId() == SoVRMLGroup::getClassTypeId()) {
1907  extractGroup((SoVRMLGroup *)child, transform_recursive, idFace);
1908  }
1909 
1910  if (child->getTypeId() == SoVRMLTransform::getClassTypeId()) {
1911  extractGroup((SoVRMLTransform *)child, transform_recursive, idFace);
1912  }
1913 
1914  if (child->getTypeId() == SoVRMLShape::getClassTypeId()) {
1915  SoChildList *child2list = child->getChildren();
1916  std::string name = child->getName().getString();
1917 
1918  for (int j = 0; j < child2list->getLength(); j++) {
1919  if (((SoNode *)child2list->get(j))->getTypeId() == SoVRMLIndexedFaceSet::getClassTypeId()) {
1920  SoVRMLIndexedFaceSet *face_set;
1921  face_set = (SoVRMLIndexedFaceSet *)child2list->get(j);
1922  if (!strncmp(face_set->getName().getString(), "cyl", 3)) {
1923  extractCylinders(face_set, transform, idFace, name);
1924  } else {
1925  extractFaces(face_set, transform, idFace, name);
1926  }
1927  }
1928  if (((SoNode *)child2list->get(j))->getTypeId() == SoVRMLIndexedLineSet::getClassTypeId()) {
1929  SoVRMLIndexedLineSet *line_set;
1930  line_set = (SoVRMLIndexedLineSet *)child2list->get(j);
1931  extractLines(line_set, idFace, name);
1932  }
1933  }
1934  }
1935  }
1936 }
1937 
1947 void vpMbTracker::extractFaces(SoVRMLIndexedFaceSet *face_set, vpHomogeneousMatrix &transform, int &idFace,
1948  const std::string &polygonName)
1949 {
1950  std::vector<vpPoint> corners;
1951  corners.resize(0);
1952 
1953  // SoMFInt32 indexList = _face_set->coordIndex;
1954  // int indexListSize = indexList.getNum();
1955  int indexListSize = face_set->coordIndex.getNum();
1956 
1957  vpColVector pointTransformed(4);
1958  vpPoint pt;
1959  SoVRMLCoordinate *coord;
1960 
1961  for (int i = 0; i < indexListSize; i++) {
1962  if (face_set->coordIndex[i] == -1) {
1963  if (corners.size() > 1) {
1964  addPolygon(corners, idFace++, polygonName);
1965  initFaceFromCorners(*(faces.getPolygon().back())); // Init from the last polygon that was added
1966  corners.resize(0);
1967  }
1968  } else {
1969  coord = (SoVRMLCoordinate *)(face_set->coord.getValue());
1970  int index = face_set->coordIndex[i];
1971  pointTransformed[0] = coord->point[index].getValue()[0];
1972  pointTransformed[1] = coord->point[index].getValue()[1];
1973  pointTransformed[2] = coord->point[index].getValue()[2];
1974  pointTransformed[3] = 1.0;
1975 
1976  pointTransformed = transform * pointTransformed;
1977 
1978  pt.setWorldCoordinates(pointTransformed[0], pointTransformed[1], pointTransformed[2]);
1979  corners.push_back(pt);
1980  }
1981  }
1982 }
1983 
1998 void vpMbTracker::extractCylinders(SoVRMLIndexedFaceSet *face_set, vpHomogeneousMatrix &transform, int &idFace,
1999  const std::string &polygonName)
2000 {
2001  std::vector<vpPoint> corners_c1, corners_c2; // points belonging to the
2002  // first circle and to the
2003  // second one.
2004  SoVRMLCoordinate *coords = (SoVRMLCoordinate *)face_set->coord.getValue();
2005 
2006  unsigned int indexListSize = (unsigned int)coords->point.getNum();
2007 
2008  if (indexListSize % 2 == 1) {
2009  std::cout << "Not an even number of points when extracting a cylinder." << std::endl;
2010  throw vpException(vpException::dimensionError, "Not an even number of points when extracting a cylinder.");
2011  }
2012  corners_c1.resize(indexListSize / 2);
2013  corners_c2.resize(indexListSize / 2);
2014  vpColVector pointTransformed(4);
2015  vpPoint pt;
2016 
2017  // extract all points and fill the two sets.
2018 
2019  for (int i = 0; i < coords->point.getNum(); ++i) {
2020  pointTransformed[0] = coords->point[i].getValue()[0];
2021  pointTransformed[1] = coords->point[i].getValue()[1];
2022  pointTransformed[2] = coords->point[i].getValue()[2];
2023  pointTransformed[3] = 1.0;
2024 
2025  pointTransformed = transform * pointTransformed;
2026 
2027  pt.setWorldCoordinates(pointTransformed[0], pointTransformed[1], pointTransformed[2]);
2028 
2029  if (i < (int)corners_c1.size()) {
2030  corners_c1[(unsigned int)i] = pt;
2031  } else {
2032  corners_c2[(unsigned int)i - corners_c1.size()] = pt;
2033  }
2034  }
2035 
2036  vpPoint p1 = getGravityCenter(corners_c1);
2037  vpPoint p2 = getGravityCenter(corners_c2);
2038 
2039  vpColVector dist(3);
2040  dist[0] = p1.get_oX() - corners_c1[0].get_oX();
2041  dist[1] = p1.get_oY() - corners_c1[0].get_oY();
2042  dist[2] = p1.get_oZ() - corners_c1[0].get_oZ();
2043  double radius_c1 = sqrt(dist.sumSquare());
2044  dist[0] = p2.get_oX() - corners_c2[0].get_oX();
2045  dist[1] = p2.get_oY() - corners_c2[0].get_oY();
2046  dist[2] = p2.get_oZ() - corners_c2[0].get_oZ();
2047  double radius_c2 = sqrt(dist.sumSquare());
2048 
2049  if (std::fabs(radius_c1 - radius_c2) >
2050  (std::numeric_limits<double>::epsilon() * vpMath::maximum(radius_c1, radius_c2))) {
2051  std::cout << "Radius from the two circles of the cylinders are different." << std::endl;
2052  throw vpException(vpException::badValue, "Radius from the two circles of the cylinders are different.");
2053  }
2054 
2055  // addPolygon(p1, p2, idFace, polygonName);
2056  // initCylinder(p1, p2, radius_c1, idFace++);
2057 
2058  int idRevolutionAxis = idFace;
2059  addPolygon(p1, p2, idFace++, polygonName);
2060 
2061  std::vector<std::vector<vpPoint> > listFaces;
2062  createCylinderBBox(p1, p2, radius_c1, listFaces);
2063  addPolygon(listFaces, idFace, polygonName);
2064  idFace += 4;
2065 
2066  initCylinder(p1, p2, radius_c1, idRevolutionAxis, polygonName);
2067 }
2068 
2077 void vpMbTracker::extractLines(SoVRMLIndexedLineSet *line_set, int &idFace, const std::string &polygonName)
2078 {
2079  std::vector<vpPoint> corners;
2080  corners.resize(0);
2081 
2082  int indexListSize = line_set->coordIndex.getNum();
2083 
2084  SbVec3f point(0, 0, 0);
2085  vpPoint pt;
2086  SoVRMLCoordinate *coord;
2087 
2088  for (int i = 0; i < indexListSize; i++) {
2089  if (line_set->coordIndex[i] == -1) {
2090  if (corners.size() > 1) {
2091  addPolygon(corners, idFace++, polygonName);
2092  initFaceFromCorners(*(faces.getPolygon().back())); // Init from the last polygon that was added
2093  corners.resize(0);
2094  }
2095  } else {
2096  coord = (SoVRMLCoordinate *)(line_set->coord.getValue());
2097  int index = line_set->coordIndex[i];
2098  point[0] = coord->point[index].getValue()[0];
2099  point[1] = coord->point[index].getValue()[1];
2100  point[2] = coord->point[index].getValue()[2];
2101 
2102  pt.setWorldCoordinates(point[0], point[1], point[2]);
2103  corners.push_back(pt);
2104  }
2105  }
2106 }
2107 
2108 #endif // VISP_HAVE_COIN3D
2109 
2119 vpPoint vpMbTracker::getGravityCenter(const std::vector<vpPoint> &pts) const
2120 {
2121  if (pts.empty()) {
2122  std::cout << "Cannot extract center of gravity of empty set." << std::endl;
2123  throw vpException(vpException::dimensionError, "Cannot extract center of gravity of empty set.");
2124  }
2125  double oX = 0;
2126  double oY = 0;
2127  double oZ = 0;
2128  vpPoint G;
2129 
2130  for (unsigned int i = 0; i < pts.size(); ++i) {
2131  oX += pts[i].get_oX();
2132  oY += pts[i].get_oY();
2133  oZ += pts[i].get_oZ();
2134  }
2135 
2136  G.setWorldCoordinates(oX / pts.size(), oY / pts.size(), oZ / pts.size());
2137  return G;
2138 }
2139 
2152 std::pair<std::vector<vpPolygon>, std::vector<std::vector<vpPoint> > >
2153 vpMbTracker::getPolygonFaces(const bool orderPolygons, const bool useVisibility, const bool clipPolygon)
2154 {
2155  // Temporary variable to permit to order polygons by distance
2156  std::vector<vpPolygon> polygonsTmp;
2157  std::vector<std::vector<vpPoint> > roisPtTmp;
2158 
2159  // Pair containing the list of vpPolygon and the list of face corners
2160  std::pair<std::vector<vpPolygon>, std::vector<std::vector<vpPoint> > > pairOfPolygonFaces;
2161 
2162  for (unsigned int i = 0; i < faces.getPolygon().size(); i++) {
2163  // A face has at least 3 points
2164  if (faces.getPolygon()[i]->nbpt > 2) {
2165  if ((useVisibility && faces.getPolygon()[i]->isvisible) || !useVisibility) {
2166  std::vector<vpImagePoint> roiPts;
2167 
2168  if (clipPolygon) {
2169  faces.getPolygon()[i]->getRoiClipped(cam, roiPts, cMo);
2170  } else {
2171  roiPts = faces.getPolygon()[i]->getRoi(cam, cMo);
2172  }
2173 
2174  if (roiPts.size() <= 2) {
2175  continue;
2176  }
2177 
2178  polygonsTmp.push_back(vpPolygon(roiPts));
2179 
2180  std::vector<vpPoint> polyPts;
2181  if (clipPolygon) {
2182  faces.getPolygon()[i]->getPolygonClipped(polyPts);
2183  } else {
2184  for (unsigned int j = 0; j < faces.getPolygon()[i]->nbpt; j++) {
2185  polyPts.push_back(faces.getPolygon()[i]->p[j]);
2186  }
2187  }
2188  roisPtTmp.push_back(polyPts);
2189  }
2190  }
2191  }
2192 
2193  if (orderPolygons) {
2194  // Order polygons by distance (near to far)
2195  std::vector<PolygonFaceInfo> listOfPolygonFaces;
2196  for (unsigned int i = 0; i < polygonsTmp.size(); i++) {
2197  double x_centroid = 0.0, y_centroid = 0.0, z_centroid = 0.0;
2198  for (unsigned int j = 0; j < roisPtTmp[i].size(); j++) {
2199  x_centroid += roisPtTmp[i][j].get_X();
2200  y_centroid += roisPtTmp[i][j].get_Y();
2201  z_centroid += roisPtTmp[i][j].get_Z();
2202  }
2203 
2204  x_centroid /= roisPtTmp[i].size();
2205  y_centroid /= roisPtTmp[i].size();
2206  z_centroid /= roisPtTmp[i].size();
2207 
2208  double squared_dist = x_centroid * x_centroid + y_centroid * y_centroid + z_centroid * z_centroid;
2209  listOfPolygonFaces.push_back(PolygonFaceInfo(squared_dist, polygonsTmp[i], roisPtTmp[i]));
2210  }
2211 
2212  // Sort the list of polygon faces
2213  std::sort(listOfPolygonFaces.begin(), listOfPolygonFaces.end());
2214 
2215  polygonsTmp.resize(listOfPolygonFaces.size());
2216  roisPtTmp.resize(listOfPolygonFaces.size());
2217 
2218  size_t cpt = 0;
2219  for (std::vector<PolygonFaceInfo>::const_iterator it = listOfPolygonFaces.begin(); it != listOfPolygonFaces.end();
2220  ++it, cpt++) {
2221  polygonsTmp[cpt] = it->polygon;
2222  roisPtTmp[cpt] = it->faceCorners;
2223  }
2224 
2225  pairOfPolygonFaces.first = polygonsTmp;
2226  pairOfPolygonFaces.second = roisPtTmp;
2227  } else {
2228  pairOfPolygonFaces.first = polygonsTmp;
2229  pairOfPolygonFaces.second = roisPtTmp;
2230  }
2231 
2232  return pairOfPolygonFaces;
2233 }
2234 
2244 {
2245  useOgre = v;
2246  if (useOgre) {
2247 #ifndef VISP_HAVE_OGRE
2248  useOgre = false;
2249  std::cout << "WARNING: ViSP doesn't have Ogre3D, basic visibility test "
2250  "will be used. setOgreVisibilityTest() set to false."
2251  << std::endl;
2252 #endif
2253  }
2254 }
2255 
2261 void vpMbTracker::setFarClippingDistance(const double &dist)
2262 {
2263  if ((clippingFlag & vpPolygon3D::NEAR_CLIPPING) == vpPolygon3D::NEAR_CLIPPING && dist <= distNearClip)
2264  vpTRACE("Far clipping value cannot be inferior than near clipping value. "
2265  "Far clipping won't be considered.");
2266  else if (dist < 0)
2267  vpTRACE("Far clipping value cannot be inferior than 0. Far clipping "
2268  "won't be considered.");
2269  else {
2271  distFarClip = dist;
2272  for (unsigned int i = 0; i < faces.size(); i++) {
2273  faces[i]->setFarClippingDistance(distFarClip);
2274  }
2275 #ifdef VISP_HAVE_OGRE
2277 #endif
2278  }
2279 }
2280 
2291 void vpMbTracker::setLod(const bool useLod, const std::string &name)
2292 {
2293  for (unsigned int i = 0; i < faces.size(); i++) {
2294  if (name.empty() || faces[i]->name == name) {
2295  faces[i]->setLod(useLod);
2296  }
2297  }
2298 }
2299 
2309 void vpMbTracker::setMinLineLengthThresh(const double minLineLengthThresh, const std::string &name)
2310 {
2311  for (unsigned int i = 0; i < faces.size(); i++) {
2312  if (name.empty() || faces[i]->name == name) {
2313  faces[i]->setMinLineLengthThresh(minLineLengthThresh);
2314  }
2315  }
2316 }
2317 
2326 void vpMbTracker::setMinPolygonAreaThresh(const double minPolygonAreaThresh, const std::string &name)
2327 {
2328  for (unsigned int i = 0; i < faces.size(); i++) {
2329  if (name.empty() || faces[i]->name == name) {
2330  faces[i]->setMinPolygonAreaThresh(minPolygonAreaThresh);
2331  }
2332  }
2333 }
2334 
2341 {
2342  if ((clippingFlag & vpPolygon3D::FAR_CLIPPING) == vpPolygon3D::FAR_CLIPPING && dist >= distFarClip)
2343  vpTRACE("Near clipping value cannot be superior than far clipping value. "
2344  "Near clipping won't be considered.");
2345  else if (dist < 0)
2346  vpTRACE("Near clipping value cannot be inferior than 0. Near clipping "
2347  "won't be considered.");
2348  else {
2350  distNearClip = dist;
2351  for (unsigned int i = 0; i < faces.size(); i++) {
2352  faces[i]->setNearClippingDistance(distNearClip);
2353  }
2354 #ifdef VISP_HAVE_OGRE
2356 #endif
2357  }
2358 }
2359 
2367 void vpMbTracker::setClipping(const unsigned int &flags)
2368 {
2369  clippingFlag = flags;
2370  for (unsigned int i = 0; i < faces.size(); i++)
2372 }
2373 
2374 void vpMbTracker::computeCovarianceMatrixVVS(const bool isoJoIdentity_, const vpColVector &w_true,
2375  const vpHomogeneousMatrix &cMoPrev, const vpMatrix &L_true,
2376  const vpMatrix &LVJ_true, const vpColVector &error)
2377 {
2378  if (computeCovariance) {
2379  vpMatrix D;
2380  D.diag(w_true);
2381 
2382  // Note that here the covariance is computed on cMoPrev for time
2383  // computation efficiency
2384  if (isoJoIdentity_) {
2385  covarianceMatrix = vpMatrix::computeCovarianceMatrixVVS(cMoPrev, error, L_true, D);
2386  } else {
2387  covarianceMatrix = vpMatrix::computeCovarianceMatrixVVS(cMoPrev, error, LVJ_true, D);
2388  }
2389  }
2390 }
2391 
2405 void vpMbTracker::computeJTR(const vpMatrix &interaction, const vpColVector &error, vpColVector &JTR) const
2406 {
2407  if (interaction.getRows() != error.getRows() || interaction.getCols() != 6) {
2408  throw vpMatrixException(vpMatrixException::incorrectMatrixSizeError, "Incorrect matrices size in computeJTR.");
2409  }
2410 
2411  JTR.resize(6, false);
2412 
2413  bool checkSSE2 = vpCPUFeatures::checkSSE2();
2414 #if !VISP_HAVE_SSE2
2415  checkSSE2 = false;
2416 #endif
2417 
2418  if (checkSSE2) {
2419 #if VISP_HAVE_SSE2
2420  __m128d v_JTR_0_1 = _mm_setzero_pd();
2421  __m128d v_JTR_2_3 = _mm_setzero_pd();
2422  __m128d v_JTR_4_5 = _mm_setzero_pd();
2423 
2424  for (unsigned int i = 0; i < interaction.getRows(); i++) {
2425  const __m128d v_error = _mm_set1_pd(error[i]);
2426 
2427  __m128d v_interaction = _mm_loadu_pd(&interaction[i][0]);
2428  v_JTR_0_1 = _mm_add_pd(v_JTR_0_1, _mm_mul_pd(v_interaction, v_error));
2429 
2430  v_interaction = _mm_loadu_pd(&interaction[i][2]);
2431  v_JTR_2_3 = _mm_add_pd(v_JTR_2_3, _mm_mul_pd(v_interaction, v_error));
2432 
2433  v_interaction = _mm_loadu_pd(&interaction[i][4]);
2434  v_JTR_4_5 = _mm_add_pd(v_JTR_4_5, _mm_mul_pd(v_interaction, v_error));
2435  }
2436 
2437  _mm_storeu_pd(JTR.data, v_JTR_0_1);
2438  _mm_storeu_pd(JTR.data + 2, v_JTR_2_3);
2439  _mm_storeu_pd(JTR.data + 4, v_JTR_4_5);
2440 #endif
2441  } else {
2442  const unsigned int N = interaction.getRows();
2443 
2444  for (unsigned int i = 0; i < 6; i += 1) {
2445  double ssum = 0;
2446  for (unsigned int j = 0; j < N; j += 1) {
2447  ssum += interaction[j][i] * error[j];
2448  }
2449  JTR[i] = ssum;
2450  }
2451  }
2452 }
2453 
2455  const vpColVector &m_error_prev, const vpHomogeneousMatrix &cMoPrev,
2456  double &mu, bool &reStartFromLastIncrement, vpColVector *const w,
2457  const vpColVector *const m_w_prev)
2458 {
2460  if (error.sumSquare() / (double)error.getRows() > m_error_prev.sumSquare() / (double)m_error_prev.getRows()) {
2461  mu *= 10.0;
2462 
2463  if (mu > 1.0)
2464  throw vpTrackingException(vpTrackingException::fatalError, "Optimization diverged");
2465 
2466  cMo = cMoPrev;
2467  error = m_error_prev;
2468  if (w != NULL && m_w_prev != NULL) {
2469  *w = *m_w_prev;
2470  }
2471  reStartFromLastIncrement = true;
2472  }
2473  }
2474 }
2475 
2476 void vpMbTracker::computeVVSPoseEstimation(const bool isoJoIdentity_, const unsigned int iter, vpMatrix &L,
2477  vpMatrix &LTL, vpColVector &R, const vpColVector &error,
2478  vpColVector &error_prev, vpColVector &LTR, double &mu, vpColVector &v,
2479  const vpColVector *const w, vpColVector *const m_w_prev)
2480 {
2481  if (isoJoIdentity_) {
2482  LTL = L.AtA();
2483  computeJTR(L, R, LTR);
2484 
2485  switch (m_optimizationMethod) {
2487  vpMatrix LMA(LTL.getRows(), LTL.getCols());
2488  LMA.eye();
2489  vpMatrix LTLmuI = LTL + (LMA * mu);
2490  v = -m_lambda * LTLmuI.pseudoInverse(LTLmuI.getRows() * std::numeric_limits<double>::epsilon()) * LTR;
2491 
2492  if (iter != 0)
2493  mu /= 10.0;
2494 
2495  error_prev = error;
2496  if (w != NULL && m_w_prev != NULL)
2497  *m_w_prev = *w;
2498  break;
2499  }
2500 
2502  default:
2503  v = -m_lambda * LTL.pseudoInverse(LTL.getRows() * std::numeric_limits<double>::epsilon()) * LTR;
2504  break;
2505  }
2506  } else {
2508  cVo.buildFrom(cMo);
2509  vpMatrix LVJ = (L * (cVo * oJo));
2510  vpMatrix LVJTLVJ = (LVJ).AtA();
2511  vpColVector LVJTR;
2512  computeJTR(LVJ, R, LVJTR);
2513 
2514  switch (m_optimizationMethod) {
2516  vpMatrix LMA(LVJTLVJ.getRows(), LVJTLVJ.getCols());
2517  LMA.eye();
2518  vpMatrix LTLmuI = LVJTLVJ + (LMA * mu);
2519  v = -m_lambda * LTLmuI.pseudoInverse(LTLmuI.getRows() * std::numeric_limits<double>::epsilon()) * LVJTR;
2520  v = cVo * v;
2521 
2522  if (iter != 0)
2523  mu /= 10.0;
2524 
2525  error_prev = error;
2526  if (w != NULL && m_w_prev != NULL)
2527  *m_w_prev = *w;
2528  break;
2529  }
2531  default:
2532  v = -m_lambda * LVJTLVJ.pseudoInverse(LVJTLVJ.getRows() * std::numeric_limits<double>::epsilon()) * LVJTR;
2533  v = cVo * v;
2534  break;
2535  }
2536  }
2537 }
2538 
2540 {
2541  if (error.getRows() > 0)
2542  robust.MEstimator(vpRobust::TUKEY, error, w);
2543 }
2544 
2557 {
2558  vpColVector v(6);
2559  for (unsigned int i = 0; i < 6; i++)
2560  v[i] = oJo[i][i];
2561  return v;
2562 }
2563 
2580 {
2581  if (v.getRows() == 6) {
2582  isoJoIdentity = true;
2583  for (unsigned int i = 0; i < 6; i++) {
2584  // if(v[i] != 0){
2585  if (std::fabs(v[i]) > std::numeric_limits<double>::epsilon()) {
2586  oJo[i][i] = 1.0;
2587  } else {
2588  oJo[i][i] = 0.0;
2589  isoJoIdentity = false;
2590  }
2591  }
2592  }
2593 }
2594 
2595 void vpMbTracker::createCylinderBBox(const vpPoint &p1, const vpPoint &p2, const double &radius,
2596  std::vector<std::vector<vpPoint> > &listFaces)
2597 {
2598  listFaces.clear();
2599 
2600  // std::vector<vpPoint> revolutionAxis;
2601  // revolutionAxis.push_back(p1);
2602  // revolutionAxis.push_back(p2);
2603  // listFaces.push_back(revolutionAxis);
2604 
2605  vpColVector axis(3);
2606  axis[0] = p1.get_oX() - p2.get_oX();
2607  axis[1] = p1.get_oY() - p2.get_oY();
2608  axis[2] = p1.get_oZ() - p2.get_oZ();
2609 
2610  vpColVector randomVec(3);
2611  randomVec = 0;
2612 
2613  vpColVector axisOrtho(3);
2614 
2615  randomVec[0] = 1.0;
2616  axisOrtho = vpColVector::crossProd(axis, randomVec);
2617 
2618  if (axisOrtho.euclideanNorm() < std::numeric_limits<double>::epsilon()) {
2619  randomVec = 0;
2620  randomVec[1] = 1.0;
2621  axisOrtho = vpColVector::crossProd(axis, randomVec);
2622  if (axisOrtho.euclideanNorm() < std::numeric_limits<double>::epsilon()) {
2623  randomVec = 0;
2624  randomVec[2] = 1.0;
2625  axisOrtho = vpColVector::crossProd(axis, randomVec);
2626  if (axisOrtho.euclideanNorm() < std::numeric_limits<double>::epsilon())
2627  throw vpMatrixException(vpMatrixException::badValue, "Problem in the cylinder definition");
2628  }
2629  }
2630 
2631  axisOrtho.normalize();
2632 
2633  vpColVector axisOrthoBis(3);
2634  axisOrthoBis = vpColVector::crossProd(axis, axisOrtho);
2635  axisOrthoBis.normalize();
2636 
2637  // First circle
2638  vpColVector p1Vec(3);
2639  p1Vec[0] = p1.get_oX();
2640  p1Vec[1] = p1.get_oY();
2641  p1Vec[2] = p1.get_oZ();
2642  vpColVector fc1 = p1Vec + axisOrtho * radius;
2643  vpColVector fc2 = p1Vec + axisOrthoBis * radius;
2644  vpColVector fc3 = p1Vec - axisOrtho * radius;
2645  vpColVector fc4 = p1Vec - axisOrthoBis * radius;
2646 
2647  vpColVector p2Vec(3);
2648  p2Vec[0] = p2.get_oX();
2649  p2Vec[1] = p2.get_oY();
2650  p2Vec[2] = p2.get_oZ();
2651  vpColVector sc1 = p2Vec + axisOrtho * radius;
2652  vpColVector sc2 = p2Vec + axisOrthoBis * radius;
2653  vpColVector sc3 = p2Vec - axisOrtho * radius;
2654  vpColVector sc4 = p2Vec - axisOrthoBis * radius;
2655 
2656  std::vector<vpPoint> pointsFace;
2657  pointsFace.push_back(vpPoint(fc1[0], fc1[1], fc1[2]));
2658  pointsFace.push_back(vpPoint(sc1[0], sc1[1], sc1[2]));
2659  pointsFace.push_back(vpPoint(sc2[0], sc2[1], sc2[2]));
2660  pointsFace.push_back(vpPoint(fc2[0], fc2[1], fc2[2]));
2661  listFaces.push_back(pointsFace);
2662 
2663  pointsFace.clear();
2664  pointsFace.push_back(vpPoint(fc2[0], fc2[1], fc2[2]));
2665  pointsFace.push_back(vpPoint(sc2[0], sc2[1], sc2[2]));
2666  pointsFace.push_back(vpPoint(sc3[0], sc3[1], sc3[2]));
2667  pointsFace.push_back(vpPoint(fc3[0], fc3[1], fc3[2]));
2668  listFaces.push_back(pointsFace);
2669 
2670  pointsFace.clear();
2671  pointsFace.push_back(vpPoint(fc3[0], fc3[1], fc3[2]));
2672  pointsFace.push_back(vpPoint(sc3[0], sc3[1], sc3[2]));
2673  pointsFace.push_back(vpPoint(sc4[0], sc4[1], sc4[2]));
2674  pointsFace.push_back(vpPoint(fc4[0], fc4[1], fc4[2]));
2675  listFaces.push_back(pointsFace);
2676 
2677  pointsFace.clear();
2678  pointsFace.push_back(vpPoint(fc4[0], fc4[1], fc4[2]));
2679  pointsFace.push_back(vpPoint(sc4[0], sc4[1], sc4[2]));
2680  pointsFace.push_back(vpPoint(sc1[0], sc1[1], sc1[2]));
2681  pointsFace.push_back(vpPoint(fc1[0], fc1[1], fc1[2]));
2682  listFaces.push_back(pointsFace);
2683 }
double euclideanNorm() const
vpDisplay * display
Definition: vpImage.h:134
Implementation of a matrix and operations on matrices.
Definition: vpMatrix.h:104
vpMatrix pseudoInverse(double svThreshold=1e-6) const
Definition: vpMatrix.cpp:1931
vpMatrix covarianceMatrix
Covariance matrix.
Definition: vpMbTracker.h:132
virtual ~vpMbTracker()
bool parseBoolean(std::string &input)
Definition: vpMbTracker.h:763
double get_oY() const
Get the point Y coordinate in the object frame.
Definition: vpPoint.cpp:422
Implements a 3D polygon with render functionnalities like clipping.
Definition: vpPolygon3D.h:59
Class that defines generic functionnalities for display.
Definition: vpDisplay.h:171
virtual void setNbPoint(const unsigned int nb)
static vpMatrix computeCovarianceMatrixVVS(const vpHomogeneousMatrix &cMo, const vpColVector &deltaS, const vpMatrix &Ls, const vpMatrix &W)
unsigned int nbLines
Number of lines in CAO model.
Definition: vpMbTracker.h:164
static bool getClick(const vpImage< unsigned char > &I, bool blocking=true)
virtual void extractCylinders(SoVRMLIndexedFaceSet *face_set, vpHomogeneousMatrix &transform, int &idFace, const std::string &polygonName="")
void MEstimator(const vpRobustEstimatorType method, const vpColVector &residues, vpColVector &weights)
Compute the weights according a residue vector and a PsiFunction.
Definition: vpRobust.cpp:176
unsigned int size() const
std::map< std::string, std::string > parseParameters(std::string &endLine)
static bool isAbsolutePathname(const std::string &pathname)
Definition: vpIoTools.cpp:1476
unsigned int nbCircles
Number of circles in CAO model.
Definition: vpMbTracker.h:172
vpMbHiddenFaces< vpMbtPolygon > faces
Set of faces describing the object.
Definition: vpMbTracker.h:145
void setNearClippingDistance(const double &dist)
Definition: vpAROgre.h:210
Implementation of an homogeneous matrix and operations on such kind of matrices.
virtual void extractGroup(SoVRMLGroup *sceneGraphVRML2, vpHomogeneousMatrix &transform, int &idFace)
std::map< std::string, std::string > mapOfParameterNames
Definition: vpMbTracker.h:184
unsigned int nbCylinders
Number of cylinders in CAO model.
Definition: vpMbTracker.h:170
vpMatrix AtA() const
Definition: vpMatrix.cpp:524
#define vpERROR_TRACE
Definition: vpDebug.h:393
unsigned int nbPoints
Number of points in CAO model.
Definition: vpMbTracker.h:162
Display for windows using GDI (available on any windows 32 platform).
Definition: vpDisplayGDI.h:129
vpHomogeneousMatrix cMo
The current pose.
Definition: vpMbTracker.h:115
virtual void initCircle(const vpPoint &p1, const vpPoint &p2, const vpPoint &p3, const double radius, const int idFace=0, const std::string &name="")=0
static void displayText(const vpImage< unsigned char > &I, const vpImagePoint &ip, const std::string &s, const vpColor &color)
Use the X11 console to display images on unix-like OS. Thus to enable this class X11 should be instal...
Definition: vpDisplayX.h:151
bool modelInitialised
Definition: vpMbTracker.h:125
void setMinPolygonAreaThresh(const double min_polygon_area)
Definition: vpMbtPolygon.h:152
error that can be emited by ViSP classes.
Definition: vpException.h:71
static std::string path(const char *pathname)
Definition: vpIoTools.cpp:839
void set_x(const double x)
Set the point x coordinate in the image plane.
Definition: vpPoint.cpp:470
virtual void loadCAOModel(const std::string &modelFile, std::vector< std::string > &vectorOfModelFilename, int &startIdFace, const bool verbose=false, const bool parent=true)
unsigned int getRows() const
Definition: vpArray2D.h:156
static void displayPoint(const vpImage< unsigned char > &I, const vpImagePoint &ip, const vpColor &color, unsigned int thickness=1)
static void convertPoint(const vpCameraParameters &cam, const double &u, const double &v, double &x, double &y)
Point coordinates conversion from pixel coordinates to normalized coordinates in meter...
void setName(const std::string &face_name)
Definition: vpMbtPolygon.h:159
Type * data
Address of the first element of the data array.
Definition: vpArray2D.h:84
Provides simple mathematics computation tools that are not available in the C mathematics library (ma...
Definition: vpMath.h:86
bool useOgre
Use Ogre3d for visibility tests.
Definition: vpMbTracker.h:157
std::string modelFileName
Definition: vpMbTracker.h:122
virtual void setEstimatedDoF(const vpColVector &v)
virtual void initFromPose(const vpImage< unsigned char > &I, const std::string &initFile)
static std::string getParent(const std::string &pathname)
Definition: vpIoTools.cpp:1371
bool computeCovariance
Flag used to specify if the covariance matrix has to be computed or not.
Definition: vpMbTracker.h:130
static const vpColor green
Definition: vpColor.h:183
static void flush(const vpImage< unsigned char > &I)
double get_oX() const
Get the point X coordinate in the object frame.
Definition: vpPoint.cpp:420
void setFarClippingDistance(const double &dist)
Definition: vpAROgre.h:199
virtual void extractLines(SoVRMLIndexedLineSet *line_set, int &idFace, const std::string &polygonName="")
static const vpColor red
Definition: vpColor.h:180
Class that defines what is a point.
Definition: vpPoint.h:58
vpCameraParameters cam
The camera parameters.
Definition: vpMbTracker.h:113
static Type maximum(const Type &a, const Type &b)
Definition: vpMath.h:137
Implementation of a rotation matrix and operations on such kind of matrices.
virtual void init(const vpImage< unsigned char > &I)=0
unsigned int getCols() const
Definition: vpArray2D.h:146
double distFarClip
Distance for near clipping.
Definition: vpMbTracker.h:153
static bool checkFilename(const char *filename)
Definition: vpIoTools.cpp:573
vpAROgre * getOgreContext()
Defines a generic 2D polygon.
Definition: vpPolygon.h:103
virtual void setMinPolygonAreaThresh(const double minPolygonAreaThresh, const std::string &name="")
virtual void display(const vpImage< unsigned char > &I, const vpHomogeneousMatrix &cMo, const vpCameraParameters &cam, const vpColor &col, const unsigned int thickness=1, const bool displayFullModel=false)=0
vpColVector & normalize()
vpMatrix oJo
The Degrees of Freedom to estimate.
Definition: vpMbTracker.h:117
static std::string createFilePath(const std::string &parent, const std::string &child)
Definition: vpIoTools.cpp:1435
Error that can be emited by the vpTracker class and its derivates.
Implementation of a polygon of the model used by the model-based tracker.
Definition: vpMbtPolygon.h:66
void diag(const double &val=1.0)
Definition: vpMatrix.cpp:692
vpVelocityTwistMatrix buildFrom(const vpTranslationVector &t, const vpRotationMatrix &R)
#define vpTRACE
Definition: vpDebug.h:416
static double sqr(double x)
Definition: vpMath.h:108
double minLineLengthThresholdGeneral
Minimum line length threshold for LOD mode (general setting)
Definition: vpMbTracker.h:179
VISP_EXPORT bool checkSSE2()
static void display(const vpImage< unsigned char > &I)
void clear()
Definition: vpColVector.h:113
void createCylinderBBox(const vpPoint &p1, const vpPoint &p2, const double &radius, std::vector< std::vector< vpPoint > > &listFaces)
The vpDisplayOpenCV allows to display image using the OpenCV library. Thus to enable this class OpenC...
double getB() const
Definition: vpPlane.h:104
void addPoint(const unsigned int n, const vpPoint &P)
Class used for pose computation from N points (pose from point only). Some of the algorithms implemen...
Definition: vpPose.h:79
virtual void initFaceFromCorners(vpMbtPolygon &polygon)=0
void set_y(const double y)
Set the point y coordinate in the image plane.
Definition: vpPoint.cpp:472
Main methods for a model-based tracker.
Definition: vpMbTracker.h:106
std::vector< PolygonType * > & getPolygon()
std::string & trim(std::string &s) const
Definition: vpMbTracker.h:788
bool computePose(vpPoseMethodType method, vpHomogeneousMatrix &cMo, bool(*func)(vpHomogeneousMatrix *)=NULL)
Definition: vpPose.cpp:362
double get_oZ() const
Get the point Z coordinate in the object frame.
Definition: vpPoint.cpp:424
virtual void loadVRMLModel(const std::string &modelFile)
Implementation of a rotation vector as quaternion angle minimal representation.
double m_lambda
Gain of the virtual visual servoing stage.
Definition: vpMbTracker.h:189
void setIsPolygonOriented(const bool &oriented)
Definition: vpMbtPolygon.h:166
virtual void computeVVSWeights(vpRobust &robust, const vpColVector &error, vpColVector &w)
unsigned int nbPolygonLines
Number of polygon lines in CAO model.
Definition: vpMbTracker.h:166
vpPoint getGravityCenter(const std::vector< vpPoint > &_pts) const
vpMbtOptimizationMethod m_optimizationMethod
Optimization method used.
Definition: vpMbTracker.h:142
void addPolygon(PolygonType *p)
virtual void initClick(const vpImage< unsigned char > &I, const std::string &initFile, const bool displayHelp=false)
void buildFrom(const vpTranslationVector &t, const vpRotationMatrix &R)
static std::string getName(const std::string &pathname)
Definition: vpIoTools.cpp:1336
static double rad(double deg)
Definition: vpMath.h:102
virtual void setMinLineLengthThresh(const double minLineLengthThresh, const std::string &name="")
std::string poseSavingFilename
Definition: vpMbTracker.h:128
int getWindowXPosition() const
Definition: vpDisplay.h:245
double getA() const
Definition: vpPlane.h:102
int getWindowYPosition() const
Definition: vpDisplay.h:250
static void displayCross(const vpImage< unsigned char > &I, const vpImagePoint &ip, unsigned int size, const vpColor &color, unsigned int thickness=1)
unsigned int nbPolygonPoints
Number of polygon points in CAO model.
Definition: vpMbTracker.h:168
double minPolygonAreaThresholdGeneral
Minimum polygon area threshold for LOD mode (general setting)
Definition: vpMbTracker.h:181
virtual void setOgreVisibilityTest(const bool &v)
void setWorldCoordinates(const double oX, const double oY, const double oZ)
Definition: vpPoint.cpp:113
virtual void loadModel(const char *modelFile, const bool verbose=false)
static void read(vpImage< unsigned char > &I, const std::string &filename)
Definition: vpImageIo.cpp:207
bool applyLodSettingInConfig
Definition: vpMbTracker.h:177
Implementation of column vector and the associated operations.
Definition: vpColVector.h:72
static void displayFrame(const vpImage< unsigned char > &I, const vpHomogeneousMatrix &cMo, const vpCameraParameters &cam, double size, const vpColor &color=vpColor::none, unsigned int thickness=1, const vpImagePoint &offset=vpImagePoint(0, 0))
void setLod(const bool use_lod)
virtual void initFaceFromLines(vpMbtPolygon &polygon)=0
virtual void computeVVSPoseEstimation(const bool isoJoIdentity_, const unsigned int iter, vpMatrix &L, vpMatrix &LTL, vpColVector &R, const vpColVector &error, vpColVector &error_prev, vpColVector &LTR, double &mu, vpColVector &v, const vpColVector *const w=NULL, vpColVector *const m_w_prev=NULL)
Implementation of a pose vector and operations on poses.
Definition: vpPoseVector.h:92
double sumSquare() const
virtual void computeCovarianceMatrixVVS(const bool isoJoIdentity_, const vpColVector &w_true, const vpHomogeneousMatrix &cMoPrev, const vpMatrix &L_true, const vpMatrix &LVJ_true, const vpColVector &error)
Contains an M-Estimator and various influence function.
Definition: vpRobust.h:58
error that can be emited by the vpMatrix class and its derivates
virtual vpColVector getEstimatedDoF() const
double getC() const
Definition: vpPlane.h:106
static std::string getAbsolutePathname(const std::string &pathname)
Definition: vpIoTools.cpp:1393
vpPoseVector buildFrom(const double tx, const double ty, const double tz, const double tux, const double tuy, const double tuz)
virtual void setClipping(const unsigned int &flags)
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition: vpImagePoint.h:88
void addPolygon(const std::vector< vpPoint > &corners, const int idFace=-1, const std::string &polygonName="", const bool useLod=false, const double minPolygonAreaThreshold=2500.0, const double minLineLengthThreshold=50.0)
static vpColVector crossProd(const vpColVector &a, const vpColVector &b)
This class defines the container for a plane geometrical structure.
Definition: vpPlane.h:58
unsigned int clippingFlag
Flags specifying which clipping to used.
Definition: vpMbTracker.h:155
virtual void initFromPoints(const vpImage< unsigned char > &I, const std::string &initFile)
double computeResidual(const vpHomogeneousMatrix &cMo) const
Compute and return the residual expressed in meter for the pose matrix &#39;cMo&#39;.
Definition: vpPose.cpp:324
virtual void setFarClippingDistance(const double &dist)
void addPoint(const vpPoint &P)
Definition: vpPose.cpp:137
void savePose(const std::string &filename) const
unsigned int getWidth() const
Definition: vpImage.h:229
void computeJTR(const vpMatrix &J, const vpColVector &R, vpColVector &JTR) const
double distNearClip
Distance for near clipping.
Definition: vpMbTracker.h:151
bool useLodGeneral
True if LOD mode is enabled.
Definition: vpMbTracker.h:174
virtual void extractFaces(SoVRMLIndexedFaceSet *face_set, vpHomogeneousMatrix &transform, int &idFace, const std::string &polygonName="")
Class that consider the case of a translation vector.
void eye()
Definition: vpMatrix.cpp:360
virtual void computeVVSCheckLevenbergMarquardt(const unsigned int iter, vpColVector &error, const vpColVector &m_error_prev, const vpHomogeneousMatrix &cMoPrev, double &mu, bool &reStartFromLastIncrement, vpColVector *const w=NULL, const vpColVector *const m_w_prev=NULL)
bool isoJoIdentity
Boolean to know if oJo is identity (for fast computation)
Definition: vpMbTracker.h:119
virtual std::pair< std::vector< vpPolygon >, std::vector< std::vector< vpPoint > > > getPolygonFaces(const bool orderPolygons=true, const bool useVisibility=true, const bool clipPolygon=false)
void removeComment(std::ifstream &fileId)
virtual void initCylinder(const vpPoint &p1, const vpPoint &p2, const double radius, const int idFace=0, const std::string &name="")=0
void setMinLineLengthThresh(const double min_line_length)
Definition: vpMbtPolygon.h:141
void resize(const unsigned int i, const bool flagNullify=true)
Definition: vpColVector.h:241
virtual void setIndex(const int i)
Definition: vpMbtPolygon.h:124
void clearPoint()
Definition: vpPose.cpp:122
virtual void setLod(const bool useLod, const std::string &name="")
virtual void setNearClippingDistance(const double &dist)