Rework radar system

This commit is contained in:
Ayzen
2026-10-06 12:32:26 +03:00
parent 552cdc688a
commit 5bb86b7165
299 changed files with 13537 additions and 27763 deletions
+62 -9
View File
@@ -208,16 +208,69 @@ ref» — сигнал на первом приёмнике.
отсчёты приёмников. Считает хост, в
`librevna_multi_device_driver/cycle_collection.py`.
Нормировка (`calculate_last_cycle_s_parameters`, строка 783): каждый канал
делится на опорный приёмник **мастера**, а не на локальный опорный приёмник
слейва — потому что излучает именно мастер. Опорные измерения хранятся по
номеру выходного канала (`master_reference_measurements_by_output`), так как с
переключением стимула выходов больше, чем портов мастера.
Нормировка (`calculate_s_parameters`): каждый канал прохождения
делится на опорный приёмник **мастера**, а не на локальную опору слейва,
потому что излучает мастер. Опорные измерения хранятся по выходному каналу
(`master_reference_measurements_by_output`): при переключении стимула выходов
больше, чем физических портов мастера.
Имена S-параметров: отражение мастера — `master_reflection_s_parameter_name`
(строка 760), прямые каналы — `build_forward_s_parameter_names` (строка 765).
Нумерация приёмных портов слейвов начинается **после** всех выходов, чтобы
`S33`/`S44` отражения не столкнулись с прямыми каналами.
Отражения мастера приложение не собирает и не использует для отбраковки циклов.
Ключ канала — пара `(input_pos, output_pos)` с нумерацией от нуля. Входы слейвов
идут подряд: два порта первого слейва, затем два порта второго. Выход равен
стадии мастера. Эти же физические номера используются в `ComboKey` коллекции.
Одиночный LibreVNA использует Python-драйвер `librevna_driver`: порт 1 излучает
на стадии 0, порт 2 выключен (`port2Stage = 7`), `port3Stage = 0` означает
отсутствие под-стадий. Хост сохраняет S21 = отсчёт порта 2 / опорный отсчёт
той же стадии. Опора распознаётся по биту Reference даже при маске `0x13`;
она никогда не подменяет сигнальный отсчёт из-за одновременно выставленных
битов портов. Физические номера антенных ключей остаются заданными конфигом.
Бюджет ожидания одиночного свипа зависит от числа точек, `1 / IFBW` и dwell,
с запасом на установление частоты и обмен по USB. Отдельный тайм-аут отсутствия
новых точек прерывает зависший прибор независимо от общего бюджета свипа.
В multi-device `collect_complete_running_sweep_cycle` собирает один цикл.
Окно коллекции и всех её трасс берётся по получению от мастера точки 0 и
последней принятой точки этого цикла. Метка точки 0 фиксируется до ожидания
слейвов на барьере синхронизации. Слив очередей, ожидание начала цикла и
повторные попытки сбора в окно не входят.
### Формат коллекций между процессами хоста
Это отдельный формат от USB-пакетов прибора. `RAW3` и `PRP3` — четыре ASCII-байта
magic (`0x33574152` и `0x33505250` little-endian). В каждой трассе идут массив
float32 частот и массив complex64 S21: 12 байт на точку. Окна съёма коллекции
и отдельных трасс обязательны: после массивов идут два u64 окна коллекции,
u32 числа трасс и по два u64 на каждую трассу. Усечённый хвост отвергается,
нулевые окна разрешены в бандлах калибровки/референса. Полный размер кадра:
`44 + число_пар × (28 + 12 × число_точек)` байт. Старые RAW2/PPR2 не принимаются;
runtime-бандлы пересобираются из NPZ при Start. Старые NPZ с лишними S11-массивами
читаются по S21 без изменения файлов. Формат пакетов LibreVNA этим не меняется.
Кадр результата — `RSL3` (`0x334c5352`, ASCII little-endian). Его заголовок
занимает 64 байта, все поля little-endian, без выравнивающих промежутков:
| Смещение | Поле | Тип |
| --- | --- | --- |
| 0 | magic | u32 |
| 4 | collection_id | u64 |
| 12 | monotonic_ns (завершение обработки) | u64 |
| 20 | processing_duration_ns | u64 |
| 28 | settings_revision | u64 |
| 36 | capture_start_ns | u64 |
| 44 | capture_end_ns | u64 |
| 52 | speed_m_s | f32 |
| 56 | число payload коллекции | u32 |
| 60 | число блоков пар | u32 |
После заголовка идут payload'ы коллекции и блоки пар. Блок содержит номера
входа и выхода, число payload'ов (три u32), затем сами payload'ы. Каждый payload
начинается с типа u8 и имени (длина u16 и байты UTF-8); далее идут данные типа:
комплексная трасса, скаляр f32, изображение f32 или таблица f32. Идентичность
свипа на всех стадиях — `(collection_id, capture_start_ns)`, время стадии её
не меняет.
RSL2 отвергается; Python и C++ обновляются одновременно после остановки процессов.
## 7. Почему поле мощности читается, но не используется
+13 -8
View File
@@ -18,12 +18,12 @@
## Раскладка стадий
| Стадия | Порт мастера | Ключ | Выход | Отражение |
|---|---|---|---|---|
| 0 | 1 | A | 0 | `S11` |
| 1 | 1 | B | 1 | `S22` |
| 2 | 2 | A | 2 | `S33` |
| 3 | 2 | B | 3 | `S44` |
| Стадия | Порт мастера | Ключ | Выход |
|---|---|---|---|
| 0 | 1 | A | 0 |
| 1 | 1 | B | 1 |
| 2 | 2 | A | 2 |
| 3 | 2 | B | 3 |
И стадии, и выходы нумеруются **порт-мажорно**: старшие биты счётчика стадий
выбирают порт, младший — положение ключа. **Номер выхода равен номеру стадии**,
@@ -35,8 +35,8 @@
> два оказывались переставлены относительно физического порядка — слоты 0,1,2,3
> попадали на выходы 0,2,1,3. Физический порядок подтверждён замером. Данные,
> снятые до смены, **несопоставимы** с новыми: выходы 1 и 2 поменялись смыслом,
> поэтому калибровки и референсы надо переснять. Имена S-параметров те же, но
> `S22` теперь означает «порт 1, положение B», а не «порт 2, положение A».
> поэтому калибровки и референсы надо переснять. Выход 1 теперь означает
> «порт 1, положение B», а не «порт 2, положение A».
Из этого следует главное свойство: **положение ключа — это младший бит номера
стадии**, а период 2 нацело делит 4 стадии. Значит через границу точки чередование
@@ -44,6 +44,11 @@
цикл триггера — абсолютный счётчик стадий не нужен, нужна только правильная
чётность, а её контроллер восстанавливает на каждой точке по длине паузы.
Приложение сохраняет только прохождение от мастера к приёмникам слейвов.
Отражения мастера не собираются. Канал хранится как физическая пара
`(input, output)`: входы 0 и 1 — порты первого слейва, 2 и 3 — второго;
выход — номер стадии из таблицы.
## Контракт по проводу
Хост отправляет это в `build_sweep_settings_payload`, прошивка читает — обе