Main MRPT website > C++ reference for MRPT 1.9.9
COccupancyGridMap2D_simulate.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 "maps-precomp.h" // Precomp header
11 
15 #include <mrpt/utils/round.h> // round()
17 
18 #include <mrpt/random.h>
19 
20 using namespace mrpt;
21 using namespace mrpt::maps;
22 using namespace mrpt::obs;
23 using namespace mrpt::utils;
24 using namespace mrpt::random;
25 using namespace mrpt::poses;
26 using namespace std;
27 
29 
30 // See docs in header
32  mrpt::obs::CObservation2DRangeScan& inout_Scan, const CPose2D& robotPose,
33  float threshold, size_t N, float noiseStd, unsigned int decimation,
34  float angleNoiseStd) const
35 {
37 
38  ASSERT_(decimation >= 1)
39  ASSERT_(N >= 2)
40 
41  // Sensor pose in global coordinates
42  CPose3D sensorPose3D = CPose3D(robotPose) + inout_Scan.sensorPose;
43  // Aproximation: grid is 2D !!!
44  CPose2D sensorPose(sensorPose3D);
45 
46  // Scan size:
47  inout_Scan.resizeScan(N);
48 
49  double A = sensorPose.phi() +
50  (inout_Scan.rightToLeft ? -0.5 : +0.5) * inout_Scan.aperture;
51  const double AA =
52  (inout_Scan.rightToLeft ? 1.0 : -1.0) * (inout_Scan.aperture / (N - 1));
53 
54  const float free_thres = 1.0f - threshold;
55 
56  for (size_t i = 0; i < N; i += decimation, A += AA * decimation)
57  {
58  bool valid;
59  float out_range;
60  simulateScanRay(
61  sensorPose.x(), sensorPose.y(), A, out_range, valid,
62  inout_Scan.maxRange, free_thres, noiseStd, angleNoiseStd);
63  inout_Scan.setScanRange(i, out_range);
64  inout_Scan.setScanRangeValidity(i, valid);
65  }
66 
67  MRPT_END
68 }
69 
71  CObservationRange& inout_observation, const CPose2D& robotPose,
72  float threshold, float rangeNoiseStd, float angleNoiseStd) const
73 {
74  const float free_thres = 1.0f - threshold;
75 
76  for (CObservationRange::iterator itR = inout_observation.begin();
77  itR != inout_observation.end(); ++itR)
78  {
79  const CPose2D sensorAbsolutePose =
80  CPose2D(CPose3D(robotPose) + CPose3D(itR->sensorPose));
81 
82  // For each sonar cone, simulate several rays and keep the shortest
83  // distance:
84  ASSERT_(inout_observation.sensorConeApperture > 0)
85  size_t nRays =
86  round(1 + inout_observation.sensorConeApperture / DEG2RAD(1.0));
87 
88  double direction = sensorAbsolutePose.phi() -
89  0.5 * inout_observation.sensorConeApperture;
90  const double Adir = inout_observation.sensorConeApperture / nRays;
91 
92  float min_detected_obs = 0;
93  for (size_t i = 0; i < nRays; i++, direction += Adir)
94  {
95  bool valid;
96  float sim_rang;
97  simulateScanRay(
98  sensorAbsolutePose.x(), sensorAbsolutePose.y(), direction,
99  sim_rang, valid, inout_observation.maxSensorDistance,
100  free_thres, rangeNoiseStd, angleNoiseStd);
101 
102  if (valid && (sim_rang < min_detected_obs || !i))
103  min_detected_obs = sim_rang;
104  }
105  // Save:
106  itR->sensedDistance = min_detected_obs;
107  }
108 }
109 
111  const double start_x, const double start_y, const double angle_direction,
112  float& out_range, bool& out_valid, const double max_range_meters,
113  const float threshold_free, const double noiseStd,
114  const double angleNoiseStd) const
115 {
116  const double A_ =
117  angle_direction +
118  (angleNoiseStd > .0
119  ? getRandomGenerator().drawGaussian1D_normalized() * angleNoiseStd
120  : .0);
121 
122 // Unit vector in the directorion of the ray:
123 #ifdef HAVE_SINCOS
124  double Arx, Ary;
125  ::sincos(A_, &Ary, &Arx);
126 #else
127  const double Arx = cos(A_);
128  const double Ary = sin(A_);
129 #endif
130 
131  // Ray tracing, until collision, out of the map or out of range:
132  const unsigned int max_ray_len =
133  mrpt::utils::round(max_range_meters / resolution);
134  unsigned int ray_len = 0;
135 
136 // Use integers for all ray tracing for efficiency
137 #define INTPRECNUMBIT 10
138 #define int_x2idx(_X) (_X >> INTPRECNUMBIT)
139 #define int_y2idx(_Y) (_Y >> INTPRECNUMBIT)
140 
141  int64_t rxi = static_cast<int64_t>(
142  ((start_x - x_min) / resolution) * (1L << INTPRECNUMBIT));
143  int64_t ryi = static_cast<int64_t>(
144  ((start_y - y_min) / resolution) * (1L << INTPRECNUMBIT));
145 
146  const int64_t Arxi = static_cast<int64_t>(
147  RAYTRACE_STEP_SIZE_IN_CELL_UNITS * Arx * (1L << INTPRECNUMBIT));
148  const int64_t Aryi = static_cast<int64_t>(
149  RAYTRACE_STEP_SIZE_IN_CELL_UNITS * Ary * (1L << INTPRECNUMBIT));
150 
151  cellType hitCellOcc_int = 0; // p2l(0.5f)
152  const cellType threshold_free_int = p2l(threshold_free);
153  int x, y = int_y2idx(ryi);
154 
155  while ((x = int_x2idx(rxi)) >= 0 && (y = int_y2idx(ryi)) >= 0 &&
156  x < static_cast<int>(size_x) && y < static_cast<int>(size_y) &&
157  (hitCellOcc_int = map[x + y * size_x]) > threshold_free_int &&
158  ray_len < max_ray_len)
159  {
160  rxi += Arxi;
161  ryi += Aryi;
162  ray_len++;
163  }
164 
165  // Store:
166  // Check out of the grid?
167  // Tip: if x<0, (unsigned)(x) will also be >>> size_x ;-)
168  if (abs(hitCellOcc_int) <= 1 || static_cast<unsigned>(x) >= size_x ||
169  static_cast<unsigned>(y) >= size_y)
170  {
171  out_valid = false;
172  out_range = max_range_meters;
173  }
174  else
175  { // No: The normal case:
176  out_range = RAYTRACE_STEP_SIZE_IN_CELL_UNITS * ray_len * resolution;
177  out_valid = (ray_len < max_ray_len); // out_range<max_range_meters;
178  // Add additive Gaussian noise:
179  if (noiseStd > 0 && out_valid)
180  out_range += noiseStd * getRandomGenerator().drawGaussian1D_normalized();
181  }
182 }
183 
186  : method(sumUnscented),
187  UT_alpha(0.99),
188  UT_kappa(.0),
189  UT_beta(2.0),
190  MC_samples(10),
191  aperture(M_PIf),
192  rightToLeft(true),
193  maxRange(80.f),
194  nRays(361),
195  rangeNoiseStd(.0f),
196  angleNoiseStd(.0f),
197  decimation(1),
198  threshold(.6f)
199 {
200 }
201 
204 {
205 }
206 
208 {
211 };
212 
214  const Eigen::Vector3d& x_pose, const TFunctorLaserSimulData& fixed_param,
215  Eigen::VectorXd& y_scanRanges)
216 {
217  ASSERT_(fixed_param.params && fixed_param.grid)
218  ASSERT_(fixed_param.params->decimation >= 1)
219  ASSERT_(fixed_param.params->nRays >= 2)
220 
221  const size_t N = fixed_param.params->nRays;
222 
223  // Sensor pose in global coordinates
224  const CPose3D sensorPose3D =
225  CPose3D(x_pose[0], x_pose[1], .0, x_pose[2], .0, .0) +
226  fixed_param.params->sensorPose;
227  // Aproximation: grid is 2D !!!
228  const CPose2D sensorPose(sensorPose3D);
229 
230  // Scan size:
231  y_scanRanges.resize(N);
232 
233  double A = sensorPose.phi() +
234  (fixed_param.params->rightToLeft ? -0.5 : +0.5) *
235  fixed_param.params->aperture;
236  const double AA = (fixed_param.params->rightToLeft ? 1.0 : -1.0) *
237  (fixed_param.params->aperture / (N - 1));
238 
239  const float free_thres = 1.0f - fixed_param.params->threshold;
240 
241  for (size_t i = 0; i < N; i += fixed_param.params->decimation,
242  A += AA * fixed_param.params->decimation)
243  {
244  bool valid;
245  float range;
246 
247  fixed_param.grid->simulateScanRay(
248  sensorPose.x(), sensorPose.y(), A, range, valid,
249  fixed_param.params->maxRange, free_thres, .0 /*noiseStd*/,
250  .0 /*angleNoiseStd*/);
251  y_scanRanges[i] = valid ? range : fixed_param.params->maxRange;
252  }
253 }
254 
258 {
259  const Eigen::Vector3d robPoseMean =
260  in_params.robotPose.mean.getAsVectorVal();
261 
262  TFunctorLaserSimulData simulData;
263  simulData.grid = this;
264  simulData.params = &in_params;
265 
266  switch (in_params.method)
267  {
268  case sumUnscented:
270  robPoseMean, // x_mean
271  in_params.robotPose.cov, // x_cov
272  &func_laserSimul_callback, // void (*functor)(const
273  // VECTORLIKE1 &x,const USERPARAM
274  // &fixed_param, VECTORLIKE3 &y)
275  simulData, // const USERPARAM &fixed_param,
276  out_results.scanWithUncert.rangesMean,
277  out_results.scanWithUncert.rangesCovar,
278  nullptr, // elem_do_wrap2pi,
279  in_params.UT_alpha, in_params.UT_kappa,
280  in_params.UT_beta // alpha, K, beta
281  );
282  break;
283  case sumMonteCarlo:
284  //
286  robPoseMean, // x_mean
287  in_params.robotPose.cov, // x_cov
288  &func_laserSimul_callback, // void (*functor)(const
289  // VECTORLIKE1 &x,const USERPARAM
290  // &fixed_param, VECTORLIKE3 &y)
291  simulData, // const USERPARAM &fixed_param,
292  out_results.scanWithUncert.rangesMean,
293  out_results.scanWithUncert.rangesCovar, in_params.MC_samples);
294  break;
295  default:
296  throw std::runtime_error(
297  "[laserScanSimulatorWithUncertainty] Unknown `method` value");
298  break;
299  };
300 
301  // Outputs:
302  out_results.scanWithUncert.rangeScan.aperture = in_params.aperture;
303  out_results.scanWithUncert.rangeScan.maxRange = in_params.maxRange;
304  out_results.scanWithUncert.rangeScan.rightToLeft = in_params.rightToLeft;
305  out_results.scanWithUncert.rangeScan.sensorPose = in_params.sensorPose;
306 
307  out_results.scanWithUncert.rangeScan.resizeScan(in_params.nRays);
308  for (unsigned i = 0; i < in_params.nRays; i++)
309  {
311  i, (float)out_results.scanWithUncert.rangesMean[i]);
312  out_results.scanWithUncert.rangeScan.setScanRangeValidity(i, true);
313  }
314 
315  // Add minimum uncertainty: grid cell resolution:
316  out_results.scanWithUncert.rangesCovar.diagonal().array() +=
317  0.5 * resolution * resolution;
318 }
const COccupancyGridMap2D::TLaserSimulUncertaintyParams * params
mrpt::poses::CPosePDFGaussian robotPose
The robot pose Gaussian, in map coordinates.
A namespace of pseudo-random numbers genrators of diferent distributions.
double x() const
Common members of all points & poses classes.
Definition: CPoseOrPoint.h:135
GLsizei range
Definition: glext.h:5907
Declares a class derived from "CObservation" that encapsules a single range measurement, and associated parameters.
Classes for serialization, sockets, ini-file manipulation, streams, list of properties-values, timewatch, extensions to STL.
CPose2D mean
The mean value.
float threshold
(Default: 0.6f) The minimum occupancy threshold to consider a cell to be occupied ...
static void func_laserSimul_callback(const Eigen::Vector3d &x_pose, const TFunctorLaserSimulData &fixed_param, Eigen::VectorXd &y_scanRanges)
float sensorConeApperture
Cone aperture of each ultrasonic beam, in radians.
mrpt::obs::CObservation2DRangeScanWithUncertainty scanWithUncert
The scan + its uncertainty.
mrpt::math::CVectorDouble getAsVectorVal() const
Return the pose or point as a 1xN vector with all the components (see derived classes for each implem...
Definition: CPoseOrPoint.h:265
mrpt::poses::CPose3D sensorPose
(Default: at origin) The 6D pose of the sensor on the robot at the moment of starting the scan...
Eigen::VectorXd rangesMean
The same ranges than in rangeScan.scan[], for convenience as an Eigen container, and with double prec...
#define INTPRECNUMBIT
void setScanRange(const size_t i, const float val)
Output params for laserScanSimulatorWithUncertainty()
#define int_y2idx(_Y)
void laserScanSimulator(mrpt::obs::CObservation2DRangeScan &inout_Scan, const mrpt::poses::CPose2D &robotPose, float threshold=0.6f, size_t N=361, float noiseStd=0, unsigned int decimation=1, float angleNoiseStd=mrpt::utils::DEG2RAD(0)) const
Simulates a laser range scan into the current grid map.
STL namespace.
CObservation2DRangeScan rangeScan
The observation with the mean ranges in the scan field.
bool rightToLeft
(Default: true) The scanning direction: true=counterclockwise; false=clockwise
const COccupancyGridMap2D * grid
mrpt::math::CMatrixDouble33 cov
The 3x3 covariance matrix.
#define int_x2idx(_X)
float maxRange
The maximum range allowed by the device, in meters (e.g.
#define M_PIf
#define MRPT_END
size_t MC_samples
[sumMonteCarlo] MonteCarlo parameter: number of samples (Default: 10)
__int64 int64_t
Definition: rptypes.h:49
float aperture
(Default: M_PI) The "aperture" or field-of-view of the range finder, in radians (typically M_PI = 180...
This namespace contains representation of robot actions and observations.
void sonarSimulator(mrpt::obs::CObservationRange &inout_observation, const mrpt::poses::CPose2D &robotPose, float threshold=0.5f, float rangeNoiseStd=0.f, float angleNoiseStd=mrpt::utils::DEG2RAD(0.f)) const
Simulates the observations of a sonar rig into the current grid map.
unsigned int decimation
(Default: 1) The rays that will be simulated are at indexes: 0, D, 2D, 3D,...
#define DEG2RAD
void transform_gaussian_unscented(const VECTORLIKE1 &x_mean, const MATLIKE1 &x_cov, void(*functor)(const VECTORLIKE1 &x, const USERPARAM &fixed_param, VECTORLIKE3 &y), const USERPARAM &fixed_param, VECTORLIKE2 &y_mean, MATLIKE2 &y_cov, const bool *elem_do_wrap2pi=nullptr, const double alpha=1e-3, const double K=0, const double beta=2.0)
Scaled unscented transformation (SUT) for estimating the Gaussian distribution of a variable Y=f(X) f...
Classes for 2D/3D geometry representation, both of single values and probability density distribution...
Definition: CPoint.h:17
void laserScanSimulatorWithUncertainty(const TLaserSimulUncertaintyParams &in_params, TLaserSimulUncertaintyResult &out_results) const
Like laserScanSimulatorWithUncertainty() (see it for a discussion of most parameters) but taking into...
A class for storing an occupancy grid map.
#define MRPT_START
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
A "CObservation"-derived class that represents a 2D range scan measurement (typically from a laser sc...
A class used to store a 2D pose, including the 2D coordinate point and a heading (phi) angle...
Definition: CPose2D.h:40
A class used to store a 3D pose (a 3D translation + a rotation in 3D).
Definition: CPose3D.h:88
Input params for laserScanSimulatorWithUncertainty()
void simulateScanRay(const double x, const double y, const double angle_direction, float &out_range, bool &out_valid, const double max_range_meters, const float threshold_free=0.4f, const double noiseStd=.0, const double angleNoiseStd=.0) const
Simulate just one "ray" in the grid map.
void resizeScan(const size_t len)
Resizes all data vectors to allocate a given number of scan rays.
const double & phi() const
Get the phi angle of the 2D pose (in radians)
Definition: CPose2D.h:91
TLaserSimulUncertaintyMethod method
(Default: sumMonteCarlo) Select the method to do the uncertainty propagation
Eigen::MatrixXd rangesCovar
The covariance matrix for all the ranges in rangeScan.scan[].
float aperture
The "aperture" or field-of-view of the range finder, in radians (typically M_PI = 180 degrees)...
#define ASSERT_(f)
int round(const T value)
Returns the closer integer (int) to x.
Definition: round.h:25
static double RAYTRACE_STEP_SIZE_IN_CELL_UNITS
(Default:1.0) Can be set to <1 if a more fine raytracing is needed in sonarSimulator() and laserScanS...
GLenum GLint GLint y
Definition: glext.h:3538
std::deque< TMeasurement >::iterator iterator
void transform_gaussian_montecarlo(const VECTORLIKE1 &x_mean, const MATLIKE1 &x_cov, void(*functor)(const VECTORLIKE1 &x, const USERPARAM &fixed_param, VECTORLIKE3 &y), const USERPARAM &fixed_param, VECTORLIKE2 &y_mean, MATLIKE2 &y_cov, const size_t num_samples=1000, typename mrpt::aligned_containers< VECTORLIKE3 >::vector_t *out_samples_y=nullptr)
Simple Montecarlo-base estimation of the Gaussian distribution of a variable Y=f(X) for an arbitrary ...
float maxRange
(Default: 80) The maximum range allowed by the device, in meters (e.g.
GLenum GLint x
Definition: glext.h:3538
CRandomGenerator & getRandomGenerator()
A static instance of a CRandomGenerator class, for use in single-thread applications.
int16_t cellType
The type of the map cells:
mrpt::poses::CPose3D sensorPose
The 6D pose of the sensor on the robot at the moment of starting the scan.
bool rightToLeft
The scanning direction: true=counterclockwise; false=clockwise.
double drawGaussian1D_normalized()
Generate a normalized (mean=0, std=1) normally distributed sample.
void setScanRangeValidity(const size_t i, const bool val)



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