当前位置: 首页 > news >正文

《LIO-SAM阅读笔记》3.后端优化

前言:

LIO-SAM后端优化部分写在了mapOptimization.cpp文件中,本部分主要进行了激光帧的scan-to-map匹配,回环检测以及关键帧的因子图优化。本部分主要有两个环节同步进行,一个单独开辟了回环检测线程,另外一个是lidar数据的回调函数。

功能简介:

  • 1、scan-to-map匹配:提取当前激光帧特征点(角点、平面点),局部关键帧map的特征点,执行scan-to-map迭代优化,更新当前帧位姿;
  • 2、闭环检测:在历史关键帧中找距离相近,时间相隔较远的帧设为匹配帧,匹配帧周围提取局部关键帧map,同样执行scan-to-map匹配,得到位姿变换,构建闭环因子数据,加入因子图优化。
  • 3、关键帧因子图优化:关键帧加入因子图,添加激光里程计因子、GPS因子、闭环因子,执行因子图优化,更新所有关键帧位姿;

订阅:

  • 1、订阅当前激光帧点云信息,来自FeatureExtraction;
  • 2、订阅GPS里程计;
  • 3、订阅来自外部闭环检测程序提供的闭环数据,本程序没有提供,这里实际没用上。

发布:

  • 1、发布历史关键帧里程计;
  • 2、发布局部关键帧map的特征点云;
  • 3、发布激光里程计,rviz中表现为坐标轴;
  • 4、发布激光里程计;
  • 5、发布激光里程计路径,rviz中表现为载体的运行轨迹;
  • 6、发布地图保存服务;
  • 7、发布闭环匹配关键帧局部map;
  • 8、发布当前关键帧经过闭环优化后的位姿变换之后的特征点云;
  • 9、发布闭环边,rviz中表现为闭环帧之间的连线;
  • 10、发布局部map的降采样平面点集合;
  • 11、发布历史帧(累加的)的角点、平面点降采样集合;
  • 12、发布当前帧原始点云配准之后的点云。

一:scan-to-map匹配

scan-to-map匹配出现在雷达数据的回调函数laserCloudInfoHandler中,其是激光里程计最基本的位姿估计方法,其进行的操作有:当前帧位姿的初始化、组建局部地图、进行当前帧到局部地图的匹配和位姿优化、用imu原始RPY数据与scan-to-map优化后的位姿进行加权融合。

1.位姿初始化

(1)如果是第一帧,用原始imu数据的RPY初始化当前帧位姿(旋转部分)

(2)后续帧,用imu里程计计算两帧之间的增量位姿变换,作用于前一帧的激光位姿(是因子图联合优化后的最优位姿),得到当前帧激光位姿 // note:利用imu里程计信息设置优化的初值

注意:此处的当前帧和上一帧之间的位姿变换 = 由上一帧的imu里程计位姿的逆*当前帧的imu里程计位姿。

2.局部地图map

(1)对最近的一帧关键帧,搜索时空维度上相邻的关键帧集合,降采样一下。这里采用的kdtree进行搜索,是将历史所有关键帧集合存入kdtree中进行搜索。

(2)对关键帧集合中的每一帧,提取对应的角点、平面点,加入局部map中。局部地图map中的点云超过一定数量时,就会清空下一帧的点云进行scan-to-map时进行重新创建。因此局部地图并不是每一帧点云到来时都进行重新,创建一次,只需要往点云地图中添加新的点云即可。

3.scan-to-map位姿优化

前面位姿初始化时,我们设置的当前帧的位姿主要是通过imu里程计得到,这里对上面的初始化位姿进行优化。

3.1 当前激光帧角点寻找局部map匹配点

(1)更新当前帧位姿,将当前帧角点坐标变换到map系下,在局部map中查找5个最近点,距离小于1m,且5个点构成直线(用距离中心点的协方差矩阵,特征值进行判断),则认为匹配上了。

(2)计算当前帧角点到直线的距离、垂线的单位向量,存储为角点参数。

3.2 当前激光帧平面点寻找局部map匹配点

(1)更新当前帧位姿,将当前帧平面点坐标变换到map系下,在局部map中查找5个最近点,距离小于1m,且5个点构成平面(最小二乘拟合平面),则认为匹配上了。

(2)计算当前帧平面点到平面的距离、垂线的单位向量,存储为平面点参数。

3.3 scan-to-map优化

上面的角点到直线的距离以及平面点到平面的距离,就是非线性优化中的约束项,并以此构建残差。

对匹配特征点计算Jacobian矩阵,观测值为特征点到直线、平面的距离,构建高斯牛顿方程,迭代优化当前位姿,存transformTobeMapped

3.4 与imu原始RPY数据加权融合

此处imu使用的是一个九轴的imu相比与六轴imu多出一个全局的imu位姿,此处imu原始RPY就是一个全局的imu位姿的roll、pitch和yaw角。

更新当前帧位姿的roll, pitch, z坐标;因为是小车,roll、pitch是相对稳定的,不会有很大变动,一定程度上可以信赖imu的数据,z是进行高度约束。

二:闭环检测线程

在此.cpp文件的节点中单独开辟了一个回环检测线程,在检测到回环后,在回环检测线程会对当前帧位姿进行一个icp的优化位姿。

1.选取候选闭环帧

在历史关键帧中查找与当前关键帧距离最近的关键帧集合,选择时间相隔较远的一帧作为候选闭环帧,此处同样使用的是kdtree的方法进行搜索。

这里时间的间隔设置的是30s,必须满足时间上超过一定的阈值,才认为是一个有效的回环。

2.提取当前帧特征点集合和组建候选帧区域map

提取当前关键帧特征点集合,降采样;提取闭环匹配关键帧前后相邻若干帧的关键帧特征点集合,降采样,目的是使用scan-to-map的方法进行优化位姿。

3.scan-to-map优化:icp

执行scan-to-map优化,调用icp方法,得到优化后位姿,构造闭环因子需要的数据,在因子图优化中一并加入更新位姿。

注意:

  • 前面也有scan-to-map优化,是基于非线性优化的方法来进行优化的;此处采用的icp点云配准的方法,这种ICP方法视为基于线性优化的变体。
  • 闭环的时候没有立即更新当前帧的位姿,而是添加闭环因子,让图优化去更新位姿。

通过调用PCL的icp库可以得到闭环帧到当前帧较为准确的位姿变换,用此位姿变换去矫正当前帧位姿,并作为约束因子加入到gtsam中,等待因子图优化环节一起优化。

三:因子图优化

因子图优化也是写在了雷达数据的回调函数laserCloudInfoHandler中,因子图优化联合了雷达里程计信息(包含IMU信息)、GPS信息和闭环信息一起进行优化。因子图优化是全局关键帧优化,前面的优化都是对当前帧的局部优化。

1.添加关键帧

计算当前帧与前一帧位姿变换,如果变化太小,不设为关键帧,反之设为关键帧,非关键帧则跳出,不进行因子图优化。

2.添加激光里程计因子

激光里程计因子是一个帧间约束,前一帧和当前帧(3.3中scan-to-map之后的位姿)的位姿变换。

3. 添加GPS因子

gps的数据会先被一个成熟的节点(在module_navsat.launch文件)处理,我们直接调用的gps的处理结果。

本项目中作者对gps的使用较为谨慎。

4.添加闭环因子

闭环因子就是就是闭环检测线程中计算的当前帧和闭环帧之间的位姿变换。

5.执行因子图优化

执行了因子图优化后,优化器中所有的关键帧位姿都进行了优化。

执行完因子图优化后,清空一下这一轮优化使用的因子图(里面的优化因子),历史数据不会清掉,ISAM保存起来了,只是清空因子图不是清空的优化器。

到此为之,不管是全局优化还是局部优化都完成了,有几个变量需要注意:

// note:当前位姿的一个最优估计(最准确的),通过以下两种方式更新:

// 1.如果这帧是普通帧,通过scan to map得到

// 2.若果这帧是关键帧,先通过scan to map更新,再通过因子图优化更新

transformTobeMapped[6]

// 历史关键帧位姿

// note:所有的雷达帧位姿会在这里更新 (如果是普通帧,则是因子图优化之前的san-map得到的位姿,如果是关键帧,则是因子图优化得到的位姿)

pcl::PointCloud<PointTypePose>::Ptr cloudKeyPoses6D;

pcl::PointCloud<PointType>::Ptr copy_cloudKeyPoses3D;

pcl::PointCloud<PointTypePose>::Ptr copy_cloudKeyPoses6D;

四:发布激光里程计

此处发布了一个增量式里程计信息,用于IMU预计分时使用。此外还有一个优化后的最优位姿,用于IMU里程计使用。

增量式里程计当前帧(scan to map 后的位姿,没经过回环因子图优化)与前一帧(因子图优化后的位姿)之间的位姿变换 (这是一个平滑的结果)。

相关文章:

《LIO-SAM阅读笔记》3.后端优化

前言&#xff1a; LIO-SAM后端优化部分写在了mapOptimization.cpp文件中&#xff0c;本部分主要进行了激光帧的scan-to-map匹配&#xff0c;回环检测以及关键帧的因子图优化。本部分主要有两个环节同步进行&#xff0c;一个单独开辟了回环检测线程&#xff0c;另外一个是lidar…...

mac下jd-gui提示没有找到合适的jdk版本

mac下jd-gui提示jdk有问题 背景解决看一下是不是真有问题了方法一&#xff1a;修改启动脚本方法二&#xff1a;设置launchd环境变量 扩展动态切jdk脚本(.bash_profile) 背景 配置了动态jdk后&#xff0c;再次使用JD-GUI提示没有找到合适的jdk版本。 解决 看一下是不是真有问题…...

FlinkSQL窗口实例分析

Windowing TVFs Windowing table-valued functions (Windowing TVFs)&#xff0c;即窗口表值函数 注意&#xff1a;窗口函数不可以单独使用&#xff0c;需要聚合函数&#xff0c;按照 window_start、window_end 分区&#xff0c;即存在&#xff1a;group by window_start,wind…...

18-网络安全框架及模型-信息系统安全保障模型

信息系统安全保障模型 1 基本概念 信息系统安全保障是针对信息系统在运行环境中所面临的各种风险&#xff0c;制定信息系统安全保障策略&#xff0c;设计并实现信息系统安全保障架构或模型&#xff0c;采取工程、技术、管理等安全保障要素&#xff0c;将风险减少至预定可接受的…...

Android 提取(备份)apk(安装包)

Android 提取(备份)apk(安装包) 一、通过安卓代码的方式 主要分三步&#xff1a; 根据应用找到包名根据包名获得apk提取apk 提取apk代码 private static final String BACKUP_PATH "/sdcard/backup1/"; private static final String APK ".apk";pri…...

gRPC-Go基础(4)metadata和超时设置

文章目录 0. 简介1. metadata1.1 metadata结构1.2 metadata创建1.3 客户端处理metadata1.4 服务端处理metadata1.5 metadata的传输 2. 超时设置2.1 客户端输出超时信息2.2 服务端端接收超时信息 3. 小结 0. 简介 Go在多个go routine之间传递数据使用的是Go SDK提供的context包…...

语言模型:从n-gram到神经网络的演进

目录 1 前言2 语言模型的两个任务2.1 自然语言理解2.2 自然语言生成 3 n-gram模型4 神经网络语言模型5 结语 1 前言 语言模型是自然语言处理领域中的关键技术之一&#xff0c;它致力于理解和生成人类语言。从最初的n-gram模型到如今基于神经网络的深度学习模型&#xff0c;语言…...

docker compose 部署 grafana + loki + vector 监控kafka消息

Centos7 随笔记录记录 docker compose 统一管理 granfana loki vector 监控kafka 信息。 当然如果仅仅是想通过 Grafana 监控kafka&#xff0c;推荐使用 Grafana Prometheus 通过JMX监控kafka 目录 1. 目录结构 2. 前提已安装Docker-Compose 3. docker-compose 自定义服…...

kubeadm创建k8s集群

kubeadm来快速的搭建一个k8s集群&#xff1a; 二进制搭建适合大集群&#xff0c;50台以上。 kubeadm更适合中下企业的业务集群。 部署框架 master192.168.10.10dockerkubelet kubeadm kubectl flannelnode1192.168.10.20dockerkubelet kubeadm kubectl flannelnode2192.168.1…...

鸿蒙开发之android对比开发《基础知识》

基于华为鸿蒙未来可能不再兼容android应用&#xff0c;推出鸿蒙开发系列文档&#xff0c;帮助android开发人员快速上手鸿蒙应用开发。 1. 鸿蒙使用什么基础语言开发&#xff1f; ArkTS是鸿蒙生态的应用开发语言。它在保持TypeScript&#xff08;简称TS&#xff09;基本语法风…...

2702 高级打字机

因为Undo操作只能撤销Type操作&#xff0c;所以Undo x 实际上就是删除文章末尾x个字母。用一个栈即可解决&#xff08;每个字母最多进出一次&#xff09;。 这种情况下只需要设计一个合理的数据结构依次执行操作即可。 版本树&#xff1a;Undo x撤销最近的x次修改操作&#xf…...

yolov5旋转目标检测-遥感图像检测-无人机旋转目标检测-附代码和原理

综述 为了解决旋转目标检测问题&#xff0c;研究者们提出了多种方法和算法。以下是一些常见的旋转目标检测方法&#xff1a; 基于滑动窗口的方法&#xff1a;在图像上以不同的尺度和角度滑动窗口&#xff0c;通过分类器判断窗口中是否存在目标。这种方法简单直观&#xff0c;…...

Qt学习:Qt的意义安装Qt

Qt 的简介 QT 是一个跨平台的 C图形用户界面应用程序框架。它为程序开发者提供图形界面所需的所有功能。它是完全面向对象的&#xff0c;很容易扩展&#xff0c;并且允许真正地组件编程。 支持平台 xP 、 Vista、Win7、win8、win2008、win10Windows . Unix/Linux: Ubuntu 等…...

Anylogic Pro 8.8.x for Mac / for Linux Crack

Digital twins – a step towards a digital enterprise AnyLogic是唯一一个支持创建模拟模型的方法的模拟建模工具&#xff1a;面向过程&#xff08;离散事件&#xff09;、系统动态和代理&#xff0c;以及它们的任何组合。AnyLogic提供的建模语言的独特性、灵活性和强大性使…...

ROS无人机初始化GPS定位漂移误差,确保无人机稳定飞行

引言&#xff1a; 由于GPS在室外漂移的误差比较大&#xff0c;在长时间静止后启动&#xff0c;程序发布的位置可能已经和预期的位置相差较大&#xff0c;导致无法完成任务&#xff0c;尤其是气压计的数据不准&#xff0c;可能会导致无人机不能起飞或者一飞冲天。本文主要是在进…...

k8s网络类型

k8s中的通信模式&#xff1a; pod内部之间容器与容器之间的通信。 在同一个pod中的容器共享资源和网络&#xff0c;使用同一个网络命名空间。可以直接通信的。 同一个node节点之内&#xff0c;不同pod之间的通信。 每一个pod都有一个全局的真实的IP地址&#xff0c;同一个n…...

Seata 中封装了四种分布式事务模式,分别是: AT 模式, TCC 模式, Saga 模式, XA 模式,

文章目录 seata概述Seata 中封装了四种分布式事务模式&#xff0c;分别是&#xff1a;AT 模式&#xff0c;TCC 模式&#xff0c;Saga 模式&#xff0c;XA 模式&#xff0c; 今天我们来聊聊seata seata 概述 在微服务架构下&#xff0c;由于数据库和应用服务的拆分&#xff0c…...

为什么设计制造行业需要数据加密?

设计制造行业是一个涉及多种技术、工艺、材料和产品的广泛领域&#xff0c;它对经济和社会的发展有着重要的影响。然而&#xff0c;随着数字化、智能化和网络化的发展&#xff0c;设计制造行业也面临着越来越多的数据安全风险&#xff0c;如数据泄露、数据篡改、数据窃取等。这…...

查看ios app运行日志

摘要 本文介绍了一款名为克魔助手的iOS应用日志查看工具&#xff0c;该工具可以方便地查看iPhone设备上应用和系统运行时的实时日志和奔溃日志。同时还提供了奔溃日志分析查看模块&#xff0c;可以对苹果奔溃日志进行符号化、格式化和分析&#xff0c;极大地简化了开发者的调试…...

怎么卸载macOS上的爱思助手如何卸载macOS上的logitech g hub,如何卸载顽固macOS应用

1.在App Store里下载Cleaner One Pro &#xff08;注意&#xff0c;不需要订阅付费&#xff01;&#xff01;&#xff01;白嫖基础功能就完全够了&#xff01;&#xff01;&#xff01;&#xff09; 2.运行软件&#xff0c;在左侧目录中选择“应用程序管理”&#xff0c;然后点…...

Leetcode 3576. Transform Array to All Equal Elements

Leetcode 3576. Transform Array to All Equal Elements 1. 解题思路2. 代码实现 题目链接&#xff1a;3576. Transform Array to All Equal Elements 1. 解题思路 这一题思路上就是分别考察一下是否能将其转化为全1或者全-1数组即可。 至于每一种情况是否可以达到&#xf…...

IGP(Interior Gateway Protocol,内部网关协议)

IGP&#xff08;Interior Gateway Protocol&#xff0c;内部网关协议&#xff09; 是一种用于在一个自治系统&#xff08;AS&#xff09;内部传递路由信息的路由协议&#xff0c;主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...

工程地质软件市场:发展现状、趋势与策略建议

一、引言 在工程建设领域&#xff0c;准确把握地质条件是确保项目顺利推进和安全运营的关键。工程地质软件作为处理、分析、模拟和展示工程地质数据的重要工具&#xff0c;正发挥着日益重要的作用。它凭借强大的数据处理能力、三维建模功能、空间分析工具和可视化展示手段&…...

12.找到字符串中所有字母异位词

&#x1f9e0; 题目解析 题目描述&#xff1a; 给定两个字符串 s 和 p&#xff0c;找出 s 中所有 p 的字母异位词的起始索引。 返回的答案以数组形式表示。 字母异位词定义&#xff1a; 若两个字符串包含的字符种类和出现次数完全相同&#xff0c;顺序无所谓&#xff0c;则互为…...

【C++从零实现Json-Rpc框架】第六弹 —— 服务端模块划分

一、项目背景回顾 前五弹完成了Json-Rpc协议解析、请求处理、客户端调用等基础模块搭建。 本弹重点聚焦于服务端的模块划分与架构设计&#xff0c;提升代码结构的可维护性与扩展性。 二、服务端模块设计目标 高内聚低耦合&#xff1a;各模块职责清晰&#xff0c;便于独立开发…...

Java面试专项一-准备篇

一、企业简历筛选规则 一般企业的简历筛选流程&#xff1a;首先由HR先筛选一部分简历后&#xff0c;在将简历给到对应的项目负责人后再进行下一步的操作。 HR如何筛选简历 例如&#xff1a;Boss直聘&#xff08;招聘方平台&#xff09; 直接按照条件进行筛选 例如&#xff1a…...

【开发技术】.Net使用FFmpeg视频特定帧上绘制内容

目录 一、目的 二、解决方案 2.1 什么是FFmpeg 2.2 FFmpeg主要功能 2.3 使用Xabe.FFmpeg调用FFmpeg功能 2.4 使用 FFmpeg 的 drawbox 滤镜来绘制 ROI 三、总结 一、目的 当前市场上有很多目标检测智能识别的相关算法&#xff0c;当前调用一个医疗行业的AI识别算法后返回…...

技术栈RabbitMq的介绍和使用

目录 1. 什么是消息队列&#xff1f;2. 消息队列的优点3. RabbitMQ 消息队列概述4. RabbitMQ 安装5. Exchange 四种类型5.1 direct 精准匹配5.2 fanout 广播5.3 topic 正则匹配 6. RabbitMQ 队列模式6.1 简单队列模式6.2 工作队列模式6.3 发布/订阅模式6.4 路由模式6.5 主题模式…...

return this;返回的是谁

一个审批系统的示例来演示责任链模式的实现。假设公司需要处理不同金额的采购申请&#xff0c;不同级别的经理有不同的审批权限&#xff1a; // 抽象处理者&#xff1a;审批者 abstract class Approver {protected Approver successor; // 下一个处理者// 设置下一个处理者pub…...

Python 高效图像帧提取与视频编码:实战指南

Python 高效图像帧提取与视频编码:实战指南 在音视频处理领域,图像帧提取与视频编码是基础但极具挑战性的任务。Python 结合强大的第三方库(如 OpenCV、FFmpeg、PyAV),可以高效处理视频流,实现快速帧提取、压缩编码等关键功能。本文将深入介绍如何优化这些流程,提高处理…...