GMapping代码解析[通俗易懂]

GMapping代码解析[通俗易懂]前言:   最近正好用到GMapping,需要改代码,但看过也总是在忘,那干脆写篇博客记录下来同时也可以帮助想要了解GMapping代码的同学。   代码的入口依然是main函数,但GMapping代码中由很多是没有用的,所以并不需要挨个看,可以说代码的作者代码能力挺强但代码风格却是不敢恭维。这里就不带大家挨个文件度代码,只是对几个主要的函数进行介绍。   …

大家好,又见面了,我是你们的朋友全栈君。

前言:

      最近正好 用到GMapping,需要改代码, 但看过也总是在忘,那干脆写篇博客记录 下来同时也可以帮助想要了解GMapping代码的同学。

      代码的入口依然是main函数,但GMapping代码中由很多是没有用的,所以并 不需要挨个看,可以说代码的作者代码能力挺强但代码风格却是不敢恭维。这里就 不带大家挨个文件度代码,只是对几个主要的 函数进行介绍。

      在看代码前,读者最好选择一个IDE来看代码,因为会涉及大量的跳转,如果只是手动去找的话就太累了。yi

main.cpp

int
main(int argc, char** argv)
{
  ros::init(argc, argv, "slam_gmapping");

  SlamGMapping gn;
  gn.startLiveSlam();
  ros::spin();

  return(0);
}

      代码的入口 ,主要作用就是生成了一个类对象,类对象调用成员函数startLiveSlam()。说明一下ros里面基础知识这里就不过多介绍,读者自学一下ros就行。

startLiveSlam()

/*订阅一些主题 发布一些主题*/
void SlamGMapping::startLiveSlam()
{
    entropy_publisher_ = private_nh_.advertise<std_msgs::Float64>("entropy", 1, true);
    sst_ = node_.advertise<nav_msgs::OccupancyGrid>("map", 1, true);
    sstm_ = node_.advertise<nav_msgs::MapMetaData>("map_metadata", 1, true);
    ss_ = node_.advertiseService("dynamic_map", &SlamGMapping::mapCallback, this);

    //订阅激光数据 同时和odom_frame之间的转换同步
    scan_filter_sub_ = new message_filters::Subscriber<sensor_msgs::LaserScan>(node_, "scan", 5);
    scan_filter_ = new tf::MessageFilter<sensor_msgs::LaserScan>(*scan_filter_sub_, tf_, odom_frame_, 5);
    scan_filter_->registerCallback(boost::bind(&SlamGMapping::laserCallback, this, _1));

    std::cout <<"Subscribe LaserScan & odom!!!"<<std::endl;
 

    /*发布转换关系的线程*/
    transform_thread_ = new boost::thread(boost::bind(&SlamGMapping::publishLoop, this, transform_publish_period_));
}

       这个函数的功能就是发布发布四个消息,订阅一个话题,会涉及boost库的一些知识,网上都有搜一下就行。下一步进行回调函数laserCallback中。

laserCallback()

void SlamGMapping::laserCallback(const sensor_msgs::LaserScan::ConstPtr& scan)
{

    laser_count_++;
    if ((laser_count_ % throttle_scans_) != 0)//throttle_scans_实现降频,如果激光频率较高而
        return;                              //处理器计算能力有限,可以降低处理激光数据的频率

    static ros::Time last_map_update(0,0);

    // We can't initialize the mapper until we've got the first scan
    if(!got_first_scan_)
    {
        if(!initMapper(*scan))//第一帧激光数据时执行初始化
            return;
        got_first_scan_ = true;
    }

    GMapping::OrientedPoint odom_pose;
    if(addScan(*scan, odom_pose))//初始化完后,再有激光数据时执行addScan函数
    {
        ROS_DEBUG("scan processed");

        GMapping::OrientedPoint mpose = gsp_->getParticles()[gsp_->getBestParticleIndex()].pose;
        ROS_DEBUG("new best pose: %.3f %.3f %.3f", mpose.x, mpose.y, mpose.theta);
        ROS_DEBUG("odom pose: %.3f %.3f %.3f", odom_pose.x, odom_pose.y, odom_pose.theta);
        ROS_DEBUG("correction: %.3f %.3f %.3f", mpose.x - odom_pose.x, mpose.y - odom_pose.y, mpose.theta - odom_pose.theta);

        tf::Transform laser_to_map = tf::Transform(tf::createQuaternionFromRPY(0, 0, mpose.theta), tf::Vector3(mpose.x, mpose.y, 0.0)).inverse();
        tf::Transform odom_to_laser = tf::Transform(tf::createQuaternionFromRPY(0, 0, odom_pose.theta), tf::Vector3(odom_pose.x, odom_pose.y, 0.0));

        map_to_odom_mutex_.lock();
        map_to_odom_ = (odom_to_laser * laser_to_map).inverse();
        map_to_odom_mutex_.unlock();

        /*如果没有地图那肯定需要直接更新,如果有地图了则需要到时间了,才更新地图了*/
        if(!got_map_ || (scan->header.stamp - last_map_update) > map_update_interval_)
        {
            /*多久更新一次地图*/
            updateMap(*scan);
            last_map_update = scan->header.stamp;
            ROS_DEBUG("Updated the map");
        }
    }
    else
        ROS_DEBUG("cannot process scan");
}

未完待续

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/148589.html原文链接:https://javaforall.net

(0)
上一篇 2022年6月16日 上午7:00
下一篇 2022年6月16日 上午7:00


相关推荐

  • 现在90,00后经常上哪些网站?喜欢看啥网站?

    现在90,00后经常上哪些网站?喜欢看啥网站?现在90,00后经常上哪些网站?喜欢看啥网站?13页PPT:揭秘90后最全研究报告!|网站运营http://www.iyunying.org/seo/sjfx/61716.html90后男生明显比90后女生更愿意在天猫上购买服装和鞋。在天猫上,男装的购买偏好为49%,女装为35%;男鞋的购物偏好为40%,女鞋为31%。90后最渴望的事情是旅行,其中旅行愿望最为迫切的是工作中的90后,达50…

    2022年7月25日
    10
  • 分治法-汉诺塔问题

    分治法-汉诺塔问题

    2021年12月6日
    44
  • 何为文件句柄??_窗口句柄是什么意思

    何为文件句柄??_窗口句柄是什么意思一、百度百科解释:在文件I/O中,要从一个文件读取数据,应用程序首先要调用操作系统函数并传送文件名,并选一个到该文件的路径来打开文件。该函数取回一个顺序号,即文件句柄(filehandle),该文件句柄对于打开的文件是唯一的识别依据。要从文件中读取一块数据,应用程序需要调用函数ReadFile,并将文件句柄在内存中的地址和要拷贝的字节数传送给操作系统。当完成任务后,再通过调用系统函数来关闭该…

    2022年10月9日
    2
  • 【Java设计模式】——单例模式

    【Java设计模式】——单例模式单例模式是 Java 中最简单的设计模式之一 属于创建型模式 它提供一种创建对象的最佳方式 单例模式顾名思义就是单一的实例 涉及到一个单一的类 该类负责创建自己的对象 同时确保只有一个对象被创建 并且提供一种可以访问这个对象的方式 可以直接访问 不需要实例化该类的对象 单例模式的特点 单例类只能有一个实例这个实例必须由单例类自己创建单例类需要提供给外界访问这个实例

    2026年3月16日
    2
  • 龙族幻想购买限制_龙族幻想宽限一日

    龙族幻想购买限制_龙族幻想宽限一日 龙族系列,可设每月自动无最小支付/1. http://www.apachemails.com/pages/index.php?refid=wy13062232. http://www.bondjamesbond.net/pages/index.php?refid=wy1306223. http://www.cashpointclicks.com/pages/index.php?r

    2022年10月8日
    4
  • linux环境jstack命令详解,Linux jstack命令详解

    linux环境jstack命令详解,Linux jstack命令详解jstack 用于打印出给定的 java 进程 ID 或 corefile 或远程调试服务的 Java 堆栈信息 如果是在 64 位机器上 需要指定选项 J d64 Windows 的 jstack 使用方式只支持以下的这种方式 jstack l pid 如果 java 程序崩溃生成 core 文件 jstack 工具可以用来获得 core 文件的 javastack 和 nativestack 的信息 从而可以轻松地知道 java 程

    2026年3月18日
    2

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号