zoukankan      html  css  js  c++  java
  • Gmapping之gridslamprocessor详解

    从很多博客上看了关于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;
    

      

      

  • 相关阅读:
    hdu 3336 Count the string KMP+DP优化
    Codeforces Round #345 (Div. 1) A. Watchmen 模拟加点
    Codeforces Round #345 (Div. 1) B. Image Preview
    大数据时代下EDM邮件营销的变革
    如何选择EDM电子邮件服务提供商
    一般邮件营销平台可以获取的三个参数
    EDM邮件营销真的落伍了吗?
    EDM概念之A/B分类测试法
    EDM营销技巧之如何进行用户唤醒
    如何优化电子邮件营销的效果
  • 原文地址:https://www.cnblogs.com/cwyblogs/p/8342329.html
Copyright © 2011-2022 走看看