BIEVR-LIO:基于高分辨率体素图像地图的鲁棒激光雷达惯性里程计
1. 项目概述为什么我们需要一个更“抗造”的激光雷达里程计做机器人定位与建图SLAM的朋友尤其是玩激光雷达LiDAR的肯定都踩过类似的坑在空旷的走廊里点云特征少得可怜里程计飘得亲妈都不认识在高速运动的场景下点云畸变严重匹配起来一塌糊涂或者环境里突然冒出来几个动态物体比如走动的行人、穿梭的车辆地图里就留下了一串“鬼影”直接带偏后续的定位。这些问题本质上都是传统激光雷达惯性里程计LIO在应对极端场景时的“脆弱性”体现。今天要聊的这个BIEVR-LIO就是冲着解决这些“脆弱点”来的。它的全称是“基于高分辨率体素图像地图的鲁棒激光雷达惯性里程计”。名字有点长但拆开看就很有意思BIEVR是它的核心创新我理解是“Bidirectional Implicit Encoding Voxel Representation”的缩写即“双向隐式编码体素表示”LIO是大家熟悉的激光雷达惯性里程计框架而“高分辨率体素图像地图”则是它实现鲁棒性的关键武器。简单来说BIEVR-LIO干了一件什么事呢它不再满足于用传统的点云地图或者粗糙的体素地图来做匹配定位。传统方法里一个体素格子比如边长10cm里可能塞了几十个甚至上百个点但最终只用它们的中心或者平均位置来代表这个格子细节丢失严重。BIEVR-LIO则是在每个体素内部构建了一个高分辨率的、隐式编码的“图像”。你可以把它想象成把一个米粒大小的体素内部又划分成了更精细的网格比如1cm分辨率并且用一种紧凑的数学方式隐式编码记录下这个微小空间里表面的朝向、距离等信息。这样当地图与当前帧激光点云做匹配时就能获得远比传统方法丰富和精确的几何约束。为什么这就能提升鲁棒性我举个例子。传统方法在长走廊里两边的墙面可能因为点云稀疏在体素地图里就变成了两排稀疏的“柱子”约束力很弱容易在走廊方向发生滑动。而BIEVR-LIO的高分辨率体素图像能清晰地“画”出墙面连续的表面即使当前帧点云打在墙上的点不多也能从地图中这些连续的表面信息获得强烈的“吸附力”有效抑制漂移。对于动态物体因为这种表示对场景的表面几何刻画得非常精细动态物体留下的短暂、不连贯的痕迹更容易被识别为噪声并在优化中被剔除。所以BIEVR-LIO瞄准的就是那些让传统LIO“翻车”的场景特征退化环境长廊、隧道、广场、高速运动带来的点云畸变、以及存在动态干扰的复杂环境。它试图通过一种更丰富、更精细的地图表征方式为激光雷达里程计披上一身“重甲”让它变得更抗造、更可靠。接下来我们就深入它的内部看看这套“重甲”是如何锻造出来的。2. 核心思路拆解从体素到体素“图像”的进化之路要理解BIEVR-LIO我们得先看看主流LIO是怎么工作的然后才能明白它革新在哪里。目前高性能的LIO系统比如FAST-LIO系列、LIO-SAM等其核心框架可以概括为“紧耦合迭代卡尔曼滤波IEKF或因子图优化”。简单说就是利用IMU惯性测量单元的高频数据预测机器人的运动提供一个初值同时用激光雷达扫描到的点云去和已有的地图进行匹配通过最小化匹配误差来修正预测得到更精确的位姿位置和姿态。这里面最关键的步骤就是“点云-地图匹配”。传统方法的地图无非是以下几种点云地图最直接就是把所有历史点云累积在一起。优点是保留了原始精度缺点是数据量大、查询慢且无法处理动态点。体素地图将空间划分成均匀的立方体格体素每个体素内只保留一个代表点如中心点或均值点。这大大压缩了数据量但损失了细节尤其在体素尺寸较大时。平面地图提取点云中的平面特征如墙面、地面用平面方程来表示。在结构化环境中很高效但在非结构化环境如树林、废墟中特征提取困难。BIEVR-LIO的突破点就在于对“体素地图”进行了升级。它不满足于一个体素只存一个“代表点”而是想存下这个体素内部更精细的几何结构。这就引出了它的核心高分辨率体素图像。2.1 什么是“体素图像”你可以把一个标准的体素比如10cm边长的立方体想象成一个微型的“房间”。传统方法只记录了这个房间的“中心点”。而BIEVR-LIO则在这个房间里布置了一个密集的、三维的网格比如每个方向划分10份那就有了1000个10x10x10更小的格子。它并不直接存储这1000个小格子里有没有点而是用一种称为隐式神经表示Implicit Neural Representation, INR的技术学习一个函数。这个函数以空间坐标x,y,z相对于该体素中心为输入输出这个坐标位置的某些几何属性比如符号距离函数SDF值表示该点到最近物体表面的带符号距离内部为负外部为正。截断符号距离函数TSDF值只关心表面附近一定范围内的距离。特征向量一个更高维的编码隐式地包含法向量、语义等信息。这个学习到的函数就像一个“魔法公式”可以随时查询体素内任意一点的信息。所谓“体素图像”我理解就是将这个体素内部按照固定分辨率比如1cm采样用这个“魔法公式”计算出每个采样点的属性如SDF值形成的一个三维数据阵列。这个阵列就像一张描述体素内部几何的“图像”只不过它是三维的。2.2 “双向隐式编码”又是什么“双向”Bidirectional是BIEVR的另一个精妙之处。在构建这个隐式函数时它不仅仅是根据落入该体素的激光点来学习还考虑了该点与传感器原点之间的射线。正向编码一个激光点提供了它击中位置表面点的信息。反向编码从传感器原点到这个激光点的整条射线提供了这条路径上空间是“空”的信息直到击中点为止。传统的隐式重建如NeRF主要利用正向信息。BIEVR将反向的射线信息也编码进去这使得学习到的隐式函数不仅能更准确地表达表面在哪里SDF零值面还能更好地表达哪些地方是自由空间SDF正值区域。这在匹配时非常有用因为当前帧的激光点不仅应该落在表面的零值面上其对应的射线路径也应该大部分处于地图预测的自由空间中。这相当于为匹配增加了一个额外的、强有力的约束。注意这里的“双向”与网络结构中的双向循环神经网络Bi-RNN不是一回事。它指的是利用点位置表面和射线空域这两种不同视角的观测数据来进行隐式编码。2.3 BIEVR-LIO的整体工作流程结合以上两点BIEVR-LIO的流程就清晰了传感器数据输入接收激光雷达点云和IMU数据流。运动预测与去畸变利用IMU数据预测当前时刻的位姿并基于此对当前帧的激光点云进行运动补偿去畸变。地图查询与匹配对于去畸变后的每一个激光点找到它所在的高层级体素比如10cm的体素然后利用该体素内预构建好的“隐式函数”查询该点精确位置处的几何属性如SDF值及其梯度/法向量。构建残差与优化将“当前点应位于表面SDF0”作为一个约束构建点到面的残差。同时可能利用射线空域信息构建额外的残差。将所有点的残差与IMU预测的残差一起送入一个非线性优化器如高斯牛顿法、LM法进行求解得到最优的当前位姿。地图更新用优化后的位姿将当前帧的有效点云“融合”到地图中。这里不是简单的添加点而是更新对应体素内部的“隐式函数”参数使函数能更好地拟合新观测到的几何。这个过程不断循环实现实时的定位与高精度地图构建。其优势在于匹配时利用的是连续、可微的几何场而非离散的点点或点面匹配理论上能提供更稳定、更精确的约束。3. 关键技术实现细节剖析理解了宏观思路我们深入到几个关键的技术实现细节这些往往是论文不会细说但在实际复现或理解中至关重要的部分。3.1 隐式函数的网络结构与训练BIEVR-LIO的核心是一个轻量级的神经网络用于实现每个体素内的隐式函数。它不能太大否则实时性无法保证也不能太简单否则拟合能力不够。常见的结构选择小型MLP多层感知机输入是3D坐标经过该体素局部坐标归一化经过3-5个全连接层输出SDF值或TSDF值和/或一个特征向量。激活函数常用ReLU或SineSIREN。哈希编码 小型MLP借鉴Instant-NGP的思想使用一个可学习的多分辨率哈希表对输入坐标进行编码然后将编码后的特征向量输入一个极小的MLP甚至只有1-2层。这种方式能极大加快训练和推理速度是实时系统的首选。训练地图更新过程 地图更新本质上是在线训练这些神经网络。每个体素对应一个独立的网络。当新的激光点落入一个体素时采样点生成不仅在该表面点附近采样还在其对应的传感器射线路径上采样一些“空点”。损失函数计算对于表面点计算网络预测的SDF值与0的差距。对于射线上的空点计算网络预测的SDF值是否大于0或一个小的截断距离。同时通常还会加入Eikonal正则项强制预测的SDF场梯度近似为1以保证其是一个有效的距离场。反向传播与参数更新只更新该体素对应的网络参数。由于每个体素网络很小且每次只更新少数几个因此计算量可控。实操心得在线训练神经网络对系统稳定性是巨大挑战。学习率设置非常关键太大导致地图震荡太小则无法及时融入新观测。通常采用一个衰减的学习率策略并且对于长时间未观测的体素可以“冻结”其网络参数以减少计算和防止遗忘。3.2 多分辨率体素管理与哈希索引整个地图由不同层级的体素构成粗分辨率体素例如0.5m或1m用于快速全局查找和动态对象过滤。一个动态物体如行人通常只占据少数几个粗体素可以通过统计该体素内点的存活时间被观测到的持续帧数来滤除短暂存在的点。高分辨率体素例如0.1m或0.05m这是存储“体素图像”/隐式函数的基本单元。它提供了精细的几何细节。管理海量体素尤其是高分辨率体素需要高效的数据结构。稀疏体素哈希表是标准选择。它只为被占用的体素分配内存即存储其隐式网络参数。给定一个3D坐标通过一个哈希函数快速映射到哈希表中的一个条目从而找到对应的体素及其网络。哈希冲突处理是一个工程难点。当两个不同的3D坐标哈希到同一个表条目时发生冲突。常用链地址法每个条目存一个链表或更复杂的空间哈希函数如带有位移向量的哈希来缓解。3.3 点云-地图匹配的优化策略匹配过程就是求解一个非线性最小二乘问题最小化所有激光点残差之和。对于BIEVR-LIO第i个点的残差通常定义为r_i sdf(T * p_i)其中T是待求的位姿变换矩阵p_i是当前帧激光点sdf()函数就是查询该变换后点所在体素的隐式网络得到的SDF值。优化要点雅可比矩阵计算优化需要残差对位姿T的雅可比矩阵。这需要用到链式法则dr_i/dT (dsdf/dx) * (dx/dT)。dsdf/dx是SDF值对空间位置的梯度即该点的表面法向量可以通过网络自动微分得到。dx/dT是变换后的点坐标对位姿参数的导数这是标准的李代数导数。鲁棒核函数为了应对误匹配如动态点、噪声点必须使用鲁棒核函数如Huber、Cauchy来降低大残差的权重防止它们把优化拉偏。迭代求解采用高斯-牛顿或LM算法迭代求解。由于隐式函数是可微的整个过程可以流畅地进行。效率优化点云下采样匹配前对当前帧点云进行体素下采样减少计算量。并行查询对多个激光点的SDF查询是独立的可以在GPU上并行进行。局部地图只维护机器人周围一定范围内的活跃地图区域并进行优化远处的区域可以保持固定或转为低分辨率表示。4. 实战从零搭建BIEVR-LIO的简化原型完全复现论文系统需要大量的工程工作。这里我带你搭建一个极度简化但核心思想一致的BIEVR-LIO原型帮助理解整个流水线。我们使用Python和PyTorch并假设已有IMU预积分功能或使用简单匀速模型。4.1 环境准备与依赖安装# 创建虚拟环境 conda create -n bievr_lio_demo python3.8 conda activate bievr_lio_demo # 安装核心依赖 pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118 # 根据CUDA版本调整 pip install numpy open3d scipy matplotlib tqdm pip install einops # 方便张量操作4.2 定义隐式体素网络我们采用“哈希编码微型MLP”的方案参考Instant-NGP但极度简化。import torch import torch.nn as nn import torch.nn.functional as F import numpy as np class TinyHashMLP(nn.Module): 一个超轻量的哈希编码MLP用于一个体素 def __init__(self, hash_size1024, hash_dim2, mlp_hidden16, output_dim1): super().__init__() self.hash_table nn.Parameter(torch.randn(hash_size, hash_dim) * 0.01) # 可学习的哈希表 self.hash_size hash_size # 微型MLP: 输入是多个哈希特征拼接输出SDF值 self.net nn.Sequential( nn.Linear(hash_dim * 8, mlp_hidden), # 假设我们用8个分辨率级别 nn.ReLU(), nn.Linear(mlp_hidden, output_dim) ) def hash_function(self, x): 一个简单的空间哈希函数将3D坐标映射到哈希表索引 # x: [N, 3] 归一化到[0, 1]的局部坐标 primes torch.tensor([1, 2654435761, 805459861], devicex.device) hash_val (x * primes).sum(dim1, keepdimTrue) return torch.abs(hash_val.long()) % self.hash_size def forward(self, x): x: [N, 3] 体素局部坐标范围假设为[-0.5, 0.5] 返回: [N, 1] SDF值 # 1. 将坐标归一化到[0,1]用于哈希 x_norm (x 0.5) # 现在范围是[0,1] # 2. 多分辨率哈希编码简化版仅示意 features [] for res in [1, 2, 4, 8, 16, 32, 64, 128]: # 8个分辨率级别 # 缩放坐标 x_scaled x_norm * res x_floor torch.floor(x_scaled).long() # 简单线性插值实际Instant-NGP更复杂 idx self.hash_function(x_floor / res) # 获取哈希索引 feat self.hash_table[idx] # [N, hash_dim] features.append(feat) # 拼接所有分辨率的特征 all_feat torch.cat(features, dim-1) # [N, hash_dim*8] # 3. 通过微型MLP sdf self.net(all_feat) return sdf4.3 构建稀疏体素地图管理器class SparseVoxelMap: 管理稀疏的高分辨率体素及其网络 def __init__(self, voxel_size0.1, hash_size1024): self.voxel_size voxel_size self.hash_size hash_size self.voxels {} # 字典键为体素索引tuple值为TinyHashMLP网络 def get_voxel_index(self, point): 将全局坐标点转换为体素索引 index torch.floor(point / self.voxel_size).int() return tuple(index.cpu().numpy()) def get_voxel_center(self, index): 根据体素索引计算体素中心全局坐标 center (torch.tensor(index, dtypetorch.float32) 0.5) * self.voxel_size return center def query_sdf(self, points_global): 查询一批全局坐标点的SDF值 points_global: [N, 3] 返回: sdf_values [N, 1], valid_mask [N,] sdf_list [] valid_mask [] for i, pt in enumerate(points_global): idx self.get_voxel_index(pt) if idx in self.voxels: # 获取该体素网络 net self.voxels[idx] # 计算局部坐标 center self.get_voxel_center(idx).to(pt.device) pt_local (pt - center) / self.voxel_size # 范围约[-0.5, 0.5] pt_local pt_local.unsqueeze(0) # [1,3] # 查询 with torch.no_grad(): sdf net(pt_local) sdf_list.append(sdf) valid_mask.append(True) else: # 该点所在体素不存在于地图中赋予一个大的正值表示自由空间 sdf_list.append(torch.tensor([10.0], devicepoints_global.device)) valid_mask.append(False) sdf_vals torch.stack(sdf_list).squeeze(-1) if sdf_list else torch.tensor([], devicepoints_global.device) valid_mask torch.tensor(valid_mask, devicepoints_global.device) return sdf_vals, valid_mask def update_map(self, points_global, poses): 用新点云更新地图极度简化仅示意 # 实际这里应该进行在线训练此处简化为若体素不存在则初始化一个网络 for pt in points_global: idx self.get_voxel_index(pt) if idx not in self.voxels: # 初始化该体素的网络 self.voxels[idx] TinyHashMLP(hash_sizeself.hash_size).to(points_global.device) # 理论上这里应该用该体素内的点云数据来训练这个网络 # 但为简化我们只做初始化 # 实际系统中此处应有复杂的在线训练循环 print(f地图更新当前体素数量{len(self.voxels)})4.4 实现紧耦合优化器简化版我们用一个基于点-面距离的ICP迭代最近点优化来模拟匹配过程但残差来源于我们学习的SDF场。from scipy.spatial.transform import Rotation as R def optimize_pose_icp_sdf(curr_points, map_manager, init_pose, iterations10): 使用SDF场进行点云配准简化版高斯牛顿 curr_points: [N, 3] 当前帧点云传感器坐标系 map_manager: SparseVoxelMap 实例 init_pose: 初始位姿 [4,4] 齐次变换矩阵 (世界坐标系 - 传感器坐标系) pose init_pose.copy() last_loss 1e10 for iter in range(iterations): # 1. 将当前点变换到世界坐标系 pts_world (pose[:3, :3] curr_points.T pose[:3, 3:4]).T # [N,3] # 2. 查询SDF值 sdf_vals, valid_mask map_manager.query_sdf(pts_world) if not valid_mask.any(): print(没有有效匹配点) break valid_sdf sdf_vals[valid_mask] valid_pts_world pts_world[valid_mask.cpu().numpy()] # 3. 计算残差 (理想情况下SDF应为0) residuals valid_sdf.unsqueeze(-1).cpu().numpy() # [M, 1] # 4. 计算雅可比矩阵 (简化这里需要SDF对位姿的导数实际需通过网络梯度计算) # 我们这里用一个简化假设残差只与位置有关且雅可比近似为点云法向量由SDF梯度近似 # 实际BIEVR-LIO会通过自动微分精确计算。 J np.zeros((len(residuals), 6)) # 对6自由度位姿的雅可比 [M, 6] # ... 此处省略复杂的雅可比计算实际应用需实现 ... # 5. 高斯牛顿更新 (简化假设HJ^T*J) # 由于雅可比计算复杂这里我们用一个退化的梯度下降示意 current_loss np.mean(residuals**2) print(fIteration {iter}, Loss: {current_loss:.6f}) if current_loss last_loss * 0.999: # 简单收敛判断 print(Loss收敛缓慢停止迭代) break last_loss current_loss # 简化更新沿SDF梯度反方向移动这只是一个示意并非正确的位姿更新 # 正确的做法是构建H矩阵和b向量求解增量dx # 这里我们跳过直接返回初始位姿强调流程 if iter iterations - 1: print(达到最大迭代次数) # 返回优化后的位姿 (此处未真正优化仅示意) return pose4.5 主循环流程示意def main_loop(lidar_stream, imu_stream): 主处理循环极度简化示意 map_manager SparseVoxelMap(voxel_size0.1) current_pose np.eye(4) # 初始位姿世界坐标系原点 for frame_id, (points, imu_data) in enumerate(zip(lidar_stream, imu_stream)): print(f\n--- Processing Frame {frame_id} ---) # 步骤1: IMU预测简化假设匀速模型或使用预积分库如imu_utils # predicted_pose predict_with_imu(current_pose, imu_data) predicted_pose current_pose # 简化直接用上一帧位姿作为预测 # 步骤2: 点云去畸变简化假设瞬时扫描 undistorted_points points # 实际需要根据IMU数据做运动补偿 # 步骤3: 点云下采样 downsampled_points voxel_downsample(undistorted_points, voxel_size0.05) # 步骤4: 点云-地图匹配优化 optimized_pose optimize_pose_icp_sdf( downsampled_points, map_manager, predicted_pose, iterations5 ) current_pose optimized_pose # 步骤5: 地图更新将当前帧点云融入 # 需要将点云变换到世界坐标系 points_world (current_pose[:3, :3] downsampled_points.T current_pose[:3, 3:4]).T map_manager.update_map(points_world, current_pose) # 输出当前位姿 print(fOptimized Pose t: {current_pose[:3, 3]}) if frame_id 50: # 只处理前50帧示意 break print(处理完成。)重要提示以上代码是高度简化的教学原型省略了IMU预积分、精确的SDF梯度计算、完整的非线性优化、高效的哈希编码、以及神经网络在线训练等核心复杂模块。它仅用于展示BIEVR-LIO算法流程的骨架。实际系统需要基于C/CUDA实现并集成成熟的数学库如Sophus, g2o, Ceres-Solver和深度学习框架如LibTorch。5. 性能优化与工程落地挑战将BIEVR-LIO从论文搬到现实需要面对一系列工程挑战。5.1 实时性保障这是最大的挑战。隐式网络的前向查询和反向训练都比简单的最近邻搜索耗时得多。网络轻量化使用类似Instant-NGP的哈希编码将网络参数量压缩到极致每个体素可能只需几百个参数。前向推理只需几次查表和简单的MLP计算。CUDA并行化所有操作坐标变换、哈希查询、网络推理、损失计算都必须深度并行化。特别是对成千上万个点的批量处理必须放在GPU上。选择性更新并非每帧都更新所有被观测体素的网络。可以采用“关键帧”策略或者只对SDF误差大的区域进行更新。多尺度优化先使用低分辨率体素地图进行快速粗匹配再用高分辨率体素进行精匹配减少需要查询的高精度体素数量。5.2 地图一致性维护在线学习神经网络地图如何保证其长期一致性不遗忘旧信息和全局一致性闭环时如何修正是个难题。弹性权重巩固EWC思想在更新网络参数时对之前学到的“重要”参数施加惩罚防止其被新数据过度修改。子地图管理将地图划分为多个子地图每个子地图维护自己的局部隐式表示。闭环检测调整的是子地图之间的位姿约束子地图内部的表示可以保持不变或进行较小调整。这比直接调整一个巨大的全局网络要容易。定期重定位与全局优化在后台线程运行一个全局姿态图优化当检测到闭环时优化关键帧位姿。然后根据优化后的位姿对涉及区域的隐式地图进行“微调”或重新训练。5.3 动态物体处理BIEVR-LIO的隐式表示本身对动态物体有一定鲁棒性因为动态点不会形成稳定、连续的表面其对应的SDF值会不断变化在优化中可能被核函数抑制。但更主动的策略包括运动物体检测利用多帧点云的一致性或结合视觉信息检测出潜在的运动物体区域。在这些区域降低其观测值在地图更新中的权重甚至不进行地图更新。临时物体过滤通过统计体素内点的“存活时间”过滤掉只出现少数几帧的点云这些很可能是动态物体或噪声。5.4 内存管理高分辨率体素意味着巨大的潜在内存消耗即使使用稀疏哈希表。滑动窗口只保留机器人周围一定半径内的活跃体素。远离的体素可以将其网络参数序列化后存入硬盘或者转换为一种更紧凑的表示如提取为网格或面片。参数共享探索是否可以让相邻的、几何相似的体素共享部分网络参数进一步压缩模型。混合表示在远处或几何简单的区域如空旷天空退回到传统的点云或低分辨率体素表示只在近处和复杂区域使用高分辨率隐式表示。6. 常见问题与调试心得在实际尝试实现或理解这类系统时你肯定会遇到各种问题。以下是我根据经验总结的一些常见坑点和排查思路。6.1 定位发散或漂移严重可能原因1SDF场学习不准确。网络没有正确收敛预测的SDF值杂乱无章。排查可视化SDF场。在几个已知的物体表面如地面、墙面采样查看其SDF值是否接近0法向量方向是否合理。解决检查损失函数设计确保包含了Eikonal正则项。调整学习率可能初始学习率太高。增加射线空点样本的权重确保空域约束有效。可能原因2优化问题病态。在特征退化区域如长廊即使SDF场准确约束也可能不足。排查检查优化过程中信息矩阵Hessian矩阵近似的条件数。在长廊中沿着长廊方向的特征值会非常小。解决紧密耦合IMU。这是LIO的优势在视觉/激光退化时IMU提供的短期约束至关重要。确保IMU预积分和雅可比计算正确。也可以考虑引入其他传感器如轮速计、磁力计或先验信息如已知的地面平面。可能原因3动态物体干扰。排查观察残差分布动态物体对应的点通常会有持续的大残差。解决引入更鲁棒的核函数如Tukey核或实现前述的动态物体检测与滤除模块。6.2 地图出现“重影”或“鬼影”可能原因动态物体被错误地融入了地图。因为系统是增量式建图一个移动的人走过可能会在轨迹上留下一串模糊的表面。解决提高更新阈值一个体素需要被观测到足够多的次数例如连续5帧才被确认为静态物体并更新地图。显式动态检测如前所述利用几何或时间一致性检测。使用更短的地图记忆在滑动窗口内如果某个表面只在最近一两帧出现随后消失则将其从地图中移除。6.3 系统运行速度慢无法实时可能原因1网络查询是瓶颈。解决确保哈希查询和微型MLP推理在GPU上完成并且是批量进行的。使用半精度fp16推理可以进一步提升速度。可能原因2优化迭代次数过多。解决设置合理的迭代停止条件如残差变化小于阈值。使用更高效的优化器如Dog-leg。良好的IMU预测可以提供非常接近的初值减少所需的迭代次数。可能原因3地图管理开销大。解决优化稀疏哈希表的数据结构和冲突处理算法。使用内存池来管理网络参数。6.4 闭环检测与修正困难挑战隐式地图不像点云地图或特征点地图那样容易提取全局描述子如Scan Context, LiDAR Iris进行快速闭环检测。思路双图层地图在维护隐式地图的同时维护一个用于闭环检测的轻量化全局描述图层。例如定期从隐式地图中提取一个低分辨率的占据栅格地图或语义标签地图用于计算全局描述子。基于位姿图的闭环当检测到可能的闭环时通过描述子匹配或几何验证在因子图中添加一个闭环约束因子。优化的是关键帧的位姿而不是直接修改隐式地图。优化后根据新的关键帧位姿对相关区域的隐式地图进行“调整”。这个调整可以是通过额外的训练步骤将旧观测在新位姿下重新融入。调试心得从简单场景开始。先在一个静态、小范围的室内环境如一个房间跑通流程确保基本的定位和建图功能正常。然后逐步增加难度加入缓慢运动加入动态物体如一个摆动的钟摆再到长廊、室外广场等退化环境。每一步都仔细可视化中间结果预测轨迹、地图SDF切片、残差图这是定位问题最直接的方法。BIEVR-LIO是一个复杂的系统耐心和细致的调试是成功的关键。

相关新闻