Skip to main content

Visual Inertial Odometry

Visual Inertial Odometry (VIO) is the bigger sibling of optical flow. Where optical flow gives you horizontal velocity from a downward camera plus a rangefinder, VIO gives you a full 6-degree-of-freedom pose (position and orientation in three dimensions) from a forward or downward camera fused with the FC’s IMU.
VIO ships in the plugin. Two engines (OpenVINS and VINS-Fusion) ride inside the signed plugin archive as vendor binaries. They stay on disk and never run until you select a VIO mode. VIO needs a one-time camera-IMU calibration and a board with an NPU or a strong multicore CPU; on a weak board the estimator cannot keep up. For low-altitude GPS-denied flight on light hardware, the optical-flow modes are the simpler path.

What it adds

Optical flow tells the EKF “the drone is moving north at 2.1 m/s.” VIO tells the EKF “the drone is at (12.3, 4.7, 1.8) meters from the origin, rolled 2 degrees, pitched 5 degrees, yawed 18 degrees, and moving at (1.4, 1.0, 0.0) m/s.” The richer state lets the FC do things optical flow can’t:
  • Fly at altitudes where the rangefinder can’t see the ground (above 10 m on most sensors).
  • Follow corridors and tunnels where the downward camera has nothing to track.
  • Maintain heading-relative position over long flights without GPS or compass drift.
  • Land on uneven terrain by combining VIO altitude with the IMU’s gravity vector.
The trade-off is compute. A monocular VIO at 30 Hz on a 640x480 camera needs an NPU or a strong CPU. VIO modes are intended for capable boards; a weak board cannot run them at the rate the EKF expects.

Two engines, side by side

The plugin ships two VIO modes:
  • vio_openvins uses OpenVINS, a filter-based (MSCKF) estimator. Lower CPU cost, strong on fast motion, slightly looser bound on long-flight drift.
  • vio_vins_fusion uses VINS-Fusion, a sliding-window bundle-adjustment estimator. Higher CPU cost, tighter drift bound in feature-rich scenes, stronger in low-feature or texture-poor environments.
OpenVINS is the default. VINS-Fusion is the advanced option for boards with the headroom.

Hardware requirements

The plugin’s VIO modes target a monocular forward-facing or downward-facing camera plus the FC IMU. Stereo and full-SLAM (loop-closure) engines are not in this release; the architecture leaves the seam open. Camera: a forward-facing or downward-facing camera at 30 Hz, 640x480 or higher. A rolling-shutter camera works but is more sensitive to fast motion. Global shutter is strongly preferred. IMU: the FC’s IMU, sampled through MAVLink RAW_IMU (the universal path every FC publishes). A higher-rate direct IMU path (a direct-I2C BMI088 at around 400 Hz) is a planned addition; until it lands the MAVLink path is the only source.

How it plugs in

The VIO engine runs as a vendor binary inside the plugin’s process sandbox, started by the plugin and watched by a heartbeat watchdog. The Rust agent reads frames from the shared vision frame bus and bridges them into the engine’s shared-memory ring (zero-copy); IMU samples and control messages flow through a Unix-domain socket encoded as length-prefixed msgpack. Pose estimates flow back over the same socket. The plugin then emits VISION_POSITION_ESTIMATE on MAVLink component 197 (MAV_COMP_ID_VISUAL_INERTIAL_ODOMETRY) at the camera frame rate (around 30 Hz). ArduPilot’s EKF3 fuses these messages when EK3_SRC1_POSXY, EK3_SRC1_VELXY, and EK3_SRC1_YAW are set to ExternalNav (6). PX4’s EKF2 fuses them when EKF2_EV_CTRL enables external vision. The IPC protocol is documented in the Architecture page. Adding a third engine (a future home-grown estimator) is a new VIO engine variant plus a vendor binary that speaks the same protocol.

Calibration

VIO needs calibrated intrinsics and known camera-IMU extrinsics including the static time offset between the two clocks. The plugin accepts Kalibr-compatible camchain.yaml files directly, or you can run the guided in-app wizard. See Calibration for the full workflow. The pre-arm gate refuses to arm a VIO mode without loaded calibration files. The GCS sensors card surfaces a Calibrate prompt when intrinsics are not yet loaded.

License compliance

Both OpenVINS and VINS-Fusion are GPL-3.0-licensed. Shipping a pre-compiled binary inside the plugin archive carries the GPL source-offer obligation. The plugin’s manifest declares a vendor_attribution block for each engine with the upstream repository, the license, the upstream version, and a notice. The install dialog surfaces these blocks during the summary stage so operators see what they are installing.

When to use VIO vs optical flow

If you fly close to the ground (under 8 m), have a downward camera, and need stable hover and waypoint flight, the optical-flow modes are the simpler path. See Configure optical flow for the setup. If you fly at altitude, in long corridors, or in environments where the downward camera has nothing to track, VIO is the mode you want, on a board with the compute to run it.

Stay in the loop

Plugin updates are announced through the standard channels:
  • The ADOSExtensions GitHub repository’s release feed.
  • The Mission Control update notifier (in-app banner when a new plugin version is published).
  • Community channels listed in Open source.