Skip to content

Adaptive channel migration for fixed-channel video links#311

Merged
josephnef merged 1 commit into
masterfrom
chanmig
Jul 19, 2026
Merged

Adaptive channel migration for fixed-channel video links#311
josephnef merged 1 commit into
masterfrom
chanmig

Conversation

@josephnef

Copy link
Copy Markdown
Collaborator

Slow, evidence-driven whole-link channel migration for a fixed-channel FPV video link — the deliberate complement to per-slot FHSS. The link normally sits on one channel and moves rarely, only when a second radio has proven a better home exists. Five composable, independently useful layers, all pure caller-side logic under src/chanmig/ (header-mostly, each ctest-covered; the library reads no environment — the demos map it).

What it adds

  • Passive dual-radio spectrum scout (chanscout). A second adapter continuously surveys a candidate-channel plan while the primary receiver stays parked on the live video channel. Measures and records only — it retunes nothing but its own adapter and issues no channel-change command. A discard barrier makes each versioned survey record's FA/CCA counters (which are delta-on-read) span exactly its observation window on one bin, and decoded airtime is split into recognized-own-video vs foreign so wanted airtime is never read as interference. Grid-legality validation only — no regulatory database; the caller owns compliance.
  • Advisory recommendation engine (ChannelScore). A pure two-leg policy: the primary receiver's delivery is authoritative on the active channel (scout energy there is confounded by wanted video), the scout's occupancy on candidates. A move needs persistent channel-attributable impairment AND a materially cleaner, sufficiently observed candidate — never a single threshold; weak-signal and near-field saturation are held as non-channel faults. Every decision cites an evidence generation + plan/policy hash and is explainable from the logs (a stdlib dashboard and a shadow-mode confusion-matrix replay render purely from them).
  • Authenticated coordinated migration protocol. Ground proposes; the drone video transmitter validates and is the final schedule authority. A SipHash-MAC'd byte-packed wire codec, random per-boot epochs (no persisted in-flight state), and pure proposer/responder state machines. Two rules make every failure case converge without split-brain: the drone arms activation only after the ground echoes its nonce, and the ground follows the drone's authoritative status rather than declaring success unilaterally. Control frames are their own canonical-SA 802.11 frames — video payload bytes are never touched.
  • Conservative autonomous policy (MigGate). Modes off / advisory / manual / automatic (default advisory); a pure deterministic gate that proposes only under a conservative conjunction and hedges every move with cooldown, residency, per-channel exponential backoff, a session move cap, probation, and an operator kill switch. Fault-domain classification keeps migration from being used to "fix" a weak signal, broad interference, saturation, or a USB/scout fault.
  • Optional drone-side target validation. Legality/caps checks (the product default) reject an unsupported target before commit at zero cost; an opt-in abort-safe single-radio pre-commit probe is retained as research (it costs a real, measured video outage), and a post-switch probation window covers the after-the-fact case. The drone's result is reporting-only.

Validation

  • Headless (exhaustive): a failure matrix that drops, duplicates, reorders, replays, and restarts every message and endpoint and proves both ends converge to a shared channel with no lasting split-brain; known-answer wire vectors with a byte-flip tamper sweep; the scoring and gate scenario matrices with a determinism guarantee. All selftests green.
  • On hardware: the scout's ≥10,000-retune stress runs wedge-free (post-run adapter graded healthy), and the control wire codec decodes and authenticates end-to-end. The RX frame's trailing FCS and the demo's multi-thread state-machine access were the two bring-up bugs found and fixed, now pinned by tests.
  • Bench note: the on-air whole-link migration endurance needs a decoupled adapter pair — a near-field pair saturates the RX front end and the reverse control path is intermittent, and the in-tree rtw88/rtw89 modules must be unbound (they auto-probe on every enumeration).

Docs

docs/adaptive-channel-migration.md, docs/channel-migration-protocol.md, docs/channel-migration-validation.md, the event registry in docs/logging.md, and a CLAUDE.md capability section.

🤖 Generated with Claude Code

Slow, evidence-driven whole-link channel migration — the deliberate
complement to per-slot FHSS. A fixed FPV video link normally sits on one
channel and moves rarely, only when a second radio has proven a better home
exists. Five composable, independently useful layers, all pure caller-side
logic under src/chanmig/ (namespace devourer::chanmig, header-mostly, each
ctest-covered; the library reads no environment — the demos map it).

Passive dual-radio spectrum scout (chanscout). A second adapter continuously
surveys a configured candidate-channel plan while the primary receiver stays
parked on the live video channel. It measures and records only; it retunes
nothing but its own scout adapter and issues no channel-change command. The
dwell executor performs a discard barrier (the FA/CCA counters are
delta-on-read) so each versioned survey record's counters span exactly its
observation window on exactly one bin, and it splits decoded airtime into
recognized-own-video vs foreign so wanted airtime is never mistaken for
interference. Grid-legality validation only — there is no regulatory database
anywhere; the caller owns compliance and no-IR/DFS are pass-through flags.

Advisory recommendation engine (ChannelScore). A pure two-leg policy: the
primary receiver's delivery is authoritative on the active channel (scout
energy there is confounded by wanted video), the scout's occupancy on
candidates. A recommendation needs persistent channel-attributable impairment
AND a sufficiently observed, materially cleaner candidate — never a single
threshold. Weak-signal and near-field saturation are held as non-channel
faults. Every decision cites an evidence generation, plan hash, and policy
hash and is explainable from logged score components (a stdlib dashboard and a
shadow-mode confusion-matrix replay render entirely from the logs).

Authenticated coordinated migration protocol. Ground proposes; the drone video
transmitter validates and is the final schedule authority. A SipHash-MAC'd
byte-packed wire codec, random per-boot epochs (no persisted in-flight state),
and pure proposer/responder state machines. Two rules make every failure case
converge without split-brain: the drone arms activation only after the ground
echoes its nonce, and the ground follows the drone's authoritative status
rather than declaring success unilaterally. Control frames are their own
canonical-SA 802.11 frames — video payload bytes are never touched. Activation
schedules from a relative TSF offset (no clock translation); the activation
guard is composed from measured residual/drain/retune percentiles.

Conservative autonomous policy (MigGate). Modes off / advisory / manual /
automatic (default advisory), a pure deterministic gate that proposes only
under a conservative conjunction and hedges every move with cooldown,
residency, per-channel exponential backoff, a session move cap, probation, and
an operator kill switch (mode / approve-next / inhibit / pin). Fault-domain
classification keeps migration from being used to "fix" a weak signal, broad
interference, saturation, or a USB/scout fault.

Optional drone-side target validation. Legality/caps checks (the product
default) reject an unsupported target before commit at zero cost; an opt-in,
abort-safe single-radio pre-commit probe is retained as research (it costs a
real, measured video outage), and a post-switch probation window covers the
after-the-fact case. The drone's result is reporting-only — the ground logs it
and flags asymmetric-interference disagreements but never applies a target
from it.

Validated headless by an exhaustive selftest suite — a failure matrix that
drops, duplicates, reorders, replays, and restarts every message and endpoint
and proves both ends converge to a shared channel with no lasting split-brain;
known-answer wire vectors with a byte-flip tamper sweep; the scoring and gate
scenario matrices with a determinism guarantee. On hardware: the scout's
>=10,000-retune stress runs wedge-free, and the control wire codec decodes and
authenticates end-to-end (the RX frame's trailing FCS and the demo's
multi-thread state-machine access were the two bring-up bugs, now pinned by
tests). Bench note: the on-air whole-link migration endurance needs a decoupled
adapter pair — a near-field pair saturates the RX front end and the reverse
control path is intermittent.

Docs: docs/adaptive-channel-migration.md, docs/channel-migration-protocol.md,
docs/channel-migration-validation.md, plus the event registry in
docs/logging.md and a CLAUDE.md capability section.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant