【PLIO学习总结】laserMapping中的时间戳与状态更新逻辑

本文仅用于个人学习总结记录。如有错误,请批评指正。

0、PLIO简要思路

从PLIO的论文中,可以知道,完整的PLIO算法采用IMU和LiDAR数据同时作为“输入”,维护状态变量包括加速度和角速度。

同时,PLIO是一种distortion-free的方法,即不需要进行去畸变。
之所以是不需要去畸变,是因为对每个雷达点都进行状态更新,然后将lidar点投回世界系作为地图点。

有了这个基本概念,我们就开始看laserMappingmain函数中的处理流程。

本文按照“IMU作为output”,即IMU不仅用于预测,也具有观测模型。此时,use_imu_as_input为false,imu_en为true。

1、不同时刻的更新逻辑

对于一个LIO系统,同时存在LiDAR和IMU数据,下图画出了对齐以后的两个时间轴。

在这里插入图片描述
可以看出,一次lidar的scan之间有多个绿色的雷达点,同时也有多个IMU测量。
两个IMU的测量间,可能有多个LiDAR pint;
两个LiDAR point间,也可能有多个IMU(虽然我不知道为啥,但代码的逻辑是这么处理的。实测发现,基本上两个Point之间只会出现“1个”IMU)

在代码的sync_packages时,把LiDAR和IMU数据进行了打包,保证了在后续处理时,永远是一个完整的scan中LiDAR Point
和IMU数据。

那么,在收到一个IMU或一个LiDAR时,理论上都进行状态更新。
但是,在代码实现中,永远是在每个LiDAR Point到来时进行更新。只不过,如果这个point到来时,buffer中下一个IMU数据如果是这个point之前,则需要用IMU的数据进行更新;否则,只更新LiDAR Point这部分。

1.1 无IMU数据

这里我们把这种情况叫做 Case 1,具体的示意图如下:

在这里插入图片描述
即当前时间是一个lidar point对应的时刻,前一次状态更新时刻time_predict_last_const和当前时刻time_current之间没有插入IMU数据。

此时,需要做的事情为:

  • 根据上一次IMU的输入,进行预测操作,预测状态量,和对应的协方差;
  • 根据LiDAR的观测和残差,更新状态量和协方差。

1.2 有IMU的数据

这里我们把这种情况叫做 Case 2,具体的示意图如下:

在这里插入图片描述

这就稍微有一些复杂了,因为上一个“状态完整更新”时刻应该是上一个Point,但当前的Point和前一个Point之间,有了多个IMU数据(一般是1个)。

此时,做的事情包括:

  • 对第1个IMU时刻,计算上一个Point到这个IMU的时间间隔dt,然后预测新的状态,和协方差;
  • 利用第1个IMU的数据,观测模型,计算残差,并进行更新全部状态和协方差;
  • 如果有多个IMU,则重复上面两个步骤。注意,重复时,时间间隔为距离上一个IMU测量的时间间隔,而不是到前一个LiDAR Point的;
  • 完成所有IMU时刻的预测和更新之后,处理新的LiDAR Point的数据,此时再执行1.1里面的两步:计算当前Point到前面最近IMU的时间间隔dt,预测状态和协方差;根据LiDAR的数据进行更新。

1.3 完整的时间戳示意图

在这里插入图片描述

2、代码

捋清楚上面的过程,就可以看代码了。这里,只保留代码的框架。


// IMU作为状态量进行更新
if (!use_imu_as_input){// 对所有(时间压缩后的)雷达点进行更新for (k = 0; k < time_seq.size(); k++)       {PointType &point_body  = feats_down_body->points[idx+time_seq[k]];time_current = point_body.curvature / 1000.0 + pcl_beg_time;    // 获取当前雷达点时间戳if(imu_en){bool imu_comes = time_current > imu_next.header.stamp.toSec();// 是否有了新的IMU数据?如果有,执行下面while,即case2中所说的内容;如果没有,跳过这部分,只是简单的case1while (imu_comes){imu_next = *(imu_deque.front());                // 获得buffer中的IMU,这个IMU的时间戳处于“上一次更新”和“当前雷达点”时间戳之间double dt = imu_last.header.stamp.toSec() - time_predict_last_const;kf_output.predict(dt, Q_output, input_in, true, false);                 // case2中,预测到当前IMU时刻时,状态的预测;double dt_cov = imu_last.header.stamp.toSec() - time_update_last;       // 问题:if (dt_cov > 0.0){kf_output.predict(dt_cov, Q_output, input_in, false, true);         // case2中,预测到当前IMU时刻时,协方差的状态;kf_output.update_iterated_dyn_share_IMU();                          // case2中,IMU进行update}}}double dt = time_current - time_predict_last_const;             kf_output.predict(dt, Q_output, input_in, true, false);         // case1,lidar点到前一个预测时刻,状态的预测time_predict_last_const = time_current;if (!kf_output.update_iterated_dyn_share_modified())            // case1,lidar进行update{idx = idx+time_seq[k];				// 获取下一个 Lidar Point的索引continue;}}
}

3、遗留问题

现在还遗留了一个问题,就是代码中有两个变量,记录上一次XXX的时间:
time_predict_last_consttime_update_last
从名字上看,前者是“上一次predict的时刻”,后者是“上一次update的时刻”。二者什么区别么?

在代码中,二者的区别体现在

if(!prop_at_freq_of_imu)
{double dt_cov = time_current - time_update_last;if (dt_cov > 0.0){kf_output.predict(dt_cov, Q_output, input_in, false, true);time_update_last = time_current;   							// 这里更新了“上一次更新时间戳”}
}
kf_output.predict(dt, Q_output, input_in, true, false);
time_predict_last_const = time_current;								// 这里更新了“上一次预测时间戳”

即,如果prop_at_freq_of_imu是false的,两者不一样;
但是,目前版本的代码中,prop_at_freq_of_imu一直是true,因此,这里时间戳有一些的混乱。

所以,在作者的代码中,有这么一行:

time_predict_last_const = imu_last.header.stamp.toSec(); // big problem 

作者注释了“大问题”,可能是一些功能增删造成的混乱吧。但应该不影响上面部分的大逻辑。

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

YOLOv7改进 | 更换主干网络之PP-LCNet

前言:Hello大家好,我是小哥谈。PP-LCNet是一个由百度团队针对Intel-CPU端加速而设计的轻量高性能网络。它是一种基于MKLDNN加速策略的轻量级卷积神经网络,适用于多任务,并具有提高模型准确率的方法。与之前预测速度相近的模型相比,PP-LCNet具有更高的准确性。此外,对于计…

F-logic DataCube3 任意文件上传漏洞复现(CVE-2024-25832)

0x01 产品简介 F-logic DataCube3是一款用于光伏发电系统的紧凑型终端测量系统。 0x02 漏洞概述 F-logic DataCube3 /admin/setting_photo.php接口处存在任意文件上传漏洞 ,未经身份验证的攻击者可通过该漏洞在服务器端写入后门,获取服务器权限,进而控制整个web服务器。 …

【ShenYu源码阅读】支持提醒通知设计,来看看开源贡献者都做了什么

相信大家碰到源码时经常无从下手&#x1f643;&#xff0c;不知道从哪开始阅读&#xff0c;面对大量代码晕头转向&#xff0c;索性就读不下去了&#xff0c;又浪费了一次提升自己的机会&#x1f62d;。 我认为有一种方法&#xff0c;可以解决大家的困扰&#xff01;那就是通过阅…

【vue.js】文档解读【day 5】| ref模板引用

如果阅读有疑问的话&#xff0c;欢迎评论或私信&#xff01;&#xff01; 本人会很热心的阐述自己的想法&#xff01;谢谢&#xff01;&#xff01;&#xff01; 文章目录 模板引用前言访问模板引用模板引用与v-if、v-show的结合v-for中的模板引用函数模板引用 模板引用 前言 …

如何把Spring的Bean注入到Quartz中

前言 今天写Quartz定时调度的时候遇到了想调用增删改查操作数据库的情况 这时候在Quartz容器中 直接注入bean 但是会出现bean为空的情况&#xff0c; 一、为什么为空 这种情况是因为Quartz容器 中 它读取不到Spring 容器中的bean&#xff0c;所以我们需要加一些方法让他读到 …

macOs charles 证书过期

macOs charles ssl证书有效期是一年&#xff0c;到期续期更新 1.点击help ->SSL proxying->Install charless Certificate 完了会进入到钥匙串访问&#xff0c; 2.在钥匙串访问中 找到新生成的证书&#xff0c;点击信任&#xff0c;选择始终信任 3.如果在钥匙串种找不到…

git的实际运用

1. SSH配置和Github仓库克隆 注意博主在这里演示的SSH密钥生成方式&#xff0c;下面追加的五行不成功时可手动到.ssh下的config文件中添加即可 $ tail -5 config Host github.comHostName github.comPreferredAuthentications publickeyIdentityFile ~/.ssh/test 演示 2. 关联…

MySQL-索引事务

文章目录 前言一、 索引1.1 概念1.2 作用1.3 使用场景1.4 使用1.5 索引的底层数据结构1.5.1 用来查询的数据结构1.5.2 B树1.5.3 B树 二、事务2.1 为什么使用事务2.2 事务的概念2.3 事务的性质&#xff08;ACID&#xff09;2.4 事务的使用 前言 在这里将最近学习的MySQL中索引及…

办公自动化的得力助手 —— 定时执行专家

目录 一、软件简介 二、办公应用场景 1、自动化文件处理 2、定时提醒与日程管理 3、网络操作与远程控制 4、系统维护与优化 三、使用体验 四、总结 在快节奏的现代办公环境中&#xff0c;如何高效地管理任务、节省时间并提升工作效率成为了每个职场人士关注的焦点。今天…

为什么光学器件需要厚度

确定光学厚度的限值 光学元件的功能和性能在很大程度上受到可用光学材料的限制。制造和光学元件设计的最新发展现在拓宽了可以实现的目标。特别是&#xff0c;平面光学器件或超表面可以设计为具有大块光学元件的功能&#xff0c;但其厚度缩小到仅几百纳米。米勒现在提出了一项…

七月论文审稿GPT第3.2版和第3.5版:通过paper-review数据集分别微调Mistral、gemma

前言 我司第二项目组一直在迭代论文审稿GPT(对应的第二项目组成员除我之外&#xff0c;包括&#xff1a;阿荀、阿李、鸿飞、文弱等人)&#xff0c;比如 七月论文审稿GPT第1版&#xff1a;通过3万多篇paper和10多万的review数据微调RWKV七月论文审稿GPT第2版&#xff1a;用一万…

springboot275毕业就业信息管理系统的设计与实现

毕业就业信息管理系统设计与实现 摘 要 传统办法管理信息首先需要花费的时间比较多&#xff0c;其次数据出错率比较高&#xff0c;而且对错误的数据进行更改也比较困难&#xff0c;最后&#xff0c;检索数据费事费力。因此&#xff0c;在计算机上安装毕业就业信息管理系统软件…