35 double COccupancyGridMap2D::internal_computeObservationLikelihood(
44 if (!scan->
isPlanarScan(insertionOptions.horizontalTolerance))
46 if (insertionOptions.useMapAltitude &&
47 fabs(insertionOptions.mapAltitude - scan->
sensorPose.z() ) > 0.01 )
57 switch (likelihoodOptions.likelihoodMethod)
61 return computeObservationLikelihood_rayTracing(obs,takenFrom);
63 case lmMeanInformation:
64 return computeObservationLikelihood_MI(obs,takenFrom);
67 return computeObservationLikelihood_Consensus(obs,takenFrom);
69 case lmCellsDifference:
70 return computeObservationLikelihood_CellsDifference(obs,takenFrom);
72 case lmLikelihoodField_Thrun:
73 return computeObservationLikelihood_likelihoodField_Thrun(obs,takenFrom);
75 case lmLikelihoodField_II:
76 return computeObservationLikelihood_likelihoodField_II(obs,takenFrom);
79 return computeObservationLikelihood_ConsensusOWA(obs,takenFrom);
87 double COccupancyGridMap2D::computeObservationLikelihood_Consensus(
106 if ( ! o->
isPlanarScan(insertionOptions.horizontalTolerance) )
return 0.5f;
121 const size_t n = compareMap->
size();
123 for (
size_t i=0;i<
n;i+=likelihoodOptions.consensus_takeEachRange)
129 int cx0 = x2idx( pointGlobal.
x );
130 int cy0 = y2idx( pointGlobal.
y );
132 likResult += 1-getCell_nocheck(cx0,cy0);
135 if (Denom) likResult/=Denom;
136 likResult = pow(likResult,
static_cast<double>( likelihoodOptions.consensus_pow ) );
138 return log(likResult);
144 double COccupancyGridMap2D::computeObservationLikelihood_ConsensusOWA(
148 double likResult = 0;
163 if ( ! o->
isPlanarScan(insertionOptions.horizontalTolerance) )
return 0.5;
177 const size_t n = compareMap->
size();
180 likelihoodOutputs.OWA_pairList.clear();
181 for (
size_t i=0;i<
n;i++)
187 int cx0 = x2idx( pointGlobal.
x );
188 int cy0 = y2idx( pointGlobal.
y );
190 int cxMin = max(0,cx0 - Acells);
191 int cxMax =
min(
static_cast<int>(size_x)-1,cx0 + Acells);
192 int cyMin = max(0,cy0 - Acells);
193 int cyMax =
min(
static_cast<int>(size_y)-1,cy0 + Acells);
197 for (
int cx=cxMin;cx<=cxMax;cx++)
198 for (
int cy=cyMin;cy<=cyMax;cy++)
199 lik += 1-getCell_nocheck(cx,cy);
201 int nCells = (cxMax-cxMin+1)*(cyMax-cyMin+1);
207 element.second = pointGlobal;
208 likelihoodOutputs.OWA_pairList.push_back( element );
213 std::sort(likelihoodOutputs.OWA_pairList.begin(),likelihoodOutputs.OWA_pairList.end());
216 size_t M = likelihoodOptions.OWA_weights.size();
217 ASSERT_( likelihoodOutputs.OWA_pairList.size()>=M );
219 likelihoodOutputs.OWA_pairList.resize(M);
220 likelihoodOutputs.OWA_individualLikValues.resize( M );
222 for (
size_t k=0;k<M;k++)
224 likelihoodOutputs.OWA_individualLikValues[k] = likelihoodOutputs.OWA_pairList[k].first;
225 likResult+= likelihoodOptions.OWA_weights[k] * likelihoodOutputs.OWA_individualLikValues[k];
228 return log(likResult);
234 double COccupancyGridMap2D::computeObservationLikelihood_CellsDifference(
250 if (!o->
isPlanarScan(insertionOptions.horizontalTolerance))
return 0.5;
253 COccupancyGridMap2D compareGrid(takenFrom.
x()-10,takenFrom.
x()+10,takenFrom.
y()-10,takenFrom.
y()+10,resolution);
263 Ax =
round((x_min - compareGrid.
x_min) / resolution);
264 Ay =
round((y_min - compareGrid.
y_min) / resolution);
266 int nCellsCompared = 0;
267 float cellsDifference = 0;
270 int x1 =
min(compareGrid.
size_x, size_x+Ax);
271 int y1 =
min(compareGrid.
size_y, size_y+Ay);
273 for (
int x=x0;
x<x1;
x+=1)
275 for (
int y=y0;
y<y1;
y+=1)
277 float xx = compareGrid.
idx2x(
x);
278 float yy = compareGrid.
idx2y(
y);
280 float c1 = getPos(xx,yy);
282 if ( c2<0.45f || c2>0.55f )
285 if ((c1>0.5 && c2<0.5) || (c1<0.5 && c2>0.5))
290 ret = 1 - cellsDifference / (nCellsCompared);
298 double COccupancyGridMap2D::computeObservationLikelihood_MI(
308 updateInfoChangeOnly.enabled =
true;
309 insertionOptions.maxDistanceInsertion*= likelihoodOptions.MI_ratio_max_distance;
312 updateInfoChangeOnly.cellsUpdated = 0;
313 updateInfoChangeOnly.I_change = 0;
314 updateInfoChangeOnly.laserRaysSkip = likelihoodOptions.MI_skip_rays;
317 insertObservation(obs,&poseRobot);
320 double newObservation_mean_I;
321 if (updateInfoChangeOnly.cellsUpdated)
322 newObservation_mean_I = updateInfoChangeOnly.I_change / updateInfoChangeOnly.cellsUpdated;
323 else newObservation_mean_I = 0;
326 updateInfoChangeOnly.enabled =
false;
327 insertionOptions.maxDistanceInsertion/=likelihoodOptions.MI_ratio_max_distance;
330 res = pow(newObservation_mean_I,
static_cast<double>(likelihoodOptions.MI_exponent) );
337 double COccupancyGridMap2D::computeObservationLikelihood_rayTracing(
354 if (!o->
isPlanarScan(insertionOptions.horizontalTolerance))
return 0.5;
357 int decimation = likelihoodOptions.rayTracing_decimation;
375 double stdLaser = likelihoodOptions.rayTracing_stdHit;
376 double stdSqrt2 = sqrt(2.0f) * stdLaser;
384 for (
int j=0;j<nRays;j+=decimation)
387 r_sim = simulatedObs.
scan[j];
388 r_obs = o->
scan[ j ];
393 likelihood = 0.1/o->
maxRange + 0.9*exp( -
square(
min((
float)fabs(r_sim-r_obs),2.0f)/stdSqrt2) );
394 ret += log(likelihood);
408 double COccupancyGridMap2D::computeObservationLikelihood_likelihoodField_Thrun(
426 if (!o->
isPlanarScan(insertionOptions.horizontalTolerance))
return -10;
450 ret = computeLikelihoodField_Thrun( &pts, &takenFrom );
462 double COccupancyGridMap2D::computeObservationLikelihood_likelihoodField_II(
480 if (!o->
isPlanarScan(insertionOptions.horizontalTolerance))
return 0.5f;
499 double COccupancyGridMap2D::computeLikelihoodField_Thrun(
const CPointsMap *pm,
const CPose2D *relativePose )
504 size_t N = pm->
size();
505 int K = (int)ceil(likelihoodOptions.LF_maxCorrsDistance / resolution);
507 bool Product_T_OrSum_F = !likelihoodOptions.LF_alternateAverageMethod;
517 float stdHit = likelihoodOptions.LF_stdHit;
518 float zHit = likelihoodOptions.LF_zHit;
519 float zRandom = likelihoodOptions.LF_zRandom;
520 float zRandomMaxRange = likelihoodOptions.LF_maxRange;
521 float zRandomTerm = zRandom / zRandomMaxRange;
522 float Q = -0.5f /
square(stdHit);
525 unsigned int size_x_1 = size_x-1;
526 unsigned int size_y_1 = size_y-1;
530 double maxCorrDist_sq =
square(likelihoodOptions.LF_maxCorrsDistance);
531 double minimumLik = zRandomTerm + zHit * exp( Q * maxCorrDist_sq );
533 float occupiedMinDist;
535 #define LIK_LF_CACHE_INVALID (66)
537 if (likelihoodOptions.enableLikelihoodCache)
540 if (precomputedLikelihoodToBeRecomputed)
544 else precomputedLikelihood.clear();
546 precomputedLikelihoodToBeRecomputed =
false;
550 cellType thresholdCellValue = p2l(0.5f);
551 int decimation = likelihoodOptions.LF_decimation;
553 const double _resolution = this->resolution;
554 const double constDist2DiscrUnits = 100 / (_resolution * _resolution);
555 const double constDist2DiscrUnits_INV = 1.0 / constDist2DiscrUnits;
558 if (N<10) decimation = 1;
563 for (
size_t j=0;j<N;j+= decimation)
566 occupiedMinDist = maxCorrDist_sq;
574 ::sincos(relativePose->
phi(), &ssin,&ccos);
576 ccos = cos(relativePose->
phi());
577 ssin = sin(relativePose->
phi());
579 pointGlobal.
x = relativePose->
x() + pointLocal.
x * ccos - pointLocal.
y * ssin;
580 pointGlobal.
y = relativePose->
y() + pointLocal.
x * ssin + pointLocal.
y * ccos;
588 int cx = x2idx( pointGlobal.
x );
589 int cy = y2idx( pointGlobal.
y );
593 if (
static_cast<unsigned>(cx)>=size_x_1 ||
static_cast<unsigned>(cy)>=size_y_1 )
596 thisLik = minimumLik;
601 if (likelihoodOptions.enableLikelihoodCache)
603 thisLik = precomputedLikelihood[ cx+cy*size_x ];
611 int xx1 = max(0,cx-K);
612 int xx2 =
min(size_x_1,(
unsigned)(cx+K));
613 int yy1 = max(0,cy-K);
614 int yy2 =
min(size_y_1,(
unsigned)(cy+K));
618 cellType *mapPtr = &map[xx1+yy1*size_x];
619 unsigned incrAfterRow = size_x - ((xx2-xx1)+1);
621 signed int Ax0 = 10*(xx1-cx);
622 signed int Ay = 10*(yy1-cy);
624 unsigned int occupiedMinDistInt =
mrpt::utils::round( maxCorrDist_sq * constDist2DiscrUnits );
626 for (
int yy=yy1;yy<=yy2;yy++)
628 unsigned int Ay2 =
square((
unsigned int)(Ay));
632 for (
int xx=xx1;xx<=xx2;xx++)
634 if ( (cell =*mapPtr++) < thresholdCellValue )
636 unsigned int d =
square((
unsigned int)(Ax)) + Ay2;
642 mapPtr += incrAfterRow;
646 occupiedMinDist = occupiedMinDistInt * constDist2DiscrUnits_INV ;
649 if (likelihoodOptions.LF_useSquareDist)
650 occupiedMinDist*=occupiedMinDist;
652 thisLik = zRandomTerm + zHit * exp( Q * occupiedMinDist );
654 if (likelihoodOptions.enableLikelihoodCache)
656 precomputedLikelihood[ cx+cy*size_x ] = thisLik;
661 if (Product_T_OrSum_F)
672 if (!Product_T_OrSum_F)
673 ret = log( ret / M );
683 double COccupancyGridMap2D::computeLikelihoodField_II(
const CPointsMap *pm,
const CPose2D *relativePose )
688 size_t N = pm->
size();
690 if (!N)
return 1e-100;
700 float zRandomTerm = 1.0f / likelihoodOptions.LF_maxRange;
701 float Q = -0.5f /
square( likelihoodOptions.LF_stdHit );
709 int maxRangeInCells = (int)ceil(likelihoodOptions.LF_maxCorrsDistance / resolution);
715 for (j=0;j<N;j+= likelihoodOptions.LF_decimation)
722 pointGlobal = *relativePose + pointLocal;
731 cx0 = x2idx( pointGlobal.
x );
732 cy0 = y2idx( pointGlobal.
y );
736 cx_min = max( cx0-maxRangeInCells,0);
737 cx_max =
min( cx0+maxRangeInCells,
static_cast<int>(size_x));
738 cy_min = max( cy0-maxRangeInCells,0);
739 cy_max =
min( cy0+maxRangeInCells,
static_cast<int>(size_y));
746 for (cx=cx_min;cx<=cx_max;cx++)
748 for (cy=cy_min;cy<=cy_max;cy++)
750 float P_free = getCell(cx,cy);
751 float termDist = exp(Q*(
square(idx2x(cx)-pointGlobal.
x)+
square(idx2y(cy)-pointGlobal.
y) ));
753 lik += P_free * zRandomTerm +
754 (1-P_free) * termDist;
759 if (likelihoodOptions.LF_alternateAverageMethod)
761 else ret += log(lik/((cy_max-cy_min+1)*(cx_max-cx_min+1)));
766 if (likelihoodOptions.LF_alternateAverageMethod && nCells>0)
767 ret = log(ret/nCells);
768 else ret = ret/nCells;
780 COccupancyGridMap2D::TLikelihoodOptions::TLikelihoodOptions() :
781 likelihoodMethod ( lmLikelihoodField_Thrun),
785 LF_zRandom ( 0.05f ),
786 LF_maxRange ( 81.0f ),
788 LF_maxCorrsDistance ( 0.3f ),
789 LF_useSquareDist ( false ),
790 LF_alternateAverageMethod ( false ),
792 MI_exponent ( 2.5f ),
794 MI_ratio_max_distance ( 1.5f ),
796 rayTracing_useDistanceFilter ( true ),
797 rayTracing_decimation ( 10 ),
798 rayTracing_stdHit ( 1.0f ),
800 consensus_takeEachRange ( 1 ),
802 OWA_weights (100,1/100.0f),
804 enableLikelihoodCache ( true )
817 enableLikelihoodCache = iniFile.
read_bool(section,
"enableLikelihoodCache",enableLikelihoodCache);
819 LF_stdHit = iniFile.
read_float(section,
"LF_stdHit",LF_stdHit);
820 LF_zHit = iniFile.
read_float(section,
"LF_zHit",LF_zHit);
821 LF_zRandom = iniFile.
read_float(section,
"LF_zRandom",LF_zRandom);
822 LF_maxRange = iniFile.
read_float(section,
"LF_maxRange",LF_maxRange);
823 LF_decimation = iniFile.
read_int(section,
"LF_decimation",LF_decimation);
824 LF_maxCorrsDistance = iniFile.
read_float(section,
"LF_maxCorrsDistance",LF_maxCorrsDistance);
825 LF_useSquareDist = iniFile.
read_bool(section,
"LF_useSquareDist",LF_useSquareDist);
826 LF_alternateAverageMethod = iniFile.
read_bool(section,
"LF_alternateAverageMethod",LF_alternateAverageMethod);
828 MI_exponent = iniFile.
read_float(section,
"MI_exponent",MI_exponent);
829 MI_skip_rays = iniFile.
read_int(section,
"MI_skip_rays",MI_skip_rays);
830 MI_ratio_max_distance = iniFile.
read_float(section,
"MI_ratio_max_distance",MI_ratio_max_distance);
832 rayTracing_useDistanceFilter = iniFile.
read_bool(section,
"rayTracing_useDistanceFilter",rayTracing_useDistanceFilter);
833 rayTracing_stdHit = iniFile.
read_float(section,
"rayTracing_stdHit",rayTracing_stdHit);
835 consensus_takeEachRange = iniFile.
read_int(section,
"consensus_takeEachRange",consensus_takeEachRange);
836 consensus_pow = iniFile.
read_float(section,
"consensus_pow",consensus_pow);
838 iniFile.
read_vector(section,
"OWA_weights",OWA_weights,OWA_weights);
846 out.
printf(
"\n----------- [COccupancyGridMap2D::TLikelihoodOptions] ------------ \n\n");
848 out.
printf(
"likelihoodMethod = ");
849 switch (likelihoodMethod)
859 out.
printf(
"UNKNOWN!!!");
break;
863 out.
printf(
"enableLikelihoodCache = %c\n", enableLikelihoodCache ?
'Y':
'N');
865 out.
printf(
"LF_stdHit = %f\n", LF_stdHit );
866 out.
printf(
"LF_zHit = %f\n", LF_zHit );
867 out.
printf(
"LF_zRandom = %f\n", LF_zRandom );
868 out.
printf(
"LF_maxRange = %f\n", LF_maxRange );
869 out.
printf(
"LF_decimation = %u\n", LF_decimation );
870 out.
printf(
"LF_maxCorrsDistance = %f\n", LF_maxCorrsDistance );
871 out.
printf(
"LF_useSquareDist = %c\n", LF_useSquareDist ?
'Y':
'N');
872 out.
printf(
"LF_alternateAverageMethod = %c\n", LF_alternateAverageMethod ?
'Y':
'N');
873 out.
printf(
"MI_exponent = %f\n", MI_exponent );
874 out.
printf(
"MI_skip_rays = %u\n", MI_skip_rays );
875 out.
printf(
"MI_ratio_max_distance = %f\n", MI_ratio_max_distance );
876 out.
printf(
"rayTracing_useDistanceFilter = %c\n", rayTracing_useDistanceFilter ?
'Y':
'N');
877 out.
printf(
"rayTracing_decimation = %u\n", rayTracing_decimation );
878 out.
printf(
"rayTracing_stdHit = %f\n", rayTracing_stdHit );
879 out.
printf(
"consensus_takeEachRange = %u\n", consensus_takeEachRange );
880 out.
printf(
"consensus_pow = %.02f\n", consensus_pow);
881 out.
printf(
"OWA_weights = [");
882 for (
size_t i=0;i<OWA_weights.size();i++)
884 if (i<3 || i>(OWA_weights.size()-3))
885 out.
printf(
"%.03f ",OWA_weights[i]);
886 else if (i==3 && OWA_weights.size()>6)
889 out.
printf(
"] (size=%u)\n",(
unsigned)OWA_weights.size());
#define MRPT_LOAD_CONFIG_VAR_CAST(variableName, variableType, variableTypeCast, configFileObject, sectionNameStr)
#define IS_CLASS(ptrObj, class_name)
Evaluates to true if the given pointer to an object (derived from mrpt::utils::CSerializable) is of t...
#define CLASS_ID(class_name)
Access to runtime class ID for a defined class name.
#define LIK_LF_CACHE_INVALID
bool insertObservation(const mrpt::obs::CObservation *obs, const mrpt::poses::CPose3D *robotPose=NULL)
Insert the observation information into this map.
float maxOccupancyUpdateCertainty
A value in the range [0.5,1] used for updating cell with a bayesian approach (default 0....
float mapAltitude
The altitude (z-axis) of 2D scans (within a 0.01m tolerance) for they to be inserted in this map!
bool useMapAltitude
The parameter "mapAltitude" has effect while inserting observations in the grid only if this is true.
float horizontalTolerance
The tolerance in rads in pitch & roll for a laser scan to be considered horizontal,...
float maxDistanceInsertion
The largest distance at which cells will be updated (Default 15 meters)
void loadFromConfigFile(const mrpt::utils::CConfigFileBase &source, const std::string §ion) MRPT_OVERRIDE
This method load the options from a ".ini" file.
void dumpToTextStream(mrpt::utils::CStream &out) const MRPT_OVERRIDE
This method should clearly display all the contents of the structure in textual form,...
A class for storing an occupancy grid map.
uint32_t size_y
The size of the grid in cells.
TInsertionOptions insertionOptions
With this struct options are provided to the observation insertion process.
TLikelihoodMethod
The type for selecting a likelihood computation method.
@ lmLikelihoodField_Thrun
float idx2y(const size_t cy) const
float getCell(int x, int y) const
Read the real valued [0,1] contents of a cell, given its index.
std::pair< double, mrpt::math::TPoint2D > TPairLikelihoodIndex
Auxiliary private class.
bool internal_canComputeObservationLikelihood(const mrpt::obs::CObservation *obs) const MRPT_OVERRIDE
Returns true if this map is able to compute a sensible likelihood function for this observation (i....
float idx2x(const size_t cx) const
Transform a cell index into a coordinate value.
int16_t cellType
The type of the map cells:
A cloud of points in 2D or 3D, which can be built from a sequence of laser scans or other sensors.
size_t size() const
Returns the number of stored points in the map.
unsigned long getPoint(size_t index, float &x, float &y, float &z) const
Access to a given point from map, as a 2D point.
TInsertionOptions insertionOptions
The options used when inserting observations in the map.
A cloud of points in 2D or 3D, which can be built from a sequence of laser scans.
A "CObservation"-derived class that represents a 2D range scan measurement (typically from a laser sc...
float maxRange
The maximum range allowed by the device, in meters (e.g. 80m, 50m,...)
mrpt::utils::ContainerReadOnlyProxyAccessor< std::vector< char > > validRange
It's false (=0) on no reflected rays, referenced to elements in scan.
float aperture
The "aperture" or field-of-view of the range finder, in radians (typically M_PI = 180 degrees).
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.
const POINTSMAP * buildAuxPointsMap(const void *options=NULL) const
Returns a cached points map representing this laser scan, building it upon the first call.
bool isPlanarScan(const double tolerance=0) const
Return true if the laser scanner is "horizontal", so it has an absolute value of "pitch" and "roll" l...
mrpt::utils::ContainerReadOnlyProxyAccessor< std::vector< float > > scan
The range values of the scan, in meters. Must have same length than validRange.
Declares a class that represents any robot's observation.
bool insertObservationInto(METRICMAP *theMap, const mrpt::poses::CPose3D *robotPose=NULL) const
This method is equivalent to:
virtual const mrpt::utils::TRuntimeClassId * GetRuntimeClass() const
Returns information about the class of an object in runtime.
Declares a class derived from "CObservation" that encapsules a single range measurement,...
A class used to store a 2D pose, including the 2D coordinate point and a heading (phi) angle.
void composePoint(double lx, double ly, double &gx, double &gy) const
An alternative, slightly more efficient way of doing with G and L being 2D points and P this 2D pose...
const double & phi() const
Get the phi angle of the 2D pose (in radians)
A class used to store a 3D pose (a 3D translation + a rotation in 3D).
double x() const
Common members of all points & poses classes.
This class allows loading and storing values and vectors of different types from a configuration text...
void read_vector(const std::string §ion, const std::string &name, const VECTOR_TYPE &defaultValue, VECTOR_TYPE &outValues, bool failIfNotFound=false) const
Reads a configuration parameter of type vector, stored in the file as a string: "[v1 v2 v3 ....
bool read_bool(const std::string §ion, const std::string &name, bool defaultValue, bool failIfNotFound=false) const
int read_int(const std::string §ion, const std::string &name, int defaultValue, bool failIfNotFound=false) const
float read_float(const std::string §ion, const std::string &name, float defaultValue, bool failIfNotFound=false) const
This base class is used to provide a unified interface to files,memory buffers,..Please see the deriv...
virtual int printf(const char *fmt,...) MRPT_printf_format_check(2
Writes a string to the stream in a textual form.
GLsizei const GLchar ** string
int round(const T value)
Returns the closer integer (int) to x.
This base provides a set of functions for maths stuff.
T square(const T x)
Inline function for the square of a number.
This namespace contains representation of robot actions and observations.
Classes for 2D/3D geometry representation, both of single values and probability density distribution...
Classes for serialization, sockets, ini-file manipulation, streams, list of properties-values,...
void keep_min(T &var, const K test_val)
If the second argument is below the first one, set the first argument to this lower value.
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
With this struct options are provided to the observation insertion process.
float minDistBetweenLaserPoints
The minimum distance between points (in 3D): If two points are too close, one of them is not inserted...
bool isPlanarMap
If set to true, only HORIZONTAL (in the XY plane) measurements will be inserted in the map (Default v...
float horizontalTolerance
The tolerance in rads in pitch & roll for a laser scan to be considered horizontal,...