64 const CActionCollectionPtr &actions,
65 const CSensoryFramePtr &sf )
83 it->d->robotPoses[ currentPoseID ] = initPose;
88 CHMHMapNodePtr firstArea =
m_parent->m_map.getFirstNode();
97 bool insertNewRobotPose =
false;
102 insertNewRobotPose =
true;
110 CPose3D *currentRobotPose = & lstRobotPoses[currentPoseID];
111 float minDistLin = 1e6f;
112 float minDistAng = 1e6f;
117 if (it->first != currentPoseID )
119 float linDist = it->second.
distanceTo( *currentRobotPose );
120 float angDist = fabs(
math::wrapToPi( it->second.yaw() - currentRobotPose->
yaw() ));
122 minDistLin =
min( minDistLin, linDist );
124 if ( linDist < m_parent->m_options.SLAM_MIN_DIST_BETWEEN_OBS )
125 minDistAng =
min(minDistAng, angDist);
130 insertNewRobotPose = (minDistLin>
m_parent->m_options.SLAM_MIN_DIST_BETWEEN_OBS) || ( minDistAng >
m_parent->m_options.SLAM_MIN_HEADING_BETWEEN_OBS );
145 pf.
executeOn( *LMH, actions.pointer(), sf.pointer() );
154 if (insertNewRobotPose)
156 m_parent->logStr( mrpt::utils::LVL_INFO,
"[CLSLAM_RBPF_2DLASER] Adding new pose...\n");
169 const CPose3D *curRobotPose = &partIt->d->robotPoses[currentPoseID];
170 partIt->d->robotPoses[newCurrentPoseID]= *curRobotPose;
171 sf->insertObservationsInto( &partIt->d->metricMaps, curRobotPose );
180 LMH->
m_SFs[ currentPoseID ] = *sf;
184 TPoseID newlyAddedPose = currentPoseID;
192 m_parent->logFmt( mrpt::utils::LVL_INFO,
"[CLSLAM_RBPF_2DLASER] Added pose %i.\n", (
int)newlyAddedPose);
200 (*it)->OnNewPose( newlyAddedPose, sf.pointer() );
234 bool SFhasValidObservations =
false;
239 if (!act)
THROW_EXCEPTION(
"Action list does not contain any CActionRobotMovement2D derived object!");
249 act->poseChange->getMeanVal();
257 SFhasValidObservations = (*LMH->
m_particles.begin()).d->metricMaps.canComputeObservationsLikelihood( *sf );
272 LMH->
m_parent->m_options.MIN_ODOMETRY_STD_XY);
275 LMH->
m_parent->m_options.MIN_ODOMETRY_STD_PHI);
313 printf(
"[prepareFastDrawSample] Done in %.06f ms\n",tictac.
Tac()*1e3f);
327 vector<double> newParticlesWeight;
328 vector<size_t> newParticlesDerivedFromIdx;
337 float MIN_ACCEPT_UNIF_DISTRIB = 0.00f;
339 CPose2D movementDraw,newPose,oldPose;
340 double acceptanceProb,newPoseLikelihood,ratioLikLik;
341 unsigned int statsTrialsCount = 0, statsTrialsSuccess = 0;
342 std::vector<bool> maxLikMovementDrawHasBeenUsed(M,
false);
343 unsigned int statsWarningsAccProbAboveOne = 0;
351 newParticles.resize(M);
352 newParticlesWeight.resize(M);
353 newParticlesDerivedFromIdx.resize(M);
355 bool doResample = LMH->
ESS() < 0.5;
371 if ( LMH->
m_SFs.empty() )
384 if (!maxLikMovementDrawHasBeenUsed[k])
387 maxLikMovementDrawHasBeenUsed[k] =
true;
390 cout <<
"Drawn pose (max. lik): " << movementDraw << endl;
406 acceptanceProb =
min( 1.0, ratioLikLik );
408 if ( ratioLikLik > 1)
412 statsWarningsAccProbAboveOne++;
424 statsTrialsSuccess++;
429 newParticles[i] = newPose;
439 newParticlesWeight[i] = 0;
440 else newParticlesWeight[i] = LMH->
m_particles[k].log_w + weightFact;
443 newParticlesDerivedFromIdx[i] = (
unsigned int)k;
454 N = newParticles.size();
460 std::vector<bool> oldParticleAlreadyCopied(LMH->
m_particles.size(),
false);
463 for (newPartIt=newParticlesArray.begin(),i=0;newPartIt!=newParticlesArray.end();newPartIt++,i++)
466 newPartIt->log_w = newParticlesWeight[i];
469 if (!oldParticleAlreadyCopied[newParticlesDerivedFromIdx[i]])
472 newPartData = LMH->
m_particles[ newParticlesDerivedFromIdx[i] ].d.release();
473 oldParticleAlreadyCopied[newParticlesDerivedFromIdx[i]] =
true;
481 newPartIt->d.reset(newPartData);
486 for (newPartIt=newParticlesArray.begin(),i=0;newPartIt!=newParticlesArray.end();newPartIt++,i++)
496 LMH->
m_particles.resize( newParticlesArray.size() );
497 for (newPartIt=newParticlesArray.begin(),trgPartIt=LMH->
m_particles.begin(); newPartIt!=newParticlesArray.end(); newPartIt++, trgPartIt++ )
499 trgPartIt->log_w = newPartIt->log_w;
500 trgPartIt->d.move_from(newPartIt->d);
504 newParticles.clear();
505 newParticlesArray.clear();
506 newParticlesWeight.clear();
507 newParticlesDerivedFromIdx.clear();
509 double out_max_log_w;
514 printf(
"[REJ-SAMP.RATIO: \t%.03f%% \t %u out of %u with P(acep)>1]\n\n",
515 100.0f*statsTrialsSuccess / (
float)(max(1u,statsTrialsCount)),
516 statsWarningsAccProbAboveOne,
535 const void *observation )
550 double indivLik, maxLik= -std::numeric_limits<double>::max();
551 size_t maxLikDraw = 0;
553 size_t nDraws = myObj->m_movementDraws.size();
566 for (
size_t q=0;
q<N;
q++)
568 CPose2D x_predict( oldPose + myObj->m_movementDraws[ (++myObj->m_movementDrawsIdx) % nDraws ] );
579 vectLiks[
q] = indivLik;
582 if ( indivLik > maxLik )
584 maxLikDraw = myObj->m_movementDrawsIdx % nDraws;
591 vectLiks.array() -= maxLogLik;
595 double avrgLogLik = log( vectLiks.array().exp().sum() ) + maxLogLik - log( (
double)N );
598 myObj->m_pfAuxiliaryPFOptimal_estimatedProb[
index] = avrgLogLik;
599 myObj->m_maxLikelihood[
index] = maxLik;
600 myObj->m_movementDrawMaximumLikelihood[
index] = myObj->m_movementDraws[ maxLikDraw ];
608 double ret = myObj->m_particles[
index].log_w + myObj->m_pfAuxiliaryPFOptimal_estimatedProb[
index];
623 size_t particleIndexForMap,
641 std::cout <<
"x = [";
642 for (it=
x.begin(); it!=
x.end(); it++) std::cout << *it <<
" ";
643 std::cout <<
"]" << std::endl;
645 std::cout <<
"y = [";
646 for (it=
y.begin(); it!=
y.end(); it++) std::cout << *it <<
" ";
647 std::cout <<
"]" << std::endl;
649 std::cout <<
"Phi = [";
650 for (it=
phi.begin(); it!=
phi.end(); it++) std::cout << *it <<
" ";
651 std::cout <<
"]" << std::endl;
666 lenBinPath = path->size();
673 outBin.
x.resize(lenBinPath + (newPose!=NULL ? 1:0) );
674 outBin.
y.resize(lenBinPath + (newPose!=NULL ? 1:0));
675 outBin.
phi.resize(lenBinPath + (newPose!=NULL ? 1:0));
681 for (itSrc = path->begin(), itX=outBin.
x.begin(),itY=outBin.
y.begin(),itPHI=outBin.
phi.begin();
682 itSrc != path->end();
683 itSrc++, itX++, itY++, itPHI++ )
685 *itX = (int)
round( itSrc->second.x() /
m_parent->m_options.KLD_params.KLD_binSize_XY);
686 *itY = (int)
round( itSrc->second.y() /
m_parent->m_options.KLD_params.KLD_binSize_XY );
687 *itPHI = (int)
round( itSrc->second.yaw() /
m_parent->m_options.KLD_params.KLD_binSize_PHI );
695 outBin.
x[lenBinPath] = (int)
round( newPose->
x() /
m_parent->m_options.KLD_params.KLD_binSize_XY );
696 outBin.
y[lenBinPath] = (int)
round( newPose->
y() /
m_parent->m_options.KLD_params.KLD_binSize_XY );
697 outBin.
phi[lenBinPath] = (int)
round( newPose->
phi() /
m_parent->m_options.KLD_params.KLD_binSize_PHI );
706 std::deque<CLSLAM_RBPF_2DLASER::TPathBin> &theSet
714 for (it=theSet.begin(),ret=0;it!=theSet.end();it++,ret++)
715 if ( (it->x==desiredBin.
x) && (it->y==desiredBin.
y) && (it->phi==desiredBin.
phi) )
746 bool SFhasValidObservations =
false;
751 if (!act)
THROW_EXCEPTION(
"Action list does not contain any CActionRobotMovement2D derived object!");
761 act->poseChange->getMeanVal();
769 SFhasValidObservations = (*LMH->
m_particles.begin()).d->metricMaps.canComputeObservationsLikelihood( *sf );
811 localMapPoints.
clear();
819 for (
size_t i=0;i<M;i++)
824 if ( LMH->
m_SFs.empty() )
839 if (!part.
d->metricMaps.m_pointsMaps.empty())
840 mapalign = part.
d->metricMaps.m_pointsMaps[0].pointer();
841 else if (!part.
d->metricMaps.m_gridMaps.empty())
842 mapalign = part.
d->metricMaps.m_gridMaps[0].pointer();
844 THROW_EXCEPTION(
"There is no point or grid map. At least one needed for ICP.");
847 CPosePDFPtr alignEst = icp.
Align(
850 initialPoseEstimation,
854 icpEstimation.
copyFrom( *alignEst );
858 CPose3D Ap = finalEstimatedPoseGauss.mean - ith_last_pose;
859 double Ap_dist = Ap.
norm();
860 finalEstimatedPoseGauss.cov.zeros();
861 finalEstimatedPoseGauss.cov(0,0) =
square( fabs(Ap_dist)*0.01 );
862 finalEstimatedPoseGauss.cov(1,1) =
square( fabs(Ap_dist)*0.01 );
863 finalEstimatedPoseGauss.cov(2,2) =
square( fabs(Ap.
yaw())*0.02 );
884 const double log_lik =
893 part.
log_w += log_lik;
903 double out_max_log_w;
907 printf(
"[CLSLAM_RBPF_2DLASER] Overall likelihood = %.2e\n",out_max_log_w);
908 printf(
"[CLSLAM_RBPF_2DLASER] Done in %.03fms\n",1e3*tictac.Tac());
struct OBS_IMPEXP mrpt::obs::CActionRobotMovement2D::TMotionModelOptions motionModelConfiguration
void clear()
Erase all the contents of the map.
int findTPathBinIntoSet(TPathBin &desiredBin, std::deque< TPathBin > &theSet)
Checks if a given "TPathBin" element is already into a set of them, and return its index (first one i...
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.
A class acquiring a CCriticalSection at its constructor, and releasing it at destructor.
Classes for serialization, sockets, ini-file manipulation, streams, list of properties-values, timewatch, extensions to STL.
THypothesisID m_ID
The unique ID of the hypothesis (Used for accessing mrpt::slam::CHierarchicalMHMap).
mrpt::poses::CPosePDFPtr Align(const mrpt::maps::CMetricMap *m1, const mrpt::maps::CMetricMap *m2, const mrpt::poses::CPose2D &grossEst, float *runningTime=NULL, void *info=NULL)
The method for aligning a pair of metric maps, aligning only 2D + orientation.
double distanceTo(const CPoseOrPoint< OTHERCLASS > &b) const
Returns the Euclidean distance to another pose/point:
double ESS() const MRPT_OVERRIDE
Returns the normalized ESS (Estimated Sample Size), in the range [0,1].
unsigned int pfAuxFilterOptimal_MaximumSearchSamples
In the algorithm "CParticleFilter::pfAuxiliaryPFOptimal" (and in "CParticleFilter::pfAuxiliaryPFStand...
Classes related to the implementation of Hybrid Metric Topological (HMT) SLAM.
static TPoseID generatePoseID()
Generates a new and unique pose ID.
Several implementations of ICP (Iterative closest point) algorithms for aligning two point maps or a ...
#define MRPT_CHECK_NORMAL_NUMBER(val)
The namespace for Bayesian filtering algorithm: different particle filters and Kalman filter algorith...
std::vector< double > m_maxLikelihood
Auxiliary variable used in the "pfAuxiliaryPFOptimal" algorithm.
std::vector< std::map< TPoseID, double > > m_log_w_metric_history
The historic log-weights of the metric observations inserted in this LMH, for each particle...
#define THROW_EXCEPTION(msg)
GLdouble GLdouble GLdouble GLdouble q
BASE_IMPEXP CRandomGenerator randomGenerator
A static instance of a CRandomGenerator class, for use in single-thread applications.
This file implements several operations that operate element-wise on individual or pairs of container...
Column vector, like Eigen::MatrixX*, but automatically initialized to zeros since construction...
double yaw() const
Get the YAW angle (in radians)
A cloud of points in 2D or 3D, which can be built from a sequence of laser scans. ...
double m_log_w
Log-weight of this hypothesis.
void computeFromOdometry(const mrpt::poses::CPose2D &odometryIncrement, const TMotionModelOptions &options)
Computes the PDF of the pose increment from an odometry reading and according to the given motion mod...
const Scalar * const_iterator
uint64_t TPoseID
An integer number uniquely identifying each robot pose stored in HMT-SLAM.
float thresholdAng
Initial threshold distance for two points to become a correspondence.
void processOneLMH(CLocalMetricHypothesis *LMH, const mrpt::obs::CActionCollectionPtr &act, const mrpt::obs::CSensoryFramePtr &sf)
Main entry point from HMT-SLAM: process some actions & observations.
float ALFA
The scale factor for threshold everytime convergence is achieved.
Virtual base for local SLAM methods, used in mrpt::slam::CHMTSLAM.
TConfigParams options
The options employed by the ICP align.
void Tic()
Starts the stopwatch.
GLsizei GLsizei GLuint * obj
An implementation of Hybrid Metric Topological SLAM (HMT-SLAM).
static double particlesEvaluator_AuxPFOptimal(const mrpt::bayes::CParticleFilter::TParticleFilterOptions &PF_options, const mrpt::bayes::CParticleFilterCapable *obj, size_t index, const void *action, const void *observation)
Auxiliary function used in "prediction_and_update_pfAuxiliaryPFOptimal".
Declares a class for storing a collection of robot actions.
mrpt::utils::safe_ptr< CHMTSLAM > m_parent
mrpt::obs::CActionRobotMovement2D m_accumRobotMovement
Used in CLSLAM_RBPF_2DLASER.
T square(const T x)
Inline function for the square of a number.
mrpt::poses::StdVector_CPose2D m_movementDraws
Auxiliary variable used in the "pfAuxiliaryPFOptimal" algorithm.
void dumpToStdOut() const
For debugging purposes!
CONTAINER::Scalar minimum(const CONTAINER &v)
Represents a probabilistic 2D movement of the robot mobile base.
CParticleList m_particles
The array of particles.
void executeOn(CParticleFilterCapable &obj, const mrpt::obs::CActionCollection *action, const mrpt::obs::CSensoryFrame *observation, TParticleFilterStats *stats=NULL)
Executes a complete prediction + update step of the selected particle filtering algorithm.
TPoseIDList m_posesPendingAddPartitioner
The list of poseIDs waiting to be added to the graph partitioner, what happens in the LSLAM thread ma...
Declares a class that represents a Probability Density function (PDF) of a 2D pose ...
#define MRPT_UNUSED_PARAM(a)
Can be used to avoid "not used parameters" warnings from the compiler.
void composeFrom(const CPose3D &A, const CPose3D &B)
Makes "this = A (+) B"; this method is slightly more efficient than "this= A + B;" since it avoids th...
void fastDrawSingleSample(mrpt::poses::CPose2D &outSample) const
Faster version than "drawSingleSample", but requires a previous call to "prepareFastDrawSingleSamples...
double norm() const
Returns the euclidean norm of vector: .
std::map< TPoseID, CHMHMapNode::TNodeID > m_nodeIDmemberships
The hybrid map node membership for each robot pose.
double computeObservationsLikelihood(const mrpt::obs::CSensoryFrame &sf, const mrpt::poses::CPose2D &takenFrom)
Returns the sum of the log-likelihoods of each individual observation within a mrpt::obs::CSensoryFra...
unsigned int maxIterations
Maximum number of iterations to run.
This class implements a high-performance stopwatch.
mrpt::utils::safe_ptr< CHMTSLAM > m_parent
For quick access to our parent object.
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...
This virtual class defines the interface that any particles based PDF class must implement in order t...
mrpt::math::CVectorDouble m_pfAuxiliaryPFOptimal_estimatedProb
Auxiliary variable used in the "pfAuxiliaryPFOptimal" algorithm.
unsigned int m_movementDrawsIdx
Auxiliary variable used in the "pfAuxiliaryPFOptimal" algorithm.
bool doRANSAC
Perform a RANSAC step, mrpt::tfest::se2_l2_robust(), after the ICP convergence, to obtain a better es...
This class acts as a common interface to the different interfaces (see CParticleFilter::TParticleFilt...
This class is used in HMT-SLAM to represent each of the Local Metric Hypotheses (LMHs).
bool onlyClosestCorrespondences
The usual approach: to consider only the closest correspondence for each local point (Default to true...
CONTAINER::Scalar maximum(const CONTAINER &v)
T wrapToPi(T a)
Modifies the given angle to translate it into the ]-pi,pi] range.
void keep_max(T &var, const K test_val)
If the second argument is above the first one, set the first argument to this higher value...
Classes for 2D/3D geometry representation, both of single values and probability density distribution...
void prepareFastDrawSample(const bayes::CParticleFilter::TParticleFilterOptions &PF_options, TParticleProbabilityEvaluator partEvaluator=defaultEvaluator, const void *action=NULL, const void *observation=NULL) const
Prepares data structures for calling fastDrawSample method next.
virtual ~CLSLAM_RBPF_2DLASER()
Destructor.
Auxiliary class used in mrpt::slam::CLocalMetricHypothesis for HMT-SLAM; this class keeps the data re...
mrpt::aligned_containers< TPoseID, mrpt::poses::CPose3D >::map_t TMapPoseID2Pose3D
void prepareFastDrawSingleSamples() const
Call this before calling a high number of times "fastDrawSingleSample", which is much faster than "dr...
mrpt::poses::StdVector_CPose2D m_movementDrawMaximumLikelihood
Auxiliary variable used in the "pfAuxiliaryPFOptimal" algorithm.
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
bool m_accumRobotMovementIsValid
Used in CLSLAM_RBPF_2DLASER.
std::deque< CParticleData > CParticleList
Use this type to refer to the list of particles m_particles.
A template class for holding a the data and the weight of a particle.
std::map< TPoseID, mrpt::obs::CSensoryFrame > m_SFs
The SF gathered at each robot pose.
void getMeans(TMapPoseID2Pose3D &outList) const
Returns the mean of each robot pose in this LMH, as computed from the set of particles.
Declares a virtual base class for all metric maps storage classes.
A class used to store a 2D pose, including the 2D coordinate point and a heading (phi) angle...
A class used to store a 3D pose (a 3D translation + a rotation in 3D).
double normalizeWeights(double *out_max_log_w=NULL) MRPT_OVERRIDE
Normalize the (logarithmic) weights, such as the maximum weight is zero.
float smallestThresholdDist
The size for threshold such that iterations will stop, since it is considered precise enough...
double powFactor
An optional step to "smooth" dramatic changes in the observation model to affect the variance of the ...
const double & phi() const
Get the phi angle of the 2D pose (in radians)
The configuration of a particle filter.
void composeFrom(const CPose2D &A, const CPose2D &B)
Makes .
double log_w
The (logarithmic) weight value for this particle.
CActionRobotMovement2DPtr getBestMovementEstimation() const
Returns the best pose increment estimator in the collection, based on the determinant of its pose cha...
The ICP algorithm return information.
static double auxiliarComputeObservationLikelihood(const mrpt::bayes::CParticleFilter::TParticleFilterOptions &PF_options, const mrpt::bayes::CParticleFilterCapable *obj, size_t particleIndexForMap, const mrpt::obs::CSensoryFrame *observation, const mrpt::poses::CPose2D *x)
Auxiliary function that evaluates the likelihood of an observation, given a robot pose...
mrpt::utils::copy_ptr< T > d
The data associated with this particle. The use of copy_ptr<> allows relying on compiler-generated co...
double mean(const CONTAINER &v)
Computes the mean value of a vector.
double Tac()
Stops the stopwatch.
class HMTSLAM_IMPEXP CLSLAM_RBPF_2DLASER
#define NODE_ANNOTATION_REF_POSEID
Declares a class that represents a Probability Density function (PDF) of a 3D pose ...
int round(const T value)
Returns the closer integer (int) to x.
TInsertionOptions insertionOptions
The options used when inserting observations in the map.
struct OBS_IMPEXP mrpt::obs::CActionRobotMovement2D::TMotionModelOptions::TOptions_GaussianModel gaussianModel
void drawSingleSample(CPose3D &outPart) const MRPT_OVERRIDE
Draws a single sample from the distribution.
This class stores any customizable set of metric maps.
bool m_insertNewRobotPose
For use within PF callback methods.
CParticleFilter::TParticleFilterOptions m_options
The options to be used in the PF, must be set before executing any step of the particle filter...
void prediction_and_update_pfAuxiliaryPFOptimal(CLocalMetricHypothesis *LMH, const mrpt::obs::CActionCollection *action, const mrpt::obs::CSensoryFrame *observation, const bayes::CParticleFilter::TParticleFilterOptions &PF_options)
The PF algorithm implementation.
const mrpt::poses::CPose3D * getCurrentPose(const size_t &particleIdx) const
Returns the i'th particle hypothesis for the current robot pose.
mrpt::aligned_containers< CPose2D >::vector_t StdVector_CPose2D
Eigen aligment-compatible container.
bool insertObservationsInto(mrpt::maps::CMetricMap *theMap, const mrpt::poses::CPose3D *robotPose=NULL) const
Insert all the observations in this SF into a metric map or any kind (see mrpt::maps::CMetricMap).
size_t fastDrawSample(const bayes::CParticleFilter::TParticleFilterOptions &PF_options) const
Draws a random sample from the particle filter, in such a way that each particle has a probability pr...
void loadTPathBinFromPath(TPathBin &outBin, TMapPoseID2Pose3D *path=NULL, mrpt::poses::CPose2D *newPose=NULL)
Fills out a "TPathBin" variable, given a path hypotesis and (if not set to NULL) a new pose appended ...
bool adaptiveSampleSize
A flag that indicates whether the CParticleFilterCapable object should perform adative sample size (d...
mrpt::poses::CPose2D rawOdometryIncrementReading
This is the raw odometry reading, and only is used when "estimationMethod" is "TEstimationMethod::emO...
float minDistBetweenLaserPoints
The minimum distance between points (in 3D): If two points are too close, one of them is not inserted...
void copyFrom(const CPosePDF &o) MRPT_OVERRIDE
Copy operator, translating if necesary (for example, between particles and gaussian representations) ...
void prediction_and_update_pfOptimalProposal(CLocalMetricHypothesis *LMH, const mrpt::obs::CActionCollection *action, const mrpt::obs::CSensoryFrame *observation, const bayes::CParticleFilter::TParticleFilterOptions &PF_options)
The PF algorithm implementation.
TPoseID m_currentRobotPose
The current robot pose (its global unique ID) for this hypothesis.