Files
2025-06-06 16:15:07 +08:00

244 lines
7.6 KiB
C++

/*****************************************************************
*
* This file is part of the GMAPPING project
*
* GMAPPING Copyright (c) 2004 Giorgio Grisetti,
* Cyrill Stachniss, and Wolfram Burgard
*
* This software is licensed under the "Creative Commons
* License (Attribution-NonCommercial-ShareAlike 2.0)"
* and is copyrighted by Giorgio Grisetti, Cyrill Stachniss,
* and Wolfram Burgard.
*
* Further information on this license can be found at:
* http://creativecommons.org/licenses/by-nc-sa/2.0/
*
* GMAPPING is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE.
*
*****************************************************************/
#include <utils/commandline.h>
#include <carmenwrapper/carmenwrapper.h>
#include <gridfastslam/gridslamprocessor.h>
#include <utils/orientedboundingbox.h>
#include <configfile/configfile.h>
#define DEBUG cout << __PRETTY_FUNCTION__
/*
Example file for interfacing carmen, and gfs.
if you want to look for a specific topic search for one of the following keywords in the file comments
KEYWORDS:
CREATION
INITIALIZATION
SENSOR MAP
BEST PARTICLE INDEX
PARTICLE VECTOR
PARTICLE TRAJECTORIES
BEST MAP
BOUNDING BOX
*/
using namespace GMapping;
using namespace std;
int main(int argc, const char * const * argv){
std::string outfilename="";
double xmin=-100.;
double ymin=-100.;
double xmax=100.;
double ymax=100.;
double delta=0.05;
//scan matching parameters
double sigma=0.05;
double maxrange=80.;
double maxUrange=80.;
double regscore=1e4;
double lstep=.05;
double astep=.05;
int kernelSize=1;
int iterations=5;
double critscore=0.;
double maxMove=1.;
double lsigma=.075;
double ogain=3;
int lskip=0;
//motion model parameters
double srr=0.01, srt=0.01, str=0.01, stt=0.01;
//particle parameters
int particles=30;
//gfs parameters
double angularUpdate=0.5;
double linearUpdate=1;
double resampleThreshold=0.5;
bool generateMap=true;
std::string configfilename = "";
CMD_PARSE_BEGIN_SILENT(1,argc);
parseStringSilent("-cfg",configfilename);
CMD_PARSE_END_SILENT;
if (configfilename.length()>0){
ConfigFile cfg(configfilename);
outfilename = (std::string) cfg.value("gfs","outfilename",outfilename);
xmin = cfg.value("gfs","xmin", xmin);
xmax = cfg.value("gfs","xmax",xmax);
ymin = cfg.value("gfs","ymin",ymin);
ymax = cfg.value("gfs","ymax",ymax);
delta = cfg.value("gfs","delta",delta);
maxrange = cfg.value("gfs","maxrange",maxrange);
maxUrange = cfg.value("gfs","maxUrange",maxUrange);
regscore = cfg.value("gfs","regscore",regscore);
critscore = cfg.value("gfs","critscore",critscore);
kernelSize = cfg.value("gfs","kernelSize",kernelSize);
sigma = cfg.value("gfs","sigma",sigma);
iterations = cfg.value("gfs","iterations",iterations);
lstep = cfg.value("gfs","lstep",lstep);
astep = cfg.value("gfs","astep",astep);
maxMove = cfg.value("gfs","maxMove",maxMove);
srr = cfg.value("gfs","srr", srr);
srt = cfg.value("gfs","srt", srt);
str = cfg.value("gfs","str", str);
stt = cfg.value("gfs","stt", stt);
particles = cfg.value("gfs","particles",particles);
angularUpdate = cfg.value("gfs","angularUpdate", angularUpdate);
linearUpdate = cfg.value("gfs","linearUpdate", linearUpdate);
lsigma = cfg.value("gfs","lsigma", lsigma);
ogain = cfg.value("gfs","lobsGain", ogain);
lskip = (int)cfg.value("gfs","lskip", lskip);
// randseed = cfg.value("gfs","randseed", randseed);
resampleThreshold = cfg.value("gfs","resampleThreshold", resampleThreshold);
generateMap = cfg.value("gfs","generateMap", generateMap);
}
CMD_PARSE_BEGIN(1,argc);
parseString("-cfg",configfilename);
parseString("-outfilename",outfilename);
parseDouble("-xmin",xmin);
parseDouble("-xmax",xmax);
parseDouble("-ymin",ymin);
parseDouble("-ymax",ymax);
parseDouble("-delta",delta);
parseDouble("-maxrange",maxrange);
parseDouble("-maxUrange",maxUrange);
parseDouble("-regscore",regscore);
parseDouble("-critscore",critscore);
parseInt("-kernelSize",kernelSize);
parseDouble("-sigma",sigma);
parseInt("-iterations",iterations);
parseDouble("-lstep",lstep);
parseDouble("-astep",astep);
parseDouble("-maxMove",maxMove);
parseDouble("-srr", srr);
parseDouble("-srt", srt);
parseDouble("-str", str);
parseDouble("-stt", stt);
parseInt("-particles",particles);
parseDouble("-angularUpdate", angularUpdate);
parseDouble("-linearUpdate", linearUpdate);
parseDouble("-lsigma", lsigma);
parseDouble("-lobsGain", ogain);
parseInt("-lskip", lskip);
parseDouble("-resampleThreshold", resampleThreshold);
parseFlag("-generateMap", generateMap);
CMD_PARSE_END;
cerr << "Parameter parsed, connecting to Carmen!";
CarmenWrapper::initializeIPC(argv[0]);
CarmenWrapper::start(argv[0]);
while (! CarmenWrapper::sensorMapComputed()){
usleep(500000);
cerr << "." << flush;
}
//CREATION
GridSlamProcessor* processor=new GridSlamProcessor;
//SENSOR MAP
//loads from the carmen wrapper the laser and robot settings
SensorMap sensorMap=CarmenWrapper::sensorMap();
cerr << "Connected " << endl;
processor->setSensorMap(sensorMap);
//set the command line parameters
processor->setMatchingParameters(maxUrange, maxrange, sigma, kernelSize, lstep, astep, iterations, lsigma, ogain, lskip);
processor->setMotionModelParameters(srr, srt, str, stt);
processor->setUpdateDistances(linearUpdate, angularUpdate, resampleThreshold);
processor->setgenerateMap(generateMap);
OrientedPoint initialPose(xmin+xmax/2, ymin+ymax/2, 0);
//INITIALIZATION
processor->init(particles, xmin, ymin, xmax, ymax, delta, initialPose);
if (outfilename.length()>0)
processor->outputStream().open(outfilename.c_str());
bool running=true;
GridSlamProcessor* ap, *copy=processor->clone();
ap=processor; processor=copy; copy=ap;
//this is the CORE LOOP;
RangeReading rr(0,0);
while (running){
while (CarmenWrapper::getReading(rr)){
bool processed=processor->processScan(rr);
//this returns true when the algorithm effectively processes (the traveled path since the last processing is over a given threshold)
if (processed){
cerr << "PROCESSED" << endl;
//for searching for the BEST PARTICLE INDEX
// unsigned int best_idx=processor->getBestParticleIndex();
//if you want to access to the PARTICLE VECTOR
const GridSlamProcessor::ParticleVector& particles = processor->getParticles();
//remember to use a const reference, otherwise it copys the whole particles and maps
//this is for recovering the tree of PARTICLE TRAJECTORIES (obtaining the ancestor of each particle)
cerr << "Particle reproduction story begin" << endl;
for (unsigned int i=0; i<particles.size(); i++){
cerr << particles[i].previousIndex << "->" << i << " ";
}
cerr << "Particle reproduction story end" << endl;
/*
//then if you want to access the BEST MAP,
//of course by copying it in a plain structure
Map<double, DoubleArray2D, false>* mymap = processor->getParticles()[best_idx].map.toDoubleMap();
//at this point mymap is yours. Can do what you want.
double best_weight=particles[best_idx].weightSum;
cerr << "Best Particle is " << best_idx << " with weight " << best_weight << endl;
*/
cerr << __PRETTY_FUNCTION__ << "CLONING... " << endl;
GridSlamProcessor* newProcessor=processor->clone();
cerr << "DONE" << endl;
cerr << __PRETTY_FUNCTION__ << "DELETING... " << endl;
delete processor;
cerr << "DONE" << endl;
processor=newProcessor;
}
}
}
return 0;
}