添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
相关文章推荐
犯傻的小笼包  ·  调试System.IO.FileNotFou ...·  11 月前    · 
无聊的松鼠  ·  C++ List(#include) ...·  1 年前    · 
有胆有识的大熊猫  ·  Android ...·  1 年前    · 

激光SLAM简单入门(1)-matlab读取bag文件并保存为mat文件

最近在一篇公众号发现了一篇激光SLAM的入门文章,作者提供了源码,下载下来跑了一下,效果还不错。之前一直在用激光雷达建图,但一直没能对激光雷达SLAM基础理论有深入的研究,因此萌生了以该代码为基础,系统整理激光雷达SLAM步骤的想法。原文见:

本系列主要内容是理解激光SLAM的过程,在原文的基础上进行了改进和升级,并增加了的细节内容,同时也加入了部分自己的理解。

作者在文章中提供了所有的代码,把所有的代码复制到同一文件夹下,运行main.m文件即可,我也将代码整理到我的github,下载地址为:

第一部分记录matlab读取bag文件并将需要的数据保存成mat文件的过程。写这部分的原因是网络上关于matlab读取bag文件的内容较少,在提取数据的过程中浪费了较多时间。主要步骤包括下载bag文件,在ros环境下解压缩,解压缩后bag文件的数据提取和保存(matlab)。

1 下载bag文件

谷歌的Cartographer算法中提供的数据集,文件下载地址:

我下载了 b2-2014-12-12-14-41-29.bag ,文件大小为46MB。

ps:下载后直接在matlab下用rosbag函数读取,会提示如下错误:

原因:matlab只能读取未压缩的文件,直接下载的bag文件是压缩后的文件,因此首先需要解压缩。

2 在ros环境中解压缩bag文件

在ros环境(ubuntu16.04+ros kinetic)下对原始的bag文件进行解压缩,得到解压后的bag文件。

rosbag decompress b2-2014-12-12-14-41-29.bag

解压后文件大小为230M:

3 在matlab下对bag文件中的数据进行提取和保存

matlab提供了ros相关的函数来提取数据,但是一次对所有的数据进行处理,会发生内存不足的问题。比如我用如下的代码读取bag文件:

bag = rosbag('b2-2014-12-12-14-41-29.bag');%读取所有数据
%读取水平雷达topic 数据
laser = select(bag, 'Time', ...
            [bag.StartTime bag.EndTime], 'Topic', '/horizontal_laser_2d');
x = readMessages(laser);

matlab报错(内存不足):

Error in robotics.ros.BagSelection/readMessages (line 194)
            msgs = obj.deserializeMessages(obj.MessageList, rows);
Error in LoadMeasurements (line 47)
    msgs = readMessages(bag);

因此,采用循环的方式逐一读取数据,代码如下:

clear;clc;
bag = rosbag('b2-2014-12-12-14-41-29.bag');%读取所有数据
%读取水平雷达topic 数据
 laser = select(bag, 'Time', ...
            [bag.StartTime bag.EndTime], 'Topic', '/horizontal_laser_2d');
%% 从文件中查找数据的大小 
N = laser.NumMessages;%雷达数据条数
x = readMessages(laser,1);
[M,~] = size(x{1,1}.Ranges);
times = zeros(N,1);%时间参数
ranges = zeros(N,M);%距离参数
%% 循环读取数据 :整体读取时会出现内存不足的情况
for i=1:N
    temp = readMessages(laser,i);
    times(i) = temp{1,1}.Header.Stamp.Sec;%时间
    ranges_temp = temp{1,1}.Ranges;%雷达测量(1079维数据)
    for j = 1:M %不知道如何整体读取,所以加了循环
        laser_echo = ranges_temp(j,1).Echoes;
        [xx,yy] = size(laser_echo);
        if xx*yy<1 %当laser_echo为空时,跳出当前循环
            continue
        ranges(i,j) = laser_echo(1);%雷达测量的距离数据
    %显示进度