Main MRPT website > C++ reference for MRPT 1.9.9
CMonteCarloLocalization2D.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 
10 #include "slam-precomp.h" // Precompiled headerss
11 
13 
14 #include <mrpt/utils/CTicTac.h>
17 #include <mrpt/obs/CSensoryFrame.h>
18 
19 #include <mrpt/random.h>
20 
22 
24 
25 using namespace mrpt;
26 using namespace mrpt::bayes;
27 using namespace mrpt::poses;
28 using namespace mrpt::math;
29 using namespace mrpt::maps;
30 using namespace mrpt::obs;
31 using namespace mrpt::slam;
32 using namespace mrpt::random;
33 using namespace mrpt::utils;
34 using namespace std;
35 
37 
38 namespace mrpt
39 {
40 namespace slam
41 {
42 /** Fills out a "TPoseBin2D" variable, given a path hypotesis and (if not set to
43  * nullptr) a new pose appended at the end, using the KLD params in "options".
44  */
45 template <>
47  mrpt::slam::detail::TPoseBin2D& outBin, const TKLDParams& opts,
48  const CMonteCarloLocalization2D::CParticleDataContent* currentParticleValue,
49  const TPose3D* newPoseToBeInserted)
50 {
51  // 2D pose approx: Use the latest pose only:
52  if (newPoseToBeInserted)
53  {
54  outBin.x = round(newPoseToBeInserted->x / opts.KLD_binSize_XY);
55  outBin.y = round(newPoseToBeInserted->y / opts.KLD_binSize_XY);
56  outBin.phi = round(newPoseToBeInserted->yaw / opts.KLD_binSize_PHI);
57  }
58  else
59  {
60  ASSERT_(currentParticleValue)
61  outBin.x = round(currentParticleValue->x() / opts.KLD_binSize_XY);
62  outBin.y = round(currentParticleValue->y() / opts.KLD_binSize_XY);
63  outBin.phi = round(currentParticleValue->phi() / opts.KLD_binSize_PHI);
64  }
65 }
66 
67 /*---------------------------------------------------------------
68  ctor
69  ---------------------------------------------------------------*/
70 // Passing a "this" pointer at this moment is not a problem since it will be NOT
71 // access until the object is fully initialized
72 CMonteCarloLocalization2D::CMonteCarloLocalization2D(size_t M)
73  : m_poseParticles(M)
74 {
75  this->setLoggerName("CMonteCarloLocalization2D");
76 }
77 
78 /*---------------------------------------------------------------
79  Dtor
80  ---------------------------------------------------------------*/
83  const size_t i, bool& is_valid_pose) const
84 {
85  if (i >= m_poseParticles.m_particles.size())
86  THROW_EXCEPTION("Particle index out of bounds!");
87  is_valid_pose = true;
90 }
91 
92 /*---------------------------------------------------------------
93  PF_SLAM_computeObservationLikelihoodForParticle
94  ---------------------------------------------------------------*/
95 double
98  const size_t particleIndexForMap, const CSensoryFrame& observation,
99  const CPose3D& x) const
100 {
101  MRPT_UNUSED_PARAM(PF_options);
102  ASSERT_(
103  options.metricMap || particleIndexForMap < options.metricMaps.size())
104 
105  CMetricMap* map =
106  (options.metricMap) ? options.metricMap : // All particles, one map
107  options.metricMaps[particleIndexForMap]; // One map per particle
108 
109  // For each observation:
110  double ret = 1;
111  for (CSensoryFrame::const_iterator it = observation.begin();
112  it != observation.end(); ++it)
113  ret += map->computeObservationLikelihood(
114  it->get(), x); // Compute the likelihood:
115 
116  // Done!
117  return ret;
118 }
119 
120 // Specialization for my kind of particles:
123  CPose2D* particleData, const TPose3D& newPose) const
124 {
125  *particleData = CPose2D(TPose2D(newPose));
126 }
127 
129  CParticleList& old_particles, const vector<TPose3D>& newParticles,
130  const vector<double>& newParticlesWeight,
131  const vector<size_t>& newParticlesDerivedFromIdx) const
132 {
133  MRPT_UNUSED_PARAM(newParticlesDerivedFromIdx);
135  size_t(newParticlesWeight.size()), size_t(newParticles.size()));
136 
137  // ---------------------------------------------------------------------------------
138  // Substitute old by new particle set:
139  // Old are in "m_particles"
140  // New are in "newParticles",
141  // "newParticlesWeight","newParticlesDerivedFromIdx"
142  // ---------------------------------------------------------------------------------
143  // Free old m_particles: not needed since "d" is now a smart ptr
144 
145  // Copy into "m_particles"
146  const size_t N = newParticles.size();
147  old_particles.resize(N);
148  for (size_t i = 0; i < N; i++)
149  {
150  old_particles[i].log_w = newParticlesWeight[i];
151  old_particles[i].d.reset(new CPose2D(TPose2D(newParticles[i])));
152  }
153 }
154 
156  COccupancyGridMap2D* theMap, const double freeCellsThreshold,
157  const int particlesCount, const double x_min, const double x_max,
158  const double y_min, const double y_max, const double phi_min,
159  const double phi_max)
160 {
161  MRPT_START
162 
163  ASSERT_(theMap != nullptr)
164 
165  int sizeX = theMap->getSizeX();
166  int sizeY = theMap->getSizeY();
167  double gridRes = theMap->getResolution();
168  std::vector<double> freeCells_x, freeCells_y;
169  size_t nFreeCells;
170  unsigned int xIdx1, xIdx2;
171  unsigned int yIdx1, yIdx2;
172 
173  freeCells_x.reserve(sizeX * sizeY);
174  freeCells_y.reserve(sizeX * sizeY);
175 
176  if (x_min > theMap->getXMin())
177  xIdx1 = max(0, theMap->x2idx(x_min));
178  else
179  xIdx1 = 0;
180  if (x_max < theMap->getXMax())
181  xIdx2 = min(sizeX - 1, theMap->x2idx(x_max));
182  else
183  xIdx2 = sizeX - 1;
184  if (y_min > theMap->getYMin())
185  yIdx1 = max(0, theMap->y2idx(y_min));
186  else
187  yIdx1 = 0;
188  if (y_max < theMap->getYMax())
189  yIdx2 = min(sizeY - 1, theMap->y2idx(y_max));
190  else
191  yIdx2 = sizeY - 1;
192 
193  for (unsigned int x = xIdx1; x <= xIdx2; x++)
194  for (unsigned int y = yIdx1; y <= yIdx2; y++)
195  if (theMap->getCell(x, y) >= freeCellsThreshold)
196  {
197  freeCells_x.push_back(theMap->idx2x(x));
198  freeCells_y.push_back(theMap->idx2y(y));
199  }
200 
201  nFreeCells = freeCells_x.size();
202 
203  // Assure that map is not fully occupied!
204  ASSERT_(nFreeCells);
205 
206  if (particlesCount > 0)
207  {
209  m_poseParticles.m_particles.resize(particlesCount);
210  for (int i = 0; i < particlesCount; i++)
211  m_poseParticles.m_particles[i].d.reset(new CPose2D());
212  }
213 
214  const size_t M = m_poseParticles.m_particles.size();
215 
216  // Generate pose m_particles:
217  for (size_t i = 0; i < M; i++)
218  {
219  int idx =
220  round(getRandomGenerator().drawUniform(0.0, nFreeCells - 1.001));
221 
223  freeCells_x[idx] +
224  getRandomGenerator().drawUniform(-gridRes, gridRes));
226  freeCells_y[idx] +
227  getRandomGenerator().drawUniform(-gridRes, gridRes));
228  m_poseParticles.m_particles[i].d->phi(
229  getRandomGenerator().drawUniform(phi_min, phi_max));
230  m_poseParticles.m_particles[i].log_w = 0;
231  }
232 
233  MRPT_END
234 }
235 
238  const mrpt::obs::CActionCollection* action,
239  const mrpt::obs::CSensoryFrame* observation,
242 {
243  switch (PF_algorithm)
244  {
245  case CParticleFilter::pfStandardProposal:
246  pf.executeOn<
248  *this, action, observation, stats);
249  break;
250  case CParticleFilter::pfAuxiliaryPFStandard:
251  pf.executeOn<
253  *this, action, observation, stats);
254  break;
255  case CParticleFilter::pfAuxiliaryPFOptimal:
256  pf.executeOn<
258  *this, action, observation, stats);
259  break;
260  default:
261  {
262  THROW_EXCEPTION("Invalid particle filter algorithm selection!");
263  }
264  break;
265  }
266 }
267 }
268 }
CParticleList m_particles
The array of particles.
This class acts as a common interface to the different interfaces (see CParticleFilter::TParticleFilt...
TParticleFilterAlgorithm
Defines different types of particle filter algorithms.
void executeOn(PARTICLEFILTERCAPABLE &obj, const mrpt::obs::CActionCollection *action, const mrpt::obs::CSensoryFrame *observation, TParticleFilterStats *stats=nullptr)
Executes a complete prediction + update step of the selected particle filtering algorithm.
Declares a virtual base class for all metric maps storage classes.
Definition: CMetricMap.h:57
double computeObservationLikelihood(const mrpt::obs::CObservation *obs, const mrpt::poses::CPose3D &takenFrom)
Computes the log-likelihood of a given observation given an arbitrary robot 3D pose.
Definition: CMetricMap.cpp:189
A class for storing an occupancy grid map.
float getResolution() const
Returns the resolution of the grid map.
float getYMin() const
Returns the "y" coordinate of top side of grid map.
float idx2y(const size_t cy) const
unsigned int getSizeX() const
Returns the horizontal size of grid map in cells count.
float getCell(int x, int y) const
Read the real valued [0,1] contents of a cell, given its index.
int x2idx(float x) const
Transform a coordinate value into a cell index.
unsigned int getSizeY() const
Returns the vertical size of grid map in cells count.
float getXMin() const
Returns the "x" coordinate of left side of grid map.
float idx2x(const size_t cx) const
Transform a cell index into a coordinate value.
Declares a class for storing a collection of robot actions.
Declares a class for storing a "sensory frame", a set of "observations" taken by the robot approximat...
Definition: CSensoryFrame.h:55
const_iterator end() const
Returns a constant iterator to the end of the list of observations: this is an example of usage:
const_iterator begin() const
Returns a constant iterator to the first observation: this is an example of usage:
std::deque< CObservation::Ptr >::const_iterator const_iterator
You can use CSensoryFrame::begin to get a iterator to the first element.
A class used to store a 2D pose, including the 2D coordinate point and a heading (phi) angle.
Definition: CPose2D.h:41
A class used to store a 3D pose (a 3D translation + a rotation in 3D).
Definition: CPose3D.h:89
void clear()
Free all the memory associated to m_particles, and set the number of parts = 0.
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...
void PF_SLAM_implementation_custom_update_particle_with_new_pose(CParticleDataContent *particleData, const mrpt::math::TPose3D &newPose) const override
mrpt::poses::CPosePDFParticles::CParticleDataContent CParticleDataContent
void PF_SLAM_implementation_replaceByNewParticleSet(CParticleList &old_particles, const std::vector< mrpt::math::TPose3D > &newParticles, const std::vector< double > &newParticlesWeight, const std::vector< size_t > &newParticlesDerivedFromIdx) const override
TMonteCarloLocalizationParams options
MCL parameters.
mrpt::math::TPose3D getLastPose(const size_t i, bool &is_valid_pose) const override
Return the robot pose for the i'th particle.
mrpt::poses::CPosePDFParticles m_poseParticles
mrpt::poses::CPosePDFParticles::CParticleList CParticleList
double PF_SLAM_computeObservationLikelihoodForParticle(const mrpt::bayes::CParticleFilter::TParticleFilterOptions &PF_options, const size_t particleIndexForMap, const mrpt::obs::CSensoryFrame &observation, const mrpt::poses::CPose3D &x) const override
Evaluate the observation likelihood for one particle at a given location.
A generic implementation of the PF method "pfStandardProposal" (standard proposal distribution,...
Option set for KLD algorithm.
Definition: TKLDParams.h:21
double KLD_binSize_XY
Parameters for the KLD adaptive sample size algorithm (see Dieter Fox's papers), which is used only i...
Definition: TKLDParams.h:35
GLenum GLint GLint y
Definition: glext.h:3538
GLenum GLint x
Definition: glext.h:3538
int round(const T value)
Returns the closer integer (int) to x.
Definition: round.h:25
for(ctr=DCTSIZE;ctr > 0;ctr--)
Definition: jidctflt.cpp:56
#define ASSERT_EQUAL_(__A, __B)
Definition: mrpt_macros.h:318
#define MRPT_START
Definition: mrpt_macros.h:425
#define ASSERT_(f)
Definition: mrpt_macros.h:309
#define ASSERTDEB_(f)
Defines an assertion mechanism - only when compiled in debug.
Definition: mrpt_macros.h:355
#define MRPT_END
Definition: mrpt_macros.h:429
#define THROW_EXCEPTION(msg)
Definition: mrpt_macros.h:111
#define MRPT_UNUSED_PARAM(a)
Can be used to avoid "not used parameters" warnings from the compiler.
Definition: mrpt_macros.h:365
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
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.
void KLF_loadBinFromParticle(mrpt::slam::detail::TPoseBin2D &outBin, const TKLDParams &opts, const CMonteCarloLocalization2D::CParticleDataContent *currentParticleValue, const TPose3D *newPoseToBeInserted)
Fills out a "TPoseBin2D" variable, given a path hypotesis and (if not set to nullptr) a new pose appe...
Classes for serialization, sockets, ini-file manipulation, streams, list of properties-values,...
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
#define min(a, b)
The configuration of a particle filter.
Statistics for being returned from the "execute" method.
Lightweight 2D pose.
Lightweight 3D pose (three spatial coordinates, plus three angular coordinates).
double x
X,Y,Z, coords.
double yaw
Yaw coordinate (rotation angle over Z axis).
mrpt::maps::TMetricMapList metricMaps
[update stage] Alternative way (if metricMap==nullptr): A metric map is supplied for each particle: T...
mrpt::maps::CMetricMap * metricMap
[update stage] Must be set to a metric map used to estimate the likelihood of observations
Auxiliary structure used in KLD-sampling in particle filters.



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