从很多博客上看了关于gmapping的源码详解,至今不是很详细,有些部分不是很理解,决定综合一下,自己对着远吗看一遍,同时把笔记记录下来。
参考来源:http://www.cnblogs.com/yhlx125/p/5634128.html
以及github源码
接下来先看gridslamprocessor源文件:
首先是头文件:
namespace GMapping { /* 首先定义粒子结构体信息 */ struct ParticleData_{ OrientedPoint pose; /* 机器人在前一刻的坐标 */ OrientedPoint previousPose; double weight; //粒子权重 double weightSum; //累积权重 double gweight; //???我也不知道是什么 int previousIndex;//前一个粒子的标号,the trajectory }; typedef struct Particle_ ParticleData; //这个类定义基本的GridFastSLAM algorithm,定义了一个粒子滤波器,每一个粒子有自己的地图机器人坐标,整个工作流程如下:每一次接收到新的里程计和激光读数对,然后把栗子的机器人坐标进行更新,更新策略按照运动学模型,随后,这个坐标用来初始化一个scan matching algorithm。scanmatcher展现了一个局部优化,使用运动学模型对坐标进行初始化。为了避免不必要的计算,只有在机器人移动超过阈值的时候,才更新滤波器状态。 class GridSlamProcessor{ public: //首先定义一个策略树的翻转节点node(别问我啥意思,那个地没看懂) //每一个树的节点有一个标记指向父母和一个计数器指向孩子的数量 //粒子更新的话,树就更新?? struct TNode{ //构造the trajectory tree的node //参数有机器人坐标pose、权重weight、累积权重、父母、孩子数 //构造函数,!(天啊,构造函数啊,结构体也可以用构造函数) TNode(const OrientedPoint& pose, double weight, Tnode* parent = 0, unsigned int childs = 0); //析构函数:毁灭一个树节点,并持续的更新树,如果一个有父母的节点被删除了,并且这个父母只有这一个节点,那么父母节点也删除,因为在策略树种们不会再有任何能抵达父母的可能性。 ~TNode(); //机器人坐标 OrientedPoint pose; double weight; double accweight; double gweight; TNode* parent; unsigned int childs; //计数器关于访问节点???????? mutable unsigned int visitCounter; //visit flag mutable bool flag; }; typedef std::vector<GridSlamProcessor::TNode*> TNodeVector; typedef std::deque<GridSlamProcessor::TNode*> TNodeDeque;//为毛用这个。。这个deque叫做双端队列 //定义滤波器的粒子,每一个例子有一个地图、坐标、权重和保留的当前策略树中的node
struct Particle{
//构造一个粒子,给一个地图,输入参数,粒子地图
Particle(const ScanMatcherMap& map);
inline operator double() const {return weight;}//内联没意见,加个operator、const是什么意思?
inline operator OrientedPoint() const {return pose;}//返回坐标
//设置粒子权重
inline void setWeight(double w) {weight=w;}
//下面就是定义相关结构体的一些参数了
ScanMatcherMap map;
OrientedPoint pose;
OrientedPoint previousPose;
double weight;
double weightSum;
double gweight;
int previousIndex;//前一个粒子的序号
Tnode* node;//???
}
typedef std::vector<Particle> ParticleVector;
//以上大概是定义了两个结构体,以及其变量、成员函数等,接下来是本类的一些。。。
//构造函数,初始化使用
GridSlamProcessor();
GridSlamProcessor(std::ostream& infoStr);//构造函数2号,输入流?
//可镂grid slam的所有内部结构
GridSlamProcessor* clone() const;//const表明这个函数不会修改类中的数据成员
//析构函数
Virtual ~GridSlamProcessor();//当一个列被作用基类的时候,析构函数才会被写成虚析构函数,能避免内存泄漏
//获取栅格地图
InfMap getInfMap(void);
//处理参数的方法
void setSensorMap(const SensorMap& smap);//传入的SensorMap变量 在const修饰下会自动创建一个临时变量,不明白这样做的道理
void init(unsigned int size, double xmin, double ymin, double xmax, double ymax, double delta, OrientedPoint initialPose=OrientedPoint(0,0,0));
void setMatchingParameters(double urange, double range, double sigma, int kernsize, double lopt, double aopt, int iterations, double likelihoodSigma=1, double likelihoodGain=1, unsigned int likelihoodSkip=0);
void setMotionModelParameters(double srr, double srt, double str, double stt);
void setUpdateDistances(double linear, double angular, double resampleThreshold);
void setUpdatePeriod(double p) {period_=p;}
//核心算法
void processTruePos(const OdometryReading & odometry);
bool processScan(const RangeReading & reading, int adaptParticles=0);
//这个方法复制树种滤波器的状态
//树使用逆指针表示(每一个节点都有一个指针指向父母)
//叶节点存储在vector中,尺寸和粒子的总数一样
//返回树木的叶节点
TnodeVector getTrajectories() const;
void integrateScanSequence(Tnode* node);
//scanmatcher算法
ScanMatcherm_matcher;
//用于写输出流的算法
std::ofstream& outputStream();
//用于写info/debug信息
std::ostream& infoDtream();
//获得粒子
inline const ParticleVector& getParticles() const {return m_particles;}
int getBestParticleIndex() const;
//回调函数
virtual void onOdometryUpdate();
virtual void onResampleUpdate();
virtual void onScanmatchUpdate();
//存取值accessor methods
//下面的都是宏定义的,文件在utils文件夹中的macro_params中
//MEMBER_PARAM_SET_GET(member, type, name, qualifier, setqualifier, getqualifier)
//get的话,以type类型 返回 member.get##name(),set的话,以type设置member.set##name(name)
MEMBER_PARAM_SET_GET(m_matcher, double, laserMaxRange, protected, public, public);//与此相同的,还要设置usableRangegaussianSigmalikelihoodSigmakernelSize
optAngularDelta optLinearDelta optRecursiveIterations likelihoodSkip llsamplerange lasamplerange llsamplestep lasamplestep generateMap enlargeStep OrientedPoint srr srt str stt 以及minimumScore protected: //复制构造函数 GridSlamProcessor(const GridSlamProcessor& gsp); //激光束 unsigned intm_beams; double last_update_time_; double period_; //粒子群 ParticleVector m_particles; //内部使用,重采样后的内部标记??? std::vector<unsigned int> m_indexes; //粒子权重,内部使用 std::vector<double> m_weights; //运动模型 MotionModel m_motionModel; PARAM_SET_GET(...resampleThreshold ...) //state int m_count, m_readingCount; OrientedPoint m_lastPartPose; OrientedPoint m_odoPose; OrientedPoint m_pose; double m_linearDistance, m_angularDistance; //以下是设置一些参数或者get一些 PARAM_GET(...xmin...) ymin xmax ymax delta regScore critScore maxMove linearThresholdDistacne angularThresholdDistance obsSIgmaGain //写数据流?gfs file std::ofstream m_outputStream; //write messages std::ostream& m_infoStream; private: InfMap cvMap_;//栅格地图参数 bool isInitParas_;//是否初始化参数 std::vector<ParticleData> v_particleData;//粒子的备份 ICP *icp; Gridmap *map;//栅格地图对象 Laser laser;//雷达扫描数据 bool isCopyParticleData;//是否备份粒子 void initParasite(void); void refreshGridmap();//刷新地图 void copyParticles();拷贝粒子数据 void recoverParticles(void)//复原粒子数据 OrientedPoint getPose(void)//获得最优粒子位置 bool judgeGmappingNormal(void);//判断gmapping 是否正常,正常则插图,否则不插 void laserScanConvert(const RangeReading & reading); //scanMatch all the particles inline void scanMatch(comst double *plainReading); inline void normalize();//归一化权重 //重采样?? inline bool resample(const double* plainReading, int adaptParticles, const RangeReading* rr=0); //tree uyiliyies void updateTreeWeights(bool weightsAlreadyNormalized = false); void resetTree(); double propagateWeights() }; typedef std::multimap<const GridSlamProcessor::TNode*, GridSlamProcessor::TNode*> TNodeMultimap;