|
|
# FPV Tracker Optimized
|
|
|
|
|
|
Русская документация для проекта сопровождения и удержания воздушной цели на базе `YOLO + ByteTrack + Kalman + KLT`.
|
|
|
|
|
|
Проект умеет:
|
|
|
|
|
|
- принимать видео с файла, камеры, RTSP, UDP-потока и готового UDP-дампа камеры;
|
|
|
- обнаруживать и сопровождать цель;
|
|
|
- удерживать цель при кратковременной потере детекции;
|
|
|
- строить команды наведения в экранных координатах;
|
|
|
- экспортировать команды в `json`, `mavlink`, `msp` и испытательный `proto_udp`;
|
|
|
- работать локально или в Docker с GPU.
|
|
|
|
|
|
## Быстрый старт
|
|
|
|
|
|
### Локальный запуск
|
|
|
|
|
|
1. Установите Python 3.12 и зависимости.
|
|
|
2. Проверьте, что модель `best.pt` лежит в корне проекта.
|
|
|
3. Настройте `SOURCE` и `MODEL_PATH` в `config.py`.
|
|
|
4. При необходимости настройте backend в `config_intercept.py`.
|
|
|
5. Запустите:
|
|
|
|
|
|
```bash
|
|
|
python main.py
|
|
|
```
|
|
|
|
|
|
### Docker-запуск
|
|
|
|
|
|
1. Установите Docker.
|
|
|
2. Для GPU установите NVIDIA Container Toolkit на хосте.
|
|
|
3. Соберите образ:
|
|
|
|
|
|
```bash
|
|
|
docker compose build
|
|
|
```
|
|
|
|
|
|
4. Запустите:
|
|
|
|
|
|
```bash
|
|
|
docker compose up
|
|
|
```
|
|
|
|
|
|
Откройте `http://localhost:8080` и запустите обработку кнопкой «Старт». Отдельный трекер без UI: `docker compose --profile standalone up fpv-tracker`.
|
|
|
|
|
|
### HDMI по USB в Docker Desktop
|
|
|
|
|
|
Linux-контейнер Docker Desktop не видит Windows DirectShow-камеры как `/dev/video*`. Перед использованием режима `HDMI по USB` один раз запустите локальный мост:
|
|
|
|
|
|
```powershell
|
|
|
powershell -ExecutionPolicy Bypass -File .\start-hdmi-bridge.ps1
|
|
|
docker compose up -d
|
|
|
```
|
|
|
|
|
|
В UI выберите `HDMI по USB`, индекс Windows-устройства, качество и FPS. Мост принимает HDMI на Windows и передаёт контейнеру MJPEG через `host.docker.internal:8091`. Повторный запуск скрипта не создаёт второй процесс.
|
|
|
|
|
|
## Комплект документации
|
|
|
|
|
|
- [Полный runbook](docs/RUNBOOK_RU.md)
|
|
|
- [Архитектура проекта](docs/ARCHITECTURE_RU.md)
|
|
|
- [Справочник конфигурации](docs/CONFIG_REFERENCE_RU.md)
|
|
|
- [Испытательный UDP-протокол](docs/PROTOCOL_UDP_RU.md)
|
|
|
- [Поиск и устранение проблем](docs/TROUBLESHOOTING_RU.md)
|
|
|
|
|
|
## Что является точкой входа
|
|
|
|
|
|
Основной runtime проекта запускается через:
|
|
|
|
|
|
```bash
|
|
|
python main.py
|
|
|
```
|
|
|
|
|
|
В проекте нет полноценного CLI с аргументами командной строки. Конфигурация задается:
|
|
|
|
|
|
- напрямую через `config.py`;
|
|
|
- напрямую через `config_intercept.py`;
|
|
|
- через env-переменные, если проект запускается в контейнере или через shell.
|
|
|
|
|
|
## Основные файлы
|
|
|
|
|
|
- `main.py` — основной цикл обработки видео.
|
|
|
- `hdmi_usb_bridge.py` — мост Windows DirectShow → MJPEG для Docker.
|
|
|
- `start-hdmi-bridge.ps1` — фоновый запуск HDMI-моста.
|
|
|
- `config.py` — настройки источника, детектора, трекинга, ROI и вывода.
|
|
|
- `config_intercept.py` — настройки наведения, range/PN/FSM и backend'ов.
|
|
|
- `guidance.py` — экранный guidance и экспорт `guidance_state.json`.
|
|
|
- `autopilot_bridge.py` — отправка команд наружу.
|
|
|
- `runtime_env.py` — env-overrides для контейнера и shell-запуска.
|
|
|
- `bytetrack_min_aggressive.py` — локальная реализация ByteTrack.
|
|
|
|
|
|
## Что генерируется во время работы
|
|
|
|
|
|
В зависимости от настроек проект может создавать:
|
|
|
|
|
|
- `out_infer_*.mp4` — видео с наложениями;
|
|
|
- `runtime-data/track-logs/track_log_*.csv` — покадровый лог;
|
|
|
- `runtime-data/track-summaries/track_summary_*.json` — сводка по прогону;
|
|
|
- `guidance_state.json` — текущее состояние guidance;
|
|
|
- `autopilot_cmd.json` — команды автопилота при backend `json`.
|
|
|
|
|
|
## Статус Docker-упаковки
|
|
|
|
|
|
В проекте уже подготовлены:
|
|
|
|
|
|
- `Dockerfile`
|
|
|
- `docker-compose.yml`
|
|
|
- `docker/entrypoint.sh`
|
|
|
- `requirements-docker.txt`
|
|
|
|
|
|
После сборки образ рассчитан на запуск без интернета.
|
|
|
|
|
|
## UDP-источники
|
|
|
|
|
|
В `Настройки → Источник → Режим` доступны пять отдельных вариантов:
|
|
|
|
|
|
- `Камера UDP — кадры с разделительным байтом` — живой поток raw-кадров. Размер и FPS задаются произвольно; профиль `512x640 @ 50 FPS` соответствует 640 строкам по 512 значений.
|
|
|
- `Камера UDP МИК — протокол документа` — приём и сборка payload-пакетов МИК по `first/last`, sequence и offset.
|
|
|
- `Камера UDP — пользовательский пакет` — конструктор заголовка и способа сборки без изменения кода.
|
|
|
- `Файл UDP-лога МИК` — готовый лог с четырёхбайтовой обёрткой `порт + размер payload`; порт определяется по файлу и может отличаться от `59004`.
|
|
|
- `Файл UDP-лога — кадры с разделителем` — готовая последовательность кадров, разделённых одним байтом.
|
|
|
|
|
|
Для live-режимов задаются bind-адрес, UDP-порт, ширина `16–8192`, высота `16–8192` и FPS `1–240`. В Docker поле адреса приёма обычно должно быть `0.0.0.0`, а не IP отправителя. Docker Compose публикует `59004/udp` для МИК, `59005/udp` и `40404/udp` для кадров с разделителем. Для raw-потока размер кадра определяет его границу, поэтому значения пикселей могут совпадать с разделителем; отдельный байт между кадрами отбрасывается. Поддержаны `JPEG/PNG`, `BGR24`, `RGB24`, `Gray 8-bit`, `Gray 16-bit` и `YUYV 4:2:2`.
|
|
|
|
|
|
В поле `Способ разбора` доступны `Автоопределение`, `МИК по документу`, `Кадры с разделителем` и `Пользовательский пакет`. Автоопределение слушает выбранные адрес и порт 3 секунды, показывает фактический IP и порт отправителя, размеры датаграмм, HEX/ASCII и SHA-256 образцов, затем проверяет структуры МИК, RTP, MPEG-TS, JPEG/PNG, H.264/H.265, raw-кадров, JSON и текста. При строгом совпадении найденный режим применяется автоматически. Все UDP payload сохраняются без изменений в `runtime-data/udp-probes/*.udp`; рядом лежит JSON с временными метками, адресами отправителей и SHA-256 каждого пакета.
|
|
|
|
|
|
Конструктор показывает заголовок как ленту отдельных байтов. Кнопка `+ байт` добавляет блок, крестик удаляет его вместе с байтами, стрелки меняют порядок. Для каждого блока задаются имя, длина и назначение: `не читать`, `читать как число`, `flags`, `sequence`, `номер фрагмента` или `размер/смещение`. Размер заголовка и offsets вычисляются автоматически; именованные числовые поля читаются с выбранным endian. Отдельно задаются маски начала/конца, смысл `value`, способ сборки (`фрагменты`, `один датаграмм`, `поток`) и содержимое результата (`кадр` или массив МИК`). Для кадра выбираются размер, FPS и `JPEG/PNG`, `BGR24`, `RGB24`, `Gray8`, `Gray16` либо `YUYV422`. Повреждённая цепочка отбрасывается до следующего пакета с флагом начала.
|
|
|
|
|
|
Большие UDP-дампы загружаются напрямую в `/data/input` одним потоком, без второй временной копии в памяти или на диске. Интерфейс показывает процент загрузки и позволяет отменить операцию; незавершённый файл не попадает в список источников.
|
|
|
|
|
|
Разделительный байт не должен встречаться внутри данных кадра. Если это невозможно гарантировать, используйте формат МИК с явной длиной массива.
|
|
|
|
|
|
Готовое видео не ограничивается расширением файла: источник определяется FFmpeg по содержимому. Поддерживаются все контейнеры и кодеки, доступные в FFmpeg образа, включая `MP4`, `AVI`, `MOV`, `MKV`, `WebM`, `MPEG-TS`, `M2TS`, `MXF`, `WMV/ASF`, `FLV`, `VOB`, `OGV`, `3GP`, raw `H.264/H.265` и файлы с нестандартным расширением. В вебе любой успешно декодированный источник выводится через единый поток кадров, а обработанная запись сохраняется в совместимом MP4.
|
|
|
|
|
|
Для файла `1785156788883112336` структура разобрана согласно документу «МИК. Описание передачи данных на порт 59004»:
|
|
|
|
|
|
- `7c e6` — UDP-порт `59004` (`uint16 LE`), следующие 2 байта — длина payload;
|
|
|
- заголовок UDP payload: версия, флаги начала/конца, номер последовательности, номер пакета и `uint32 LE` размера/смещения;
|
|
|
- большой массив: `uint32 LE` количества меток, по 40 байт на метку, затем 8-байтный заголовок видеокадра;
|
|
|
- заголовок кадра задаёт ширину, высоту, Pixel ID и количество байт выравнивания каждой строки;
|
|
|
- в примере: `INT16`, `636x476`, по 8 padding-байт на строку; padding не передаётся модели как пиксели.
|
|
|
|
|
|
Декодер проверяет sequence, циклический packet number, offsets и флаги начала/конца, пропускает повреждённые последовательности, извлекает метки и формирует BGR-кадр. Поддержаны форматы `GRAY8`, `GRAY16`, `RGB888`, `YCbCr422` и `INT16`. Частота кадров берётся из настройки сценария. `PCAP/PCAPNG` сначала нужно преобразовать, извлекая UDP payload.
|
|
|
|
|
|
Переменные окружения для этих источников:
|
|
|
|
|
|
```text
|
|
|
FPV_SOURCE_MODE=udp_mik_live|udp_delimited_live|udp_custom_live|udp_dump|udp_delimited_file
|
|
|
FPV_UDP_INPUT_HOST=0.0.0.0
|
|
|
FPV_UDP_INPUT_PORT=59004
|
|
|
FPV_FRAME_SEPARATOR_BYTE=0
|
|
|
FPV_FRAME_ENCODING=auto|bgr24|rgb24|gray8|gray16|yuyv422
|
|
|
FPV_UDP_PACKET_SCHEMA={"assembly":"fragmented","header_size":8,"byte_order":"little"}
|
|
|
```
|