Module map
Start-up
- Merge the static config with the live per-drone keys and start the config watcher. The watcher polls the store once a second; on a change it exits with status 75 and the unit’s restart policy brings the plugin back on the new config.
- Register MAVLink component 198 as kind
vio. The registration needs themavlink.component.viopermission, which the manifest requests. - Subscribe to the flight controller streams the modes need. A refused subscription is recorded in
degradedReasons. - Start the ticks: TIMESYNC (1 Hz), the companion
HEARTBEAT(1 Hz), the health publish (1 Hz), andMAV_CMD_SET_MESSAGE_INTERVALrequests forRAW_IMUat 100 Hz andDISTANCE_SENSORat 20 Hz, repeated every 30 s so a flight controller reboot does not drop them. - Run the estimator on every frame pair from the vision frame bus. While the plugin reads frames, the vision tap holds a hero lease on the video encoder, so a drone on the thumbnail profile still encodes at the hero frame rate. The lease has no expiry and ends when the engine detaches.
The estimator contract
Every estimator answersstep(...) with one EstimatorOutput:
off returns an empty None sample and emits nothing. The two optical-flow estimators fill the flow fields.
A frame becomes a MAVLink message
The scale ladder
scale::ScaleLadder serves optical_flow_degraded. Each pick() returns the first healthy rung:
degraded on the static rung whatever the raw quality.
The pre-arm gate
pre_arm::PreArmGate::evaluate() is a pure function: no MAVLink, no filesystem, no async. It returns a report of checks, each ok, pending or blocking with a detail string, and an armable flag that is true only when every check is ok.
off: no checks.optical_flow:companion_active,flow_quality(at or above the gate),rangefinder(a configured topology and a fresh reading inside the sensor’s min-max range).optical_flow_degraded:companion_active,flow_quality,scale_source(rangefinder,baro,gpsorvision;staticblocks).
Companion state
The companion state drives the component-198HEARTBEAT system_status:
A converged estimator makes the companion active. A 2 s
degraded or failed streak, or 2 s with no frames, makes it critical.
The navigation heartbeat
Once a second the plugin publishes anavigation block through ctx.telemetry.extend. Losing frames or getting them back publishes the block at once instead of waiting for the next tick. Keys are camelCase end to end; a snake_case key is dropped at the cloud relay.
Adding an estimator
- Implement the
Estimatortrait inestimators.rs(or a new module). - Add its id to
available_estimators()so the heartbeat advertises it. - Add the mode variant to
Modeinconfig.rs, and to themodeenum inconfig-schema.json. - Add a branch to
PreArmGate::evaluate()with the checks the new mode needs. - Add the mode to the GCS mode card.
- Write tests for its state machine and output shape.
Next steps
Vision plugins
The vision frame bus and detection APIs for plugin authors.
Overview
Back to the start of the Vision Navigation guide.