Main MRPT website > C++ reference for MRPT 1.9.9
CRejectionSamplingRangeOnlyLocalization.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 headers
11 
14 #include <mrpt/maps/CLandmark.h>
16 #include <mrpt/math/utils.h>
17 
18 using namespace mrpt::utils;
19 using namespace mrpt::math;
20 using namespace mrpt::slam;
21 using namespace mrpt::maps;
22 using namespace mrpt::obs;
23 using namespace mrpt::random;
24 using namespace mrpt::poses;
25 using namespace std;
26 
27 /*---------------------------------------------------------------
28  Constructor
29 ---------------------------------------------------------------*/
30 CRejectionSamplingRangeOnlyLocalization::
31  CRejectionSamplingRangeOnlyLocalization()
32  : m_z_robot(0),
33  m_sigmaRanges(0.10f),
34  m_oldPose(),
35  m_drawIndex(0),
36  m_dataPerBeacon()
37 {
38 }
39 
40 /*---------------------------------------------------------------
41  RS_drawFromProposal
42 ---------------------------------------------------------------*/
44  CPose2D& outSample)
45 {
47 
48  // Use the first beacon data to draw a pose:
49  if (m_dataPerBeacon.size() == 0)
51  "There is no information from which to draw samples!! Use "
52  "'setParams' with valid data!");
53 
55 
56  float ang = getRandomGenerator().drawUniform(
57  m_dataPerBeacon[m_drawIndex].minAngle,
58  m_dataPerBeacon[m_drawIndex].maxAngle);
60  m_dataPerBeacon[m_drawIndex].radiusAtRobotPlane, m_sigmaRanges);
61 
62  // This is the point where the SENSOR is:
63  outSample.x(m_dataPerBeacon[m_drawIndex].beaconPosition.x + cos(ang) * R);
64  outSample.y(m_dataPerBeacon[m_drawIndex].beaconPosition.y + sin(ang) * R);
65 
66  outSample.phi(getRandomGenerator().drawGaussian1D(m_oldPose.phi(), DEG2RAD(2)));
67 
68  // Compute the robot pose P.
69  // P = SAMPLE - ROT ยท SENSOR_ON_ROBOT
71  m_dataPerBeacon[m_drawIndex].sensorOnRobot.x,
72  m_dataPerBeacon[m_drawIndex].sensorOnRobot.y);
73  mrpt::math::TPoint2D S(outSample.x(), outSample.y());
74  on = mrpt::math::TPoint2D(mrpt::math::TPose2D(0, 0, outSample.phi()) + on);
75  S = S - on;
76 
77  outSample.x(S.x);
78  outSample.y(S.y);
79 
80  MRPT_END
81 }
82 
83 /*---------------------------------------------------------------
84  RS_observationLikelihood
85 ---------------------------------------------------------------*/
87  const CPose2D& x)
88 {
90 
91  double lik = 1.0;
92  double m_sigmaRanges2 = square(m_sigmaRanges);
93 
94  // Evaluate the likelihood for all the observations but the "m_drawIndex":
95  for (size_t i = 0; i < m_dataPerBeacon.size(); i++)
96  {
97  // TODO: height now includes the sensor "z"!!!...
98  CPoint3D P(
99  x + CPoint3D(
100  m_dataPerBeacon[i].sensorOnRobot.x,
101  m_dataPerBeacon[i].sensorOnRobot.y, 0));
102 
103  if (i != m_drawIndex)
104  // Evalute:
105  lik *= exp(
106  -0.5 * square(
107  m_dataPerBeacon[i].radiusAtRobotPlane -
108  P.distanceTo(m_dataPerBeacon[i].beaconPosition)) /
109  m_sigmaRanges2);
110  }
111 
112  return lik;
113 
114  MRPT_END
115 }
116 
117 /*---------------------------------------------------------------
118  setParams
119 ---------------------------------------------------------------*/
121  const CLandmarksMap& beaconsMap,
122  const CObservationBeaconRanges& observation, float sigmaRanges,
123  const CPose2D& oldPose, float robot_z, bool autoCheckAngleRanges)
124 
125 {
126  MRPT_START
127 
128  // Various vars:
129  m_z_robot = robot_z;
130  m_oldPose = oldPose;
131  m_sigmaRanges = sigmaRanges; // TODO: observation.stdError;
132 
133  double xMin = 1e30, xMax = -1e30, yMin = 1e30, yMax = -1e30,
134  gridRes = 2 * m_sigmaRanges;
135  float R;
136 
137  // Save each observed beacon data:
138  m_dataPerBeacon.clear();
139 
140  // Minimum radius:
141  std::deque<
143  size_t i;
144 
145  // For each observation:
146  for (i = 0, it = observation.sensedData.begin();
147  it != observation.sensedData.end(); ++it, ++i)
148  {
149  // Is in the map?
150  const CLandmark* lm = beaconsMap.landmarks.getByBeaconID(it->beaconID);
151  if (lm != nullptr)
152  {
154 
155  data.sensorOnRobot = it->sensorLocationOnRobot;
156 
157  data.beaconPosition.x = lm->pose_mean.x;
158  data.beaconPosition.y = lm->pose_mean.y;
159 
160  // First compute squared:
161  data.radiusAtRobotPlane =
162  square(it->sensedDistance) - square(lm->pose_mean.z - robot_z);
163 
164  if (data.radiusAtRobotPlane > 0)
165  {
166  data.radiusAtRobotPlane = sqrt(data.radiusAtRobotPlane);
167  data.minAngle = -M_PIf;
168  data.maxAngle = M_PIf;
169  m_dataPerBeacon.push_back(data);
170 
171  // std::cout << "BEACON: " << m_dataPerBeacon.size() << "\n "
172  // <<data.beaconPosition << " R=" << data.radiusAtRobotPlane <<
173  // "\n";
174 
175  // Keep max/min:
176  xMin = min(
177  xMin, data.beaconPosition.x - (data.radiusAtRobotPlane +
178  4 * m_sigmaRanges + 1.0));
179  xMax = max(
180  xMax, data.beaconPosition.x + (data.radiusAtRobotPlane +
181  4 * m_sigmaRanges + 1.0));
182  yMin = min(
183  yMin, data.beaconPosition.y - (data.radiusAtRobotPlane +
184  4 * m_sigmaRanges + 1.0));
185  yMax = max(
186  yMax, data.beaconPosition.y + (data.radiusAtRobotPlane +
187  4 * m_sigmaRanges + 1.0));
188  }
189  else
190  {
191  printf(
192  "\nWARNING: Beacon range is shorter than distance between "
193  "the robot and the beacon in the Z axis!!!: Ignoring this "
194  "measurement\n");
195  }
196  }
197  } // end for
198 
199  // ------------------------------------------------------------------------
200  // Precompute the min/max angles for potential samples, for each beacon:
201  // ------------------------------------------------------------------------
202  if (autoCheckAngleRanges && m_dataPerBeacon.size() > 1)
203  {
204  // Build the grid:
205  // Each cell in the grid is a vector of bools, each one indicating
206  // whether some samples from the i'th beacon falls there.
207  utils::CDynamicGrid<vector_bool> grid(xMin, xMax, yMin, yMax, gridRes);
208  grid.fill(vector_bool(m_dataPerBeacon.size(), false));
209  vector_bool* cell;
210 
211  // The ngular step size:
212  float Aa = DEG2RAD(5);
213 
214  // Fill the grid:
215  for (i = 0; i < m_dataPerBeacon.size(); i++)
216  {
217  for (float a = -M_PIf; a <= M_PIf; a += Aa)
218  {
219  // Radius R - 3*SIGMA:
220  R = m_dataPerBeacon[i].radiusAtRobotPlane -
221  3.0f * m_sigmaRanges;
222  R = max(R, 0.0f);
223  cell = grid.cellByPos(
224  m_dataPerBeacon[i].beaconPosition.x + cos(a) * R,
225  m_dataPerBeacon[i].beaconPosition.y + sin(a) * R);
226  ASSERT_(cell != nullptr);
227  (*cell)[i] = true;
228  // Radius R :
229  R = m_dataPerBeacon[i].radiusAtRobotPlane;
230  cell = grid.cellByPos(
231  m_dataPerBeacon[i].beaconPosition.x + cos(a) * R,
232  m_dataPerBeacon[i].beaconPosition.y + sin(a) * R);
233  ASSERT_(cell != nullptr);
234  (*cell)[i] = true;
235  // Radius R + 3*SIGMA:
236  R = m_dataPerBeacon[i].radiusAtRobotPlane +
237  3.0f * m_sigmaRanges;
238  cell = grid.cellByPos(
239  m_dataPerBeacon[i].beaconPosition.x + cos(a) * R,
240  m_dataPerBeacon[i].beaconPosition.y + sin(a) * R);
241  ASSERT_(cell != nullptr);
242  (*cell)[i] = true;
243  } // end for a
244  } // end for i
245 
246  // Check the angles:
247  for (i = 0; i < m_dataPerBeacon.size(); i++)
248  {
249  float maxA = -M_PIf, minA = M_PIf;
250  for (float a = -M_PIf; a < M_PIf; a += Aa)
251  {
252  // Radius R - 3*SIGMA:
253  R = m_dataPerBeacon[i].radiusAtRobotPlane -
254  3.0f * m_sigmaRanges;
255  R = max(R, 0.0f);
256  cell = grid.cellByPos(
257  m_dataPerBeacon[i].beaconPosition.x + cos(a) * R,
258  m_dataPerBeacon[i].beaconPosition.y + sin(a) * R);
259  ASSERT_(cell != nullptr);
260  if (std::count(cell->begin(), cell->end(), true) > 1)
261  {
262  maxA = max(maxA, a);
263  minA = min(minA, a);
264  }
265  // Radius R :
266  R = m_dataPerBeacon[i].radiusAtRobotPlane;
267  cell = grid.cellByPos(
268  m_dataPerBeacon[i].beaconPosition.x + cos(a) * R,
269  m_dataPerBeacon[i].beaconPosition.y + sin(a) * R);
270  ASSERT_(cell != nullptr);
271  if (std::count(cell->begin(), cell->end(), true) > 1)
272  {
273  maxA = max(maxA, a);
274  minA = min(minA, a);
275  }
276  // Radius R + 3*SIGMA:
277  R = m_dataPerBeacon[i].radiusAtRobotPlane +
278  3.0f * m_sigmaRanges;
279  cell = grid.cellByPos(
280  m_dataPerBeacon[i].beaconPosition.x + cos(a) * R,
281  m_dataPerBeacon[i].beaconPosition.y + sin(a) * R);
282  ASSERT_(cell != nullptr);
283  if (std::count(cell->begin(), cell->end(), true) > 1)
284  {
285  maxA = max(maxA, a);
286  minA = min(minA, a);
287  }
288  } // end for a
289  m_dataPerBeacon[i].minAngle = max(-M_PIf, minA - Aa);
290  m_dataPerBeacon[i].maxAngle = min(M_PIf, maxA + Aa);
291  } // end for i
292  } // end if >1 beacons
293 
294  // Select best candidate for "m_drawIndex":
295  float minCoberture = 1e30f;
296  m_drawIndex = 0;
297  for (i = 0; i < m_dataPerBeacon.size(); i++)
298  {
299  float c = m_dataPerBeacon[i].radiusAtRobotPlane *
300  (m_dataPerBeacon[i].maxAngle - m_dataPerBeacon[i].minAngle);
301  if (c < minCoberture)
302  {
303  minCoberture = c;
304  m_drawIndex = i;
305  }
306  } // end for i
307 
308  // End!
309  return m_dataPerBeacon.size() != 0;
310  MRPT_END
311 }
A namespace of pseudo-random numbers genrators of diferent distributions.
double drawUniform(const double Min, const double Max)
Generate a uniformly distributed pseudo-random number using the MT19937 algorithm, scaled to the selected range.
double x() const
Common members of all points & poses classes.
Definition: CPoseOrPoint.h:135
GLuint GLuint GLsizei count
Definition: glext.h:3528
Classes for serialization, sockets, ini-file manipulation, streams, list of properties-values, timewatch, extensions to STL.
#define min(a, b)
double distanceTo(const CPoseOrPoint< OTHERCLASS > &b) const
Returns the Euclidean distance to another pose/point:
Definition: CPoseOrPoint.h:206
#define THROW_EXCEPTION(msg)
void RS_drawFromProposal(mrpt::poses::CPose2D &outSample)
Generates one sample, drawing from some proposal distribution.
Declares a class derived from "CObservation" that represents one (or more) range measurements to labe...
Data for each beacon observation with a correspondence with the map.
STL namespace.
const Scalar * const_iterator
Definition: eigen_plugins.h:27
void fill(const T &value)
Fills all the cells with the same value.
Definition: CDynamicGrid.h:119
const CLandmark * getByBeaconID(unsigned int ID) const
Returns the landmark with a given beacon ID, or nullptr if not found.
double drawGaussian1D(const double mean, const double std)
Generate a normally distributed pseudo-random number.
T square(const T x)
Inline function for the square of a number.
Definition: bits.h:55
std::vector< bool > vector_bool
A type for passing a vector of bools.
Definition: types_simple.h:31
size_t m_drawIndex
The index in "m_dataPerBeacon" used to draw samples (the rest will be used to evaluate the likelihood...
T * cellByPos(double x, double y)
Returns a pointer to the contents of a cell given by its coordinates, or nullptr if it is out of the ...
Definition: CDynamicGrid.h:213
This base provides a set of functions for maths stuff.
Definition: CArrayNumeric.h:19
bool setParams(const mrpt::maps::CLandmarksMap &beaconsMap, const mrpt::obs::CObservationBeaconRanges &observation, float sigmaRanges, const mrpt::poses::CPose2D &oldPose, float robot_z=0, bool autoCheckAngleRanges=true)
The parameters used in the generation of random samples:
A 2D grid of dynamic size which stores any kind of data at each cell.
Definition: CDynamicGrid.h:40
#define M_PIf
A class for storing a map of 3D probabilistic landmarks.
Definition: CLandmarksMap.h:75
#define MRPT_END
const GLubyte * c
Definition: glext.h:6313
double RS_observationLikelihood(const mrpt::poses::CPose2D &x)
Returns the NORMALIZED observation likelihood (linear, not exponential!!!) at a given point of the st...
std::deque< TMeasurement > sensedData
The list of observed ranges.
This namespace contains representation of robot actions and observations.
double x
X,Y,Z coordinates.
#define DEG2RAD
A class used to store a 3D point.
Definition: CPoint3D.h:32
Classes for 2D/3D geometry representation, both of single values and probability density distribution...
Definition: CPoint.h:17
std::deque< TDataPerBeacon > m_dataPerBeacon
Data for each beacon observation with a correspondence with the map.
#define MRPT_START
The class for storing "landmarks" (visual or laser-scan-extracted features,...)
Definition: CLandmark.h:35
A class used to store a 2D pose, including the 2D coordinate point and a heading (phi) angle...
Definition: CPose2D.h:40
const float R
const double & phi() const
Get the phi angle of the 2D pose (in radians)
Definition: CPose2D.h:91
Lightweight 2D pose.
#define ASSERT_(f)
GLenum GLint x
Definition: glext.h:3538
mrpt::math::TPoint3D pose_mean
The mean of the landmark 3D position.
Definition: CLandmark.h:47
CRandomGenerator & getRandomGenerator()
A static instance of a CRandomGenerator class, for use in single-thread applications.
Lightweight 2D point.
GLsizei GLsizei GLenum GLenum const GLvoid * data
Definition: glext.h:3546
GLubyte GLubyte GLubyte a
Definition: glext.h:6279
struct mrpt::maps::CLandmarksMap::TCustomSequenceLandmarks landmarks



Page generated by Doxygen 1.8.14 for MRPT 1.9.9 Git: ae4571287 Thu Nov 23 00:06:53 2017 +0100 at dom oct 27 23:51:55 CET 2019