这篇文章做一个Fastlio_localization(以下简称fastlio_lc)的跑通记录文档。
步骤包括:源码获取、数据集获取、环境配置、源码编译、定位地图制作、基于数据集的脚本修改、源码运行、定位结果保存txt 等步骤
1.源码获取
1.直接进入github上下载,地址为:
https://github.com/HViktorTsoi/FAST_LIO_LOCALIZATION
2.直接在Linux的终端运行
git clone https://github.com/HViktorTsoi/FAST_LIO_LOCALIZATION
2.数据集获取
复现这篇论文的主要目的是通过fastlio_lc做Apollo_daoxianglake(Apollo官方数据集——稻香湖场景)的定位实验,但是在复现Apollo_daoxianglake之前肯定都会做一下fastlio_lc作者给出的官方数据集,其地址为:
百度网盘 请输入提取码,密码为:ne8d
与之配套的地图地址为:
百度网盘 请输入提取码,密码为:kw6f
3.环境配置
其环境配置是要求python2.7版本、pcl库的话我看有些地方写需要pcl1.8,但是我安装的pcl1.7.2是同样能跑通的、以及rosnumpy、open3d。注意这里的rosnumpy和open3d都需要在python2.7的环境下进行安装,因为有的人linux下安装了多个python版本,有2.7、3.5、3.6等版本,如果你在python3.6下安装了open3d,你在运行代码的时候一定会报错找不到open3d模块的,这里一定要注意,一定要在python2.7环境下安装。
本人在这里浪费了不少时间解决open3d库安装问题,在python2.7环境下安装一些库会出现很多问题,因为python2.7太旧了,所以会有一系列连带问题,相信大家也都经历过。因为问题实在太多,所以我这里不一一列举了,大家这里环境配置如果哪儿出现了问题,可以在评论区给我留言,我都会给大家一一回复。
4.源码编译
编译的话正常来说直接在工作空间下面catkin_make就可以了,但是总会出现一些乱七八糟的问题
下面我总结出一些出现比较多的问题以及解决办法,如果大家遇到下面没有罗列出来的问题也可以在评论区给我留言。
问题一:
大家先去FAST_LIO_LOCALIZATION-main/include/ikd-Tree这个文件夹中有没有ikd_Tree.cpp和ikd_Tree.h文件,如果没有的话编译就会出现下面这个问题
这个时候就直接去这个网站中hku-mars/ikd-Tree at 3d115a41377243420a74fc15dd7cf7ef337730df (github.com)
把这三个文件(其实只需要.cpp和.h文件)下载下来后复制粘贴进FAST_LIO_LOCALIZATION-main/include/ikd-Tree文件夹中,重新编译就不会报错了。
问题二:
报错没有fast_lio/Pose6D.h,这个时候只需要进入FAST_LIO_LOCALIZATION-main/include/common_lib.h文件中,用ctrl+f找到fast_lio,然后把这个文件中的所有fast_lio都改为fast_lio_localization,重新编译就没问题了。
5.地图制作
因为我跑的是官方数据集和Apollo数据集,官方数据集给出的地图和与之配套的bag包在第一步已经给出了,而Apollo数据集的地图制作我是直接使用的LIO-SAM来提取每帧的特征点来做的,每帧的位姿直接使用bag包中的GPS真值来给的,然后把每个关键帧的所有特征点拼在一起就可以了。最后做出来的地图如下所示,效果很好。(但是这么做有一个局限性就是,数据集中每个激光雷达帧都需要有一个对应的GPS帧,如果不是这样的话,就得用SLAM算法或者GPS插值来做了。)
7.基于数据集的脚本参数修改
先说说global_localization.py中main函数下的几个重要参数:
MAP_VOXEL_SIZE:地图降采样size
SCAN_VOXEL_SIZE:当前帧点云采样size
FREQ_LOCALIZATION:定位频率
LOCALIZATION_TH:点云配准得分,得分越高配准越准确
FOV:数据集中激光雷达视场角弧度
FOV_FAR:数据集中激光雷达能够探测的最大深度,通过这个参数来改变局部地图的size
首先来说官方数据集。如果是跑官方数据集的话就直接roslaunch这个localization_avia.launch就可以了,不需要修改python脚本中的参数
如果是Apollo数据集。里面对应的激光雷达为velodyne64线,探测最大深度为100,但是我看了一下大概每帧百分之九十五以上的点云都在80m以内,所以我把FOV_FAR改为了80。然后又因为vld64线激光雷达为环形激光雷达,视场角为360°,所以将FOV改为3.1416。然后LOCALIZATION_TH这个参数我改为了0.9而不是0.95,因为有时候地图中或当前帧中有动态或半动态物体干扰,导致某些帧的ICP配准精度达不到0.95但是并没有跑飞(为什么我这里能确定没有跑飞,我后面会说),这个时候就会有误导,所以降低一点并不会太影响精度。FREQ_LOCALIZATION这个参数就是按照某个频率来进行定位输出,我没有用到这个参数。因为我是要通过fastlio_lc这个模型与自己做的模型来通过evo工具来进行实验对比,我需要得到的是每一帧点云对应的位姿,而不是每隔一段时间的定位位姿,所以我把这里的代码逻辑进行了修改,把thread.start_new_thread(thread_localization, ())这行代码直接进行了注释,然后把global_localization()函数放进了点云回调函数中。
MAP_VOXEL_SIZE和SCAN_VOXEL_SIZE这个基于自己的地图密度和点云密度自己改就行,我个人推荐这两个值最好在0.1到0.5之间。
回到上面,我为什么说我能确定某些配准分数差的帧没有跑飞,是因为我在源代码中写了一个GPS回调,并在rviz中输出其path,然后与其定位的输出点进行比较,如果二者基本上能重合或者离得不远,就说明没有跑飞。
6.源码运行
运行之前先source一下,然后:
roslaunch fast_lio_localization localization_avia.launch map:=/map_path
这里的map_path换成你们自己的地图路径就可以了。
然后等待几秒钟(具体等待时间看你的地图大小,地图越大等待时间越长)后rviz中有地图显示出来以后,就像这样:
出现以后就可以直接rosbag play自己的bag包了,运行零点几秒以后暂停就可以把当前帧对应点的初始位姿通过另外一个终端输入了
rosrun fast_lio_localization publish_initial_pose.py x y z yaw pitch roll
这里的x y z yaw pitch roll对应初始位姿的坐标和欧拉角,注意欧拉角顺序是yaw pitch和roll,输入完以后就取消bag包的暂停,开始运行。运行结果如下所示:
绿色点云代表局部地图点云、黄色点云代表当前帧点云、红色点云代表全部地图。
大家可以在我的主页里面看到一个视频:QQ录屏20231213120537
这个视频就是我录制的一个运行fastlio_lc的视频,大概一分钟。
7.结果保存
最后定位结果的保存,可以直接改transform_fusion.py的脚本,在transform_fusion()函数中修改如下:
就能保存位置和位姿了。因为源代码逻辑是每隔两秒进行一次全局定位的结果输出,而我所需要的结果是每一帧点云都要进行一次全局定位的结果输出,修改结果输出的逻辑也很简单,只需要把transform_fusion()函数放进map_to_odom的回调函数中就可以了。
总结:这篇文章做了一个fastlio_lc的一个复现,不仅仅使用官方数据集复现,还使用了Apollo数据集进行复现,包括源码获取、编译、地图制作、运行定位、定位结果的保存等。如果有哪一步不会,或者遇到关于该代码运行的问题可以在评论区进行留言讨论,我会尽量帮助大家解决。