301 lines
27 KiB
Markdown
301 lines
27 KiB
Markdown
# Калибровка и предобработка
|
||
|
||
Препроцессор (`data_preprocessor`) по очереди применяет к каждой коллекции четыре
|
||
шага и только потом отдаёт её на обработку. Зачем нужен каждый шаг, объяснено в
|
||
главе [Как работает радар](principles.md).
|
||
|
||
## Цепочка предобработки
|
||
|
||
Для каждой пары и каждой частотной точки:
|
||
|
||
| Шаг | Формула | Набор |
|
||
| --- | --- | --- |
|
||
| 1. Калибровка | S21 ← S21 / S21_through | набор калибровки (through) |
|
||
| 2. Вычитание референса | S21 ← S21 − S21_ref / S21_through | набор референса |
|
||
| 3. Режекторный фильтр | S21 ← S21 · m(f) | настройки `preprocess.notch` в профиле |
|
||
| 4. Калибровка по объекту | S21 ← S21 · F | набор калибровки по объекту, если выбран |
|
||
|
||
Референс делится на through один раз при загрузке, поэтому вычитается уже
|
||
откалиброванный фон. Точки, где |S21_through|² не больше 10⁻¹², на шаге 1 остаются как
|
||
есть, без деления. Окно съёма и номер коллекции не меняются.
|
||
|
||
У каждого набора должна быть каждая пара сбора, а сетка частот — совпадать с
|
||
развёрткой: то же число точек, а каждая частота отличается от своей не больше чем на
|
||
10⁻⁵ её значения, но допуск не меньше 1 мГц (на 6 ГГц — 60 кГц). Наборы проверяются при запуске
|
||
препроцессора, и неподходящий набор его останавливает. Если это случилось, пока
|
||
программа ждёт готовности процессов, **Start** отказывает с сообщением
|
||
``Failed to start pipeline: RuntimeError: Process `data_preprocessor` exited with code 1.``
|
||
и текстом ошибки. Если позже, в журнале окна появляется отчёт о завершении
|
||
процесса, а программа перезапускает конвейер с нарастающей паузой.
|
||
|
||
Коллекцию, которая не прошла проверку уже во время
|
||
работы, препроцессор отбрасывает и пишет об этом в свой журнал
|
||
`python_app/runtime/logs/data_preprocessor.err.log`. В окне программы это видно
|
||
только по тому, что изображение перестаёт обновляться.
|
||
|
||
## Наборы
|
||
|
||
| Набор | Каталог | Обязателен |
|
||
| --- | --- | --- |
|
||
| S21 Calibration — калибровка (through) | `python_app/data/s21_calibration/` | да |
|
||
| S21 Reference — референс | `python_app/data/s21_reference/` | да |
|
||
| Object Calibration — калибровка по объекту | `python_app/data/s21_object_calibration/` | нет |
|
||
|
||
Набор — архив NPZ с массивами частот и S21 по парам и JSON-файл рядом с описанием
|
||
(формат — в главе [Данные на диске](data.md)). Наборы лежат в подкаталогах с именем
|
||
`radar_key` — ключа конфигурации радара:
|
||
|
||
- у LibreVNA ключ складывается из модели, серийных номеров, начала и конца
|
||
развёртки, числа точек, полосы ПЧ и мощности, а у многоприборной схемы ещё из
|
||
положений ключей;
|
||
- у радиофотонного радара ключ — хеш выходной полосы, фазовой калибровки, параметров
|
||
источника, положений ключей и настроек лазера; лазер входит в ключ, если плата
|
||
лазеров включена в профиле или источник — плата RFG.
|
||
|
||
Программа показывает только наборы текущего ключа. Если изменить любую из этих
|
||
величин (например, число точек), старые наборы пропадают из списков, а выбор
|
||
сбрасывается с записью `Preprocess selection reset: <старый ключ> -> <новый ключ>; cleared {...}`
|
||
в журнале. Так программа не даёт применить калибровку, снятую при других
|
||
настройках. Если вернуть прежние настройки, наборы снова появятся в списках, но
|
||
выбрать их придётся заново.
|
||
|
||
Наборы применяются при запуске сбора: программа пересобирает из выбранных наборов
|
||
файлы `python_app/runtime/*_bundle.bin` и заново запускает препроцессор. Запуск — это
|
||
**Start**, а также продолжение сбора после приостановки: после съёма набора,
|
||
временного референса или нейтральных наборов сбор, если он шёл, продолжается уже с
|
||
новыми наборами. Смена выбора в списке во время сбора применится при следующем
|
||
запуске.
|
||
|
||
Перед запуском программа проверяет наборы и, если что-то не так, отказывается
|
||
запускаться, ничего не остановив. Окно ошибки показывает
|
||
`Failed to start pipeline: <тип ошибки>: <текст>`, где текст — один из этих:
|
||
|
||
| Условие | Сообщение |
|
||
| --- | --- |
|
||
| не выбраны калибровка или референс | `Select all required preprocess sets in Preprocessing Panel before Start: S21 Calibration, S21 Reference` |
|
||
| файла набора нет для текущего ключа | `Missing set files for <вид>/<radar_key>/<имя>` |
|
||
| в наборе нет какой-то пары сбора | `Selected <набор> set does not cover requested run combos` |
|
||
| архив повреждён или содержит не числа | `Corrupted preprocess set <вид>/<ключ>/<имя>: …` |
|
||
| калибровка по объекту не подходит | см. раздел «Калибровка по объекту» |
|
||
|
||
## Окно Preprocessing Setup
|
||
|
||
Открывается кнопкой **Preprocessing…**. Окно не модальное: пока оно открыто, главным
|
||
окном можно пользоваться.
|
||
|
||
Группа **Preprocess Sets**:
|
||
|
||
| Элемент | Что делает |
|
||
| --- | --- |
|
||
| **Set name** | имя нового набора; по умолчанию `set_001`. Для этого вида набора и этого ключа радара имя должно быть новым |
|
||
| **Create Neutral S21 Sets** | создаёт нейтральные наборы (см. ниже). Кнопка есть только у радиофотонного радара, у многоприборной схемы и у одиночного LibreVNA в режиме `mock` |
|
||
| **Refresh Sets** | перечитывает списки наборов с диска и каталог вариантов радара |
|
||
| **Sweeps per combo (median)** | сколько развёрток снимать на каждую пару, от 1 до 99, по умолчанию 5. В набор идёт медиана по каждой частоте, отдельно по вещественной и мнимой части: при трёх развёртках и больше одиночный сбой развёртки в набор не попадает. Это же число развёрток берут временный референс и калибровка по объекту |
|
||
| **Radar Config Variants** → **Directory**, **Browse…** | каталог с профилями JSON для съёма наборов сразу под несколько настроек развёртки (см. ниже). Под полем — итог просмотра: `Directory: <каталог> \| json=…, valid=…, skipped=…, duplicates=…` (файлов JSON, подходящих вариантов, пропущенных, повторов) или `No radar config directory selected.` |
|
||
| **Capture current combo for all found radar configs** | включает съём по всем вариантам из каталога |
|
||
| **S21 calibration**, **S21 reference** | выбор набора калибровки и референса для следующего **Start** |
|
||
| **Object calibration** | выбор калибровки по объекту; **Off** — не применять |
|
||
| **Create…** | открывает окно калибровки по объекту |
|
||
|
||
Группа **Capture All Antenna Pairs**:
|
||
|
||
| Элемент | Что делает |
|
||
| --- | --- |
|
||
| **Active type**, **Progress**, **Current combo** | вид снимаемого набора, сколько пар снято из скольких, какая пара следующая; без съёма — `<none>`, `0 / 0`, после последней пары — `<complete>` |
|
||
| **Start S21 Calibration**, **Start S21 Reference** | начинают съём набора |
|
||
| **Capture Current Combo** | снимает следующую пару |
|
||
| **Capture All Remaining** | снимает подряд все оставшиеся пары |
|
||
| **Undo Last Capture** | отменяет последний съём, чтобы переснять пару |
|
||
| **Save Captured Set** | сохраняет набор и выбирает его; доступна, когда сняты все пары |
|
||
| **Abort Sequence** | прерывает съём и отбрасывает снятое |
|
||
|
||
Ниже — журнал съёма (`S21 Calibration: 1/8 | input=0 output=0` на каждую пару),
|
||
строка состояния (сначала `Ready`) и графики модуля и фазы последней снятой развёртки
|
||
(до первого съёма — `Preview will appear after the first successful capture.`).
|
||
Последняя развёртка рисуется и в главном окне.
|
||
|
||
## Съём калибровки и референса
|
||
|
||
1. Выберите профиль и настройки радара. Наборы привязаны к ключу радара, поэтому
|
||
снимайте их при тех настройках развёртки, с которыми будете работать.
|
||
2. Подготовьте установку. Для калибровки — эталонный тракт для текущей пары; для
|
||
референса — пустую сцену: всё, что должно остаться в фоне, на месте, целей нет.
|
||
3. Нажмите **Preprocessing…**, задайте **Set name** и
|
||
**Sweeps per combo (median)**.
|
||
4. Нажмите **Start S21 Calibration** или **Start S21 Reference**. Сбор
|
||
приостанавливается, и на время съёма прибором управляет окно предобработки.
|
||
5. Снимайте пары кнопкой **Capture Current Combo** или все сразу кнопкой
|
||
**Capture All Remaining**. Проверяйте каждую развёртку по графикам; неудачную
|
||
переснимите через **Undo Last Capture**. При ошибке съёма уже снятые пары
|
||
сохраняются, и съём можно повторить.
|
||
6. Когда сняты все пары, нажмите **Save Captured Set**. Набор сохраняется и
|
||
выбирается, приостановленный сбор продолжается.
|
||
|
||
Съём всегда идёт по полной матрице положений ключей, а не только по парам сбора.
|
||
|
||
- Одиночный LibreVNA: для каждой пары программа выставляет ключи, ждёт время
|
||
установления (`run.settling_ms`, в окне — **Settling (ms)**) и снимает нужное
|
||
число развёрток этой пары.
|
||
- Многоприборная схема при калибровке: прибор снимает всю матрицу, а в набор идёт
|
||
только текущая пара, по одной за нажатие. **Capture All Remaining** здесь
|
||
недоступна.
|
||
- Многоприборная схема при съёме референса: одно нажатие снимает всю матрицу нужное
|
||
число раз, и набор сразу готов.
|
||
|
||
### Варианты радара
|
||
|
||
Иногда наборы нужны сразу под несколько развёрток — например, под разные полосы
|
||
частот. Для этого в **Directory** указывают каталог с профилями JSON. Профиль
|
||
считается вариантом, если в его `radar.sweep` есть хотя бы одно из полей
|
||
`start_hz`, `stop_hz`, `points`, `if_bandwidth_hz`, `stimulus_power_dbm`; эти поля
|
||
накладываются на текущий профиль, повторы одного ключа пропускаются. С включённой
|
||
**Capture current combo for all found radar configs** каждое нажатие снимает пару во
|
||
всех вариантах подряд, с перенастройкой прибора. **Save Captured Set** сохраняет
|
||
по набору на каждый вариант под одним именем, а картинки развёрток — в
|
||
`python_app/data/preview_png/<вид>/<имя>/<radar_key>/i<вход>_o<выход>.png`.
|
||
|
||
## Временный референс
|
||
|
||
Кнопка **Capture Temporary Reference** в секции **Data Actions** снимает референс
|
||
одним нажатием, не открывая окно предобработки. То же действие есть в
|
||
веб-интерфейсе и на GPIO-кнопке.
|
||
|
||
Программа приостанавливает сбор, снимает полную матрицу с текущими настройками
|
||
(медиана **Sweeps per combo (median)** развёрток) и сохраняет её как набор
|
||
`tmp_reference`, заменяя прежний. Затем она выбирает этот набор, очищает историю
|
||
обработки, рисует последнюю развёртку с подписью `Tmp S21 Reference last trace` и
|
||
продолжает сбор. Процессор и локатор при этом не перезапускаются, клиенты локатора
|
||
не отключаются.
|
||
|
||
Временный референс нужен, когда сцена или положение радара изменились: после
|
||
перестановки, на новом месте, после заметного изменения обстановки.
|
||
|
||
## Нейтральные наборы
|
||
|
||
**Create Neutral S21 Sets** сохраняет под именем из **Set name** два набора:
|
||
калибровку, равную 1, и референс, равный 0, для всех пар на текущей сетке частот.
|
||
С ними данные проходят предобработку без изменений. Они нужны, чтобы запустить
|
||
конвейер, пока настоящей калибровки нет: с симулятором, при первой проверке прибора.
|
||
Если набор с таким именем уже есть, программа откажется. После создания наборы
|
||
выбираются, история очищается, а процессор перезапускается: сразу, если сбор шёл,
|
||
иначе при следующем **Start**.
|
||
|
||
## Режекторный фильтр
|
||
|
||
Фильтр настраивается только в профиле, в разделе `preprocess.notch`; в окне
|
||
программы его нет.
|
||
|
||
| Ключ | По умолчанию | Что делает |
|
||
| --- | --- | --- |
|
||
| `enabled` | `false` | включает фильтр |
|
||
| `bands_hz` | `[]` | полосы подавления: список пар `[нижняя, верхняя]` в герцах, верхняя не меньше нижней |
|
||
| `taper_width_hz` | `40e6` | ширина плавного края w, Гц, не меньше 0 |
|
||
| `taper_type` | `"cosine"` | форма края: `"cosine"` — косинусный спад, `"hard"` — без спада |
|
||
|
||
Внутри полосы [L, H] множитель m(f) равен нулю. При `"cosine"` по краям полосы он
|
||
плавно спадает от 1 до 0 по закону 0,5·(1 + cos(…)) на участках [L − w, L] и
|
||
[H, H + w]. При `"hard"` (или w = 0) зануляется вся полоса [L − w, H + w]. Края
|
||
соседних полос перемножаются.
|
||
|
||
Во всех профилях-примерах `enabled: true` и `bands_hz: []`, то есть фильтр ничего не
|
||
подавляет. Изменение фильтра применяется при следующем **Start** и сбрасывает
|
||
историю.
|
||
|
||
## Калибровка по объекту
|
||
|
||
Калибровка по объекту находит для каждой пары комплексную поправку по частоте так,
|
||
чтобы отклик известного отражателя у всех пар совпадал по фазе. Эталон — ноутбук
|
||
`MIMO_calibration.ipynb`, он хранится вне репозитория. Поправку можно строить по
|
||
нескольким положениям отражателя: они уточняют друг друга.
|
||
|
||
Что нужно заранее:
|
||
|
||
- кольцо `rings.preprocessed_tap` в профиле: калибровка снимает данные из него;
|
||
- таблицы геометрии антенн: в калибровку входят только пары, у которых есть
|
||
геометрия обеих антенн, остальные получают поправку 1;
|
||
- выбранный набор калибровки (through): поправка запоминает его имя и содержимое и
|
||
годится только вместе с ним;
|
||
- металлический шар известного радиуса (или другой точечный отражатель) и способ
|
||
измерить положение его центра.
|
||
|
||
Окно **MIMO Object Calibration** открывается кнопкой **Create…** в окне
|
||
предобработки. Вверху — подсказка о порядке работы
|
||
(`Capture data, then enter the measured reflector centre: …`), внизу — строка
|
||
состояния (сначала `Ready to capture`), а на месте карт фаз до расчёта —
|
||
`Pair phases at the target will appear after calculation.`
|
||
|
||
| Элемент | Что делает |
|
||
| --- | --- |
|
||
| **Set name** | имя набора поправки |
|
||
| таблица **Target**, **Sweeps**, **X (m)**, **Y (m)**, **Z (m)** | снятые положения отражателя: сколько коллекций снято и измеренный центр |
|
||
| **Capture Data** | снимает данные для нового положения отражателя |
|
||
| **Remove Selected Target** | удаляет выбранное положение |
|
||
| **Sphere radius (m, 0 = point)** | радиус шара, по умолчанию 0,16 м; 0 — точечный отражатель |
|
||
| **Antenna origin height above ground (m)** | высота начала осей антенн над землёй, по умолчанию 0,92 м |
|
||
| **Radar downward tilt (°)** | наклон радара вниз, по умолчанию 10° |
|
||
| **Calculation Settings** | раскрывает остальные параметры расчёта (таблица ниже) |
|
||
| **Calculate and Save** | считает поправку в фоне и сохраняет набор |
|
||
| **Cancel Operation** | прерывает съём или расчёт |
|
||
| **Close** | закрывает окно |
|
||
|
||
Параметры в **Calculation Settings**:
|
||
|
||
| Параметр | По умолчанию | Что делает |
|
||
| --- | --- | --- |
|
||
| **Estimation band start (MHz)**, **Estimation band stop (MHz)** | 2000 и 6000 | полоса, по которой оценивается поправка; в ней должно быть не меньше 4 точек |
|
||
| **Echo path gate half-width (m)** | 0,15 | полуширина окна вокруг ожидаемого пути до отражателя, в котором ищется его эхо |
|
||
| **Gate taper width (m)** | 0,03 | ширина плавного края этого окна |
|
||
| **Coarse path search (±m, 0 = off)** | 0,6 | предварительный поиск: на сколько можно сдвинуть отражатель по дальности до самого сильного эха |
|
||
| **Coordinate refinement (±m)** | 0,1 | в каких пределах уточнять координаты отражателя |
|
||
| **Refine coordinates** X, Y, Z | все три | по каким осям уточнять координаты |
|
||
| **Antenna phase model** | `linear` | модель фазы антенны по частоте: `const` — постоянная, `linear` — линейная (задержка), `poly3` — многочлен третьей степени, `raw` — без сглаживания |
|
||
| **Equalize amplitudes** | выключен | выравнивать и амплитуды, а не только фазы |
|
||
|
||
Порядок:
|
||
|
||
1. Поставьте отражатель в сцену и измерьте положение его центра в осях сцены: X —
|
||
вдоль ряда антенн, Y — высота над землёй, Z — вдоль земли от радара.
|
||
2. Нажмите **Capture Data**. Программа приостанавливает текущий сбор и запускает
|
||
конвейер с этим же профилем, но без калибровки по объекту и по всем парам из
|
||
таблиц геометрии (многоприборная схема — по полной матрице). Она собирает
|
||
столько новых коллекций, сколько задано в
|
||
**Sweeps per combo (median)**, и возвращает прежний режим работы. Предел ожидания —
|
||
300 с.
|
||
3. Введите X, Y, Z в строке нового положения.
|
||
4. Повторите для других положений, если нужно. Все положения должны быть сняты при
|
||
одних и тех же настройках радара, геометрии и предобработке.
|
||
5. Нажмите **Calculate and Save**. Расчёт идёт в фоне. После него окно показывает
|
||
карты фаз пар в точке отражателя до и после поправки (**Before**, **After**):
|
||
строки — передающие антенны, столбцы — приёмные, фаза — относительно суммы по
|
||
всем парам, по шкале ±180°, с разбросом в градусах.
|
||
**Capture Data** отказывает, если идёт однократный съём или запись на диск
|
||
(`Finish the single capture or disk recording before taking calibration data`), если
|
||
нет таблиц геометрии (`Configure Tx/Rx antenna positions before taking calibration data`)
|
||
или кольца копии
|
||
(`Object calibration requires rings.preprocessed_tap; enable it in the run profile`).
|
||
6. Если набор подходит к текущим настройкам, он выбирается и применяется при
|
||
следующем **Start** (`Applies on the next Start.`). Иначе он сохраняется
|
||
невыбранным с объяснением `Not selected for the current configuration: <причина>`.
|
||
|
||
Коллекции одного положения усредняются. По каждой частоте поправка раскладывается на
|
||
множители передающих и приёмных антенн; фазы сглаживаются выбранной моделью и
|
||
продолжаются на всю сетку частот. Поправка пары — сопряжённая фаза произведения
|
||
множителей, а с **Equalize amplitudes** — обратное произведение.
|
||
|
||
Перед каждым **Start** программа проверяет, что поправка снята при тех же настройках
|
||
радара, той же геометрии и с тем же набором калибровки (по имени и содержимому), что
|
||
она и калибровка покрывают все пары сбора, не содержит нулей и имеет ту же сетку
|
||
частот. Сообщения при отказе:
|
||
|
||
- `Object calibration has no capture provenance; capture it again`;
|
||
- `Object calibration radar configuration differs from the captured state` (а также
|
||
`antenna geometry`, `through calibration name`, `through calibration content`);
|
||
- `Object calibration and through must cover input=i, output=o`;
|
||
- `Object calibration corrections must be nonzero`;
|
||
- `Object calibration frequency grid differs for input=i, output=o`.
|
||
|
||
Если изменить таблицу геометрии так, что она перестала совпадать с геометрией
|
||
выбранной поправки, выбор поправки снимается, а работающий с ней сбор
|
||
приостанавливается и продолжается уже без неё.
|
||
|