本章将在机载电脑(树莓派 5)上部署 OpenVINS 双目视觉惯性里程计(VIO),使无人机能够在无 GPS 的室内或复杂环境中获取精准的三维空间坐标。
部署完成后,VIO 输出的位姿定位数据将通过 MAVROS 回传给飞控 EKF(Extended Kalman Filter,扩展卡尔曼滤波器),替代传统的光流传感器,作为主要的位置估算源,从而实现无人机高精度的室内自主定位悬停与飞行任务。
完成本章的部署与测试后,MVD35 应达到以下状态:

VIO(Visual-Inertial Odometry,视觉惯性里程计)通过融合高频的惯性测量单元(IMU)数据与低频的相机图像来实时估计飞行器的三维位姿(位置和姿态)。
相比于依赖地面纹理且只能测量二维位移的传统“光流+测距”方案,VIO 能够提供完整的六自由度(6-DoF)位姿估计,定位精度更高,且不受低纹理地面、沙地或积水环境的影响,是室内无 GPS 自主飞行的核心技术。
本教程使用 OpenVINS 作为 VIO 算法框架。它是由特拉华大学开发的开源轻量化 VIO 系统,支持多相机配置、IMU 在线标定,并且在树莓派 5 平台上有较好的实时运行效率。
MVD35 VIO 系统数据流向:

1. 传感器数据采集:
2. 状态解算与位姿发布(OpenVINS):
/mavros/vision_pose/pose 话题,由 MAVROS 回传至飞控。3. 飞控 EKF 融合定位:
ℹ️ MVD35 直接使用飞控内置的高质量 IMU 作为惯性源(由 MAVROS 以 200Hz 发布),省去了相机模组额外集成 IMU 的硬件成本,且飞控 IMU 经过物理防震设计,更加适用于无人机飞行场景。
Ceres Solver 是由 Google 开发的高性能开源非线性最小二乘问题求解器。在 OpenVINS 中,用于进行滑动窗口中的状态估计和外参在线标定等核心优化计算。
ℹ️ 为什么需要从源码编译安装?
Ubuntu 24.04 官方源提供的 Ceres 版本为 2.2.0,与 ROS 2 Jazzy 环境下的 Eigen 等库存在接口或版本兼容问题。为确保 OpenVINS 的编译和运行稳定性,本教程选择从源码编译并安装经过兼容性测试的 2.0.0 版本。
3.1.1 确认系统核心组件
lsb_release -a
python3 --version
cmake --version
opencv_version
Release: 24.04
Codename: noble
python3: 3.12.3
cmake: 3.28.3
opencv4: 4.6.0

3.1.2 安装依赖库
sudo apt-get install cmake libgoogle-glog-dev libgflags-dev libatlas-base-dev libeigen3-dev libsuitesparse-dev -y
3.1.3 下载源代码
mkdir -p ~/vio && cd ~/vio
git clone --branch=ceres-2.0.0 https://github.com/Minderring/ceres-solver.git

3.1.4 创建编译环境
cd ceres-solver/
mkdir build && cd build
cmake ..

3.1.5 编译 ceres-solver
make


3.1.6 安装 ceres-solver
sudo make install


3.1.7 验证 ceres-solver 安装版本
grep -E "CERES_VERSION_(MAJOR|MINOR|REVISION)" /usr/local/include/ceres/version.h

ℹ️ 输出以下内容表示安装版本为 2.0.0,Ceres-Solver 安装成功。
#define CERES_VERSION_MAJOR 2
#define CERES_VERSION_MINOR 0
#define CERES_VERSION_REVISION 0
3.2.1 安装依赖库
sudo apt-get install ros-jazzy-ros2bag ros-jazzy-rosbag2* libeigen3-dev libboost-all-dev -y
sudo cp -r /usr/include/eigen3/Eigen /usr/include/
3.2.2 设置交换内存
ℹ️ 为什么需要设置交换内存?
由于选用的机载电脑为树莓派5 4G RAM 版本,在运行编译任务时容易因内存不足导致编译中断。通过设置交换内存,可以有效缓解内存压力,确保编译过程的稳定性。
sudo fallocate -l 4G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile

htop

ℹ️
htop命令可以实时查看系统中各进程的资源使用情况,包含 CPU、内存等。图中Mem和Swp分别表示物理内存和交换内存的使用情况。
3.2.3 下载源代码
mkdir -p ~/vio/openvins_ws/src/ && cd ~/vio/openvins_ws/src/
git clone --branch=micoair-mvd35 https://github.com/Minderring/open_vins.git

ℹ️ micoair-mvd35 分支是微空在官方 OpenVINS 基础上针对 MVD35 平台适配和优化后的版本。
3.2.4 编译 OpenVINS
cd ~/vio/openvins_ws/
MAKEFLAGS="-j1" colcon build --parallel-workers 1 --cmake-args -DCMAKE_BUILD_TYPE=Release --packages-select ov_core ov_init ov_msckf


ℹ️ 编译过程中可在另一个终端通过
htop查看系统资源使用情况,确认不会因内存不足导致编译中断。
ℹ️ 编译结果显示Summary: 3 packages finished,则表示编译成功。日志中的 stderr 输出为第三方依赖库(Eigen、Boost、Python)与较新版本 GCC 之间的兼容性警告,不影响 VIO 运行功能。
3.2.5 配置终端环境
echo "source ~/vio/openvins_ws/install/setup.bash" >> ~/.bashrc
source ~/.bashrc
3.3.1 下载数据包

3.3.2 上传数据包到机载电脑

3.3.3 启动 OpenVINS 并回放数据集验证
ros2 launch ov_msckf subscribe.launch.py config:=euroc_mav
ros2 bag play ~/vio/V1_01_easy.db3

ℹ️ 终端日志输出能看到 OpenVINS 实时运行情况、位置及轨迹长度信息等,最后定位位置回到原点附近
p_IinG = -0.617,-0.069,0.081,轨迹长度dist = 57.31 (meters)与数据集实际 58m 非常接近,表明 OpenVINS 在树莓派 5 上运行效果良好。
通过 ROSBAG 数据集验证后,接下来将 D430 双目相机和飞控 IMU 的实时数据接入 OpenVINS,验证其在真机上的运行效果。
3.4.1 监测系统状态
htop

ℹ️ 实时查看系统资源使用情况,确认 OpenVINS 资源负载在正常范围内。
3.4.2 启动相机节点
ros2 launch realsense2_camera mvd35_d430_launch.py

ℹ️ 启动节点后能看到双目启动的信息及
RealSense Node Is Up!标识,则说明相机启动成功。
3.4.3 启动 MAVROS 节点
ros2 launch mavros apm.launch

ℹ️ 启动节点后,能看到 MAVROS 的日志输出,包括
飞控固件版本、飞控型号等信息,表示 MAVROS 已成功连接到飞控。
3.4.4 启动 OpenVINS
ros2 launch ov_msckf subscribe.launch.py config:=mvd35

ℹ️ 在静止状态下启动节点后,OpenVINS 接收双目及 IMU 数据,完成初始化后进入
ZUPT(Zero velocity UPdaTe,零速更新)状态——系统检测到无人机静止时,利用零速约束抑制 IMU 漂移。当无人机开始移动后,ZUPT状态自动解除,进入正常位姿输出模式。
3.4.5 验证位姿输出
ℹ️ 轻轻晃动无人机,使
ZUPT状态解除,OpenVINS 开始稳定输出位姿数据。

ros2 topic hz /mavros/vision_pose/pose

ros2 topic echo /mavros/vision_pose/pose

ℹ️
/mavros/vision_pose/pose话题以约 30Hz 频率稳定输出,数据与实际位姿一致,说明 OpenVINS 在真机上运行正常。
设置飞控 EKF 以接受外部视觉定位数据,替代光流作为主要定位源。
VIO 启用后,OpenVINS 以 30Hz 频率向飞控回传位姿数据,显著增加了数传链路的带宽负载。为确保数据传输稳定,需将遥数一体数传切换为 high-speed 模式,并相应调整飞控串口波特率。
4.1.1 修改链路模式
将高频头连接到电脑
浏览器访问 微空助手网页版
选择 高频头端口 -> 打开 配置数传 -> 点击 连接,连接到高频头

保存到设备 并断开连接
4.1.2 修改飞控数传串口波特率
将飞控通过 USB 线连接到电脑
连接到 MicoConfigurator 并修改对应串口波特率
设置 -> 端口设置 -> 设置 SERIAL1 USART1 波特率 为 115200SERIAL1_BAUD 115: 115200

⚠️ 切换为
high-speed模式后,通过数传连接 MicoConfigurator 时,波特率需选择115200,否则无法正常通信。

1. VIO 类型与位置参数设置
参数 -> VISO -> VISO_POS_X 设置为 0.09;VISO_TYPE 设置为 1: MAVLinkVISO_POS_X 0.09
VISO_TYPE 1: MAVLink

2. 飞控时钟参数设置
参数 -> BRD -> BRD_RTC_TYPES 设置为 2BRD_RTC_TYPES 2

3. 飞控系统ID参数设置
参数 -> SYSID -> SYSID_MYGCS 设置为 1SYSID_MYGCS 1

4. 飞控 EKF 数据源设置
设置 -> EKF
EK3_SRC1 水平位置源 设置为 6: ExternalNav;垂直位置源 设置为 2: RangeFinder;水平速度源 设置为 0: None;垂直速度源 设置为 0: None;偏航角源 设置为 6: ExternalNav
EK3_SRC1_POSXY 6: ExternalNav
EK3_SRC1_POSZ 2: RangeFinder
EK3_SRC1_VELXY 0: None
EK3_SRC1_VELZ 0: None
EK3_SRC1_YAW 6: ExternalNav

4.3.1 启动所有节点
htop
ros2 launch realsense2_camera mvd35_d430_launch.py
ros2 launch mavros apm.launch
ros2 launch ov_msckf subscribe.launch.py config:=mvd35


4.3.2 验证 EKF 融合状态

ℹ️ 数传链路接收速率占用带宽显著上升,由未启动 VIO 前的 1.5 KB/s 增加至 5.5 KB/s
在 消息控制台 可以看到 VISION_POSITION_ESTIMATE 消息输出,数据及频率与树莓派上的输出一致
在 MicoConfigurator 底部消息栏可以看到 EKF3 已经融合了外部位置数据,并输出位置数据

确认 EKF 融合状态正常后,保持 4.3 节中所有节点运行,进行手持移动测试。
测试步骤:
VISION_POSITION_ESTIMATE 和 LOCAL_POSITION_NED 消息。LOCAL_POSITION_NED 中的 x、y、z 值是否跟随实际运动同步变化。完成后检查:
✅
VISION_POSITION_ESTIMATE消息持续稳定输出,频率约 30Hz。
✅LOCAL_POSITION_NED数据(飞控 EKF 融合 VIO 后的定位结果)跟随实际运动实时变化:
- 向机头方向移动 → x 增大
- 向右侧移动 → y 增大
- 向上抬高 → z 减小(NED 坐标系 z 轴朝下)
✅ 回到起始位置后,坐标值接近零点,无明显累积漂移。

常见问题:
LOCAL_POSITION_NED 无数据变化:EKF 来源参数配置错误,重新检查 EK3_SRC1 参数。⚠️ 安全警告:首次飞行测试务必在开阔安全的室内环境中进行,建议由有飞行经验的操作员完成。飞行全程始终保持一个模式通道为 Stabilize,如发现位姿漂移或跳变,立即切回 Stabilize 模式手动降落。
1. 启动所有节点
按照 4.3 节的方式依次启动 RealSense → MAVROS → OpenVINS,确认 EKF 融合状态正常。
2. 起飞
3. 定位验证
4. 降落
完成后检查:
常见问题:
VISO_DELAY_MS 设置不当,根据飞行日志调整。EK3_SRC1_POSZ 是否正确设置为 2: RangeFinder。| 现象 | 可能原因 | 解决方案 |
|---|---|---|
| OpenVINS 无法初始化 | 初始化阶段运动不足 | 启动后轻轻晃动无人机几秒钟 |
| VIO 位姿快速漂移 | 标定参数不准确 | 重新进行相机和 IMU-Camera 标定 |
| VIO 位姿跳变 | 视觉特征不足或光照突变 | 确保环境有纹理,避免对着纯白墙壁 |
| 飞控不使用 VIO 数据 | EKF 来源配置错误 | 检查 EK3_SRC 或 EKF2_EV 参数 |
| 飞行中位置漂移 | DELAY_MS 设置不当 | 根据日志分析调整延迟补偿值 |
| 快速运动时定位丢失 | 运动模糊导致特征跟踪失败 | 降低飞行速度,或提高相机曝光速度 |
| OpenVINS 编译 OOM | 树莓派内存不足 | 增加 4GB swap 空间后重试 |