尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

视觉SLAM位姿估计:从数学表示到重投影误差优化实践

视觉SLAM位姿估计:从数学表示到重投影误差优化实践 1. 项目概述从“我在哪”到“世界什么样”搞视觉SLAMSimultaneous Localization and Mapping同步定位与建图的朋友估计都绕不开“位姿”这个核心概念。我第一次接触这个词的时候也觉得有点抽象不就是位置和姿态吗但真正上手写代码、调参数才发现这里面门道太深了。位姿理解不到位整个SLAM系统就像在雾里开车地图建得歪七扭八定位也飘得没边。这个项目我们就来深挖一下视觉SLAM中的位姿特别是那个听起来有点绕的“间接求解”到底是怎么一回事。简单来说视觉SLAM要解决两个核心问题定位我/相机现在在哪儿朝向哪和建图我周围的环境长什么样。而“位姿”就是“定位”问题的数学化描述它精确地定义了相机在三维世界中的位置和旋转方向。你可以把它想象成给相机贴了一个独一无二的“身份证”上面写着它在世界坐标系下的x, y, z坐标和roll, pitch, yaw三个旋转角。但问题来了相机自己并没有GPS它只能通过“看”到的图像来推断自己的这个“身份证”信息这个过程就是位姿估计。为什么“间接求解”这么重要因为相机直接测量到的是像素是二维平面上的一个个亮点。我们无法直接从一张图片里读出“相机向前移动了1米并向右旋转了5度”。我们必须通过分析连续图像之间像素点的对应关系、三维空间点的重投影误差等间接信息反推出相机的运动。这个过程充满了噪声、误匹配和数学上的非线性也正是SLAM算法魅力和挑战所在。这篇文章我会结合自己调试ORB-SLAM、VINS-Mono等开源系统的经验把位姿的表示、求解思路、以及实操中那些容易踩的坑掰开揉碎了讲清楚。2. 位姿的数学外衣不止一种穿法理解位姿求解首先得知道我们用什么“语言”来描述它。不同的数学工具就像不同的外衣各有各的适用场合和优缺点。2.1 旋转的表示从欧拉角到四元数与旋转矩阵最直观的表示大概是欧拉角Yaw, Pitch, Roll分别对应绕Z、Y、X轴的旋转。它非常符合人类直觉告诉你“偏航多少度”、“俯仰多少度”、“翻滚多少度”。在调试和可视化时我经常用欧拉角来快速判断姿态是否合理。但是欧拉角有个致命缺陷万向节死锁Gimbal Lock。当俯仰角Pitch为±90度时偏航和翻滚会失去一个自由度导致姿态表示不唯一在插值和优化时会引发剧烈跳变。所以欧拉角绝不适合作为SLAM内部核心计算的表示形式。为了解决这个问题我们引入了旋转矩阵R一个3x3的正交矩阵和四元数q一个4维向量。旋转矩阵非常“厚重”9个参数带有6个约束正交且行列式为1能直接与三维点坐标相乘进行旋转操作。而四元数则非常“精炼”用4个参数无奇异地表示三维旋转在存储和插值上效率极高。实操心得在代码中我通常采用“内存用四元数计算用旋转矩阵人机交互看欧拉角”的策略。例如在C的Eigen库中状态变量存储为四元数Eigen::Quaterniond需要变换点时转换为旋转矩阵.toRotationMatrix()在ROS的Rviz里查看轨迹时则发布成包含欧拉角的几何消息格式。2.2 齐次坐标与变换矩阵把位置和旋转打包仅有旋转还不够我们还需要位置即平移向量t一个3维向量。将旋转矩阵R和平移向量t组合起来就构成了一个完整的刚体变换。但更优雅的方式是使用齐次坐标和变换矩阵TT [ R t ] [ 0 1 ]这是一个4x4的矩阵。为什么用齐次坐标因为它能让旋转和平移统一成一个矩阵乘法操作。对于一个三维点P_w世界坐标系其在相机坐标系下的坐标P_c可以通过下式求得P_c R * P_w t。用齐次坐标表示点P [x, y, z, 1]^T则上式可优雅地写为P_c T * P_w‘。这种形式在连续变换时尤其方便因为多次变换就是多次矩阵连乘。这里有一个关键理解变换矩阵T的逆T^{-1}表示从相机坐标系到世界坐标系的变换。在SLAM中我们经常需要在这两个坐标系间来回切换。例如将地图点从世界坐标转换到当前相机坐标进行重投影或者将新观测到的点从相机坐标转换到世界坐标加入地图。3. 间接求解的核心基于重投影误差的优化现在进入硬核部分相机如何通过看到的图像“间接”求解出位姿T主流方法几乎都绕不开“重投影误差”这个概念。3.1 从特征匹配到几何约束假设我们有两帧图像I1 和 I2。SLAM算法如ORB-SLAM会提取并匹配它们之间的特征点如ORB特征。每一对匹配点(p1, p2)都对应着三维空间中的同一个物理点P。在I1帧相机位姿为T1观测到P的像素坐标为p1。在I2帧相机位姿为T2观测到P的像素坐标为p2。如果我们能知道P的三维坐标那么我们就可以计算“重投影误差”用估计的位姿T2将P投影到I2的图像平面上得到一个预测的像素坐标p2然后计算p2和p2的距离。这个距离就是误差。我们的目标就是找到一个T2使得对于所有匹配点这个误差的总和最小。但问题在于一开始我们既不知道准确的T2也不知道准确的P。这就是一个“鸡生蛋还是蛋生鸡”的问题。解决方案是捆绑调整Bundle Adjustment, BA它同时优化所有相机位姿和所有三维地图点的位置使得整体重投影误差最小。这是一个大规模的非线性最小二乘问题。3.2 求解的利器非线性优化与李群李代数直接对旋转矩阵R和平移向量t或变换矩阵T进行优化是困难的因为旋转矩阵自身有约束正交阵直接在它上面做加法R ΔR会破坏约束。这时李群和李代数就登场了。简单类比李群如旋转矩阵群SO(3)、变换矩阵群SE(3)就是我们要优化的“对象本身”但它生活在弯曲的空间里不方便进行微积分运算。而李代数如 so(3), se(3)对应的是这个弯曲空间在原点附近的“切线空间”它是一个向量空间我们可以自由地做加法、求导。在优化时我们实际上是在优化李代数上的扰动量ξ一个6维向量前3维代表旋转后3维代表平移。我们用一个初始位姿T加上一个由李代数ξ表示的小扰动通过指数映射得到更新后的位姿T exp(ξ^∧) * T。这样我们就把一个在非线性流形上的优化问题转化为了在向量空间李代数上的优化问题就可以愉快地使用高斯牛顿法、列文伯格-马夸尔特法LM法等工具了。注意事项在实现或调用优化库如g2o, Ceres时需要正确定义参数块ParameterBlock和残差块ResidualBlock。对于位姿我们通常将李代数ξ作为参数块。残差就是重投影误差。雅可比矩阵的计算即误差关于李代数的导数是重中之重推导复杂但很多库已自动实现。如果自己推导务必注意是左扰动模型还是右扰动模型一致性是关键。3.3 两步走的经典策略对极几何初始化与局部BA在实际的视觉SLAM系统中完整的全局BA计算量巨大通常采用分层策略初始化与位姿估计对于刚开始的连续两帧我们还没有地图点。此时使用对极几何Epipolar Geometry来初步估计相对位姿。通过对极约束x2^T * E * x1 0其中E是本质矩阵可以分解出R和t再通过三角化得到第一批粗糙的三维地图点。这是一个纯几何过程为后续优化提供了一个不错的初始值。局部捆集调整Local BA系统运行中不会每次都优化所有帧和所有点。通常维护一个“局部地图”包含当前帧、共视关系强的关键帧以及它们观测到的地图点。只优化这个局部窗口内的所有位姿和地图点。这保证了实时性。g2o或Ceres在这里大显身手。全局捆集调整Global BA在后台线程低速运行或者在回环检测闭合后触发对所有关键帧和所有地图点进行全局优化以消除长时间运行累积的漂移。4. 实操中的核心环节与参数调试理论懂了上手写代码或者跑通开源算法时才是真正挑战的开始。下面我以经典的单目ORB-SLAM2为例拆解几个核心环节。4.1 特征提取与匹配稳定性的基石位姿求解的精度极度依赖于特征匹配的质量。误匹配就是优化问题中的“离群点”Outlier会严重拉偏优化结果。ORB参数调优在ORB-SLAM的yaml配置文件中ORBextractor.nFeatures提取的特征点数是关键。在纹理丰富的室内1000点可能足够但在空旷的室外可能需要调到2000甚至3000以保证有足够多的匹配。ORBextractor.scaleFactor金字塔尺度因子影响尺度不变性通常用1.2是一个平衡点。匹配策略与筛选ORB-SLAM使用了词袋模型进行快速候选匹配但随后必须用描述子距离汉明距离进行最近邻/次近邻比Ratio Test如Lowe’s 0.8筛选。这能过滤掉大部分模糊匹配。但还不够必须用几何约束进行第二次筛选对极约束用于初始化或未三角化的点使用RANSAC算法拟合基础矩阵F或本质矩阵E剔除不满足几何约束的误匹配。PnP用于已有地图点的帧使用RANSAC求解EPnP或UPnP直接利用三维点-二维点对应关系来剔除外点。踩坑实录我曾在一个光照变化剧烈的走廊场景中发现轨迹频繁跳动。排查后发现默认的ORB阈值对明暗变化太敏感。解决方案是1) 启用图像金字塔增强尺度鲁棒性2) 在特征提取前加入简单的直方图均衡化CLAHE缓解光照不均3) 将RANSAC的迭代次数提高并降低内点判断的像素误差阈值让几何校验更严格。调整后系统稳定性大幅提升。4.2 优化器的配置与雅可比当你使用g2o或Ceres时优化器的配置直接影响收敛速度和精度。优化算法选择LM法比高斯牛顿法更鲁棒因为它引入了阻尼因子在梯度大时更像最速下降法梯度小时更像高斯牛顿法。通常首选LM。迭代次数与终止条件maxIterations不能设太小如10否则可能未收敛也不能设太大如100浪费算力。30-50次是常见范围。更要关注终止条件如设置functionTolerance函数值变化阈值和parameterTolerance参数变化阈值。信息矩阵Information Matrix的设定这是很多初学者忽略的一点。重投影误差的权重应该与特征点检测的不确定性相关。一个简单的启发式方法是将信息矩阵设为单位矩阵乘以一个尺度因子该因子与特征点尺度的平方成反比尺度越大定位可能越不准权重越低。更精细的做法会考虑图像金字塔的层级。关于雅可比如果你是自己定义Ceres的CostFunction需要手动推导和编码雅可比矩阵。对于重投影误差关于李代数的雅可比推导涉及链式法则和SO(3)/SE(3)的扰动模型。这是一个易错点。一个调试技巧是开启Ceres的数值求导检查功能CHECK_JACOBIANS与你手写的解析雅可比进行对比确保一致。4.3 尺度不确定性单目SLAM的“阿喀琉斯之踵”这是单目视觉SLAM独有的、必须深刻理解的问题。单目相机无法从单张图像中获取绝对尺度。我们通过对极几何和三角化恢复出的三维点云和相机运动其尺度是任意的可能比真实世界大10倍也可能小10倍。如何确定尺度在ORB-SLAM中通过两个步骤1)初始化时假设一个平面场景如地面并设定初始特征点的平均深度为1从而确定一个初始尺度。2)运行时通过不断地将新三角化点的深度与已有地图点的中值深度进行比较进行尺度漂移的微小修正。如何与真实尺度对齐这需要外部信息。常见方法有引入已知尺寸的物体在场景中放置一个边长为已知的标定板或物体系统可以通过识别它来恢复绝对尺度。传感器融合这也是为什么VINS-Mono等算法要融合IMU。IMU提供的加速度测量直接包含了物理世界的米/秒^2单位可以稳定地估计并纠正单目视觉的尺度漂移。在初始化阶段VINS会有一段“对齐”过程将视觉的初始尺度与IMU的尺度拉齐。个人体会纯单目SLAM在手持手机做快速旋转时尺度漂移非常明显轨迹可能会被压扁或拉长。而在缓慢平移的场景下尺度相对稳定。因此在评估一个单目SLAM算法时一定要在多种运动模式下测试其尺度一致性。如果项目要求绝对尺度强烈建议考虑双目、RGB-D或融合IMU的方案。5. 常见问题排查与性能调优指南视觉SLAM系统在运行时会出现各种问题以下是一些典型症状和我的排查思路。问题现象可能原因排查步骤与解决方案轨迹整体漂移越跑越偏累积误差这是增量式SLAM的本质问题。1.检查回环检测是否正常工作词袋数据库是否太小回环确认阈值是否太严2.增加全局BA频率在保证实时性的前提下在后台线程更频繁地执行轻量级全局优化。3.检查局部BA窗口大小窗口太小约束不足窗口太大计算慢且容易受旧错误帧影响。初始化频繁失败场景纹理缺失、纯旋转或平移太小。1.可视化特征点看看提取的特征点是否足够且分布均匀。2.检查运动尝试让设备做足够的侧向平移这是单目初始化成功的关键。3.调整初始化参数如增加RANSAC迭代次数放宽对极几何的内点阈值。运行时突然跟踪丢失快速运动导致图像模糊、光照剧变、或被遮挡。1.启用运动模型预测用上一帧的速度模型预测当前位姿在特征匹配时缩小搜索范围。2.重定位机制检查重定位模块是否触发词袋模型是否能在丢失后找回。3.增加关键帧插入的冗余度在运动快时适当降低插入关键帧的时空阈值避免信息链断裂。地图点云稀疏或不稳定三角化成功率低、点云剔除策略太激进。1.检查三角化条件视差角是否足够大通常1度匹配是否正确2.调整地图点生命周期不要过早剔除被短暂遮挡的点。可以增加“被观测次数”和“最近被观测帧ID”的判断阈值。3.检查深度滤波器如PTAM中的滤波器如果是滤波方式检查其收敛速度和不确定性估计是否合理。优化耗时过长无法实时局部BA窗口内变量太多、优化设置不当。1.限制局部BA窗口大小固定优化最近N个关键帧而不是所有共视关键帧。2.使用舒尔补Schur Complement消元在BA中先消去地图点变量只求解相机位姿变量能极大加速。g2o和Ceres默认支持。3.降低优化频率不一定每帧都做局部BA可以每插入一个关键帧做一次。性能调优的一个核心思想是权衡在精度、鲁棒性和实时性之间找到平衡点。没有一套参数适合所有场景。我的建议是准备一个具有不同挑战性的数据集如慢速平移、快速旋转、纹理重复、光照变化针对你的目标平台PC、嵌入式设备进行系统性的参数扫描测试记录轨迹误差和CPU占用率最终确定一组最优的折中参数。最后再分享一个调试时的小技巧可视化是王道。除了轨迹一定要把特征匹配、关键帧、地图点云、共视关系图、优化误差曲线等都可视化出来。很多问题比如误匹配集中在某个区域、某个关键帧位姿异常、误差在某个时刻突增在图上都能一目了然比看日志数字高效得多。用好像Rviz、Pangolin这样的工具能极大提升开发和调试效率。
返回列表