220 lines
19 KiB
Markdown
220 lines
19 KiB
Markdown
# Lab049: отдельный ELRS для управления и SDR для видео
|
||
|
||
Актуальная архитектурная постановка от 8 сентября 2026 года:
|
||
**RadioMaster → штатный ELRS → CRSF → контроллер ровера** для управления и
|
||
критической телеметрии; отдельный SDR — для изображений и объёмных данных.
|
||
Будущие примерно 180 МГц относятся только к SDR; аппаратная лабораторная
|
||
база остаётся 1400 МГц. Стандартный ELRS не объявляется работающим на 180 МГц.
|
||
|
||
Подробный [аудит CRSF/ELRS, схема и контракт безопасности](lab049_crsf_elrs_architecture.md)
|
||
сверен с официальным ExpressLRS 4.1.0. Модели аппаратуры пока не указаны,
|
||
сопряжение контроллера с CRSF и сквозная безопасность не реализованы/не проверены.
|
||
Сохраняются локальное торможение при потере управления, аварийная защёлка,
|
||
защита от самовозобновления. Видео не обновляет таймер управления.
|
||
|
||
Прежний общий CONTROL > TELEMETRY > VIDEO — исторический стресс-тест ниже.
|
||
Его 20 CONTROL и 10 TELEMETRY в секунду **не резервируют ёмкость SDR**.
|
||
Старые программные результаты и отрицательные вердикты сохранены.
|
||
|
||
| SDR, ксимв/с | JPEG 8724 байта в идеале, кадры/с | Полезно, кбит/с |
|
||
|---|---:|---:|
|
||
| 20 | 0,09635 | 6,724 |
|
||
| 50 | 0,24088 | 16,811 |
|
||
| 100 | 0,48175 | 33,622 |
|
||
| 200 | 0,96350 | 67,245 |
|
||
|
||
Требуется **больше 3 кадров/с**: 3 — промежуточный минимум, 5 — следующий
|
||
ориентир, 10 — дальнейший. Тот же JPEG в нынешнем PHY требует соответственно
|
||
622,728 / 1037,880 / 2075,760 ксимв/с с защитными интервалами, без запаса на
|
||
потери и объёмные данные. Только JPEG: 209,376 / 348,960 / 697,920 кбит/с.
|
||
Штатная ELRS-телеметрия для такого видео недостаточна; официальные источники,
|
||
расходы по ступеням, движение и бюджет полной задержки приведены в новом отчёте.
|
||
|
||
Новый [расчётчик](../experiments/lab049_crsf_elrs_budget.py) создаёт отдельный
|
||
[crsf_elrs_budget.json](../data/processed/lab049/crsf_elrs_budget.json),
|
||
переиспользует существующие независимые замеры IQ по SHA и не запускает RF.
|
||
Он считает ELRS-возможности слотов, не измеренную задержку стики→ровер.
|
||
35 новых тестов бюджета проходят; quick_gate: 606 тестов и 13 функциональных
|
||
проверок, полный pytest: 606 passed, git diff --check: PASS. Одно предупреждение
|
||
pytest относится к доступу к `.pytest_cache`; ruff не установлен.
|
||
Независимые verifier/adversary не обнаружили воспроизведённых расхождений.
|
||
Подробности общих проверок — в записи 038.
|
||
Следующий рекомендуемый Lab050: программное профилирование и потоковая
|
||
обработка SDR-видео с ограничением возраста очереди; затем отдельное сопряжение CRSF.
|
||
|
||
## Сохранённый независимый IQ-опыт и общий стресс-тест
|
||
|
||
Актуальный программный результат от 8 сентября 2026 года: **полностью пригодного режима нет**.
|
||
Максимальная проверенная скорость с точным JPEG в идеальном и фиксированном шумном сценариях —
|
||
200 ксимв/с. Полный приёмник в шумном сценарии не успевает в реальном времени ни в одном режиме.
|
||
Это результат одного воспроизводимого сценария, не универсальная оценка предела устойчивости BPSK.
|
||
|
||
Для отдельного будущего диагностического PHY-опыта выбран **50 ксимв/с, 160 выборок/символ**:
|
||
точный JPEG, полезная скорость в 2,5 раза выше базовой и наименьшая вычислительная перегрузка
|
||
среди точных шумных проходов (1,3543). Он не готов к непрерывному объединённому каналу:
|
||
блокировка 115,32 мс, перегрузка служебным трафиком и нарушенный аварийный срок.
|
||
Это кандидат для диагностики, не разрешение RF. 100 ксимв/с лучше по блокировке, но требует
|
||
3,60 длительности IQ для обработки; 200 ксимв/с — 7,32.
|
||
|
||
## Аудит и исправления
|
||
|
||
При входе в задачу Lab049 уже существовала без коммита. Старый результат сохранён как
|
||
`data/processed/lab049/frame_aligned_result.json`; запись 036 журнала не переписана.
|
||
Они измеряли заранее выровненные кадры без остаточного CFO. Новые данные —
|
||
`data/processed/lab049/result.json` и идентичный `independent/result.json`.
|
||
[Аудит](lab049_audit.md) содержит карту функций, проверку Lab033–Lab041 и воспроизведённые отказы.
|
||
|
||
Основной RX получает целый IQ-поток без TX-границ, payload, объекта или ожидаемого числа кадров.
|
||
Используются блочный поиск и строгий декодер Lab048: `lab046c_offline_recovery.stream_process_capture`.
|
||
Сохранён порог Lab047 `0.030964473262429237`. Адаптер последовательно задаёт Rs/SPS и предоставляет
|
||
чтение синтетического complex64; исходные константы и функции возвращаются через finally.
|
||
Старый локальный `receive_iq_frame` остаётся для регрессий формы, основной проход его не использует.
|
||
|
||
Fs = 8 000 000 выборок/с. Отношения Fs/Rs точные, дробные входы и нецелое samples/symbol
|
||
отвергаются. BPSK, PRBS7, PHY header, packet/fragment, CRC, свёрточный FEC R=1/2 K=7
|
||
(171/133 octal), tail bits и перемежитель сохранены. Новый планировщик не создан, protocol не изменён.
|
||
|
||
## Канал и объект
|
||
|
||
Один JPEG Lab047: 8724 байта, RGB 320×240, SHA-256
|
||
`e913dab9ac32795250880a4be67fbbbf89a4f96536842476ab591d1acaafc02a`; без перекодирования.
|
||
Каждый проход: JPEG → фрагменты → protocol packets → FEC → interleaver → BPSK/RRC →
|
||
CS8-квантование → IQ → независимый поиск → CFO/фаза/полярность → PHY/FEC/CRC → сборка → JPEG decode.
|
||
|
||
Идеальный канал не добавляет шум/CFO. Шумный: единый coded-bit Eb/N0=7 dB,
|
||
seed=49000+номер кадра, остаточный CFO +10 Гц, фаза 0,73 рад и чередование полярности.
|
||
Eb = sum(abs(IQ)**2)/число символов; sigma² каждой компоненты шума = Eb/(2×10**(7/10)).
|
||
Нормировка одинакова во всех режимах, параметры не подбирались до PASS.
|
||
Ведущий, межкадровые и конечный интервалы не кратны символу; фон имеет отдельные фиксированные seeds.
|
||
После добавления шума IQ не переквантован в CS8, чтобы не отсекать шум.
|
||
|
||
Кадр занимает 5766 символьных интервалов с фильтром и защитными интервалами; JPEG — 36 кадров.
|
||
Длительность IQ включает ещё 0,079217625 с фона. Полезная скорость считается по чистому времени
|
||
JPEG, отношение обработки — по всей длительности IQ. Измеряются поиск, декодирование, сборка и
|
||
JPEG decode; генерация канала и TX-сравнение после вердикта исключены. Все восемь проходов
|
||
завершились END_OF_STREAM. Первый пробный прогон с лимитами Lab046B 32/256 был неполным;
|
||
итоговые результаты получены после перехода на полный блочный путь с независимыми лимитами 4096/100000.
|
||
|
||
## Результаты IQ
|
||
|
||
| Метрика | 20 ксимв/с | 50 ксимв/с | 100 ксимв/с | 200 ксимв/с |
|
||
|---|---:|---:|---:|---:|
|
||
| Выборок/символ | 400 | 160 | 80 | 40 |
|
||
| Кадр, мс | 288.300 | 115.320 | 57.660 | 28.830 |
|
||
| Кадров JPEG | 36 | 36 | 36 | 36 |
|
||
| JPEG airtime, с | 10.37880 | 4.15152 | 2.07576 | 1.03788 |
|
||
| Полезно, байт/с, идеал | 840.560 | 2101.399 | 4202.798 | 8405.596 |
|
||
| Полезно, кбит/с, идеал | 6.724 | 16.811 | 33.622 | 67.245 |
|
||
| Идеал: кадры / SHA | 36/36 / да | 36/36 / да | 36/36 / да | 36/36 / да |
|
||
| Шум: кадры | 6/36 | 36/36 | 36/36 | 36/36 |
|
||
| До FEC, принятые кадры | 67 | 147 | 119 | 125 |
|
||
| После FEC, принятые кадры | 0 | 0 | 0 | 0 |
|
||
| CRC PASS / FAIL | 6 / 0 | 36 / 0 | 36 / 0 | 36 / 0 |
|
||
| Шум: JPEG SHA / decode | нет / нет | да / да | да / да | да / да |
|
||
| Ошибки JPEG байт / бит | не восстановлен | 0 / 0 | 0 / 0 | 0 / 0 |
|
||
| Обработка идеала, с | 8.73746 | 5.69848 | 7.36877 | 6.45915 |
|
||
| Обработка шума, с | 173.65057 | 5.72980 | 7.76244 | 8.17573 |
|
||
| Длительность IQ, с | 10.458018 | 4.230738 | 2.154978 | 1.117098 |
|
||
| Обработка / IQ, шум | 16.604540 | 1.354327 | 3.602096 | 7.318724 |
|
||
| Реальное время, шум | нет | нет | нет | нет |
|
||
| Статус | FAIL | PARTIAL | PARTIAL | PARTIAL |
|
||
|
||
На 20 ксимв/с 67 ошибок до FEC и 0 после относятся **только к шести принятым кадрам**.
|
||
JPEG не восстановлен; полезная скорость целых JPEG в шумном проходе равна нулю.
|
||
Остальные 30 кадров нельзя объявлять безошибочными. Проверено 2378 кандидатов, 2372
|
||
отклонены на PHY header. На 50/100/200 проверено 59/237/474 кандидата.
|
||
Кандидат, не достигший CRC, не записан как CRC FAIL. Причины сохранены в JSON.
|
||
Порог и шум после отказов не менялись. Все идеальные проходы имеют ноль ошибок до/после FEC.
|
||
|
||
Базовые 6,724 кбит/с согласуются с примерно 6,7 кбит/с Lab047. Выигрыш 2,5/5/10
|
||
рассчитан по фактической форме и числу кадров, а не обещан заранее.
|
||
Исторические аппаратные результаты Lab047/Lab048 не опровергнуты: здесь другой канал.
|
||
|
||
## Планирование и задержки
|
||
|
||
Переиспользован LATEST_STATE: EMERGENCY > CONTROL > TELEMETRY > VIDEO.
|
||
Проверка даёт VIDEO(active) → EMERGENCY → CONTROL → TELEMETRY → VIDEO.
|
||
Физический кадр не прерывается, но весь JPEG не удерживает канал.
|
||
CONTROL — штатные 36 байт, 20 Гц (Lab041); TELEMETRY — синтетические 64 байта,
|
||
10 Гц (Lab037–Lab041); EMERGENCY — штатный EmergencyStop, 34 байта, t=0,777 с.
|
||
Служебная нагрузка генерируется 2 с. Запас VIDEO 256 пакетов не исчерпывается в этом окне.
|
||
|
||
Каждый пакет модели занимает один полный PHY-кадр. Это модель занятости;
|
||
упаковка LinkPacket в аппаратный 256-байтный PHY payload не реализована.
|
||
Прикладные CONTROL/EMERGENCY сохраняют точные сериализованные байты.
|
||
Задержки не включают программное время RX, потери, повторы и привод; это не гарантия
|
||
времени физического торможения. Блокировка — остаток начатого VIDEO;
|
||
доставка EMERGENCY в худшей фазе — почти два кадра, включая саму команду.
|
||
Старое поле deadline в priority_probe сохранено как совместимое поле блокировки
|
||
с явным scope; классификация использует новый delivery flag.
|
||
|
||
| Метрика | 20 ксимв/с | 50 ксимв/с | 100 ксимв/с | 200 ксимв/с |
|
||
|---|---:|---:|---:|---:|
|
||
| CONTROL max VIDEO blocking, мс | 288.30 | 115.32 | 57.66 | 28.83 |
|
||
| EMERGENCY max VIDEO blocking, мс | 288.30 | 115.32 | 57.66 | 28.83 |
|
||
| EMERGENCY worst delivery, мс | 576.60 | 230.64 | 115.32 | 57.66 |
|
||
| CONTROL blocking <100 / <50 мс | нет / нет | нет / нет | да / нет | да / да |
|
||
| EMERGENCY delivery ≤50 мс | нет | нет | нет | нет |
|
||
|
||
Доставка **в активном окне 0–2 с**, min / median / max, мс. Заменённые и ещё не доставленные состояния сюда не входят:
|
||
|
||
| Метрика | 20 ксимв/с | 50 ксимв/с | 100 ксимв/с | 200 ксимв/с |
|
||
|---|---:|---:|---:|---:|
|
||
| CONTROL | 289.90 / 303.20 / 316.50 | 116.92 / 136.28 / 162.88 | 58.84 / 82.03 / 105.64 | 30.01 / 43.94 / 61.07 |
|
||
| EMERGENCY | 376.20 / 376.20 / 376.20 | 145.56 / 145.56 / 145.56 | 87.90 / 87.90 / 87.90 | 30.24 / 30.24 / 30.24 |
|
||
| TELEMETRY | нет доставленных | нет доставленных | нет доставленных | 33.84 / 45.54 / 89.69 |
|
||
| VIDEO | 288.30 / 288.30 / 288.30 | 115.32 / 115.32 / 115.32 | 57.66 / 57.66 / 57.66 | 28.83 / 850.49 / 1845.12 |
|
||
|
||
Доставка **до полного опустошения очереди**, отдельно от активной нагрузки:
|
||
|
||
| Метрика | 20 ксимв/с | 50 ксимв/с | 100 ксимв/с | 200 ксимв/с |
|
||
|---|---:|---:|---:|---:|
|
||
| CONTROL, мс | 289.90 / 303.20 / 331.40 | 116.92 / 139.48 / 216.08 | 58.84 / 83.84 / 105.64 | 30.01 / 43.73 / 61.07 |
|
||
| EMERGENCY, мс | 376.20 / 376.20 / 376.20 | 145.56 / 145.56 / 145.56 | 87.90 / 87.90 / 87.90 | 30.24 / 30.24 / 30.24 |
|
||
| TELEMETRY, мс | 644.70 / 644.70 / 644.70 | 356.40 / 356.40 / 356.40 | 183.42 / 183.42 / 183.42 | 33.84 / 45.54 / 89.69 |
|
||
| VIDEO, мс | 288.30 / 39352.95 / 76111.20 | 115.32 / 17009.70 / 31713.00 | 57.66 / 9485.07 / 16836.72 | 28.83 / 5434.46 / 9110.28 |
|
||
| Конец опустошения, с | 76.11120 | 31.71300 | 16.83672 | 9.11028 |
|
||
| Превышения CONTROL / EMERGENCY | 6 / 1 | 17 / 1 | 6 / 1 | 0 / 0 |
|
||
|
||
Очередь заменяет старое ожидающее состояние, но не удаляет пакет по deadline.
|
||
На 20/50/100 за активные 2 с доставлено 0 TELEMETRY. У 200 конкретная EMERGENCY
|
||
доставлена за 30,24 мс, но худшая фаза 57,66 мс всё равно нарушает срок 50 мс.
|
||
|
||
## Исторический бюджет единого канала — не бюджет целевой архитектуры
|
||
|
||
Прикладные CONTROL/TELEMETRY: 5760/5120 бит/с; вместе с LinkPacket до PHY —
|
||
10880/7680 бит/с. Физическая стоимость: 20/10 полных кадров/с, или
|
||
**115320/57660 символьных интервалов в секунду** BPSK, включая всю форму.
|
||
Эту стоимость нельзя прямо вычитать из JPEG-бит/с: остаток считается через время эфира.
|
||
JSON-поля reserved_link_bps 46080/23040 относятся к внутренним 288-байтным
|
||
представителям планировщика, а не к физическому кодированному потоку.
|
||
|
||
| Метрика | 20 ксимв/с | 50 ксимв/с | 100 ксимв/с | 200 ксимв/с |
|
||
|---|---:|---:|---:|---:|
|
||
| CONTROL, запрошено % эфира | 576.60 | 230.64 | 115.32 | 57.66 |
|
||
| TELEMETRY, запрошено % эфира | 288.30 | 115.32 | 57.66 | 28.83 |
|
||
| EMERGENCY, событие/2с, % эфира | 14.415 | 5.766 | 2.883 | 1.442 |
|
||
| VIDEO после C+T, кбит/с | 0.000 | 0.000 | 0.000 | 9.085 |
|
||
| Теоретические JPEG/с после C+T | 0.00000 | 0.00000 | 0.00000 | 0.13017 |
|
||
| VIDEO после C+T+E, кбит/с | 0.000 | 0.000 | 0.000 | 8.115 |
|
||
|
||
Процент больше 100 означает перегрузку, а не фактически переданные данные.
|
||
Только 200 оставляет VIDEO: 9,085 кбит/с и около 0,1302 JPEG/с;
|
||
с одной EMERGENCY за 2 с — 8,116 кбит/с. Это потенциал модели, не видеопоток:
|
||
вычислительная перегрузка и аварийный срок остаются.
|
||
|
||
## Проверки предыдущего IQ-этапа
|
||
|
||
Независимые verifier/adversary воспроизвели прежние отказы и подтвердили исправления.
|
||
Verifier: 24 целевых теста PASS, независимый пересчёт JSON совпал.
|
||
Adversary: правильный отрицательный аварийный вердикт и отдельное активное окно.
|
||
|
||
- python tools/quick_gate.py: PASS, 571 тест ядра, 12 функциональных проверок.
|
||
- python -m pytest tests/ -q: 571 passed, 0 failed; одно предупреждение о запрете записи .pytest_cache.
|
||
- git diff --check: PASS.
|
||
|
||
RF TX = 0. HackRF не запускался. Git add/commit/push/pull/fetch не выполнялись.
|
||
STOP. Следующий этап требует отдельной постановки: вычислительная перегрузка,
|
||
бюджет и задержки перед аппаратным опытом. QPSK, новый FEC, реальное видео и
|
||
переход на 180 МГц в этой работе не выполнялись.
|