34 #define BEARING_SENSOR_NOISE_STD DEG2RAD(15.0f) 35 #define RANGE_SENSOR_NOISE_STD 0.3f 36 #define DELTA_TIME 0.1f 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) 43 #define TRANSITION_MODEL_STD_XY 0.03f 44 #define TRANSITION_MODEL_STD_VXY 0.20f 46 #define NUM_PARTICLES 2000 64 double DeltaTime,
double observationRange,
double observationBearing);
66 void getState(KFVector& xkk, KFMatrix& pkk)
73 float m_obsBearing, m_obsRange;
83 void OnGetAction(KFArray_ACT& out_u)
const;
94 void OnTransitionModel(
95 const KFArray_ACT& in_u, KFArray_VEH& inout_x,
96 bool& out_skipPrediction)
const;
103 void OnTransitionJacobian(KFMatrix_VxV& out_F)
const;
110 void OnTransitionNoise(KFMatrix_VxV& out_Q)
const;
119 void OnGetObservationNoise(KFMatrix_OxO& out_R)
const;
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);
160 void OnObservationModel(
161 const std::vector<size_t>& idx_landmarks_to_predict,
162 vector_KFArray_OBS& out_predictions)
const;
173 void OnObservationJacobians(
174 const size_t& idx_landmark_to_predict, KFMatrix_OxV& Hx,
175 KFMatrix_OxF& Hy)
const;
180 void OnSubstractObservationVectors(
181 KFArray_OBS& A,
const KFArray_OBS& B)
const;
198 CRangeBearingParticleFilter,
199 mrpt::bayes::CParticleFilterData<CParticleVehicleData>::CParticleList>
214 void prediction_and_update_pfStandardProposal(
219 void initializeParticles(
size_t numParticles);
223 void getMean(
float&
x,
float&
y,
float& vx,
float& vy);
236 winEKF.setPos(10, 10);
237 winPF.setPos(480, 10);
239 winEKF.axis(-2, 20, -10, 10);
241 winPF.axis(-2, 20, -10, 10);
267 "%%%% GT_X GT_Y EKF_MEAN_X EKF_MEAN_Y EKF_STD_X EKF_STD_Y\n");
287 float realBearing = atan2(
y,
x);
288 float obsBearing = realBearing +
292 "Real/Simulated bearing: %.03f / %.03f deg\n",
RAD2DEG(realBearing),
300 printf(
"Real/Simulated range: %.03f / %.03f \n", realRange, obsRange);
308 mrpt::make_aligned_shared<CObservationBearingRange>();
309 obsRangeBear->sensedData.resize(1);
310 obsRangeBear->sensedData[0].range = obsRange;
311 obsRangeBear->sensedData[0].yaw = obsBearing;
325 "Real: x:%.03f y=%.03f heading=%.03f v=%.03f w=%.03f\n",
x,
y, phi,
327 cout <<
"EKF: " << EKF_xkk << endl;
330 cout <<
"Particle filter ESS: " << particles.
ESS() << endl;
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);
339 EKF_xkk[0], EKF_xkk[1], COVXY, 3,
"b-2",
"ellipse_EKF");
345 "%f %f %f %f %f %f\n",
x,
y,
346 EKF_xkk[0], EKF_xkk[1], std::sqrt(EKF_pkk(0, 0)),
347 std::sqrt(EKF_pkk(1, 1)));
351 vector<float> vx(2), vy(2);
353 vx[1] = vx[0] + EKF_xkk[2] * 1;
355 vy[1] = vy[0] + EKF_xkk[3] * 1;
356 winEKF.plot(vx, vy,
"g-4",
"velocityEKF");
361 vector<float> parts_x(N), parts_y(N);
362 for (i = 0; i < N; i++)
368 winPF.plot(parts_x, parts_y,
"b.2",
"particles");
371 float avrg_x, avrg_y, avrg_vx, avrg_vy;
373 particles.
getMean(avrg_x, avrg_y, avrg_vx, avrg_vy);
375 vector<float> vx(2), vy(2);
377 vx[1] = vx[0] + avrg_vx * 1;
379 vy[1] = vy[0] + avrg_vy * 1;
380 winPF.plot(vx, vy,
"g-4",
"velocityPF");
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");
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);
393 winEKF.plot(obs_x, obs_y,
"r",
"plot_obs_ray");
394 winPF.plot(obs_x, obs_y,
"r",
"plot_obs_ray");
397 std::this_thread::sleep_for(
398 std::chrono::milliseconds((
int)(
DELTA_TIME * 1000)));
413 catch (std::exception& e)
415 std::cout <<
"MRPT exception caught: " << e.what() << std::endl;
420 printf(
"Untyped exception!!");
440 m_pkk(0, 0) = m_pkk(1, 1) =
square(5.0f);
441 m_pkk(2, 2) = m_pkk(3, 3) =
square(1.0f);
446 double DeltaTime,
double observationRange,
double observationBearing)
448 m_deltaTime = (float)DeltaTime;
449 m_obsBearing = (float)observationBearing;
450 m_obsRange = (float)observationRange;
452 runOneKalmanIteration();
469 const KFArray_ACT& in_u, KFArray_VEH& inout_x,
470 bool& out_skipPrediction)
const 474 inout_x[0] += in_u[0] * inout_x[2];
475 inout_x[1] += in_u[0] * inout_x[3];
487 F(0, 2) = m_deltaTime;
488 F(1, 3) = m_deltaTime;
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)
521 out_z[0][0] = m_obsBearing;
522 out_z[0][1] = m_obsRange;
524 out_data_association.clear();
535 const std::vector<size_t>& idx_landmarks_to_predict,
536 vector_KFArray_OBS& out_predictions)
const 542 kftype h_bear = atan2(
y,
x);
546 out_predictions.resize(1);
547 out_predictions[0][0] = h_bear;
548 out_predictions[0][1] = h_range;
560 const size_t& idx_landmark_to_predict, KFMatrix_OxV& Hx,
561 KFMatrix_OxF& Hy)
const 569 Hx(0, 1) = 1 / (
x * (1 +
square(
y /
x)));
581 KFArray_OBS& A,
const KFArray_OBS& B)
const 604 size_t i, N = m_particles.size();
607 for (i = 0; i < N; i++)
609 m_particles[i].d->x +=
613 m_particles[i].d->y +=
618 m_particles[i].d->vx +=
621 m_particles[i].d->vy +=
629 ASSERT_(obs->sensedData.size() == 1);
630 float obsRange = obs->sensedData[0].range;
631 float obsBearing = obs->sensedData[0].yaw;
634 for (i = 0; i < N; i++)
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);
641 m_particles[i].log_w +=
655 m_particles.resize(M);
657 it != m_particles.end(); it++)
661 it != m_particles.end(); it++)
679 float&
x,
float&
y,
float& vx,
float& vy)
683 it != m_particles.end(); it++)
684 sumW += exp(it->log_w);
691 it != m_particles.end(); it++)
693 const double w = exp(it->log_w) / sumW;
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;
A namespace of pseudo-random numbers generators 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.
Eigen::Matrix< double, Eigen::Dynamic, 1 > KFVector
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...
double RAD2DEG(const double x)
Radians to degrees.
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...
Create a GUI window and display plots with MATLAB-like interfaces and commands.
#define RANGE_SENSOR_NOISE_STD
CParticleList m_particles
The array of particles.
void TestBayesianTracking()
double DEG2RAD(const double x)
Degrees to radians.
The namespace for Bayesian filtering algorithm: different particle filters and Kalman filter algorith...
bool enable_profiler
If enabled (default=false), detailed timing information will be dumped to the console thru a CTimerLo...
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...
void randomize(const uint32_t seed)
Initialize the PRNG from the given random seed.
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...
void OnObservationJacobians(const size_t &idx_landmark_to_predict, KFMatrix_OxV &Hx, KFMatrix_OxF &Hy) const
Implements the observation Jacobians and (when applicable) .
double ESS() const override
Returns the normalized ESS (Estimated Sample Size), in the range [0,1].
void OnTransitionNoise(KFMatrix_VxV &out_Q) const
Implements the transition noise covariance .
void OnGetAction(KFArray_ACT &out_u) const
Must return the action vector u.
#define VEHICLE_INITIAL_Y
Declares a class for storing a collection of robot actions.
double drawGaussian1D(const double mean, const double std)
Generate a normally distributed pseudo-random number.
GLubyte GLubyte GLubyte GLubyte w
void getState(KFVector &xkk, KFMatrix &pkk)
T square(const T x)
Inline function for the square of a number.
#define ASSERT_(f)
Defines an assertion mechanism.
void wrapToPiInPlace(T &a)
Modifies the given angle to translate it into the ]-pi,pi] range.
This base provides a set of functions for maths stuff.
TParticleResamplingAlgorithm resamplingMethod
The resampling algorithm to use (default=prMultinomial).
void initializeParticles(size_t numParticles)
mrpt::system::VerbosityLevel & verbosity_level
TKF_options KF_options
Generic options for the Kalman Filter algorithm itself.
#define BEARING_SENSOR_NOISE_STD
Virtual base for Kalman Filter (EKF,IEKF,UKF) implementations.
This namespace contains representation of robot actions and observations.
Declares a class for storing a "sensory frame", a set of "observations" taken by the robot approximat...
void OnTransitionJacobian(KFMatrix_VxV &out_F) const
Implements the transition Jacobian .
double leave(const char *func_name)
End of a named section.
This class acts as a common interface to the different interfaces (see CParticleFilter::TParticleFilt...
#define VEHICLE_INITIAL_V
T wrapToPi(T a)
Modifies the given angle to translate it into the ]-pi,pi] range.
This template class declares the array of particles and its internal data, managing some memory-relat...
void OnObservationModel(const std::vector< size_t > &idx_landmarks_to_predict, vector_KFArray_OBS &out_predictions) const
Implements the observation prediction .
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
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.
#define TRANSITION_MODEL_STD_XY
void getMean(float &x, float &y, float &vx, float &vy)
Computes the average velocity & position.
#define VEHICLE_INITIAL_X
The configuration of a particle filter.
This observation represents a number of range-bearing value pairs, each one for a detected landmark...
bool kbhit() noexcept
An OS-independent version of kbhit, which returns true if a key has been pushed.
mrpt::io::CFileOutputStream CFileOutputStream
Classes for creating GUI windows for 2D and 3D visualization.
TKFMethod method
The method to employ (default: kfEKFNaive)
void doProcess(double DeltaTime, double observationRange, double observationBearing)
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...
CParticleFilter::TParticleFilterOptions m_options
The options to be used in the PF, must be set before executing any step of the particle filter...
CRandomGenerator & getRandomGenerator()
A static instance of a CRandomGenerator class, for use in single-thread applications.
double normalPDF(double x, double mu, double std)
Evaluates the univariate normal (Gaussian) distribution at a given point "x".
mrpt::system::CTimeLogger & getProfiler()
#define VEHICLE_INITIAL_W
void OnGetObservationNoise(KFMatrix_OxO &out_R) const
Return the observation NOISE covariance matrix, that is, the model of the Gaussian additive noise of ...
TParticleFilterAlgorithm PF_algorithm
The PF algorithm to use (default=pfStandardProposal) See TParticleFilterAlgorithm for the posibilitie...
void OnTransitionModel(const KFArray_ACT &in_u, KFArray_VEH &inout_x, bool &out_skipPrediction) const
Implements the transition model .
#define TRANSITION_MODEL_STD_VXY
void enter(const char *func_name)
Start of a named section.
A curiously recurring template pattern (CRTP) approach to providing the basic functionality of any CP...
bool adaptiveSampleSize
A flag that indicates whether the CParticleFilterCapable object should perform adative sample size (d...
double drawGaussian1D_normalized()
Generate a normalized (mean=0, std=1) normally distributed sample.