Skip to main content
WFB-ng (WiFi Broadcast next generation) is the radio link the agent uses for long-range video and MAVLink. It is not standard WiFi. It broadcasts raw 802.11 frames in monitor mode with forward error correction (FEC). Expect 1-3 km on stock antennas; much longer with a high-gain ground antenna and clear line of sight. The agent runs the link itself: ados-wfb transmits on a drone and ados-wfb-rx receives on a ground station, both driven by the native ados-radio binary. No OpenHD or other wrapper is required.

How it works

Standard WiFi needs a two-way handshake (connect, authenticate, associate), which limits range to the distance at which both sides hear each other reliably. WFB-ng skips the handshake. The transmitter broadcasts one way and the receiver decodes whatever it hears.

Hardware

WiFi adapter

The supported chipset is the RTL8812EU (5 GHz, 802.11ac). It supports monitor mode and packet injection. The agent starts at 5 dBm and clamps to tx_power_max_dbm (15 by default); see TX power. List the adapters the agent sees and its injection verdict for each:
The RTL8812EU needs an out-of-tree kernel driver (module 8812eu). The installer builds it on supported boards. If the module is missing, for example after a kernel upgrade, rebuild it with sudo ados radio install-driver --force.

Antennas

The adapter’s built-in antenna is for bench testing. For flight, use external antennas:
  • Air side (drone): omnidirectional dipole, 3-5 dBi. The drone moves in every direction, so omnidirectional coverage matters.
  • Ground side: directional patch or panel antenna, pointed at the drone.
Range depends mostly on the ground antenna. Stock antennas give 1-3 km line of sight. A high-gain ground antenna, a clear line of sight and a higher TX power ceiling extend that; treat any long-range figure as a ceiling under good conditions, not a default.

Configuration

The radio reads the video.wfb block of /etc/ados/config.yaml when it starts. A typical drone block with the shipped defaults:
Change one key over the REST API, then restart the radio unit so it re-reads the block (ados-wfb on a drone, ados-wfb-rx on a ground station):
While the vehicle is armed, the agent refuses radio writes that can drop the link: channel hop, TX power, radio unpair, opening a local bind, and PUT /api/config of a radio or regulatory key. Each answers 409 with E_ARMED unless the caller sets "force": true (or ?force=1). Make radio changes on the ground.
With the defaults the agent picks channels, bitrate and MCS itself. Manual tuning is only needed to pin a value.

Home channel and auto-hop

channel is the home (rendezvous) channel. Drone and ground station both start there and return there when they lose each other, so they always meet before any hopping. The default, 149 (5745 MHz, U-NII-3), is non-DFS and allowed under most regulatory domains. With auto_hop_enabled: true (the default) the drone moves the link to the quietest channel inside band:
  • Periodic: a rescan every hop_period_seconds (60 s).
  • Reactive: an off-schedule hop when packet loss reaches hop_loss_threshold_percent (10 %) or RSSI falls to hop_rssi_threshold_dbm (-75 dBm), once the link has been stable on the current channel for at least 30 s.
  • Coordinated: the drone broadcasts an authenticated hop announcement and flips about 3 s later, after the ground station acknowledges. It does not hop at all until it has heard a ground station acknowledge once.
  • Return home: when the peer has been silent for more than 25 s, the drone goes back to the home channel.
Hop by hand with ados radio hop <channel> or POST /api/wfb/channel. The route answers 202 once the coordinated hop is initiated; read the operating channel from ados radio status. Set auto_hop_enabled: false to pin the link to channel.

Band

band limits the hop candidates. auto_channel_enabled (default false) makes the agent scan band on a fresh bind and write the quietest channel into the config before the radio starts. Leave it off unless both rigs share a domain; with it on, the two sides can pick different channels.

Adaptive bitrate and MCS

With adaptive_bitrate_enabled: true (the default) a 1 Hz controller watches link quality and drives two ladders:
  • Bitrate and FEC, on packet loss and RSSI with hysteresis: 4 Mbps at 8/12, 3 Mbps at 8/14, 2 Mbps at 8/16, 1.2 Mbps at 4/12. Each rung caps the video encoder, so a degrading link puts fewer bytes on the air.
  • MCS, on measured SNR: MCS 5 at 30 dB or more, 4 at 24, 3 at 21, 2 at 15, otherwise MCS 1. adaptive_mcs_max (default 3, range 1-5) caps the top rung.
Changes go to the running wfb_tx over its management socket, so a rung change costs no video blackout; a restart of about 1-2 s is the fallback when the socket does not answer. A drone with no ground station reporting statistics holds its rung, so the controller does nothing until a ground station is present. Set adaptive_bitrate_enabled: false to run fixed values. wfb_link_preset sets MCS and FEC together: With conservative selected, explicit mcs_index, fec_k and fec_n values in the config take precedence, so a rig with custom values keeps them.

Fleet addressing

fleet_id (1-65535) names the fleet and fleet_slot names the node in it: 0 for the ground station, 1-24 for drones. Together they form the WFB-ng link id, so two fleets can share a channel. The ground station issues a drone’s slot at bind time and writes it into the drone’s config; it is never negotiated at runtime. Two drones with the same slot thrash each other’s FEC decoder, which looks like unexplained link loss. The swarm bus uses the same addressing.

Operating region

By default the radio is unrestricted and you are responsible for compliance. Pin an operating region (ados network regulatory region <CC> or dashboard Settings → Region) to have the agent apply that country’s channels and power limits.
The posture lives in network.regulatory (mode: unrestricted | region, region: <ISO 3166-1 alpha-2>). With a region pinned, the radio refuses to transmit on a channel that region forbids. Restart the agent after a change. Separately, video.wfb.reg_domain (default US) is the kernel regulatory domain set on both rigs before the radio enters monitor mode, so that drone and ground station enable the same channels at usable power. Set it to your country code if 149 needs a different domain where you fly. The power ceiling and brownout clamps below apply in either posture.

TX power

Default 5 dBm, clamped to tx_power_max_dbm (15). Raise with ados radio set-tx-power <dbm> or PUT /api/wfb/tx-power after validating the link. Above about 18 dBm a USB-VBUS-powered RTL8812EU can brown out; use topology: powered_hub or external_5v first.
  • A value above tx_power_max_dbm is refused (400, above_ceiling); a value below 1 dBm is refused (below_floor).
  • An accepted value is applied to the running radio and written to video.wfb.tx_power_dbm, so it survives a restart.
  • To go above 15 dBm, raise tx_power_max_dbm in the config first, on a powered supply.
  • Mission Control’s node Radio panel has a TX power slider that uses the same route.
The legacy tx_power key from older configs is ignored. It never set radio power, so it is dropped rather than migrated; use tx_power_dbm.

FEC tuning

fec_k is the number of data blocks and fec_n the total (data plus parity). The ratio sets how much packet loss a block survives. More parity buys resilience at the cost of airtime. With adaptive bitrate on, the controller chooses FEC from its ladder; with a preset, the preset chooses.

Key model

The drone holds tx.key and the ground station rx.key, complementary halves of one key pair created by a bind. They are not identical files. Compare the fingerprint in ados radio pair status on both nodes instead. A ground station holds one receive key for its fleet; drones are distinguished by video.wfb.fleet_slot. You never edit key files by hand: a bind writes them and ados radio pair unpair wipes them. See WFB-ng pairing for the bind itself and Swarm bus for the fleet key.
ados diag link reports whether the radio decodes its peer (healthy, searching, deaf, mis_keyed, jammed) and leads with LOSSY at 2 % measured loss. See Drone Agent diagnostics. The same data is on the agent dashboard’s WFB Transmit page (drone) and WFB Receive page (ground station), in Mission Control’s node Radio panel, and at GET /api/wfb.

Distributed receive on the ground

The drone always transmits with wfb_tx. A ground station receives in one of three roles:
  • direct: single node running plain wfb_rx. The default.
  • relay: forwards the fragments it hears over the local mesh to a receiver.
  • receiver: aggregates fragments from its own radio and every paired relay, then runs one FEC combine across the merged stream.
The same receive key works in all three roles. See Mesh overview and Pick a role.

Troubleshooting

Run lsusb and look for the Realtek device, then check the driver:
If the module is absent, rebuild it with sudo ados radio install-driver --force. Use a direct USB port; a passive hub can starve the adapter.
Check the antenna connections and the ground antenna’s pointing. Check tx_power_dbm against your power topology: on host_vbus stay at or below 15 dBm. Run ados diag link on the ground station; with auto-hop on, the link already moves off a congested channel.
ados diag link reporting mis_keyed, or a climbing decrypt error count, means the two nodes hold keys from different binds. Compare the fingerprint in ados radio pair status on both, then re-bind them. See WFB-ng pairing.
A climbing FEC failed count means the link is at the edge of range or under interference. Leave adaptive bitrate on so the controller can step down, use a directional ground antenna, or choose a lower-throughput preset.

Next steps

WFB-ng pairing

How a drone and a ground station bind and exchange keys.

Swarm bus

The fleet beacon that rides the same radio and fleet key.

Drone Agent diagnostics

Per-hop verdicts for the video pipeline and the radio link.

Operating region

Your responsibilities for legal RF operation.
Last modified on October 11, 2026