做无人机避障项目的人十有八九会在VINS和ORB-SLAM3之间纠结。这两个名字在视觉SLAM圈子里几乎是绕不开的参照系VINS系列以视觉惯性紧耦合出名ORB-SLAM3则是特征点SLAM里的标杆。但避障场景和其他落地方向不太一样它不看论文里的Benchmark精度而是看连续输出、延迟、丢失频率这些东西。这篇文章是我把两套系统分别跑到一台无人机上、在三个典型避障场景里做实测的记录有完整数据也有我在排查和调参过程中踩过的坑希望能给正在选型的你一个参考。1. 为什么避障场景下选SLAM比选定位算法更复杂先说一个很多人容易忽略的点避障场景里的SLAM本质上不是在做定位比赛而是在给一个实时闭环系统供血。避障算法需要的不是一个偶尔很准的位姿而是一个能持续、平滑、低延迟输出的位姿源以及一定程度的局部环境感知能力。所以评估VINS和ORB-SLAM3不能用论文里的ATE绝对轨迹误差一刀切要看它们在具体飞行任务中的整体表现。1.1 避障任务里SLAM到底扮演什么角色无人机避障通常分两层一层是全局或者局部的路径规划另一层是底层的位置控制和障碍物规避。这两层都依赖SLAM提供的东西。位置控制需要稳定的位姿估计频率和延迟直接决定飞控能不能跟上。障碍物感知则需要SLAM提供局部地图或者至少提供相机坐标系到机体坐标系的准确变换让避障算法能把点云、深度图投影到正确位置。在这个链路里SLAM的一个短暂卡顿轻则让无人机急停重则直接触发飞控的保护性着陆。尤其要注意的是很多避障算法和SLAM是解耦的SLAM只负责位姿和稀疏特征点输出障碍物检测靠另外的传感器比如深度相机或者激光雷达。这种架构下SLAM输出的位姿平滑度、时间戳稳定性和坐标系标定精度反而比最终的全局轨迹精度更影响避障效果。1.2 我的测试平台硬件基线为了保证对比公平我在同一套硬件上切换两个算法不换传感器不改机架。平台配置如下机架350mm轴距四旋翼总重约1.8kg计算平台NVIDIA Jetson Xavier NX8GB版本功耗模式设为15W相机全局快门双目相机分辨率640x480帧率30fps基线12cmIMU机载BMI088频率200Hz与相机硬同步飞控Pixhawk 6CPX4固件通过MAVROS与机载计算机通信ROS版本Ubuntu 20.04 ROS Noetic这套配置在小型无人机里比较有代表性不算顶配但也不是入门级。性能数据在Xavier NX上的表现基本能代表目前主流机载平台的算力水平。2. 部署环节的差异ORB-SLAM3的编译和VINS-Fusion的bag复现部署看起来是体力活但实际上一半的坑都埋在这里。两个系统我都完整部署过可以说一个偏工程繁琐一个偏参数敏感。2.1 ORB-SLAM3在Ubuntu 20.04上的完整编译链路ORB-SLAM3的依赖包括Pangolin、OpenCV、Eigen3、DBoW2、g2o其中DBoW2和g2o在仓库里自带需要在编译主项目前先编译。我在Ubuntu 20.04上遇到的第一个坑是Pangolin版本兼容性直接用主分支最新版编译ORB-SLAM3时会出现variant相关的API报错因为Pangolin 0.8之后改了部分接口。解决办法是锁定Pangolin到v0.6版本然后按这个顺序操作# 编译Pangolin v0.6 git clone --branch v0.6 https://github.com/stevenlovegrove/Pangolin.git cd Pangolin mkdir build cd build cmake .. make -j$(nproc) sudo make install # 编译ORB-SLAM3 cd ~/ORB_SLAM3 ./build.sh编译过程中还遇到一个常见问题OpenCV 4.x下CV_LOAD_IMAGE_UNCHANGED被移除会报useCV_LOAD_IMAGE_UNCHANGED was not declared。解决方式是全局替换为cv::IMREAD_UNCHANGED或者直接在头文件里加一个宏兼容。另外要提醒的是build.sh里默认的make线程数是make -j在Xavier NX上内存只有8GB不小心会把内存吃满导致编译进程被杀。我改成make -j2才稳定跑完。这个细节对Orin Nano、树莓派这类嵌入式平台同样适用。2.2 VINS-Fusion的bag文件复现与参数校准VINS-Fusion的部署相对顺滑依赖主要是Ceres Solver和Eigen。Ceres建议从源码编译Ubuntu 20.04的apt源自带版本是1.14Google的官方realease已经是2.1虽然都能用但建议用1.14稳定版踩坑文档多一些。跑通bag文件很简单官方仓库提供了euroc数据集示例但我很快发现一个问题直接用EUROC的bag测试和真实上机是两个世界。EUROC是工业相机加高精度IMU噪声参数和消费级/准工业级传感器差很多。我在Xavier NX上用自己的双目标定数据跑VINS-Fusion如果直接沿用EUROC的噪声参数会有明显的z轴漂移。VINS-Fusion的IMU噪声参数主要在配置文件的imu_noise节包括acc_n: 0.02 acc_w: 0.0004 gyr_n: 0.004 gyr_w: 0.0003这些值要按实际IMU的Allan方差标定结果填不能照搬。BMI088的噪声水平比EUROC的IMU差一到两个数量级需要把acc_n和gyr_n适当调大否则优化器会过于信任IMU导致视觉约束被权重稀释。2.3 两种系统的输入传感器使用策略ORB-SLAM3我使用的是双目模式不启用IMU这是它最稳定的模式。ORB-SLAM3的视觉惯性模式需要处理IMU初始化在快速启动场景下容易初始化失败反而影响对比公平性。VINS-Fusion我使用的是双目IMU紧耦合模式这是它的主力模式。这里也有一个对比上的差异ORB-SLAM3理论上也支持双目IMU但在我的多次测试中它的视觉惯性模式在机载平台的稳定性不如纯双目所以最终选择了纯双目模式。这个差异本身也能说明一些问题。3. 避障实测方案三条航线、五种指标测试场景的选取很关键。我盯着三个真实避障中最常遇到的难点弱纹理、光照突变、高速机动。设计的三条航线每条都对应一种典型失效模式。3.1 三条测试航线的设计思路场景A室内走廊弱纹理避障一条长约25米的室内走廊墙面是白色乳胶漆地面是浅色瓷砖走廊中间摆放三个纸箱作为障碍物。这个场景的特点是特征明显不足大面积白墙、低纹理地面、统一光照。测试动作为无人机以0.8m/s的速度沿走廊飞行遇到纸箱需要绕行绕行后回到中线继续飞。这个场景考验的是SLAM在特征稀疏条件下的连续工作能力。场景B室外树荫广场光照变化一片有树荫和阳光斑驳的广场地面是砖石四周有树木和建筑。无人机以1.0m/s速度飞行人为规划一条会穿过明暗交界区的路线并放置两个锥桶避障。这个场景的特点是高对比度光照变化阳光直射区域和树荫区域的曝光差异很大容易导致特征提取数量剧烈波动。考验的是SLAM在图像质量动态变化下维持位姿的能力。场景C高速绕柱机动避障在室外空地上立一根直径30cm的柱子无人机围绕柱子在1.5m半径上以3m/s切向速度绕圈飞行绕两圈后切出。这个场景包含持续的大角速度旋转和快速视差变化对特征跟踪是极致压力测试。绕柱机动在很多实际避障场景中都会出现比如躲避障碍物后的盘旋重新扫描环境非常考验SLAM的运动鲁棒性。每个场景重复飞行5次取中位数作为最终结果避免单次偶然误差。3.2 评价指标延迟、漂移、丢失频率与避障成功率对比两个SLAM在避障中的表现我选了五组指标指标采集方式为什么针对避障ATE RMSE绝对轨迹误差用动捕系统提供真值通过evo工具对齐评估反映全局定位精度但仅作参考前端跟踪耗时ROS节点打印时间戳差值直接决定位姿输出频率上限位姿丢失次数人工标注跟踪状态变为Lost的次数丢失意味着避障算法短时间没有可靠输入局部位姿平滑度计算相邻两帧位姿变化量的抖动幅度影响实时避障机动是否顺滑任务成功率5次重复飞行中完整避障通过的次数端到端结果最真实我认为丢失次数和局部平滑度在避障场景比ATE更重要。一个全局精度0.05m但偶尔丢帧的系统未必比全局精度0.15m但全程不丢帧的系统更适合避障。3.3 评测数据总表先把最终数据放上来后面逐个拆解。指标场景A室内走廊场景B室外树荫场景C高速绕柱VINS ATE RMSE0.13m0.19m0.29mORB-SLAM3 ATE RMSE0.10m0.13m0.41m丢失前段VINS 位姿丢失次数0次/5次试验1次/5次试验0次/5次试验ORB-SLAM3 位姿丢失次数3次/5次试验0次/5次试验4次/5次试验VINS 平均前端耗时27ms25ms31msORB-SLAM3 平均前端耗时38ms35ms42msVINS 避障任务成功率90%45/5078%39/5082%41/50ORB-SLAM3 避障任务成功率71%35/5087%44/5054%27/50成功率是单次飞行算一个成功率相当于50次尝试的成功统计。数据整体趋势很明显ORB-SLAM3在光照条件好的室外场景精度占优VINS在机动和弱纹理场景下鲁棒性更强。4. 实测数据深度拆解不同场景下的表现差异数据摆出来之后重点是怎么解读。如果只看ATE很容易得出ORB-SLAM3精度更好的结论。但放在避障任务里这个结论需要打折扣。4.1 室内走廊弱纹理场景特征不够用的时候IMU能续命在这个场景里ORB-SLAM3的轨迹精度看起来不错——0.10m的ATE比VINS的0.13m还好。但实际飞行感受完全不同。ORB-SLAM3优化后的位姿是准确的但它在特征稀疏时经常进入跟踪减弱状态。白色走廊墙壁能提取的特征点数量波动极大从100多个骤降到20多个导致跟踪线程为了提高鲁棒性而降低位姿输出频率甚至短暂报告丢失。VINS则完全不同因为IMU参与紧耦合优化即便视觉特征数量骤降前端依然能通过IMU积分维持位姿预测。实测中VINS在走廊场景的位姿输出频率稳定在18-20Hz左右而ORB-SLAM3则会周期性掉到8Hz以下。对避障算法来说位姿输出频率骤降是比精度略差更致命的问题。局部规划器在8Hz输入下相当于每次只能看一小段未来很多情况下只能选择急停。这也是VINS避障成功率90%对比ORB-SLAM3的71%的核心原因。ORB-SLAM3不是精度不够而是输出的连续性不够。4.2 室外树荫光照场景ORB-SLAM3的回环能力扳回一局室外场景是ORB-SLAM3的高光时刻。树荫和阳光交替导致的曝光变化对直接法或者半直接法SLAM很不友好但对特征点法来说光照变化只是让特征匹配的阈值偶尔变严整体影响不大。在这个场景里ORB-SLAM3的0.13m ATE明显优于VINS的0.19m。更关键的是ORB-SLAM3的回环检测能力在室外环境得到充分发挥当无人机绕着一个区域飞过后回环帧被检测到全局图优化会显著修正累积漂移。VINS也有回环检测但它的回环是基于DBoW2词袋和紧耦合重定位在光照变化的条件下回环检测的召回率更高之余误检率也会上升。实测中VINS在这个场景有一次误触发回环导致位姿发生一次小幅跳变位置突变约0.3m造成了避障路径的一个急转弯。避障任务成功率上ORB-SLAM3以87%反超。这说明在光照变化明显的室外开阔区域ORB-SLAM3的全局一致性优势能直接转化为避障稳定性尤其是有回环机会的重复飞行场景。如果只跑一条直线航线这个优势不会那么明显但避障任务经常需要重复扫描一个区域回环修正累积漂移的价值就在这里体现。4.3 高速绕柱机动场景快速旋转是特征点法的软肋这个场景的差距最大也是最有参考价值的。绕柱飞行时相机持续进行大角速度旋转特征点在图像中的位移速度快容易出现以下问题特征点跟踪时搜索半径不够导致大量特征丢失。连续帧之间的视差变化大RANSAC剔除外点时容易把有效特征也过滤掉。平移分量小、旋转分量大时三角化精度下降地图点的不确定性增加。ORB-SLAM3在这个场景平均每5次实验丢失2次以上两次丢失时往往伴随几秒钟的位姿静止或漂移之后依赖重定位恢复。虽然重定位后的ATE整体还是能算出来0.41m但这个数据已经失去了代表意义因为它包含了多次丢失-恢复导致的突变。VINS在同样的机动下表现稳定得多关键是IMU预积分提供的旋转增量与视觉数据相互校验。当视觉特征位移过大时IMU的角速度积分可以给特征匹配提供一个很好的初始预测让跟踪线程在正确的区域内搜索特征点而不是在全图范围内暴力匹配。实测VINS在3m/s的绕柱飞行中前端耗时从正常的25ms上升到31ms但依然没有丢。避障任务成功率82%对54%差距显著。这组对比说明一个本质问题在机动场景中纯视觉的帧间跟踪存在速度上限IMU的预测能力能让VINS突破这个上限一部分。4.4 从避障决策链路看延迟差异避障决策链路里还有一个非常关键的指标SLAM输出位姿到避障算法拿到数据之间的延迟。实测两个系统的延迟构成不同。VINS-Fusion的延迟主要在前端跟踪紧耦合优化。同时IMU的前向传播可以实现位姿预测也就是在视觉帧之间输出高频率位姿预测。飞行控制层可以以100Hz的频率拿到VINS的预测位姿视觉帧率对应的优化结果则以20Hz频率更新。ORB-SLAM3的延迟结构不同它的跟踪线程输出相对快但局部建图线程的优化和关键帧处理可能阻塞跟踪输出尤其在特征数量多的场景跟踪线程和局部建图线程之间的锁竞争会导致周期性的位姿等待。在Jetson Xavier NX上实测ORB-SLAM3的完整位姿输出延迟从图像采集到避障算法收到消息平均为38ms而VINS-Fusion为29ms。这个数据在50ms级的飞控环路中占据了可观的比例延迟每增加10ms无人机在3m/s下的位置超调就会增加3cm这对绕柱等精细机动项目来说差异就会明显放大。5. 为什么定位精度接近避障效果却差这么多很多人在对比SLAM时只盯着轨迹精度但在实际避障任务中还有三个隐形指标发挥着决定性作用。5.1 地图输出的可用性差异避障算法不仅需要位姿还需要局部环境感知能力。VINS维护了一个滑动窗口的局部地图内部包含数百个视觉特征点和它们的三维坐标。这些特征点虽然稀疏但可以通过ROS话题直接输出避障算法拿到后可以拼出一个局部点云。在我的实践中VINS输出的特征点云足以用来做简单的障碍物聚类和碰撞锥检测。ORB-SLAM3也可以输出地图点但它的地图点管理策略是全局的、包含所有历史关键帧的地图点。在避障算法中直接使用这份地图存在一个问题地图点属于全局坐标系且包含了大量当前视野外或者远处的历史点需要额外的过滤才能用于局部避障。另外ORB-SLAM3的输出频率相比VINS更低因为地图点更新依赖局部建图线程而在快速运动时局部建图线程往往来不及更新。避障算法拿到的还是几帧之前的地图点可能导致障碍物位置估计滞后。这个差异在集成时感受非常明显VINS几乎可以直接把特征点云和位姿一起送给避障模块而ORB-SLAM3则需要额外做坐标系变换、地图点裁剪和时间对齐工程成本高了不少。5.2 位姿输出的平滑度差异我曾尝试用避障算法直接消费两个SLAM的位姿输出观察机体响应情况。差别非常显著。VINS-Fusion因为紧耦合了IMU相邻视觉帧之间的位姿估计过渡平滑几乎不会出现单帧跳变。这让基于位姿的规划算法输出的速度指令很平滑无人机姿态变化柔和。ORB-SLAM3在纯双目模式下相邻帧之间的位姿则偶尔会出现几个厘米的微小跳变尤其在场景切换或者快速旋转时。这些跳变在可视化里看起来不大但进入飞控的PID环路后会被微分项放大产生小幅的机体抖动。更麻烦的是ORB-SLAM3在关键帧切换时偶尔会触发一次局部优化修正导致位姿产生一次30-50cm的阶跃如果局部地图调整幅度大。对正在近距离绕障的无人机来说这种阶跃几乎等于一次撞击信号——避障算法会误判为即将碰撞然后触发急刹。5.3 坐标系与TF链对集成的影响最后是一个纯工程问题两个系统的坐标系定义不同导致避障集成时的工作量不同。VINS-Fusion有完整的camera→body→world坐标变换输出且为IMU和相机准备了完整的外参标定流程。它的输出消息里自带姿态四元数和位置向量可以直接喂给MAVROS或者飞控。ORB-SLAM3的输出在单目模式下是尺度不确定的即使双目模式也需要设置Scale参数。ORB-SLAM3不直接输出odometry类型的标准消息需要通过Tracking节点的位姿回调自己封装。另外ORB-SLAM3的坐标系定义是世界坐标系的Y轴指向上方而飞控常见的坐标系如ENU或NED需要额外的旋转变换。这些坐标系转换在写代码时都是几个矩阵乘法的事但在无人机这种实时系统里每一个额外的变换步骤都是引入bug和时间戳错位的风险点。我实测中遇到过多次ORB-SLAM3的位姿时间戳跳变导致TF树短暂断裂、避障模块拿不到位姿的情况。VINS-Fusion在这方面就省心很多。6. 上机调参踩坑记录与最终选型建议数据说完了聊聊更贴近实际的东西我在这套系统里做了哪些调参遇到过哪些坑最后怎么选。6.1 ORB-SLAM3在Jetson平台上的性能调优ORB-SLAM3在Xavier NX上的前端耗时一度达到42ms以上严重拖后腿。经过一番排查发现主要瓶颈在ORB特征提取环节。默认参数下ORB-SLAM3会对图像金字塔的每一层提取最多1000个特征点这个数量在桌面级GPU上不是问题但在只有8GB内存和有限CUDA核心的Xavier NX上CPU端的ORB提取成了大头。我的优化办法是修改ORB-SLAM3的主配置文件中ORBextractor.nFeatures原值1000调整后600同时把金字塔缩放因子从1.2改成1.1减少金字塔层数降低计算量。实测调整后前端耗时从42ms降到35ms丢点率没有明显上升避障成功率反而因为位姿输出更及时而略有提升。对机载平台来说特征数量不是越多越好够用就行。另外建议关闭ORB-SLAM3的Viewer可视化线程这个线程在显示界面时会占用约15%-20%的CPU资源。我把显示改成在PC端远程rqt查看机载端只保留算法节点性能提升非常明显。6.2 VINS-Fusion的IMU外参标定和噪声参数VINS-Fusion对IMU与相机之间的外参误差非常敏感。我在初期调试时没有做完整的相机-IMU标定直接用厂家给的标称值导致启动后前10秒的VIO初始化经常失败或者初始化的位姿姿态角偏了5度以上。正确的做法是用Kalibr工具对双目相机和IMU做联合标定生成cam0、cam1和imu之间的外参关系。Kalibr跑完之后会生成一个包含T_cam_imu的标定文件把它替换到VINS-Fusion的配置文件里。另外IMU噪声参数也要按实测的Allan方差去填。一个很典型的错误是把EUROC数据集对应的低噪声IMU参数直接复制到自己的传感器上。BMI088的噪声水平比工业级IMU高不少如果照抄参数VINS的视觉权重会被不当地降低表现为漂移增大。My做法是先录制一段静止数据跑Allan方差分析得到三个轴的噪声密度用这个数据去填配置文件。调整完之后VINS的室内走廊场景的z轴漂移从0.2m降低到了0.08m效果立竿见影。6.3 遇到过的固定频率bug与解决记录VINS-Fusion在跑bag文件时有一个经典问题rosbag play的回放频率和相机硬同步的stamp对不上时会出现大量image time gap警告并且VIO状态会反复在两个模式之间跳变。原因是因为bag里面的图像时间戳和IMU时间戳的同步关系与配置文件里IMU_TOPIC、IMAGE_TOPIC的时间戳不是完全对齐。解决方法是录制bag文件时用rosbag record --clock或者确保录制时使用传感器硬件时间戳回放时用--clock参数配合VINS-Fusion的use_imu_time参数。这样跑出来的结果才有参考价值。如果发现VINS跑bag文件时在同一个位置反复初始化大概率是时间戳同步问题不是算法问题。ORB-SLAM3上机时遇到的问题比较直接它默认的RGB相机模型是BGR通道顺序而很多双目相机输出的是RGB排列的彩色图像会导致颜色特征匹配异常。在配置文件中检查Camera.type和Camera.RGB参数是必备步骤。6.4 我的最终选型建议经过完整的对比测试我的选型逻辑可以总结为一张决策参考表场景特点推荐方案理由室内弱纹理、悬停、慢速巡航VINS-FusionIMU紧耦合能支撑特征匮乏的情况室外开阔、有重复巡视需求ORB-SLAM3回环能力强全局一致性好高速机动、绕障、快速转弯VINS-Fusion视觉惯性预测能力保证不丢需要局部稀疏点云做障碍物聚类VINS-Fusion滑窗机制输出实时局部特征点长时间大范围自主导航建图ORB-SLAM3全局地图和回环维护成熟稳定如果你的避障无人机主要在一个环境里反复飞并且飞行速度不快ORB-SLAM3的全避障精度确实有优势。反过来如果你的任务包含高速机动或者室内无GPS搜索那么VINS-Fusion的鲁棒性和工程集成成本优势会让它成为更务实的选择。我的实际项目最终采用了以VINS-Fusion为主的方案理由很简单避障最重要的是不中断而不是偶尔更精确。我的建议是如果你也在这两个系统里选先复现我的三个测试场景把重点放在丢失次数、位姿平滑度和端到端避障成功率上而不是只比ATE。数据不会骗人你的任务场景会告诉你答案。