开源激光SLAM项目BLAM-----1
最近在学习SLAM和ROS,首先接触到的是github上的开源项目BLAM,是berkely的一位小哥所写,油管上有相关的视频。这篇教程面向于SLAM和ROS的初学者,如果有问题还希望各位大神进行指正。
先贴一张github上附带的效果图
系统概述
BLAM使用PointCloudXYZ类型点云数据作为输入,在视频里使用一个velodyneVLP16激光雷达作为传感器,逐步的绘制出整个点云地图。
BLAM系统框架很简单:
代码主要分为下列几个大部分
- 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相关推荐
- 开源激光SLAM项目BLAM-----2
接上一章节提到的**ProcessPointCloudMessage(m->msg)**函数,它传入一个const PointCloud::ConstPtr& 类型,即点云常指针的引用, ...
- 开源3D激光SLAM项目BLAM
最近在学习SLAM和ROS,首先接触到的是github上的开源项目BLAM,是berkely的一位小哥所写,油管上有相关的视频.这篇教程面向于SLAM和ROS的初学者,如果有问题还希望各位大神进行指正 ...
- 使用开源激光SLAM方案LIO-SAM运行KITTI数据集,如有用,请评论雷锋
第一次写博客~ LIOSAM作为优秀的激光slam方案,当然想尝试着运行更多数据啦,然而没有发现类似的方法分享到底如何实现,在B站看到有伙伴发布了测试视频,但是仍然没有写出方法.所以我跑通了之后记录一 ...
- 基于LOAM框架的激光SLAM开源程序集合
一.前言 LOAM, 即Lidar Odometry and Mapping,是 Ji Zhang 博士于2014年提出的使用激光雷达完成定位与三维建图的算法.其算法流程如下: LOAM算法中主要包含 ...
- 【激光SLAM】 01 cartographer环境建立以及建图测试(详细级)
[激光SLAM]cartographer环境建立以及建图测试(详细级) cartographer Launch the 2D backpack demo. Download the 3D backpa ...
- 激光SLAM理论与实践(一)--激光SLAM简要介绍
疫情原因一直在家,所以把之前学习的某蓝学院的激光SLAM的教程做一个学习笔记记录一下.话不多说,直接开始! 第一章主要是是激光SLAM的基本脉络的简介,综述类的介绍,主要分为以下四部分,讲了激光SLA ...
- ROS2_Foxy学习10——多机激光SLAM准备篇
ROS2_Foxy学习10--多机激光SLAM准备篇 1 安装Ubuntu20.04 mate 2 安装ROS noetic 3 安装cartographer 4 详细配置cartographer 5 ...
- 激光SLAM技术总结(1)激光SLAM对比视觉V-SLAM
目录 1. SLAM 2. 激光SLAM 3. 视觉SLAM地图构建 4. 激光SLAM VS V-SLAM 5. 小结 1. SLAM SLAM(同步定位与地图构建),是指运动物体根据传感器的信息 ...
- 3D激光开源项目——BLAM安装使用过程的一些问题
最近由于在做3D激光slam的相关工作,在网上看见 BLAM 的效果不错,就下载了相关的代码跑了一下,在编译安装过程中遇到了一些问题,在这里记录一下,供有需要的同学看一下. 具体的安装过程这里就不在赘 ...
最新文章
- IntelliJ IDEA 12详细开发教程(四) 搭建Android应用开发环境与Android项目创建
- java 白皮书_java第三天学习内容回顾——java白皮书第四章
- 快速排序及优化(Java实现)
- Linux学习之六-Yum命令的使用
- [vue] vue变量名如果以_、$开头的属性会发生什么问题?怎么访问到它们的值?
- 计算机视觉(一)——深度学习
- 处理quartz 异常 Couldn‘t retrieve trigger: No record found for selection of Trigger with key:
- msf-Msfvenonm生成后门木马
- 基于91助手实现80/54坐标转换到2000大地坐标的七参数计算
- 尝试导入导出Alembic动画模型(.abc)
- 探秘广场舞:中老年市场绝佳切口?
- 为什么大部分人,会对南北经济“差距”产生误解?
- Godaddy怎么解析域名指向自己的服务器?
- 2019年冬 --11月24周总结
- 交流电中为什么要用相量法?
- 学习Java第十九天(一):1、Java中的网络编程
- 经典 bgp 路由黑洞
- 制作小地图MiniMap小结
- iOS二维码生成与识别
- Hive的Parquet存储与LZO压缩
热门文章
- Spring Data ElasticSearch增删改查
- x265代码阅读:码率控制(一)
- Notepad++行首行尾批量添加字符
- 利用茉莉机器人接口开发一个简单的安卓机器人app
- numeric_limits的运用
- quadro 2000专业显卡 win7计算机体验指数5.9,英伟达全新Quadro K2200专业级显卡评测...
- JAVA消息(第一篇)JMS 很重要!!!!包教包会!!不闹!!!下一篇-AMQP(wire-level protocol)
- 2021Java面经:最便宜java培训机构
- 用C++开发STM32程序
- 数据结构--图的存储结构