Main MRPT website > C++ reference for MRPT 1.9.9
CMonteCarloLocalization2D_unittest.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-2017, 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 
11 #include <mrpt/utils/CConfigFile.h>
14 #include <mrpt/maps/CSimpleMap.h>
15 #include <mrpt/obs/CRawlog.h>
16 #include <mrpt/system/filesystem.h>
17 #include <mrpt/system/os.h>
18 #include <mrpt/random.h>
19 #include <gtest/gtest.h>
20 
22 
23 using namespace mrpt;
24 using namespace mrpt::bayes;
25 using namespace mrpt::slam;
26 using namespace mrpt::maps;
27 using namespace mrpt::utils;
28 using namespace mrpt::poses;
29 using namespace mrpt::math;
30 using namespace mrpt::random;
31 using namespace mrpt::system;
32 using namespace mrpt::obs;
33 using namespace std;
34 
35 // Defined in tests/test_main.cpp
36 namespace mrpt
37 {
38 namespace utils
39 {
41 }
42 } // namespace mrpt
43 
45 {
46  // ------------------------------------------------------
47  // The code below is a simplification of the program "pf-localization"
48  // ------------------------------------------------------
49  const string ini_fil =
50  MRPT_GLOBAL_UNITTEST_SRC_DIR + string("/tests/montecarlo_test1.ini");
51  if (!mrpt::system::fileExists(ini_fil))
52  {
53  cerr << "WARNING: Skipping test due to missing file: " << ini_fil
54  << "\n";
55  return;
56  }
57 
58  CConfigFile iniFile(ini_fil);
59  vector_int particles_count; // Number of initial particles (if size>1, run
60  // the experiments N times)
61 
62  // Load configuration:
63  // -----------------------------------------
64  string iniSectionName("LocalizationExperiment");
65 
66  // Mandatory entries:
67  iniFile.read_vector(
68  iniSectionName, "particles_count", vector_int(1, 0), particles_count,
69  /*Fail if not found*/ true);
70  string RAWLOG_FILE = iniFile.read_string(
71  iniSectionName, "rawlog_file", "", /*Fail if not found*/ true);
72 
73  RAWLOG_FILE = MRPT_GLOBAL_UNITTEST_SRC_DIR + string("/") + RAWLOG_FILE;
74 
75  // Non-mandatory entries:
76  string MAP_FILE = iniFile.read_string(iniSectionName, "map_file", "");
77 
78  MAP_FILE = MRPT_GLOBAL_UNITTEST_SRC_DIR + string("/") + MAP_FILE;
79 
80  size_t rawlog_offset = iniFile.read_int(iniSectionName, "rawlog_offset", 0);
81  int NUM_REPS = iniFile.read_int(iniSectionName, "experimentRepetitions", 1);
82 
83  // PF-algorithm Options:
84  // ---------------------------
86  pfOptions.loadFromConfigFile(iniFile, "PF_options");
87 
88  // PDF Options:
89  // ------------------
90  TMonteCarloLocalizationParams pdfPredictionOptions;
91  pdfPredictionOptions.KLD_params.loadFromConfigFile(iniFile, "KLD_options");
92 
93  // Metric map options:
94  // -----------------------------
96  mapList.loadFromConfigFile(iniFile, "MetricMap");
97 
98  // --------------------------------------------------------------------
99  // EXPERIMENT PREPARATION
100  // --------------------------------------------------------------------
101  CTicTac tictac, tictacGlobal;
102  CSimpleMap simpleMap;
103  CRawlog rawlog;
104  size_t rawlogEntry, rawlogEntries;
106 
107  // Load the set of metric maps to consider in the experiments:
108  CMultiMetricMap metricMap;
109  metricMap.setListOfMaps(&mapList);
110 
112 
113  // Load the map (if any):
114  // -------------------------
115  if (MAP_FILE.size())
116  {
117  ASSERT_(fileExists(MAP_FILE));
118 
119  // Detect file extension:
120  // -----------------------------
121  string mapExt = lowerCase(extractFileExtension(
122  MAP_FILE, true)); // Ignore possible .gz extensions
123 
124  if (!mapExt.compare("simplemap"))
125  {
126  // It's a ".simplemap":
127  // -------------------------
128  CFileGZInputStream(MAP_FILE.c_str()) >> simpleMap;
129 
130  ASSERT_(simpleMap.size() > 0);
131 
132  // Build metric map:
133  // ------------------------------
134  metricMap.loadFromProbabilisticPosesAndObservations(simpleMap);
135  }
136  else if (!mapExt.compare("gridmap"))
137  {
138  // It's a ".gridmap":
139  // -------------------------
140  ASSERT_(metricMap.m_gridMaps.size() == 1);
141  CFileGZInputStream(MAP_FILE) >> (*metricMap.m_gridMaps[0]);
142  }
143  else
144  {
146  "Map file has unknown extension: '%s'", mapExt.c_str());
147  }
148  }
149 
150  // --------------------------
151  // Load the rawlog:
152  // --------------------------
153  rawlog.loadFromRawLogFile(RAWLOG_FILE);
154  rawlogEntries = rawlog.size();
155 
156  for (vector_int::iterator itNum = particles_count.begin();
157  itNum != particles_count.end(); ++itNum)
158  {
159  int PARTICLE_COUNT = *itNum;
160 
161  // Global stats for all the experiment loops:
162  vector<double> covergenceErrors;
163  covergenceErrors.reserve(NUM_REPS);
164  // --------------------------------------------------------------------
165  // EXPERIMENT REPETITIONS LOOP
166  // --------------------------------------------------------------------
167  tictacGlobal.Tic();
168  for (int repetition = 0; repetition < NUM_REPS; repetition++)
169  {
170  int M = PARTICLE_COUNT;
172 
173  // PDF Options:
174  pdf.options = pdfPredictionOptions;
175 
176  pdf.options.metricMap = &metricMap;
177 
178  // Create the PF object:
179  CParticleFilter PF;
180  PF.m_options = pfOptions;
181 
182  size_t step = 0;
183  rawlogEntry = 0;
184 
185  // Initialize the PDF:
186  // -----------------------------
187  tictac.Tic();
188  if (!iniFile.read_bool(
189  iniSectionName, "init_PDF_mode", false,
190  /*Fail if not found*/ true))
192  metricMap.m_gridMaps[0].get(), 0.7f, PARTICLE_COUNT,
193  iniFile.read_float(
194  iniSectionName, "init_PDF_min_x", 0, true),
195  iniFile.read_float(
196  iniSectionName, "init_PDF_max_x", 0, true),
197  iniFile.read_float(
198  iniSectionName, "init_PDF_min_y", 0, true),
199  iniFile.read_float(
200  iniSectionName, "init_PDF_max_y", 0, true),
201  DEG2RAD(iniFile.read_float(
202  iniSectionName, "init_PDF_min_phi_deg", -180)),
203  DEG2RAD(iniFile.read_float(
204  iniSectionName, "init_PDF_max_phi_deg", 180)));
205  else
207  iniFile.read_float(
208  iniSectionName, "init_PDF_min_x", 0, true),
209  iniFile.read_float(
210  iniSectionName, "init_PDF_max_x", 0, true),
211  iniFile.read_float(
212  iniSectionName, "init_PDF_min_y", 0, true),
213  iniFile.read_float(
214  iniSectionName, "init_PDF_max_y", 0, true),
215  DEG2RAD(iniFile.read_float(
216  iniSectionName, "init_PDF_min_phi_deg", -180)),
217  DEG2RAD(iniFile.read_float(
218  iniSectionName, "init_PDF_max_phi_deg", 180)),
219  PARTICLE_COUNT);
220 
221  // -----------------------------
222  // Particle filter
223  // -----------------------------
224  CActionCollection::Ptr action;
225  CSensoryFrame::Ptr observations;
226  bool end = false;
227 
228  // TTimeStamp cur_obs_timestamp;
229 
230  while (rawlogEntry < (rawlogEntries - 1) && !end)
231  {
232  // Load pose change from the rawlog:
233  // ----------------------------------------
234  if (!rawlog.getActionObservationPair(
235  action, observations, rawlogEntry))
236  THROW_EXCEPTION("End of rawlog");
237 
238  CPose2D expectedPose; // Ground truth
239 
240  // if (observations->size()>0)
241  // cur_obs_timestamp =
242  // observations->getObservationByIndex(0)->timestamp;
243 
244  if (step >= rawlog_offset)
245  {
246  // Do not execute the PF at "step=0", to let the initial PDF
247  // to be
248  // reflected in the logs.
249  if (step > rawlog_offset)
250  {
251  // ----------------------------------------
252  // RUN ONE STEP OF THE PARTICLE FILTER:
253  // ----------------------------------------
254  tictac.Tic();
255 
256  pdf.executeOn(
257  PF,
258  action.get(), // Action
259  observations.get(), // Obs.
260  &PF_stats, // Output statistics
261  pfOptions.PF_algorithm
262  );
263  }
264 
266  // cout << meanPose << " cov trace: " << cov.trace() <<
267  // endl;
268 
269  } // end if rawlog_offset
270 
271  step++;
272 
273  }; // while rawlogEntries
274  } // for repetitions
275  } // end of loop for different # of particles
276 }
277 
278 // TEST =================
279 TEST(MonteCarlo2D, RunSampleDataset)
280 {
281 #if MRPT_IS_BIG_ENDIAN
282  MRPT_TODO("Debug this issue in big endian platforms")
283  return; // Skip this test for now
284 #endif
285 
286  // Actual ending point:
287  const CPose2D GT_endpose(15.904, -10.010, DEG2RAD(4.93));
288 
289  // Placeholder for results:
290  CPose2D meanPose;
292 
293  // Invoke test:
294  // Give it 3 opportunities, since it might fail once for bad luck, or even
295  // twice in an extreme bad luck:
296  for (int op = 0; op < 3; op++)
297  {
298  run_test_pf_localization(meanPose, cov);
299 
300  const double final_pf_cov_trace = cov.trace();
301  const CPose2D final_pf_pose = meanPose;
302 
303  bool pass1 = (final_pf_pose - GT_endpose).norm() < 0.10;
304  bool pass2 = final_pf_cov_trace < 0.01;
305 
306  if (pass1 && pass2) return; // OK!
307 
308  // else: give it another try...
309  cout << "\n*Warning: Test failed. Will give it another chance, since "
310  "after all it's nondeterministic!\n";
311  }
312 
313  FAIL() << "Failed to converge after 3 opportunities!!" << endl;
314 }
void run_test_pf_localization(CPose2D &meanPose, CMatrixDouble33 &cov)
TEST(MonteCarlo2D, RunSampleDataset)
#define DEG2RAD
Definition: bits.h:112
This class acts as a common interface to the different interfaces (see CParticleFilter::TParticleFilt...
CParticleFilter::TParticleFilterOptions m_options
The options to be used in the PF, must be set before executing any step of the particle filter.
void loadFromProbabilisticPosesAndObservations(const mrpt::maps::CSimpleMap &Map)
Load the map contents from a CSimpleMap object, erasing all previous content of the map.
Definition: CMetricMap.cpp:37
This class stores any customizable set of metric maps.
void setListOfMaps(const mrpt::maps::TSetOfMetricMapInitializers *initializers)
Sets the list of internal map according to the passed list of map initializers (Current maps' content...
ProxyFilterContainerByClass< mrpt::maps::COccupancyGridMap2D::Ptr, TListMaps > m_gridMaps
STL-like proxy to access this kind of maps in maps.
This class stores a sequence of <Probabilistic Pose,SensoryFrame> pairs, thus a "metric map" can be t...
Definition: CSimpleMap.h:36
size_t size() const
Returns the count of pairs (pose,sensory data)
Definition: CSimpleMap.cpp:65
A set of TMetricMapInitializer structures, passed to the constructor CMultiMetricMap::CMultiMetricMap...
void loadFromConfigFile(const mrpt::utils::CConfigFileBase &source, const std::string &sectionName) override
Loads the configuration for the set of internal maps from a textual definition in an INI-like file.
std::shared_ptr< CActionCollection > Ptr
This class stores a rawlog (robotic datasets) in one of two possible formats:
Definition: CRawlog.h:69
bool getActionObservationPair(CActionCollection::Ptr &action, CSensoryFrame::Ptr &observations, size_t &rawlogEntry) const
Gets the next consecutive pair action / observation from the rawlog loaded into this object.
Definition: CRawlog.cpp:545
bool loadFromRawLogFile(const std::string &fileName, bool non_obs_objects_are_legal=false)
Load the contents from a file containing one of these possibilities:
Definition: CRawlog.cpp:206
size_t size() const
Returns the number of actions / observations object in the sequence.
Definition: CRawlog.cpp:88
std::shared_ptr< CSensoryFrame > Ptr
Definition: CSensoryFrame.h:56
A class used to store a 2D pose, including the 2D coordinate point and a heading (phi) angle.
Definition: CPose2D.h:41
void resetUniform(const double &x_min, const double &x_max, const double &y_min, const double &y_max, const double &phi_min=-M_PI, const double &phi_max=M_PI, const int &particlesCount=-1)
Reset the PDF to an uniformly distributed one, inside of the defined cube.
void getCovarianceAndMean(mrpt::math::CMatrixDouble33 &cov, CPose2D &mean_point) const override
Returns an estimate of the pose covariance matrix (3x3 cov matrix) and the mean, both at once.
void randomize(const uint32_t seed)
Initialize the PRNG from the given random seed.
Declares a class that represents a Probability Density Function (PDF) over a 2D pose (x,...
void executeOn(mrpt::bayes::CParticleFilter &pf, const mrpt::obs::CActionCollection *action, const mrpt::obs::CSensoryFrame *observation, mrpt::bayes::CParticleFilter::TParticleFilterStats *stats, mrpt::bayes::CParticleFilter::TParticleFilterAlgorithm PF_algorithm)
void resetUniformFreeSpace(mrpt::maps::COccupancyGridMap2D *theMap, const double freeCellsThreshold=0.7, const int particlesCount=-1, const double x_min=-1e10f, const double x_max=1e10f, const double y_min=-1e10f, const double y_max=1e10f, const double phi_min=-M_PI, const double phi_max=M_PI)
Reset the PDF to an uniformly distributed one, but only in the free-space of a given 2D occupancy-gri...
TMonteCarloLocalizationParams options
MCL parameters.
mrpt::poses::CPosePDFParticles m_poseParticles
void loadFromConfigFile(const mrpt::utils::CConfigFileBase &source, const std::string &section) override
This method load the options from a ".ini"-like file or memory-stored string list.
Definition: TKLDParams.cpp:57
void read_vector(const std::string &section, const std::string &name, const VECTOR_TYPE &defaultValue, VECTOR_TYPE &outValues, bool failIfNotFound=false) const
Reads a configuration parameter of type vector, stored in the file as a string: "[v1 v2 v3 ....
bool read_bool(const std::string &section, const std::string &name, bool defaultValue, bool failIfNotFound=false) const
std::string read_string(const std::string &section, const std::string &name, const std::string &defaultValue, bool failIfNotFound=false) const
int read_int(const std::string &section, const std::string &name, int defaultValue, bool failIfNotFound=false) const
float read_float(const std::string &section, const std::string &name, float defaultValue, bool failIfNotFound=false) const
This class allows loading and storing values and vectors of different types from "....
Definition: CConfigFile.h:36
Transparently opens a compressed "gz" file and reads uncompressed data from it.
This class implements a high-performance stopwatch.
Definition: CTicTac.h:24
void Tic()
Starts the stopwatch.
Definition: CTicTac.cpp:82
Scalar * iterator
Definition: eigen_plugins.h:26
GLuint GLuint end
Definition: glext.h:3528
GLsizei const GLchar ** string
Definition: glext.h:4101
std::string extractFileExtension(const std::string &filePath, bool ignore_gz=false)
Extract the extension of a filename.
Definition: filesystem.cpp:97
bool fileExists(const std::string &fileName)
Test if a given file (or directory) exists.
Definition: filesystem.cpp:127
std::vector< int32_t > vector_int
Definition: types_simple.h:24
std::string lowerCase(const std::string &str)
Returns an lower-case version of a string.
#define MRPT_TODO(x)
Definition: mrpt_macros.h:82
#define ASSERT_(f)
Definition: mrpt_macros.h:309
#define THROW_EXCEPTION(msg)
Definition: mrpt_macros.h:111
#define THROW_EXCEPTION_FMT(_FORMAT_STRING,...)
Definition: mrpt_macros.h:121
The namespace for Bayesian filtering algorithm: different particle filters and Kalman filter algorith...
This base provides a set of functions for maths stuff.
Definition: CArrayNumeric.h:20
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
CONTAINER::Scalar norm(const CONTAINER &v)
This namespace contains representation of robot actions and observations.
Classes for 2D/3D geometry representation, both of single values and probability density distribution...
Definition: CPoint.h:18
A namespace of pseudo-random numbers genrators of diferent distributions.
CRandomGenerator & getRandomGenerator()
A static instance of a CRandomGenerator class, for use in single-thread applications.
This namespace provides a OS-independent interface to many useful functions: filenames manipulation,...
Definition: math_frwds.h:31
Classes for serialization, sockets, ini-file manipulation, streams, list of properties-values,...
std::string MRPT_GLOBAL_UNITTEST_SRC_DIR
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
The configuration of a particle filter.
TParticleFilterAlgorithm PF_algorithm
The PF algorithm to use (default=pfStandardProposal) See TParticleFilterAlgorithm for the posibilitie...
void loadFromConfigFile(const mrpt::utils::CConfigFileBase &source, const std::string &section) override
This method load the options from a ".ini"-like file or memory-stored string list.
Statistics for being returned from the "execute" method.
The struct for passing extra simulation parameters to the prediction stage when running a particle fi...
TKLDParams KLD_params
Parameters for dynamic sample size, KLD method.
mrpt::maps::CMetricMap * metricMap
[update stage] Must be set to a metric map used to estimate the likelihood of observations



Page generated by Doxygen 1.9.1 for MRPT 1.9.9 Git: 63ea9d1f1 Thu Nov 23 00:06:53 2017 +0100 at mar 26 may 2026 12:19:29 CEST