# Окно программы Окно называется **Radar System Control** и открывается развёрнутым на весь экран. Слева — графики выбранного режима обработки, справа — панель управления. Работу ведут несколько процессов — конвейер: процесс сбора управляет железом, препроцессор калибрует данные, процессор их обрабатывает и держит TCP-локатор для внешних программ; между собой они передают данные через кольца в разделяемой памяти (главы [Устройство программы](architecture.md) и [Словарь](glossary.md)). ```text ┌──────────────────────────────────────┬─┬──────────────────────────────────┐ │ │ │ Actions (не прокручивается)│ │ │ │ ┌──────────────────────────────┐ │ │ графики │›│ │ Data Actions │ │ │ (вид зависит от режима) │ │ │ Switches │ │ │ │ │ │ Selected Preprocess Sets │ │ │ │ │ │ Processing │ │ │ │ │ │ Radar │ │ │ │ │ └──────────────── прокрутка ───┘ │ │ │ │ Status: … History: … │ │ │ │ Runtime Log Level ▾ │ │ │ │ [журнал] │ └──────────────────────────────────────┴─┴──────────────────────────────────┘ ``` Стрелка между графиками и панелью (подсказка **Hide settings panel** или **Show settings panel**) прячет и показывает всю панель; графики тогда занимают всю ширину. Положение стрелки не запоминается. Секция **Actions** со списком **Mode** всегда на месте, остальные секции прокручиваются. Меню, панели инструментов и сочетаний клавиш нет. Многие действия приостанавливают сбор: останавливают процесс сбора и препроцессор, но оставляют работать процессор и локатор, а по окончании продолжают сбор, если он шёл. Так работают **Apply Radar**, **Clear Runtime History**, **Remove Last Measurement**, **Capture Temporary Reference** и съём наборов. Приостановка завершает и запись на диск. **Stop** отменяет ожидающее продолжение. Если в это время идёт другое такое действие, программа отвечает `Wait for the current pipeline operation to finish`. ## Actions | Кнопка | Что делает | | --- | --- | | **Start** | запускает непрерывный сбор и обработку | | **Single Capture** | снимает одну коллекцию, показывает результат и останавливает сбор | | **Stop** | останавливает сбор | | **Apply Radar** | отправляет настройки радара в железо, не запуская сбор | | **Load Config…** | загружает профиль из файла | | **Save Config…** | сохраняет текущие настройки в профиль | | **Preprocessing…** | открывает окно **Preprocessing Setup**: наборы калибровки и референса, калибровка по объекту ([Калибровка и предобработка](preprocessing.md)) | | **Clear Runtime History** | очищает историю в памяти | | **Mode** | режим обработки: `pass_through`, `bscan`, `gpr`, `sar3d` ([Режимы обработки](processing.md)) | ### Start Перед запуском программа проверяет всё и при любой ошибке отказывает, ничего не остановив; ошибка показывается окном `Failed to start pipeline: <тип>: <текст>`. Проверяются: - значения полей (например, буквы в поле **Points**: `invalid literal for int()…`); - профиль сбора: режим драйвера, модель, ключи, линии GPIO, размер слотов колец; - требования режима обработки (B-scan, GPR, 3D SAR — в главе [Режимы обработки](processing.md)); - выбранные наборы калибровки и референса (глава [Калибровка и предобработка](preprocessing.md)). Если проверка прошла, программа: 1. перезапускает процессор, если изменились настройки, от которых он зависит (глава [Файл конфигурации](configuration.md)); 2. записывает файлы наборов и рабочую копию профиля в `python_app/runtime/`; 3. очищает историю, если процессор запускается заново (первый **Start**, перезапуск на шаге 1) или изменились профиль сбора, наборы или режекторный фильтр (тогда в журнале `History reset because run settings changed`); 4. запускает процесс сбора и препроцессор и ждёт до 3 с, пока они поднимутся; 5. начинает читать кольца; строка состояния — **Status: running**. Если во время работы процесс конвейера завершился, программа пишет отчёт с хвостом его вывода и перезапускает конвейер: первый раз сразу, следующие подряд — не раньше чем через 6, 12, 24, 48, затем 60 с после предыдущей попытки, пока не получится. Повторное нажатие **Start** при работающем сборе отвечает `Pipeline is already running`. ### Single Capture Делает то же, что **Start**, но процесс сбора снимает одну коллекцию и завершается. Если шёл непрерывный сбор, он сначала останавливается. Программа ждёт результат коллекции, снятой после нажатия, рисует его и останавливает сбор (`Single capture completed`). Строка состояния — **Status: single capture running**. Если результата нет 300 с, сбор останавливается с `Single capture timed out after 300s with no result; stopping.` В режиме 3D SAR, если результат не посчитался, строка состояния показывает **Status: no signal**, **Status: error** или **Status: warning**. ### Stop Останавливает процесс сбора, дочитывает кольца (до 0,35 с), останавливает препроцессор и дочитывает результаты (до 0,25 с). Процессор и локатор продолжают работать: так остановленный B-scan можно пересчитать, а клиенты локатора остаются подключёнными. Запись на диск завершается. **Stop** отменяет и ожидающие действия: автозапуск, продолжение после приостановки, съём для калибровки по объекту, пересчёт B-scan. ### Apply Radar Приостанавливает сбор, проверяет профиль и: - одиночный LibreVNA (`native`) — открывает прибор, отправляет настройки развёртки, закрывает; - многоприборная схема — приборы не трогает (их настраивает процесс сбора), только перечитывает пределы мастера; - радиофотонный радар — программирует плату лазеров, если она включена в профиле; - режим `mock` у любой модели — ничего (`Radar pre-configuration skipped (mock mode)`). Если работает только процессор, а настройки, от которых он зависит, изменились, **Apply Radar** перезапускает процессор и очищает историю. В журнал пишется `Radar settings applied: start=…, stop=…, points=…, ifbw=…, power=…`. Профиль кнопка не меняет. ### Load Config… и Save Config… **Load Config…** открывает выбор файла (**Load Config Profile**) и загружает профиль: все поля, таблицы геометрии, выбранные наборы, режим. Сбор должен быть остановлен, иначе — `Stop all pipeline processes before loading a config profile`. Ошибка чтения показывается как `Failed to load config profile: …`, текущий профиль при этом не меняется. **Save Config…** (**Save Config Profile**) записывает профиль; имя без расширения получает `.json`, существующий файл перезаписывается. Записываются все поля окна, выбранные наборы и геометрия. Загруженный или сохранённый профиль становится стартовым для следующего запуска. ### Clear Runtime History Приостанавливает сбор, отбрасывает непрочитанные данные колец, очищает историю окна и процессора, очищает графики и продолжает сбор. Файлы на диске не трогает; подтверждения не спрашивает. Поздние результаты коллекций, снятых до очистки, отбрасываются. ## Data Actions | Элемент | Что делает | | --- | --- | | **Save Last 1000** | сохраняет до 1000 последних коллекций каждой стадии (сырые, предобработанные, результаты) в новый каталог набора данных | | **Save S21 JSON** | сохраняет S21 предобработанной стадии в файлы JSON, по файлу на пару | | **Remove Last Measurement** | удаляет новейшую коллекцию из истории всех стадий | | **Capture Temporary Reference** | снимает временный референс и сразу его применяет ([Калибровка и предобработка](preprocessing.md)) | | **Start + Record to Disk** | запускает сбор, если он остановлен, и записывает на диск следующие **Sweeps to record** коллекций | | **Sweeps to record** | сколько коллекций записать, от 1 до 1 000 000 | | **Path**, **Browse…** | каталог, в котором создаются наборы данных | | **Name** | имя набора данных; пусто — `snapshot_<дата>_<время>` по UTC | Каталог набора данных — `/<префикс>_`. Префикс описывает снятое: модель, полосу, число точек (у радиофотонного радара — `adc`) и мощность. Каталог не должен существовать (`Snapshot directory already exists`). Рядом с данными кладутся профиль, с которым они сняты (`config_profile.json`), и все ревизии настроек обработки (`processing_settings.json`). Состав файлов — в главе [Данные на диске](data.md). Перед сохранением программа дочитывает данные из колец; идущий сбор и запись при этом не прерываются. Если в памяти нет ни одной коллекции, сохранение отказывает: `No runtime data is available for save`. Окно хранит в памяти до 1000 коллекций каждой стадии; что старее, не сохранить. Без колец-копий (`raw_tap`, `preprocessed_tap`) сохраняются только результаты. **Save S21 JSON** пишет по файлу на пару: для каждой коллекции — сырая и предобработанная развёртка, рядом профиль `vna_config_profile.json`. Его можно направить в существующий каталог набора данных: существующие файлы данных JSON не перезаписываются, а `vna_config_profile.json` заменяется. **Remove Last Measurement** приостанавливает сбор и удаляет из истории окна и процессора самую новую коллекцию; если её результат ещё в пути, процессор его не выдаст. Повторное нажатие удаляет следующую. **Start + Record to Disk** записывает коллекции, которые придут после нажатия. Запись заканчивается, когда записано заданное число, по **Stop**, при приостановке сбора (очистка истории, временный референс, съём) или если диск не успевает и очередь записи переполнилась; причина пишется в журнал. Одновременно идёт только одна запись (`A recording is already in progress…`), а каталог должен быть новым. Закрытие окна дописывает принятые данные. ## Switches | Элемент | Что делает | | --- | --- | | **Settling (ms)** | пауза после переключения ВЧ-ключей перед развёрткой, мс (`run.settling_ms`) | | **Run combos** и **Select** | список пар сбора `вход:выход` через запятую; пусто — полная матрица. **Select** делает этот список источником пар | | **Single combo**: **Input**, **Output** и **Select** | одна пара сбора; **Select** делает её источником пар | | **B-scan pair** | какую пару показывать в B-scan; доступно в режиме B-scan | | **Next Combination** | следующая пара B-scan; доступно, когда пар в истории хотя бы две | Пары сбора применяются при **Start**. У многоприборной схемы список всегда равен полной матрице и не редактируется. В режимах pass-through и B-scan, если оба ключа `mock` или у обоих одно положение, снимается только пара `0:0`. ## Selected Preprocess Sets Показывает выбранные наборы: **S21 calibration**, **S21 reference**, **Object calibration**; `` — набор не выбран. Выбираются наборы в окне **Preprocessing Setup**. ## Processing Страница настроек выбранного режима. Каждое поле описано в главе [Режимы обработки](processing.md). В режимах GPR и 3D SAR над настройками — таблицы геометрии антенн. ### Таблицы геометрии **Tx geometry** — передающие антенны: **Output** (номер выхода), **X (m)**, **Y (m)**, **Z (m)**. **Rx geometry** — приёмные: **Input**, **X (m)**, **Y (m)**, **Z (m)**. Координаты — в осях радара (глава [Как работает радар](principles.md)). - **Add Antenna** добавляет строку со следующим свободным номером; строка начинает действовать после ввода X, и до этого кнопка недоступна. Недоступна она и тогда, когда строк столько же, сколько выходов или входов. - **Remove Selected** удаляет выделенные строки. - Каждая правка проверяется: номер — целый, в пределах матрицы, без повторов; координаты — числа; требования GPR и 3D SAR выполняются. Неверная правка откатывается с сообщением **Invalid Antenna Geometry**. - Принятая правка сразу уходит процессору и пересчитывает результат. Если она не совпадает с геометрией выбранной калибровки по объекту, выбор этой калибровки снимается. ## Radar Для LibreVNA и симулятора секция показывает развёртку: | Поле | Ключ профиля | | --- | --- | | **Start (Hz)** | `radar.sweep.start_hz` | | **Stop (Hz)** | `radar.sweep.stop_hz` | | **Points** | `radar.sweep.points` | | **IF bandwidth (Hz)** | `radar.sweep.if_bandwidth_hz` | | **Stimulus power (dBm)** | `radar.sweep.stimulus_power_dbm` | Под полями — пределы прибора: `Limits: freq=…, points=1..N, ifbw=…, power=…`. В режиме `mock` и у радиофотонного радара пределов нет: `Device limits are not available.` (с `driver_mode: "native"` без подключённого прибора окно не открывается — глава [Неполадки](troubleshooting.md)). С известными пределами подпись поля дополняется диапазоном, а значения вне его подрезаются с предупреждением `Radar fields were adjusted to satisfy device limits.` Поле применяется, когда из него уходит фокус или нажат Enter. Если изменение меняет ключ радара, выбор наборов сбрасывается, а границы частот обработки подрезаются под новую развёртку. Для радиофотонного радара вместо развёртки показаны поля коллектора и платы лазеров: | Поле | Ключ профиля | | --- | --- | | **Project dir**, **Executable path**, **TTY path** | `radar.rph_radar.project_dir`, `executable_path`, `tty_path` | | **Arguments** (по строке на параметр) | `radar.rph_radar.args` | | **Environment JSON** | `radar.rph_radar.env` | | **Startup timeout (s)**, **Read timeout (s)**, **Stop timeout (s)** | `startup_timeout_s`, `sweep_timeout_s`, `stop_timeout_s` | | **Board enabled** | `radar.laser_control.enabled` | | **Board port**, **Board mode** | `port`, `mode` (`manual` или `variation`) | | **PI 1 P**, **PI 1 I**, **PI 2 P**, **PI 2 I** | `pi_coeff1_p`, `pi_coeff1_i`, `pi_coeff2_p`, `pi_coeff2_i` | | **Temperature 1**, **Temperature 2**, **Current 1**, **Current 2** (режим `manual`) | `manual.temp1`, `temp2`, `current1`, `current2` | | **Static temp 1**, **Static temp 2**, **Static current 1**, **Static current 2**, **Min value**, **Max value**, **Step**, **Time step**, **Delay time** (режим `variation`) | `variation.static_temp1` … `delay_time` | Поля платы доступны при включённой **Board enabled**; видны поля только выбранного режима. Единицы и пределы — в главе [Файл конфигурации](configuration.md). Поля коллектора применяются при **Start**, поля лазера — кнопкой **Apply Radar**. ## Строка состояния и журнал Под секциями — строка состояния и счётчик истории `History: raw=0, preprocessed=0, results=0` (сколько коллекций каждой стадии в памяти). | Состояние | Что значит | | --- | --- | | **Status: idle** | сбор остановлен | | **Status: running** | идёт непрерывный сбор | | **Status: single capture running** | идёт однократный съём | | **Status: error** | в журнал записана ошибка; состояние держится до следующего изменения | | **Status: result display error (acquisition continues)** | не удалось нарисовать результат; сбор продолжается | | **Status: runtime display/recording error (acquisition continues)** | ошибка отображения или записи на диск; сбор продолжается | | **Status: no signal**, **Status: warning** | итог однократного съёма в режиме 3D SAR | **Runtime Log** — журнал программы. Список **Level** (**Debug**, **Info**, **Warning**, **Error**) задаёт наименьший уровень записей; он применяется сразу и сохраняется в профиль при **Save Config…**. Стрелка справа прячет и показывает журнал. В окне хранится до 2000 последних записей; при переполнении появляется `Log panel overflow: N record(s) dropped (they are still in the log file).` Полный журнал — в `python_app/runtime/logs/radar.log` (глава [Данные на диске](data.md)). Повторяющиеся ошибки отрисовки показываются один раз. ## Графики | Режим | Что на экране | | --- | --- | | pass-through | **Pass-Through S21**: модуль (**Magnitude (dB)**) и фаза (**Phase (deg)**) по частоте, кривая на пару, легенда `in<вход>/out<выход>` | | B-scan | **B-scan S21 in<вход>/out<выход> \| sweeps=N**: номер развёртки — дальность | | GPR | **GPR coherent BP — ground plane**: карта плоскости земли и объекты | | 3D SAR | **Front (X-Y)**, **Side (Z-Y)**, **Top (X-Z)**, **3D Projection** и строка состояния 3D SAR над ними | Подробно виды описаны в главе [Режимы обработки](processing.md). Приставку единиц на осях (Гц, МГц, ГГц, м, мм) график подбирает сам. Графики управляются мышью так, как принято в библиотеке pyqtgraph: колесо меняет масштаб, перетаскивание сдвигает, правая кнопка открывает меню (**View All** — вернуть весь график, экспорт картинки). Щелчок по строке легенды прячет и показывает кривую. Графики окна видны и в веб-интерфейсе. Последняя развёртка снятого набора (калибровка, референс, временный референс) рисуется на графике pass-through с подписью вида `Tmp S21 Reference last trace`. ## Сообщения Ошибка действия открывает окно с ошибкой и пишется в журнал. Без экрана, для действий из веб-интерфейса и для GPIO-кнопки окон нет: ошибка уходит в журнал, а веб-интерфейсу — в ответ на запрос. Причины частых ошибок — в главе [Неполадки](troubleshooting.md). Окно ошибки называется по действию и обычно показывает `<заголовок>: <тип ошибки>: <текст>` (у записи на диск — `<заголовок>: <текст>`): | Заголовок | Действие | | --- | --- | | `Failed to start pipeline` | **Start**, **Single Capture** | | `Failed to stop pipeline` | **Stop** | | `Failed to apply radar settings` | **Apply Radar** | | `Failed to load config profile`, `Failed to save config profile` | **Load Config…**, **Save Config…** | | `Failed to open preprocessing panel` | **Preprocessing…** | | `Failed to clear runtime history`, `Failed to remove last runtime measurement` | **Clear Runtime History**, **Remove Last Measurement** | | `Failed to save snapshot`, `Failed to save VNA history JSON` | **Save Last 1000**, **Save S21 JSON** | | `Failed to start disk recording` | **Start + Record to Disk** | | `Failed to capture tmp reference` | **Capture Temporary Reference** | | `Cannot switch processing mode to <режим>` | **Mode** | | `Failed to update live processing settings`, `Failed to update plot display settings`, `Failed to render processing settings` | правка настроек обработки и вида | | `Failed to recompute the B-scan` | пересчёт остановленного B-scan | | `Failed to start <вид> sequence`, `Failed to capture combo; previous captures kept, retry when ready`, `Failed to undo last preprocess capture`, `Failed to save preprocess set`, `Failed to abort capture sequence`, `Failed to refresh preprocessing sets`, `Failed to create neutral S21 sets` | окно **Preprocessing Setup** | | `Failed to capture object-calibration data`, `Failed to calculate object calibration`, `Failed to save object calibration`, `Failed to update object calibration after geometry change` | калибровка по объекту | | `Cannot perform data action`, `Cannot modify runtime history during active capture sequence` | действие с данными во время съёма или остановки | | `Shutdown operation failed` | закрытие окна | Пока идёт съём наборов, часть действий недоступна, и программа объясняет почему: `Finish the active capture sequence first`, `Wait for preprocessing capture to finish`, `Wait for object-calibration capture to finish`, `Wait for pipeline shutdown to finish`.