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 }
void clear()
Erase all the contents of the map.
Definition: CMetricMap.cpp:31
void getAs3DObject(mrpt::opengl::CSetOfObjects::Ptr &outObj) const override
Returns a 3D object representing the map.
A namespace of pseudo-random numbers generators of diferent distributions.
float fieldOfView_yaw
Information about the.
double drawUniform(const double Min, const double Max)
Generate a uniformly distributed pseudo-random number using the MT19937 algorithm, scaled to the selected range.
float EDD_RATIO
Boundary Ratio between the two lowest EDD.
internal::TSequenceLandmarks::iterator iterator
double x() const
Common members of all points & poses classes.
Definition: CPoseOrPoint.h:140
GLsizei range
Definition: glext.h:5907
Virtual base for specifying the kind and parameters of one map (normally, to be inserted into mrpt::m...
Scalar * iterator
Definition: eigen_plugins.h:26
Parameters for CMetricMap::compute3DMatchingRatio()
float SiftEDDThreshold
[For SIFT landmarks only] The minimum Euclidean Descriptor Distance value of a match to set as corres...
GLuint GLuint GLsizei count
Definition: glext.h:3528
Non-defined feature (also used for Occupancy features)
Declares a class derived from "CObservation" that encapsules an image from a camera, whose relative pose to robot is also stored.
size_t size() const
Returns the stored landmarks count.
mrpt::maps::CLandmarksMap::TInsertionOptions insertionOpts
#define MRPT_START
Definition: exceptions.h:262
int y2idx(double y) const
Definition: CDynamicGrid.h:270
CPose3D mean
The mean value.
A 2D grid of dynamic size which stores any kind of data at each cell.
Definition: CDynamicGrid.h:38
bool insert_SIFTs_from_stereo_images
If set to true (default), the insertion of a CObservationStereoImages in the map will insert SIFT 3D ...
#define min(a, b)
This class is a "CSerializable" wrapper for "CMatrixTemplateNumeric<double>".
Definition: CMatrixD.h:22
void createOneFeature()
Creates one feature in the vector "features", calling the appropriate constructor of the smart pointe...
Definition: CLandmark.h:109
std::vector< mrpt::vision::CFeature::Ptr > features
The set of features from which the landmark comes.
Definition: CLandmark.h:42
float range
The sensed landmark distance, in meters.
double latitude_degrees
The measured latitude, in degrees (North:+ , South:-)
TInternalFeatList::iterator iterator
Definition: CFeature.h:365
mrpt::img::CImage imageLeft
Image from the left camera (this image will be ALWAYS present)
#define M_2PI
Definition: common.h:58
double distanceTo(const CPoseOrPoint< OTHERCLASS > &b) const
Returns the Euclidean distance to another pose/point:
Definition: CPoseOrPoint.h:211
#define THROW_EXCEPTION(msg)
Definition: exceptions.h:41
unsigned int SIFTLikelihoodMethod
[For SIFT landmarks only] Method to compute the likelihood (Default = 0 (Our method)) 0: Our method -...
bool enableSaveAs3DObject
(Default=true) If false, calling CMetricMap::getAs3DObject() will have no effects ...
float beaconRangesStd
The standard deviation used for Beacon ranges likelihood (default=0.08) [meters]. ...
const CLandmark * getByID(CLandmark::TLandmarkID ID) const
Returns the landmark with a given landmrk ID, or nullptr if not found.
int void fclose(FILE *f)
An OS-independent version of fclose.
Definition: os.cpp:273
mrpt::system::TTimeStamp getCurrentTime()
Returns the current (UTC) system time.
Definition: datetime.h:82
uint8_t serializeGetVersion() const override
Must return the current versioning number of the object.
#define IMPLEMENTS_SERIALIZABLE(class_name, base, NameSpace)
This must be inserted in all CSerializable classes implementation files.
CPoint3D mean
The mean value.
float SIFTs_stereo_maxDepth
Maximum depth of 3D landmarks when loading a landmarks map from a stereo image observation.
double DEG2RAD(const double x)
Degrees to radians.
void fuseWith(CLandmarksMap &other, bool justInsertAllOfThem=false)
Fuses the contents of another map with this one, updating "this" object with the result.
GLdouble GLdouble GLdouble GLdouble q
Definition: glext.h:3721
long round_long(const T value)
Returns the closer integer (long) to x.
Definition: round.h:35
GLenum GLsizei n
Definition: glext.h:5074
Declares a class derived from "CObservation" that stores a Landmarks Map as seen from a stereo camera...
uint32_t satellitesUsed
The number of satelites used to compute this estimation.
struct mrpt::maps::CLandmarksMap::TFuseOptions fuseOptions
TOptions options
Set all the parameters of the desired method here.
double norm() const
Point norm.
EIGEN_STRONG_INLINE iterator begin()
Definition: eigen_plugins.h:29
float extRobotPoseStd
The standard deviation used for external robot poses likelihood (default=0.05) [meters].
double extractDayTimeFromTimestamp(const mrpt::system::TTimeStamp t)
Returns the number of seconds ellapsed from midnight in the given timestamp.
Definition: datetime.cpp:192
An observation providing an alternative robot pose from an external source.
double pitch() const
Get the PITCH angle (in radians)
Definition: CPose3D.h:532
double yaw() const
Get the YAW angle (in radians)
Definition: CPose3D.h:526
The set of parameters for all the detectors & descriptor algorithms.
Declares a class derived from "CObservation" that represents one (or more) range measurements to labe...
A pair (x,y) of pixel coordinates (subpixel resolution).
Definition: TPixelCoord.h:18
void dumpToTextStream(std::ostream &out) const override
This method should clearly display all the contents of the structure in textual form, sending it to a std::ostream.
int32_t beaconID
The ID of the sensed beacon (or INVALID_BEACON_ID if unknown)
STL namespace.
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.
TMapGenericParams genericMapParams
Common params to all maps.
Definition: CMetricMap.h:280
void dumpToTextStream(std::ostream &out) const override
This method should clearly display all the contents of the structure in textual form, sending it to a std::ostream.
float epipolar_TH
Epipolar constraint (rows of pixels)
GLdouble s
Definition: glext.h:3676
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.
GLsizei GLsizei GLuint * obj
Definition: glext.h:4070
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 serializeFrom(mrpt::serialization::CArchive &in, uint8_t serial_version) override
Pure virtual method for reading (deserializing) from an abstract archive.
mrpt::poses::CPose3D sensorPose
The pose of the sensor on the robot/vehicle.
const CLandmark * getByBeaconID(unsigned int ID) const
Returns the landmark with a given beacon ID, or nullptr if not found.
void saveMetricMapRepresentationToFile(const std::string &filNamePrefix) const override
This virtual method saves the map to a file "filNamePrefix"+< some_file_extension >...
double drawGaussian1D(const double mean, const double std)
Generate a normally distributed pseudo-random number.
GLenum GLsizei width
Definition: glext.h:3531
mrpt::containers::ContainerReadOnlyProxyAccessor< mrpt::aligned_std_vector< char > > validRange
It&#39;s false (=0) on no reflected rays, referenced to elements in scan.
void internal_clear() override
Internal method called by clear()
std::vector< CLandmark > TSequenceLandmarks
Definition: CLandmarksMap.h:31
bool beaconRangesUseObservationStd
(Default: false) If true, beaconRangesStd is ignored and each individual CObservationBeaconRanges::st...
static mrpt::maps::CLandmark::TLandmarkID _mapMaxID
float stdPixel
Standard deviation of the error in feature detection.
unsigned char uint8_t
Definition: rptypes.h:41
int64_t TLandmarkID
The type for the IDs of landmarks.
Definition: CLandmark.h:39
float yaw
The sensed landmark direction, in radians, measured as the yaw (azimuth) and pitch (negative elevatio...
#define MRPT_THROW_UNKNOWN_SERIALIZATION_VERSION(__V)
For use in CSerializable implementations.
Definition: exceptions.h:90
bool insert_SIFTs_from_monocular_images
If set to true (default), the insertion of a CObservationImage in the map will insert SIFT 3D feature...
T square(const T x)
Inline function for the square of a number.
mrpt::poses::CPose3DQuat cameraPose
The pose of the LEFT camera, relative to the robot.
mrpt::math::CMatrixDouble33 intrinsicParams
Matrix of intrinsic parameters (containing the focal length and principal point coordinates) ...
Definition: TCamera.h:42
int32_t landmarkID
The ID of the sensed beacon, or INVALID_LANDMARK_ID (-1) if the sensor does not identify the landmark...
#define ASSERT_(f)
Defines an assertion mechanism.
Definition: exceptions.h:113
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
void bayesianFusion(const CPointPDFGaussian &p1, const CPointPDFGaussian &p2)
Bayesian fusion of two points gauss.
mrpt::maps::CLandmark::TLandmarkID getMapMaxID()
double altitude_meters
The measured altitude, in meters (A).
float SIFTsLoadDistanceOfTheMean
[For SIFT landmarks only] The distance (in meters) of the mean value of landmarks, for the initial position PDF (Default = 3m)
Matching by Euclidean distance between SIFT descriptors.
int SIFTs_numberOfKLTKeypoints
Number of points to extract in the image.
This class allows loading and storing values and vectors of different types from a configuration text...
This base provides a set of functions for maths stuff.
void setPose(const mrpt::poses::CPointPDFGaussian &p)
Sets the pose from an object:
Definition: CLandmark.cpp:72
#define CLASS_ID(T)
Access to runtime class ID for a defined class name.
Definition: CObject.h:84
int SIFTs_decimation
Considers 1 out of "SIFTs_decimation" visual landmarks in the observation during the likelihood compu...
A class for storing a map of 3D probabilistic landmarks.
Definition: CLandmarksMap.h:75
float getLargestDistanceFromOrigin() const
This method returns the largest distance from the origin to any of the points, such as a sphere cente...
mrpt::img::CImage image
The image captured by the camera, that is, the main piece of information of this observation.
#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
mrpt::containers::ContainerReadOnlyProxyAccessor< mrpt::aligned_std_vector< float > > scan
The range values of the scan, in meters.
double norm() const
Returns the euclidean norm of vector: .
Definition: CPoseOrPoint.h:253
Parameters associated to a stereo system.
mrpt::math::CMatrixDouble33 cov
The 3x3 covariance matrix.
void push_back(const CLandmark &lm)
The object is copied, thus the original copy passed as a parameter can be released.
CMatrixTemplateNumeric< double > CMatrixDouble
Declares a matrix of double numbers (non serializable).
float SIFTs_stdXY
[For SIFT landmarks only] The standard deviation (in pixels) for the SIFTs detector (This is used for...
Scale Invariant Feature Transform [LOWE&#39;04].
std::pair< mrpt::math::TPoint3D, unsigned int > TPairIdBeacon
std::deque< TMeasurement > sensedData
The list of observed ranges.
GLuint GLuint end
Definition: glext.h:3528
A list of TMatchingPair.
Definition: TMatchingPair.h:81
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 longitude_degrees
The measured longitude, in degrees (East:+ , West:-)
Observation class for either a pair of left+right or left+disparity images from a stereo camera...
float fieldOfView_pitch
Information about the sensor: The "field-of-view" of the sensor, in radians (for pitch )...
virtual ~CLandmarksMap()
Virtual destructor.
This namespace contains representation of robot actions and observations.
string iniFile(myDataDir+string("benchmark-options.ini"))
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.
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.
Classes for computer vision, detectors, features, etc.
Definition: CCamModel.h:18
double x
X,Y,Z coordinates.
void getPose(mrpt::poses::CPointPDFGaussian &p) const
Returns the pose as an object:
Definition: CLandmark.cpp:53
mrpt::img::TCamera cameraParams
Intrinsic and distortion parameters of the camera.
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
void serializeTo(mrpt::serialization::CArchive &out) const override
Pure virtual method for writing (serializing) to an abstract archive.
size_t getSizeX() const
Returns the horizontal size of grid map in cells count.
Definition: CDynamicGrid.h:252
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...
GLsizei const GLchar ** string
Definition: glext.h:4101
T wrapToPi(T a)
Modifies the given angle to translate it into the ]-pi,pi] range.
Definition: wrap2pi.h:51
MSG_CLASS & getMsgByClass()
Returns a reference to the message in the list CObservationGPS::messages of the requested class...
A class used to store a 3D point.
Definition: CPoint3D.h:31
A list of visual features, to be used as output by detectors, as input/output by trackers, etc.
Definition: CFeature.h:304
Classes for 2D/3D geometry representation, both of single values and probability density distribution...
double roll() const
Get the ROLL angle (in radians)
Definition: CPose3D.h:538
float stdError
The "sigma" of the sensor, assuming a zero-mean Gaussian noise model.
mrpt::system::TTimeStamp timestampLastSeen
The last time that this landmark was observed.
Definition: CLandmark.h:75
A structure for holding correspondences between two sets of points or points-like entities in 2D or 3...
Definition: TMatchingPair.h:31
bool saveToFile(const std::string &fil) const
Saves the scene to a 3Dscene file, loadable by the application SceneViewer3D.
mrpt::poses::CPose3D sensorLocationOnRobot
The position of the sensor on the robot.
void changeCoordinatesReference(const mrpt::poses::CPose3D &newOrg)
Changes the reference system of the map to a given 3D pose.
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.
mrpt::vision::CFeatureExtraction::TOptions SIFT_feat_options
Parameters of the SIFT feature detector/descriptors while inserting images in the landmark map...
size_t getSizeY() const
Returns the vertical size of grid map in cells count.
Definition: CDynamicGrid.h:254
mrpt::maps::CLandmarksMap::TInsertionOptions insertionOptions
unsigned int minTimesSeen
Required number of times of a landmark to be seen not to be removed, in "ellapsedTime" seconds...
int fprintf(FILE *fil, const char *format,...) noexcept MRPT_printf_format_check(2
An OS-independent version of fprintf.
Definition: os.cpp:406
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.
mrpt::math::TPoint3D asTPoint() const
Definition: CPoint3D.cpp:140
bool saveToTextFile(std::string file)
Save to a text file.
float sensedDistance
The sensed range itself (in meters).
unsigned int rangeScan2D_decimation
The number of rays from a 2D range scan will be decimated by this factor (default = 1...
mrpt::math::CMatrixDouble66 cov
The 6x6 covariance matrix.
mrpt::maps::CLandmarksMap::TLikelihoodOptions likelihoodOpts
mrpt::poses::CPose3D refCameraPose
The 3D pose of the reference camera relative to robot coordinates.
auto dir
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
The class for storing "landmarks" (visual or laser-scan-extracted features,...)
Definition: CLandmark.h:33
#define MAP_DEFINITION_REGISTER(_CLASSNAME_STRINGS, _CLASSNAME_WITH_NS)
Registers one map class into TMetricMapInitializer factory.
mrpt::system::TTimeStamp timestamp
The associated UTC time-stamp.
Definition: CObservation.h:60
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:1111
A "CObservation"-derived class that represents a 2D range scan measurement (typically from a laser sc...
virtual const mrpt::rtti::TRuntimeClassId * GetRuntimeClass() const override
Returns information about the class of an object in runtime.
mrpt::poses::CPose3DPDFGaussian pose
The observed robot pose.
double productIntegralNormalizedWith2D(const CPointPDFGaussian &p) const
Computes the "correspondence likelihood" of this PDF with another one: This is implemented as the int...
virtual const mrpt::rtti::TRuntimeClassId * GetRuntimeClass() const override
Returns information about the class of an object in runtime.
Virtual base class for "archives": classes abstracting I/O streams.
Definition: CArchive.h:52
float ellapsedTime
See "minTimesSeen".
internal_msg_test_proxy< gnss::NMEA_GGA > has_GGA_datum
Evaluates as a bool; true if the corresponding field exists in messages.
Declares a virtual base class for all metric maps storage classes.
Definition: CMetricMap.h:54
A class used to store a 2D pose, including the 2D coordinate point and a heading (phi) angle...
Definition: CPose2D.h:38
bool PLOT_IMAGES
Indicates if the images (as well as the SIFT detected features) should be shown in a window...
A class used to store a 3D pose (a 3D translation + a rotation in 3D).
Definition: CPose3D.h:86
Declares a class that represents any robot&#39;s observation.
Definition: CObservation.h:43
mrpt::math::TPoint3D normal
The "normal" to the landmark, i.e.
Definition: CLandmark.h:48
std::deque< TPairIdBeacon > initialBeacons
Initial contents of the map, especified by a set of 3D Beacons with associated IDs.
float SIFTsLoadEllipsoidWidth
[For SIFT landmarks only] The width (in meters, standard deviation) of the ellipsoid in the axis perp...
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...
std::string format(const char *fmt,...) MRPT_printf_format_check(1
A std::string version of C sprintf.
Definition: format.cpp:16
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
mrpt::containers::CDynamicGrid< std::vector< int32_t > > * getGrid()
mrpt::poses::CPose3DQuat rightCameraPose
The pose of the right camera, relative to the left one: Note that using the conventional reference co...
mrpt::vision::TFeatureType getType() const
Gets the type of the first feature in its feature vector.
Definition: CLandmark.h:98
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.
#define MRPT_END
Definition: exceptions.h:266
CMatrixFixedNumeric< double, 3, 3 > CMatrixDouble33
Definition: eigen_frwds.h:57
This observation represents a number of range-bearing value pairs, each one for a detected landmark...
A structure containing options for the matching.
bool internal_insertObservation(const mrpt::obs::CObservation *obs, const mrpt::poses::CPose3D *robotPose=nullptr) override
Internal method called by insertObservation()
GLuint in
Definition: glext.h:7274
TInsertionOptions()
Initilization of default parameters.
mrpt::maps::CLandmarksMap landmarks
The landmarks, with coordinates origin in the camera reference system.
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...
content_t fields
Message content, accesible by individual fields.
This class allows the user to create, load, save, and render 3D scenes using OpenGL primitives...
Definition: COpenGLScene.h:59
GLsizei GLsizei GLchar * source
Definition: glext.h:4082
float aperture
The "aperture" or field-of-view of the range finder, in radians (typically M_PI = 180 degrees)...
mrpt::poses::CPoint3D sensorLocationOnRobot
Position of the sensor on the robot.
int x2idx(double x) const
Transform a coordinate values into cell indexes.
Definition: CDynamicGrid.h:266
#define INVALID_LANDMARK_ID
Used for CObservationBearingRange::TMeasurement::beaconID and others.
Definition: CObservation.h:27
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
virtual void auxParticleFilterCleanUp() override
This method is called at the end of each "prediction-update-map insertion" cycle within "mrpt::slam::...
void dumpToTextStream(std::ostream &out) const override
This method should clearly display all the contents of the structure in textual form, sending it to a std::ostream.
GLenum GLint GLint y
Definition: glext.h:3538
bool insert_Landmarks_from_range_scans
If set to true (default), inserting a CObservation2DRangeScan in the map will generate landmarks for ...
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...
FILE * fopen(const char *fileName, const char *mode) noexcept
An OS-independent version of fopen.
Definition: os.cpp:255
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
float maxEDD_TH
Maximum Euclidean Distance Between SIFT Descriptors.
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 ...
internal::TSequenceLandmarks::const_iterator const_iterator
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 ...
A especial case: this is not an image feature, but a 2D/3D beacon (used for range-only SLAM from mrpt...
bool validCovariances
True: The individual 3x3 covariance matrices must be taken into account, false (default): All the mea...
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.
struct mrpt::maps::CLandmarksMap::TLikelihoodOptions::TGPSOrigin GPSOrigin
GLenum GLint x
Definition: glext.h:3538
mrpt::math::TPoint3D pose_mean
The mean of the landmark 3D position.
Definition: CLandmark.h:45
Lightweight 3D point.
float SIFTs_epipolar_TH
Maximum distance (in pixels) from a point to a certain epipolar line to be considered a potential mat...
void projectMatchedFeatures(const CMatchedFeatureList &matches, const mrpt::img::TStereoCamera &stereo_camera, std::vector< mrpt::math::TPoint3D > &out_points)
TMatchingMethod matching_method
Matching method.
This class stores messages from GNSS or GNSS+IMU devices, from consumer-grade inexpensive GPS receive...
float SiftLikelihoodThreshold
[For SIFT landmarks only] The minimum likelihood value of a match to set as correspondence (Default=0...
unsigned __int32 uint32_t
Definition: rptypes.h:47
mrpt::vision::CFeatureExtraction::TOptions SIFT_feat_options
Parameters of the SIFT feature detector/descriptors while inserting images in the landmark map...
float sensor_std_range
Taken into account only if validCovariances=false: the standard deviation of the sensor noise model f...
CRandomGenerator & getRandomGenerator()
A static instance of a CRandomGenerator class, for use in single-thread applications.
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)...
mrpt::img::TCamera leftCamera
Parameters for the left/right cameras: individual intrinsic and distortion parameters of the cameras...
Functions for estimating the optimal transformation between two frames of references given measuremen...
GLfloat GLfloat p
Definition: glext.h:6305
double ang
These 3 params allow rotating and shifting GPS coordinates with other 2D maps (e.g.
GLenum const GLfloat * params
Definition: glext.h:3534
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...
const Scalar * const_iterator
Definition: eigen_plugins.h:27
mrpt::poses::CPose3D sensorPose
The 6D pose of the sensor on the robot at the moment of starting the scan.
float SiftCorrRatioThreshold
[For SIFT landmarks only] The ratio between the best and second best descriptor distances to set as c...
bool isEmpty() const override
Returns true if the map is empty/no observation has been inserted.
uint32_t seenTimesCount
The number of times that this landmark has been seen.
Definition: CLandmark.h:77
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...
struct mrpt::maps::CLandmarksMap::TCustomSequenceLandmarks landmarks
#define INVALID_TIMESTAMP
Represents an invalid timestamp, where applicable.
Definition: datetime.h:43
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
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 distance(const TPoint2D &p1, const TPoint2D &p2)
Gets the distance between two points in a 2D space.
Definition: geometry.cpp:1891
mrpt::img::CImage imageRight
Image from the right camera, only contains a valid image if hasImageRight == true.
unsigned int min_sat
Minimum number of sats to take into account the data.
A gaussian distribution for 3D points.
float GPS_sigma
A constant "sigma" for GPS localization data (in meters)
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, whose 6D pose relative to "this" is "otherMapPose" In the case of a multi-metric map, this returns the average between the maps.
A class for storing images as grayscale or RGB bitmaps.
Definition: img/CImage.h:130
bool rightToLeft
The scanning direction: true=counterclockwise; false=clockwise.
float stdDisp
Standard deviation of the error in disparity computation.
The central class from which images can be analyzed in search of different kinds of interest points a...
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
TMeasurementList sensedData
The list of observed ranges:
double drawGaussian1D_normalized()
Generate a normalized (mean=0, std=1) normally distributed sample.
mrpt::math::CMatrixDouble33 K
Intrinsic parameters.
#define MRPT_UNUSED_PARAM(a)
Determines whether this is an X86 or AMD64 platform.
Definition: common.h:186
mrpt::maps::CLandmarksMap::TLikelihoodOptions likelihoodOptions
A list of features.
Definition: CFeature.h:503
unsigned int SIFTMatching3DMethod
[For SIFT landmarks only] Method to compute 3D matching (Default = 0 (Our method)) 0: Our method -> E...



Page generated by Doxygen 1.8.14 for MRPT 1.9.9 Git: 7d5e6d718 Fri Aug 24 01:51:28 2018 +0200 at lun nov 2 08:35:50 CET 2020