FAST-LIO笔记

news2025/5/12 17:36:24

1.FAST-LIO

FAST-LIO 是一个计算效率高、鲁棒性强的激光-惯性里程计系统。该系统通过紧耦合的迭代扩展卡尔曼滤波器(IEKF)将激光雷达特征点与IMU数据进行融合,使其在快速运动、噪声较大或环境复杂、存在退化的情况下仍能实现稳定的导航。

1.1问题

1)LiDAR测量中提取的特征点通常是环境中的几何结构(如边缘和平面)。当无人机在特征不明显的复杂环境中运行时,LiDAR方案容易出现退化问题。该问题在视场角(FoV)较小的LiDAR中尤为明显; (特征稀缺的环境中或使用小FoV的LiDAR时,性能容易退化

2)由于在扫描方向上具有高分辨率,一帧LiDAR扫描通常包含大量特征点(例如几千个)。尽管这些特征点在退化场景中无法稳定估计位姿,但若将其与IMU测量进行紧耦合融合,将导致巨大的计算负担,而这对于无人机的机载计算机来说是不可承受的;(嵌入式平台对算力有要求

3)由于LiDAR使用少数激光发射/接收对逐点扫描,因此每个激光点的采样时间不同,这种时间差造成的运动畸变会显著降低点云配准的准确性。此外,无人机螺旋桨和电机的持续旋转还会对IMU测量引入显著噪声。(点云去畸变以及外部因素影响IMU测量

1.2解决方法

为使LiDAR导航适用于小型移动机器人(如无人机),提出了FAST-LIO——一个计算高效且鲁棒的LiDAR-IMU里程计算法。主要贡献如下:

1)为应对高速运动、有噪声或复杂环境中发生退化的情况,我们采用紧耦合的迭代卡尔曼滤波器,将LiDAR特征点与IMU测量数据融合。我们提出了正式的后向传播方法来补偿运动畸变

2)为减少大量LiDAR特征点带来的计算负担,我们提出了一种新的卡尔曼增益计算公式,并证明其与传统公式等价。新公式的计算复杂度取决于状态维度,而不是测量维度

3)我们将这些公式实现为一个快速且鲁棒的LiDAR-IMU里程计算软件包,系统可以运行在小型四旋翼的机载计算机上;

4)我们在多种室内和室外环境下,以及实际无人机飞行测试中,验证了系统在快速运动或强烈振动噪声条件下的鲁棒性。

1.3系统框架

  • LiDAR原始数据首先输入到特征提取模块,提取出平面特征和边缘特征。
  • 提取出的特征与IMU测量数据一同输入到状态估计模块中,以10Hz或50Hz的频率进行状态估计。IMU数据前向传播(粗略地位姿估计),后向传播(运动补偿去畸变
  • 估计得到的位姿用于将当前帧的特征点配准到全局坐标系中,并与当前已构建的特征点地图进行融合。更新后的地图将用于下一步中新点云的配准操作。

1.4系统描述        

关于流行的解释

流形(Manifold )是局部具有欧几里得空间性质的空间,是欧几里得空间中的曲线、曲面等概念的推广。参考文章中关于二维圆和三维球的例子解释的很好,二维空间中的圆就是一个一维流形,三维空间中的球面是一个二维流形

参考:https://www.cnblogs.com/icmzn/p/11082509.html

IMU运动模型

本质上是对P、V、Q的求导

离散模型

需要估计的状态量是个18维的量,包括位置、速度、姿态、偏置和加速度g .

数据预处理

由于原始LiDAR点是以非常高的频率(例如200kHz)采样的,因此通常无法在每接收到一个新点时立即处理它们。更实际的方法是将这些点积累一段时间,然后一次性处理它们。

在FAST-LIO中,最小的积累间隔设置为20毫秒,从而实现高达50Hz的全状态估计(即里程计输出)和地图更新。这种积累后的点集被称为一个扫描(scan),并且处理该扫描的时间为 tk。从原始点云中,我们提取具有较高局部平滑性的平面点和具有较低局部平滑性的边缘点。

1.5状态估计

使用迭代扩展卡尔曼滤波估计状态量X

前向传播 Forward Propagation

在 FAST-LIO 系统中,一旦接收到 IMU 输入,就会执行一次前向传播,用于预测系统当前的状态(积分得到粗略地位姿估计)。

后向传播与运动补偿 Backward Propagation and Motion Compensation

激光雷达一帧数据由很多点组成,这些点显然不是同一时间测量得到的,所以需要补偿时间差带来的运动误差。把一帧不同采样时间的点转换到最后的帧末时间(反向传播去运动畸变

残差计算和迭代状态更新

计算lidar里程计的残差,和LOAM、LIO-SAM一样,计算点面之间的距离作为残差。

利用迭代卡尔曼滤波估计位姿。

算法流程

1.6地图更新 MapUpdate

根据求解的状态量 X 把激光雷达点投影到世界坐标系的过程.

1.7初始化

为了获得系统状态(例如重力向量 Gg、偏差和噪声协方差)的良好初始估计,从而加速状态估计,需要进行初始化。在 FAST-LIO 中,初始化非常简单:保持 LiDAR 静止几秒钟(本文中的所有实验为 2 秒),然后将收集的数据用于初始化 IMU 偏差和重力向量。如果 LiDAR 支持非重复扫描(例如,Livox AVIA),保持静止还允许 LiDAR 捕捉一个初始的高分辨率地图,这对后续的导航非常有利。


 

2.代码相关

FAST-LIO 的代码是6e1fa94之前的commit的,之后的都是FAST-LIO2,注意区分。

代码有两个节点loam_feat_extract、loam_laserMapping。

2.1loam_feat_extract

1.支持四种激光雷达的点云:MID40、HORIZON、VELO16、OUST64,分别对应不同的回调函数

  • MID40:msg转为PCL点云,然后进行特征提取;
  • HORIZON(点云是livox自定义的类型)把每条线束scan的点看作一个点云,单帧点云把所有线束的点云放到容器vector中;会剔除一些重复性扫描到的点;

2.特征提取 give_feature

判断每个点类型是什么,如果是Edge_Jump或者Edge_Plane,加入到角点点云中;如果是Poss_Plane或者Real_Plane加入到面点点云中。最后将两个点云和单帧点云以话题形式发布。

2.2loam_laserMapping

1.订阅面点点云和IMU话题,把数据放到队列中,主函数中根据当前lidar的时间戳找到小于它时间戳的IMU数据 sync_packages()

2.对一组面点点云和IMU数据进行处理,计算状态量去除畸变后的面点点云 Process()

  • 第一次执行会进行初始化,利用开始的IMU帧的平均值初始化状态量x(初始化重力、陀螺仪偏差、加速度计和陀螺仪协方差)。只执行一次,执行完就退出了;
  • 后续帧会点云去畸变处理 UndistortPcl()

这个函数首先会把上一帧尾部的IMU数据添加到当前帧头部,遍历这些IMU数据,通过离散中值积分计算每两个IMU数据之间的状态量,更新协方差矩阵(对应论文公式7、8)

:关于误差卡尔曼ESKF的推导 建议参考高博的简明推导

然后将点云的每个点映射到采样结束时刻(后向传播,去畸变)。具体代码结合下面这张图更容易理解,参考[2]

假设某帧lidar采样开始时间是tb,采样结束时间是te,后向传播就是把单帧所有点的坐标映射到采样结束时刻te。

1.采样结束那一刻不一定有对应的IMU数据,因此先计算最后一个IMU数据到 te时刻的时间差 dli,以 dli 再做一次中值积分就得到了 te时刻系统的状态;

2.按时间从后往前遍历点云,假设当前点p对应的时刻为 tn,其所属的IMU区间时刻为[ tib , tie ](代码这部分设计的很巧妙),可以求得 tn 与 tib 的时间差 dt ,通过 dt 和 tib 时刻的位姿,便可求得 tn 时刻IMU的位姿。

3.上一步求得了 tn 时刻IMU的位姿,结合外参可以求出点p的世界坐标。

4.结合第一步te时刻IMU的位姿与第三步该点的世界坐标,可将该点世界坐标通过te时刻IMU位姿和外参反算回lidar系,就得到了该点在te时刻的lidar坐标系坐标。

总结:从 te 时刻至 tb 时刻,对每一个点完成上述操作,系统便完成了反向传播,即将一帧中所有点云都补偿到了这一帧结束的时刻。总之,通过向前与反向传播,得到了在点云最终时刻系统名义状态的先验值 x(计算了PVR,没有算bias) 误差状态的先验协方差 P运动补偿后的点云

3.局部地图动态管理,目的:为了始终维持lidar所在的世界坐标的位置在局部地图的中心,这样的匹配效果会更好  lasermap_fov_segment()

4.判断历史地图是否为空,若为空,用当前帧的点云降采样填充 featsFromMap;否则,对已有的 featsFromMap 再次降采样,如果降采样后点的个数大于5,会进入一个很大的if条件里。

  • 用当前帧点云与局部地图进行配准;

当前帧的每个点(lidar系)变换到世界坐标系(Pw = Twl * Pl = Twi * Til * Pl),然后找这个点在局部地图的五个近邻点,对这五个点拟合平面方程(Ax + By + Cz + D = 0),最小二乘求这个方程得到平面的法向量,计算该点到这个平面的距离作为残差。

  • 构建测量雅可比矩阵和观测值;

这部分主要是公式的推导,具体过程参考[3]的观测模型内容

  • 执行EKF状态更新;

这部分内容也是公式的推导,对当前状态进行更新以及卡尔曼增益的计算。其中卡尔曼增益的计算 用矩阵求逆定理推导了一种新的卡尔曼增益计算形式

  • 更新局部地图

根据求解的最优状态  把激光雷达点投影到世界坐标系.

5.话题的发布

发布去畸变后的点云、和局部地图匹配成功点的点云,发布里程计、路径。

总结

之前接触过的SLAM基本都是基于优化的后端方法,FAST-LIO算是我第一次接触基于滤波优化的方法,明显的区别在大量的公式推导。

参考

1.ESKF推导 https://zhuanlan.zhihu.com/p/441182819

2.Fast-Lio2代码及论文解析 https://zhuanlan.zhihu.com/p/616275334

3.观测模型的雅可比推导 https://zhuanlan.zhihu.com/p/561877392

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2374099.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

软考中级软件设计师——UML(统一建模语言)篇

UML的词汇表包含3种构造块:事物、关系和图。事物是对模型中最具有代表性的成分的抽象;关系把事物结合在一起;图聚集了相关的事物。 一、事物 UML 事物是模型中的基本元素,分为 结构事物、行为事物、分组事物、注释事物。 1. 结构事物 类(Class&#x…

TSN网络与DIOS融合:破解煤矿井下电力系统越级跳闸难题

一、引言 1.1 研究背景与意义 在现代煤矿生产中,井下电力系统作为整个煤矿生产的动力核心,其重要性不言而喻。煤矿井下的各类机械设备,如采煤机、刮板输送机、通风机、排水泵等,都依赖稳定的电力供应才能正常运行。电力系统的稳定…

SierraNet协议分析使用指导[RDMA]| 如何设置 NVMe QP 端口以进行正确解码

在解码RoCEv2数据包(包括TCP RDMA和RoCE RDMA)时,若捕获的跟踪数据无法正确解码,通常需要执行特定的解码步骤。对于RoCE RDMA跟踪数据的处理,分析器主要采用两种方式获取必要信息以实现数据包解码: 首先&am…

信号处理基础

一、目的 掌握信号处理的基本思想,理解采样信号的频谱特性,加强信号采样与重建的有关基本概念的理解,深入理解线性时不变系统输出与输入的关系,了解数字信号采样率转换前后信号频谱的特征。 二、内容与设计思想 1、给定序列,绘…

小刚说C语言刷题—1058 - 求出100至999范围内的所有水仙花数

1.题目描述 2.参考代码(C语言版) #include <stdio.h> int main(void) { int i; int bai,shi,ge; for( i100;i<999;i) { baii/100; shii/10%10; gei%10; if((bai*bai*bai)(shi*shi*shi)(ge*ge*ge)i) printf("%d\n",i); } return 0; } 今天内容到此结束&…

深入解析Docker:核心架构与最佳实践

文章目录 前言一、Docker 解决了什么问题&#xff1f;二、Docker 底层核心架构2.1 Docker 引擎的分层架构2.2 镜像的奥秘&#xff1a;联合文件系统&#xff08;UnionFS&#xff09;2.3 容器隔离的核心技术2.3.1 命名空间2.3.2 控制组&#xff08;Cgroups&#xff09;2.3.3 内核…

Edge浏览器PDF字体显示错误

Edge浏览器PDF字体显示错误 软件版本信息 Edge Version: 136.0.3240.50 Word Version: Microsoft Office 专业增强版2021问题描述 在Word中使用多级列表自动编号, 并使用Word软件自带的导出为PDF文件功能, 在Word中显示正常的数字, 在Edge中查看PDF将会出现渲染错误的现象,…

Python训练营打卡——DAY22(2025.5.11)

复习日 学习参考如何使用kaggle平台&#xff0c;写下使用注意点&#xff0c;并对下述比赛提交代码 泰坦尼克号——来自灾难的机器学习 数据来源&#xff1a; kaggle泰坦里克号人员生还预测 挑战 泰坦尼克号沉没是历史上最臭名昭著的海难之一。 1912年4月15日&#xff0c;在被普…

实战项目4(05)

​目录 任务场景一 【sw1配置】 任务场景二 【sw1配置】 【sw2配置】 任务场景一 按照下图完成网络拓扑搭建和配置 任务要求&#xff1a; 1、在交换机SW1的E0/0/1端口进行设置&#xff0c;实现允许最多两个电脑可以正常进行通信。 2、在交换机SW1的E0/0/2端口进行设置&…

C++学习之STL学习

在经过前面的简单的C入门语法的学习后&#xff0c;我们开始接触C最重要的组成部分之一&#xff1a;STL 目录 STL的介绍 什么是STL STL的历史 UTF-8编码原理&#xff08;了解&#xff09; UTF-8编码原理 核心编码规则 规则解析 编码步骤示例 1. 确定码点范围 2. 转换为…

3. 仓颉 CEF 库封装

文章目录 1. capi 使用说明2. Cangjie CEF2. 1实现目标 3. 实现示例 1. capi 使用说明 根据上一节 https://blog.csdn.net/qq_51355375/article/details/147880718?spm1011.2415.3001.5331 所述&#xff0c; cefcapi 是libcef 共享库导出一个 C API, 而以源代码形式分发的 li…

LabVIEW多通道并行数据存储系统

在工业自动化监测、航空航天测试、生物医学信号采集等领域&#xff0c;常常需要对多个传感器通道的数据进行同步采集&#xff0c;并根据后续分析需求以不同采样率保存特定通道组合。传统单线程数据存储方案难以满足实时性和资源利用效率的要求&#xff0c;因此设计一个高效的多…

谷歌在即将举行的I/O大会之前,意外泄露了其全新设计语言“Material 3 Expressive”的细节

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

十三、基于大模型的在线搜索平台——整合function calling流程

基于大模型的在线搜索平台——整合function calling流程 一、function calling调用总结 上篇文章已经实现了信息抓取能力&#xff0c;并封装成了函数。现在最后一步将能力转换为大模型可以调用的能力&#xff0c;实现搜索功能就可以了。这篇主要实现大模型的function calling能…

力扣70题解

记录 2025.5.8 题目: 思路&#xff1a; 1.初始化&#xff1a;p 和 q 初始化为 0&#xff0c;表示到达第 0 级和第 1 级前的方法数。r 初始化为 1&#xff0c;表示到达第 1 级台阶有 1 种方法。 2.循环迭代&#xff1a;从第 1 级到第 n 级台阶进行迭代&#xff1a; p 更新为前…

电商双11美妆数据分析

1、初步了解 2.2 缺失值处理 通过上面观察数据发现sale_count,comment_count 存在缺失值,先观察存在缺失值的行的基本情况 2.3 数据挖掘寻找新的特征 给出各个关键词的分类类别 由title新生成两列类别 对是否是男性专用进行分析并新增一列 对每个产品总销量新增销售额这一列

24、TypeScript:预言家之书——React 19 类型系统

一、预言家的本质 "TypeScript是魔法世界的预言家之书&#xff0c;用静态类型编织代码的命运轨迹&#xff01;" 霍格沃茨符文研究院的巫师挥动魔杖&#xff0c;类型注解与泛型的星轨在空中交织成防护矩阵。 ——基于《国际魔法联合会》第12号类型协议&#xff0c;Ty…

第8章-1 查询性能优化-优化数据访问

上一篇&#xff1a;《第7章-3 维护索引和表》 在前面的章节中&#xff0c;我们介绍了如何设计最优的库表结构、如何建立最好的索引&#xff0c;这些对于提高性能来说是必不可少的。但这些还不够——还需要合理地设计查询。如果查询写得很糟糕&#xff0c;即使库表结构再合理、索…

PCL点云按指定方向进行聚类(指定类的宽度)

需指定方向和类的宽度。测试代码如下&#xff1a; #include <iostream> #include <fstream> #include <vector> #include <string> #include <pcl/point_types.h> #include <pcl/point_cloud.h> #include <pcl/visualization/pcl_visu…

C#对SQLServer增删改查

1.创建数据库 2.SqlServerHelper using System; using System.Collections.Generic; using System.Data.SqlClient; using System.Data; using System.Linq; using System.Text; using System.Threading.Tasks;namespace WindowsFormsApp1 {internal class SqlServerHelper{//…