Lab050: model fresh-frame SDR video stream
This commit is contained in:
@@ -240,6 +240,41 @@
|
||||
- **Далее:** программный Lab050 — профиль RX, поток видео и ограничение возраста очереди.
|
||||
- **RF:** RF TX = 0, STOP.
|
||||
|
||||
## Lab050
|
||||
|
||||
- **Цель:** последовательность JPEG через отдельный SDR-транспорт, ограничение
|
||||
возраста изображения и блочный независимый IQ-приём. Управление ELRS отдельно.
|
||||
- **База:** Lab049 закреплена коммитом
|
||||
`cdf5396e807b83f82a264632dc46f71428fcd616`; Lab050 не добавлена в индекс и не коммитилась.
|
||||
- **Переиспользовано:** планировщик Lab035 с LATEST_ONLY и завершением активного
|
||||
изображения. Добавлены готовность JPEG отдельно от съёмки, произвольный предел
|
||||
возраста и прогноз RX. Поздно готовый старый снимок не вытесняет свежий.
|
||||
- **Профили:** A 320×240 RGB q35 — 8724 байта; B 160×120 RGB q35 — 2771;
|
||||
C 128×96 RGB q25 — 1740; D 160×120 grayscale q30 — 2028. По 30
|
||||
детерминированных сдвигов исходного фото; это не видео камеры.
|
||||
- **Матрица:** 240 сценариев, вход 3/5/10 кадров/с, Rs=200/400/500/800/1000 ксимв/с,
|
||||
MAX_VIDEO_AGE=200/333/500/1000 мс. Ожидающая очередь ≤1.
|
||||
- **Идеальная модель:** C/500k — 5 или 10 свежих кадров/с, возраст около 92,6 мс.
|
||||
При камере 10 и Rs=200k, возрасте 333 мс: 14 передач, 16 замен, 4,333 свежих
|
||||
кадра/с внутри окна и один дополнительный после него.
|
||||
- **Потоковый RX:** 24/24 RF-пакета и 3/3 точных JPEG до `finish` на каждой скорости;
|
||||
IQ-память ограничена. В шумном опыте processing/RF = 44,322 / 147,986 /
|
||||
170,374 / 295,095 / 333,865. Реального времени нет.
|
||||
- **Память:** удерживаемые IQ 2,13–6,51 МиБ; расчёт массивов 47,5–143,4 МиБ,
|
||||
не измеренный RSS. Состояние RX не растёт вместе с длиной сессии.
|
||||
- **Достижимость:** 5/10 кадров/с без QPSK — CONDITIONAL. C≤1952 байт,
|
||||
500 ксимв/с, стоимость RX-пакета ≤16/12 мс для модели возраста 200 мс;
|
||||
требуется ещё примерно 144/192-кратное ускорение относительно этого замера.
|
||||
- **Код:** [видеомодель](../experiments/lab050_video_stream.py),
|
||||
[потоковый RX](../experiments/lab050_streaming_receiver.py).
|
||||
- **Проверки:** [44 теста Lab050](../tests/test_lab050_video_stream.py),
|
||||
quick_gate — 650 тестов и 14 функциональных проверок; независимые verifier/adversary.
|
||||
- **Отчёт:** [состояние](lab050_current_state.md),
|
||||
[JSON](../data/processed/lab050/result.json),
|
||||
[замеры RX](../data/processed/lab050/receiver_benchmarks.json). Журнал: запись 039.
|
||||
- **Далее:** Lab051 — профиль и ускорение строгой обработки ложных кандидатов.
|
||||
- **RF:** RF TX = 0. Lab050 commit/push не выполнялись. STOP.
|
||||
|
||||
## Правило хранения данных
|
||||
|
||||
Большие записи IQ, потоки `cs8`, бинарные объекты и другие аппаратные исходные
|
||||
|
||||
379
docs/lab050_current_state.md
Normal file
379
docs/lab050_current_state.md
Normal file
@@ -0,0 +1,379 @@
|
||||
# Lab050: потоковая архитектура видео и возраст изображения
|
||||
|
||||
8 сентября 2026 года. SOFTWARE ONLY. RF TX = 0. Оборудование не запускалось
|
||||
и не инвентаризировалось. Управление ELRS/CRSF и SDR-видео остаются раздельными.
|
||||
|
||||
**Получен блочный независимый RX с ограниченным IQ-буфером и модель свежей
|
||||
видеопередачи. Текущий RX не обеспечивает 5 или 10 свежих изображений/с.**
|
||||
По времени радио оба уровня возможны на уменьшенном JPEG без QPSK; итог
|
||||
полной системы — CONDITIONAL, с конкретными ещё не выполненными условиями ниже.
|
||||
|
||||
## Фиксация Lab049 и исходный аудит
|
||||
|
||||
Исходный HEAD `ac6cc792b896e34f7dd6d291955a0387fdafcf41`, ветка main.
|
||||
Проверены status, diff/stat, diff/check и точный staged scope. В отдельный
|
||||
коммит вошли 12 файлов Lab049: три скрипта, три файла тестов, три отчёта,
|
||||
README, PROJECT_LOG и LABS_INDEX. Сгенерированные данные, `.codex`, локальные
|
||||
AGENTS/CLAUDE и посторонние файлы не добавлены.
|
||||
|
||||
Создан разрешённый коммит:
|
||||
`cdf5396e807b83f82a264632dc46f71428fcd616`
|
||||
— `Lab049: define ELRS control and SDR video architecture`.
|
||||
От него выполнена Lab050; её изменения не добавлялись в индекс и не коммитились.
|
||||
Push/pull/fetch не выполнялись.
|
||||
|
||||
Аудит Lab034–037 и связанных модулей показал:
|
||||
|
||||
| Уже существовало | Как используется в Lab050 |
|
||||
|---|---|
|
||||
| `image_fragments.py`, Lab046: image ID, индекс/число фрагментов, размер объекта | Неизменная фрагментация JPEG, отдельный ID каждого снимка |
|
||||
| Lab034: группировка изображения и изоляция стирающего FEC | Переиспользована семантика границ изображения; старый 12+3 FEC не включён |
|
||||
| Lab035, `video_frame_scheduler.py`: активный кадр, очередь ожидающих, LATEST_ONLY, прогноз завершения | Расширен существующий планировщик; новая независимая очередь не создана |
|
||||
| Lab036–037: один самый свежий ожидающий кадр, завершение активного | Сохранена политика; очередь ожидающих не больше одного изображения |
|
||||
| Lab048: корреляционный поиск и строгий PHY/FEC/CRC | Использованы в блочном API; чтение IQ отделено от memmap |
|
||||
|
||||
Изменения кода: `protocol/video_frame_scheduler.py` получает готовность JPEG
|
||||
отдельно от времени съёмки, произвольный MAX_VIDEO_AGE и прогноз задержки после
|
||||
радио. Старые вызовы и все пять прежних политик сохраняют поведение.
|
||||
`lab046c_offline_recovery.decode_candidate_from_memmap` принимает необязательный
|
||||
читатель IQ; прежнее чтение CS8 остаётся поведением по умолчанию.
|
||||
Новые файлы: [модель и эксперимент](../experiments/lab050_video_stream.py),
|
||||
[блочный RX](../experiments/lab050_streaming_receiver.py),
|
||||
[тесты](../tests/test_lab050_video_stream.py).
|
||||
|
||||
## Политика свежести
|
||||
|
||||
Активное изображение является выбранной атомарной единицей обслуживания:
|
||||
после допуска оно завершается целиком. Отдельный физический пакет тем более
|
||||
не прерывается. Во время передачи каждого пакета принимаются события готовности
|
||||
новых JPEG и заменяется ожидающий снимок. При постоянной скорости, отсутствии
|
||||
CONTROL в SDR и известном числе пакетов точный прогноз допуска позволяет
|
||||
не начинать изображение, уже не укладывающееся в возраст.
|
||||
|
||||
Свежесть определяется парой `(capture_timestamp, image_id)`, а не порядком
|
||||
завершения кодирования. Поздно готовый старый снимок не вытесняет более свежий
|
||||
и не возвращается на экран после опустошения очереди. Обнаруженный независимыми
|
||||
проверяющими отказ этого правила исправлен и покрыт двумя регрессиями.
|
||||
|
||||
Причины удаления различаются: `replaced_by_newest`, `older_capture_arrived_late`,
|
||||
`prediction_reject`; при оценке загруженного RX возможен также отказ допуска
|
||||
к обработке. Если уже нижняя оценка задержки RX делает кадр просроченным,
|
||||
его отклоняет TX-допуск, до занятия эфира. Удаление снимков — нормальная
|
||||
политика видео, а не потеря обязательной управляющей команды.
|
||||
|
||||
Планировщик здесь остаётся событийной моделью с известными входами и историей
|
||||
для отчёта. Его массив входов/результатов зависит от числа исследуемых кадров;
|
||||
**логическая ожидающая очередь** ограничена одним снимком. Готового адаптера
|
||||
живой камеры с ограниченным журналом пока нет. Независимость памяти от длины
|
||||
сессии реализована и проверена непосредственно для IQ-приёмника.
|
||||
|
||||
## Профили JPEG и источник
|
||||
|
||||
Источник — реальное фото `data/raw/lab011_scene.jpg`. Для каждого профиля
|
||||
созданы 30 исходных кадров: первый повторяет исходную подготовку, остальные
|
||||
получены детерминированным циклическим сдвигом `(7i mod 61, 3i mod 31)` пикселей
|
||||
до уменьшения. Это искусственная последовательность одного фото, не съёмка камеры.
|
||||
Разрешение, цвет и quality фиксированы; размеры файлов не подбирались вручную.
|
||||
Во всех профилях subsampling=2, optimize=False, progressive=False.
|
||||
|
||||
| Профиль | Разрешение | Цвет | Quality | Первый JPEG, байт | Диапазон 30 JPEG, байт | PSNR первого, dB |
|
||||
|---|---|---|---:|---:|---:|---:|
|
||||
| [A](../data/processed/lab050/profile_A.jpg) | 320×240 | RGB | 35 | 8724 | 8724–9250 | 28,12 |
|
||||
| [B](../data/processed/lab050/profile_B.jpg) | 160×120 | RGB | 35 | 2771 | 2771–3031 | 28,11 |
|
||||
| [C](../data/processed/lab050/profile_C.jpg) | 128×96 | RGB | 25 | 1740 | 1740–1893 | 27,17 |
|
||||
| [D](../data/processed/lab050/profile_D.jpg) | 160×120 | grayscale | 30 | 2028 | 2028–2233 | 30,15 |
|
||||
|
||||
PSNR = 10 log10(255²/MSE); сравнение с несжатым изображением **того же
|
||||
разрешения и цветового режима** после преобразования. Оно характеризует
|
||||
JPEG-искажение внутри профиля, не потерю деталей при уменьшении и не
|
||||
пригодность картинки для управления. Между RGB и grayscale эти числа не
|
||||
доказывают превосходство качества. Четыре выходных JPEG визуально проверены;
|
||||
субъективный вердикт пригодности для оператора не присваивался.
|
||||
|
||||
Первый A побайтно совпал с Lab047, SHA-256:
|
||||
`e913dab9ac32795250880a4be67fbbbf89a4f96536842476ab591d1acaafc02a`.
|
||||
Исходный контрольный JPEG не изменён. Перекодирование новых профилей разрешено
|
||||
постановкой Lab050; новый видеокодек не разрабатывался.
|
||||
|
||||
## Точная ёмкость нынешнего PHY
|
||||
|
||||
Один RF-пакет переносит 244 байта JPEG плюс 12 байт метаданных фрагмента,
|
||||
дополняется до 256 байт нагрузки packet и до 268 байт вместе с packet header/CRC.
|
||||
FEC R=1/2 K=7, шесть хвостовых бит, перемежитель, PHY header, PRBS7 и BPSK
|
||||
сохранены. RF-пакет занимает 5724 передаваемых бита и 42 дополнительных
|
||||
символьных интервала, итого **5766**. Проверено по настоящему плану Lab045.
|
||||
|
||||
Для JPEG размера J: N=ceil(J/244), T_RF=N×5766/Rs.
|
||||
Точный максимальный размер для f кадров/с:
|
||||
`Jmax = 244 × floor(Rs/(5766×f))`.
|
||||
Это ступенчатая граница с добивкой, не деление полезного битрейта на восемь.
|
||||
|
||||
| Rs, ксимв/с | Выборок/символ при 8 Мвыб/с | Jmax для 3 кадров/с | Jmax для 5 кадров/с | Jmax для 10 кадров/с |
|
||||
|---:|---:|---:|---:|---:|
|
||||
| 200 | 40 | 2684 | 1464 | 732 |
|
||||
| 400 | 20 | 5612 | 3172 | 1464 |
|
||||
| 500 | 16 | 6832 | 4148 | 1952 |
|
||||
| 800 | 10 | 11224 | 6588 | 3172 |
|
||||
| 1000 | 8 | 13908 | 8296 | 4148 |
|
||||
|
||||
Все размеры в байтах. На пределе нет запаса для потерь, пауз, объёмных данных
|
||||
или роста JPEG. Никакие ELRS CONTROL/TELEMETRY из этого бюджета не вычитаются.
|
||||
Физическая стоимость старого LinkPacket используется лишь как эквивалентная
|
||||
шкала времени существующего симулятора: его длительность принудительно равна
|
||||
5766/Rs. LinkPacket не добавлен в реальную PHY-упаковку Lab046.
|
||||
|
||||
Максимум изображений/с по времени радио для **первого** JPEG каждого профиля:
|
||||
|
||||
| Rs, ксимв/с | A, 36 пакетов | B, 12 пакетов | C, 8 пакетов | D, 9 пакетов |
|
||||
|---:|---:|---:|---:|---:|
|
||||
| 200 | 0,964 | 2,891 | 4,336 | 3,854 |
|
||||
| 400 | 1,927 | 5,781 | 8,672 | 7,708 |
|
||||
| 500 | 2,409 | 7,226 | 10,839 | 9,635 |
|
||||
| 800 | 3,854 | 11,562 | 17,343 | 15,416 |
|
||||
| 1000 | 4,818 | 14,453 | 21,679 | 19,270 |
|
||||
|
||||
По всей последовательности A использует до 38 пакетов, B до 13, D до 10;
|
||||
C остаётся в восьми пакетах. Именно C удобен для следующего воспроизводимого
|
||||
опыта. Профиль B также укладывается по радио в 5 кадров/с на 400 ксимв/с.
|
||||
JPEG A не достигает 5 кадров/с даже на 1 Мсимв/с: 8724 > 8296 байт.
|
||||
|
||||
## Матрица очередей и фактический смысл FPS
|
||||
|
||||
Выполнено 240 сценариев: четыре профиля × входные 3/5/10 кадров/с × пять Rs
|
||||
× пределы возраста 200/333/500/1000 мс. По 30 входных изображений в каждом.
|
||||
Идеальный пакетный путь сериализует packet, проверяет CRC и собирает точные
|
||||
JPEG. Стоимость FEC/поиска IQ в этой матрице сначала равна нулю **по модели**;
|
||||
её реальный замер выполнен отдельно, ниже. Ошибок радио в матрице нет.
|
||||
|
||||
Окно наблюдения H=30/input_fps: 10, 6 или 3 с. Основные RAW RECEIVED FPS и
|
||||
FRESH DISPLAY FPS считают только события внутри H. Полученные при дальнейшем
|
||||
опустошении кадры показываются отдельно. Свежим считается только показанный
|
||||
снимок с возрастом ≤MAX_VIDEO_AGE. Просроченное изображение на экран не выпускается,
|
||||
поэтому raw display FPS совпадает с fresh display FPS; повторный показ старого
|
||||
изображения не засчитывается новым обновлением.
|
||||
|
||||
| Модель | Возраст | Вход | Передано | Удалено до TX | Получено / показано всего | Fresh FPS в H | После H |
|
||||
|---|---:|---:|---:|---:|---:|---:|---:|
|
||||
| C, камера 5, Rs=500k | 200 мс | 30 | 30 | 0 | 30 / 30 | **5,000** | 0 |
|
||||
| C, камера 10, Rs=500k | 200 мс | 30 | 30 | 0 | 30 / 30 | **10,000** | 0 |
|
||||
| B, камера 5, Rs=400k | 200 мс | 30 | 30 | 0 | 30 / 30 | **5,000** | 0 |
|
||||
| C, камера 10, Rs=200k | 200 мс | 30 | 0 | 30, прогноз возраста | 0 / 0 | **0** | 0 |
|
||||
| C, камера 10, Rs=200k | 333 мс | 30 | 14 | 16, замена свежим | 14 / 14 | **4,333** | 1 |
|
||||
| A, камера 5, Rs=1000k | 200 мс | 30 | 0 | 30, прогноз возраста | 0 / 0 | **0** | 0 |
|
||||
|
||||
Для перегруженного C/10/200k при 333 мс возраст показанных снимков примерно
|
||||
231–329 мс, ожидающая очередь ≤1. Увеличение предела до 500/1000 мс в данном
|
||||
сценарии не меняет 14 передач и 16 замен; оно не создаёт дополнительную ёмкость.
|
||||
При 200 мс уже само радио требует 230,64 мс и все снимки обоснованно отклонены.
|
||||
|
||||
Результат C/5/500k: IMAGE AGE min/median/max = **92,563 / 92,590 / 92,629 мс**.
|
||||
Это возраст **в модели идеального RX и мгновенного экрана**, не камера→монитор.
|
||||
Вход 30, transmitted=received=displayed=30, dropped=0, H=6 с,
|
||||
RAW RECEIVED FPS=RAW DISPLAY FPS=FRESH DISPLAY FPS=5.
|
||||
|
||||
## Блочный приёмник
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
I[IQ-блок до 65536 выборок] --> B[Ограниченный буфер и хвост]
|
||||
B --> C[Грубый поиск в принадлежащем блоку интервале]
|
||||
C --> S[Штатная строгая проверка PHY/FEC/CRC]
|
||||
S --> P[Выдача принятого пакета из push_iq_block]
|
||||
P --> A[Сборщик текущего image ID]
|
||||
A --> J[JPEG decode; далее проверка возраста и экран]
|
||||
```
|
||||
|
||||
`StreamingReceiver.push_iq_block()` принимает непрерывные complex64-блоки
|
||||
без границ TX, payload, ожидаемых ID или числа кадров. `finish()` проверяет
|
||||
остаток, не дополняет недостающую запись нулями. Выдача пакетов не ждёт конца
|
||||
сессии. Глобальные индексы сохраняются; принятая область исключается из
|
||||
повторной строгой проверки. Список кандидатов относится лишь к одному блоку.
|
||||
Внутри RX нет истории принятых пакетов; вызывающий код должен сразу их забирать.
|
||||
|
||||
Размер удерживаемого хвоста определяется максимально допустимым PHY packet
|
||||
1024 байта, а не известными передатчику границами. Сохраняются левый запас
|
||||
уточнения, опорная последовательность, счётчики и текущие IQ. Порог Lab047
|
||||
`0.030964473262429237` не меняется и не подстраивается по успеху JPEG.
|
||||
Скалярная статистика корреляций не объявляется новой калибровкой фона.
|
||||
|
||||
Децимация 20 старого поиска непригодна как универсальная константа для
|
||||
высоких скоростей. В адаптере она равна min(20, samples_per_symbol//2):
|
||||
**20/10/8/5/4** для 200/400/500/800/1000 ксимв/с, оставляя две выборки/символ.
|
||||
Меняются параметры поиска, но не FEC, CRC, модуляция или порог.
|
||||
Константы старых лабораторий восстанавливаются после вызова; это
|
||||
последовательный программный адаптер, не потокобезопасная многопоточная библиотека.
|
||||
|
||||
IQ-блоки должны быть непрерывными. При будущих потерях блоков драйвера нужно
|
||||
явно сбросить незавершённый поиск/объект и обозначить разрыв; live-подключение,
|
||||
обработка таких разрывов и управление переполнением драйвера здесь не реализованы.
|
||||
Синхронный `push` создаёт обратное давление программному источнику; при текущей
|
||||
скорости RX настоящий источник 8 Мвыб/с потребовал бы потерь/переполнения.
|
||||
|
||||
## Интеграционный опыт IQ и производительность
|
||||
|
||||
На **каждой** из пяти скоростей поданы три JPEG C, 24 физических пакета,
|
||||
с неизвестным началом, межкадровыми интервалами и границами входных блоков.
|
||||
CS8-квантование передатчика сохранено. Шум один для всех: coded-bit Eb/N0=7 dB,
|
||||
seed=50050, остаточная частота +10 Гц, фаза 0,73 рад и чередование полярности.
|
||||
После добавления шума поток complex64 не переквантован. Фон также генерируется
|
||||
детерминированно. TX создаёт лишь очередной RF-пакет, целая IQ-запись не хранится.
|
||||
|
||||
**Все пять проходов: 24/24 пакета, 3/3 JPEG, точный SHA; все JPEG выданы до finish.**
|
||||
Сборщик принимает ID/индексы только из проверенных CRC пакетов, сопоставление
|
||||
с TX-хешами происходит после сборки. В этом опыте ID монотонны в одной сессии;
|
||||
wrap/restart видеосеанса не реализован. Разрешён только текущий объект,
|
||||
ограничены его размер (64 КиБ) и число фрагментов; журнал результатов опыта
|
||||
отделён от памяти RX. Дополнительно пройдены интеграционные тесты идеального
|
||||
канала на всех скоростях, границ двух блоков, усечённого потока и длинного фона.
|
||||
|
||||
| Rs, ксимв/с | IQ, с | Обработка, с | Обработка / RF-секунда | Кандидатов строгой проверки | Оценка массивов RX, МиБ |
|
||||
|---:|---:|---:|---:|---:|---:|
|
||||
| 200 | 0,792483 | 35,124167 | **44,322** | 2191 | 143,412 |
|
||||
| 400 | 0,401868 | 59,470863 | **147,986** | 2575 | 83,450 |
|
||||
| 500 | 0,323745 | 55,157553 | **170,374** | 2374 | 71,457 |
|
||||
| 800 | 0,206561 | 60,954975 | **295,095** | 3113 | 53,469 |
|
||||
| 1000 | 0,167499 | 55,921951 | **333,865** | 2995 | 47,473 |
|
||||
|
||||
Знаменатель — все поданные IQ, включая фон/хвост. В JSON отдельно есть время
|
||||
чистой передачи полезных RF-пакетов и соответствующее ещё худшее отношение.
|
||||
CPU-замер включает push/finish, сборку и JPEG decode; генерация TX/IQ,
|
||||
преобразование исходной фотографии и сравнение TX-хешей исключены.
|
||||
Это однократные настольные wall-clock замеры, не норматив CPU и не оценка
|
||||
предельной дальности. Они не сравниваются напрямую с Lab048 на другой записи.
|
||||
|
||||
На 500 ксимв/с грубый поиск занял 0,492 с, строгая обработка — 54,586 с.
|
||||
Из 2374 кандидатов приняты 24; большинство остальных отклонено по magic
|
||||
PHY-заголовка. Новый ограниченный буфер **не устранил** стоимость ложных
|
||||
кандидатов. Увеличение Rs не делает этот приёмник быстрее реального времени.
|
||||
Факт Lab048 «15 с → 13,966 с» остаётся характеристикой прежней записи.
|
||||
|
||||
Пять тяжёлых проходов выполнены один раз. Первый запуск после сохранения
|
||||
замеров остановился на несовпадении API `build_packet/parse_packet` в модели
|
||||
очереди; вызовы исправлены и проверены тестами. Итоговая матрица построена
|
||||
с `--reuse-benchmarks`, без повторения RF/IQ-замеров. Режим проверяет скорости,
|
||||
параметры шума/порог и хеши восстановленных контрольных объектов.
|
||||
|
||||
## Память
|
||||
|
||||
Предел блока 65536 выборок. Для каждого Rs буфер ограничен выражением:
|
||||
`core + maximum_PHY_waveform + refinement_margin + left_margin + input_block`.
|
||||
Число кадров в сессии в формулу не входит. В тесте 100 последовательных
|
||||
блоков сохраняется тот же предел и не появляется история IQ.
|
||||
|
||||
| Rs, ксимв/с | Измеренный пик удерживаемых IQ, выборок | Проверяемый предел, выборок | IQ в пике, МиБ |
|
||||
|---:|---:|---:|---:|
|
||||
| 200 | 853027 | 853556 | 6,508 |
|
||||
| 400 | 493587 | 496316 | 3,766 |
|
||||
| 500 | 424309 | 424864 | 3,237 |
|
||||
| 800 | 308819 | 317696 | 2,356 |
|
||||
| 1000 | 279589 | 281968 | 2,133 |
|
||||
|
||||
С запасом на копирование, грубый и строгий поиск расчёт массивов даёт
|
||||
47,5–143,4 МиБ против исторической оценки Lab048 около 1,44 ГиБ.
|
||||
Это **расчёт массивов, не измеренный RSS процесса**: Python/SciPy, аллокатор,
|
||||
кэши и вызывающая программа добавляют память. История отчёта и заранее
|
||||
подготовленные 30 JPEG относятся к эксперименту, не к обязательному IQ-состоянию.
|
||||
|
||||
## Задержка и условие достижимости
|
||||
|
||||
Для каждого снимка JSON хранит capture, encode_complete, queue_enter,
|
||||
first_tx, last_tx, first_rx, object_complete, decode_complete и display.
|
||||
У не переданных/не допущенных стадий стоит null, причина удаления явна.
|
||||
QUEUE AGE=first_tx−queue_enter; RF AGE=last_tx−first_tx;
|
||||
END-TO-END IMAGE AGE=display−capture.
|
||||
|
||||
| Слагаемое | Статус |
|
||||
|---|---|
|
||||
| T_CAPTURE | Реальная экспозиция/считывание неизвестны; источник задан событиями, длительность моделируется нулём |
|
||||
| T_ENCODE | Измерено CPU-кодирование подготовленных изображений; C медиана около 0,143 мс; уменьшение/сдвиг вне этого замера |
|
||||
| T_QUEUE | Рассчитано существующим планировщиком; не измерение живой очереди |
|
||||
| T_RF | Рассчитано по настоящему формату; C на 500k — 92,256 мс |
|
||||
| T_RX_PROCESSING | Измерено в IQ-опыте, включая взаимодействие с буфером; в модели подставляется отдельно как стоимость пакета |
|
||||
| T_DECODE | Измерено CPU JPEG decode; C медиана около 0,187 мс; в общем IQ-замере уже включено, повторно туда не прибавляется |
|
||||
| T_DISPLAY | Экран не подключён; длительность моделируется нулём |
|
||||
|
||||
В конвейере RF и обработка ранних пакетов перекрываются. Нельзя прибавлять
|
||||
полный CPU service time к полному RF-времени и называть это измеренной
|
||||
сквозной задержкой. Прогноз без предыдущей очереди RX после last_tx:
|
||||
`lookahead + p + (N−1)×max(0,p−T_packet) + JPEG_decode`, где p — стоимость
|
||||
пакета. Формула независимо проверена последовательным расчётом 32 наборов
|
||||
событий и допуском по обе стороны точной границы возраста.
|
||||
|
||||
На 500k консервативный предел выдачи из буфера без стоимости CPU — 52,608 мс.
|
||||
Средняя измеренная стоимость полного RX-опыта — 2,298 с на переданный RF-пакет
|
||||
(включает фон и отвергнутых кандидатов, не только принятый FEC). При подстановке
|
||||
этой стоимости все 30 кадров C/5fps отклоняются ещё до TX при любом проверенном
|
||||
MAX_VIDEO_AGE; **FRESH DISPLAY FPS=0**. Это прогноз с измеренной стоимостью,
|
||||
не эксперимент с живым экраном.
|
||||
|
||||
Проверены также два явно условных варианта ускоренного RX:
|
||||
|
||||
| Условие | 5 кадров/с | 10 кадров/с |
|
||||
|---|---:|---:|
|
||||
| Выбранный JPEG | ≤1952 байт, 8 пакетов; C фактически ≤1893 | То же |
|
||||
| Выбранный Rs | 500 ксимв/с, 16 выборок/символ | То же |
|
||||
| Нижняя граница только по радио для 8 пакетов | 230,640 ксимв/с | 461,280 ксимв/с |
|
||||
| Предположенная стоимость RX-пакета | ≤16 мс | ≤12 мс |
|
||||
| Ускорение относительно данного замера | **≥143,64 раза** | **≥191,52 раза** |
|
||||
| MAX_VIDEO_AGE | 200 мс | 200 мс |
|
||||
| Расчётный возраст min/median/max | 192,447 / 192,474 / 192,513 мс | 160,447 / 160,474 / 160,513 мс |
|
||||
| Свежих в исходном окне | 30/6 с = **5** | 29/3 с = **9,667** |
|
||||
| С учётом опустошения | 30; без дополнительных | 30; один после 3 с |
|
||||
| Частота по интервалам последовательных показов | около 5 | около 10 |
|
||||
| FEASIBLE | **CONDITIONAL** | **CONDITIONAL** |
|
||||
|
||||
Для 10 кадров/с стартовая задержка превышает период камеры, поэтому первый
|
||||
трёхсекундный отчёт честно даёт 9,667, а не 10 с включением позднего кадра.
|
||||
Частота около 10 относится к установившимся интервалам. Условия не означают,
|
||||
что такое ускорение достигнуто или достижимо только небольшой правкой.
|
||||
Живые capture/display, входной jitter, потери и запас CPU ещё должны уложиться
|
||||
в оставшийся бюджет. Для 5 кадров/с запас возраста этого примера лишь около 7,5 мс.
|
||||
|
||||
Итак, **по пропускной способности BPSK достаточно**, без QPSK и нового FEC;
|
||||
**с нынешним измеренным приёмником — нет**. Аппаратная работоспособность
|
||||
HackRF на этих Rs в данном задании не проверялась. 3 кадра/с остаются
|
||||
промежуточным уровнем, цель проекта >3, ориентиры 5 и 10.
|
||||
|
||||
## ELRS и следующий опыт
|
||||
|
||||
CONTROL LINK OK/LOST — внешнее состояние для контроллера ровера. Видеопланировщик
|
||||
вообще не принимает его как радиопакет. Проверка на существующем TwoStageFailsafe:
|
||||
при отсутствии новых команд 100 мс → замедление, 200 мс → торможение,
|
||||
а результат видеомодели остаётся тем же. Это проверка разделения моделей,
|
||||
не готовое сопряжение CRSF. Safety/session/emergency-модули не менялись.
|
||||
|
||||
Рекомендуемый Lab051 — программное профилирование и ускорение строгого
|
||||
обработчика ложных кандидатов на сохранённом детерминированном сценарии
|
||||
C/500k, с отдельной проверкой фоновых ложных принятий и неизменными FEC/CRC.
|
||||
Измерять стоимость уточнения, оценки частоты, заголовка и FEC; сохранить
|
||||
независимость от TX и корректность на границах блоков. Не объявлять 5 кадров/с
|
||||
до полного непрерывного опыта со свежими JPEG и устойчивым временем обработки.
|
||||
RF, QPSK, новый кодек, 12+3 FEC и перенос на 180 МГц этим этапом не разрешаются.
|
||||
|
||||
## Воспроизведение
|
||||
|
||||
```powershell
|
||||
python experiments/lab050_video_stream.py
|
||||
# Только пересчёт матрицы с уже сохранёнными локальными замерами IQ:
|
||||
python experiments/lab050_video_stream.py --reuse-benchmarks
|
||||
python -m pytest tests/test_lab050_video_stream.py -q -p no:cacheprovider
|
||||
python tools/quick_gate.py
|
||||
python -m pytest tests/ -q
|
||||
git diff --check
|
||||
```
|
||||
|
||||
Полный первый запуск занимает минуты; новые RF-сеансы в нём отсутствуют.
|
||||
[result.json](../data/processed/lab050/result.json) содержит 240 сценариев,
|
||||
все временные отметки, профили, расчёты ёмкости и отдельные условные модели.
|
||||
[receiver_benchmarks.json](../data/processed/lab050/receiver_benchmarks.json)
|
||||
содержит исходные пять IQ-замеров. Большие IQ-файлы не создавались.
|
||||
|
||||
44 целевых теста проходят. Verifier/adversary подтвердили исправление
|
||||
поздно завершённого старого кадра; verifier независимо проверил границы
|
||||
ёмкости, 60 сценариев очереди, 32 прогноза RX и арифметику IQ-замеров.
|
||||
Итог: quick_gate PASS — 650 тестов и 14 функциональных проверок;
|
||||
полный pytest — 650 passed за 78,73 с, одно предупреждение о доступе
|
||||
к `.pytest_cache`; git diff --check PASS. Подробности — в записи 039 журнала.
|
||||
|
||||
LAB050 GIT ADD = NOT PERFORMED. LAB050 COMMIT = NOT PERFORMED.
|
||||
PUSH = NOT PERFORMED. RF TX = 0. STOP.
|
||||
Reference in New Issue
Block a user