Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.altnautica.com/llms.txt

Use this file to discover all available pages before exploring further.

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 lets you pick the source:
ModeFieldNotes
USB UVCdevice_pathA path like /dev/video0. The dropdown lists every UVC device the agent enumerated at boot.
CSIcsi_indexAn index (0 or 1) corresponding to the CSI port. Auto-detection picks the first attached CSI camera.
Auto(none)The plugin picks CSI first, then UVC, in that order.
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 the permission grant on hardware.usb.uvc or hardware.camera.csi.

Rangefinder

The Rangefinder section lets you pick a driver:
DriverTopologyBus / source
tf-lunaCompanion-ownedUART. Pick the UART number from the dropdown.
lidar-lite-v3Companion-ownedI2C. Address defaults to 0x62.
vl53l1xCompanion-ownedI2C. Address defaults to 0x29.
mavlink-relayFC-relayedThe FC reads the rangefinder and forwards DISTANCE_SENSOR. Pick the orientation the FC reports as “down”.
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 bus address.

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.
ParameterSet toWhy
FLOW_TYPE5Selects the MAVLink-based flow driver (the message the plugin emits).
FLOW_ORIENT_YAW0 to 35999Camera yaw mount offset in centi-degrees. 0 for forward-facing chassis.
FLOW_FXSCALER0X-axis flow scale calibration. Leave at 0 unless calibrating.
FLOW_FYSCALER0Y-axis flow scale calibration.
EK3_SRC1_VELXY5Sets the primary horizontal-velocity source to optical flow.
EK3_SRC1_POSXY0No primary horizontal-position source. Position is derived from velocity.
EK3_SRC1_POSZ1Barometer for primary vertical position. Optical flow only gives horizontal.
EK3_SRC1_YAW1Compass for primary yaw. Flow doesn’t measure yaw.
EK3_FLOW_DELAY10Sensor-to-FC latency in milliseconds. 10 ms is a good starting point for companion-owned flow; raise to 20 to 30 for FC-relayed rangefinders.
EK3_FLOW_QUAL_MIN50Minimum tracker quality (0 to 255) for the EKF to fuse a flow sample. Lower to 30 in feature-poor environments.
EK3_RNG_USE_HGT70Below this percentage of RNGFND1_MAX_CM, the EKF uses rangefinder for height.
RNGFND1_TYPEper sensor8 for LightWare, 20 for Benewake TF-Luna, etc. Or 10 for MAVLink-relayed. Match your wiring.
RNGFND1_ORIENT25MAV_SENSOR_ROTATION_PITCH_270, pointing down.
ARMING_CHECKleave defaultPre-arm checks stay on. The plugin satisfies them rather than disabling.
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.
ParameterSet toWhy
EKF2_OF_CTRL1Enable optical flow fusion.
EKF2_OF_DELAY5 to 30Latency in milliseconds from sensor sample to EKF. Tune to match your transport.
EKF2_OF_GATE3Innovation gate (standard deviations). Wider gate is more permissive.
EKF2_OF_POS_Xmount offset, metersCamera position relative to vehicle IMU, X axis (forward positive).
EKF2_OF_POS_Ymount offset, metersY axis (right positive).
EKF2_OF_POS_Zmount offset, metersZ axis (down positive).
EKF2_OF_QMIN1Minimum flow quality (0 to 255) for fusion.
EKF2_RNG_AID1Use rangefinder when available.
EKF2_HGT_REF2Set primary height source to rangefinder. 0 for barometer if the rangefinder is short-range only.
SENS_FLOW_MINHGTsensor min, metersMinimum altitude at which to trust flow. Matches the rangefinder’s lower bound.
SENS_FLOW_MAXHGTsensor max, metersMatches the rangefinder’s upper bound.
SENS_FLOW_MAXR2.5Maximum trusted angular flow rate in rad/s.
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.
ParameterSet toWhy
opflow_hardwareMAVLINKTells iNav to read the optical-flow stream from the MAVLink rx UART instead of a local I2C/UART sensor.
opflow_scaleleave defaultThe plugin sends pre-scaled angular rates; iNav does not need to rescale.
nav_use_optflow_for_posholdONEnables flow-based position hold (NAV POSHOLD) when GPS is unavailable.
nav_extra_arming_safetyONPre-arm check that flow quality is healthy before allowing arming. Recommended for indoor and over-ground flight.
rangefinder_hardwarematch the wired driver (LIDARMT, VL53L1X, TFMINI, etc.) or MSPOptical flow needs a height reference to recover metric velocity. Either wire a rangefinder to the FC or use the plugin’s relay path.
nav_rangefinder_for_terrainONEnables terrain-following behavior on top of flow-based position hold.
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.
FirmwareCommandNotes
ArduPilotMAV_CMD_SET_EKF_SOURCE_SET (command ID 42007)param1 = source set number (1, 2, or 3). Mission Control sends it via the per-drone Navigation tab.
PX4Write EKF2_* params + rebootPX4 doesn’t have a runtime source-set switch. You change params and the EKF re-initializes on reboot.
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 roadmap for what comes after optical flow.
  • 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.