ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

无人机视觉SLAM实战:VINS-Fusion从环境搭建到真机飞行全指南

无人机视觉SLAM实战:VINS-Fusion从环境搭建到真机飞行全指南 1. 为什么选择VINS-Fusion做无人机视觉SLAM1.1 视觉SLAM在无人机上的真实需求无人机要在没有GPS信号的室内、林间、隧道或者城市楼宇之间稳定飞行光靠飞控里的IMU和气压计是远远不够的。IMU积分几秒钟就会漂到姥姥家气压计在风场扰动下误差能到好几米。这时候视觉SLAM就成了刚需——用摄像头当眼睛实时估计无人机在空间中的六自由度位姿同时构建环境地图。我最早接触这块是在一个室内巡检项目上飞机要在货架之间穿行GPS完全没信号光流模块在纹理稀疏的白墙前面直接歇菜。试过几套方案之后最终锁定VINS-Fusion原因很简单它把视觉和IMU紧耦合在一起单目、双目、甚至加深度相机都能跑而且在ROS生态里集成度非常高省去了大量造轮子的时间。VINS-Fusion的核心是一个基于优化的滑动窗口估计器。它不像滤波方案那样只维护当前状态而是把最近若干帧的位姿、速度、零偏、特征点深度全部放在一个窗口里联合优化。这样做的好处是精度高、漂移小代价是计算量大一些。不过对于机载计算机来说只要不是跑太高的频率一般都能扛住。1.2 VINS-Fusion相比其他方案的优势市面上视觉SLAM方案不少ORB-SLAM3、OKVIS、MSCKF各有千秋。我选VINS-Fusion主要看中这几点IMU紧耦合视觉和IMU在同一个优化框架里不是松耦合那种各跑各的再融合。这意味着在快速运动、纹理缺失的场景下IMU能撑住短时间的位姿估计视觉恢复后又能把漂移拉回来。多传感器支持单目IMU、双目IMU、双目IMUGPS都能配置后期扩展方便。我现在的项目就是先跑双目IMU后面再加GPS做全局融合。ROS原生支持节点化的设计订阅图像和IMU话题发布里程计和TF跟其他ROS节点配合非常顺滑。回环检测可选虽然VINS-Fusion本身的回环模块不算最强但配合位姿图优化能有效消除累积漂移。当然它也有短板比如对时间同步要求高IMU和图像的时间戳必须对齐否则优化会发散。这个后面会详细讲怎么处理。1.3 整套系统的硬件选型思路无人机视觉SLAM的硬件不是随便凑的每个环节都影响最终效果。我列一下我实际用的配置和选型理由部件型号选型理由机架450mm轴距四轴载重够振动相对小飞控Pixhawk 4社区支持好IMU数据质量稳定机载计算机Jetson Xavier NX算力够跑VINS-Fusion功耗低相机双目全局快门卷帘快门在振动下会畸变全局快门更稳IMU飞控内置ICM-20689先用飞控IMU后期可换外部高精度IMU这里重点说相机。很多人图便宜用USB摄像头结果跑起来图像时间戳抖动严重VINS-Fusion直接报时间同步错误。全局快门相机虽然贵一些但在无人机振动环境下卷帘快门产生的果冻效应会让特征点匹配彻底崩掉。我实测过同样飞行轨迹下卷帘快门的跟踪丢失率是全局快门的3倍以上。2. ROS环境搭建与VINS-Fusion编译踩坑记录2.1 Ubuntu和ROS版本的选择VINS-Fusion官方推荐Ubuntu 18.04 ROS Melodic或者Ubuntu 20.04 ROS Noetic。现在Ubuntu 24.04都出来了但ROS 2的生态跟VINS-Fusion的适配还不算成熟所以稳妥起见还是用ROS 1。我目前主力环境是Ubuntu 20.04 Noetic原因是Noetic是ROS 1的最后一个长期支持版本Python 3原生支持很多新库兼容性更好。如果你手头只有18.04Melodic也能跑但注意Python 2的坑会多一些。安装ROS本身没什么好说的官方教程走一遍就行。但国内网络环境下建议换源否则下载速度能让你怀疑人生。换源之后记得sudo apt update不然后面装依赖会各种找不到包。2.2 依赖库安装的隐藏坑VINS-Fusion依赖Ceres Solver、OpenCV、Eigen这几个核心库。官方文档给的安装命令看起来简单但实际操作中很容易卡在Ceres的编译上。Ceres Solver我建议用源码编译版本选2.0.0或2.1.0。太新的版本可能跟VINS-Fusion的代码有API不兼容太老的又缺少一些优化特性。编译Ceres之前先确认这几个依赖装好sudo apt-get install libgoogle-glog-dev libgflags-dev sudo apt-get install libatlas-base-dev sudo apt-get install libsuitesparse-dev编译Ceres的时候make -j4的并行数别开太大否则内存不够会直接卡死。我试过-j816G内存的机器直接OOM。编译完成后sudo make install然后跑一下官方测试用例确认没问题。OpenCV的话ROS Noetic自带4.2版本一般够用。但如果你要用CUDA加速特征提取就得自己编译带CUDA的OpenCV这个过程比较折腾后面单独说。Eigen用sudo apt install libeigen3-dev就行注意版本要在3.3以上。2.3 VINS-Fusion源码编译与常见报错创建工作空间克隆代码mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src git clone https://github.com/HKUST-Aerial-Robotics/VINS-Fusion.git cd .. catkin_make第一次编译大概率会报错我遇到过的主要有这几类报错一找不到CeresCould not find a package configuration file provided by Ceres这是因为Ceres安装路径没在CMake的搜索路径里。解决办法是在VINS-Fusion的CMakeLists.txt里加一行set(Ceres_DIR /usr/local/lib/cmake/Ceres)或者设置环境变量export Ceres_DIR/usr/local/lib/cmake/Ceres。报错二OpenCV版本冲突ROS自带的OpenCV和系统里手动装的OpenCV版本不一致时编译会报符号冲突。解决办法是在CMakeLists.txt里明确指定OpenCV路径或者用cv_bridge的时候注意版本匹配。报错三Eigen对齐问题error: static assertion failed: YOU_MIXED_MATRICES_OF_DIFFERENT_SIZES这种一般是Eigen版本或者编译选项问题。检查/usr/include/eigen3是否存在以及CMake里是否加了-marchnative。编译通过之后先跑一下EuRoC数据集的示例确认整个pipeline能跑通。这一步很重要别急着上真机先用数据集验证算法和配置没问题。3. 相机与IMU标定精度决定成败3.1 为什么标定是VINS-Fusion的生命线VINS-Fusion的优化目标函数里视觉残差和IMU残差是联合优化的。如果相机内参、相机-IMU外参、时间偏移这些参数不准优化出来的轨迹会直接飘。我见过太多人跳过标定直接跑结果飞机悬停时轨迹画出来是个大圈还以为是算法问题。标定要解决的核心参数有这几类相机内参焦距、主点、畸变系数相机-IMU外参旋转矩阵和平移向量时间偏移相机和IMU的时间戳差值IMU内参零偏、噪声密度、随机游走其中时间偏移最容易被忽略但影响巨大。相机和IMU的时钟不同步哪怕差几毫秒在快速运动时都会导致优化发散。3.2 相机标定的实操细节相机标定用ROS自带的camera_calibration包就行。准备一块棋盘格标定板打印出来贴在平整的板子上注意棋盘格不能有褶皱。标定步骤启动相机节点确认图像话题正常发布运行rosrun camera_calibration cameracalibrator.py指定图像话题和棋盘格参数移动标定板覆盖图像的各个区域包括边缘和角落采集足够多的样本后点击CALIBRATE等待计算完成保存标定结果得到内参矩阵和畸变系数注意标定板移动时要慢且平稳快速移动会导致图像模糊角点检测不准。另外标定时的分辨率要和实际飞行时一致否则内参会不匹配。双目相机还要额外做立体标定得到两个相机之间的外参。这一步用stereo_calibration原理类似但要求两个相机同时看到标定板。3.3 IMU标定与相机-IMU联合标定IMU标定我推荐用imu_utils这个工具它基于Allan方差分析能估计出IMU的噪声密度和随机游走。步骤稍微繁琐需要让IMU静止采集两个小时以上的数据。相机-IMU联合标定用Kalibr这是目前精度最高的方案之一。Kalibr支持多种相机模型和IMU模型能同时估计外参和时间偏移。Kalibr的使用流程准备一个AprilTag标定板打印并测量实际尺寸录制ROS bag包含相机图像和IMU数据配置标定参数文件指定相机模型、IMU模型、标定板参数运行Kalibr等待优化完成检查重投影误差一般要小于0.2像素才算合格提示录制bag时要让相机和IMU充分激励。具体来说就是拿着设备做各种旋转和平移运动每个轴都要激励到。静止不动或者只做一个方向的运动标定结果会不准。标定完成后把结果填入VINS-Fusion的配置文件。配置文件里主要改这几个地方# 相机内参 model_type: PINHOLE camera_name: camera image_width: 640 image_height: 480 distortion_parameters: k1: 0.0 k2: 0.0 p1: 0.0 p2: 0.0 projection_parameters: fx: 0.0 fy: 0.0 cx: 0.0 cy: 0.0 # 相机-IMU外参 extrinsicRotation: !!opencv-matrix rows: 3 cols: 3 dt: d data: [0, 0, 0, 0, 0, 0, 0, 0, 0] extrinsicTranslation: !!opencv-matrix rows: 3 cols: 1 dt: d data: [0, 0, 0] # 时间偏移 td: 0.0这些参数一个都不能马虎尤其是外参的旋转矩阵符号错了整个系统就废了。4. 配置文件逐项拆解与参数调优4.1 配置文件结构总览VINS-Fusion的配置文件分几个大块相机参数、IMU参数、优化参数、回环参数。我拿一个双目IMU的配置举例逐项说明每个参数的含义和调优经验。imu: 1 num_of_cam: 2 imu_topic: /mavros/imu/data image0_topic: /camera/left/image_raw image1_topic: /camera/right/image_raw output_path: /home/user/vins_output cam0_calib: cam0.yaml cam1_calib: cam1.yaml image_width: 640 image_height: 480imu: 1表示启用IMUnum_of_cam: 2表示双目。话题名要跟实际发布的一致否则订阅不到数据。4.2 关键参数的含义与调优feature_tracker相关参数max_cnt: 150 min_dist: 30 freq: 10max_cnt是每帧提取的最大特征点数。太小会导致约束不足太大会增加计算量。我一般设150在Jetson Xavier NX上跑10Hz没问题。min_dist是特征点之间的最小像素距离防止特征点扎堆。freq是跟踪频率跟相机帧率匹配。优化器参数max_solver_time: 0.04 max_num_iterations: 8 keyframe_parallax: 10.0max_solver_time是单次优化的最大时间单位秒。设太小优化不充分设太大会导致实时性下降。max_num_iterations是最大迭代次数。keyframe_parallax是关键帧选择的视差阈值单位像素。视差超过这个值才选为关键帧太小会导致关键帧过多太大又会导致约束不足。IMU参数acc_n: 0.1 gyr_n: 0.01 acc_w: 0.001 gyr_w: 0.0001这四个参数是IMU的噪声密度和随机游走必须用标定结果填入。用默认值也能跑但精度会差很多。4.3 参数调优的实战经验调参这件事没有万能公式但有几个原则先保证跟踪稳定如果特征点经常丢失先调max_cnt和min_dist让跟踪器有足够的特征点可用。再优化精度跟踪稳定后调整优化器参数让位姿估计更平滑。最后考虑实时性如果计算量太大导致掉帧降低max_cnt或者提高keyframe_parallax。我遇到过一个典型问题飞机在快速旋转时轨迹会突然跳变。排查后发现是keyframe_parallax设得太小导致关键帧过于密集优化窗口里全是相似视角的帧约束不够。把它从5调到10之后问题解决。还有一个坑是IMU频率。VINS-Fusion要求IMU频率至少200Hz如果飞控发布的IMU数据只有50Hz优化会不稳定。解决办法是在飞控端提高IMU发布频率或者用外部IMU。5. 从数据集验证到真机飞行的完整链路5.1 用EuRoC数据集跑通全流程真机飞行之前必须先用数据集验证。EuRoC是视觉惯性SLAM的标准数据集包含双目图像和IMU数据还有高精度的真值轨迹。跑EuRoC的步骤roslaunch vins vins_rviz.launch rosrun vins vins_node ~/catkin_ws/src/VINS-Fusion/config/euroc/euroc_stereo_imu_config.yaml rosbag play MH_01_easy.bag跑起来之后RViz里应该能看到特征点跟踪、轨迹、以及当前位姿。如果轨迹跟真值偏差很大说明配置有问题回去检查标定参数。我建议把EuRoC的所有序列都跑一遍观察不同场景下的表现。MH序列是手持设备在房间里慢速运动V1和V2序列有更快的运动和更复杂的光照。全部跑通之后你对系统的性能边界就有数了。5.2 真机部署的硬件连接与时间同步真机部署最大的坑是时间同步。VINS-Fusion要求图像和IMU的时间戳在同一个时钟域下。如果相机和飞控各自用自己的时钟时间偏移会越来越大。解决方案有两种方案一硬件触发。用飞控的定时器输出PWM信号触发相机曝光同时记录触发时刻的IMU时间戳。这样图像和IMU的时间戳天然对齐。缺点是接线复杂需要相机支持外部触发。方案二软件同步。用message_filters做时间戳对齐或者用mavros的时间同步功能。软件同步的精度取决于网络延迟和系统负载一般能做到毫秒级。我目前用的是方案二配合mavros的/mavros/time_reference话题做时间对齐。实测下来悬停时轨迹漂移在厘米级满足室内巡检需求。5.3 飞行测试的注意事项第一次飞行测试千万别直接上自动模式。我的建议是地面测试飞机放在地上螺旋桨不装通电跑VINS-Fusion观察轨迹是否稳定。手持飞机做缓慢运动看跟踪是否正常。悬停测试在开阔场地手动起飞悬停一米高度观察轨迹漂移。如果漂移超过半米检查标定和配置。低速航线悬停稳定后做低速的矩形航线观察转弯时的跟踪表现。高速机动最后再尝试快速运动和急转弯测试系统的极限。注意每次飞行前都要检查bag录制是否正常。VINS-Fusion的输出话题要全部录下来方便事后分析。我习惯录/vins_estimator/odometry、/vins_estimator/path、/vins_estimator/point_cloud这几个话题。飞行中如果发现轨迹突然跳变或者跟踪丢失第一时间切回手动模式。VINS-Fusion的失败恢复能力有限一旦发散很难自动拉回来。6. 常见故障排查与性能优化6.1 跟踪丢失的排查链路跟踪丢失是VINS-Fusion最常见的问题表现是RViz里特征点突然消失轨迹停止更新。排查思路如下第一步检查图像质量。用rqt_image_view看原始图像确认曝光正常、没有严重模糊。如果图像本身有问题算法再强也没用。第二步检查时间同步。用rosbag info看图像和IMU的时间戳确认没有大的跳变。如果时间戳抖动超过10ms优化会不稳定。第三步检查特征点数量。在RViz里看特征点跟踪的可视化如果特征点很少或者分布不均调整max_cnt和min_dist。第四步检查IMU数据。用rqt_plot看IMU的角速度和加速度确认没有异常尖峰。IMU数据有噪声或者断流优化会直接发散。第五步检查外参。如果以上都没问题重新标定相机-IMU外参。外参错误是导致跟踪丢失的隐形杀手。6.2 计算资源优化Jetson Xavier NX的算力有限跑VINS-Fusion的同时还要跑飞控通信、避障等节点。优化计算资源的方法降低图像分辨率从640x480降到320x240计算量减少四倍精度损失可接受。降低特征点数量max_cnt从150降到100跟踪稳定性略降但计算量明显减少。使用GPU加速如果OpenCV编译了CUDA特征提取可以用GPU速度提升明显。优化编译选项CMake里加-O3 -marchnative让编译器充分优化。我实测过在Xavier NX上640x480分辨率、150个特征点VINS-Fusion单帧处理时间约30ms能跑到30Hz。如果降到320x240、100个特征点单帧处理时间降到10ms以内。6.3 长时间飞行的漂移抑制VINS-Fusion是视觉惯性里程计没有全局定位能力长时间飞行必然累积漂移。抑制漂移的方法回环检测VINS-Fusion自带回环模块但需要配置pose_graph节点。回环检测能有效消除累积漂移但计算量大建议在机载计算机上跑。GPS融合如果有GPS信号可以融合GPS做全局约束。VINS-Fusion支持GPS融合配置稍微复杂一些。视觉地标在环境中布置已知位置的视觉地标检测到地标时做重定位。我目前的方案是回环检测GPS融合室内用回环室外用GPS。切换逻辑写在launch文件里根据GPS信号强度自动选择。7. 我踩过的那些坑与实战建议7.1 标定板的选择与使用标定板看起来简单但坑不少。我最早用A4纸打印棋盘格贴在硬纸板上结果纸板不平标定出来的畸变系数完全不对。后来换了铝基板标定板问题解决。AprilTag标定板比棋盘格更好用因为AprilTag的检测更鲁棒对光照和角度不敏感。Kalibr推荐用AprilTag我实测下来确实比棋盘格稳定。标定板尺寸要精确测量误差超过1mm就会影响标定精度。我用游标卡尺量了三次取平均值。7.2 IMU数据的预处理飞控IMU的数据往往带有振动噪声直接喂给VINS-Fusion会导致优化不稳定。预处理方法低通滤波用Butterworth滤波器做低通截止频率设50Hz左右。降采样如果IMU频率太高比如1000Hz降采样到200Hz减少计算量。零偏补偿飞行前做静态零偏估计飞行中实时更新。我在mavros里加了IMU滤波节点效果立竿见影。滤波前轨迹抖动明显滤波后平滑很多。7.3 飞行数据的回放与分析每次飞行后我都会用rosbag play回放数据在RViz里仔细看轨迹和特征点。重点观察转弯时特征点是否丢失快速运动时轨迹是否跳变悬停时轨迹是否漂移发现问题后调整参数重新跑bag对比效果。这种离线调参的方式比真机试错效率高得多。我还写了一个小脚本自动提取bag里的轨迹和真值如果有计算ATE和RPE误差。这样每次调参后能量化评估效果而不是凭感觉。7.4 给新手的几条建议如果你刚开始接触VINS-Fusion我建议按这个顺序来先用EuRoC数据集跑通理解整个pipeline再用自己的相机和IMU录bag做标定用录制的bag离线跑VINS-Fusion调参最后上真机从悬停开始逐步测试别跳步每一步都踩实了再往下走。我见过太多人直接上真机结果炸机了还不知道问题出在哪。另外ROS社区和VINS-Fusion的GitHub issue里有很多有价值的讨论。遇到问题先搜一下大概率有人遇到过类似的情况。最后说一个细节VINS-Fusion的输出话题里/vins_estimator/odometry是里程计/vins_estimator/path是轨迹/vins_estimator/point_cloud是稀疏点云。如果你要做避障或者建图点云话题很有用但注意它是稀疏的不能直接当深度图用。
返回列表