Article

Why optical-flow position hold can fail just above the floor

A downward-looking camera can help a quadcopter hold its position indoors without a GNSS signal. The awkward part is often the last few centimetres before landing. Optical flow can remain available as a stream of numbers even when its measurements no longer describe real horizontal movement.

A group of ArduPilot development proposals makes this problem unusually concrete. Their authors describe unreliable flow at close range, altitude estimates disturbed by prop wash, velocity estimates that continue changing after touchdown and cases where one of the two horizontal flow axes is no longer being fused. The separate fixes address separate causes. Their common lesson is that a navigation filter must know when an observation is no longer trustworthy.

What an optical-flow camera does not measure

An optical-flow sensor measures how features move across an image. With aircraft rotation accounted for, that provides information about movement relative to the ground. Translating angular image motion into ground speed needs a reliable distance to the observed surface. An inertial sensor, accurate timestamps and a downward-looking distance sensor therefore matter to the result.

The PX4 optical-flow guide explicitly pairs optical-flow sensing with a distance measurement, while the ArduPilot setup guide explains how horizontal velocity observations are selected in EKF3.

The dependency on height creates a coupling that can be missed during bench setup. If the rangefinder measurement is unavailable or the estimated distance is wrong, an otherwise stable image-motion reading can be converted into the wrong horizontal velocity. The controller may then respond to motion that never occurred.

The first problem is the camera's usable focus range

ArduPilot pull request #34292 proposes FLOW_HGT_MIN, a way of rejecting flow readings below a sensor-specific minimum height. The author describes a failure in which a close-range, out-of-focus reading is nevertheless passed to the estimator. Once converted into velocity, that reading can cause a position-hold controller to tilt the aircraft unnecessarily during descent.

The author reports tests in simulation and on hardware. In a software-in-the-loop test with an intentionally incorrect flow reading close to the floor, reported peak estimated groundspeed dropped from 0.90-1.22 m/s without the validity guard to 0.03 m/s with it. Those figures describe the particular injected-fault test. They are not independent measurements of how often this happens in normal operation.

The important design point is more general: a sensor reporting a value does not establish that the value is usable. A focus limit should be treated as a measurement-validity condition.

The second problem is vertical state at the ground boundary

Optical-flow navigation also depends on the way the aircraft estimates height. Close to a spinning multirotor, pressure disturbances can make barometric altitude less reliable. A rangefinder may be more informative about the nearby surface, but only while it is within its valid operating range.

In pull request #33359, an ArduPilot contributor describes a height-source selection problem that can leave a good rangefinder underused during hover. The proposed change draws on an IMU-assisted above-ground-level estimate instead of using a barometer-affected value for the switch. In two recorded indoor-flight replays, the author reports reduced maximum height error after the proposed change. The result is evidence for that implementation and those flights, not a guarantee across all aircraft.

A related edge case appears in pull request #34457. The developer reports that a vertical filter could retain a downward velocity while height remained clamped at the ground. On takeoff the internal state would take time to become consistent with the climb. After landing, an invalid low-range measurement could leave the filter continuing to estimate a rise even while the aircraft sat motionless.

The proposed changes address how velocity is handled at the floor and when velocity decay occurs during rangefinder outages. Both issues are about consistency between an estimator's position and velocity states. Merely preventing the reported height from becoming negative does not guarantee that the internal motion estimate is sensible.

A healthy axis can conceal a rejected one

Horizontal optical flow provides two axes of movement. The navigation estimator may check and accept those components separately.

The author of pull request #33484 describes a case in which one component stopped being accepted while the other continued to update. An overall freshness check could then remain satisfied, allowing the rejected component's velocity estimate to drift. When the pilot returned to Loiter, the vehicle could respond as though it had horizontal motion that did not exist.

The proposed design tracks the components separately and only permits recovery when supporting height and flow observations are valid. The developer reports simulation tests and flights on two airframes. Those tests support a narrowly described mechanism; they do not establish a population-wide reliability rate.

For a builder interpreting flight data, a single sensor-health indicator can therefore be less informative than the separate validity and estimator status of each measurement component.

Vertical velocity has its own missing-measurement problem

A distance to the floor is not automatically an independent estimate of vertical speed. If the estimator gives reduced weight to the barometer indoors, acceleration-sensor bias can affect its velocity calculation.

ArduPilot PR #33478 proposes an optional observation derived from an above-ground-level filter to constrain vertical velocity under specified conditions. Its author reports improvement in a software-in-the-loop test with a deliberately introduced acceleration error. The feature is presented as optional, not a universal recommendation to change a stable aircraft configuration.

There is also a dependency: an estimate derived from range and inertial data is only useful while its own inputs are sound. Adding another fusion step cannot rescue measurements that lack validity checks.

What this means for builders and maintainers

The same flight can move through several measurement regimes: sitting on the floor, climbing into the camera's usable range, hovering, descending out of range and settling after touchdown. A mid-height hover test exercises only one part of that sequence.

ArduPilot's official optical-flow setup procedure warns that a bad velocity estimate can lead to sudden acceleration and calls for ample unobstructed space and an available fallback flight mode during evaluation. That caution is more valuable than a generic promise of indoor positioning.

For software maintainers, the recent proposals also show why test evidence needs to name the precise build and conditions: one change targets focus height, another the rangefinder/barometer relationship, another filter state at touchdown and another the behavior of independently gated flow axes. A fix in one area does not establish correctness in the others.

Why the distinctions matter

These are developer reports and code proposals, not proof that every stable ArduPilot release contains the changes. PX4 has a different estimator implementation, even though optical-flow measurements share the same physical limitations. The published test figures belong to their cited configurations and must be evaluated on that basis.

The recurring failure pattern is clear without overstating the evidence. A flight controller can have a functioning camera, a functioning rangefinder and a functioning position controller, yet still command a correction based on the wrong interpretation of motion. Near the floor, validity rules and estimator-state transitions deserve as much attention as the quality of the optical image.