文档目录
文章目录
微空 AI 智能无人机教程 4 - 双目视觉里程计 (VIO) 部署运行
本章目标
本章将在机载电脑(树莓派 5)上部署 OpenVINS 双目视觉惯性里程计(VIO),使无人机能够在无 GPS 的室内或复杂环境中获取精准的三维空间坐标。
部署完成后,VIO 输出的位姿定位数据将通过 MAVROS 回传给飞控 EKF(Extended Kalman Filter,扩展卡尔曼滤波器),替代传统的光流传感器,作为主要的位置估算源,从而实现无人机高精度的室内自主定位悬停与飞行任务。
完成本章的部署与测试后,MVD35 应达到以下状态:
- VIO 算法运行稳定:OpenVINS 在树莓派 5 上能够以 30Hz 的帧率流畅、稳定地输出位姿估算数据。
- 飞控 EKF 融合 VIO 数据正常:位姿数据通过 MAVROS 稳定回传至飞控,EKF 将外部视觉定位(External Vision)融合为主要位置估算源。
- 自主定位悬停精准:在定点模式下,无人机能够完全依靠视觉里程计实现稳定的室内定位悬停,水平及高度漂移极小。

前期准备
硬件准备
- MVD35 智能版(完成前置教程的软件配置)
- 遥控器(加装 TRS 高频头)
- USB 数据线
- 电脑与良好的网络条件
软件准备
- SSH 终端工具:MobaXterm
- 微空 Web 飞控配置器: MicoConfigurator
- 遥数一体高频头配置修改:微空助手网页版
VIO 工作原理与系统架构
VIO(Visual-Inertial Odometry,视觉惯性里程计)通过融合高频的惯性测量单元(IMU)数据与低频的相机图像来实时估计飞行器的三维位姿(位置和姿态)。 相比于依赖地面纹理且只能测量二维位移的传统“光流+测距”方案,VIO 能够提供完整的六自由度(6-DoF)位姿估计,定位精度更高,且不受低纹理地面、沙地或积水环境的影响,是室内无 GPS 自主飞行的核心技术。
本教程使用 OpenVINS 作为 VIO 算法框架。它是由特拉华大学开发的开源轻量化 VIO 系统,支持多相机配置、IMU 在线标定,并且在树莓派 5 平台上有较好的实时运行效率。
MVD35 VIO 系统数据流向:

1. 传感器数据采集:
- 图像输入:机载 D430 深度相机采集双目红外图像,以 30Hz 速率传输给树莓派。
- 惯性数据输入:飞控发布 200Hz IMU 角速度和加速度数据,由 MAVROS 节点实时传输给树莓派。
2. 状态解算与位姿发布(OpenVINS):
- 树莓派上运行的 OpenVINS 节点订阅双目图像与 IMU 话题,通过 MSCKF 算法进行滑窗状态估计,实时解算出位姿数据。
- 解算完成后,OpenVINS 直接将位姿数据发布到
/mavros/vision_pose/pose话题,由 MAVROS 回传至飞控。
3. 飞控 EKF 融合定位:
- 飞控 EKF 融合外部视觉定位数据,为飞行控制算法提供稳定的位置、速度和姿态估计,从而使无人机在定点模式下实现精准悬停。
ℹ️ MVD35 直接使用飞控内置的高质量 IMU 作为惯性源(由 MAVROS 以 200Hz 发布),省去了相机模组额外集成 IMU 的硬件成本,且飞控 IMU 经过物理防震设计,更加适用于无人机飞行场景。
OpenVINS 编译与验证
编译安装 ceres-solver
Ceres Solver 是由 Google 开发的高性能开源非线性最小二乘问题求解器。在 OpenVINS 中,用于进行滑动窗口中的状态估计和外参在线标定等核心优化计算。
ℹ️ 为什么需要从源码编译安装?
Ubuntu 24.04 官方源提供的 Ceres 版本为 2.2.0,与 ROS 2 Jazzy 环境下的 Eigen 等库存在接口或版本兼容问题。为确保 OpenVINS 的编译和运行稳定性,本教程选择从源码编译并安装经过兼容性测试的 2.0.0 版本。
1. 确认系统核心组件
- 运行以下命令确认系统版本、Python 和 CMake 等工具已就绪:
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
2. 安装依赖库
sudo apt-get install cmake libgoogle-glog-dev libgflags-dev libatlas-base-dev libeigen3-dev libsuitesparse-dev -y3. 下载源代码
- 创建工作空间并拉取 2.0.0 版本源代码
mkdir -p ~/vio && cd ~/vio
git clone --branch=ceres-2.0.0 https://github.com/Minderring/ceres-solver.git
4. 创建编译环境
cd ceres-solver/
mkdir build && cd build
cmake ..
5. 编译 ceres-solver
make

6. 安装 ceres-solver
sudo make install

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
编译 OpenVINS
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/2. 设置交换内存
ℹ️ 为什么需要设置交换内存?
由于选用的机载电脑为 树莓派5 4G RAM 版本,在运行编译任务时容易因内存不足导致编译中断。通过设置交换内存,可以有效缓解内存压力,确保编译过程的稳定性。
- 分配并启用 4GB 交换内存
sudo fallocate -l 4G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
- 检查内存及交换内存使用情况
htop
ℹ️
htop命令可以实时查看系统中各进程的资源使用情况,包含 CPU、内存等。图中Mem和Swp分别表示物理内存和交换内存的使用情况。
3. 下载源代码
- 创建工作空间并拉取 micoair-mvd35 分支源代码
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 平台适配和优化后的版本。
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 运行功能。
5. 配置终端环境
echo "source ~/vio/openvins_ws/install/setup.bash" >> ~/.bashrc
source ~/.bashrc运行 ROSBAG 数据集验证
1. 下载数据包
- 在 OpenVINS Supported Datasets 中下载 rosbag2 的数据包,并解压到本地电脑。

2. 上传数据包到机载电脑
- 将下载好的 rosbag2 数据包上传到树莓派
/home/micoair/vio目录下

3. 启动 OpenVINS 并回放数据集验证
- 终端 1: 启动 OpenVINS
ros2 launch ov_msckf subscribe.launch.py config:=euroc_mav- 终端 2: 回放数据集
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,验证其在真机上的运行效果。
1. 监测系统状态
htop
ℹ️ 实时查看系统资源使用情况,确认 OpenVINS 资源负载在正常范围内。
2. 启动相机节点
ros2 launch realsense2_camera mvd35_d430_launch.py
✅ 启动节点后能看到双目启动的信息及
RealSense Node Is Up!标识,则说明相机启动成功。
3. 启动 MAVROS 节点
ros2 launch mavros apm.launch
✅ 启动节点后,能看到 MAVROS 的日志输出,包括
飞控固件版本、飞控型号等信息,表示 MAVROS 已成功连接到飞控。
4. 启动 OpenVINS
ros2 launch ov_msckf subscribe.launch.py config:=mvd35
✅ 在静止状态下启动节点后,OpenVINS 接收双目及 IMU 数据,完成初始化后进入
ZUPT(Zero velocity UPdaTe,零速更新)状态——系统检测到无人机静止时,利用零速约束抑制 IMU 漂移。当无人机开始移动后,ZUPT状态自动解除,进入正常位姿输出模式。
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 定位数据
设置飞控 EKF 以接受外部视觉定位数据,替代光流作为主要定位源。
修改遥数一体链路模式
VIO 启用后,OpenVINS 以 30Hz 频率向飞控回传位姿数据,显著增加了数传链路的带宽负载。为确保数据传输稳定,需将遥数一体数传切换为 high-speed 模式,并相应调整飞控串口波特率。
1. 修改链路模式
-
将高频头连接到电脑
-
浏览器访问 微空助手网页版
-
选择 高频头端口 -> 打开 配置数传 -> 点击
连接,连接到高频头

- 打开 参数 界面 -> 速率模式 选择 高速 -> 点击
保存到设备并断开连接

- 重新对频接收机,对频操作请参考视频教程:微空TRS遥数一体高频头&接收机使用指南
2. 修改飞控数传串口波特率
-
将飞控通过 USB 线连接到电脑
-
连接到 MicoConfigurator 并修改对应串口波特率
设置->端口设置-> 设置 SERIAL1USART1波特率 为115200
SERIAL1_BAUD 115: 115200- ⚠️ 重启飞控

- 断开飞控与电脑的 USB 线连接,并重新通过数传连接到 MicoConfigurator
⚠️ 切换为
high-speed模式后,通过数传连接 MicoConfigurator 时,波特率需选择115200,否则无法正常通信。
- 查看未启动 VIO 时的数传负载和链路质量

更新补充中……
飞控 EKF 配置
1. VIO 类型与位置参数设置
-
参数->VISOVISO_POS_X设置为0.09VISO_TYPE设置为1: MAVLink
VISO_POS_X 0.09
VISO_TYPE 1: MAVLink
2. 飞控时钟参数设置
-
参数->BRDBRD_RTC_TYPES设置为2
BRD_RTC_TYPES 2
3. 飞控系统ID参数设置
-
参数->SYSIDSYSID_MYGCS设置为1
SYSID_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
更新补充中……
- ⚠️ 重启生效
验证 VIO 数据融合
1. 启动所有节点
- 终端 1:监测系统状态
htop- 终端 2:启动相机节点
ros2 launch realsense2_camera mvd35_d430_launch.py- 终端 3:启动 MAVROS 节点
ros2 launch mavros apm.launch- 终端 4:启动 OpenVINS
ros2 launch ov_msckf subscribe.launch.py config:=mvd35
- 轻微晃动无人机,查看 OpenVINS 位姿输出

2. 验证 EKF 融合状态
- 查看启动 VIO 后,遥数一体数传负载和链路质量

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

更新补充中……
VIO 定位移动测试
确认 EKF 融合状态正常后,保持 4.3 节中所有节点运行,进行手持移动测试。
测试步骤:
- 在 MicoConfigurator 消息控制台中观察
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参数。⚠️ 位姿方向与实际运动相反:相机-IMU 外参标定有误,需重新标定或检查坐标系配置。
⚠️ 短距离移动后位姿快速漂移:环境视觉特征不足(纯白墙壁、单一纹理),更换至纹理丰富的环境重新测试。
VIO 定位飞行测试
⚠️ 安全警告
首次飞行测试务必在开阔安全的室内环境中进行,建议由有飞行经验的操作员完成。飞行全程 始终保持一个模式通道为 Stabilize,如发现位姿漂移或跳变,立即切回 Stabilize 模式手动降落。
飞行前检查
✅ 4.4 节手持移动测试通过,定位方向正确、无明显漂移。
✅ 遥控器已配置 Stabilize 模式(手动接管)和 Loiter 模式(VIO 定位飞行)。
✅ 飞行场地纹理丰富、光照稳定无频闪。
✅ 电池电量充足,螺旋桨安装牢固。
飞行操作
1. 启动所有节点
按照 4.3 节的方式依次启动 RealSense → MAVROS → OpenVINS,确认 EKF 融合状态正常。
2. 起飞
- 在 Stabilize 模式下解锁起飞,确认飞行姿态正常。
- 在低高度(0.5~1m)稳定悬停后,切换至 Loiter 模式。
- 松开摇杆,观察无人机是否能保持位置不漂移。
3. 定位验证
- 缓慢推动方向摇杆,验证位置控制响应。
- 松开摇杆后,无人机应能在新位置保持悬停。
4. 降落
- 切回 Stabilize 模式,缓慢降低油门平稳着地。
- 落地后上锁并断开电池。
完成后检查:
✅ Loiter 模式下无人机能稳定悬停,水平漂移小。
✅ 推杆后松开,无人机能在新位置保持定点。
✅ 飞行全程 OpenVINS 未出现跟踪丢失或位姿跳变。
常见问题:
⚠️ 切换模式后突然漂移或加速:
VISO_DELAY_MS设置不当,根据飞行日志调整。⚠️ 飞行中 VIO 跟踪丢失:环境特征不足或光照突变,避免对着纯白墙壁或窗户飞行。
⚠️ 起飞后高度不稳:检查
EK3_SRC1_POSZ是否正确设置为2: RangeFinder。
附录
常见问题排查
| 现象 | 可能原因 | 解决方案 |
|---|---|---|
| OpenVINS 无法初始化 | 初始化阶段运动不足 | 启动后轻轻晃动无人机几秒钟 |
| VIO 位姿快速漂移 | 标定参数不准确 | 重新进行相机和 IMU-Camera 标定 |
| VIO 位姿跳变 | 视觉特征不足或光照突变 | 确保环境有纹理,避免对着纯白墙壁 |
| 飞控不使用 VIO 数据 | EKF 来源配置错误 | 检查 EK3_SRC 或 EKF2_EV 参数 |
| 飞行中位置漂移 | DELAY_MS 设置不当 | 根据日志分析调整延迟补偿值 |
| 快速运动时定位丢失 | 运动模糊导致特征跟踪失败 | 降低飞行速度,或提高相机曝光速度 |
| OpenVINS 编译 OOM | 树莓派内存不足 | 增加 4GB swap 空间后重试 |

