11 const double ScanMatcher::nullLikelihood=-1.;
13 ScanMatcher::ScanMatcher(): m_laserPose(0,0,0){
16 m_optRecursiveIterations=3;
22 m_lasamplerange=0.005;
55 lp.
x+=cos(p.theta)*m_laserPose.x-sin(p.theta)*m_laserPose.y;
56 lp.y+=sin(p.theta)*m_laserPose.x+cos(p.theta)*m_laserPose.y;
57 lp.theta+=m_laserPose.theta;
60 for (
const double* r=readings; r<readings+
m_laserBeams; r++, angle++)
63 if (d>m_laserMaxRange)
68 Point phit=lp+
Point(d*cos(lp.theta+*angle),d*sin(lp.theta+*angle));
75 GridLineTraversalLine line;
76 line.points=linePoints;
79 for (
int i=0; i<line.num_points-1; i++){
80 activeArea.insert(map.storage().patchIndexes(linePoints[i]));
82 if (d<=m_usableRange){
83 activeArea.insert(map.storage().patchIndexes(p1));
87 if (*r>m_laserMaxRange||*r>m_usableRange)
continue;
89 phit.
x+=*r*cos(lp.theta+*angle);
90 phit.y+=*r*sin(lp.theta+*angle);
92 assert(p1.x>=0 && p1.y>=0);
93 IntPoint cp=map.storage().patchIndexes(p1);
94 assert(cp.x>=0 && cp.y>=0);
95 activeArea.insert(cp);
100 map.storage().setActiveArea(activeArea,
true);
109 map.storage().allocActiveArea();
112 lp.
x+=cos(p.theta)*m_laserPose.x-sin(p.theta)*m_laserPose.y;
113 lp.y+=sin(p.theta)*m_laserPose.x+cos(p.theta)*m_laserPose.y;
114 lp.theta+=m_laserPose.theta;
117 for (
const double* r=readings; r<readings+
m_laserBeams; r++, angle++)
120 if (d>m_laserMaxRange)
124 Point phit=lp+
Point(d*cos(lp.theta+*angle),d*sin(lp.theta+*angle));
131 GridLineTraversalLine line;
132 line.points=linePoints;
135 for (
int i=0; i<line.num_points-1; i++){
136 map.cell(line.points[i]).update(
false,
Point(0,0));
138 if (d<=m_usableRange){
139 map.cell(p1).update(
true,phit);
143 if (*r>m_laserMaxRange||*r>m_usableRange)
continue;
145 phit.
x+=*r*cos(lp.theta+*angle);
146 phit.y+=*r*sin(lp.theta+*angle);
147 map.cell(phit).update(
true,phit);
156 double currentScore=
score(map, currentPose, readings);
157 double adelta=m_optAngularDelta, ldelta=m_optLinearDelta;
158 unsigned int refinement=0;
159 enum Move{Front, Back, Left, Right, TurnLeft, TurnRight, Done};
162 if (bestScore>=currentScore){
167 bestScore=currentScore;
175 localPose=currentPose;
194 localPose.theta+=adelta;
198 localPose.theta-=adelta;
203 double localScore=
score(map, localPose, readings);
204 if (localScore>currentScore){
205 currentScore=localScore;
206 bestLocalPose=localPose;
210 currentPose=bestLocalPose;
213 }
while (currentScore>bestScore || refinement<m_optRecursiveIterations);
229 ScoredMoveList moveList;
232 ScoredMove sm={currentPose,0,0};
233 unsigned int matched=
likelihoodAndScore(sm.score, sm.likelihood, map, currentPose, readings);
234 double currentScore=sm.score;
235 moveList.push_back(sm);
236 double adelta=m_optAngularDelta, ldelta=m_optLinearDelta;
237 unsigned int refinement=0;
238 enum Move{Front, Back, Left, Right, TurnLeft, TurnRight, Done};
240 if (bestScore>=currentScore){
245 bestScore=currentScore;
253 localPose=currentPose;
272 localPose.theta+=adelta;
276 localPose.theta-=adelta;
281 double localScore, localLikelihood;
284 if (localScore>currentScore){
285 currentScore=localScore;
286 bestLocalPose=localPose;
289 sm.likelihood=localLikelihood;
291 moveList.push_back(sm);
294 currentPose=bestLocalPose;
297 }
while (currentScore>bestScore || refinement<m_optRecursiveIterations);
303 for (ScoredMoveList::const_iterator it=moveList.begin(); it!=moveList.end(); it++){
304 lmin=it->likelihood<lmin?it->likelihood:lmin;
305 lmax=it->likelihood>lmax?it->likelihood:lmax;
308 for (ScoredMoveList::iterator it=moveList.begin(); it!=moveList.end(); it++){
309 it->likelihood=exp(it->likelihood-lmax);
315 for (ScoredMoveList::const_iterator it=moveList.begin(); it!=moveList.end(); it++){
316 mean=mean+it->pose*it->likelihood;
317 lacc+=it->likelihood;
323 for (ScoredMoveList::const_iterator it=moveList.begin(); it!=moveList.end(); it++){
325 delta.theta=atan2(sin(delta.theta), cos(delta.theta));
326 cov.xx+=delta.x*delta.x*it->likelihood;
327 cov.yy+=delta.y*delta.y*it->likelihood;
328 cov.tt+=delta.theta*delta.theta*it->likelihood;
329 cov.xy+=delta.x*delta.y*it->likelihood;
330 cov.xt+=delta.x*delta.theta*it->likelihood;
331 cov.yt+=delta.y*delta.theta*it->likelihood;
333 cov.xx/=lacc, cov.xy/=lacc, cov.xt/=lacc, cov.yy/=lacc, cov.yt/=lacc, cov.tt/=lacc;
341 (
unsigned int beams,
double* angles,
const OrientedPoint& lpose){
353 ScoredMoveList moveList;
356 for (
double xx=-m_llsamplerange; xx<=m_llsamplerange; xx+=m_llsamplestep)
357 for (
double yy=-m_llsamplerange; yy<=m_llsamplerange; yy+=m_llsamplestep)
358 for (
double tt=-m_lasamplerange; tt<=m_lasamplerange; tt+=m_lasamplestep){
369 moveList.push_back(sm);
377 for (ScoredMoveList::const_iterator it=moveList.begin(); it!=moveList.end(); it++){
378 lmax=it->likelihood>lmax?it->likelihood:lmax;
380 for (ScoredMoveList::iterator it=moveList.begin(); it!=moveList.end(); it++){
382 lcum+=exp(it->likelihood-lmax);
383 it->likelihood=exp(it->likelihood-lmax);
388 for (ScoredMoveList::const_iterator it=moveList.begin(); it!=moveList.end(); it++){
389 mean=mean+it->pose*it->likelihood;
394 for (ScoredMoveList::const_iterator it=moveList.begin(); it!=moveList.end(); it++){
396 delta.
theta=atan2(sin(delta.theta), cos(delta.theta));
397 cov.xx+=delta.x*delta.x*it->likelihood;
398 cov.yy+=delta.y*delta.y*it->likelihood;
399 cov.tt+=delta.theta*delta.theta*it->likelihood;
400 cov.xy+=delta.x*delta.y*it->likelihood;
401 cov.xt+=delta.x*delta.theta*it->likelihood;
402 cov.yt+=delta.y*delta.theta*it->likelihood;
404 cov.xx/=lcum, cov.xy/=lcum, cov.xt/=lcum, cov.yy/=lcum, cov.yt/=lcum, cov.tt/=lcum;
409 return log(lcum)+lmax;
413 (
double urange,
double range,
double sigma,
int kernsize,
double lopt,
double aopt,
int iterations,
double likelihoodSigma,
unsigned int likelihoodSkip){
414 m_usableRange=urange;
415 m_laserMaxRange=range;
416 m_kernelSize=kernsize;
417 m_optLinearDelta=lopt;
418 m_optAngularDelta=aopt;
419 m_optRecursiveIterations=iterations;
420 m_gaussianSigma=sigma;
421 m_likelihoodSigma=likelihoodSigma;
422 m_likelihoodSkip=likelihoodSkip;
const char *const *argv double delta
std::set< point< int >, pointcomparator< int > > PointSet
double optimize(OrientedPoint &pnew, const ScanMatcherMap &map, const OrientedPoint &p, const double *readings) const
double registerScan(ScanMatcherMap &map, const OrientedPoint &p, const double *readings)
unsigned int likelihoodAndScore(double &s, double &l, const ScanMatcherMap &map, const OrientedPoint &p, const double *readings) const
void setLaserParameters(unsigned int beams, double *angles, const OrientedPoint &lpose)
void invalidateActiveArea()
void setMatchingParameters(double urange, double range, double sigma, int kernsize, double lopt, double aopt, int iterations, double likelihoodSigma=1, unsigned int likelihoodSkip=0)
Map< PointAccumulator, HierarchicalArray2D< PointAccumulator > > ScanMatcherMap
double m_laserAngles[LASER_MAXBEAMS]
unsigned int m_laserBeams
double score(const ScanMatcherMap &map, const OrientedPoint &p, const double *readings) const
static void gridLine(IntPoint start, IntPoint end, GridLineTraversalLine *line)
std::list< ScoredMove > ScoredMoveList
double likelihood(double &lmax, OrientedPoint &mean, CovarianceMatrix &cov, const ScanMatcherMap &map, const OrientedPoint &p, const double *readings)
Covariance3 CovarianceMatrix
void computeActiveArea(ScanMatcherMap &map, const OrientedPoint &p, const double *readings)
bool m_activeAreaComputed
orientedpoint< double, double > OrientedPoint