最近在学习SLAM和ROS,首先接触到的是github上的开源项目BLAM,是berkely的一位小哥所写,油管上有相关的视频。这篇教程面向于SLAM和ROS的初学者,如果有问题还希望各位大神进行指正。


先贴一张github上附带的效果图
  


系统概述

BLAM使用PointCloudXYZ类型点云数据作为输入,在视频里使用一个velodyneVLP16激光雷达作为传感器,逐步的绘制出整个点云地图。
BLAM系统框架很简单:

Created with Raphaël 2.2.0 PCL点云数据处理 定位 非线性优化 回环? 调整地图 建立地图 yes no

代码主要分为下列几个大部分
- point_cloud_filter :对输入的点云数据进行处理,得到过滤后的点云数据
- point_cloud_odometry :通过GICP算法计算两帧点云数据的位姿变换(初步计算)
- point_cloud_localization :通过初步计算的位姿变换来获取当前帧对应的地图中最近临点,再次执行GICP得到精确的位姿变换(第二次计算)
- laser_loop_closure :对当前帧的点云数据与历史点云数据对比判断回环是否发生,发布位姿数据
- point_cloud_mapper :构建点云地图,发布地图数据


BLAM的整个点云数据处理从 blam_slam.cc起始

#include <ros/ros.h>
#include <blam_slam/BlamSlam.h>int main(int argc, char** argv) {ros::init(argc, argv, "blam_slam");  //初始化ROS节点并命名ros::NodeHandle n("~");  //定义私有命名空间  详情请看另一篇博文BlamSlam bs;if (!bs.Initialize(n, false /* online processing */)) { //  调用Initialize函数,采用离线模式ROS_ERROR("%s: Failed to initialize BLAM SLAM.",ros::this_node::getName().c_str());return EXIT_FAILURE;}ros::spin();   return EXIT_SUCCESS;
}

这里定义了句柄n并执行了初始化函数,所以我们进入到BlamSlam::Initialize里

bool BlamSlam::Initialize(const ros::NodeHandle& n, bool from_log) {name_ = ros::names::append(n.getNamespace(), "BlamSlam");if (!filter_.Initialize(n)) {   //内部主要工作为提取.yaml文件参数  ROS_ERROR("%s: Failed to initialize point cloud filter.", name_.c_str());return false;}if (!odometry_.Initialize(n)) {    //参数为NodeHandle 保证在同一个命名空间ROS_ERROR("%s: Failed to initialize point cloud odometry.", name_.c_str());return false;}if (!loop_closure_.Initialize(n)) {ROS_ERROR("%s: Failed to initialize laser loop closure.", name_.c_str());return false;}if (!localization_.Initialize(n)) {ROS_ERROR("%s: Failed to initialize localization.", name_.c_str());return false;}if (!mapper_.Initialize(n)) {ROS_ERROR("%s: Failed to initialize mapper.", name_.c_str());return false;}if (!LoadParameters(n)) {ROS_ERROR("%s: Failed to load parameters.", name_.c_str());return false;}if (!RegisterCallbacks(n, from_log)) {ROS_ERROR("%s: Failed to register callbacks.", name_.c_str());return false;}return true;
}

这里各个模块的Initialize()函数主要作用是提取.yaml文件里的参数。不太重要,有兴趣的可以自行看一下
看到最后一个**RegisterCallbacks(n, from_log)**是初始化函数的重点,具体内容是

bool BlamSlam::RegisterCallbacks(const ros::NodeHandle& n, bool from_log) {// Create a local nodehandle to manage callback subscriptions.ros::NodeHandle nl(n);  //以n为父节点visualization_update_timer_ = nl.createTimer(visualization_update_rate_, &BlamSlam::VisualizationTimerCallback, this);//创建一个timer定时调用VisualizationTimerCallback,其内容是发布**地图**话题if (from_log)   //这里是false 所以进入onlinereturn RegisterLogCallbacks(n);elsereturn RegisterOnlineCallbacks(n);  //进入这个}

下面我们继续进入**RegisterOnlineCallbacks(n)**函数

bool BlamSlam::RegisterOnlineCallbacks(const ros::NodeHandle& n) {ROS_INFO("%s: Registering online callbacks.", name_.c_str());// Create a local nodehandle to manage callback subscriptions.ros::NodeHandle nl(n);estimate_update_timer_ = nl.createTimer(estimate_update_rate_, &BlamSlam::EstimateTimerCallback, this); //定时器pcld_sub_ = nl.subscribe("pcld", 100, &BlamSlam::PointCloudCallback, this);//消息订阅return CreatePublishers(n);
}

首先先看到订阅者,订阅了一个名为pcld的相对话题名称,在launch文件里这个话题名被重映射到了/PointCloudXYZ,所以这里订阅的是PointCloudXYZ的点云数据

另外是一个以**estimate_update_rate_为调用间隔的EstimateTimerCallback()**函数,我们继续进入

void BlamSlam::EstimateTimerCallback(const ros::TimerEvent& ev) {// Sort all messages accumulated since the last estimate update.synchronizer_.SortMessages();                         //对点云数据根据时间排序,并得到index数组// Iterate through sensor messages, passing to update functions.MeasurementSynchronizer::sensor_type type;unsigned int index = 0;while (synchronizer_.GetNextMessage(&type, &index)) {   //找到下一个点云数据的indexswitch(type) {// Point cloud messages.case MeasurementSynchronizer::PCL_POINTCLOUD: {    //根据类型进入这个分支const MeasurementSynchronizer::Message<PointCloud>::ConstPtr& m =synchronizer_.GetPCLPointCloudMessage(index);  //通过index得到pointcloud数据ProcessPointCloudMessage(m->msg); //执行数据处理 *********break;}// Unhandled sensor messages.default: {ROS_WARN("%s: Unhandled measurement type (%s).", name_.c_str(),MeasurementSynchronizer::GetTypeString(type).c_str());break;}}}// Remove processed messages from the synchronizer.synchronizer_.ClearMessages();
}

这个函数主要工作是,根据timestamp对暂存的点云数据进行排序,根据排序结果依次对点云数据进行处理(调用**ProcessPointCloudMessage(m->msg)**函数)

所有数据处理工作都在**ProcessPointCloudMessage(m->msg)**函数中完成,这一章主要介绍了整个程序的的入口,下一章里会介绍点云处理过程


                                        转载请注明出处欢迎讨论交流

开源激光SLAM项目BLAM-----1相关推荐

  1. 开源激光SLAM项目BLAM-----2

    接上一章节提到的**ProcessPointCloudMessage(m->msg)**函数,它传入一个const PointCloud::ConstPtr& 类型,即点云常指针的引用, ...

  2. 开源3D激光SLAM项目BLAM

    最近在学习SLAM和ROS,首先接触到的是github上的开源项目BLAM,是berkely的一位小哥所写,油管上有相关的视频.这篇教程面向于SLAM和ROS的初学者,如果有问题还希望各位大神进行指正 ...

  3. 使用开源激光SLAM方案LIO-SAM运行KITTI数据集,如有用,请评论雷锋

    第一次写博客~ LIOSAM作为优秀的激光slam方案,当然想尝试着运行更多数据啦,然而没有发现类似的方法分享到底如何实现,在B站看到有伙伴发布了测试视频,但是仍然没有写出方法.所以我跑通了之后记录一 ...

  4. 基于LOAM框架的激光SLAM开源程序集合

    一.前言 LOAM, 即Lidar Odometry and Mapping,是 Ji Zhang 博士于2014年提出的使用激光雷达完成定位与三维建图的算法.其算法流程如下: LOAM算法中主要包含 ...

  5. 【激光SLAM】 01 cartographer环境建立以及建图测试(详细级)

    [激光SLAM]cartographer环境建立以及建图测试(详细级) cartographer Launch the 2D backpack demo. Download the 3D backpa ...

  6. 激光SLAM理论与实践(一)--激光SLAM简要介绍

    疫情原因一直在家,所以把之前学习的某蓝学院的激光SLAM的教程做一个学习笔记记录一下.话不多说,直接开始! 第一章主要是是激光SLAM的基本脉络的简介,综述类的介绍,主要分为以下四部分,讲了激光SLA ...

  7. ROS2_Foxy学习10——多机激光SLAM准备篇

    ROS2_Foxy学习10--多机激光SLAM准备篇 1 安装Ubuntu20.04 mate 2 安装ROS noetic 3 安装cartographer 4 详细配置cartographer 5 ...

  8. 激光SLAM技术总结(1)激光SLAM对比视觉V-SLAM

    目录 1. SLAM 2. 激光SLAM 3. 视觉SLAM地图构建 4. 激光SLAM  VS V-SLAM 5. 小结 1. SLAM SLAM(同步定位与地图构建),是指运动物体根据传感器的信息 ...

  9. 3D激光开源项目——BLAM安装使用过程的一些问题

    最近由于在做3D激光slam的相关工作,在网上看见 BLAM 的效果不错,就下载了相关的代码跑了一下,在编译安装过程中遇到了一些问题,在这里记录一下,供有需要的同学看一下. 具体的安装过程这里就不在赘 ...

最新文章

  1. IntelliJ IDEA 12详细开发教程(四) 搭建Android应用开发环境与Android项目创建
  2. java 白皮书_java第三天学习内容回顾——java白皮书第四章
  3. 快速排序及优化(Java实现)
  4. Linux学习之六-Yum命令的使用
  5. [vue] vue变量名如果以_、$开头的属性会发生什么问题?怎么访问到它们的值?
  6. 计算机视觉(一)——深度学习
  7. 处理quartz 异常 Couldn‘t retrieve trigger: No record found for selection of Trigger with key:
  8. msf-Msfvenonm生成后门木马
  9. 基于91助手实现80/54坐标转换到2000大地坐标的七参数计算
  10. 尝试导入导出Alembic动画模型(.abc)
  11. 探秘广场舞:中老年市场绝佳切口?
  12. 为什么大部分人,会对南北经济“差距”产生误解?
  13. Godaddy怎么解析域名指向自己的服务器?
  14. 2019年冬 --11月24周总结
  15. 交流电中为什么要用相量法?
  16. 学习Java第十九天(一):1、Java中的网络编程
  17. 经典   bgp 路由黑洞
  18. 制作小地图MiniMap小结
  19. iOS二维码生成与识别
  20. Hive的Parquet存储与LZO压缩

热门文章

  1. Spring Data ElasticSearch增删改查
  2. x265代码阅读:码率控制(一)
  3. Notepad++行首行尾批量添加字符
  4. 利用茉莉机器人接口开发一个简单的安卓机器人app
  5. numeric_limits的运用
  6. quadro 2000专业显卡 win7计算机体验指数5.9,英伟达全新Quadro K2200专业级显卡评测...
  7. JAVA消息(第一篇)JMS 很重要!!!!包教包会!!不闹!!!下一篇-AMQP(wire-level protocol)
  8. 2021Java面经:最便宜java培训机构
  9. 用C++开发STM32程序
  10. 数据结构--图的存储结构