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);
258 compareGrid.insertionOptions.maxDistanceInsertion = insertionOptions.maxDistanceInsertion;
259 compareGrid.insertionOptions.maxOccupancyUpdateCertainty = 0.95f;
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);
281 float c2 = compareGrid.getCell(
x,
y);
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());
bool insertObservationInto(METRICMAP *theMap, const mrpt::poses::CPose3D *robotPose=NULL) const
This method is equivalent to:
double x() const
Common members of all points & poses classes.
bool isPlanarMap
If set to true, only HORIZONTAL (in the XY plane) measurements will be inserted in the map (Default v...
bool read_bool(const std::string §ion, const std::string &name, bool defaultValue, bool failIfNotFound=false) const
Declares a class derived from "CObservation" that encapsules a single range measurement, and associated parameters.
Classes for serialization, sockets, ini-file manipulation, streams, list of properties-values, timewatch, extensions to STL.
float read_float(const std::string §ion, const std::string &name, float defaultValue, bool failIfNotFound=false) const
TLikelihoodMethod
The type for selecting a likelihood computation method.
A cloud of points in 2D or 3D, which can be built from a sequence of laser scans. ...
TInsertionOptions insertionOptions
With this struct options are provided to the observation insertion process.
void dumpToTextStream(mrpt::utils::CStream &out) const MRPT_OVERRIDE
This method should clearly display all the contents of the structure in textual form, sending it to a CStream.
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...
This class allows loading and storing values and vectors of different types from a configuration text...
T square(const T x)
Inline function for the square of a number.
float maxRange
The maximum range allowed by the device, in meters (e.g. 80m, 50m,...)
int read_int(const std::string §ion, const std::string &name, int defaultValue, bool failIfNotFound=false) const
With this struct options are provided to the observation insertion process.
This base class is used to provide a unified interface to files,memory buffers,..Please see the deriv...
A cloud of points in 2D or 3D, which can be built from a sequence of laser scans or other sensors...
This base provides a set of functions for maths stuff.
virtual const mrpt::utils::TRuntimeClassId * GetRuntimeClass() const
Returns information about the class of an object in runtime.
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...
#define MRPT_LOAD_CONFIG_VAR_CAST(variableName, variableType, variableTypeCast, configFileObject, sectionNameStr)
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 ...
#define LIK_LF_CACHE_INVALID
This namespace contains representation of robot actions and observations.
mrpt::utils::ContainerReadOnlyProxyAccessor< std::vector< char > > validRange
It's false (=0) on no reflected rays, referenced to elements in scan.
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...
GLsizei const GLchar ** string
Classes for 2D/3D geometry representation, both of single values and probability density distribution...
#define CLASS_ID(class_name)
Access to runtime class ID for a defined class name.
A class for storing an occupancy grid 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.
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
A "CObservation"-derived class that represents a 2D range scan measurement (typically from a laser sc...
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...
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.
float horizontalTolerance
The tolerance in rads in pitch & roll for a laser scan to be considered horizontal, then processed by calls to this class (default=0).
const double & phi() const
Get the phi angle of the 2D pose (in radians)
#define IS_CLASS(ptrObj, class_name)
Evaluates to true if the given pointer to an object (derived from mrpt::utils::CSerializable) is of t...
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, considered only when isPlanarMap=true (default=0).
float aperture
The "aperture" or field-of-view of the range finder, in radians (typically M_PI = 180 degrees)...
float mapAltitude
The altitude (z-axis) of 2D scans (within a 0.01m tolerance) for they to be inserted in this map! ...
int round(const T value)
Returns the closer integer (int) to x.
TInsertionOptions insertionOptions
The options used when inserting observations in the map.
mrpt::utils::ContainerReadOnlyProxyAccessor< std::vector< float > > scan
The range values of the scan, in meters. Must have same length than validRange.
size_t size() const
Returns the number of stored points in the map.
std::pair< double, mrpt::math::TPoint2D > TPairLikelihoodIndex
Auxiliary private class.
bool insertObservation(const mrpt::obs::CObservation *obs, const mrpt::poses::CPose3D *robotPose=NULL)
Insert the observation information into this map.
int16_t cellType
The type of the map cells:
mrpt::poses::CPose3D sensorPose
The 6D pose of the sensor on the robot at the moment of starting the scan.
void loadFromConfigFile(const mrpt::utils::CConfigFileBase &source, const std::string §ion) MRPT_OVERRIDE
This method load the options from a ".ini" file.
virtual int printf(const char *fmt,...) MRPT_printf_format_check(2
Writes a string to the stream in a textual form.
bool rightToLeft
The scanning direction: true=counterclockwise; false=clockwise.
float minDistBetweenLaserPoints
The minimum distance between points (in 3D): If two points are too close, one of them is not inserted...
const POINTSMAP * buildAuxPointsMap(const void *options=NULL) const
Returns a cached points map representing this laser scan, building it upon the first call...