48 const TPose3D* newPoseToBeInserted)
51 if (newPoseToBeInserted)
60 currentParticleValue && !currentParticleValue->
robotPath.empty());
75 const TPose3D* newPoseToBeInserted)
77 const size_t lenBinPath = (currentParticleValue !=
nullptr)
82 outBin.
bins.resize(lenBinPath + (newPoseToBeInserted !=
nullptr ? 1 : 0));
85 if (currentParticleValue !=
nullptr)
86 for (
size_t i = 0; i < lenBinPath; ++i)
97 if (newPoseToBeInserted !=
nullptr)
100 outBin.
bins[lenBinPath].x =
102 outBin.
bins[lenBinPath].y =
104 outBin.
bins[lenBinPath].phi =
117 : sensorLocationOnRobot(),
133 return a.nGaussiansInMap <
b.nGaussiansInMap;
142 void CMultiMetricMapPDF::prediction_and_update_pfAuxiliaryPFOptimal(
149 PF_SLAM_implementation_pfAuxiliaryPFOptimal<mrpt::slam::detail::TPoseBin2D>(
150 actions, sf, PF_options, options.KLD_params);
158 void CMultiMetricMapPDF::prediction_and_update_pfAuxiliaryPFStandard(
165 PF_SLAM_implementation_pfAuxiliaryPFStandard<
167 actions, sf, PF_options, options.KLD_params);
187 void CMultiMetricMapPDF::prediction_and_update_pfOptimalProposal(
198 size_t M = m_particles.size();
199 bool updateStageAlreadyDone =
false;
200 CPose3D initialPose, incrPose, finalPose;
221 robotMovement2D->poseChange.get_ptr());
222 motionModelMeanIncr =
231 robotActionSampler.
setPosePDF(robotMovement3D->poseChange);
232 robotMovement3D->poseChange.getMean(motionModelMeanIncr);
242 averageMapIsUpdated =
false;
250 printf(
" 1) Prediction...");
251 M = m_particles.size();
254 size_t particleWithHighestW = 0;
255 for (
size_t i = 0; i < M; i++)
256 if (getW(i) > getW(particleWithHighestW)) particleWithHighestW = i;
259 ASSERT_(!m_particles[0].d->robotPath.empty());
263 bool built_map_points =
false;
264 bool built_map_lms =
false;
268 for (i = 0, partIt = m_particles.begin(); partIt != m_particles.end();
271 double extra_log_lik = 0;
275 *partIt->d->robotPath.rbegin());
277 CPose3D initialPoseEstimation = ith_last_pose + motionModelMeanIncr;
280 if (options.pfOptimalProposal_mapSelection == 0 ||
281 options.pfOptimalProposal_mapSelection == 1 ||
282 options.pfOptimalProposal_mapSelection == 3)
287 if (partIt->d->mapTillNow.m_pointsMaps.size())
289 ASSERT_(partIt->d->mapTillNow.m_pointsMaps.size() == 1);
296 if (options.pfOptimalProposal_mapSelection == 0)
298 ASSERT_(!partIt->d->mapTillNow.m_gridMaps.empty());
301 if (!built_map_points)
303 built_map_points =
true;
305 localMapPoints.insertionOptions.minDistBetweenLaserPoints =
308 localMapPoints.insertionOptions.isPlanarMap =
true;
312 map_to_align_to = partIt->d->mapTillNow.m_gridMaps[0].get();
314 else if (options.pfOptimalProposal_mapSelection == 3)
317 ASSERT_(!partIt->d->mapTillNow.m_pointsMaps.empty());
320 if (!built_map_points)
322 built_map_points =
true;
324 localMapPoints.insertionOptions.minDistBetweenLaserPoints =
327 localMapPoints.insertionOptions.isPlanarMap =
true;
331 map_to_align_to = partIt->d->mapTillNow.m_pointsMaps[0].get();
335 ASSERT_(partIt->d->mapTillNow.m_landmarksMap);
340 built_map_lms =
true;
344 map_to_align_to = partIt->d->mapTillNow.m_landmarksMap.get();
347 ASSERT_(map_to_align_to !=
nullptr);
352 map_to_align_to, &localMapPoints,
353 CPose2D(initialPoseEstimation),
nullptr, &icpInfo);
357 if (i == particleWithHighestW)
359 newInfoIndex = 1 - icpInfo.
goodness;
368 if (icpInfo.
goodness < options.ICPGlobalAlign_MinQuality &&
372 "[rbpf-slam] Warning: gridICP[%u]: %.02f%% -> Using " 373 "odometry instead!\n",
374 (
unsigned int)i, 100 * icpInfo.
goodness);
375 icpEstimation.
mean =
CPose2D(initialPoseEstimation);
394 #if 0 // Use hacked ICP covariance: 395 CPose3D Ap = finalEstimatedPoseGauss.
mean - ith_last_pose;
396 const double Ap_dist = Ap.
norm();
398 finalEstimatedPoseGauss.
cov.zeros();
399 finalEstimatedPoseGauss.
cov(0,0) =
square( fabs(Ap_dist)*0.01 );
400 finalEstimatedPoseGauss.
cov(1,1) =
square( fabs(Ap_dist)*0.01 );
401 finalEstimatedPoseGauss.
cov(2,2) =
square( fabs(Ap.
yaw())*0.02 );
414 finalEstimatedPoseGauss.
mean;
416 rndSamples, finalEstimatedPoseGauss.
cov);
418 finalPose.setFromValues(
419 finalPose.x() + rndSamples[0], finalPose.y() + rndSamples[1],
420 finalPose.z(), finalPose.yaw() + rndSamples[2],
421 finalPose.pitch(), finalPose.roll());
423 else if (options.pfOptimalProposal_mapSelection == 2)
431 ASSERT_(partIt->d->mapTillNow.m_beaconMap);
434 updateStageAlreadyDone =
447 bool methodSOGorGrid =
false;
449 float firstEstimateRobotHeading = std::numeric_limits<float>::max();
452 CPoint3D centerPositionPrior(ith_last_pose);
453 float centerPositionPriorRadius = 2.0f;
457 firstEstimateRobotHeading = ith_last_pose.
yaw();
462 if (!beacMap->size())
465 cerr <<
"[RO-SLAM] Optimal filtering without map & " 466 "odometry...this message should appear only the " 475 if (beacMap->get(0).m_typePDF == CBeacon::pdfSOG)
477 cerr <<
"[RO-SLAM] Optimal filtering without map & " 478 "odometry->FIXING ONE BEACON!" 480 ASSERT_(beacMap->get(0).m_locationSOG.size() > 0);
482 beacMap->get(0).m_locationSOG[0].val.mean);
485 beacMap->get(0).m_typePDF = CBeacon::pdfGauss;
486 beacMap->get(0).m_locationSOG.clear();
487 beacMap->get(0).m_locationGauss.mean = fixedBeacon;
488 beacMap->get(0).m_locationGauss.cov.unit(3, 1e-6);
495 deque<TAuxRangeMeasInfo> lstObservedRanges;
498 itObs != sf->
end(); ++itObs)
505 deque<CObservationBeaconRanges::TMeasurement>::
506 const_iterator itRanges;
508 itRanges != obs->
sensedData.end(); itRanges++)
513 itBeacs != beacMap->end(); ++itBeacs)
515 if ((itBeacs)->m_ID == itRanges->beaconID)
518 newMeas.
beaconID = itRanges->beaconID;
520 itRanges->sensedDistance;
522 itRanges->sensorLocationOnRobot;
525 (itBeacs)->m_typePDF == CBeacon::pdfGauss ||
526 (itBeacs)->m_typePDF == CBeacon::pdfSOG);
528 (itBeacs)->m_typePDF == CBeacon::pdfSOG
529 ? (itBeacs)->m_locationSOG.size()
532 lstObservedRanges.push_back(newMeas);
545 lstObservedRanges.begin(), lstObservedRanges.end(),
552 fusedObsModels.
clear();
569 firstEstimateRobotHeading = auxPose.
yaw();
579 poseCOV.setSize(2, 2);
580 poseCOV.setSize(3, 3);
581 newMode.
val.
cov = poseCOV;
588 itBeacs != beacMap->end(); ++itBeacs)
593 lstObservedRanges.begin();
594 itObs != lstObservedRanges.end(); ++itObs)
596 if ((itBeacs)->m_ID == itObs->beaconID)
599 float sensedRange = itObs->sensedDistance;
602 (itBeacs)->generateObservationModelDistribution(
603 sensedRange, newObsModel,
605 itObs->sensorLocationOnRobot,
608 centerPositionPrior, centerPositionPriorRadius);
610 if (!fusedObsModels.
size())
614 fusedObsModels = newObsModel;
621 fusedObsModels, newObsModel,
624 fusedObsModels = tempFused;
631 cout <<
"#modes bef: " << fusedObsModels.
size()
632 <<
" ESS: " << fusedObsModels.
ESS()
634 double max_w = -1e100;
639 for (it = fusedObsModels.
begin();
640 it != fusedObsModels.
end(); it++)
642 max(max_w, (it)->log_w);
646 for (it = fusedObsModels.
begin();
647 it != fusedObsModels.
end();)
649 if (max_w - (it)->log_w >
651 it = fusedObsModels.
erase(it);
657 <<
"#modes after: " << fusedObsModels.
size()
666 currentCov(0, 0) > 0 && currentCov(1, 1) > 0);
667 if (sqrt(currentCov(0, 0)) < 0.10f &&
668 sqrt(currentCov(1, 1)) < 0.10f &&
669 sqrt(currentCov(2, 2)) < 0.10f)
673 fusedObsModels.
getMean(currentMean);
674 fusedObsModels[0].log_w = 0;
675 fusedObsModels[0].val.mean = currentMean;
676 fusedObsModels[0].val.cov = currentCov;
716 float grid_min_x = ith_last_pose.
x() - 0.5f;
717 float grid_max_x = ith_last_pose.
x() + 0.5f;
718 float grid_min_y = ith_last_pose.
y() - 0.5f;
719 float grid_max_y = ith_last_pose.
y() + 0.5f;
720 float grid_resXY = 0.02f;
722 bool repeatGridCalculation =
false;
727 grid_min_x, grid_max_x, grid_min_y, grid_max_y,
728 grid_resXY,
DEG2RAD(180), 0, 0);
735 itBeacs != beacMap->end(); ++itBeacs)
740 lstObservedRanges.begin();
741 itObs != lstObservedRanges.end(); ++itObs)
743 if ((itBeacs)->m_ID == itObs->beaconID)
746 float sensedRange = itObs->sensedDistance;
762 for (
size_t idxX = 0;
765 float grid_x = pdfGrid->
idx2x(idxX);
766 for (
size_t idxY = 0;
769 double grid_y = pdfGrid->
idx2y(idxY);
778 switch ((itBeacs)->m_typePDF)
780 case CBeacon::pdfSOG:
783 &(itBeacs)->m_locationSOG;
784 double sensorSTD2 =
square(
785 beacMap->likelihoodOptions
789 for (it = sog->
begin();
790 it != sog->
end(); it++)
796 (it)->
val.mean.distance2DTo(
799 ->sensorLocationOnRobot
803 ->sensorLocationOnRobot
827 float maxX = 0, maxY = 0;
828 for (
size_t idxX = 0; idxX < pdfGrid->
getSizeX();
832 for (
size_t idxY = 0; idxY < pdfGrid->
getSizeY();
842 maxX = pdfGrid->
idx2x(idxX);
843 maxY = pdfGrid->
idx2y(idxY);
847 newDrawnPosition.
x(maxX);
848 newDrawnPosition.
y(maxY);
856 outMat *= 1.0f/outMat.maxCoeff();
857 CImage imgF(outMat,
true);
858 static int autocount=0;
859 imgF.saveToFile(
format(
"debug_grid_%f_%05i.png",grid_resXY,autocount++));
860 printf(
"grid res: %f MAX: %f,%f\n",grid_resXY,maxX,maxY);
865 if (grid_resXY > 0.01f)
867 grid_min_x = maxX - 0.03f;
868 grid_max_x = maxX + 0.03f;
869 grid_min_y = maxY - 0.03f;
870 grid_max_y = maxY + 0.03f;
872 repeatGridCalculation =
true;
875 repeatGridCalculation =
false;
891 }
while (repeatGridCalculation);
900 if (!beacMap->size())
904 finalPose = ith_last_pose;
908 cout <<
"Drawn: " << newDrawnPosition << endl;
914 firstEstimateRobotHeading !=
915 std::numeric_limits<float>::max());
918 newDrawnPosition.
x(), newDrawnPosition.
y(),
919 newDrawnPosition.z(), firstEstimateRobotHeading, 0, 0);
930 double weightUpdate = 0;
931 partIt->log_w += PF_options.
powFactor * weightUpdate;
940 "Action list does not contain any CActionRobotMovement2D " 941 "or CActionRobotMovement3D object!");
945 finalPose = ith_last_pose + incrPose;
949 partIt->d->robotPath.push_back(finalPose.
asTPose());
954 if (!updateStageAlreadyDone)
957 (PF_SLAM_computeObservationLikelihoodForParticle(
958 PF_options, i, *sf, finalPose) +
972 void CMultiMetricMapPDF::prediction_and_update_pfStandardProposal(
979 PF_SLAM_implementation_pfStandardProposal<mrpt::slam::detail::TPoseBin2D>(
980 actions, sf, PF_options, options.KLD_params);
983 averageMapIsUpdated =
false;
989 void CMultiMetricMapPDF::
990 PF_SLAM_implementation_custom_update_particle_with_new_pose(
993 particleData->
robotPath.push_back(newPose);
997 bool CMultiMetricMapPDF::PF_SLAM_implementation_doWeHaveValidObservations(
998 const CMultiMetricMapPDF::CParticleList& particles,
1001 if (sf ==
nullptr)
return false;
1003 return particles.begin()
1005 ->mapTillNow.canComputeObservationsLikelihood(*sf);
1009 bool CMultiMetricMapPDF::PF_SLAM_implementation_skipRobotMovement()
const 1011 return 0 == getNumberOfObservationsInSimplemap();
1018 double CMultiMetricMapPDF::PF_SLAM_computeObservationLikelihoodForParticle(
1020 const size_t particleIndexForMap,
const CSensoryFrame& observation,
1025 &m_particles[particleIndexForMap].d->mapTillNow);
1028 it != observation.
end(); ++it)
A namespace of pseudo-random numbers generators of diferent distributions.
mrpt::math::TPose3D asTPose() const
double x() const
Common members of all points & poses classes.
void copyFrom(const CPosePDF &o) override
Copy operator, translating if necesary (for example, between particles and gaussian representations) ...
CPose2D mean
The mean value.
CPose3D mean
The mean value.
This class is a "CSerializable" wrapper for "CMatrixTemplateNumeric<double>".
static bool cmp_Asc(const TAuxRangeMeasInfo &a, const TAuxRangeMeasInfo &b)
Auxiliary for optimal sampling in RO-SLAM.
#define THROW_EXCEPTION(msg)
void getMean(CPoint3D &mean_point) const override
Returns an estimate of the point, (the mean, or mathematical expectation of the PDF) ...
mrpt::poses::CPosePDF::Ptr Align(const mrpt::maps::CMetricMap *m1, const mrpt::maps::CMetricMap *m2, const mrpt::poses::CPose2D &grossEst, float *runningTime=nullptr, void *info=nullptr)
The method for aligning a pair of metric maps, aligning only 2D + orientation.
CPoint3D mean
The mean value.
Several implementations of ICP (Iterative closest point) algorithms for aligning two point maps or a ...
double DEG2RAD(const double x)
Degrees to radians.
The namespace for Bayesian filtering algorithm: different particle filters and Kalman filter algorith...
void resize(const size_t N)
Resize the number of SOG modes.
Declares a class that represents a Probability Density function (PDF) of a 3D point ...
The struct for each mode:
double computeObservationLikelihood(const mrpt::obs::CObservation *obs, const mrpt::poses::CPose3D &takenFrom)
Computes the log-likelihood of a given observation given an arbitrary robot 3D pose.
void uniformDistribution()
Assigns the same value to all the cells in the grid, so the sum 1.
This file contains the implementations of the template members declared in mrpt::slam::PF_implementat...
Column vector, like Eigen::MatrixX*, but automatically initialized to zeros since construction...
void clear()
Clear all the gaussian modes.
double yaw() const
Get the YAW angle (in radians)
Declares a class derived from "CObservation" that represents one (or more) range measurements to labe...
Option set for KLD algorithm.
void drawSingleSample(CPoint3D &outSample) const override
Draw a sample from the pdf.
A cloud of points in 2D or 3D, which can be built from a sequence of laser scans. ...
void getCovariance(mrpt::math::CMatrixDouble &cov) const
Returns the estimate of the covariance matrix (STATE_LEN x STATE_LEN covariance matrix) ...
double yaw
Yaw coordinate (rotation angle over Z axis).
bool isPrepared() const
Return true if samples can be generated, which only requires a previous call to setPosePDF.
void KLF_loadBinFromParticle(detail::TPathBin2D &outBin, const TKLDParams &opts, const mrpt::maps::CRBPFParticleData *currentParticleValue, const TPose3D *newPoseToBeInserted)
Fills out a "TPathBin2D" variable, given a path hypotesis and (if not set to nullptr) a new pose appe...
Declares a class for storing a collection of robot actions.
double idx2y(size_t y) const
Returns coordinates from "indexes":
void getAsMatrix(const double &phi, MATRIXLIKE &outMat)
Returns the whole grid as a matrix, for a given constant "phi" and where each row contains values for...
const T * getByIndex(size_t x, size_t y, size_t phi) const
Reads the contents of a cell.
T square(const T x)
Inline function for the square of a number.
const_iterator begin() const
Returns a constant iterator to the first observation: this is an example of usage: ...
#define ASSERT_(f)
Defines an assertion mechanism.
Represents a probabilistic 3D (6D) movement.
float goodness
A goodness measure for the alignment, it is a [0,1] range indicator of percentage of correspondences...
This base provides a set of functions for maths stuff.
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...
A class for storing a map of 3D probabilistic landmarks.
Declares a class that represents a Probability Density function (PDF) of a 2D pose ...
void setPosePDF(const CPosePDF *pdf)
This method must be called to select the PDF from which to draw samples.
CActionRobotMovement2D::Ptr getBestMovementEstimation() const
Returns the best pose increment estimator in the collection, based on the determinant of its pose cha...
double norm() const
Returns the euclidean norm of vector: .
void push_back(const TGaussianMode &m)
Inserts a copy of the given mode into the SOG.
void getOriginalPDFCov2D(mrpt::math::CMatrixDouble33 &cov3x3) const
Retrieves the 3x3 covariance of the original PDF in .
mrpt::math::CMatrixDouble33 cov
The 3x3 covariance matrix.
std::deque< TMeasurement > sensedData
The list of observed ranges.
std::deque< CObservation::Ptr >::const_iterator const_iterator
You can use CSensoryFrame::begin to get a iterator to the first element.
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...
double KLD_binSize_XY
Parameters for the KLD adaptive sample size algorithm (see Dieter Fox's papers), which is used only i...
A class used to store a 3D point.
Classes for 2D/3D geometry representation, both of single values and probability density distribution...
Auxiliary class used in mrpt::maps::CMultiMetricMapPDF.
iterator erase(iterator i)
Auxiliary structure used in KLD-sampling in particle filters.
mrpt::math::CMatrixDouble66 cov
The 6x6 covariance matrix.
#define INVALID_BEACON_ID
Used for CObservationBeaconRange, CBeacon, etc.
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
void drawGaussianMultivariate(std::vector< T > &out_result, const MATRIX &cov, const std::vector< T > *mean=nullptr)
Generate multidimensional random samples according to a given covariance matrix.
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).
Declares a class that represents any robot's observation.
double powFactor
An optional step to "smooth" dramatic changes in the observation model to affect the variance of the ...
std::string format(const char *fmt,...) MRPT_printf_format_check(1
A std::string version of C sprintf.
double ESS() const
Computes the "Effective sample size" (typical measure for Particle Filters), applied to the weights o...
CPoint3D sensorLocationOnRobot
#define IS_CLASS(ptrObj, class_name)
Evaluates to true if the given pointer to an object (derived from mrpt::rtti::CObject) is of the give...
The configuration of a particle filter.
size_t size() const
Return the number of Gaussian modes.
std::deque< mrpt::math::TPose3D > robotPath
void setFromValues(const double x0, const double y0, const double z0, const double yaw=0, const double pitch=0, const double roll=0)
Set the pose from a 3D position (meters) and yaw/pitch/roll angles (radians) - This method recomputes...
The ICP algorithm return information.
Lightweight 3D pose (three spatial coordinates, plus three angular coordinates).
Declares a class that represents a Probability Density function (PDF) of a 3D pose ...
double log_w
The log-weight.
std::vector< TPoseBin2D > bins
double idx2x(size_t x) const
Returns coordinates from "indexes":
T::Ptr getActionByClass(const size_t &ith=0) const
Access to the i'th action of a given class, or a nullptr smart pointer if there is no action of that ...
Auxiliary for optimal sampling in RO-SLAM.
CPose2D & drawSample(CPose2D &p) const
Generate a new sample from the selected PDF.
const_iterator end() const
Returns a constant iterator to the end of the list of observations: this is an example of usage: ...
This class stores any customizable set of metric maps.
An efficient generator of random samples drawn from a given 2D (CPosePDF) or 3D (CPose3DPDF) pose pro...
Declares a class that represents a Probability Distribution function (PDF) of a 2D pose (x...
CRandomGenerator & getRandomGenerator()
A static instance of a CRandomGenerator class, for use in single-thread applications.
bool insertObservationsInto(mrpt::maps::CMetricMap *theMap, const mrpt::poses::CPose3D *robotPose=nullptr) const
Insert all the observations in this SF into a metric map or any kind (see mrpt::maps::CMetricMap).
GLubyte GLubyte GLubyte a
void normalize()
Normalizes the PDF, such as all cells sum the unity.
std::deque< CBeacon >::iterator iterator
void bayesianFusion(const CPointPDF &p1, const CPointPDF &p2, const double minMahalanobisDistToDrop=0) override
Bayesian fusion of two point distributions (product of two distributions->new distribution), then save the result in this object (WARNING: See implementing classes to see classes that can and cannot be mixtured!)
std::deque< TGaussianMode >::iterator iterator
#define MRPT_UNUSED_PARAM(a)
Determines whether this is an X86 or AMD64 platform.
int round(const T value)
Returns the closer integer (int) to x.