Ubuntu 20.04下PX4与VINS-FUSION深度联调实战:从参数精调到仿真全链路避坑

最近在折腾无人机视觉定位,想把PX4飞控和VINS-FUSION这套视觉惯性里程计系统给打通,在XTDrone仿真环境里跑起来。本以为照着官方教程走一遍就行,结果从环境配置、参数修改到编译运行,踩的坑一个接一个,尤其是Ubuntu 20.04这个特定版本下,一些依赖和配置的细节和旧版本差别不小。这篇文章就是把我这段时间趟过的雷、填过的坑,还有最终跑通的全过程梳理出来,给同样在Ubuntu 20.04上做PX4+VINS-FUSION联调的开发者们一个更清晰、更落地的参考。整个过程涉及PX4的EKF参数调整、VINS-FUSION在Ubuntu 20.04上的编译适配、相机配置的匹配,以及仿真测试中的各种细节处理,目标就是让你能避开我遇到的那些麻烦,更高效地搭建起这套视觉定位仿真测试环境。

1. 环境准备与基础依赖梳理

在开始任何具体操作之前,确保你的Ubuntu 20.04系统有一个干净、兼容的基础环境至关重要。很多后续的编译错误和运行时问题,根源往往在于前期依赖没有装对或者版本冲突。

首先,更新系统并安装一些通用开发工具:

sudo apt update && sudo apt upgrade -y
sudo apt install -y git cmake build-essential curl wget

对于ROS,我们使用Noetic版本,这是官方支持Ubuntu 20.04的ROS发行版。安装过程务必注意网络环境,确保所有包都能正确拉取。

sudo sh -c 'echo "deb http://packages.ros.org/ros/ubuntu $(lsb_release -sc) main" > /etc/apt/sources.list.d/ros-latest.list'
sudo apt-key adv --keyserver 'hkp://keyserver.ubuntu.com:80' --recv-key C1CF6E31E6BADE8868B172B4F42ED6FBAB17C654
sudo apt update
sudo apt install -y ros-noetic-desktop-full

安装完成后,别忘了把ROS环境变量加到你的bashrc里,并初始化rosdep。

echo "source /opt/ros/noetic/setup.bash" >> ~/.bashrc
source ~/.bashrc
sudo rosdep init
rosdep update

接下来是PX4开发环境的搭建。PX4官方推荐使用其提供的安装脚本,但这里我建议手动安装一些关键组件,以便更好地控制版本,尤其是后面会遇到的empy版本问题。

# 安装Gazebo仿真器 (版本要与ROS Noetic匹配)
sudo apt install -y gazebo11 libgazebo11-dev

# 安装PX4所需的工具链
sudo apt install -y python3-pip python3-dev python3-wheel
# 注意:这里先不安装empy,我们后面会专门处理它
sudo apt install -y ninja-build exiftool

# 安装MAVROS,这是PX4与ROS通信的桥梁
sudo apt install -y ros-noetic-mavros ros-noetic-mavros-extras
# 安装地理信息数据库
wget https://raw.githubusercontent.com/mavlink/mavros/master/mavros/scripts/install_geographiclib_datasets.sh
sudo bash ./install_geographiclib_datasets.sh

注意:Ubuntu 20.04的软件源中,empy的默认版本可能是4.x,而PX4的某些构建脚本与新版empy存在兼容性问题。这是后续编译失败的一个常见原因,我们先记下,后面会专门解决。

2. PX4固件配置与EKF参数深度解析

PX4的扩展卡尔曼滤波器(EKF2)是其状态估计的核心。当我们要从GPS定位切换到纯视觉定位时,必须正确配置EKF2的传感器融合策略。这一步如果错了,飞控根本无法正确理解VINS-FUSION提供的位姿信息。

首先,获取PX4固件源码。建议使用稳定版本,以减少未知错误。

cd ~
git clone https://github.com/PX4/PX4-Autopilot.git --recursive
cd PX4-Autopilot
# 切换到稳定的发布分支,例如v1.13.x
git checkout v1.13.3
git submodule update --init --recursive

关键点来了:修改EKF2的辅助数据源配置。我们需要告诉EKF2,主位置信息源不再是GPS,而是视觉里程计(VIO),同时高度信息也由视觉/气压计融合提供。

对于PX4 v1.13及以上版本,参数修改的方式与旧版不同。直接修改ROMFS中的启动脚本(rcS)在编译后可能不生效,因为构建系统会生成最终的文件。更可靠的做法是修改构建目录下的文件,或者通过启动后发送参数命令。但为了在仿真开始时即生效,我们采用修改构建后文件的方法:

  1. 首先,进行一次初始编译以生成必要的文件结构:

    make px4_sitl_default gazebo
    

    首次编译会花费较长时间,编译完成后按Ctrl+C退出。

  2. 定位到构建目录下的rcS文件进行修改:

    gedit ~/PX4-Autopilot/build/px4_sitl_default/etc/init.d-posix/rcS
    

    在文件中找到与EKF2辅助数据源和高度源相关的参数设置部分。通常,你需要将EKF2_AID_MASK参数设置为24,这表示启用视觉位置和视觉偏航融合,同时禁用GPS。将EKF2_HGT_MODE参数设置为3,表示将视觉信息作为主要高度参考源。

    # 注释掉或替换原有的GPS设置
    # param set EKF2_AID_MASK 1
    param set EKF2_AID_MASK 24
    
    # 注释掉或替换原有的高度源设置
    # param set EKF2_HGT_MODE 0
    param set EKF2_HGT_MODE 3
    

提示:EKF2_AID_MASK是一个位掩码参数。值1代表GPS,24是8(视觉位置)和16(视觉偏航)的和。EKF2_HGT_MODE中,0是气压计,3是视觉。理解这些数字背后的含义,有助于你在调试时根据实际情况进行调整。

修改完成后,强烈建议清除PX4的旧参数缓存,以防止残留配置干扰新的视觉定位模式:

rm -rf ~/.ros/eeprom/parameters*
rm -rf ~/.ros/sitl*

这个操作相当于重置了仿真的飞控参数,确保每次启动都从我们修改后的rcS文件加载配置。

3. VINS-FUSION在Ubuntu 20.04上的编译与适配

VINS-FUSION的官方代码主要针对ROS Kinetic(Ubuntu 16.04)和Melodic(Ubuntu 18.04)进行过测试。在Ubuntu 20.04 (ROS Noetic)上直接编译,大概率会遇到各种依赖库版本和编译器标准不兼容的问题。我们需要进行一些针对性的修改。

首先,创建工作空间并获取代码。这里我们使用XTDrone中提供的VINS-FUSION版本,它通常已经包含了一些实用的启动脚本。

mkdir -p ~/catkin_ws/src
cd ~/catkin_ws/src
# 假设你已经克隆了XTDrone仓库到~/XTDrone
cp -r ~/XTDrone/sensing/slam/vio/vins-fusion ./
cd ..

接下来是解决编译问题的核心步骤。问题通常集中在几个方面:

  • OpenCV版本:Ubuntu 20.04默认安装OpenCV 4,而VINS-FUSION代码可能基于OpenCV 3编写。需要修改CMakeLists.txt和源代码中的头文件引用。
  • C++标准:部分代码可能需要指定更高的C++标准(如C++14)。
  • 依赖包:确保所有ROS依赖包都已安装。

步骤一:修改CMakeLists.txt 进入vins-fusion的各个子目录(如vins_estimator, loop_fusion),修改其CMakeLists.txt文件。

  1. 将find_package(OpenCV REQUIRED) 修改为 find_package(OpenCV 4 REQUIRED),并明确链接OpenCV的组件,例如:
    find_package(OpenCV 4 REQUIRED COMPONENTS core highgui imgproc imgcodecs calib3d)
    
  2. 确保C++标准设置正确,在add_executable之前添加:
    set(CMAKE_CXX_STANDARD 14)
    set(CMAKE_CXX_STANDARD_REQUIRED ON)
    

步骤二:修改源代码中的OpenCV引用 在vins_estimator和loop_fusion的src目录下,搜索.cpp文件,将类似#include <opencv2/opencv.hpp>的通用头文件,替换为更具体的头文件,例如:

// 替换前
#include <opencv2/opencv.hpp>
// 替换后
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/calib3d.hpp>
#include <opencv2/imgcodecs.hpp>

同时,检查代码中是否使用了OpenCV 3中已弃用、在OpenCV 4中移除的常量或函数(如CV_LOAD_IMAGE_GRAYSCALE应改为cv::IMREAD_GRAYSCALE)。

步骤三:安装特定依赖 确保安装了ceres-solver。Ubuntu 20.04仓库中的版本可能足够。

sudo apt install -y libceres-dev

步骤四:编译 完成上述修改后,尝试编译:

cd ~/catkin_ws
catkin_make -DCMAKE_BUILD_TYPE=Release

如果遇到未定义的引用错误,通常是链接库缺失,根据错误信息安装对应的-dev包即可。

步骤五:配置相机话题 编译成功后,需要根据你的仿真模型配置VINS-FUNSION的启动文件。关键文件是~/catkin_ws/src/vins-fusion/config/euroc/euroc_config.yaml(或其他你使用的配置文件)。 你需要修改其中的话题名称,使其与Gazebo仿真中发布的图像和IMU话题匹配。例如,使用XTDrone的iris_stereo_camera模型时,配置可能如下:

imu_topic: "/iris_0/mavros/imu/data_raw"
image0_topic: "/iris_0/stereo_camera/left/image_raw"
image1_topic: "/iris_0/stereo_camera/right/image_raw"
output_path: "/home/你的用户名/catkin_ws/vins_output"

务必确认image0_topic和image1_topic与你在Gazebo中看到的左右相机话题名称完全一致,可以通过rostopic list命令来查看。

4. XTDrone仿真环境集成与相机模型匹配

XTDrone提供了一个很好的集成化仿真测试框架,但其中的相机配置文件与默认的PX4 Gazebo模型可能不完全匹配,这会导致VINS-FUSION收不到图像数据。

首先,确保你正确克隆并设置了XTDrone。

cd ~
git clone https://github.com/robin-shaun/XTDrone.git
cd XTDrone
bash setup.sh

核心问题在于:XTDrone的示例启动文件(如indoor1.launch)可能指定了一个特定的无人机模型(例如iris),而这个模型在Gazebo中可能没有搭载你所需要的双目相机传感器。因此,VINS-FUSION订阅的图像话题自然是空的。

解决方案是使用一个预定义了双目相机的无人机模型。XTDrone的models目录下通常有iris_stereo_camera或iris_realsense这样的模型。后者不仅包含双目相机,还有深度相机,更适合视觉SLAM测试。

你需要修改你的仿真启动脚本或launch文件。例如,创建一个自定义的启动脚本my_vio_test.sh:

#!/bin/bash

# 启动Gazebo世界和带有双目相机的无人机模型
gnome-terminal --tab --title="Gazebo" -- bash -c "source ~/catkin_ws/devel/setup.bash; roslaunch px4 indoor1.launch vehicle:=iris_stereo_camera; exec bash"

sleep 15 # 等待Gazebo和PX4完全启动

# 启动MAVROS,连接Gazebo中的PX4实例
gnome-terminal --tab --title="MAVROS" -- bash -c "source ~/catkin_ws/devel/setup.bash; roslaunch mavros px4.launch fcu_url:="udp://:14540@127.0.0.1:14557"; exec bash"

sleep 5

# 启动VINS-FUSION
gnome-terminal --tab --title="VINS" -- bash -c "source ~/catkin_ws/devel/setup.bash; roslaunch vins vins_rviz.launch config_path:=/home/你的用户名/catkin_ws/src/vins-fusion/config/euroc/ euroc_config.yaml; exec bash"

sleep 5

# 启动VINS-FUSION的另一个节点(如闭环检测)
gnome-terminal --tab --title="Loop Fusion" -- bash -c "source ~/catkin_ws/devel/setup.bash; rosrun loop_fusion loop_fusion_node /home/你的用户名/catkin_ws/src/vins-fusion/config/euroc/euroc_config.yaml; exec bash"

这个脚本的关键在于vehicle:=iris_stereo_camera参数,它确保了Gazebo加载的是带有双目相机的模型。

5. 常见编译与运行时问题排查

即使按照上述步骤操作,你可能还是会遇到一些棘手的问题。这里汇总了几个最典型的坑及其解决方案。

问题一:PX4编译时出现empy相关错误 错误信息可能类似于“TypeError: ‘module’ object is not callable”。这是因为PX4构建系统调用的empy版本不兼容。

  • 排查:首先检查已安装的empy版本:pip3 list | grep empy。如果版本是4.x,很可能就是它导致的。
  • 解决:卸载新版,安装兼容的3.x版本。
    pip3 uninstall empy
    pip3 install 'empy==3.3.4'
    
    之后,彻底清理PX4的构建目录,再重新编译:
    cd ~/PX4-Autopilot
    make clean
    make px4_sitl_default gazebo
    

问题二:VINS-FUSION编译时遇到关于cv_bridge的错误 错误可能提示找不到cv_bridge或与OpenCV版本冲突。这是因为cv_bridge需要与你使用的OpenCV版本匹配。

  • 解决:确保你安装了ROS Noetic版本的cv_bridge,它默认链接OpenCV 4。
    sudo apt install -y ros-noetic-cv-bridge
    
    在VINS-FUSION的CMakeLists.txt中,find_package部分应包含cv_bridge:
    find_package(catkin REQUIRED COMPONENTS
      roscpp
      std_msgs
      geometry_msgs
      sensor_msgs
      cv_bridge
      ...
    )
    

问题三:仿真启动后,VINS-FUSION没有输出轨迹,RVIZ中看不到点云 这是一个综合性问题,需要按顺序排查:

  1. 话题检查:分别打开几个终端,用rostopic list和rostopic hz /topic_name命令检查。
    • /iris_0/stereo_camera/left/image_raw 和 /iris_0/stereo_camera/right/image_raw 是否有数据?
    • /iris_0/mavros/imu/data_raw 是否有数据?
    • /vins_estimator/odometry 和 /vins_estimator/path 是否被发布?
  2. 相机信息:VINS-FUSION需要相机内参。检查你的配置文件(如euroc_config.yaml)中的cam0和cam1内参矩阵、畸变系数是否正确。对于Gazebo中的标准相机模型,你可能需要使用标定工具获取参数,或使用一个合理的近似值。
  3. 时间同步:确保图像话题和IMU话题的时间戳是同步的。在Gazebo中,检查仿真时间是否正常推进。有时可以通过设置use_sim_time参数为true来解决。
  4. EKF状态:在QGroundControl或通过MAVLink命令行工具连接PX4,检查EKF2_AID_MASK和EKF2_HGT_MODE参数是否确实被设置为了24和3。有时参数写入可能失败。

问题四:VINS-FUSION输出轨迹漂移严重,或无人机在Gazebo中剧烈晃动 这通常说明VINS-FUSION估计的位姿与PX4的期望不匹配,或者传感器数据质量有问题。

  • 检查IMU数据:Gazebo默认提供的IMU数据可能过于“理想”,噪声和偏置设置不当。可以尝试修改无人机SDF模型文件,为IMU插件添加更真实的噪声参数。
  • 调整VINS参数:VINS-FUSION配置文件中有大量可调参数,如加速度计和陀螺仪噪声密度、视觉特征点提取数量等。针对仿真环境,可能需要降低某些噪声值,或调整特征点数量。
  • 检查相机帧率:确保Gazebo中相机传感器的发布频率(如30Hz)与VINS配置文件中的image0_topic和image1_topic的期望频率相匹配。

整个联调过程就像是在解一个多环相扣的谜题,任何一个环节的配置偏差都可能导致最终失败。我的经验是,保持耐心,使用rostopic echo、rqt_graph、rqt_console这些ROS工具进行细致的诊断,从数据流的最源头(Gazebo传感器话题)开始,一步步向后追踪,直到VINS-FUSION的输出和PX4的响应。当你在RVIZ中看到稳定的绿色轨迹点云,并且无人机能跟随你的指令平稳飞行时,之前所有的调试努力就都值得了。

更多推荐