Adaptive video link: energy-min controller + SVC-HEVC UEP pipeline#115
Merged
Conversation
Energy-minimizing adaptive link for the drone VTX -> ground VRX video
downlink — the dual of OpenIPC's alink: instead of maximizing quality
within a power budget, it minimizes energy-per-delivered-bit subject to a
per-layer UEP delivery SLA (base/IDR >= 99%, enhancement best-effort).
Control stack (tools/precoder/, Python, reuses the committed fused-FEC
modules):
- energy_model / link_model: airtime x power E_bit and SNR -> P_deliver,
with a documented nominal calibration ("model now, meter later").
- op_table / controller: argmin-e_bit over SLA-feasible rows; TXAGC chosen
as the minimum that clears the MCS; path-loss (not SNR) asymmetric EWMA;
slow-up/fast-down hysteresis; MAX_RANGE failsafe. SvcController bank adds
per-temporal-layer targets + enhancement shedding + one shared PA power.
- rc_proto / score / rendezvous: CRC16-guarded RCF/DISC codec, post-FEC
residual-loss scoring, receiver-initiated low-duty discovery.
- adaptive_link.py: --role vtx|vrx orchestrator driving StreamDuplexDemo.
SVC-HEVC pipeline:
- tests/gen_svc_nals.py: importable synthetic HEVC source (realistic VBR
per-layer sizes, 4:8:16 T0/T1/T2 + IDR access units).
- svc_uep_fec.py: opt-in NAL fragmentation/reassembly so real-sized NALs
ride symbol-sized FEC packets (default off; existing behavior unchanged).
- svc_pipeline.py: end-to-end encode -> per-layer (MCS,SNR) sub-block
corruption -> SBI salvage -> decode, plus a closed-loop adaptive variant
driven by SvcController.
C++: StreamDuplexDemo gains a stdin control-opcode escape (SET_PWR /
SET_RATE / SET_CHAN) so the Python policy moves the knobs with no USB
churn or restart.
Verification:
- tests/sim_loop.py headline: 34% energy/bit saved vs the best static
energy-min profile, 53% vs an over-provisioned robust profile, delivery
0.999, no flapping.
- New .github/workflows/precoder-tests.yml runs the whole precoder suite
(uv + swif build + pytest) headlessly in CI; 205 tests pass.
- On-air harness tests/adaptive_onair.sh (8812 VTX <-> 8821 VRX + B210
interferer), witnessed by the peer's own rate=/rssi=.
Docs: docs/adaptive-link.md — the design plus a competitive comparison
(wfb-ng, OpenIPC alink, RubyFPV, OpenHD, DJI OcuSync) and feature matrix.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Replace hardcoded ~/git/devourer absolute paths with __file__-relative ones (sim_loop, calibrate_energy, test_controller, adaptive_link --duplex default) so the code works regardless of clone location; test_controller no longer relies on another test's sys.path side-effect. - Rewrite docs/adaptive-link.md as a balanced comparison of the field (wfb-ng, OpenIPC alink, RubyFPV, OpenHD, DJI) rather than an alink-centric piece; drop implementation details (file paths, APIs, config constants); fix the inaccurate "video link is one-way" framing — the video is one-way broadcast but the link is two-way (RC up / telemetry down, feedback rides the return channel). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
An energy-minimizing adaptive link for the drone VTX → ground VRX video downlink — the dual of OpenIPC's
alink. Wherealinkmaximizes video quality within a power budget, this minimizes energy-per-delivered-bit subject to a per-layer UEP delivery SLA (base/IDR ≥ 99 %, enhancement best-effort). It rides the highest MCS the link bears (short airtime) and spends only the minimum TX power that clears it — the opposite reflex of a throughput-maximizer.All userspace: policy in Python (
tools/precoder/), reusing the already-merged fused-FEC modules (#113/#114); the C++ demo gains only mechanical control hooks.Pieces
Control stack (
tools/precoder/)energy_model/link_model— airtime×powerE_bit, SNR→P_deliver; documented nominal calibration with a metered-JSON hook ("model now, meter later").op_table/controller— argmin-e_bitover SLA-feasible rows, TXAGC = minimum that clears the MCS, path-loss (not SNR) asymmetric EWMA, slow-up/fast-down hysteresis, MAX_RANGE failsafe.SvcControllerbank adds per-temporal-layer targets, enhancement shedding, one shared PA power.rc_proto/score/rendezvous— CRC16-guarded RCF/DISC codec, post-FEC residual-loss scoring, receiver-initiated low-duty discovery.adaptive_link.py—--role vtx|vrxorchestrator drivingStreamDuplexDemo.SVC-HEVC pipeline
tests/gen_svc_nals.py— importable synthetic HEVC source (realistic per-layer VBR sizes; 4:8:16 T0/T1/T2 + IDR access units).svc_uep_fec.py— opt-in NAL fragmentation/reassembly so real-sized NALs ride symbol-sized FEC packets (default off; existing behavior byte-identical).svc_pipeline.py— end-to-end encode → per-layer (MCS,SNR) sub-block corruption → SBI salvage → decode, plus a closed-loop adaptive variant driven bySvcController.C++ —
StreamDuplexDemogains a stdin control-opcode escape (SET_PWR/SET_RATE/SET_CHAN) so the Python policy moves the knobs with no USB churn or restart.Results
tests/sim_loop.pyheadline (fly-out-and-back): 34 % energy/bit saved vs the best static energy-min profile, 53 % vs an over-provisioned robust profile, delivery 0.999, 2 operating-point changes over 200 ticks (no flapping)..github/workflows/precoder-tests.ymlruns the whole precoder suite (uv + swif build + pytest) headlessly in CI — 205 tests pass.tests/adaptive_onair.sh(8812 VTX ↔ 8821 VRX + B210 interferer), witnessed by the peer's ownrate=/rssi=.Docs
docs/adaptive-link.md— the design plus a competitive comparison and feature matrix across wfb-ng, OpenIPC alink, RubyFPV, OpenHD, DJI OcuSync. The two axes unique to this link: it makes energy the objective and does per-temporal-layer UEP (PHY-MCS ⊕ FEC ladder + shedding) + corrupt-frame salvage.Scope notes
SvcTxDemo); the adaptive SVC path (VRX retuning the per-layer ladder live via per-frame layer-tagged radiotap) is the named integration point.🤖 Generated with Claude Code