Files
radar_system/docs/installation.md
T
2026-10-16 18:35:02 +03:00

239 lines
16 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Установка и запуск
Программа работает в Linux: на рабочей станции с экраном и на Raspberry Pi 5 без
оператора. Python-часть ставится в виртуальное окружение `.venv` внутри каталога
проекта, C++-часть собирается командой `make` в `build/bin/`.
## Что нужно
| Что | Зачем |
| --- | --- |
| Linux, bash, coreutils, `flock` | запуск через `start.sh` |
| Python 3.10 или новее с модулем `venv` | программа и окружение |
| компилятор C++20 (g++), `make` | процессы конвейера |
| библиотеки `libusb-1.0` и `libatomic.so.1` | USB-доступ к LibreVNA и кольца разделяемой памяти |
| `libxcb-cursor0`, `libxkbcommon-x11-0` (Debian/Ubuntu) | окно Qt на рабочем столе |
| видеокарта NVIDIA с драйвером, NVRTC и заголовки CUDA | только для режима 3D SAR |
| библиотеки L-Card `libx502api.so`, `libe502api.so` | только для радиофотонного радара с АЦП E-502 |
Python-пакеты перечислены в `requirements.txt`:
| Пакет | Для чего |
| --- | --- |
| `numpy` | массивы данных |
| `scipy` | оптимизация в калибровке по объекту |
| `libusb1` | USB-драйвер LibreVNA |
| `pyserial` | последовательный порт платы лазеров |
| `PyQt6` | окно программы (без экрана — тоже, в режиме `offscreen`) |
| `pyqtgraph` | графики |
| `fastapi`, `uvicorn[standard]` | веб-интерфейс |
| `nvidia-cuda-nvrtc`, `nvidia-cuda-runtime` | NVRTC и заголовки CUDA для 3D SAR; ставятся только на x86_64 |
PyQt6 ставится только из готовых сборок (wheel), поэтому pip выбирает самую новую
версию, которая работает с системной glibc.
## Установка
Из каталога проекта:
```sh
python3 -m venv .venv
.venv/bin/python -m pip install --upgrade pip
.venv/bin/python -m pip install -r requirements.txt
make # build/bin/data_preprocessor и build/bin/data_processor
make rph_radar_collector # только для радиофотонного радара с АЦП E-502
```
`./start.sh` при обычном запуске делает это сам: создаёт `.venv`, если его нет, ставит
недостающие пакеты, ставит системные библиотеки через менеджер пакетов (apt, dnf, yum,
pacman, zypper или brew, через `sudo`), правило udev для LibreVNA и собирает C++. Без
экрана (`--headless`) он ничего не ставит: всё должно быть установлено заранее.
## Запуск
```sh
./start.sh --profile run_config_examples/run_config_librevna_multi_per_point.example.json
```
Без `--profile` программа берёт последний использованный профиль, а если его нет —
корневой `run_config.json` (симулятор). Порядок выбора профиля — в главе
[Файл конфигурации](configuration.md). Но сам `start.sh` без `--profile` определяет
модель радара, решает, собирать ли коллектор E-502, и проверяет программы по
корневому `run_config.json`, а `--producer-only` берёт именно его. Поэтому с профилем
радиофотонного радара и для `--producer-only` всегда указывайте `--profile`.
| Ключ `start.sh` | Что делает |
| --- | --- |
| `--profile ПУТЬ` | профиль для запуска; файл должен существовать. Относительный путь — от каталога проекта |
| `--headless` | без окна: окно не показывается, через 0,5 с выполняется **Apply Radar**, ещё через 1 с — **Start**; если **Start** не удался, программа завершается с кодом 1 (`Headless auto-start did not bring the pipeline up`). Ничего не устанавливает |
| `--auto-start` | с окном, но **Start** выполняется сам через 0,5 с после запуска |
| `--producer-only` | запустить только процесс сбора для профиля, без окна; вывод — в терминал |
| `--skip-build` | не собирать C++ (наличие программ всё равно проверяется) |
| `--build-only` | подготовить окружение, собрать и выйти |
| `--clean-shm` | удалить известные кольца в `/dev/shm` перед запуском (глава [Данные на диске](data.md)) |
| `-h`, `--help` | справка |
Порядок работы `start.sh`: проверка окружения → определение модели радара по профилю
→ системные библиотеки и правило udev (не для `--headless`) → Python-пакеты → сборка
C++ (для радиофотонного радара — и коллектора) → проверка программ в `build/bin/` →
остановка службы `radar.service`, если она работает → блокировка
`/tmp/radar_system.lock` → запуск программы. Если блокировку держит другой
экземпляр, `start.sh` завершается с
`Another radar instance already holds /tmp/radar_system.lock; aborting.`
Для разработки окно можно запустить и напрямую:
`.venv/bin/python -m python_app.gui.main`. Тогда нет ни сборки, ни блокировки.
### Первый запуск без железа
1. Запустите `./start.sh` (корневой профиль — симулятор).
2. Нажмите **Preprocessing…**, затем **Create Neutral S21 Sets**: предобработке
нужны наборы калибровки и референса, нейтральные данные не меняют.
3. Нажмите **Start**. Симулятор показывает точечный отражатель, который движется
по сцене; режим обработки меняется списком **Mode**.
Режим 3D SAR без видеокарты NVIDIA показывает только предупреждение.
### Первый запуск с железом
1. Скопируйте нужный профиль из `run_config_examples/` и проверьте в нём серийные
номера, порты, линии GPIO и геометрию антенн (глава
[Файл конфигурации](configuration.md)).
2. Запустите `./start.sh --profile <профиль>`. При первом запуске он может спросить
пароль `sudo`, чтобы поставить системные библиотеки и правило udev для LibreVNA.
3. Нажмите **Apply Radar**, снимите калибровку и референс (глава
[Калибровка и предобработка](preprocessing.md)) и нажмите **Start**.
4. Нажмите **Save Config…**: выбор наборов и правки в окне сохраняются только так.
Порядок работы по шагам — в главе [Типовые сценарии](workflow.md).
## Видеокарта для 3D SAR
Ядра 3D SAR компилируются при запуске библиотекой NVRTC под установленную карту.
`make` ищет `nvrtc.h`, `cuda.h` и `libnvrtc` в пакетах `nvidia-cuda-*` из `.venv` и в
`/usr/local/cuda`, а `libcuda.so.1` (драйвер) — в системных каталогах. Если чего-то
нет, `make` пишет `note: CUDA not found, selecting sar3d will show a warning` и
собирает процессор без 3D SAR. После установки CUDA снова запустите `make`: он
заметит изменение и пересоберёт нужную часть.
- На x86_64 CUDA 13 ставится из `requirements.txt`. Целевая карта — RTX 5070.
- NVRTC 13 не компилирует под карты старее поколения sm_75 (например, GTX 1060,
sm_61). Для них поставьте NVRTC 12 отдельно от `.venv` и соберите в отдельный
каталог:
```sh
pip install --target ~/.cache/radar_nvrtc12 nvidia-cuda-nvrtc-cu12 nvidia-cuda-runtime-cu12
make BUILD_DIR=/tmp/build-nvrtc12 CUDA_ROOTS="$HOME/.cache/radar_nvrtc12/nvidia/cuda_nvrtc $HOME/.cache/radar_nvrtc12/nvidia/cuda_runtime"
```
Программа запускает процессор только из `build/bin/`, поэтому такая сборка нужна
для проверки на старой карте (глава [Разработка](development.md)).
- На Jetson CUDA берётся из JetPack (`/usr/local/cuda`); pip-пакеты CUDA там не
ставятся. PyQt6 на Jetson с glibc 2.35 — версии 6.7.
## Служба без экрана
На машине без оператора программу запускает служба systemd. Установка — один раз,
от обычного пользователя через `sudo`:
```sh
sudo bash deploy/install-daemon.sh
```
Скрипт создаёт `/etc/systemd/system/radar.service`, разрешает пользователю без пароля
`sudo systemctl stop|start|restart radar.service` (`/etc/sudoers.d/radar`) и включает
службу при загрузке, но не запускает её. Служба работает от имени этого пользователя
в каталоге проекта, запускает `start.sh --headless --skip-build`, перезапускается через
3 с после сбоя, а при остановке ждёт программу до 25 с.
```sh
sudo systemctl start radar.service # запустить
systemctl status radar.service # состояние
journalctl -u radar.service -f # журнал
sudo systemctl disable --now radar.service && sudo rm /etc/systemd/system/radar.service /etc/sudoers.d/radar && sudo systemctl daemon-reload # удалить
```
Служба берёт последний использованный профиль. Перед её запуском откройте окно
программы на этой машине, загрузите профиль с железом, выберите наборы и нажмите
**Save Config…**. Работа со службой — в разделе «Работа без экрана» главы
[Веб-интерфейс, кнопка и локатор](web.md).
## Машина развёртывания
Raspberry Pi 5 Model B (Cortex-A76 ×4, 4 ГиБ), Debian 13, Python 3.13. Проект лежит в
`~/Documents/radar_system`. На машине собираются `.venv` и C++; копировать их с
рабочей станции нельзя: там другая архитектура (x86_64).
```sh
python3 -m venv .venv && .venv/bin/python -m pip install -r requirements.txt
make -j4
QT_QPA_PLATFORM=offscreen .venv/bin/python -m unittest discover -s python_app/tests
```
На Pi нужна только часть проекта: `data_acq_and_processing`, `deploy`, `python_app`,
`run_config_examples`, `Makefile`, `requirements.txt`, `run_config.json`, `start.sh`.
Каталог `device_firmware/` и документация не нужны.
> **Внимание.** Номер GPIO-чипа 40-контактного разъёма на Pi 5 зависит от версии
> ядра. После установки и обновления ядра проверьте его: `gpiodetect` и
> `gpioinfo -c gpiochip0`. Неверный чип в профиле — ключи, которые молча не
> переключаются.
## Обновление с флешки
На рабочей станции:
```sh
deploy/pack-usb.sh /media/<пользователь>/<флешка>
```
Без аргумента скрипт берёт единственную подключённую съёмную флешку. В каталог
`radar_update/` на ней он кладёт архив `radar_system-<дата коммита>-<хеш>.tar.gz`
с частью проекта для Pi из **последнего коммита** (незакоммиченные изменения в него не
попадают) и скрипт `update.sh`.
На машине, от обычного пользователя (не через `sudo`), из каталога, где лежит
`radar_update`:
```sh
bash radar_update/update.sh # перенести текущий .venv
bash radar_update/update.sh --python 3.13 # собрать .venv заново этим Python
```
Скрипту можно передать путь к архиву: `bash radar_update/update.sh <архив>`; без него
берётся последний по имени `radar_system-*.tar.gz` рядом со скриптом.
Перед обновлением закройте окно программы, иначе скрипт откажется и покажет, какие
процессы работают в каталоге. Службу он остановит сам и запустит снова, если она
работала.
Что делает `update.sh`:
1. проверяет архив и переименовывает текущую версию в `radar_system<N>` — следующий
свободный номер; это копия для отката;
2. разворачивает новую версию в `~/Documents/radar_system` (другой каталог задаёт
переменная `RADAR_DIR`);
3. переносит из прежней версии: `run_config.json`; профили из
`run_config_examples/`, изменённые на машине (версия из архива ложится рядом с
окончанием `.new`); `python_app/runtime/` без журналов; данные
`python_app/data*` и чужие каталоги верхнего уровня — жёсткими ссылками, без
копирования и места на диске; `.venv` — копией;
4. ставит пакеты из `requirements.txt` и собирает C++ (`make all rph_radar_collector`);
5. записывает имя архива в файл `RELEASE` и запускает службу, если она работала.
Если что-то пошло не так, скрипт печатает команду отката. Вручную:
```sh
sudo systemctl stop radar.service
mv ~/Documents/radar_system ~/Documents/radar_system_failed
mv ~/Documents/radar_system<N> ~/Documents/radar_system
sudo systemctl start radar.service
```
Новую версию при откате лучше переименовать, а не удалять: в ней могут быть
измерения, снятые после обновления.
На свежую машину (без прежней версии) `update.sh` спрашивает
`Install a fresh one there? [y/N]` и ставит корневой `run_config.json` из архива, то есть
симулятор: профиль с железом нужно выбрать после установки.