Files
agv_pro_ros2/slam_gmapping/openslam_gmapping/scanmatcher/scanmatcherprocessor.cpp
T
2025-06-06 16:15:07 +08:00

234 lines
6.7 KiB
C++

#include <iostream>
#include "scanmatcherprocessor.h"
#include "eig3.h"
//#define SCANMATHCERPROCESSOR_DEBUG
namespace GMapping {
using namespace std;
ScanMatcherProcessor::ScanMatcherProcessor(const ScanMatcherMap& m)
: m_map(m.getCenter(), m.getWorldSizeX(), m.getWorldSizeY(), m.getResolution()),
m_pose(0,0,0){
m_regScore=300;
m_critScore=.5*m_regScore;
m_maxMove=1;
m_beams=0;
m_computeCovariance=false;
//m_eigenspace=gsl_eigen_symmv_alloc(3);
useICP=false;
}
ScanMatcherProcessor::ScanMatcherProcessor
(double xmin, double ymin, double xmax, double ymax, double delta, double patchdelta):
m_map(Point((xmax+xmin)*.5, (ymax+ymin)*.5), xmax-xmin, ymax-ymin, patchdelta), m_pose(0,0,0){
m_regScore=300;
m_critScore=.5*m_regScore;
m_maxMove=1;
m_beams=0;
m_computeCovariance=false;
//m_eigenspace=gsl_eigen_symmv_alloc(3);
useICP=false;
}
ScanMatcherProcessor::~ScanMatcherProcessor (){
//gsl_eigen_symmv_free(m_eigenspace);
}
void ScanMatcherProcessor::setSensorMap(const SensorMap& smap, std::string sensorName){
m_sensorMap=smap;
/*
Construct the angle table for the sensor
FIXME has to be extended to more than one laser...
*/
SensorMap::const_iterator laser_it=m_sensorMap.find(sensorName);
assert(laser_it!=m_sensorMap.end());
const RangeSensor* rangeSensor=dynamic_cast<const RangeSensor*>((laser_it->second));
assert(rangeSensor && rangeSensor->beams().size());
m_beams=static_cast<unsigned int>(rangeSensor->beams().size());
double* angles=new double[rangeSensor->beams().size()];
for (unsigned int i=0; i<m_beams; i++){
angles[i]=rangeSensor->beams()[i].pose.theta;
}
m_matcher.setLaserParameters(m_beams, angles, rangeSensor->getPose());
delete [] angles;
}
void ScanMatcherProcessor::init(){
m_first=true;
m_pose=OrientedPoint(0,0,0);
m_count=0;
}
void ScanMatcherProcessor::processScan(const RangeReading & reading){
/**retireve the position from the reading, and compute the odometry*/
OrientedPoint relPose=reading.getPose();
if (!m_count){
m_odoPose=relPose;
}
//compute the move in the scan m_matcher
//reference frame
OrientedPoint move=relPose-m_odoPose;
double dth=m_odoPose.theta-m_pose.theta;
// cout << "rel-move x="<< move.x << " y=" << move.y << " theta=" << move.theta << endl;
double lin_move=move*move;
if (lin_move>m_maxMove){
cerr << "Too big jump in the log file: " << lin_move << endl;
cerr << "relPose=" << relPose.x << " " <<relPose.y << endl;
cerr << "ignoring" << endl;
return;
//assert(0);
dth=0;
move.x=move.y=move.theta=0;
}
double s=sin(dth), c=cos(dth);
OrientedPoint dPose;
dPose.x=c*move.x-s*move.y;
dPose.y=s*move.x+c*move.y;
dPose.theta=move.theta;
#ifdef SCANMATHCERPROCESSOR_DEBUG
cout << "abs-move x="<< dPose.x << " y=" << dPose.y << " theta=" << dPose.theta << endl;
#endif
m_pose=m_pose+dPose;
m_pose.theta=atan2(sin(m_pose.theta), cos(m_pose.theta));
#ifdef SCANMATHCERPROCESSOR_DEBUG
cout << "StartPose: x="
<< m_pose.x << " y=" << m_pose.y << " theta=" << m_pose.theta << endl;
#endif
m_odoPose=relPose; //update the past pose for the next iteration
//FIXME here I assume that everithing is referred to the center of the robot,
//while the offset of the laser has to be taken into account
assert(reading.size()==m_beams);
/*
double * plainReading = new double[m_beams];
#ifdef SCANMATHCERPROCESSOR_DEBUG
cout << "PackedReadings ";
#endif
for(unsigned int i=0; i<m_beams; i++){
plainReading[i]=reading[i];
#ifdef SCANMATHCERPROCESSOR_DEBUG
cout << plainReading[i] << " ";
#endif
}
*/
double * plainReading = new double[m_beams];
reading.rawView(plainReading, m_map.getDelta());
#ifdef SCANMATHCERPROCESSOR_DEBUG
cout << endl;
#endif
//the final stuff: scan match the pose
double score=0;
OrientedPoint newPose=m_pose;
if (m_count){
if(m_computeCovariance){
ScanMatcher::CovarianceMatrix cov;
score=m_matcher.optimize(newPose, cov, m_map, m_pose, plainReading);
/*
gsl_matrix* m=gsl_matrix_alloc(3,3);
gsl_matrix_set(m,0,0,cov.xx); gsl_matrix_set(m,0,1,cov.xy); gsl_matrix_set(m,0,2,cov.xt);
gsl_matrix_set(m,1,0,cov.xy); gsl_matrix_set(m,1,1,cov.yy); gsl_matrix_set(m,1,2,cov.yt);
gsl_matrix_set(m,2,0,cov.xt); gsl_matrix_set(m,2,1,cov.yt); gsl_matrix_set(m,2,2,cov.tt);
gsl_matrix* evec=gsl_matrix_alloc(3,3);
gsl_vector* eval=gsl_vector_alloc(3);
*/
double m[3][3];
double evec[3][3];
double eval[3];
m[0][0] = cov.xx;
m[0][1] = cov.xy;
m[0][2] = cov.xt;
m[1][0] = cov.xy;
m[1][1] = cov.yy;
m[1][2] = cov.yt;
m[2][0] = cov.xt;
m[2][1] = cov.yt;
m[2][2] = cov.tt;
//gsl_eigen_symmv (m, eval, evec, m_eigenspace);
eigen_decomposition(m,evec,eval);
#ifdef SCANMATHCERPROCESSOR_DEBUG
//cout << "evals=" << gsl_vector_get(eval, 0) << " " << gsl_vector_get(eval, 1)<< " " << gsl_vector_get(eval, 2)<<endl;
cout << "evals=" << eval[0] << " " << eval[1]<< " " << eval[2]<<endl;
#endif
//gsl_matrix_free(m);
//gsl_matrix_free(evec);
//gsl_vector_free(eval);
} else {
if (useICP){
cerr << "USING ICP" << endl;
score=m_matcher.icpOptimize(newPose, m_map, m_pose, plainReading);
}else
score=m_matcher.optimize(newPose, m_map, m_pose, plainReading);
}
}
//...and register the scan
if (!m_count || score<m_regScore){
#ifdef SCANMATHCERPROCESSOR_DEBUG
cout << "Registering" << endl;
#endif
m_matcher.invalidateActiveArea();
if (score<m_critScore){
#ifdef SCANMATHCERPROCESSOR_DEBUG
cout << "New Scan added, using odo pose" << endl;
#endif
m_matcher.registerScan(m_map, m_pose, plainReading);
} else {
m_matcher.registerScan(m_map, newPose, plainReading);
#ifdef SCANMATHCERPROCESSOR_DEBUG
cout << "New Scan added, using matched pose" << endl;
#endif
}
}
#ifdef SCANMATHCERPROCESSOR_DEBUG
cout << " FinalPose: x="
<< newPose.x << " y=" << newPose.y << " theta=" << newPose.theta << endl;
cout << "score=" << score << endl;
#endif
m_pose=newPose;
delete [] plainReading;
m_count++;
}
void ScanMatcherProcessor::setMatchingParameters
(double urange, double range, double sigma, int kernsize, double lopt, double aopt, int iterations, bool computeCovariance){
m_matcher.setMatchingParameters(urange, range, sigma, kernsize, lopt, aopt, iterations);
m_computeCovariance=computeCovariance;
}
void ScanMatcherProcessor::setRegistrationParameters(double regScore, double critScore){
m_regScore=regScore;
m_critScore=critScore;
}
OrientedPoint ScanMatcherProcessor::getPose() const{
return m_pose;
}
};