Main MRPT website > C++ reference for MRPT 1.9.9
test.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 // Refer to the description in the wiki:
11 // http://www.mrpt.org/Kalman_Filters
12 // ------------------------------------------------------
13 
16 
18 #include <mrpt/random.h>
19 #include <mrpt/system/os.h>
20 #include <mrpt/math/wrap2pi.h>
22 #include <mrpt/obs/CSensoryFrame.h>
24 #include <iostream>
25 
26 using namespace mrpt;
27 using namespace mrpt::bayes;
28 using namespace mrpt::gui;
29 using namespace mrpt::math;
30 using namespace mrpt::obs;
31 using namespace mrpt::random;
32 using namespace std;
33 
34 #define BEARING_SENSOR_NOISE_STD DEG2RAD(15.0f)
35 #define RANGE_SENSOR_NOISE_STD 0.3f
36 #define DELTA_TIME 0.1f
37 
38 #define VEHICLE_INITIAL_X 4.0f
39 #define VEHICLE_INITIAL_Y 4.0f
40 #define VEHICLE_INITIAL_V 1.0f
41 #define VEHICLE_INITIAL_W DEG2RAD(20.0f)
42 
43 #define TRANSITION_MODEL_STD_XY 0.03f
44 #define TRANSITION_MODEL_STD_VXY 0.20f
45 
46 #define NUM_PARTICLES 2000
47 
48 // Uncomment to save text files with grount truth vs. estimated states
49 //#define SAVE_GT_LOGS
50 
51 // ------------------------------------------------------
52 // Implementation of the system models as a EKF
53 // ------------------------------------------------------
55  4 /* x y vx vy*/, 2 /* range yaw */, 0, 1 /* Atime */>
56 // <size_t VEH_SIZE, size_t OBS_SIZE, size_t FEAT_SIZE, size_t
57 // ACT_SIZE, size typename kftype = double>
58 {
59  public:
60  CRangeBearing();
61  virtual ~CRangeBearing();
62 
63  void doProcess(
64  double DeltaTime, double observationRange, double observationBearing);
65 
66  void getState(KFVector& xkk, KFMatrix& pkk)
67  {
68  xkk = m_xkk;
69  pkk = m_pkk;
70  }
71 
72  protected:
73  float m_obsBearing, m_obsRange;
74  float m_deltaTime;
75 
76  /** @name Virtual methods for Kalman Filter implementation
77  @{
78  */
79 
80  /** Must return the action vector u.
81  * \param out_u The action vector which will be passed to OnTransitionModel
82  */
83  void OnGetAction(KFArray_ACT& out_u) const;
84 
85  /** Implements the transition model \f$ \hat{x}_{k|k-1} = f(
86  * \hat{x}_{k-1|k-1}, u_k ) \f$
87  * \param in_u The vector returned by OnGetAction.
88  * \param inout_x At input has \f$ \hat{x}_{k-1|k-1} \f$, at output must
89  * have \f$ \hat{x}_{k|k-1} \f$.
90  * \param out_skip Set this to true if for some reason you want to skip the
91  * prediction step (to do not modify either the vector or the covariance).
92  * Default:false
93  */
94  void OnTransitionModel(
95  const KFArray_ACT& in_u, KFArray_VEH& inout_x,
96  bool& out_skipPrediction) const;
97 
98  /** Implements the transition Jacobian \f$ \frac{\partial f}{\partial x} \f$
99  * \param out_F Must return the Jacobian.
100  * The returned matrix must be \f$N \times N\f$ with N being either the
101  * size of the whole state vector or get_vehicle_size().
102  */
103  void OnTransitionJacobian(KFMatrix_VxV& out_F) const;
104 
105  /** Implements the transition noise covariance \f$ Q_k \f$
106  * \param out_Q Must return the covariance matrix.
107  * The returned matrix must be of the same size than the jacobian from
108  * OnTransitionJacobian
109  */
110  void OnTransitionNoise(KFMatrix_VxV& out_Q) const;
111 
112  /** Return the observation NOISE covariance matrix, that is, the model of
113  * the Gaussian additive noise of the sensor.
114  * \param out_R The noise covariance matrix. It might be non diagonal, but
115  * it'll usually be.
116  * \note Upon call, it can be assumed that the previous contents of out_R
117  * are all zeros.
118  */
119  void OnGetObservationNoise(KFMatrix_OxO& out_R) const;
120 
121  /** This is called between the KF prediction step and the update step, and
122  * the application must return the observations and, when applicable, the
123  * data association between these observations and the current map.
124  *
125  * \param out_z N vectors, each for one "observation" of length OBS_SIZE, N
126  * being the number of "observations": how many observed landmarks for a
127  * map, or just one if not applicable.
128  * \param out_data_association An empty vector or, where applicable, a
129  * vector where the i'th element corresponds to the position of the
130  * observation in the i'th row of out_z within the system state vector (in
131  * the range [0,getNumberOfLandmarksInTheMap()-1]), or -1 if it is a new map
132  * element and we want to insert it at the end of this KF iteration.
133  * \param in_all_predictions A vector with the prediction of ALL the
134  * landmarks in the map. Note that, in contrast, in_S only comprises a
135  * subset of all the landmarks.
136  * \param in_S The full covariance matrix of the observation predictions
137  * (i.e. the "innovation covariance matrix"). This is a M·O x M·O matrix
138  * with M=length of "in_lm_indices_in_S".
139  * \param in_lm_indices_in_S The indices of the map landmarks (range
140  * [0,getNumberOfLandmarksInTheMap()-1]) that can be found in the matrix
141  * in_S.
142  *
143  * This method will be called just once for each complete KF iteration.
144  * \note It is assumed that the observations are independent, i.e. there
145  * are NO cross-covariances between them.
146  */
147  void OnGetObservationsAndDataAssociation(
148  vector_KFArray_OBS& out_z, std::vector<int>& out_data_association,
149  const vector_KFArray_OBS& in_all_predictions, const KFMatrix& in_S,
150  const std::vector<size_t>& in_lm_indices_in_S,
151  const KFMatrix_OxO& in_R);
152 
153  /** Implements the observation prediction \f$ h_i(x) \f$.
154  * \param idx_landmark_to_predict The indices of the landmarks in the map
155  * whose predictions are expected as output. For non SLAM-like problems,
156  * this input value is undefined and the application should just generate
157  * one observation for the given problem.
158  * \param out_predictions The predicted observations.
159  */
160  void OnObservationModel(
161  const std::vector<size_t>& idx_landmarks_to_predict,
162  vector_KFArray_OBS& out_predictions) const;
163 
164  /** Implements the observation Jacobians \f$ \frac{\partial h_i}{\partial x}
165  * \f$ and (when applicable) \f$ \frac{\partial h_i}{\partial y_i} \f$.
166  * \param idx_landmark_to_predict The index of the landmark in the map
167  * whose prediction is expected as output. For non SLAM-like problems, this
168  * will be zero and the expected output is for the whole state vector.
169  * \param Hx The output Jacobian \f$ \frac{\partial h_i}{\partial x} \f$.
170  * \param Hy The output Jacobian \f$ \frac{\partial h_i}{\partial y_i}
171  * \f$.
172  */
173  void OnObservationJacobians(
174  const size_t& idx_landmark_to_predict, KFMatrix_OxV& Hx,
175  KFMatrix_OxF& Hy) const;
176 
177  /** Computes A=A-B, which may need to be re-implemented depending on the
178  * topology of the individual scalar components (eg, angles).
179  */
180  void OnSubstractObservationVectors(
181  KFArray_OBS& A, const KFArray_OBS& B) const;
182 
183  /** @}
184  */
185 };
186 
187 // ---------------------------------------------------------------
188 // Implementation of the system models as a Particle Filter
189 // ---------------------------------------------------------------
191 {
192  float x, y, vx, vy; // Vehicle state (position & velocities)
193 };
194 
196  : public mrpt::bayes::CParticleFilterData<CParticleVehicleData>,
198  CRangeBearingParticleFilter,
199  mrpt::bayes::CParticleFilterData<CParticleVehicleData>::CParticleList>
200 {
201  public:
202  /** Update the m_particles, predicting the posterior of robot pose and map
203  * after a movement command.
204  * This method has additional configuration parameters in "options".
205  * Performs the update stage of the RBPF, using the sensed Sensorial Frame:
206  *
207  * \param action This is a pointer to CActionCollection, containing the
208  * pose change the robot has been commanded.
209  * \param observation This must be a pointer to a CSensoryFrame object,
210  * with robot sensed observations.
211  *
212  * \sa options
213  */
214  void prediction_and_update_pfStandardProposal(
215  const mrpt::obs::CActionCollection* action,
216  const mrpt::obs::CSensoryFrame* observation,
218 
219  void initializeParticles(size_t numParticles);
220 
221  /** Computes the average velocity & position
222  */
223  void getMean(float& x, float& y, float& vx, float& vy);
224 };
225 
226 // ------------------------------------------------------
227 // TestBayesianTracking
228 // ------------------------------------------------------
230 {
232 
233  CDisplayWindowPlots winEKF("Tracking - Extended Kalman Filter", 450, 400);
234  CDisplayWindowPlots winPF("Tracking - Particle Filter", 450, 400);
235 
236  winEKF.setPos(10, 10);
237  winPF.setPos(480, 10);
238 
239  winEKF.axis(-2, 20, -10, 10);
240  winEKF.axis_equal();
241  winPF.axis(-2, 20, -10, 10);
242  winPF.axis_equal();
243 
244  // Create EKF
245  // ----------------------
246  CRangeBearing EKF;
248 
250  EKF.KF_options.enable_profiler = true;
251 
252  // Create PF
253  // ----------------------
255  PF_options.adaptiveSampleSize = false;
258 
259  CRangeBearingParticleFilter particles;
261  CParticleFilter PF;
262  PF.m_options = PF_options;
263 
264 #ifdef SAVE_GT_LOGS
265  CFileOutputStream fo_log_ekf("log_GT_vs_EKF.txt");
266  fo_log_ekf.printf(
267  "%%%% GT_X GT_Y EKF_MEAN_X EKF_MEAN_Y EKF_STD_X EKF_STD_Y\n");
268 #endif
269 
270  // Init. simulation:
271  // -------------------------
272  float x = VEHICLE_INITIAL_X, y = VEHICLE_INITIAL_Y, phi = DEG2RAD(-180),
274  float t = 0;
275 
276  while (winEKF.isOpen() && winPF.isOpen() && !mrpt::system::os::kbhit())
277  {
278  // Update vehicle:
279  x += v * DELTA_TIME * (cos(phi) - sin(phi));
280  y += v * DELTA_TIME * (sin(phi) + cos(phi));
281  phi += w * DELTA_TIME;
282 
283  v += 1.0f * DELTA_TIME * cos(t);
284  w -= 0.1f * DELTA_TIME * sin(t);
285 
286  // Simulate noisy observation:
287  float realBearing = atan2(y, x);
288  float obsBearing = realBearing +
291  printf(
292  "Real/Simulated bearing: %.03f / %.03f deg\n", RAD2DEG(realBearing),
293  RAD2DEG(obsBearing));
294 
295  float realRange = sqrt(square(x) + square(y));
296  float obsRange =
297  max(0.0, realRange +
299  getRandomGenerator().drawGaussian1D_normalized());
300  printf("Real/Simulated range: %.03f / %.03f \n", realRange, obsRange);
301 
302  // Process with EKF:
303  EKF.doProcess(DELTA_TIME, obsRange, obsBearing);
304 
305  // Process with PF:
306  CSensoryFrame SF;
307  CObservationBearingRange::Ptr obsRangeBear =
308  mrpt::make_aligned_shared<CObservationBearingRange>();
309  obsRangeBear->sensedData.resize(1);
310  obsRangeBear->sensedData[0].range = obsRange;
311  obsRangeBear->sensedData[0].yaw = obsBearing;
312  SF.insert(obsRangeBear); // memory freed by SF.
313 
314  EKF.getProfiler().enter("PF:complete_step");
315  PF.executeOn(particles, nullptr, &SF); // Process in the PF
316  EKF.getProfiler().leave("PF:complete_step");
317 
318  // Show EKF state:
319  CRangeBearing::KFVector EKF_xkk;
320  CRangeBearing::KFMatrix EKF_pkk;
321 
322  EKF.getState(EKF_xkk, EKF_pkk);
323 
324  printf(
325  "Real: x:%.03f y=%.03f heading=%.03f v=%.03f w=%.03f\n", x, y, phi,
326  v, w);
327  cout << "EKF: " << EKF_xkk << endl;
328 
329  // Show PF state:
330  cout << "Particle filter ESS: " << particles.ESS() << endl;
331 
332  // Draw EKF state:
333  CRangeBearing::KFMatrix COVXY(2, 2);
334  COVXY(0, 0) = EKF_pkk(0, 0);
335  COVXY(1, 1) = EKF_pkk(1, 1);
336  COVXY(0, 1) = COVXY(1, 0) = EKF_pkk(0, 1);
337 
338  winEKF.plotEllipse(
339  EKF_xkk[0], EKF_xkk[1], COVXY, 3, "b-2", "ellipse_EKF");
340 
341 // Save GT vs EKF state:
342 #ifdef SAVE_GT_LOGS
343  // %% GT_X GT_Y EKF_MEAN_X EKF_MEAN_Y EKF_STD_X EKF_STD_Y:
344  fo_log_ekf.printf(
345  "%f %f %f %f %f %f\n", x, y, // Real (GT)
346  EKF_xkk[0], EKF_xkk[1], std::sqrt(EKF_pkk(0, 0)),
347  std::sqrt(EKF_pkk(1, 1)));
348 #endif
349 
350  // Draw the velocity vector:
351  vector<float> vx(2), vy(2);
352  vx[0] = EKF_xkk[0];
353  vx[1] = vx[0] + EKF_xkk[2] * 1;
354  vy[0] = EKF_xkk[1];
355  vy[1] = vy[0] + EKF_xkk[3] * 1;
356  winEKF.plot(vx, vy, "g-4", "velocityEKF");
357 
358  // Draw PF state:
359  {
360  size_t i, N = particles.m_particles.size();
361  vector<float> parts_x(N), parts_y(N);
362  for (i = 0; i < N; i++)
363  {
364  parts_x[i] = particles.m_particles[i].d->x;
365  parts_y[i] = particles.m_particles[i].d->y;
366  }
367 
368  winPF.plot(parts_x, parts_y, "b.2", "particles");
369 
370  // Draw PF velocities:
371  float avrg_x, avrg_y, avrg_vx, avrg_vy;
372 
373  particles.getMean(avrg_x, avrg_y, avrg_vx, avrg_vy);
374 
375  vector<float> vx(2), vy(2);
376  vx[0] = avrg_x;
377  vx[1] = vx[0] + avrg_vx * 1;
378  vy[0] = avrg_y;
379  vy[1] = vy[0] + avrg_vy * 1;
380  winPF.plot(vx, vy, "g-4", "velocityPF");
381  }
382 
383  // Draw GT:
384  winEKF.plot(vector<float>(1, x), vector<float>(1, y), "k.8", "plot_GT");
385  winPF.plot(vector<float>(1, x), vector<float>(1, y), "k.8", "plot_GT");
386 
387  // Draw noisy observations:
388  vector<float> obs_x(2), obs_y(2);
389  obs_x[0] = obs_y[0] = 0;
390  obs_x[1] = obsRange * cos(obsBearing);
391  obs_y[1] = obsRange * sin(obsBearing);
392 
393  winEKF.plot(obs_x, obs_y, "r", "plot_obs_ray");
394  winPF.plot(obs_x, obs_y, "r", "plot_obs_ray");
395 
396  // Delay:
397  std::this_thread::sleep_for(
398  std::chrono::milliseconds((int)(DELTA_TIME * 1000)));
399  t += DELTA_TIME;
400  }
401 }
402 
403 // ------------------------------------------------------
404 // MAIN
405 // ------------------------------------------------------
406 int main()
407 {
408  try
409  {
411  return 0;
412  }
413  catch (std::exception& e)
414  {
415  std::cout << "MRPT exception caught: " << e.what() << std::endl;
416  return -1;
417  }
418  catch (...)
419  {
420  printf("Untyped exception!!");
421  return -1;
422  }
423 }
424 
426 {
427  // KF_options.method = kfEKFNaive;
428  KF_options.method = kfEKFAlaDavison;
429 
430  // INIT KF STATE
431  m_xkk.resize(4); // State: (x,y,heading,v,w)
432  m_xkk[0] = VEHICLE_INITIAL_X;
433  m_xkk[1] = VEHICLE_INITIAL_Y;
434  m_xkk[2] = -VEHICLE_INITIAL_V;
435  m_xkk[3] = 0;
436 
437  // Initial cov: Large uncertainty
438  m_pkk.setSize(4, 4);
439  m_pkk.unit();
440  m_pkk(0, 0) = m_pkk(1, 1) = square(5.0f);
441  m_pkk(2, 2) = m_pkk(3, 3) = square(1.0f);
442 }
443 
446  double DeltaTime, double observationRange, double observationBearing)
447 {
448  m_deltaTime = (float)DeltaTime;
449  m_obsBearing = (float)observationBearing;
450  m_obsRange = (float)observationRange;
451 
452  runOneKalmanIteration();
453 }
454 
455 /** Must return the action vector u.
456  * \param out_u The action vector which will be passed to OnTransitionModel
457  */
458 void CRangeBearing::OnGetAction(KFArray_ACT& u) const { u[0] = m_deltaTime; }
459 /** Implements the transition model \f$ \hat{x}_{k|k-1} = f( \hat{x}_{k-1|k-1},
460  * u_k ) \f$
461  * \param in_u The vector returned by OnGetAction.
462  * \param inout_x At input has \f$ \hat{x}_{k-1|k-1} \f$, at output must have
463  * \f$ \hat{x}_{k|k-1} \f$.
464  * \param out_skip Set this to true if for some reason you want to skip the
465  * prediction step (to do not modify either the vector or the covariance).
466  * Default:false
467  */
469  const KFArray_ACT& in_u, KFArray_VEH& inout_x,
470  bool& out_skipPrediction) const
471 {
472  // in_u[0] : Delta time
473  // in_out_x: [0]:x [1]:y [2]:vx [3]: vy
474  inout_x[0] += in_u[0] * inout_x[2];
475  inout_x[1] += in_u[0] * inout_x[3];
476 }
477 
478 /** Implements the transition Jacobian \f$ \frac{\partial f}{\partial x} \f$
479  * \param out_F Must return the Jacobian.
480  * The returned matrix must be \f$N \times N\f$ with N being either the size
481  * of the whole state vector or get_vehicle_size().
482  */
483 void CRangeBearing::OnTransitionJacobian(KFMatrix_VxV& F) const
484 {
485  F.unit();
486 
487  F(0, 2) = m_deltaTime;
488  F(1, 3) = m_deltaTime;
489 }
490 
491 /** Implements the transition noise covariance \f$ Q_k \f$
492  * \param out_Q Must return the covariance matrix.
493  * The returned matrix must be of the same size than the jacobian from
494  * OnTransitionJacobian
495  */
496 void CRangeBearing::OnTransitionNoise(KFMatrix_VxV& Q) const
497 {
498  Q(0, 0) = Q(1, 1) = square(TRANSITION_MODEL_STD_XY);
499  Q(2, 2) = Q(3, 3) = square(TRANSITION_MODEL_STD_VXY);
500 }
501 
502 /** Return the observation NOISE covariance matrix, that is, the model of the
503  * Gaussian additive noise of the sensor.
504  * \param out_R The noise covariance matrix. It might be non diagonal, but it'll
505  * usually be.
506  * \note Upon call, it can be assumed that the previous contents of out_R are
507  * all zeros.
508  */
509 void CRangeBearing::OnGetObservationNoise(KFMatrix_OxO& R) const
510 {
513 }
514 
516  vector_KFArray_OBS& out_z, std::vector<int>& out_data_association,
517  const vector_KFArray_OBS& in_all_predictions, const KFMatrix& in_S,
518  const std::vector<size_t>& in_lm_indices_in_S, const KFMatrix_OxO& in_R)
519 {
520  out_z.resize(1);
521  out_z[0][0] = m_obsBearing;
522  out_z[0][1] = m_obsRange;
523 
524  out_data_association.clear(); // Not used
525 }
526 
527 /** Implements the observation prediction \f$ h_i(x) \f$.
528  * \param idx_landmark_to_predict The indices of the landmarks in the map whose
529  * predictions are expected as output. For non SLAM-like problems, this input
530  * value is undefined and the application should just generate one observation
531  * for the given problem.
532  * \param out_predictions The predicted observations.
533  */
535  const std::vector<size_t>& idx_landmarks_to_predict,
536  vector_KFArray_OBS& out_predictions) const
537 {
538  // predicted bearing:
539  kftype x = m_xkk[0];
540  kftype y = m_xkk[1];
541 
542  kftype h_bear = atan2(y, x);
543  kftype h_range = sqrt(square(x) + square(y));
544 
545  // idx_landmarks_to_predict is ignored in NON-SLAM problems
546  out_predictions.resize(1);
547  out_predictions[0][0] = h_bear;
548  out_predictions[0][1] = h_range;
549 }
550 
551 /** Implements the observation Jacobians \f$ \frac{\partial h_i}{\partial x} \f$
552  * and (when applicable) \f$ \frac{\partial h_i}{\partial y_i} \f$.
553  * \param idx_landmark_to_predict The index of the landmark in the map whose
554  * prediction is expected as output. For non SLAM-like problems, this will be
555  * zero and the expected output is for the whole state vector.
556  * \param Hx The output Jacobian \f$ \frac{\partial h_i}{\partial x} \f$.
557  * \param Hy The output Jacobian \f$ \frac{\partial h_i}{\partial y_i} \f$.
558  */
560  const size_t& idx_landmark_to_predict, KFMatrix_OxV& Hx,
561  KFMatrix_OxF& Hy) const
562 {
563  // predicted bearing:
564  kftype x = m_xkk[0];
565  kftype y = m_xkk[1];
566 
567  Hx.zeros();
568  Hx(0, 0) = -y / (square(x) + square(y));
569  Hx(0, 1) = 1 / (x * (1 + square(y / x)));
570 
571  Hx(1, 0) = x / sqrt(square(x) + square(y));
572  Hx(1, 1) = y / sqrt(square(x) + square(y));
573 
574  // Hy: Not used
575 }
576 
577 /** Computes A=A-B, which may need to be re-implemented depending on the
578  * topology of the individual scalar components (eg, angles).
579  */
581  KFArray_OBS& A, const KFArray_OBS& B) const
582 {
583  A -= B;
584  math::wrapToPiInPlace(A[0]); // The angular component
585 }
586 
587 /** Update the m_particles, predicting the posterior of robot pose and map after
588  * a movement command.
589  * This method has additional configuration parameters in "options".
590  * Performs the update stage of the RBPF, using the sensed Sensorial Frame:
591  *
592  * \param action This is a pointer to CActionCollection, containing the pose
593  * change the robot has been commanded.
594  * \param observation This must be a pointer to a CSensoryFrame object, with
595  * robot sensed observations.
596  *
597  * \sa options
598  */
600  const mrpt::obs::CActionCollection* action,
601  const mrpt::obs::CSensoryFrame* observation,
603 {
604  size_t i, N = m_particles.size();
605 
606  // Transition model:
607  for (i = 0; i < N; i++)
608  {
609  m_particles[i].d->x +=
610  DELTA_TIME * m_particles[i].d->vx +
613  m_particles[i].d->y +=
614  DELTA_TIME * m_particles[i].d->vy +
617 
618  m_particles[i].d->vx +=
621  m_particles[i].d->vy +=
624  }
625 
628  ASSERT_(obs);
629  ASSERT_(obs->sensedData.size() == 1);
630  float obsRange = obs->sensedData[0].range;
631  float obsBearing = obs->sensedData[0].yaw;
632 
633  // Update weights
634  for (i = 0; i < N; i++)
635  {
636  float predicted_range =
637  sqrt(square(m_particles[i].d->x) + square(m_particles[i].d->y));
638  float predicted_bearing =
639  atan2(m_particles[i].d->y, m_particles[i].d->x);
640 
641  m_particles[i].log_w +=
642  log(math::normalPDF(
643  predicted_range - obsRange, 0, RANGE_SENSOR_NOISE_STD)) +
644  log(math::normalPDF(
645  math::wrapToPi(predicted_bearing - obsBearing), 0,
647  }
648 
649  // Resample is automatically performed by CParticleFilter when required.
650 }
651 
653 {
654  clearParticles();
655  m_particles.resize(M);
656  for (CParticleList::iterator it = m_particles.begin();
657  it != m_particles.end(); it++)
658  it->d.reset(new CParticleVehicleData());
659 
660  for (CParticleList::iterator it = m_particles.begin();
661  it != m_particles.end(); it++)
662  {
663  (*it).d->x = getRandomGenerator().drawUniform(
664  VEHICLE_INITIAL_X - 2.0f, VEHICLE_INITIAL_X + 2.0f);
665  (*it).d->y = getRandomGenerator().drawUniform(
666  VEHICLE_INITIAL_Y - 2.0f, VEHICLE_INITIAL_Y + 2.0f);
667 
668  (*it).d->vx =
670  (*it).d->vy = getRandomGenerator().drawGaussian1D(0, 0.2f);
671 
672  it->log_w = 0;
673  }
674 }
675 
676 /** Computes the average velocity
677  */
679  float& x, float& y, float& vx, float& vy)
680 {
681  double sumW = 0;
682  for (CParticleList::iterator it = m_particles.begin();
683  it != m_particles.end(); it++)
684  sumW += exp(it->log_w);
685 
686  ASSERT_(sumW > 0);
687 
688  x = y = vx = vy = 0;
689 
690  for (CParticleList::iterator it = m_particles.begin();
691  it != m_particles.end(); it++)
692  {
693  const double w = exp(it->log_w) / sumW;
694 
695  x += (float)w * (*it).d->x;
696  y += (float)w * (*it).d->y;
697  vx += (float)w * (*it).d->vx;
698  vy += (float)w * (*it).d->vy;
699  }
700 }
mrpt::bayes::CKalmanFilterCapable::KF_options
TKF_options KF_options
Generic options for the Kalman Filter algorithm itself.
Definition: CKalmanFilterCapable.h:618
mrpt::system::os::kbhit
bool kbhit() noexcept
An OS-independent version of kbhit, which returns true if a key has been pushed.
Definition: os.cpp:390
os.h
TRANSITION_MODEL_STD_VXY
#define TRANSITION_MODEL_STD_VXY
Definition: vision_stereo_rectify/test.cpp:44
mrpt::bayes::CParticleFilter::prSystematic
@ prSystematic
Definition: CParticleFilter.h:97
mrpt::bayes::CParticleFilter::TParticleFilterOptions::adaptiveSampleSize
bool adaptiveSampleSize
A flag that indicates whether the CParticleFilterCapable object should perform adative sample size (d...
Definition: CParticleFilter.h:115
mrpt::random::CRandomGenerator::drawGaussian1D_normalized
double drawGaussian1D_normalized()
Generate a normalized (mean=0, std=1) normally distributed sample.
Definition: RandomGenerator.cpp:42
mrpt::bayes::CParticleFilter::executeOn
void executeOn(CParticleFilterCapable &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.
Definition: CParticleFilter.cpp:45
TestBayesianTracking
void TestBayesianTracking()
Definition: vision_stereo_rectify/test.cpp:229
t
GLdouble GLdouble t
Definition: glext.h:3689
mrpt::bayes::TKF_options::method
TKFMethod method
The method to employ (default: kfEKFNaive)
Definition: CKalmanFilterCapable.h:106
mrpt::bayes::CParticleFilter::m_options
CParticleFilter::TParticleFilterOptions m_options
The options to be used in the PF, must be set before executing any step of the particle filter.
Definition: CParticleFilter.h:209
RANGE_SENSOR_NOISE_STD
#define RANGE_SENSOR_NOISE_STD
Definition: vision_stereo_rectify/test.cpp:35
CRangeBearing::CRangeBearing
CRangeBearing()
Definition: vision_stereo_rectify/test.cpp:425
CRangeBearing::doProcess
void doProcess(double DeltaTime, double observationRange, double observationBearing)
Definition: vision_stereo_rectify/test.cpp:445
CRangeBearing::OnTransitionJacobian
void OnTransitionJacobian(KFMatrix_VxV &out_F) const
Implements the transition Jacobian .
Definition: vision_stereo_rectify/test.cpp:483
mrpt::bayes::CParticleFilter
This class acts as a common interface to the different interfaces (see CParticleFilter::TParticleFilt...
Definition: CParticleFilter.h:51
VEHICLE_INITIAL_Y
#define VEHICLE_INITIAL_Y
Definition: vision_stereo_rectify/test.cpp:39
CParticleFilterData.h
mrpt::bayes::TKF_options::enable_profiler
bool enable_profiler
If enabled (default=false), detailed timing information will be dumped to the console thru a CTimerLo...
Definition: CKalmanFilterCapable.h:112
CRangeBearing::OnObservationModel
void OnObservationModel(const std::vector< size_t > &idx_landmarks_to_predict, vector_KFArray_OBS &out_predictions) const
Implements the observation prediction .
Definition: vision_stereo_rectify/test.cpp:534
mrpt::obs::CObservationBearingRange::Ptr
std::shared_ptr< CObservationBearingRange > Ptr
Definition: CObservationBearingRange.h:33
wrap2pi.h
CRangeBearing::OnGetObservationNoise
void OnGetObservationNoise(KFMatrix_OxO &out_R) const
Return the observation NOISE covariance matrix, that is, the model of the Gaussian additive noise of ...
Definition: vision_stereo_rectify/test.cpp:509
NUM_PARTICLES
#define NUM_PARTICLES
Definition: vision_stereo_rectify/test.cpp:46
mrpt::obs::CActionCollection
Declares a class for storing a collection of robot actions.
Definition: CActionCollection.h:28
mrpt
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
Definition: CKalmanFilterCapable.h:30
w
GLubyte GLubyte GLubyte GLubyte w
Definition: glext.h:4178
R
const float R
Definition: CKinematicChain.cpp:138
ASSERT_
#define ASSERT_(f)
Defines an assertion mechanism.
Definition: exceptions.h:113
mrpt::square
T square(const T x)
Inline function for the square of a number.
Definition: core/include/mrpt/core/bits_math.h:18
mrpt::RAD2DEG
double RAD2DEG(const double x)
Radians to degrees.
Definition: core/include/mrpt/core/bits_math.h:48
mrpt::math::wrapToPiInPlace
void wrapToPiInPlace(T &a)
Modifies the given angle to translate it into the ]-pi,pi] range.
Definition: wrap2pi.h:64
mrpt::bayes::kfEKFNaive
@ kfEKFNaive
Definition: CKalmanFilterCapable.h:42
mrpt::system::CTimeLogger::enter
void enter(const char *func_name)
Start of a named section.
Definition: system/CTimeLogger.h:116
mrpt::bayes::CParticleFilter::TParticleFilterOptions::PF_algorithm
TParticleFilterAlgorithm PF_algorithm
The PF algorithm to use (default=pfStandardProposal) See TParticleFilterAlgorithm for the posibilitie...
Definition: CParticleFilter.h:136
mrpt::obs
This namespace contains representation of robot actions and observations.
Definition: CParticleFilter.h:17
BEARING_SENSOR_NOISE_STD
#define BEARING_SENSOR_NOISE_STD
Definition: vision_stereo_rectify/test.cpp:34
CRangeBearingParticleFilter::prediction_and_update_pfStandardProposal
void prediction_and_update_pfStandardProposal(const mrpt::obs::CActionCollection *action, const mrpt::obs::CSensoryFrame *observation, const bayes::CParticleFilter::TParticleFilterOptions &PF_options)
Update the m_particles, predicting the posterior of robot pose and map after a movement command.
Definition: vision_stereo_rectify/test.cpp:599
mrpt::math::normalPDF
double normalPDF(double x, double mu, double std)
Evaluates the univariate normal (Gaussian) distribution at a given point "x".
Definition: math.cpp:33
random.h
mrpt::system::CTimeLogger::leave
double leave(const char *func_name)
End of a named section.
Definition: system/CTimeLogger.h:122
mrpt::random::CRandomGenerator::randomize
void randomize(const uint32_t seed)
Initialize the PRNG from the given random seed.
Definition: RandomGenerator.cpp:32
mrpt::bayes::CParticleFilter::pfStandardProposal
@ pfStandardProposal
Definition: CParticleFilter.h:72
mrpt::math::CMatrixTemplateNumeric< double >
v
const GLdouble * v
Definition: glext.h:3678
main
int main()
Definition: vision_stereo_rectify/test.cpp:78
mrpt::obs::CSensoryFrame
Declares a class for storing a "sensory frame", a set of "observations" taken by the robot approximat...
Definition: CSensoryFrame.h:54
CRangeBearingParticleFilter::initializeParticles
void initializeParticles(size_t numParticles)
Definition: vision_stereo_rectify/test.cpp:652
mrpt::bayes::CKalmanFilterCapable< 4, 2, 0, 1 >::KFVector
Eigen::Matrix< double, Eigen::Dynamic, 1 > KFVector
Definition: CKalmanFilterCapable.h:242
CObservationBearingRange.h
mrpt::math::wrapToPi
T wrapToPi(T a)
Modifies the given angle to translate it into the ]-pi,pi] range.
Definition: wrap2pi.h:53
mrpt::random::CRandomGenerator::drawUniform
double drawUniform(const double Min, const double Max)
Generate a uniformly distributed pseudo-random number using the MT19937 algorithm,...
Definition: RandomGenerators.h:111
mrpt::bayes::kfEKFAlaDavison
@ kfEKFAlaDavison
Definition: CKalmanFilterCapable.h:43
mrpt::obs::CSensoryFrame::getObservationByClass
T::Ptr getObservationByClass(const size_t &ith=0) const
Returns the i'th observation of a given class (or of a descendant class), or nullptr if there is no s...
Definition: CSensoryFrame.h:213
DELTA_TIME
#define DELTA_TIME
Definition: vision_stereo_rectify/test.cpp:36
CRangeBearingParticleFilter
Definition: vision_stereo_rectify/test.cpp:195
distributions.h
VEHICLE_INITIAL_V
#define VEHICLE_INITIAL_V
Definition: vision_stereo_rectify/test.cpp:40
mrpt::obs::CSensoryFrame::insert
void insert(const CObservation::Ptr &obs)
Inserts a new observation to the list: The pointer to the objects is copied, thus DO NOT delete the p...
Definition: CSensoryFrame.cpp:139
mrpt::bayes::CParticleFilterData
This template class declares the array of particles and its internal data, managing some memory-relat...
Definition: CParticleFilterData.h:206
CRangeBearing::OnTransitionModel
void OnTransitionModel(const KFArray_ACT &in_u, KFArray_VEH &inout_x, bool &out_skipPrediction) const
Implements the transition model .
Definition: vision_stereo_rectify/test.cpp:468
CRangeBearing::OnGetObservationsAndDataAssociation
void OnGetObservationsAndDataAssociation(vector_KFArray_OBS &out_z, std::vector< int > &out_data_association, const vector_KFArray_OBS &in_all_predictions, const KFMatrix &in_S, const std::vector< size_t > &in_lm_indices_in_S, const KFMatrix_OxO &in_R)
This is called between the KF prediction step and the update step, and the application must return th...
Definition: vision_stereo_rectify/test.cpp:515
mrpt::obs::CObservationBearingRange
This observation represents a number of range-bearing value pairs, each one for a detected landmark,...
Definition: CObservationBearingRange.h:31
CRangeBearing::OnGetAction
void OnGetAction(KFArray_ACT &out_u) const
Must return the action vector u.
Definition: vision_stereo_rectify/test.cpp:458
VEHICLE_INITIAL_X
#define VEHICLE_INITIAL_X
Definition: vision_stereo_rectify/test.cpp:38
CRangeBearing::OnSubstractObservationVectors
void OnSubstractObservationVectors(KFArray_OBS &A, const KFArray_OBS &B) const
Computes A=A-B, which may need to be re-implemented depending on the topology of the individual scala...
Definition: vision_stereo_rectify/test.cpp:580
mrpt::gui
Classes for creating GUI windows for 2D and 3D visualization.
Definition: about_box.h:16
mrpt::gui::CDisplayWindowPlots
Create a GUI window and display plots with MATLAB-like interfaces and commands.
Definition: CDisplayWindowPlots.h:31
CSensoryFrame.h
CRangeBearing::~CRangeBearing
virtual ~CRangeBearing()
Definition: vision_stereo_rectify/test.cpp:444
mrpt::bayes::CParticleFilterData::m_particles
CParticleList m_particles
The array of particles.
Definition: CParticleFilterData.h:218
mrpt::system::LVL_DEBUG
@ LVL_DEBUG
Definition: system/COutputLogger.h:30
TRANSITION_MODEL_STD_XY
#define TRANSITION_MODEL_STD_XY
Definition: vision_stereo_rectify/test.cpp:43
mrpt::bayes::TKF_options::verbosity_level
mrpt::system::VerbosityLevel & verbosity_level
Definition: CKalmanFilterCapable.h:107
mrpt::random::getRandomGenerator
CRandomGenerator & getRandomGenerator()
A static instance of a CRandomGenerator class, for use in single-thread applications.
Definition: RandomGenerator.cpp:19
mrpt::bayes
The namespace for Bayesian filtering algorithm: different particle filters and Kalman filter algorith...
Definition: CKalmanFilterCapable.h:32
CRangeBearing::OnTransitionNoise
void OnTransitionNoise(KFMatrix_VxV &out_Q) const
Implements the transition noise covariance .
Definition: vision_stereo_rectify/test.cpp:496
CKalmanFilterCapable.h
mrpt::math
This base provides a set of functions for maths stuff.
Definition: math/include/mrpt/math/bits_math.h:13
CRangeBearing::OnObservationJacobians
void OnObservationJacobians(const size_t &idx_landmark_to_predict, KFMatrix_OxV &Hx, KFMatrix_OxF &Hy) const
Implements the observation Jacobians and (when applicable) .
Definition: vision_stereo_rectify/test.cpp:559
mrpt::utils::CFileOutputStream
mrpt::io::CFileOutputStream CFileOutputStream
Definition: utils/CFileOutputStream.h:7
mrpt::random
A namespace of pseudo-random numbers generators of diferent distributions.
Definition: random_shuffle.h:17
iterator
Scalar * iterator
Definition: eigen_plugins.h:26
mrpt::bayes::CParticleFilterDataImpl
A curiously recurring template pattern (CRTP) approach to providing the basic functionality of any CP...
Definition: CParticleFilterData.h:33
CParticleVehicleData
Definition: vision_stereo_rectify/test.cpp:190
mrpt::bayes::CKalmanFilterCapable::getProfiler
mrpt::system::CTimeLogger & getProfiler()
Definition: CKalmanFilterCapable.h:616
mrpt::random::CRandomGenerator::drawGaussian1D
double drawGaussian1D(const double mean, const double std)
Generate a normally distributed pseudo-random number.
Definition: RandomGenerators.h:162
CRangeBearing::getState
void getState(KFVector &xkk, KFMatrix &pkk)
Definition: vision_stereo_rectify/test.cpp:66
CDisplayWindowPlots.h
mrpt::bayes::CParticleFilter::TParticleFilterOptions::resamplingMethod
TParticleResamplingAlgorithm resamplingMethod
The resampling algorithm to use (default=prMultinomial).
Definition: CParticleFilter.h:138
mrpt::bayes::CParticleFilter::TParticleFilterOptions
The configuration of a particle filter.
Definition: CParticleFilter.h:102
CRangeBearing
Definition: vision_stereo_rectify/test.cpp:54
mrpt::bayes::CKalmanFilterCapable
Virtual base for Kalman Filter (EKF,IEKF,UKF) implementations.
Definition: CKalmanFilterCapable.h:52
mrpt::bayes::CParticleFilterDataImpl::ESS
double ESS() const override
Returns the normalized ESS (Estimated Sample Size), in the range [0,1].
Definition: CParticleFilterData.h:88
y
GLenum GLint GLint y
Definition: glext.h:3538
VEHICLE_INITIAL_W
#define VEHICLE_INITIAL_W
Definition: vision_stereo_rectify/test.cpp:41
x
GLenum GLint x
Definition: glext.h:3538
CRangeBearingParticleFilter::getMean
void getMean(float &x, float &y, float &vx, float &vy)
Computes the average velocity & position.
Definition: vision_stereo_rectify/test.cpp:678
mrpt::DEG2RAD
double DEG2RAD(const double x)
Degrees to radians.
Definition: core/include/mrpt/core/bits_math.h:42



Page generated by Doxygen 1.8.17 for MRPT 1.9.9 Git: ad3a9d8ae Tue May 1 23:10:22 2018 -0700 at mié 12 jul 2023 10:03:34 CEST