Skip to main content

Configure Optical Flow

This page walks through the per-drone configuration after the Vision Navigation plugin is installed and enabled. The order matters: pick the hardware first, then set the FC parameters, then switch the active EKF source set, then verify pre-arm.

Pick the camera and rangefinder

Open the drone detail panel, click Plugins, click the plugin row to open its configuration drawer.

Camera

The Camera section sets which device the agent’s vision host captures (the plugin reads the resulting frames from the shared vision bus): The drawer shows a tiny live preview once the camera is selected. Frame rate and resolution under the preview should show 30 fps at 320x240 or higher. If the preview is black, check the camera connection and that the agent’s vision host has the camera.

Rangefinder

The Rangefinder section lets you pick a topology and driver: The drawer shows the current rangefinder reading once the driver connects. A healthy reading is non-zero, updates at the sensor’s native rate, and matches your visual estimate of ground distance. If the reading is stuck at zero or saturates at the sensor’s maximum, double-check wiring and the topology.

ArduPilot parameters

ArduPilot’s optical flow fusion lives inside EKF3. You set these parameters from Mission Control’s Parameters panel or from the plugin’s pre-flight helper button. The helper writes all of them in one batch, verifies each one read back correctly, and asks the FC to commit to EEPROM. The plugin emits OPTICAL_FLOW_RAD on MAVLink component ID 198. ArduPilot accepts the message from any component when FLOW_TYPE=5; you don’t need to whitelist the component on the FC side.

PX4 parameters

PX4’s EKF2 handles flow fusion differently from ArduPilot. The plugin’s helper still batches the writes; you can also set them by hand from the Parameters panel. PX4 needs a reboot after writing EKF2_OF_CTRL. The plugin’s helper button triggers a soft reboot of the FC and waits for it to come back before reporting success.

iNav parameters

iNav 7.0 and newer consumes the same OPTICAL_FLOW_RAD message the plugin already emits to ArduPilot and PX4. The MSP-level configuration is short. Wire the FC’s UART that carries MAVLink to the ADOS Drone Agent. In iNav’s Ports tab, set the UART’s MAVLINK function bit. Reboot the FC. The plugin’s heartbeat detects MAV_AUTOPILOT_INVALID plus the iNav-specific STATUS_MESSAGE strings and flips the firmware tag automatically. iNav does not support runtime source-set switching the way ArduPilot does. The plugin’s GCS panel disables the source-set switcher on iNav and surfaces the iNav-specific parameter list as a read-only reference. VIO modes are not surfaced on iNav. iNav has external position-injection hooks but the EKF integration is not VIO-grade in the 7.x series; the plugin disables vio_openvins, vio_vins_fusion, and hybrid_of_plus_vio on iNav at install time. Operators who want VIO on a small FC should cross-flash ArduPilot Copter.

Betaflight: not supported

Betaflight is a flight controller designed for racing and freestyle, not autonomous position-hold. It has no position estimator, so optical-flow injection has no consumer inside the FC. The plugin refuses to enable on a Betaflight-detected FC and surfaces an explanation in the Navigation tab. Cross-flash iNav or ArduPilot Copter on the same FC to enable GPS-denied flight; most STM32F405 / F722 / H743 boards run all three firmwares.

Switch the active EKF source set

ArduPilot supports three EKF source sets (SRC1, SRC2, SRC3) and lets you swap between them at runtime. A common setup is SRC1 for GPS, SRC2 for optical flow, and SRC3 for an external pose source. The Navigation tab exposes a source-set switcher. The switch is logged to the per-drone Navigation tab telemetry ring and surfaced as a notification in the GCS toast channel so you don’t lose track of which estimator the FC is currently fusing.

Pre-arm checks for GPS-denied flight

Vision-only flight skips a few pre-arm checks that exist for GPS-based flight (GPS HDOP, GPS lock, glitch detection) and adds a few that don’t.

Set the GPS global origin

ArduPilot needs a reference point for its local position frame. With GPS, the EKF auto-seeds the origin from the first valid GPS fix. Without GPS, you have to send one. The plugin handles this automatically when it sees the EKF reporting “waiting for home.” It dispatches SET_GPS_GLOBAL_ORIGIN with the drone’s last-known location (from your fleet database) or a sensible default (the most recent paired-from location). The Navigation tab’s arm-readiness card shows the origin was set successfully. PX4 needs the same thing, though it uses a slightly different flow. The plugin’s helper handles both firmwares.

AHRS waiting for home

ArduPilot reports AHRS waiting for home on the GCS while it’s waiting for the origin. Once SET_GPS_GLOBAL_ORIGIN succeeds and the EKF has fused a few seconds of flow plus rangefinder, the message clears.

EKF3 position healthy

The drone won’t accept LOITER or auto-mission arming until EKF3 reports a healthy position. The Navigation tab’s arm-readiness card aggregates four checks:
  • Camera healthy (frames arriving at 30 Hz, quality above the configured threshold)
  • Rangefinder healthy (reading inside valid range, updating at sensor rate)
  • EKF position healthy (innovation within gate, source set 2 active)
  • FC armable (no other pre-arm failures)
All four green means you can arm and take off. Any red shows the corresponding check inline so you know what to fix.

Tuning tips

  • Flow quality threshold. Default is 50 on ArduPilot, 1 on PX4. Lower the ArduPilot value (down to 30) for feature-poor surfaces (smooth concrete, snow, water). Don’t lower it below 20 unless you’re testing in a safe environment; below 20 the tracker emits noise instead of motion.
  • Latency tuning. If the vehicle oscillates in LOITER, the EKF is fusing flow with the wrong latency assumption. Increase EK3_FLOW_DELAY by 5 ms steps until the oscillation damps. The plugin’s Navigation tab shows the round-trip flow latency it measured; use that as the starting point rather than guessing.
  • Yaw stability. Optical flow doesn’t measure yaw. Compass calibration matters more than usual. Run the compass cal twice if the vehicle drifts a meter or two in LOITER over a minute.
  • Initial altitude. Auto-takeoff on optical flow should target 1.5 m to 3 m for the first hop. Below 1 m the rangefinder is close to its lower bound; above 3 m the optical flow tracker has fewer trackable features at typical FOVs.

Next steps

  • Visual Inertial Odometry for full 6-DOF pose estimation.
  • The plugin emits structured logs through the agent’s normal log pipe. Tail them with ados plugin logs com.altnautica.vision-nav for debugging.
  • Plugins overview for the underlying plugin host model.