MRPT  1.9.9
CLandmarksMap.cpp
Go to the documentation of this file.
1 /* +------------------------------------------------------------------------+
2  | Mobile Robot Programming Toolkit (MRPT) |
3  | http://www.mrpt.org/ |
4  | |
5  | Copyright (c) 2005-2018, Individual contributors, see AUTHORS file |
6  | See: http://www.mrpt.org/Authors - All rights reserved. |
7  | Released under BSD License. See details in http://www.mrpt.org/License |
8  +------------------------------------------------------------------------+ */
9 
10 #include "vision-precomp.h" // Precompiled headers
11 
12 #include <mrpt/math/geometry.h>
14 
16 #include <mrpt/maps/CLandmark.h>
25 #include <mrpt/system/os.h>
26 #include <mrpt/random.h>
27 
29 #include <mrpt/opengl/CEllipsoid.h>
31 
32 using namespace mrpt;
33 using namespace mrpt::math;
34 using namespace mrpt::maps;
35 using namespace mrpt::obs;
36 using namespace mrpt::poses;
37 using namespace mrpt::tfest;
38 using namespace mrpt::random;
39 using namespace mrpt::system;
40 using namespace mrpt::vision;
41 using namespace mrpt::img;
42 using namespace mrpt::containers;
43 using namespace std;
45 
46 // =========== Begin of Map definition ============
47 MAP_DEFINITION_REGISTER("CLandmarksMap,landmarksMap", mrpt::maps::CLandmarksMap)
48 
50 void CLandmarksMap::TMapDefinition::loadFromConfigFile_map_specific(
52  const std::string& sectionNamePrefix)
53 {
54  // [<sectionNamePrefix>+"_creationOpts"]
55  const std::string sSectCreation =
56  sectionNamePrefix + string("_creationOpts");
57  this->initialBeacons.clear();
58  const unsigned int nBeacons = source.read_int(sSectCreation, "nBeacons", 0);
59  for (unsigned int q = 1; q <= nBeacons; q++)
60  {
61  TPairIdBeacon newPair;
62  newPair.second =
63  source.read_int(sSectCreation, format("beacon_%03u_ID", q), 0);
64 
65  newPair.first.x =
66  source.read_float(sSectCreation, format("beacon_%03u_x", q), 0);
67  newPair.first.y =
68  source.read_float(sSectCreation, format("beacon_%03u_y", q), 0);
69  newPair.first.z =
70  source.read_float(sSectCreation, format("beacon_%03u_z", q), 0);
71 
72  this->initialBeacons.push_back(newPair);
73  }
74 
75  insertionOpts.loadFromConfigFile(
76  source, sectionNamePrefix + string("_insertOpts"));
77  likelihoodOpts.loadFromConfigFile(
78  source, sectionNamePrefix + string("_likelihoodOpts"));
79 }
80 
81 void CLandmarksMap::TMapDefinition::dumpToTextStream_map_specific(
82  std::ostream& out) const
83 {
84  out << mrpt::format(
85  "number of initial beacons = %u\n",
86  (int)initialBeacons.size());
87 
88  out << mrpt::format(" ID (X,Y,Z)\n");
89  out << mrpt::format(
90  "--------------------------------------------------------\n");
91  for (std::deque<TPairIdBeacon>::const_iterator p = initialBeacons.begin();
92  p != initialBeacons.end(); ++p)
93  out << mrpt::format(
94  " %03u (%8.03f,%8.03f,%8.03f)\n", p->second,
95  p->first.x, p->first.y, p->first.z);
96 
97  this->insertionOpts.dumpToTextStream(out);
98  this->likelihoodOpts.dumpToTextStream(out);
99 }
100 
101 mrpt::maps::CMetricMap* CLandmarksMap::internal_CreateFromMapDefinition(
103 {
104  const CLandmarksMap::TMapDefinition& def =
105  *dynamic_cast<const CLandmarksMap::TMapDefinition*>(&_def);
107 
108  for (std::deque<
110  def.initialBeacons.begin();
111  p != def.initialBeacons.end(); ++p)
112  {
113  CLandmark lm;
114 
115  lm.createOneFeature();
116  lm.features[0]->type = featBeacon;
117 
118  lm.features[0]->ID = p->second;
119  lm.ID = p->second;
120 
121  lm.pose_mean = p->first;
122 
123  lm.pose_cov_11 = lm.pose_cov_22 = lm.pose_cov_33 = lm.pose_cov_12 =
124  lm.pose_cov_13 = lm.pose_cov_23 = square(0.01f);
125 
126  obj->landmarks.push_back(lm);
127  }
128 
129  obj->insertionOptions = def.insertionOpts;
130  obj->likelihoodOptions = def.likelihoodOpts;
131  return obj;
132 }
133 // =========== End of Map definition Block =========
134 
136 
137 /*---------------------------------------------------------------
138  Static variables initialization
139  ---------------------------------------------------------------*/
140 std::map<
141  std::pair<
143  double>
144  CLandmarksMap::_mEDD;
145 mrpt::maps::CLandmark::TLandmarkID CLandmarksMap::_mapMaxID;
146 bool CLandmarksMap::_maxIDUpdated = false;
147 /*---------------------------------------------------------------
148  Constructor
149  ---------------------------------------------------------------*/
150 CLandmarksMap::CLandmarksMap()
151  : landmarks(),
152  insertionOptions(),
153  likelihoodOptions(),
154  insertionResults(),
155  fuseOptions()
156 {
157  landmarks.clear();
158  //_mEDD.clear();
159  //_mapMaxID = 0;
160 }
161 
162 /*---------------------------------------------------------------
163  Destructor
164  ---------------------------------------------------------------*/
166 /*---------------------------------------------------------------
167  clear
168  ---------------------------------------------------------------*/
170 /*---------------------------------------------------------------
171  getLandmarksCount
172  ---------------------------------------------------------------*/
173 size_t CLandmarksMap::size() const { return landmarks.size(); }
176 {
177  uint32_t n = landmarks.size();
178 
179  // First, write the number of landmarks:
180  out << n;
181 
182  // Write all landmarks:
184  it != landmarks.end(); ++it)
185  out << (*it);
186 }
187 
190 {
191  switch (version)
192  {
193  case 0:
194  {
195  uint32_t n, i;
196  CLandmark lm;
197 
198  // Delete previous content of map:
199  // -------------------------------------
200  landmarks.clear();
201 
202  // Load from stream:
203  // -------------------------------------
204  in >> n;
205 
206  landmarks.clear(); // resize(n);
207 
208  // Read all landmarks:
209  for (i = 0; i < n; i++)
210  {
211  in >> lm;
212  landmarks.push_back(lm);
213  }
214  }
215  break;
216  default:
218  };
219 }
220 
221 /*---------------------------------------------------------------
222  computeObservationLikelihood
223  ---------------------------------------------------------------*/
225  const CObservation* obs, const CPose3D& robotPose3D)
226 {
227  MRPT_START
228 
231  {
232  /********************************************************************
233  OBSERVATION TYPE: CObservation2DRangeScan
234  ********************************************************************/
235  const CObservation2DRangeScan* o =
236  static_cast<const CObservation2DRangeScan*>(obs);
237  CLandmarksMap auxMap;
238  CPose2D sensorPose2D(robotPose3D + o->sensorPose);
239 
241  *o, &robotPose3D, likelihoodOptions.rangeScan2D_decimation);
242 
243  // And compute its likelihood:
244  return computeLikelihood_RSLC_2007(&auxMap, sensorPose2D);
245  } // end of likelihood of 2D range scan:
247  {
248  /********************************************************************
249  OBSERVATION TYPE: CObservationStereoImages
250  Lik. between "this" and "auxMap";
251  ********************************************************************/
252  const CObservationStereoImages* o =
253  static_cast<const CObservationStereoImages*>(obs);
254 
255  CLandmarksMap auxMap;
259  auxMap.changeCoordinatesReference(robotPose3D);
260 
261  // ACCESS TO STATIC VARIABLE
262  // std::cout << "_mapMaxID, from " << CLandmarksMap::_mapMaxID << " to
263  // ";
265  {
266  CLandmarksMap::_mapMaxID += auxMap.size();
268  } // end if
269 
270  // std::cout << CLandmarksMap::_mapMaxID <<std::endl;
271  return computeLikelihood_SIFT_LandmarkMap(&auxMap);
272 
273  } // end of likelihood of Stereo Images scan:
275  {
276  /********************************************************************
277 
278  OBSERVATION TYPE: CObservationBeaconRanges
279 
280  Lik. between "this" and "auxMap";
281 
282  ********************************************************************/
283  const CObservationBeaconRanges* o =
284  static_cast<const CObservationBeaconRanges*>(obs);
285 
288  CPointPDFGaussian beaconPDF;
289  CPoint3D point3D, beacon3D;
290  double ret = 0; // 300;
291 
292  for (it = o->sensedData.begin(); it != o->sensedData.end(); it++)
293  {
294  // Look for the beacon in this map:
295  unsigned int sensedID = it->beaconID;
296  bool found = false;
297 
298  for (lm_it = landmarks.begin(); !found && lm_it != landmarks.end();
299  lm_it++)
300  {
301  if ((lm_it->getType() == featBeacon) &&
302  (lm_it->ID == sensedID) &&
303  (!std::isnan(it->sensedDistance)))
304  {
305  lm_it->getPose(beaconPDF);
306  beacon3D = beaconPDF.mean;
307 
308  // Compute the 3D position of the sensor:
309  point3D = robotPose3D + it->sensorLocationOnRobot;
310 
311  const float expectedRange = point3D.distanceTo(beacon3D);
312  float sensedDist = it->sensedDistance;
313  if (sensedDist < 0) sensedDist = 0;
314 
315  float sensorStd =
317  ? o->stdError
319  ret +=
320  (-0.5f *
321  square((expectedRange - sensedDist) / sensorStd));
322  found = true;
323  }
324  }
325 
326  // If not found, uniform distribution:
327  if (!found)
328  {
330  ret += log(
331  1.0 / (o->maxSensorDistance - o->minSensorDistance));
332  }
333 
334  } // for each sensed beacon "it"
335 
337  return ret;
338 
339  } // end of likelihood of CObservationBeaconRanges
340  else if (CLASS_ID(CObservationRobotPose) == obs->GetRuntimeClass())
341  {
342  /********************************************************************
343 
344  OBSERVATION TYPE: CObservationRobotPose
345 
346  Lik. between "this" and "robotPose";
347 
348  ********************************************************************/
349  const CObservationRobotPose* o =
350  static_cast<const CObservationRobotPose*>(obs);
351 
352  // Compute the 3D position of the sensor:
353  CPose3D sensorPose3D = robotPose3D + o->sensorPose;
354 
355  // Compute the likelihood according to mahalanobis distance between
356  // poses:
357  CMatrixD dij(1, 6), Cij(6, 6), Cij_1;
358  dij(0, 0) = o->pose.mean.x() - sensorPose3D.x();
359  dij(0, 1) = o->pose.mean.y() - sensorPose3D.y();
360  dij(0, 2) = o->pose.mean.z() - sensorPose3D.z();
361  dij(0, 3) = wrapToPi(o->pose.mean.yaw() - sensorPose3D.yaw());
362  dij(0, 4) = wrapToPi(o->pose.mean.pitch() - sensorPose3D.pitch());
363  dij(0, 5) = wrapToPi(o->pose.mean.roll() - sensorPose3D.roll());
364 
365  // Equivalent covariance from "i" to "j":
366  Cij = CMatrixDouble(o->pose.cov);
367  Cij_1 = Cij.inv();
368 
369  double distMahaFlik2 = dij.multiply_HCHt_scalar(Cij_1);
370  double ret =
371  -0.5 * (distMahaFlik2 / square(likelihoodOptions.extRobotPoseStd));
372 
374  return ret;
375 
376  } // end of likelihood of CObservation
377  else if (CLASS_ID(CObservationGPS) == obs->GetRuntimeClass())
378  {
379  /********************************************************************
380 
381  OBSERVATION TYPE: CObservationGPS
382 
383  ********************************************************************/
384  const CObservationGPS* o = static_cast<const CObservationGPS*>(obs);
385  // Compute the 3D position of the sensor:
386  CPoint3D point3D = CPoint3D(robotPose3D);
387  CPoint3D GPSpose;
388  double x, y;
389  double earth_radius = 6378137;
390 
391  if ((o->has_GGA_datum) &&
394  {
395  // Compose GPS robot position
396 
397  x = DEG2RAD(
401  earth_radius * 1.03;
402  y = DEG2RAD(
406  earth_radius * 1.15;
407  GPSpose.x(
408  (x * cos(likelihoodOptions.GPSOrigin.ang) +
411  GPSpose.y(
412  (-x * sin(likelihoodOptions.GPSOrigin.ang) +
415  GPSpose.z(
419  // std::cout<<"GPSpose calculo: "<<GPSpose.x<<","<<GPSpose.y<<"\n";
420 
421  //-------------------------------//
422  // sigmaGPS =
423  // f(o->getMsgByClass<gnss::Message_NMEA_GGA>().fields.satellitesUsed)
424  // //funcion del numero de satelites
425  //-------------------------------//
426 
427  // std::cout<<"datos de longitud y latitud:
428  // "<<o->getMsgByClass<gnss::Message_NMEA_GGA>().fields.longitude_degrees<<","<<o->getMsgByClass<gnss::Message_NMEA_GGA>().fields.latitude_degrees<<","<<"\n";
429  // std::cout<<"x,y sin rotar: "<<x<<","<<y<<","<<"\n";
430  // std::cout<<"angulo: "<<likelihoodOptions.GPSOrigin.ang<<"\n";
431  // std::cout<<"desp x,y:
432  // "<<likelihoodOptions.GPSOrigin.x_shift<<","<<likelihoodOptions.GPSOrigin.y_shift<<"\n";
433  // std::cout<<"GPS ORIGIN :
434  // "<<likelihoodOptions.GPSOrigin.longitude<<","<<likelihoodOptions.GPSOrigin.latitude<<","<<likelihoodOptions.GPSOrigin.altitude<<"\n";
435  // std::cout<<"POSE DEL ROBOT:
436  // "<<point3D.x<<","<<point3D.y<<","<<point3D.z<<"\n";
437  // std::cout<<"POSE GPS :
438  // "<<GPSpose.x<<","<<GPSpose.y<<","<<GPSpose.z<<"\n";
439  // std::cin.get();
440 
441  float distance = GPSpose.distanceTo(point3D);
442 
443  // std::cout<<"likel gps:"<<-0.5f*square( ( distance
444  // )/likelihoodOptions.GPS_sigma)<<"\n";;
445  double ret =
448  return ret;
449  }
450  else
451  return 0.5;
452  } // end of likelihood of CObservationGPS
453  else
454  {
455  /********************************************************************
456 
457  OBSERVATION TYPE: Unknown
458 
459  ********************************************************************/
460  return 0.5;
461  }
462 
463  MRPT_END
464 }
465 
466 /*---------------------------------------------------------------
467  insertObservation
468  ---------------------------------------------------------------*/
470  const CObservation* obs, const CPose3D* robotPose)
471 {
472  MRPT_START
473 
474  CPose2D robotPose2D;
475  CPose3D robotPose3D;
476 
477  if (robotPose)
478  {
479  robotPose2D = CPose2D(*robotPose);
480  robotPose3D = (*robotPose);
481  }
482  else
483  {
484  // Default values are (0,0,0)
485  }
486 
487  if (CLASS_ID(CObservationImage) == obs->GetRuntimeClass() &&
489  {
490  /********************************************************************
491 
492  OBSERVATION TYPE: CObservationImage
493 
494  ********************************************************************/
495  const CObservationImage* o = static_cast<const CObservationImage*>(obs);
496  CLandmarksMap tempMap;
497 
498  // 1) Load the features in a temporary 3D landmarks map:
501 
502  // 2) This temp. map must be moved to its real position on the global
503  // reference coordinates:
504  tempMap.changeCoordinatesReference(robotPose3D);
505 
506  // 3) Fuse that map with the current contents of "this" one:
507  fuseWith(tempMap);
508 
509  // DONE!!
510 
511  // Observation was successfully inserted into the map
512  // --------------------------------------------------------
513  return true;
514  }
515  // else
516  // if ( CLASS_ID(CObservation2DRangeScan)==obs->GetRuntimeClass() &&
517  // insertionOptions.insert_Landmarks_from_range_scans)
518  // {
519  /********************************************************************
520 
521  OBSERVATION TYPE: CObservation2DRangeScan
522 
523  ********************************************************************/
524  /* CObservation2DRangeScan *o = (CObservation2DRangeScan*) obs;
525  CLandmarksMap tempMap;
526 
527  // Load into the map:
528  tempMap.loadOccupancyFeaturesFrom2DRangeScan(*o, robotPose);
529  fuseWith( tempMap );
530 
531  // Observation was successfully inserted into the map
532  // --------------------------------------------------------
533  return true;
534  } */
535  else if (
538  {
539  /********************************************************************
540  OBSERVATION TYPE: CObservationStereoImages
541  ********************************************************************/
542  const CObservationStereoImages* o =
543  static_cast<const CObservationStereoImages*>(obs);
544 
545  // Change coordinates ref:
546  CLandmarksMap auxMap;
550  auxMap.changeCoordinatesReference(robotPose3D);
551 
552  fuseWith(auxMap);
553 
554  // Observation was successfully inserted into the map
555  // --------------------------------------------------------
556  return true;
557  }
559  {
560  /********************************************************************
561 
562  OBSERVATION TYPE: CObservationVisualLandmarks
563 
564  ********************************************************************/
565  const CObservationVisualLandmarks* o =
566  static_cast<const CObservationVisualLandmarks*>(obs);
567 
568  // Change coordinates ref:
569  CLandmarksMap auxMap;
570  CPose3D acumTransform(robotPose3D + o->refCameraPose);
571  auxMap.changeCoordinatesReference(acumTransform, &o->landmarks);
572 
573  // Fuse with current:
574  fuseWith(auxMap, true);
575 
576  // Observation was successfully inserted into the map
577  // --------------------------------------------------------
578  return true;
579  }
580  else
581  {
582  /********************************************************************
583  OBSERVATION TYPE: Unknown
584  ********************************************************************/
585  return false;
586  }
587 
588  MRPT_END
589 }
590 
591 /*---------------------------------------------------------------
592  computeMatchingWith2D
593  ---------------------------------------------------------------*/
595  const mrpt::maps::CMetricMap* otherMap, const CPose2D& otherMapPose,
596  float maxDistForCorrespondence, float maxAngularDistForCorrespondence,
597  const CPose2D& angularDistPivotPoint, TMatchingPairList& correspondences,
598  float& correspondencesRatio, float* sumSqrDist, bool onlyKeepTheClosest,
599  bool onlyUniqueRobust) const
600 {
601  MRPT_UNUSED_PARAM(onlyKeepTheClosest);
602  MRPT_UNUSED_PARAM(onlyUniqueRobust);
603  MRPT_UNUSED_PARAM(sumSqrDist);
604  MRPT_UNUSED_PARAM(angularDistPivotPoint);
605  MRPT_UNUSED_PARAM(maxDistForCorrespondence);
606  MRPT_UNUSED_PARAM(maxAngularDistForCorrespondence);
607 
608  MRPT_START
609 
610  CLandmarksMap auxMap;
611  CPose3D otherMapPose3D(otherMapPose);
612 
613  correspondencesRatio = 0;
614 
615  // Check the other map class:
617  const CLandmarksMap* otherMap2 =
618  static_cast<const CLandmarksMap*>(otherMap);
619  std::vector<bool> otherCorrespondences;
620 
621  // Coordinates change:
622  auxMap.changeCoordinatesReference(otherMapPose3D, otherMap2);
623 
624  //// Use the 3D matching method:
626  otherMap2, correspondences, correspondencesRatio, otherCorrespondences);
627 
628  MRPT_END
629 }
630 
631 /*---------------------------------------------------------------
632  loadSiftFeaturesFromImageObservation
633  ---------------------------------------------------------------*/
635  const CObservationImage& obs,
636  const mrpt::vision::CFeatureExtraction::TOptions& feat_options)
637 {
638  CImage corImg;
639  CPointPDFGaussian landmark3DPositionPDF;
642  CMatrixDouble33 P, D;
643  CLandmark lm;
644 
646  vision::CFeatureList siftList; // vision::TSIFTFeatureList siftList;
648  sift; // vision::TSIFTFeatureList::iterator sift;
649 
650  // Timestamp:
651  lm.timestampLastSeen = obs.timestamp;
652  lm.seenTimesCount = 1;
653 
654  // Remove distortion:
655  corImg =
656  obs.image; // obs.image.correctDistortion(obs.intrinsicParams,obs.distortionParams);
657 
658  // Extract SIFT features:
659  fExt.options = feat_options;
660  fExt.detectFeatures(
661  corImg, siftList); // vision::computeSiftFeatures(corImg, siftList );
662 
663  // Save them as 3D landmarks:
664  landmarks.clear(); // resize( siftList.size() );
665 
666  for (sift = siftList.begin(); sift != siftList.end(); sift++)
667  {
668  // Find the 3D position from the pixels
669  // coordinates and the camera intrinsic matrix:
671  TPixelCoordf((*sift)->x, (*sift)->y),
672  obs.cameraParams.intrinsicParams); // dir = vision::pixelTo3D(
673  // sift->x,sift->y,
674  // obs.intrinsicParams );
675 
676  // Compute the mean and covariance of the landmark gaussian 3D position,
677  // from the unitary direction vector and a given distance:
678  // --------------------------------------------------------------------------
679  landmark3DPositionPDF.mean = CPoint3D(dir); // The mean is easy :-)
680  landmark3DPositionPDF.mean *= d;
681 
682  // The covariance:
684 
685  // Diagonal matrix (with the "size" of the ellipsoid)
686  D(0, 0) = square(0.5 * d);
687  D(1, 1) = square(width);
688  D(2, 2) = square(width);
689 
690  // Finally, compute the covariance!
691  landmark3DPositionPDF.cov = CMatrixDouble33(P * D * P.transpose());
692 
693  // Save into the landmarks vector:
694  // --------------------------------------------
695  lm.features.resize(1);
696  lm.features[0] = (*sift);
697 
698  CPoint3D Normal = landmark3DPositionPDF.mean;
699  Normal *= -1 / Normal.norm();
700 
701  lm.normal = Normal.asTPoint();
702 
703  lm.pose_mean = landmark3DPositionPDF.mean.asTPoint();
704 
705  lm.pose_cov_11 = landmark3DPositionPDF.cov(0, 0);
706  lm.pose_cov_22 = landmark3DPositionPDF.cov(1, 1);
707  lm.pose_cov_33 = landmark3DPositionPDF.cov(2, 2);
708  lm.pose_cov_12 = landmark3DPositionPDF.cov(0, 1);
709  lm.pose_cov_13 = landmark3DPositionPDF.cov(0, 2);
710  lm.pose_cov_23 = landmark3DPositionPDF.cov(1, 2);
711 
712  landmarks.push_back(lm);
713  }
714 
715 } // end loadSiftFeaturesFromImageObservation
716 
717 /*---------------------------------------------------------------
718  loadSiftFeaturesFromStereoImagesObservation
719  ---------------------------------------------------------------*/
722  const mrpt::vision::CFeatureExtraction::TOptions& feat_options)
723 {
724  MRPT_START
725 
727  vision::CFeatureList leftSiftList, rightSiftList;
728  vision::CMatchedFeatureList matchesList;
729  vision::TMatchingOptions matchingOptions;
730  vision::TStereoSystemParams stereoParams;
731 
732  CLandmarksMap landmarkMap;
733 
734  // Extract SIFT features:
735  fExt.options = feat_options; // OLD:
736  // fExt.options.SIFTOptions.implementation =
737  // vision::CFeatureExtraction::Hess;
738 
739  // Default: Hess implementation
740  fExt.detectFeatures(
741  obs.imageLeft, leftSiftList, fID,
743  fExt.detectFeatures(
744  obs.imageRight, rightSiftList, fID,
746 
747  matchingOptions.matching_method =
751  matchingOptions.maxEDD_TH = insertionOptions.SiftEDDThreshold;
753  leftSiftList, rightSiftList, matchesList, matchingOptions);
754 
756  {
757  std::cerr << "Warning: insertionOptions.PLOT_IMAGES has no effect "
758  "since MRPT 0.9.1\n";
759  }
760 
761  // obs.imageLeft.saveToFile("LImage.jpg");
762  // obs.imageRight.saveToFile("RImage.jpg");
763  // FILE *fmt;
764  // fmt = os::fopen( "matchesRBPF.txt", "at" );
765  // os::fprintf( fmt, "%d\n", (unsigned int)matchesList.size() );
766  // os::fclose(fmt);
767  // matchesList.saveToTextFile("matches.txt");
768 
769  // Feature Projection to 3D
770  // Parameters of the stereo rig
771 
772  stereoParams.K = obs.leftCamera.intrinsicParams;
773  stereoParams.stdPixel = insertionOptions.SIFTs_stdXY;
775  stereoParams.baseline = obs.rightCameraPose.x();
776  stereoParams.minZ = 0.0f;
778 
779  size_t numM = matchesList.size();
780  vision::projectMatchedFeatures(matchesList, stereoParams, *this);
781 
782  // Add Timestamp and the "Seen-Times" counter
784  for (ii = landmarks.begin(); ii != landmarks.end(); ii++)
785  {
786  (*ii).timestampLastSeen = obs.timestamp;
787  (*ii).seenTimesCount = 1;
788  }
789 
790  printf(
791  "%u (out of %u) corrs!\n", static_cast<unsigned>(landmarks.size()),
792  static_cast<unsigned>(numM));
793 
794  // CLandmarksMap::_maxMapID = fID;
795 
796  // Project landmarks according to the ref. camera pose:
798 
799  MRPT_END
800 }
801 
802 /*---------------------------------------------------------------
803  changeCoordinatesReference
804  ---------------------------------------------------------------*/
806 {
808 
809  CMatrixDouble44 HM;
810  newOrg.getHomogeneousMatrix(HM);
811 
812  // Build the rotation only transformation:
813  double R11 = HM.get_unsafe(0, 0);
814  double R12 = HM.get_unsafe(0, 1);
815  double R13 = HM.get_unsafe(0, 2);
816  double R21 = HM.get_unsafe(1, 0);
817  double R22 = HM.get_unsafe(1, 1);
818  double R23 = HM.get_unsafe(1, 2);
819  double R31 = HM.get_unsafe(2, 0);
820  double R32 = HM.get_unsafe(2, 1);
821  double R33 = HM.get_unsafe(2, 2);
822 
823  double c11, c22, c33, c12, c13, c23;
824 
825  // Change the reference of each individual landmark:
826  // ----------------------------------------------------
827  for (lm = landmarks.begin(); lm != landmarks.end(); lm++)
828  {
829  // Transform the pose mean & covariance:
830  // ---------------------------------------------------------
831  newOrg.composePoint(lm->pose_mean, lm->pose_mean);
832 
833  float C11 = lm->pose_cov_11;
834  float C22 = lm->pose_cov_22;
835  float C33 = lm->pose_cov_33;
836  float C12 = lm->pose_cov_12;
837  float C13 = lm->pose_cov_13;
838  float C23 = lm->pose_cov_23;
839 
840  // The covariance: cov = M * cov * (~M);
841  c11 = R11 * (C11 * R11 + C12 * R12 + C13 * R13) +
842  R12 * (C12 * R11 + C22 * R12 + C23 * R13) +
843  R13 * (C13 * R11 + C23 * R12 + C33 * R13);
844  c12 = (C11 * R11 + C12 * R12 + C13 * R13) * R21 +
845  (C12 * R11 + C22 * R12 + C23 * R13) * R22 +
846  (C13 * R11 + C23 * R12 + C33 * R13) * R23;
847  c13 = (C11 * R11 + C12 * R12 + C13 * R13) * R31 +
848  (C12 * R11 + C22 * R12 + C23 * R13) * R32 +
849  (C13 * R11 + C23 * R12 + C33 * R13) * R33;
850  c22 = R21 * (C11 * R21 + C12 * R22 + C13 * R23) +
851  R22 * (C12 * R21 + C22 * R22 + C23 * R23) +
852  R23 * (C13 * R21 + C23 * R22 + C33 * R23);
853  c23 = (C11 * R21 + C12 * R22 + C13 * R23) * R31 +
854  (C12 * R21 + C22 * R22 + C23 * R23) * R32 +
855  (C13 * R21 + C23 * R22 + C33 * R23) * R33;
856  c33 = R31 * (C11 * R31 + C12 * R32 + C13 * R33) +
857  R32 * (C12 * R31 + C22 * R32 + C23 * R33) +
858  R33 * (C13 * R31 + C23 * R32 + C33 * R33);
859 
860  // save into the landmark:
861  lm->pose_cov_11 = c11;
862  lm->pose_cov_22 = c22;
863  lm->pose_cov_33 = c33;
864  lm->pose_cov_12 = c12;
865  lm->pose_cov_13 = c13;
866  lm->pose_cov_23 = c23;
867 
868  // Rotate the normal: lm->normal = rot + lm->normal;
869  // ---------------------------------------------------------
870  float Nx = lm->normal.x;
871  float Ny = lm->normal.y;
872  float Nz = lm->normal.z;
873 
874  lm->normal.x = Nx * R11 + Ny * R12 + Nz * R13;
875  lm->normal.y = Nx * R21 + Ny * R22 + Nz * R23;
876  lm->normal.z = Nx * R31 + Ny * R32 + Nz * R33;
877  }
878 
879  // For updating the KD-Tree
881 }
882 
883 /*---------------------------------------------------------------
884  changeCoordinatesReference
885  ---------------------------------------------------------------*/
887  const CPose3D& newOrg, const mrpt::maps::CLandmarksMap* otherMap)
888 {
890  CLandmark newLandmark;
891 
892  CMatrixDouble44 HM;
893  newOrg.getHomogeneousMatrix(HM);
894 
895  // Build the rotation only transformation:
896  double R11 = HM.get_unsafe(0, 0);
897  double R12 = HM.get_unsafe(0, 1);
898  double R13 = HM.get_unsafe(0, 2);
899  double R21 = HM.get_unsafe(1, 0);
900  double R22 = HM.get_unsafe(1, 1);
901  double R23 = HM.get_unsafe(1, 2);
902  double R31 = HM.get_unsafe(2, 0);
903  double R32 = HM.get_unsafe(2, 1);
904  double R33 = HM.get_unsafe(2, 2);
905 
906  double c11, c22, c33, c12, c13, c23;
907 
908  landmarks.clear();
909 
910  // Change the reference of each individual landmark:
911  // ----------------------------------------------------
912  for (lm = otherMap->landmarks.begin(); lm != otherMap->landmarks.end();
913  lm++)
914  {
915  // Transform the pose mean & covariance:
916  // ---------------------------------------------------------
917  // The mean: mean = newReferenceBase + mean;
918  newOrg.composePoint(lm->pose_mean, newLandmark.pose_mean);
919 
920  float C11 = lm->pose_cov_11;
921  float C22 = lm->pose_cov_22;
922  float C33 = lm->pose_cov_33;
923  float C12 = lm->pose_cov_12;
924  float C13 = lm->pose_cov_13;
925  float C23 = lm->pose_cov_23;
926 
927  // The covariance: cov = M * cov * (~M);
928  c11 = R11 * (C11 * R11 + C12 * R12 + C13 * R13) +
929  R12 * (C12 * R11 + C22 * R12 + C23 * R13) +
930  R13 * (C13 * R11 + C23 * R12 + C33 * R13);
931  c12 = (C11 * R11 + C12 * R12 + C13 * R13) * R21 +
932  (C12 * R11 + C22 * R12 + C23 * R13) * R22 +
933  (C13 * R11 + C23 * R12 + C33 * R13) * R23;
934  c13 = (C11 * R11 + C12 * R12 + C13 * R13) * R31 +
935  (C12 * R11 + C22 * R12 + C23 * R13) * R32 +
936  (C13 * R11 + C23 * R12 + C33 * R13) * R33;
937  c22 = R21 * (C11 * R21 + C12 * R22 + C13 * R23) +
938  R22 * (C12 * R21 + C22 * R22 + C23 * R23) +
939  R23 * (C13 * R21 + C23 * R22 + C33 * R23);
940  c23 = (C11 * R21 + C12 * R22 + C13 * R23) * R31 +
941  (C12 * R21 + C22 * R22 + C23 * R23) * R32 +
942  (C13 * R21 + C23 * R22 + C33 * R23) * R33;
943  c33 = R31 * (C11 * R31 + C12 * R32 + C13 * R33) +
944  R32 * (C12 * R31 + C22 * R32 + C23 * R33) +
945  R33 * (C13 * R31 + C23 * R32 + C33 * R33);
946 
947  // save into the landmark:
948  newLandmark.pose_cov_11 = c11;
949  newLandmark.pose_cov_22 = c22;
950  newLandmark.pose_cov_33 = c33;
951  newLandmark.pose_cov_12 = c12;
952  newLandmark.pose_cov_13 = c13;
953  newLandmark.pose_cov_23 = c23;
954 
955  // Rotate the normal: lm->normal = rot + lm->normal;
956  // ---------------------------------------------------------
957  float Nx = lm->normal.x;
958  float Ny = lm->normal.y;
959  float Nz = lm->normal.z;
960 
961  newLandmark.normal.x = Nx * R11 + Ny * R12 + Nz * R13;
962  newLandmark.normal.y = Nx * R21 + Ny * R22 + Nz * R23;
963  newLandmark.normal.z = Nx * R31 + Ny * R32 + Nz * R33;
964 
965  newLandmark.ID = lm->ID;
966 
967  newLandmark.features = lm->features;
968 
969  newLandmark.timestampLastSeen = lm->timestampLastSeen;
970  newLandmark.seenTimesCount = lm->seenTimesCount;
971 
972  landmarks.push_back(newLandmark);
973  }
974 }
975 
976 /*---------------------------------------------------------------
977  fuseWith
978  ---------------------------------------------------------------*/
979 void CLandmarksMap::fuseWith(CLandmarksMap& other, bool justInsertAllOfThem)
980 {
981  MRPT_START
982 
983  // std::cout << "Entrando en fuseWith" << std::endl;
984 
985  std::vector<bool> otherCorrs(other.size(), false);
986  TMatchingPairList corrs;
988  float corrsRatio;
989  CLandmark *thisLM, *otherLM;
990  int i, n;
991  bool verbose = true; // false;
992  TTimeStamp lastestTime;
993  unsigned int nRemoved = 0;
994 
995  if (!justInsertAllOfThem)
996  {
997  // 1) Compute matching between the global and the new map:
998  // ---------------------------------------------------------
999  computeMatchingWith3DLandmarks(&other, corrs, corrsRatio, otherCorrs);
1000 
1001  // 2) Fuse correspondences
1002  // ---------------------------------------------------------
1003  for (corrIt = corrs.begin(); corrIt != corrs.end(); corrIt++)
1004  {
1005  thisLM = landmarks.get(corrIt->this_idx);
1006  otherLM = other.landmarks.get(corrIt->other_idx);
1007 
1008  // Fuse their poses:
1009  CPointPDFGaussian P, P1, P2;
1010 
1011  thisLM->getPose(P1);
1012  otherLM->getPose(P2);
1013 
1014  P.bayesianFusion(P1, P2);
1015 
1016  landmarks.isToBeModified(corrIt->this_idx);
1017  thisLM->setPose(P);
1018 
1019  // Update "seen" data:
1020  thisLM->seenTimesCount++;
1021  thisLM->timestampLastSeen = otherLM->timestampLastSeen;
1022 
1023  landmarks.hasBeenModified(corrIt->this_idx);
1024 
1025  } // end foreach corrs
1026  }
1027 
1028  // 3) Add new landmarks from the other map:
1029  // ---------------------------------------------------------
1030  n = other.size();
1031  for (i = 0; i < n; i++)
1032  {
1033  // Find the lastest time.
1034  lastestTime =
1035  max(lastestTime, other.landmarks.get(i)->timestampLastSeen);
1036 
1037  if (!otherCorrs[i])
1038  {
1039  // No corrs: A NEW LANDMARK!
1040  landmarks.push_back(*other.landmarks.get(i));
1041  }
1042  } // end foreach other landmark
1043 
1044  if (!justInsertAllOfThem)
1045  {
1046  // 4) Remove landmarks that have been not seen the required
1047  // number of times:
1048  // ---------------------------------------------------------
1049  n = landmarks.size();
1050  for (i = n - 1; i >= 0; i--)
1051  {
1052  if (landmarks.get(i)->getType() !=
1053  featNotDefined) // Occupancy features
1054  {
1055  const double dt =
1056  1e-3 *
1057  std::chrono::duration_cast<std::chrono::milliseconds>(
1058  lastestTime - landmarks.get(i)->timestampLastSeen)
1059  .count();
1060  if (dt > fuseOptions.ellapsedTime &&
1062  {
1063  landmarks.erase(i);
1064  nRemoved++;
1065  }
1066  }
1067  }
1068  }
1069 
1070  if (verbose)
1071  {
1072  printf(
1073  "[CLandmarksMap::fuseWith] %u fused/ %u new/ %u removed -> %u "
1074  "total\n",
1075  static_cast<unsigned int>(corrs.size()),
1076  static_cast<unsigned int>(other.size() - corrs.size()),
1077  static_cast<unsigned int>(nRemoved),
1078  static_cast<unsigned int>(landmarks.size()));
1079  FILE* f = os::fopen("Fused.txt", "at");
1080  fprintf(
1081  f, "%u\t%u\t%u\t%u\n", static_cast<unsigned int>(corrs.size()),
1082  static_cast<unsigned int>(other.size() - corrs.size()),
1083  static_cast<unsigned int>(nRemoved),
1084  static_cast<unsigned int>(landmarks.size()));
1085  os::fclose(f);
1086  }
1087 
1088  MRPT_END
1089 }
1090 
1091 /*---------------------------------------------------------------
1092  computeMatchingWith3DLandmarks
1093  ---------------------------------------------------------------*/
1095  const mrpt::maps::CLandmarksMap* anotherMap,
1096  TMatchingPairList& correspondences, float& correspondencesRatio,
1097  std::vector<bool>& otherCorrespondences) const
1098 {
1099  MRPT_START
1100 
1101  TSequenceLandmarks::const_iterator thisIt, otherIt;
1102  unsigned int nThis, nOther;
1103  int maxIdx;
1104  float desc;
1105  unsigned int i, n, j, k;
1106  TMatchingPair match;
1107  double lik_dist, lik_desc, lik, maxLik;
1108  // double maxLikDist = -1, maxLikDesc =
1109  // -1;
1110  CPointPDFGaussian pointPDF_k, pointPDF_j;
1111  std::vector<bool> thisLandmarkAssigned;
1112  double K_desc = 0.0;
1113  double K_dist = 0.0;
1114 
1115  // FILE *f = os::fopen( "flik.txt", "wt"
1116  //);
1117 
1118  // Get the number of landmarks:
1119  nThis = landmarks.size();
1120  nOther = anotherMap->landmarks.size();
1121 
1122  // Initially no LM has a correspondence:
1123  thisLandmarkAssigned.resize(nThis, false);
1124 
1125  // Initially, set all landmarks without correspondences:
1126  correspondences.clear();
1127  otherCorrespondences.clear();
1128  otherCorrespondences.resize(nOther, false);
1129  correspondencesRatio = 0;
1130 
1131  // Method selection:
1132  // 0. Our Method.
1133  // 1. Sim, Elinas, Griffin, Little.
1134 
1136  {
1137  case 0:
1138  // Our method: Filter out by the likelihood of the 3D position and
1139  // compute the likelihood of the Euclidean descriptor distance
1140 
1141  // "Constants" for the distance computation
1142  K_desc =
1144  K_dist = -0.5 / square(likelihoodOptions.SIFTs_mahaDist_std);
1145 
1146  // CDynamicGrid<std::vector<int32_t>> *gridLandmarks =
1147  // landmarks.getGrid();
1148  // std::vector<int32_t> closeLandmarksList;
1149 
1150  for (k = 0, otherIt = anotherMap->landmarks.begin();
1151  otherIt != anotherMap->landmarks.end(); otherIt++, k++)
1152  {
1153  // Load into "pointPDF_k" the PDF of landmark "otherIt":
1154  otherIt->getPose(pointPDF_k);
1155 
1156  if (otherIt->getType() == featSIFT)
1157  {
1158  // minDist = minDist2 = 1e10f;
1159  maxLik = -1;
1160  maxIdx = -1;
1161 
1162  /*
1163  // Get the list of close landmarks:
1164  // ---------------------------------------------
1165  int cx0 = gridLandmarks->x2idx( otherIt->pose_mean.x,
1166  otherIt->pose_mean.y );
1167  int cx0 = gridLandmarks->x2idx( otherIt->pose_mean.x,
1168  otherIt->pose_mean.y );
1169 
1170  closeLandmarksList.clear();
1171  closeLandmarksList.reserve(300);
1172  ...
1173  */
1174 
1175  for (j = 0, thisIt = landmarks.begin();
1176  thisIt != landmarks.end(); thisIt++, j++)
1177  {
1178  if (thisIt->getType() == featSIFT &&
1179  thisIt->features.size() ==
1180  otherIt->features.size() &&
1181  !thisIt->features.empty() && thisIt->features[0] &&
1182  otherIt->features[0] &&
1183  thisIt->features[0]->descriptors.SIFT.size() ==
1184  otherIt->features[0]->descriptors.SIFT.size())
1185  {
1186  // Compute "coincidence probability":
1187  // --------------------------------------
1188  // Load into "pointPDF_j" the PDF of landmark
1189  // "otherIt":
1190  thisIt->getPose(pointPDF_j);
1191 
1192  // Compute lik:
1193  // lik_dist =
1194  // pointPDF_k.productIntegralNormalizedWith(
1195  // &pointPDF_j );
1196  CMatrixDouble dij(1, 3), Cij(3, 3), Cij_1;
1197  double distMahaFlik2;
1198 
1199  // Distance between means:
1200  dij(0, 0) =
1201  pointPDF_k.mean.x() - pointPDF_j.mean.x();
1202  dij(0, 1) =
1203  pointPDF_k.mean.y() - pointPDF_j.mean.y();
1204  dij(0, 2) =
1205  pointPDF_k.mean.z() - pointPDF_j.mean.z();
1206 
1207  // Equivalent covariance from "i" to "j":
1208  Cij =
1209  CMatrixDouble(pointPDF_k.cov + pointPDF_j.cov);
1210  Cij_1 = Cij.inv();
1211 
1212  distMahaFlik2 = dij.multiply_HCHt_scalar(
1213  Cij_1); //( dij * Cij_1 * (~dij) )(0,0);
1214 
1215  lik_dist =
1216  exp(K_dist * distMahaFlik2); // Likelihood
1217  // regarding the
1218  // spatial
1219  // distance
1220 
1221  if (lik_dist > 1e-2)
1222  {
1223  // Compute distance between descriptors:
1224  // --------------------------------------
1225 
1226  // MODIFICATION 19-SEPT-2007
1227  // ONLY COMPUTE THE EUCLIDEAN DISTANCE BETWEEN
1228  // DESCRIPTORS IF IT HAS NOT BEEN COMPUTED
1229  // BEFORE
1230  // Make the pair of points
1231  std::pair<
1234  mPair(thisIt->ID, otherIt->ID);
1235 
1236  if (CLandmarksMap::_mEDD[mPair] == 0)
1237  {
1238  n = otherIt->features[0]
1239  ->descriptors.SIFT.size();
1240  desc = 0;
1241  for (i = 0; i < n; i++)
1242  desc += square(
1243  otherIt->features[0]
1244  ->descriptors.SIFT[i] -
1245  thisIt->features[0]
1246  ->descriptors.SIFT[i]);
1247 
1248  CLandmarksMap::_mEDD[mPair] = desc;
1249  // std::cout << "[fuseWith] - Nueva entrada!
1250  // - (LIK): " << exp( K_desc * desc ) << "
1251  // -> " << "(" << mPair.first << "," <<
1252  // mPair.second << ")" << std::endl;
1253 
1254  } // end if
1255  else
1256  {
1257  desc = CLandmarksMap::_mEDD[mPair];
1258  // std::cout << "[fuseWith] - Ya esta
1259  // calculado!: " << "(" << mPair.first <<
1260  // "," << mPair.second << ")" << ": " <<
1261  // desc << std::endl;
1262  }
1263 
1264  lik_desc = exp(K_desc * desc); // Likelihood
1265  // regarding the
1266  // descriptor
1267  }
1268  else
1269  {
1270  lik_desc = 1e-3;
1271  }
1272 
1273  // Likelihood of the correspondence
1274  // --------------------------------------
1275  lik = lik_dist * lik_desc;
1276 
1277  // os::fprintf( f,
1278  //"%i\t%i\t%f\t%f\t%f\n", k, j, lik_desc, lik_dist,
1279  // lik );
1280 
1281  if (lik > maxLik)
1282  {
1283  // maxLikDist =
1284  // lik_dist;
1285  // maxLikDesc =
1286  // lik_desc;
1287  maxLik = lik;
1288  maxIdx = j;
1289  }
1290 
1291  } // end of this landmark is SIFT
1292 
1293  } // End of for each "this", j
1294  // os::fprintf(f, "%i\t%i\t%f\t%f\t%f\n", maxIdx, k,
1295  // maxLikDist, maxLikDesc, maxLik);
1296 
1297  // Is it a correspondence?
1299  {
1300  // TODO: Solve in a better way the multiple
1301  // correspondences case!!!
1302  // ****************************************************************
1303  // If a previous correspondence for this LM was found,
1304  // discard this one!
1305  if (!thisLandmarkAssigned[maxIdx])
1306  {
1307  thisLandmarkAssigned[maxIdx] = true;
1308 
1309  // OK: A correspondence found!!
1310  otherCorrespondences[k] = true;
1311 
1312  match.this_idx = maxIdx;
1313  match.this_x = landmarks.get(maxIdx)->pose_mean.x;
1314  match.this_y = landmarks.get(maxIdx)->pose_mean.y;
1315  match.this_z = landmarks.get(maxIdx)->pose_mean.z;
1316 
1317  match.other_idx = k;
1318  match.other_x =
1319  anotherMap->landmarks.get(k)->pose_mean.x;
1320  match.other_y =
1321  anotherMap->landmarks.get(k)->pose_mean.y;
1322  match.other_z =
1323  anotherMap->landmarks.get(k)->pose_mean.z;
1324 
1325  correspondences.push_back(match);
1326  }
1327  }
1328 
1329  } // end of "otherIt" is SIFT
1330 
1331  } // end of other it., k
1332 
1333  // Compute the corrs ratio:
1334  correspondencesRatio =
1335  correspondences.size() / static_cast<float>(nOther);
1336  // os::fclose(f);
1337 
1338  break;
1339 
1340  case 1:
1341 
1342  // IMPLEMENTATION OF THE METHOD DESCRIBED IN [VISION-BASED SLAM
1343  // USING THE RBPF][SIM, ELINAS, GRIFFIN, LITTLE]
1344  // 1. Compute Euclidean descriptor distance (EDD).
1345  // 2. Matching based on a Threshold.
1346  // 3. Compute likelihood based only on the position of the 3D
1347  // landmarks.
1348 
1349  // 1.- COMPUTE EDD
1350 
1351  ASSERT_(!anotherMap->landmarks.begin()->features.empty());
1352  ASSERT_(!landmarks.begin()->features.empty());
1353  unsigned int dLen = anotherMap->landmarks.begin()
1354  ->features[0]
1355  ->descriptors.SIFT.size();
1356  for (k = 0, otherIt = anotherMap->landmarks.begin();
1357  otherIt != anotherMap->landmarks.end(); otherIt++, k++)
1358  {
1359  double mEDD = -1.0;
1360  unsigned int mEDDidx = 0;
1361  for (j = 0, thisIt = landmarks.begin();
1362  thisIt != landmarks.end(); thisIt++, j++)
1363  {
1364  // Compute EDD
1365  double EDD = 0.0;
1366  for (i = 0; i < dLen; i++)
1367  EDD += square(
1368  otherIt->features[0]->descriptors.SIFT[i] -
1369  thisIt->features[0]->descriptors.SIFT[i]);
1370 
1371  EDD = sqrt(EDD);
1372 
1373  if (EDD > mEDD)
1374  {
1375  mEDD = EDD;
1376  mEDDidx = j;
1377  } // end if
1378  } // end for j
1379 
1381  {
1382  // There is a correspondence
1383  if (!thisLandmarkAssigned[mEDDidx]) // If there is not
1384  // multiple
1385  // correspondence
1386  {
1387  thisLandmarkAssigned[mEDDidx] = true;
1388 
1389  // OK: A correspondence found!!
1390  otherCorrespondences[k] = true;
1391 
1392  otherIt->getPose(pointPDF_k);
1393  thisIt->getPose(pointPDF_j);
1394 
1395  match.this_idx = j;
1396  match.this_x = landmarks.get(mEDDidx)->pose_mean.x;
1397  match.this_y = landmarks.get(mEDDidx)->pose_mean.y;
1398  match.this_z = landmarks.get(mEDDidx)->pose_mean.z;
1399 
1400  match.other_idx = k;
1401  match.other_x =
1402  anotherMap->landmarks.get(k)->pose_mean.x;
1403  match.other_y =
1404  anotherMap->landmarks.get(k)->pose_mean.y;
1405  match.other_z =
1406  anotherMap->landmarks.get(k)->pose_mean.z;
1407 
1408  correspondences.push_back(match);
1409 
1410  } // end if multiple correspondence
1411 
1412  } // end if mEDD
1413 
1414  } // end for k
1415 
1416  correspondencesRatio =
1417  correspondences.size() / static_cast<float>(nOther);
1418 
1419  break;
1420 
1421  } // end switch
1422 
1423  MRPT_END
1424 }
1425 
1426 /*---------------------------------------------------------------
1427  saveToTextFile
1428  ---------------------------------------------------------------*/
1430 {
1431  MRPT_START
1432 
1433  FILE* f = os::fopen(file.c_str(), "wt");
1434  if (!f) return false;
1435 
1436  // os::fprintf(f,"%% Map of landmarks - file dumped by
1437  // mrpt::maps::CLandmarksMap\n");
1438  // os::fprintf(f,"%% Columns are: X Y Z TYPE(TFeatureType) TIMES_SEEN
1439  // TIME_OF_LAST_OBSERVATION [SIFT DESCRIPTOR] ID\n");
1440  // os::fprintf(f,"%%
1441  // -----------------------------------------------------------------------------------------------------\n");
1442 
1444  it != landmarks.end(); ++it)
1445  {
1446  os::fprintf(
1447  f, "%10f %10f %10f %4i %4u %10f", it->pose_mean.x, it->pose_mean.y,
1448  it->pose_mean.z, static_cast<int>(it->getType()),
1449  it->seenTimesCount,
1450  it->timestampLastSeen == INVALID_TIMESTAMP
1451  ? 0
1453  it->timestampLastSeen));
1454 
1455  if (it->getType() == featSIFT)
1456  {
1457  ASSERT_(!it->features.empty() && it->features[0]);
1458  for (unsigned int i = 0;
1459  i < it->features[0]->descriptors.SIFT.size(); i++)
1460  os::fprintf(f, " %u ", it->features[0]->descriptors.SIFT[i]);
1461  }
1462  os::fprintf(f, " %i ", (int)it->ID);
1463 
1464  os::fprintf(f, "\n");
1465  }
1466 
1467  os::fclose(f);
1468 
1469  return true;
1470 
1471  MRPT_END
1472 }
1473 
1474 /*---------------------------------------------------------------
1475  saveToMATLABScript3D
1476  ---------------------------------------------------------------*/
1478  std::string file, const char* style, float confInterval) const
1479 {
1480  FILE* f = os::fopen(file.c_str(), "wt");
1481  if (!f) return false;
1482 
1483  // Header:
1484  os::fprintf(
1485  f, "%%-------------------------------------------------------\n");
1486  os::fprintf(f, "%% File automatically generated using the MRPT method:\n");
1487  os::fprintf(f, "%% 'CLandmarksMap::saveToMATLABScript3D'\n");
1488  os::fprintf(f, "%%\n");
1489  os::fprintf(f, "%% ~ MRPT ~\n");
1490  os::fprintf(
1491  f, "%% Jose Luis Blanco Claraco, University of Malaga @ 2006\n");
1492  os::fprintf(f, "%% http://www.isa.uma.es/ \n");
1493  os::fprintf(
1494  f, "%%-------------------------------------------------------\n\n");
1495 
1496  // Main code:
1497  os::fprintf(f, "hold on;\n\n");
1498 
1500  it != landmarks.end(); ++it)
1501  {
1502  os::fprintf(
1503  f, "m=[%.4f %.4f %.4f];", it->pose_mean.x, it->pose_mean.y,
1504  it->pose_mean.z);
1505  os::fprintf(
1506  f, "c=[%.8f %.8f %.8f;%.8f %.8f %.8f;%.8f %.8f %.8f]; ",
1507  it->pose_cov_11, it->pose_cov_12, it->pose_cov_13, it->pose_cov_12,
1508  it->pose_cov_22, it->pose_cov_23, it->pose_cov_13, it->pose_cov_23,
1509  it->pose_cov_33);
1510 
1511  os::fprintf(
1512  f,
1513  "error_ellipse(c,m,'conf',%f,'style','%s','numPointsEllipse',10);"
1514  "\n",
1515  confInterval, style);
1516  }
1517 
1518  os::fprintf(f, "axis equal;grid on;xlabel('x'); ylabel('y'); zlabel('z');");
1519 
1520  os::fclose(f);
1521  return true;
1522 }
1523 /**/
1524 
1525 /*---------------------------------------------------------------
1526  saveToMATLABScript2D
1527  ---------------------------------------------------------------*/
1529  std::string file, const char* style, float stdCount)
1530 {
1531  FILE* f = os::fopen(file.c_str(), "wt");
1532  if (!f) return false;
1533 
1534  const int ELLIPSE_POINTS = 30;
1535  std::vector<float> X, Y, COS, SIN;
1536  std::vector<float>::iterator x, y, Cos, Sin;
1537  double ang;
1538  CMatrixD cov(2, 2), eigVal, eigVec, M;
1539 
1540  X.resize(ELLIPSE_POINTS);
1541  Y.resize(ELLIPSE_POINTS);
1542  COS.resize(ELLIPSE_POINTS);
1543  SIN.resize(ELLIPSE_POINTS);
1544 
1545  // Fill the angles:
1546  for (Cos = COS.begin(), Sin = SIN.begin(), ang = 0; Cos != COS.end();
1547  Cos++, Sin++, ang += (M_2PI / (ELLIPSE_POINTS - 1)))
1548  {
1549  *Cos = cos(ang);
1550  *Sin = sin(ang);
1551  }
1552 
1553  // Header:
1554  os::fprintf(
1555  f, "%%-------------------------------------------------------\n");
1556  os::fprintf(f, "%% File automatically generated using the MRPT method:\n");
1557  os::fprintf(f, "%% 'CLandmarksMap::saveToMATLABScript2D'\n");
1558  os::fprintf(f, "%%\n");
1559  os::fprintf(f, "%% ~ MRPT ~\n");
1560  os::fprintf(
1561  f, "%% Jose Luis Blanco Claraco, University of Malaga @ 2006\n");
1562  os::fprintf(f, "%% http://www.isa.uma.es/ \n");
1563  os::fprintf(
1564  f, "%%-------------------------------------------------------\n\n");
1565 
1566  // Main code:
1567  os::fprintf(f, "hold on;\n\n");
1568 
1570  it != landmarks.end(); ++it)
1571  {
1572  // Compute the eigen-vectors & values:
1573  cov(0, 0) = it->pose_cov_11;
1574  cov(1, 1) = it->pose_cov_22;
1575  cov(0, 1) = cov(1, 0) = it->pose_cov_12;
1576 
1577  cov.eigenVectors(eigVec, eigVal);
1578  eigVal = eigVal.array().sqrt().matrix();
1579  M = eigVal * eigVec.transpose();
1580 
1581  // Compute the points of the ellipsoid:
1582  // ----------------------------------------------
1583  for (x = X.begin(), y = Y.begin(), Cos = COS.begin(), Sin = SIN.begin();
1584  x != X.end(); x++, y++, Cos++, Sin++)
1585  {
1586  *x =
1587  (it->pose_mean.x +
1588  stdCount * (*Cos * M(0, 0) + *Sin * M(1, 0)));
1589  *y =
1590  (it->pose_mean.y +
1591  stdCount * (*Cos * M(0, 1) + *Sin * M(1, 1)));
1592  }
1593 
1594  // Save the code to plot the ellipsoid:
1595  // ----------------------------------------------
1596  os::fprintf(f, "plot([ ");
1597  for (x = X.begin(); x != X.end(); x++)
1598  {
1599  os::fprintf(f, "%.4f", *x);
1600  if (x != (X.end() - 1)) os::fprintf(f, ",");
1601  }
1602  os::fprintf(f, "],[ ");
1603  for (y = Y.begin(); y != Y.end(); y++)
1604  {
1605  os::fprintf(f, "%.4f", *y);
1606  if (y != (Y.end() - 1)) os::fprintf(f, ",");
1607  }
1608 
1609  os::fprintf(f, "],'%s');\n", style);
1610 
1611  // os::fprintf(f,"error_ellipse(c,m,'conf',0.99,'style','%s','numPointsEllipse',10);\n",style);
1612  }
1613 
1614  os::fprintf(f, "\naxis equal;\n");
1615  os::fclose(f);
1616  return true;
1617 }
1618 
1619 /*---------------------------------------------------------------
1620  loadOccupancyFeaturesFrom2DRangeScan
1621  ---------------------------------------------------------------*/
1623  const CObservation2DRangeScan& obs, const CPose3D* robotPose,
1624  unsigned int downSampleFactor)
1625 {
1626  unsigned int i, n = obs.scan.size();
1627  double Th, dTh; // angle of the ray
1628  double J11, J12, J21, J22; // The jacobian elements.
1629  double d;
1630  CPose3D sensorGlobalPose;
1631 
1632  // Empty the map:
1633  this->clear();
1634 
1635  // Sensor pose in 3D:
1636  if (!robotPose)
1637  sensorGlobalPose = obs.sensorPose;
1638  else
1639  sensorGlobalPose = *robotPose + obs.sensorPose;
1640 
1641  // Starting direction:
1642  if (obs.rightToLeft)
1643  {
1644  Th = -0.5 * obs.aperture;
1645  dTh = obs.aperture / n;
1646  }
1647  else
1648  {
1649  Th = +0.5 * obs.aperture;
1650  dTh = -obs.aperture / n;
1651  }
1652 
1653  // Measurement uncertainties:
1654  double var_d = square(0.005); // square(obs.stdError);
1655  double var_th = square(dTh / 10.0);
1656 
1657  // For each range:
1658  for (i = 0; i < n; i += downSampleFactor, Th += downSampleFactor * dTh)
1659  {
1660  // If it is a valid ray:
1661  if (obs.validRange[i])
1662  {
1663  CLandmark newLandmark;
1664 
1665  // Timestamp:
1666  newLandmark.timestampLastSeen = obs.timestamp;
1667  newLandmark.seenTimesCount = 1;
1668 
1669  newLandmark.createOneFeature();
1670  newLandmark.features[0]->type = featNotDefined;
1671 
1672  d = obs.scan[i];
1673 
1674  // Compute the landmark in 2D:
1675  // -----------------------------------------------
1676  // Descriptor:
1677  newLandmark.features[0]->orientation = Th;
1678  newLandmark.features[0]->scale = d;
1679 
1680  // Mean:
1681  newLandmark.pose_mean.x = (cos(Th) * d);
1682  newLandmark.pose_mean.y = (sin(Th) * d);
1683  newLandmark.pose_mean.z = 0;
1684 
1685  // Normal direction:
1686  newLandmark.normal = newLandmark.pose_mean;
1687  newLandmark.normal *= -1.0f / newLandmark.pose_mean.norm();
1688 
1689  // Jacobian:
1690  J11 = -d * sin(Th);
1691  J12 = cos(Th);
1692  J21 = d * cos(Th);
1693  J22 = sin(Th);
1694 
1695  // Covariance matrix:
1696  newLandmark.pose_cov_11 = (J11 * J11 * var_th + J12 * J12 * var_d);
1697  newLandmark.pose_cov_12 = (J11 * J21 * var_th + J12 * J22 * var_d);
1698  newLandmark.pose_cov_22 = (J21 * J21 * var_th + J22 * J22 * var_d);
1699  newLandmark.pose_cov_33 = (square(0.005)); // var_d;
1700  newLandmark.pose_cov_13 = newLandmark.pose_cov_23 = 0;
1701 
1702  // Append it:
1703  // -----------------------------------------------
1704  landmarks.push_back(newLandmark);
1705 
1706  } // end of valid ray.
1707 
1708  } // end for n
1709 
1710  // Take landmarks to 3D according to the robot & sensor 3D poses:
1711  // -----------------------------------------------
1712  changeCoordinatesReference(sensorGlobalPose);
1713 }
1714 
1715 /*---------------------------------------------------------------
1716  METHOD DESCRIBED IN PAPER
1717  -------------------------
1718 
1719  ICRA 2007,....
1720 
1721  ---------------------------------------------------------------*/
1723  const CLandmarksMap* s, const CPose2D& sensorPose)
1724 {
1725  MRPT_UNUSED_PARAM(sensorPose);
1726  MRPT_START
1727 
1728  double lik = 1.0;
1730  CLandmark* lm; //*itClosest;
1731  double corr;
1732  double PrNoCorr;
1733  CPointPDFGaussian poseThis, poseOther;
1734  // double STD_THETA = DEG2RAD(0.15);
1735  // double STD_DIST = 0.5f;
1736  double nFoundCorrs = 0;
1737  std::vector<int32_t>* corrs;
1738  unsigned int cx, cy, cx_1, cx_2, cy_1, cy_2;
1739 
1740  // s->saveToMATLABScript2D(std::string("ver_sensed.m"));
1741  // saveToMATLABScript2D(std::string("ver_ref.m"),"r");
1742 
1744  // grid->saveToTextFile( "debug_grid.txt" );
1745 
1746  // For each landmark in the observations:
1747  for (itOther = s->landmarks.begin(); itOther != s->landmarks.end();
1748  itOther++)
1749  {
1750  itOther->getPose(poseOther);
1751 
1752  cx = cy = grid->y2idx(itOther->pose_mean.y);
1753 
1754  cx_1 = max(0, grid->x2idx(itOther->pose_mean.x - 0.10f));
1755  cx_2 =
1756  min(static_cast<int>(grid->getSizeX()) - 1,
1757  grid->x2idx(itOther->pose_mean.x + 0.10f));
1758  cy_1 = max(0, grid->y2idx(itOther->pose_mean.y - 0.10f));
1759  cy_2 =
1760  min(static_cast<int>(grid->getSizeY()) - 1,
1761  grid->y2idx(itOther->pose_mean.y + 0.10f));
1762 
1763  // The likelihood of no correspondence starts at "1" and will be
1764  // modified next:
1765  PrNoCorr = 1;
1766 
1767  // For each landmark in this map: Compute its correspondence likelihood
1768  // and conditioned observation likelihood:
1769  // itClosest = nullptr;
1770 
1771  // Look at landmarks in sourronding cells only:
1772  for (cx = cx_1; cx <= cx_2; cx++)
1773  for (cy = cy_1; cy <= cy_2; cy++)
1774  {
1775  corrs = grid->cellByIndex(cx, cy);
1776  ASSERT_(corrs != nullptr);
1777  if (!corrs->empty())
1778  for (std::vector<int32_t>::iterator it = corrs->begin();
1779  it != corrs->end(); ++it)
1780  {
1781  lm = landmarks.get(*it);
1782 
1783  // Compute the "correspondence" in the range [0,1]:
1784  // -------------------------------------------------------------
1785 
1786  // Shortcut:
1787  if (fabs(lm->pose_mean.x - itOther->pose_mean.x) >
1788  0.15f ||
1789  fabs(lm->pose_mean.y - itOther->pose_mean.y) >
1790  0.15f)
1791  {
1792  // Absolutely no correspondence, not need to compute
1793  // it:
1794  corr = 0;
1795  }
1796  else
1797  {
1798  lm->getPose(poseThis);
1799  corr = poseOther.productIntegralNormalizedWith2D(
1800  poseThis);
1801  }
1802 
1803  // The likelihood of no corresp. is proportional to the
1804  // product of all "1-CORRij":
1805  // -------------------------------------------------------------
1806  PrNoCorr *= 1 - corr;
1807 
1808  } // end of each landmark in this map.
1809  }
1810 
1811  // Only consider this "point" if it has some real chance to has a
1812  // correspondence:
1813  nFoundCorrs += 1 - PrNoCorr;
1814 
1815  /**** DEBUG **** /
1816  {
1817  //FILE *f=os::fopen("debug_corrs.txt","wt");
1818  //for (Cij=v_Cij.begin(),pZj=v_pZj.begin(); pZj!=v_pZj.end();
1819  Cij++,pZj++)
1820  //{
1821  // os::fprintf(f,"%e %e\n", *Cij, *pZj);
1822  //}
1823 
1824  //os::fprintf(f,"\n INDIV LIK=%e\n lik=%e\n
1825  closestObstacleInLine=%e\n measured
1826  range=%e\n",indivLik,lik,closestObstacleInLine,
1827  itOther->descriptors.SIFT[1]);
1828  //os::fprintf(f,"
1829  closestObstacleDirection=%e\n",closestObstacleDirection);
1830  //os::fclose(f);
1831 
1832  printf("\n lik=%e\n closestObstacleInLine=%e\n measured
1833  range=%e\n",lik,closestObstacleInLine, itOther->descriptors.SIFT[1]);
1834  if (itClosest)
1835  printf(" closest=(%.03f,%.03f)\n", itClosest->pose_mean.x,
1836  itClosest->pose_mean.y);
1837  else printf(" closest=nullptr\n");
1838 
1839  printf(" P(no corrs)=%e\n", PrNoCorr );
1840  mrpt::system::pause();
1841  }
1842  / ***************/
1843 
1844  lik *= 1 - PrNoCorr;
1845 
1846  } // enf for each landmark in the other map.
1847 
1848  lik = nFoundCorrs / static_cast<double>(s->size());
1849 
1850  lik = log(lik);
1851 
1853  return lik;
1854 
1855  MRPT_END
1856 }
1857 
1858 /*---------------------------------------------------------------
1859 
1860  TCustomSequenceLandmarks
1861 
1862  ---------------------------------------------------------------*/
1864  : m_landmarks(),
1865  m_grid(-10.0f, 10.0f, -10.0f, 10.f, 0.20f),
1866  m_largestDistanceFromOrigin(),
1867  m_largestDistanceFromOriginIsUpdated(false)
1868 {
1869 }
1870 
1872 {
1873  m_landmarks.clear();
1874 
1875  // Erase the grid:
1876  m_grid.clear();
1877 
1878  m_largestDistanceFromOriginIsUpdated = false;
1879 }
1880 
1882 {
1883  // Resize grid if necesary:
1884  std::vector<int32_t> dummyEmpty;
1885 
1886  m_grid.resize(
1887  min(m_grid.getXMin(), l.pose_mean.x - 0.1),
1888  max(m_grid.getXMax(), l.pose_mean.x + 0.1),
1889  min(m_grid.getYMin(), l.pose_mean.y - 0.1),
1890  max(m_grid.getYMax(), l.pose_mean.y + 0.1), dummyEmpty);
1891 
1892  m_landmarks.push_back(l);
1893 
1894  // Add to the grid:
1895  std::vector<int32_t>* cell = m_grid.cellByPos(l.pose_mean.x, l.pose_mean.y);
1896  ASSERT_(cell);
1897  cell->push_back(m_landmarks.size() - 1);
1898 
1899  m_largestDistanceFromOriginIsUpdated = false;
1900 }
1901 
1903 {
1904  return &m_landmarks[indx];
1905 }
1906 
1908  unsigned int indx) const
1909 {
1910  return &m_landmarks[indx];
1911 }
1912 
1914 {
1915  std::vector<int32_t>* cell = m_grid.cellByPos(
1916  m_landmarks[indx].pose_mean.x, m_landmarks[indx].pose_mean.y);
1917 
1919  for (it = cell->begin(); it != cell->end(); it++)
1920  {
1921  if (*it == static_cast<int>(indx))
1922  {
1923  cell->erase(it);
1924  return;
1925  }
1926  }
1927 
1928  m_largestDistanceFromOriginIsUpdated = false;
1929 }
1930 
1932 {
1933  m_landmarks.erase(m_landmarks.begin() + indx);
1934  m_largestDistanceFromOriginIsUpdated = false;
1935 }
1936 
1938 {
1939  std::vector<int32_t> dummyEmpty;
1940 
1941  // Resize grid if necesary:
1942  m_grid.resize(
1943  min(m_grid.getXMin(), m_landmarks[indx].pose_mean.x),
1944  max(m_grid.getXMax(), m_landmarks[indx].pose_mean.x),
1945  min(m_grid.getYMin(), m_landmarks[indx].pose_mean.y),
1946  max(m_grid.getYMax(), m_landmarks[indx].pose_mean.y), dummyEmpty);
1947 
1948  // Add to the grid:
1949  std::vector<int32_t>* cell = m_grid.cellByPos(
1950  m_landmarks[indx].pose_mean.x, m_landmarks[indx].pose_mean.y);
1951  cell->push_back(indx);
1952  m_largestDistanceFromOriginIsUpdated = false;
1953 }
1954 
1956 {
1957  MRPT_START
1958 
1960  unsigned int idx;
1961  double min_x = -10.0, max_x = 10.0;
1962  double min_y = -10.0, max_y = 10.0;
1963  std::vector<int32_t> dummyEmpty;
1964 
1965  // Clear cells:
1966  m_grid.clear();
1967 
1968  // Resize the grid to the outer limits of landmarks:
1969  for (idx = 0, it = m_landmarks.begin(); it != m_landmarks.end();
1970  idx++, it++)
1971  {
1972  min_x = min(min_x, it->pose_mean.x);
1973  max_x = max(max_x, it->pose_mean.x);
1974  min_y = min(min_y, it->pose_mean.y);
1975  max_y = max(max_y, it->pose_mean.y);
1976  }
1977  m_grid.resize(min_x, max_x, min_y, max_y, dummyEmpty);
1978 
1979  // Add landmarks to cells:
1980  for (idx = 0, it = m_landmarks.begin(); it != m_landmarks.end();
1981  idx++, it++)
1982  {
1983  std::vector<int32_t>* cell =
1984  m_grid.cellByPos(it->pose_mean.x, it->pose_mean.y);
1985  cell->push_back(idx);
1986  }
1987 
1988  m_largestDistanceFromOriginIsUpdated = false;
1989  MRPT_END
1990 }
1991 
1992 /*---------------------------------------------------------------
1993  getLargestDistanceFromOrigin
1994 ---------------------------------------------------------------*/
1996  const
1997 {
1998  // Updated?
1999  if (!m_largestDistanceFromOriginIsUpdated)
2000  {
2001  // NO: Update it:
2002  float maxDistSq = 0, d;
2003  for (const_iterator it = begin(); it != end(); ++it)
2004  {
2005  d = square(it->pose_mean.x) + square(it->pose_mean.y) +
2006  square(it->pose_mean.z);
2007  maxDistSq = max(d, maxDistSq);
2008  }
2009 
2010  m_largestDistanceFromOrigin = sqrt(maxDistSq);
2011  m_largestDistanceFromOriginIsUpdated = true;
2012  }
2013  return m_largestDistanceFromOrigin;
2014 }
2015 
2016 /*---------------------------------------------------------------
2017  computeLikelihood_SIFT_LandmarkMap
2018  ---------------------------------------------------------------*/
2020  CLandmarksMap* theMap, TMatchingPairList* correspondences,
2021  std::vector<bool>* otherCorrespondences)
2022 {
2023  double lik = 0; // For 'traditional'
2024  double lik_i;
2025  unsigned long distDesc;
2026  double likByDist, likByDesc;
2027 
2029  double K_dist = -0.5 / square(likelihoodOptions.SIFTs_mahaDist_std);
2030  double K_desc =
2032 
2033  unsigned int idx1, idx2;
2034  CPointPDFGaussian lm1_pose, lm2_pose;
2035  CMatrixD dij(1, 3), Cij(3, 3), Cij_1;
2036  double distMahaFlik2;
2037  int decimation = likelihoodOptions.SIFTs_decimation;
2038 
2039  // USE INSERTOPTIONS METHOD
2041  {
2042  case 0: // Our method
2043  {
2044  // lik = 1e-9; // For consensus
2045  lik = 1.0; // For traditional
2046 
2048  for (idx1 = 0, lm1 = theMap->landmarks.begin();
2049  lm1 < theMap->landmarks.end();
2050  lm1 += decimation, idx1 += decimation) // Other theMap LM1
2051  {
2052  if (lm1->getType() == featSIFT)
2053  {
2054  // Get the pose of lm1 as an object:
2055  lm1->getPose(lm1_pose);
2056 
2057  lik_i = 0; // Counter
2058 
2059  for (idx2 = 0, lm2 = landmarks.begin();
2060  lm2 != landmarks.end();
2061  lm2++, idx2++) // This theMap LM2
2062  {
2063  if (lm2->getType() == featSIFT)
2064  {
2065  // Get the pose of lm2 as an object:
2066  lm2->getPose(lm2_pose);
2067 
2068  // Compute the likelihood according to mahalanobis
2069  // distance:
2070  // Distance between means:
2071  dij(0, 0) = lm1->pose_mean.x - lm2->pose_mean.x;
2072  dij(0, 1) = lm1->pose_mean.y - lm2->pose_mean.y;
2073  dij(0, 2) = lm1->pose_mean.z - lm2->pose_mean.z;
2074 
2075  // std::cout << "ED POSICION: " << sqrt(
2076  // dij(0,0)*dij(0,0) + dij(0,1)*dij(0,1) +
2077  // dij(0,2)*dij(0,2) ) << std::endl;
2078  // Equivalent covariance from "i" to "j":
2079  Cij = CMatrixDouble(lm1_pose.cov + lm2_pose.cov);
2080  Cij_1 = Cij.inv();
2081 
2082  distMahaFlik2 = dij.multiply_HCHt_scalar(
2083  Cij_1); //( dij * Cij_1 * (~dij) )(0,0);
2084 
2085  likByDist = exp(K_dist * distMahaFlik2);
2086 
2087  if (likByDist > 1e-2)
2088  {
2089  // If the EUCLIDEAN distance is not too large,
2090  // we compute the Descriptor distance
2091  // Compute Likelihood by descriptor
2092  // Compute distance between descriptors
2093 
2094  // IF the EDD has been already computed, we skip
2095  // this step!
2096  std::pair<
2099  mPair(lm2->ID, lm1->ID);
2100  // std::cout << "Par: (" << lm2->ID << "," <<
2101  // lm1->ID << ") -> ";
2102 
2103  if (CLandmarksMap::_mEDD[mPair] == 0)
2104  {
2105  distDesc = 0;
2106  ASSERT_(
2107  !lm1->features.empty() &&
2108  !lm2->features.empty());
2109  ASSERT_(
2110  lm1->features[0] && lm2->features[0]);
2111  ASSERT_(
2112  lm1->features[0]
2113  ->descriptors.SIFT.size() ==
2114  lm2->features[0]
2115  ->descriptors.SIFT.size());
2116 
2117  for (it1 = lm1->features[0]
2118  ->descriptors.SIFT.begin(),
2119  it2 = lm2->features[0]
2120  ->descriptors.SIFT.begin();
2121  it1 != lm1->features[0]
2122  ->descriptors.SIFT.end();
2123  it1++, it2++)
2124  distDesc += square(*it1 - *it2);
2125 
2126  // Insert into the vector of Euclidean
2127  // distances
2128  CLandmarksMap::_mEDD[mPair] = distDesc;
2129  } // end if
2130  else
2131  {
2132  distDesc = (unsigned long)
2133  CLandmarksMap::_mEDD[mPair];
2134  }
2135  likByDesc = exp(K_desc * distDesc);
2136  lik_i += likByDist *
2137  likByDesc; // Cumulative Likelihood
2138  }
2139  else
2140  {
2141  // If the EUCLIDEAN distance is too large, we
2142  // assume that the cumulative likelihood is
2143  // (almost) zero.
2144  lik_i += 1e-10f;
2145  }
2146  } // end if
2147  } // end for "lm2"
2148  lik *= (0.1 + 0.9 * lik_i); // (TRADITIONAL) Total
2149  }
2150  } // end for "lm1"
2151  }
2152  break;
2153 
2154  case 1: // SIM, ELINAS, GRIFFIN, LITTLE
2155  double dist;
2156  unsigned int k;
2158 
2159  lik = 1.0f;
2160 
2161  // Check if the Matches are inserted into the function
2162  if (correspondences == nullptr)
2164  "When using this method with SIFTLikelihoodMethod = 1, "
2165  "TMatchingPairList *correspondence can not be NULL");
2166 
2167  if (otherCorrespondences == nullptr)
2169  "When using this method with SIFTLikelihoodMethod = 1, "
2170  "std::vector<bool> *otherCorrespondences can not be NULL");
2171 
2172  for (itCorr = correspondences->begin();
2173  itCorr != correspondences->end(); itCorr++)
2174  {
2175  CLandmark* lm1 = theMap->landmarks.get(itCorr->other_idx);
2176  CLandmark* lm2 = landmarks.get(itCorr->this_idx);
2177 
2178  dij(0, 0) = lm1->pose_mean.x - lm2->pose_mean.x;
2179  dij(0, 1) = lm1->pose_mean.y - lm2->pose_mean.y;
2180  dij(0, 2) = lm1->pose_mean.z - lm2->pose_mean.z;
2181 
2182  // Equivalent covariance from "i" to "j":
2183  Cij = CMatrixDouble(lm1_pose.cov + lm2_pose.cov);
2184  Cij_1 = Cij.inv();
2185 
2186  distMahaFlik2 = dij.multiply_HCHt_scalar(
2187  Cij_1); // ( dij * Cij_1 * (~dij) )(0,0);
2188 
2189  dist = min(
2191  distMahaFlik2);
2192 
2193  lik *= exp(-0.5 * dist);
2194 
2195  } // end for correspondences
2196 
2197  // We complete the likelihood with the null correspondences
2198  for (k = 1; k <= (theMap->size() - correspondences->size()); k++)
2200 
2201  break;
2202 
2203  } // end switch
2204 
2205  lik = log(lik);
2207  return lik;
2208 }
2209 
2210 /*---------------------------------------------------------------
2211  TInsertionOptions
2212  ---------------------------------------------------------------*/
2214  : insert_SIFTs_from_monocular_images(true),
2215  insert_SIFTs_from_stereo_images(true),
2216  insert_Landmarks_from_range_scans(true),
2217  SiftCorrRatioThreshold(0.4f),
2218  SiftLikelihoodThreshold(0.5f),
2219 
2220  SiftEDDThreshold(200.0f),
2221  SIFTMatching3DMethod(0),
2222  SIFTLikelihoodMethod(0),
2223 
2224  SIFTsLoadDistanceOfTheMean(3.0f),
2225  SIFTsLoadEllipsoidWidth(0.05f),
2226 
2227  SIFTs_stdXY(2.0f),
2228  SIFTs_stdDisparity(1.0f),
2229 
2230  SIFTs_numberOfKLTKeypoints(60),
2231  SIFTs_stereo_maxDepth(15.0f),
2232 
2233  SIFTs_epipolar_TH(1.5f),
2234  PLOT_IMAGES(false),
2235 
2236  SIFT_feat_options(vision::featSIFT)
2237 {
2238 }
2239 
2240 /*---------------------------------------------------------------
2241  dumpToTextStream
2242  ---------------------------------------------------------------*/
2244 {
2245  out << mrpt::format(
2246  "\n----------- [CLandmarksMap::TInsertionOptions] ------------ \n\n");
2247 
2248  out << mrpt::format(
2249  "insert_SIFTs_from_monocular_images = %c\n",
2250  insert_SIFTs_from_monocular_images ? 'Y' : 'N');
2251  out << mrpt::format(
2252  "insert_SIFTs_from_stereo_images = %c\n",
2253  insert_SIFTs_from_stereo_images ? 'Y' : 'N');
2254  out << mrpt::format(
2255  "insert_Landmarks_from_range_scans = %c\n",
2256  insert_Landmarks_from_range_scans ? 'Y' : 'N');
2257  out << mrpt::format("\n");
2258  out << mrpt::format(
2259  "SiftCorrRatioThreshold = %f\n",
2260  SiftCorrRatioThreshold);
2261  out << mrpt::format(
2262  "SiftLikelihoodThreshold = %f\n",
2263  SiftLikelihoodThreshold);
2264  out << mrpt::format(
2265  "SiftEDDThreshold = %f\n", SiftEDDThreshold);
2266  out << mrpt::format(
2267  "SIFTMatching3DMethod = %d\n", SIFTMatching3DMethod);
2268  out << mrpt::format(
2269  "SIFTLikelihoodMethod = %d\n", SIFTLikelihoodMethod);
2270 
2271  out << mrpt::format(
2272  "SIFTsLoadDistanceOfTheMean = %f\n",
2273  SIFTsLoadDistanceOfTheMean);
2274  out << mrpt::format(
2275  "SIFTsLoadEllipsoidWidth = %f\n",
2276  SIFTsLoadEllipsoidWidth);
2277  out << mrpt::format("\n");
2278  out << mrpt::format(
2279  "SIFTs_stdXY = %f\n", SIFTs_stdXY);
2280  out << mrpt::format(
2281  "SIFTs_stdDisparity = %f\n", SIFTs_stdDisparity);
2282  out << mrpt::format("\n");
2283  out << mrpt::format(
2284  "SIFTs_numberOfKLTKeypoints = %i\n",
2285  SIFTs_numberOfKLTKeypoints);
2286  out << mrpt::format(
2287  "SIFTs_stereo_maxDepth = %f\n",
2288  SIFTs_stereo_maxDepth);
2289  out << mrpt::format(
2290  "SIFTs_epipolar_TH = %f\n", SIFTs_epipolar_TH);
2291  out << mrpt::format(
2292  "PLOT_IMAGES = %c\n",
2293  PLOT_IMAGES ? 'Y' : 'N');
2294 
2295  SIFT_feat_options.dumpToTextStream(out);
2296 
2297  out << mrpt::format("\n");
2298 }
2299 
2300 /*---------------------------------------------------------------
2301  loadFromConfigFile
2302  ---------------------------------------------------------------*/
2304  const mrpt::config::CConfigFileBase& iniFile, const std::string& section)
2305 {
2306  insert_SIFTs_from_monocular_images = iniFile.read_bool(
2307  section.c_str(), "insert_SIFTs_from_monocular_images",
2308  insert_SIFTs_from_monocular_images);
2309  insert_SIFTs_from_stereo_images = iniFile.read_bool(
2310  section.c_str(), "insert_SIFTs_from_stereo_images",
2311  insert_SIFTs_from_stereo_images);
2312  insert_Landmarks_from_range_scans = iniFile.read_bool(
2313  section.c_str(), "insert_Landmarks_from_range_scans",
2314  insert_Landmarks_from_range_scans);
2315  SiftCorrRatioThreshold = iniFile.read_float(
2316  section.c_str(), "SiftCorrRatioThreshold", SiftCorrRatioThreshold);
2317  SiftLikelihoodThreshold = iniFile.read_float(
2318  section.c_str(), "SiftLikelihoodThreshold", SiftLikelihoodThreshold);
2319  SiftEDDThreshold = iniFile.read_float(
2320  section.c_str(), "SiftEDDThreshold", SiftEDDThreshold);
2321  SIFTMatching3DMethod = iniFile.read_int(
2322  section.c_str(), "SIFTMatching3DMethod", SIFTMatching3DMethod);
2323  SIFTLikelihoodMethod = iniFile.read_int(
2324  section.c_str(), "SIFTLikelihoodMethod", SIFTLikelihoodMethod);
2325  SIFTsLoadDistanceOfTheMean = iniFile.read_float(
2326  section.c_str(), "SIFTsLoadDistanceOfTheMean",
2327  SIFTsLoadDistanceOfTheMean);
2328  SIFTsLoadEllipsoidWidth = iniFile.read_float(
2329  section.c_str(), "SIFTsLoadEllipsoidWidth", SIFTsLoadEllipsoidWidth);
2330  SIFTs_stdXY =
2331  iniFile.read_float(section.c_str(), "SIFTs_stdXY", SIFTs_stdXY);
2332  SIFTs_stdDisparity = iniFile.read_float(
2333  section.c_str(), "SIFTs_stdDisparity", SIFTs_stdDisparity);
2334  SIFTs_numberOfKLTKeypoints = iniFile.read_int(
2335  section.c_str(), "SIFTs_numberOfKLTKeypoints",
2336  SIFTs_numberOfKLTKeypoints);
2337  SIFTs_stereo_maxDepth = iniFile.read_float(
2338  section.c_str(), "SIFTs_stereo_maxDepth", SIFTs_stereo_maxDepth);
2339  SIFTs_epipolar_TH = iniFile.read_float(
2340  section.c_str(), "SIFTs_epipolar_TH", SIFTs_epipolar_TH);
2341  PLOT_IMAGES =
2342  iniFile.read_bool(section.c_str(), "PLOT_IMAGES", PLOT_IMAGES);
2343 
2344  SIFT_feat_options.loadFromConfigFile(iniFile, section);
2345 }
2346 
2347 /*---------------------------------------------------------------
2348  TLikelihoodOptions
2349  ---------------------------------------------------------------*/
2351  : rangeScan2D_decimation(20),
2352  SIFTs_sigma_euclidean_dist(0.30f),
2353  SIFTs_sigma_descriptor_dist(100.0f),
2354  SIFTs_mahaDist_std(4.0f),
2355  SIFTnullCorrespondenceDistance(4.0f),
2356  SIFTs_decimation(1),
2357  SIFT_feat_options(vision::featSIFT),
2358  beaconRangesStd(0.08f),
2359  beaconRangesUseObservationStd(false),
2360  extRobotPoseStd(0.05f),
2361  GPSOrigin(),
2362  GPS_sigma(1.0f)
2363 {
2364 }
2365 
2367  : longitude(-4.47763833333333),
2368  latitude(36.71559000000000),
2369  altitude(42.3),
2370  ang(0),
2371  x_shift(0),
2372  y_shift(0),
2373  min_sat(4)
2374 {
2375 }
2376 
2377 /*---------------------------------------------------------------
2378  dumpToTextStream
2379  ---------------------------------------------------------------*/
2381  std::ostream& out) const
2382 {
2383  out << mrpt::format(
2384  "\n----------- [CLandmarksMap::TLikelihoodOptions] ------------ \n\n");
2385 
2386  out << mrpt::format(
2387  "rangeScan2D_decimation = %i\n",
2389  out << mrpt::format(
2390  "SIFTs_sigma_euclidean_dist = %f\n",
2392  out << mrpt::format(
2393  "SIFTs_sigma_descriptor_dist = %f\n",
2395  out << mrpt::format(
2396  "SIFTs_mahaDist_std = %f\n", SIFTs_mahaDist_std);
2397  out << mrpt::format(
2398  "SIFTs_decimation = %i\n", SIFTs_decimation);
2399  out << mrpt::format(
2400  "SIFTnullCorrespondenceDistance = %f\n",
2402  out << mrpt::format(
2403  "beaconRangesStd = %f\n", beaconRangesStd);
2404  out << mrpt::format(
2405  "beaconRangesUseObservationStd = %c\n",
2406  beaconRangesUseObservationStd ? 'Y' : 'N');
2407  out << mrpt::format(
2408  "extRobotPoseStd = %f\n", extRobotPoseStd);
2409 
2410  out << mrpt::format(
2411  "GPSOrigin:LATITUDE = %f\n", GPSOrigin.latitude);
2412  out << mrpt::format(
2413  "GPSOrigin:LONGITUDE = %f\n", GPSOrigin.longitude);
2414  out << mrpt::format(
2415  "GPSOrigin:ALTITUDE = %f\n", GPSOrigin.altitude);
2416  out << mrpt::format(
2417  "GPSOrigin:Rotation_Angle = %f\n", GPSOrigin.ang);
2418  out << mrpt::format(
2419  "GPSOrigin:x_shift = %f\n", GPSOrigin.x_shift);
2420  out << mrpt::format(
2421  "GPSOrigin:y_shift = %f\n", GPSOrigin.y_shift);
2422  out << mrpt::format(
2423  "GPSOrigin:min_sat = %i\n", GPSOrigin.min_sat);
2424 
2425  out << mrpt::format(
2426  "GPS_sigma = %f (m)\n", GPS_sigma);
2427 
2429 
2430  out << mrpt::format("\n");
2431 }
2432 
2433 /*---------------------------------------------------------------
2434  loadFromConfigFile
2435  ---------------------------------------------------------------*/
2437  const mrpt::config::CConfigFileBase& iniFile, const std::string& section)
2438 {
2439  rangeScan2D_decimation = iniFile.read_int(
2440  section.c_str(), "rangeScan2D_decimation", rangeScan2D_decimation);
2441  SIFTs_sigma_euclidean_dist = iniFile.read_double(
2442  section.c_str(), "SIFTs_sigma_euclidean_dist",
2444  SIFTs_sigma_descriptor_dist = iniFile.read_double(
2445  section.c_str(), "SIFTs_sigma_descriptor_dist",
2447  SIFTs_mahaDist_std = iniFile.read_float(
2448  section.c_str(), "SIFTs_mahaDist_std", SIFTs_mahaDist_std);
2450  iniFile.read_int(section.c_str(), "SIFTs_decimation", SIFTs_decimation);
2452  section.c_str(), "SIFTnullCorrespondenceDistance",
2454 
2455  GPSOrigin.latitude = iniFile.read_double(
2456  section.c_str(), "GPSOriginLatitude", GPSOrigin.latitude);
2457  GPSOrigin.longitude = iniFile.read_double(
2458  section.c_str(), "GPSOriginLongitude", GPSOrigin.longitude);
2459  GPSOrigin.altitude = iniFile.read_double(
2460  section.c_str(), "GPSOriginAltitude", GPSOrigin.altitude);
2461  GPSOrigin.ang =
2462  iniFile.read_double(section.c_str(), "GPSOriginAngle", GPSOrigin.ang) *
2463  M_PI / 180;
2464  GPSOrigin.x_shift = iniFile.read_double(
2465  section.c_str(), "GPSOriginXshift", GPSOrigin.x_shift);
2466  GPSOrigin.y_shift = iniFile.read_double(
2467  section.c_str(), "GPSOriginYshift", GPSOrigin.y_shift);
2468  GPSOrigin.min_sat =
2469  iniFile.read_int(section.c_str(), "GPSOriginMinSat", GPSOrigin.min_sat);
2470 
2471  GPS_sigma = iniFile.read_float(section.c_str(), "GPSSigma", GPS_sigma);
2472 
2473  beaconRangesStd =
2474  iniFile.read_float(section.c_str(), "beaconRangesStd", beaconRangesStd);
2476  section.c_str(), "beaconRangesUseObservationStd",
2478 
2479  extRobotPoseStd =
2480  iniFile.read_float(section.c_str(), "extRobotPoseStd", extRobotPoseStd);
2481 
2483 }
2484 
2485 /*---------------------------------------------------------------
2486  TFuseOptions
2487  ---------------------------------------------------------------*/
2489  : minTimesSeen(2), ellapsedTime(4.0f)
2490 {
2491 }
2492 
2493 /*---------------------------------------------------------------
2494  isEmpty
2495  ---------------------------------------------------------------*/
2496 bool CLandmarksMap::isEmpty() const { return size() == 0; }
2497 /*---------------------------------------------------------------
2498  simulateBeaconReadings
2499  ---------------------------------------------------------------*/
2501  const CPose3D& in_robotPose, const CPoint3D& in_sensorLocationOnRobot,
2502  mrpt::obs::CObservationBeaconRanges& out_Observations) const
2503 {
2506  CPoint3D point3D, beacon3D;
2507  CPointPDFGaussian beaconPDF;
2508 
2509  // Compute the 3D position of the sensor:
2510  point3D = in_robotPose + in_sensorLocationOnRobot;
2511 
2512  // Clear output data:
2513  out_Observations.sensedData.clear();
2514  out_Observations.timestamp = mrpt::system::getCurrentTime();
2515 
2516  // For each BEACON landmark in the map:
2517  for (it = landmarks.begin(); it != landmarks.end(); it++)
2518  {
2519  if (it->getType() == featBeacon)
2520  {
2521  // Get the 3D position of the beacon (just the mean value):
2522  it->getPose(beaconPDF);
2523  beacon3D = beaconPDF.mean;
2524 
2525  float range = point3D.distanceTo(beacon3D);
2526 
2527  // Add noise:
2528  range += out_Observations.stdError *
2530  range = max(0.0f, range);
2531 
2532  if (range >= out_Observations.minSensorDistance &&
2533  range <= out_Observations.maxSensorDistance)
2534  {
2535  // Fill out:
2536  newMeas.beaconID = it->ID;
2537  newMeas.sensorLocationOnRobot = in_sensorLocationOnRobot;
2538  newMeas.sensedDistance = range;
2539 
2540  // Insert:
2541  out_Observations.sensedData.push_back(newMeas);
2542  }
2543  } // end if beacon
2544  } // end for it
2545  // Done!
2546 }
2547 
2548 /*---------------------------------------------------------------
2549  saveMetricMapRepresentationToFile
2550  ---------------------------------------------------------------*/
2552  const std::string& filNamePrefix) const
2553 {
2554  MRPT_START
2555 
2556  // Matlab:
2557  std::string fil1(filNamePrefix + std::string("_3D.m"));
2558  saveToMATLABScript3D(fil1);
2559 
2560  // 3D Scene:
2561  opengl::COpenGLScene scene;
2563  mrpt::make_aligned_shared<mrpt::opengl::CSetOfObjects>();
2564  getAs3DObject(obj3D);
2565 
2566  opengl::CGridPlaneXY::Ptr objGround =
2567  mrpt::make_aligned_shared<opengl::CGridPlaneXY>(
2568  -100, 100, -100, 100, 0, 1);
2569 
2570  scene.insert(obj3D);
2571  scene.insert(objGround);
2572 
2573  std::string fil2(filNamePrefix + std::string("_3D.3Dscene"));
2574  scene.saveToFile(fil2);
2575 
2576  MRPT_END
2577 }
2578 
2579 /*---------------------------------------------------------------
2580  getAs3DObject
2581  ---------------------------------------------------------------*/
2583  mrpt::opengl::CSetOfObjects::Ptr& outObj) const
2584 {
2586 
2587  // TODO: Generate patchs in 3D, etc...
2588 
2589  // Save 3D ellipsoids
2590  CPointPDFGaussian pointGauss;
2592  it != landmarks.end(); ++it)
2593  {
2594  opengl::CEllipsoid::Ptr ellip =
2595  mrpt::make_aligned_shared<opengl::CEllipsoid>();
2596 
2597  it->getPose(pointGauss);
2598 
2599  ellip->setPose(pointGauss.mean);
2600  ellip->setCovMatrix(pointGauss.cov);
2601  ellip->enableDrawSolid3D(false);
2602  ellip->setQuantiles(3.0);
2603  ellip->set3DsegmentsCount(10);
2604  ellip->setColor(0, 0, 1);
2605  ellip->setName(
2606  mrpt::format("LM.ID=%u", static_cast<unsigned int>(it->ID)));
2607  ellip->enableShowName(true);
2608 
2609  outObj->insert(ellip);
2610  }
2611 }
2612 /**** FAMD ****/
2614 {
2615  return _mapMaxID;
2616 }
2617 /**** END FAMD ****/
2618 
2620  CLandmark::TLandmarkID ID) const
2621 {
2622  for (size_t indx = 0; indx < m_landmarks.size(); indx++)
2623  {
2624  if (m_landmarks[indx].ID == ID) return &m_landmarks[indx];
2625  }
2626  return nullptr;
2627 }
2628 
2629 // CLandmark* CLandmarksMap::TCustomSequenceLandmarks::getByID(
2630 // CLandmark::TLandmarkID ID )
2631 //{
2632 // for(size_t indx = 0; indx < m_landmarks.size(); indx++)
2633 // {
2634 // if( m_landmarks[indx].ID == ID )
2635 // return &m_landmarks[indx];
2636 // }
2637 // return nullptr;
2638 //}
2639 
2641  unsigned int ID) const
2642 {
2643  for (size_t indx = 0; indx < m_landmarks.size(); indx++)
2644  {
2645  if (m_landmarks[indx].ID == ID) return &m_landmarks[indx];
2646  }
2647  return nullptr;
2648 }
2649 
2650 /*---------------------------------------------------------------
2651  Computes the ratio in [0,1] of correspondences between "this" and the
2652  "otherMap" map, whose 6D pose relative to "this" is "otherMapPose"
2653  * In the case of a multi-metric map, this returns the average between the
2654  maps. This method always return 0 for grid maps.
2655  * \param otherMap [IN] The other map to compute the matching
2656  with.
2657  * \param otherMapPose [IN] The 6D pose of the other map as seen
2658  from "this".
2659  * \param maxDistForCorr [IN] The minimum distance between 2
2660  non-probabilistic map elements for counting them as a correspondence.
2661  * \param maxMahaDistForCorr [IN] The minimum Mahalanobis distance
2662  between 2 probabilistic map elements for counting them as a correspondence.
2663  *
2664  * \return The matching ratio [0,1]
2665  * \sa computeMatchingWith2D
2666  ----------------------------------------------------------------*/
2668  const mrpt::maps::CMetricMap* otherMap2,
2669  const mrpt::poses::CPose3D& otherMapPose,
2670  const TMatchingRatioParams& params) const
2671 {
2672  MRPT_START
2673 
2674  // Compare to a similar map only:
2675  const CLandmarksMap* otherMap = nullptr;
2676 
2677  if (otherMap2->GetRuntimeClass() == CLASS_ID(CLandmarksMap))
2678  otherMap = static_cast<const CLandmarksMap*>(otherMap2);
2679 
2680  if (!otherMap) return 0;
2681 
2683  std::deque<CPointPDFGaussian::Ptr> poses3DThis, poses3DOther;
2684  std::deque<CPointPDFGaussian::Ptr>::iterator itPoseThis, itPoseOther;
2685  CPointPDFGaussian tempPose;
2686  size_t nThis = landmarks.size();
2687  size_t nOther = otherMap->landmarks.size();
2688  size_t otherLandmarkWithCorrespondence = 0;
2689 
2690  // Checks:
2691  if (!nThis) return 0;
2692  if (!nOther) return 0;
2693 
2694  // The transformation:
2695  CMatrixDouble44 pose3DMatrix;
2696  otherMapPose.getHomogeneousMatrix(pose3DMatrix);
2697  float Tx = pose3DMatrix.get_unsafe(0, 3);
2698  float Ty = pose3DMatrix.get_unsafe(1, 3);
2699  float Tz = pose3DMatrix.get_unsafe(2, 3);
2700 
2701  // ---------------------------------------------------------------------------------------------------------------
2702  // Is there any "contact" between the spheres that contain all the points
2703  // from each map after translating them??
2704  // (Note that we can avoid computing the rotation of all the points if this
2705  // test fail, with a great speed up!)
2706  // ---------------------------------------------------------------------------------------------------------------
2707  if (sqrt(square(Tx) + square(Ty) + square(Tz)) >=
2709  otherMap->landmarks.getLargestDistanceFromOrigin() + 1.0f))
2710  return 0; // There is no contact!
2711 
2712  // Prepare:
2713  poses3DOther.resize(nOther);
2714  for (size_t i = 0; i < nOther; i++)
2715  poses3DOther[i] = mrpt::make_aligned_shared<CPointPDFGaussian>();
2716 
2717  poses3DThis.resize(nThis);
2718  for (size_t i = 0; i < nThis; i++)
2719  poses3DThis[i] = mrpt::make_aligned_shared<CPointPDFGaussian>();
2720 
2721  // Save 3D poses of the other map with transformed coordinates:
2722  for (itOther = otherMap->landmarks.begin(),
2723  itPoseOther = poses3DOther.begin();
2724  itOther != otherMap->landmarks.end(); itOther++, itPoseOther++)
2725  {
2726  itOther->getPose(**itPoseOther);
2727  (*itPoseOther)->changeCoordinatesReference(otherMapPose);
2728  }
2729 
2730  // And the 3D poses of "this" map:
2731  for (itThis = landmarks.begin(), itPoseThis = poses3DThis.begin();
2732  itThis != landmarks.end(); itThis++, itPoseThis++)
2733  {
2734  itThis->getPose(**itPoseThis);
2735  }
2736 
2737  // Check whether each "other"'s LM has a correspondence or not:
2738  for (itOther = otherMap->landmarks.begin(),
2739  itPoseOther = poses3DOther.begin();
2740  itOther != otherMap->landmarks.end(); itOther++, itPoseOther++)
2741  {
2742  for (itThis = landmarks.begin(), itPoseThis = poses3DThis.begin();
2743  itThis != landmarks.end(); itThis++, itPoseThis++)
2744  {
2745  CMatrixDouble COV =
2746  CMatrixDouble((*itPoseThis)->cov + (*itPoseOther)->cov);
2747  TPoint3D D(
2748  (*itPoseThis)->mean.x() - (*itPoseOther)->mean.x(),
2749  (*itPoseThis)->mean.y() - (*itPoseOther)->mean.y(),
2750  (*itPoseThis)->mean.z() - (*itPoseOther)->mean.z());
2751  CMatrixDouble d(1, 3);
2752  d(0, 0) = D.x;
2753  d(0, 1) = D.y;
2754  d(0, 2) = D.z;
2755 
2756  float distMaha = sqrt(d.multiply_HCHt_scalar(
2757  COV.inv())); //(d*COV.inv()*(~d))(0,0) );
2758 
2759  if (distMaha < params.maxMahaDistForCorr)
2760  {
2761  // Now test the SIFT descriptors:
2762  if (!itThis->features.empty() && !itOther->features.empty() &&
2763  itThis->features[0]->descriptors.SIFT.size() ==
2764  itOther->features[0]->descriptors.SIFT.size())
2765  {
2766  unsigned long descrDist = 0;
2768  for (it1 = itThis->features[0]->descriptors.SIFT.begin(),
2769  it2 = itOther->features[0]->descriptors.SIFT.begin();
2770  it1 != itThis->features[0]->descriptors.SIFT.end();
2771  it1++, it2++)
2772  descrDist += square(*it1 - *it2);
2773 
2774  float descrDist_f =
2775  sqrt(static_cast<float>(descrDist)) /
2776  itThis->features[0]->descriptors.SIFT.size();
2777 
2778  if (descrDist_f < 1.5f)
2779  {
2780  otherLandmarkWithCorrespondence++;
2781  break; // Go to the next "other" LM
2782  }
2783  }
2784  }
2785  } // for each in "this"
2786 
2787  } // for each in "other"
2788 
2789  return static_cast<float>(otherLandmarkWithCorrespondence) / nOther;
2790 
2791  MRPT_END
2792 }
2793 
2794 /*---------------------------------------------------------------
2795  auxParticleFilterCleanUp
2796  ---------------------------------------------------------------*/
2798 {
2799  // std::cout << "mEDD:" << std::endl;
2800  // std::cout << "-----------------------" << std::endl;
2801  // std::map<std::pair<mrpt::maps::CLandmark::TLandmarkID,
2802  // mrpt::maps::CLandmark::TLandmarkID>, unsigned long>::iterator itmEDD;
2803  // for(itmEDD = CLandmarksMap::_mEDD.begin(); itmEDD !=
2804  // CLandmarksMap::_mEDD.end(); itmEDD++)
2805  // std::cout << "(" << itmEDD->first.first << "," << itmEDD->first.second
2806  //<< ")" << ": " << itmEDD->second << std::endl;
2807 
2808  CLandmarksMap::_mEDD.clear();
2810  // TODO: Paco...
2811 }
2812 
2813 /*---------------------------------------------------------------
2814  simulateRangeBearingReadings
2815  ---------------------------------------------------------------*/
2817  const CPose3D& in_robotPose, const CPose3D& in_sensorLocationOnRobot,
2818  CObservationBearingRange& out_Observations, bool sensorDetectsIDs,
2819  const float in_stdRange, const float in_stdYaw, const float in_stdPitch,
2820  std::vector<size_t>* out_real_associations,
2821  const double spurious_count_mean, const double spurious_count_std) const
2822 {
2824  size_t idx;
2826  CPoint3D beacon3D;
2827  CPointPDFGaussian beaconPDF;
2828 
2829  if (out_real_associations) out_real_associations->clear();
2830 
2831  // Compute the 3D position of the sensor:
2832  const CPose3D point3D = in_robotPose + CPose3D(in_sensorLocationOnRobot);
2833 
2834  // Clear output data:
2835  out_Observations.validCovariances = false;
2836  out_Observations.sensor_std_range = in_stdRange;
2837  out_Observations.sensor_std_yaw = in_stdYaw;
2838  out_Observations.sensor_std_pitch = in_stdPitch;
2839 
2840  out_Observations.sensedData.clear();
2841  out_Observations.timestamp = mrpt::system::getCurrentTime();
2842  out_Observations.sensorLocationOnRobot = in_sensorLocationOnRobot;
2843 
2844  // For each BEACON landmark in the map:
2845  // ------------------------------------------
2846  for (idx = 0, it = landmarks.begin(); it != landmarks.end(); ++it, ++idx)
2847  {
2848  // Get the 3D position of the beacon (just the mean value):
2849  it->getPose(beaconPDF);
2850  beacon3D = CPoint3D(beaconPDF.mean);
2851 
2852  // Compute yaw,pitch,range:
2853  double range, yaw, pitch;
2854  point3D.sphericalCoordinates(beacon3D.asTPoint(), range, yaw, pitch);
2855 
2856  // Add noises:
2857  range += in_stdRange * getRandomGenerator().drawGaussian1D_normalized();
2858  yaw += in_stdYaw * getRandomGenerator().drawGaussian1D_normalized();
2859  pitch += in_stdPitch * getRandomGenerator().drawGaussian1D_normalized();
2860 
2861  yaw = math::wrapToPi(yaw);
2862  range = max(0.0, range);
2863 
2864  if (range >= out_Observations.minSensorDistance &&
2865  range <= out_Observations.maxSensorDistance &&
2866  fabs(yaw) <= 0.5f * out_Observations.fieldOfView_yaw &&
2867  fabs(pitch) <= 0.5f * out_Observations.fieldOfView_pitch)
2868  {
2869  // Fill out:
2870  if (sensorDetectsIDs)
2871  newMeas.landmarkID = it->ID;
2872  else
2873  newMeas.landmarkID = INVALID_LANDMARK_ID;
2874  newMeas.range = range;
2875  newMeas.yaw = yaw;
2876  newMeas.pitch = pitch;
2877 
2878  // Insert:
2879  out_Observations.sensedData.push_back(newMeas);
2880 
2881  if (out_real_associations)
2882  out_real_associations->push_back(idx); // Real indices.
2883  }
2884  } // end for it
2885 
2886  const double fSpurious = getRandomGenerator().drawGaussian1D(
2887  spurious_count_mean, spurious_count_std);
2888  size_t nSpurious = 0;
2889  if (spurious_count_std != 0 || spurious_count_mean != 0)
2890  nSpurious =
2891  static_cast<size_t>(mrpt::round_long(std::max(0.0, fSpurious)));
2892 
2893  // For each spurios reading to generate:
2894  // ------------------------------------------
2895  for (size_t i = 0; i < nSpurious; i++)
2896  {
2897  // Make up yaw,pitch,range out from thin air:
2898  // (the conditionals on yaw & pitch are to generate 2D observations if
2899  // we are in 2D, which we learn from a null std.dev.)
2900  const double range = getRandomGenerator().drawUniform(
2901  out_Observations.minSensorDistance,
2902  out_Observations.maxSensorDistance);
2903  const double yaw = (out_Observations.sensor_std_yaw == 0)
2904  ? 0
2906  -0.5f * out_Observations.fieldOfView_yaw,
2907  0.5f * out_Observations.fieldOfView_yaw);
2908  const double pitch =
2909  (out_Observations.sensor_std_pitch == 0)
2910  ? 0
2912  -0.5f * out_Observations.fieldOfView_pitch,
2913  0.5f * out_Observations.fieldOfView_pitch);
2914 
2915  // Fill out:
2916  newMeas.landmarkID =
2917  INVALID_LANDMARK_ID; // Always invalid ID since it's spurious
2918  newMeas.range = range;
2919  newMeas.yaw = yaw;
2920  newMeas.pitch = pitch;
2921 
2922  // Insert:
2923  out_Observations.sensedData.push_back(newMeas);
2924 
2925  if (out_real_associations)
2926  out_real_associations->push_back(
2927  std::string::npos); // Real index: spurious
2928  } // end for it
2929 
2930  // Done!
2931 }
#define CLASS_ID(T)
Access to runtime class ID for a defined class name.
Definition: CObject.h:84
#define IMPLEMENTS_SERIALIZABLE(class_name, base, NameSpace)
This must be inserted in all CSerializable classes implementation files.
auto dir
#define MAP_DEFINITION_REGISTER(_CLASSNAME_STRINGS, _CLASSNAME_WITH_NS)
Registers one map class into TMetricMapInitializer factory.
This class allows loading and storing values and vectors of different types from a configuration text...
A 2D grid of dynamic size which stores any kind of data at each cell.
Definition: CDynamicGrid.h:39
T * cellByIndex(unsigned int cx, unsigned int cy)
Returns a pointer to the contents of a cell given by its cell indexes, or nullptr if it is out of the...
Definition: CDynamicGrid.h:232
int y2idx(double y) const
Definition: CDynamicGrid.h:270
size_t getSizeX() const
Returns the horizontal size of grid map in cells count.
Definition: CDynamicGrid.h:252
size_t getSizeY() const
Returns the vertical size of grid map in cells count.
Definition: CDynamicGrid.h:254
int x2idx(double x) const
Transform a coordinate values into cell indexes.
Definition: CDynamicGrid.h:266
A class for storing images as grayscale or RGB bitmaps.
Definition: img/CImage.h:131
mrpt::math::CMatrixDouble33 intrinsicParams
Matrix of intrinsic parameters (containing the focal length and principal point coordinates)
Definition: TCamera.h:42
The class for storing "landmarks" (visual or laser-scan-extracted features,...)
Definition: CLandmark.h:34
int64_t TLandmarkID
The type for the IDs of landmarks.
Definition: CLandmark.h:39
mrpt::math::TPoint3D pose_mean
The mean of the landmark 3D position.
Definition: CLandmark.h:45
void createOneFeature()
Creates one feature in the vector "features", calling the appropriate constructor of the smart pointe...
Definition: CLandmark.h:109
uint32_t seenTimesCount
The number of times that this landmark has been seen.
Definition: CLandmark.h:77
void getPose(mrpt::poses::CPointPDFGaussian &p) const
Returns the pose as an object:
Definition: CLandmark.cpp:53
TLandmarkID ID
An ID for the landmark (see details next...) This ID was introduced in the version 3 of this class (2...
Definition: CLandmark.h:73
mrpt::math::TPoint3D normal
The "normal" to the landmark, i.e.
Definition: CLandmark.h:48
mrpt::system::TTimeStamp timestampLastSeen
The last time that this landmark was observed.
Definition: CLandmark.h:75
mrpt::vision::TFeatureType getType() const
Gets the type of the first feature in its feature vector.
Definition: CLandmark.h:98
void setPose(const mrpt::poses::CPointPDFGaussian &p)
Sets the pose from an object:
Definition: CLandmark.cpp:72
std::vector< mrpt::vision::CFeature::Ptr > features
The set of features from which the landmark comes.
Definition: CLandmark.h:42
A class for storing a map of 3D probabilistic landmarks.
Definition: CLandmarksMap.h:76
uint8_t serializeGetVersion() const override
Must return the current versioning number of the object.
void simulateRangeBearingReadings(const mrpt::poses::CPose3D &robotPose, const mrpt::poses::CPose3D &sensorLocationOnRobot, mrpt::obs::CObservationBearingRange &observations, bool sensorDetectsIDs=true, const float stdRange=0.01f, const float stdYaw=mrpt::DEG2RAD(0.1f), const float stdPitch=mrpt::DEG2RAD(0.1f), std::vector< size_t > *real_associations=nullptr, const double spurious_count_mean=0, const double spurious_count_std=0) const
Simulates a noisy bearing-range observation of all the beacons (landamrks with type glBeacon) in the ...
static std::map< std::pair< mrpt::maps::CLandmark::TLandmarkID, mrpt::maps::CLandmark::TLandmarkID >, double > _mEDD
Map of the Euclidean Distance between the descriptors of two SIFT-based landmarks.
void getAs3DObject(mrpt::opengl::CSetOfObjects::Ptr &outObj) const override
Returns a 3D object representing the map.
mrpt::maps::CLandmarksMap::TLikelihoodOptions likelihoodOptions
struct mrpt::maps::CLandmarksMap::TFuseOptions fuseOptions
static mrpt::maps::CLandmark::TLandmarkID _mapMaxID
float compute3DMatchingRatio(const mrpt::maps::CMetricMap *otherMap, const mrpt::poses::CPose3D &otherMapPose, const TMatchingRatioParams &params) const override
Computes the ratio in [0,1] of correspondences between "this" and the "otherMap" map,...
bool saveToMATLABScript3D(std::string file, const char *style="b", float confInterval=0.95f) const
Save to a MATLAB script which displays 3D error ellipses for the map.
virtual ~CLandmarksMap()
Virtual destructor.
bool saveToTextFile(std::string file)
Save to a text file.
mrpt::maps::CLandmark::TLandmarkID getMapMaxID()
void serializeFrom(mrpt::serialization::CArchive &in, uint8_t serial_version) override
Pure virtual method for reading (deserializing) from an abstract archive.
void computeMatchingWith2D(const mrpt::maps::CMetricMap *otherMap, const mrpt::poses::CPose2D &otherMapPose, float maxDistForCorrespondence, float maxAngularDistForCorrespondence, const mrpt::poses::CPose2D &angularDistPivotPoint, mrpt::tfest::TMatchingPairList &correspondences, float &correspondencesRatio, float *sumSqrDist=nullptr, bool onlyKeepTheClosest=false, bool onlyUniqueRobust=false) const
void simulateBeaconReadings(const mrpt::poses::CPose3D &in_robotPose, const mrpt::poses::CPoint3D &in_sensorLocationOnRobot, mrpt::obs::CObservationBeaconRanges &out_Observations) const
Simulates a noisy reading toward each of the beacons in the landmarks map, if any.
void saveMetricMapRepresentationToFile(const std::string &filNamePrefix) const override
This virtual method saves the map to a file "filNamePrefix"+< some_file_extension >,...
void internal_clear() override
Internal method called by clear()
bool isEmpty() const override
Returns true if the map is empty/no observation has been inserted.
void fuseWith(CLandmarksMap &other, bool justInsertAllOfThem=false)
Fuses the contents of another map with this one, updating "this" object with the result.
void loadOccupancyFeaturesFrom2DRangeScan(const mrpt::obs::CObservation2DRangeScan &obs, const mrpt::poses::CPose3D *robotPose=nullptr, unsigned int downSampleFactor=1)
Loads into this landmarks-map a set of occupancy features according to a 2D range scan (Previous cont...
double computeLikelihood_SIFT_LandmarkMap(CLandmarksMap *map, mrpt::tfest::TMatchingPairList *correspondences=nullptr, std::vector< bool > *otherCorrespondences=nullptr)
Returns the (logarithmic) likelihood of a set of landmarks "map" given "this" map.
bool internal_insertObservation(const mrpt::obs::CObservation *obs, const mrpt::poses::CPose3D *robotPose=nullptr) override
Internal method called by insertObservation()
void loadSiftFeaturesFromStereoImageObservation(const mrpt::obs::CObservationStereoImages &obs, mrpt::maps::CLandmark::TLandmarkID fID, const mrpt::vision::CFeatureExtraction::TOptions &feat_options=mrpt::vision::CFeatureExtraction::TOptions(mrpt::vision::featSIFT))
Loads into this landmarks map the SIFT features extracted from an observation consisting of a pair of...
size_t size() const
Returns the stored landmarks count.
mrpt::maps::CLandmarksMap::TInsertionOptions insertionOptions
double internal_computeObservationLikelihood(const mrpt::obs::CObservation *obs, const mrpt::poses::CPose3D &takenFrom) override
Computes the (logarithmic) likelihood that a given observation was taken from a given pose in the wor...
bool saveToMATLABScript2D(std::string file, const char *style="b", float stdCount=2.0f)
Save to a MATLAB script which displays 2D error ellipses for the map (top-view, projection on the XY ...
struct mrpt::maps::CLandmarksMap::TCustomSequenceLandmarks landmarks
void changeCoordinatesReference(const mrpt::poses::CPose3D &newOrg)
Changes the reference system of the map to a given 3D pose.
void loadSiftFeaturesFromImageObservation(const mrpt::obs::CObservationImage &obs, const mrpt::vision::CFeatureExtraction::TOptions &feat_options=mrpt::vision::CFeatureExtraction::TOptions(mrpt::vision::featSIFT))
Loads into this landmarks map the SIFT features extracted from an image observation (Previous content...
double computeLikelihood_RSLC_2007(const CLandmarksMap *s, const mrpt::poses::CPose2D &sensorPose)
Computes the (logarithmic) likelihood function for a sensed observation "o" according to "this" map.
void serializeTo(mrpt::serialization::CArchive &out) const override
Pure virtual method for writing (serializing) to an abstract archive.
virtual void auxParticleFilterCleanUp() override
This method is called at the end of each "prediction-update-map insertion" cycle within "mrpt::slam::...
void computeMatchingWith3DLandmarks(const mrpt::maps::CLandmarksMap *otherMap, mrpt::tfest::TMatchingPairList &correspondences, float &correspondencesRatio, std::vector< bool > &otherCorrespondences) const
Perform a search for correspondences between "this" and another lansmarks map: In this class,...
Declares a virtual base class for all metric maps storage classes.
Definition: CMetricMap.h:56
virtual const mrpt::rtti::TRuntimeClassId * GetRuntimeClass() const override
Returns information about the class of an object in runtime.
TMapGenericParams genericMapParams
Common params to all maps.
Definition: CMetricMap.h:280
void clear()
Erase all the contents of the map.
Definition: CMetricMap.cpp:31
bool enableSaveAs3DObject
(Default=true) If false, calling CMetricMap::getAs3DObject() will have no effects
This class is a "CSerializable" wrapper for "CMatrixTemplateNumeric<double>".
Definition: CMatrixD.h:24
A "CObservation"-derived class that represents a 2D range scan measurement (typically from a laser sc...
float aperture
The "aperture" or field-of-view of the range finder, in radians (typically M_PI = 180 degrees).
mrpt::containers::ContainerReadOnlyProxyAccessor< mrpt::aligned_std_vector< char > > validRange
It's false (=0) on no reflected rays, referenced to elements in scan.
mrpt::poses::CPose3D sensorPose
The 6D pose of the sensor on the robot at the moment of starting the scan.
bool rightToLeft
The scanning direction: true=counterclockwise; false=clockwise.
mrpt::containers::ContainerReadOnlyProxyAccessor< mrpt::aligned_std_vector< float > > scan
The range values of the scan, in meters.
Declares a class derived from "CObservation" that represents one (or more) range measurements to labe...
float stdError
The "sigma" of the sensor, assuming a zero-mean Gaussian noise model.
std::deque< TMeasurement > sensedData
The list of observed ranges.
This observation represents a number of range-bearing value pairs, each one for a detected landmark,...
TMeasurementList sensedData
The list of observed ranges:
float fieldOfView_pitch
Information about the sensor: The "field-of-view" of the sensor, in radians (for pitch ).
float sensor_std_range
Taken into account only if validCovariances=false: the standard deviation of the sensor noise model f...
bool validCovariances
True: The individual 3x3 covariance matrices must be taken into account, false (default): All the mea...
mrpt::poses::CPose3D sensorLocationOnRobot
The position of the sensor on the robot.
float fieldOfView_yaw
Information about the.
This class stores messages from GNSS or GNSS+IMU devices, from consumer-grade inexpensive GPS receive...
MSG_CLASS & getMsgByClass()
Returns a reference to the message in the list CObservationGPS::messages of the requested class.
internal_msg_test_proxy< gnss::NMEA_GGA > has_GGA_datum
Evaluates as a bool; true if the corresponding field exists in messages.
Declares a class that represents any robot's observation.
Definition: CObservation.h:44
mrpt::system::TTimeStamp timestamp
The associated UTC time-stamp.
Definition: CObservation.h:60
virtual const mrpt::rtti::TRuntimeClassId * GetRuntimeClass() const override
Returns information about the class of an object in runtime.
Declares a class derived from "CObservation" that encapsules an image from a camera,...
mrpt::img::CImage image
The image captured by the camera, that is, the main piece of information of this observation.
mrpt::img::TCamera cameraParams
Intrinsic and distortion parameters of the camera.
An observation providing an alternative robot pose from an external source.
mrpt::poses::CPose3DPDFGaussian pose
The observed robot pose.
mrpt::poses::CPose3D sensorPose
The pose of the sensor on the robot/vehicle.
Observation class for either a pair of left+right or left+disparity images from a stereo camera.
mrpt::poses::CPose3DQuat cameraPose
The pose of the LEFT camera, relative to the robot.
mrpt::img::CImage imageLeft
Image from the left camera (this image will be ALWAYS present)
mrpt::img::CImage imageRight
Image from the right camera, only contains a valid image if hasImageRight == true.
mrpt::img::TCamera leftCamera
Parameters for the left/right cameras: individual intrinsic and distortion parameters of the cameras.
mrpt::poses::CPose3DQuat rightCameraPose
The pose of the right camera, relative to the left one: Note that using the conventional reference co...
Declares a class derived from "CObservation" that stores a Landmarks Map as seen from a stereo camera...
mrpt::poses::CPose3D refCameraPose
The 3D pose of the reference camera relative to robot coordinates.
mrpt::maps::CLandmarksMap landmarks
The landmarks, with coordinates origin in the camera reference system.
std::shared_ptr< CEllipsoid > Ptr
Definition: CEllipsoid.h:47
std::shared_ptr< CGridPlaneXY > Ptr
Definition: CGridPlaneXY.h:32
This class allows the user to create, load, save, and render 3D scenes using OpenGL primitives.
Definition: COpenGLScene.h:60
bool saveToFile(const std::string &fil) const
Saves the scene to a 3Dscene file, loadable by the application SceneViewer3D.
void insert(const CRenderizable::Ptr &newObject, const std::string &viewportName=std::string("main"))
Insert a new object into the scene, in the given viewport (by default, into the "main" viewport).
std::shared_ptr< CSetOfObjects > Ptr
Definition: CSetOfObjects.h:28
A class used to store a 3D point.
Definition: CPoint3D.h:33
mrpt::math::TPoint3D asTPoint() const
Definition: CPoint3D.cpp:140
A gaussian distribution for 3D points.
mrpt::math::CMatrixDouble33 cov
The 3x3 covariance matrix.
double productIntegralNormalizedWith2D(const CPointPDFGaussian &p) const
Computes the "correspondence likelihood" of this PDF with another one: This is implemented as the int...
void bayesianFusion(const CPointPDFGaussian &p1, const CPointPDFGaussian &p2)
Bayesian fusion of two points gauss.
CPoint3D mean
The mean value.
A class used to store a 2D pose, including the 2D coordinate point and a heading (phi) angle.
Definition: CPose2D.h:39
A class used to store a 3D pose (a 3D translation + a rotation in 3D).
Definition: CPose3D.h:87
void sphericalCoordinates(const mrpt::math::TPoint3D &point, double &out_range, double &out_yaw, double &out_pitch) const
Computes the spherical coordinates of a 3D point as seen from the 6D pose specified by this object.
Definition: CPose3D.cpp:314
double pitch() const
Get the PITCH angle (in radians)
Definition: CPose3D.h:532
double roll() const
Get the ROLL angle (in radians)
Definition: CPose3D.h:538
void composePoint(double lx, double ly, double lz, double &gx, double &gy, double &gz, mrpt::math::CMatrixFixedNumeric< double, 3, 3 > *out_jacobian_df_dpoint=nullptr, mrpt::math::CMatrixFixedNumeric< double, 3, 6 > *out_jacobian_df_dpose=nullptr, mrpt::math::CMatrixFixedNumeric< double, 3, 6 > *out_jacobian_df_dse3=nullptr, bool use_small_rot_approx=false) const
An alternative, slightly more efficient way of doing with G and L being 3D points and P this 6D pose...
Definition: CPose3D.cpp:379
double yaw() const
Get the YAW angle (in radians)
Definition: CPose3D.h:526
void getHomogeneousMatrix(mrpt::math::CMatrixDouble44 &out_HM) const
Returns the corresponding 4x4 homogeneous transformation matrix for the point(translation) or pose (t...
Definition: CPose3D.h:221
mrpt::math::CMatrixDouble66 cov
The 6x6 covariance matrix.
double x() const
Common members of all points & poses classes.
Definition: CPoseOrPoint.h:140
double norm() const
Returns the euclidean norm of vector: .
Definition: CPoseOrPoint.h:253
double distanceTo(const CPoseOrPoint< OTHERCLASS > &b) const
Returns the Euclidean distance to another pose/point:
Definition: CPoseOrPoint.h:211
double drawGaussian1D_normalized()
Generate a normalized (mean=0, std=1) normally distributed sample.
double drawGaussian1D(const double mean, const double std)
Generate a normally distributed pseudo-random number.
double drawUniform(const double Min, const double Max)
Generate a uniformly distributed pseudo-random number using the MT19937 algorithm,...
Virtual base class for "archives": classes abstracting I/O streams.
Definition: CArchive.h:53
A list of TMatchingPair.
Definition: TMatchingPair.h:82
The central class from which images can be analyzed in search of different kinds of interest points a...
void detectFeatures(const mrpt::img::CImage &img, CFeatureList &feats, const unsigned int init_ID=0, const unsigned int nDesiredFeatures=0, const TImageROI &ROI=TImageROI()) const
Extract features from the image based on the method defined in TOptions.
TOptions options
Set all the parameters of the desired method here.
A list of visual features, to be used as output by detectors, as input/output by trackers,...
Definition: CFeature.h:305
TInternalFeatList::iterator iterator
Definition: CFeature.h:365
#define M_2PI
Definition: common.h:58
#define MRPT_UNUSED_PARAM(a)
Determines whether this is an X86 or AMD64 platform.
Definition: common.h:186
Scalar * iterator
Definition: eigen_plugins.h:26
EIGEN_STRONG_INLINE iterator begin()
Definition: eigen_plugins.h:29
const Scalar * const_iterator
Definition: eigen_plugins.h:27
#define MRPT_START
Definition: exceptions.h:262
#define ASSERT_(f)
Defines an assertion mechanism.
Definition: exceptions.h:113
#define MRPT_END
Definition: exceptions.h:266
#define MRPT_THROW_UNKNOWN_SERIALIZATION_VERSION(__V)
For use in CSerializable implementations.
Definition: exceptions.h:90
#define THROW_EXCEPTION(msg)
Definition: exceptions.h:41
#define MRPT_CHECK_NORMAL_NUMBER(v)
Throws an exception if the number is NaN, IND, or +/-INF, or return the same number otherwise.
Definition: exceptions.h:118
GLenum GLsizei n
Definition: glext.h:5074
GLsizei GLsizei GLuint * obj
Definition: glext.h:4070
GLuint GLuint end
Definition: glext.h:3528
GLenum GLint GLint y
Definition: glext.h:3538
GLenum GLsizei width
Definition: glext.h:3531
GLsizei range
Definition: glext.h:5907
GLuint in
Definition: glext.h:7274
GLenum GLint x
Definition: glext.h:3538
GLfloat GLfloat p
Definition: glext.h:6305
GLdouble s
Definition: glext.h:3676
GLenum const GLfloat * params
Definition: glext.h:3534
GLsizei const GLchar ** string
Definition: glext.h:4101
GLdouble GLdouble GLdouble GLdouble q
Definition: glext.h:3721
GLsizei GLsizei GLchar * source
Definition: glext.h:4082
T wrapToPi(T a)
Modifies the given angle to translate it into the ]-pi,pi] range.
Definition: wrap2pi.h:51
double distance(const TPoint2D &p1, const TPoint2D &p2)
Gets the distance between two points in a 2D space.
Definition: geometry.cpp:1891
CMatrixTemplateNumeric< T > generateAxisBaseFromDirection(T dx, T dy, T dz)
Computes an axis base (a set of three 3D normal vectors) with the given vector being the first of the...
Definition: geometry.h:1122
std::string format(const char *fmt,...) MRPT_printf_format_check(1
A std::string version of C sprintf.
Definition: format.cpp:16
#define INVALID_LANDMARK_ID
Used for CObservationBearingRange::TMeasurement::beaconID and others.
Definition: CObservation.h:27
long round_long(const T value)
Returns the closer integer (long) to x.
Definition: round.h:35
int void fclose(FILE *f)
An OS-independent version of fclose.
Definition: os.cpp:273
FILE * fopen(const char *fileName, const char *mode) noexcept
An OS-independent version of fopen.
Definition: os.cpp:255
int fprintf(FILE *fil, const char *format,...) noexcept MRPT_printf_format_check(2
An OS-independent version of fprintf.
Definition: os.cpp:406
size_t matchFeatures(const CFeatureList &list1, const CFeatureList &list2, CMatchedFeatureList &matches, const TMatchingOptions &options=TMatchingOptions(), const TStereoSystemParams &params=TStereoSystemParams())
Find the matches between two lists of features which must be of the same type.
void projectMatchedFeatures(const CMatchedFeatureList &matches, const mrpt::img::TStereoCamera &stereo_camera, std::vector< mrpt::math::TPoint3D > &out_points)
mrpt::math::TPoint3D pixelTo3D(const mrpt::img::TPixelCoordf &xy, const mrpt::math::CMatrixDouble33 &A)
Extract a UNITARY 3D vector in the direction of a 3D point, given from its (x,y) pixels coordinates,...
@ featBeacon
A especial case: this is not an image feature, but a 2D/3D beacon (used for range-only SLAM from mrpt...
@ featSIFT
Scale Invariant Feature Transform [LOWE'04].
@ featNotDefined
Non-defined feature (also used for Occupancy features)
#define INVALID_TIMESTAMP
Represents an invalid timestamp, where applicable.
Definition: datetime.h:43
mrpt::Clock::time_point TTimeStamp
A system independent time type, it holds the the number of 100-nanosecond intervals since January 1,...
Definition: datetime.h:40
mrpt::system::TTimeStamp getCurrentTime()
Returns the current (UTC) system time.
Definition: datetime.h:82
double extractDayTimeFromTimestamp(const mrpt::system::TTimeStamp t)
Returns the number of seconds ellapsed from midnight in the given timestamp.
Definition: datetime.cpp:192
std::vector< CLandmark > TSequenceLandmarks
Definition: CLandmarksMap.h:31
This base provides a set of functions for maths stuff.
Eigen::Matrix< typename MATRIX::Scalar, MATRIX::ColsAtCompileTime, MATRIX::ColsAtCompileTime > cov(const MATRIX &v)
Computes the covariance matrix from a list of samples in an NxM matrix, where each row is a sample,...
Definition: ops_matrices.h:148
CMatrixTemplateNumeric< double > CMatrixDouble
Declares a matrix of double numbers (non serializable).
CMatrixFixedNumeric< double, 3, 3 > CMatrixDouble33
Definition: eigen_frwds.h:57
This namespace contains representation of robot actions and observations.
Classes for 2D/3D geometry representation, both of single values and probability density distribution...
A namespace of pseudo-random numbers generators of diferent distributions.
CRandomGenerator & getRandomGenerator()
A static instance of a CRandomGenerator class, for use in single-thread applications.
Functions for estimating the optimal transformation between two frames of references given measuremen...
Classes for computer vision, detectors, features, etc.
Definition: CCamModel.h:19
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
T square(const T x)
Inline function for the square of a number.
double DEG2RAD(const double x)
Degrees to radians.
#define min(a, b)
unsigned __int32 uint32_t
Definition: rptypes.h:47
unsigned char uint8_t
Definition: rptypes.h:41
A pair (x,y) of pixel coordinates (subpixel resolution).
Definition: TPixelCoord.h:19
void push_back(const CLandmark &lm)
The object is copied, thus the original copy passed as a parameter can be released.
float getLargestDistanceFromOrigin() const
This method returns the largest distance from the origin to any of the points, such as a sphere cente...
const CLandmark * getByID(CLandmark::TLandmarkID ID) const
Returns the landmark with a given landmrk ID, or nullptr if not found.
const CLandmark * getByBeaconID(unsigned int ID) const
Returns the landmark with a given beacon ID, or nullptr if not found.
internal::TSequenceLandmarks::iterator iterator
internal::TSequenceLandmarks::const_iterator const_iterator
mrpt::containers::CDynamicGrid< std::vector< int32_t > > * getGrid()
float ellapsedTime
See "minTimesSeen".
unsigned int minTimesSeen
Required number of times of a landmark to be seen not to be removed, in "ellapsedTime" seconds.
float SiftCorrRatioThreshold
[For SIFT landmarks only] The ratio between the best and second best descriptor distances to set as c...
bool PLOT_IMAGES
Indicates if the images (as well as the SIFT detected features) should be shown in a window.
void loadFromConfigFile(const mrpt::config::CConfigFileBase &source, const std::string &section) override
This method load the options from a ".ini"-like file or memory-stored string list.
float SIFTs_epipolar_TH
Maximum distance (in pixels) from a point to a certain epipolar line to be considered a potential mat...
float SiftLikelihoodThreshold
[For SIFT landmarks only] The minimum likelihood value of a match to set as correspondence (Default=0...
bool insert_SIFTs_from_monocular_images
If set to true (default), the insertion of a CObservationImage in the map will insert SIFT 3D feature...
float SIFTsLoadEllipsoidWidth
[For SIFT landmarks only] The width (in meters, standard deviation) of the ellipsoid in the axis perp...
float SIFTs_stereo_maxDepth
Maximum depth of 3D landmarks when loading a landmarks map from a stereo image observation.
bool insert_Landmarks_from_range_scans
If set to true (default), inserting a CObservation2DRangeScan in the map will generate landmarks for ...
unsigned int SIFTMatching3DMethod
[For SIFT landmarks only] Method to compute 3D matching (Default = 0 (Our method)) 0: Our method -> E...
TInsertionOptions()
Initilization of default parameters.
float SIFTs_stdXY
[For SIFT landmarks only] The standard deviation (in pixels) for the SIFTs detector (This is used for...
mrpt::vision::CFeatureExtraction::TOptions SIFT_feat_options
Parameters of the SIFT feature detector/descriptors while inserting images in the landmark map.
unsigned int SIFTLikelihoodMethod
[For SIFT landmarks only] Method to compute the likelihood (Default = 0 (Our method)) 0: Our method -...
int SIFTs_numberOfKLTKeypoints
Number of points to extract in the image.
void dumpToTextStream(std::ostream &out) const override
This method should clearly display all the contents of the structure in textual form,...
float SiftEDDThreshold
[For SIFT landmarks only] The minimum Euclidean Descriptor Distance value of a match to set as corres...
float SIFTsLoadDistanceOfTheMean
[For SIFT landmarks only] The distance (in meters) of the mean value of landmarks,...
bool insert_SIFTs_from_stereo_images
If set to true (default), the insertion of a CObservationStereoImages in the map will insert SIFT 3D ...
double ang
These 3 params allow rotating and shifting GPS coordinates with other 2D maps (e.g.
unsigned int min_sat
Minimum number of sats to take into account the data.
mrpt::vision::CFeatureExtraction::TOptions SIFT_feat_options
Parameters of the SIFT feature detector/descriptors while inserting images in the landmark map.
bool beaconRangesUseObservationStd
(Default: false) If true, beaconRangesStd is ignored and each individual CObservationBeaconRanges::st...
float extRobotPoseStd
The standard deviation used for external robot poses likelihood (default=0.05) [meters].
float beaconRangesStd
The standard deviation used for Beacon ranges likelihood (default=0.08) [meters].
unsigned int rangeScan2D_decimation
The number of rays from a 2D range scan will be decimated by this factor (default = 1,...
struct mrpt::maps::CLandmarksMap::TLikelihoodOptions::TGPSOrigin GPSOrigin
int SIFTs_decimation
Considers 1 out of "SIFTs_decimation" visual landmarks in the observation during the likelihood compu...
void dumpToTextStream(std::ostream &out) const override
This method should clearly display all the contents of the structure in textual form,...
void loadFromConfigFile(const mrpt::config::CConfigFileBase &source, const std::string &section) override
This method load the options from a ".ini"-like file or memory-stored string list.
float GPS_sigma
A constant "sigma" for GPS localization data (in meters)
mrpt::maps::CLandmarksMap::TLikelihoodOptions likelihoodOpts
std::deque< TPairIdBeacon > initialBeacons
Initial contents of the map, especified by a set of 3D Beacons with associated IDs.
std::pair< mrpt::math::TPoint3D, unsigned int > TPairIdBeacon
mrpt::maps::CLandmarksMap::TInsertionOptions insertionOpts
Parameters for CMetricMap::compute3DMatchingRatio()
Virtual base for specifying the kind and parameters of one map (normally, to be inserted into mrpt::m...
Lightweight 3D point.
double x
X,Y,Z coordinates.
double norm() const
Point norm.
mrpt::poses::CPoint3D sensorLocationOnRobot
Position of the sensor on the robot.
int32_t beaconID
The ID of the sensed beacon (or INVALID_BEACON_ID if unknown)
float sensedDistance
The sensed range itself (in meters).
float range
The sensed landmark distance, in meters.
int32_t landmarkID
The ID of the sensed beacon, or INVALID_LANDMARK_ID (-1) if the sensor does not identify the landmark...
float yaw
The sensed landmark direction, in radians, measured as the yaw (azimuth) and pitch (negative elevatio...
double latitude_degrees
The measured latitude, in degrees (North:+ , South:-)
uint32_t satellitesUsed
The number of satelites used to compute this estimation.
double altitude_meters
The measured altitude, in meters (A).
double longitude_degrees
The measured longitude, in degrees (East:+ , West:-)
content_t fields
Message content, accesible by individual fields.
A structure for holding correspondences between two sets of points or points-like entities in 2D or 3...
Definition: TMatchingPair.h:32
The set of parameters for all the detectors & descriptor algorithms.
void loadFromConfigFile(const mrpt::config::CConfigFileBase &source, const std::string &section) override
This method load the options from a ".ini"-like file or memory-stored string list.
void dumpToTextStream(std::ostream &out) const override
This method should clearly display all the contents of the structure in textual form,...
A structure containing options for the matching.
float epipolar_TH
Epipolar constraint (rows of pixels)
@ mmDescriptorSIFT
Matching by Euclidean distance between SIFT descriptors.
float EDD_RATIO
Boundary Ratio between the two lowest EDD.
float maxEDD_TH
Maximum Euclidean Distance Between SIFT Descriptors.
TMatchingMethod matching_method
Matching method.
Parameters associated to a stereo system.
float stdDisp
Standard deviation of the error in disparity computation.
mrpt::math::CMatrixDouble33 K
Intrinsic parameters.
float stdPixel
Standard deviation of the error in feature detection.
string iniFile(myDataDir+string("benchmark-options.ini"))



Page generated by Doxygen 1.9.1 for MRPT 1.9.9 Git: 814d80880 Fri Aug 24 01:51:28 2018 +0200 at mar 26 may 2026 12:30:59 CEST