239 lines
16 KiB
Markdown
239 lines
16 KiB
Markdown
# Установка и запуск
|
||
|
||
Программа работает в 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` из архива, то есть
|
||
симулятор: профиль с железом нужно выбрать после установки.
|