Close the remaining audit findings

Environment, README, gitignore and the source self-parsing in Lab041.

requirements.txt and requirements-hardware.txt pin the versions actually
verified today on Python 3.13.1, split so the project comes up on a
machine with no SDR: pyadi-iio and libiio are only needed from Lab042 on.

The gitignore contradiction is fixed in the direction that keeps the
project reproducible. data/raw/ was ignored while six files were tracked
anyway, and four of them are the source images Lab007, Lab009, Lab011 and
Lab012 read as input. Untracking them would have broken those labs, so
the rule now carries explicit exceptions instead. Recorded in the README:
lab026_rover_source.mp4 is genuinely absent and Lab026 and Lab027 cannot
run without it.

README replaced. It claimed the next task was to write the first protocol
module, 41 labs later. It now states what exists, that the transmitter
has never been switched on, how to install either environment, how to run
tests, the gate and a lab, and that rover/, ground_station/ and gnuradio/
are still empty. Added rule 9: every number in a report must come from
the current run, transferred values must name their source.

Lab041 no longer parses its own source to check that plot labels are in
Russian. That belonged to presentation, not to model correctness, and
turned the experiment into an analyser of its own text; ast, inspect and
re are no longer imported. Rerun: 180 combinations, 24/24 checks, five
CSV and seven PNG, unchanged.

125 tests pass, gate passes.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
LittleSam129
2026-08-10 15:33:14 +03:00
parent 92289bdf7c
commit 0ae04ae4a8
6 changed files with 164 additions and 273 deletions

17
.gitignore vendored
View File

@@ -29,9 +29,24 @@ __pycache__/
venv/ venv/
env/ env/
# Необработанные данные и IQ-записи # Необработанные данные и IQ-записи.
# Правило закрывает крупные записи отсчётов и видео: они воспроизводятся
# заново и в историю не помещаются.
data/raw/ data/raw/
# Исключения: исходные изображения — это входные данные лабораторных, а не
# результат. Без них Lab007, Lab009, Lab011 и Lab012 не запускаются, поэтому
# они хранятся в репозитории. Суммарно около 1 МБ.
!data/raw/lab007_source.jpg
!data/raw/lab009_source.jpg
!data/raw/lab011_scene.jpg
!data/raw/lab012_safety_scene.jpg
# Метаданные и спектр записи Lab024a: сама запись отсчётов не хранится,
# поэтому они оставлены как след проведённого измерения.
!data/raw/lab024a_pluto_rx_100mhz.json
!data/raw/lab024a_pluto_rx_100mhz_spectrum.png
# Временные файлы редакторов # Временные файлы редакторов
*.tmp *.tmp
*.temp *.temp

361
README.md
View File

@@ -4,330 +4,169 @@
**SDR Rover Link** — учебно-исследовательский проект по разработке цифрового радиоканала для наземного робототехнического комплекса с использованием программно-определяемого радио — SDR, Software Defined Radio. **SDR Rover Link** — учебно-исследовательский проект по разработке цифрового радиоканала для наземного робототехнического комплекса с использованием программно-определяемого радио — SDR, Software Defined Radio.
Проект должен пройти полный путь от передачи простого текстового пакета до передачи телеметрии и отдельных JPEG-изображений через реальный радиоканал. Проект должен пройти полный путь от передачи простого текстового пакета до передачи телеметрии и изображений через реальный радиоканал.
Основная задача проекта — не только получить работающую систему, но и последовательно изучить все этапы цифровой радиосвязи: Основная задача — не только получить работающую систему, но и последовательно изучить все этапы цифровой радиосвязи: формирование данных, разбиение на пакеты, контроль целостности, исправление ошибок, цифровую модуляцию, формирование IQ-сигнала, передачу через SDR, приём, демодуляцию и восстановление исходных данных.
- формирование данных;
- разбиение данных на пакеты;
- контроль целостности;
- исправление ошибок;
- цифровую модуляцию;
- формирование IQ-сигнала;
- передачу через SDR;
- приём и демодуляцию;
- восстановление исходных данных.
--- ---
## 2. Целевой сценарий ## 2. Целевой сценарий
Разрабатываемая система предназначена для исследовательского наземного ровера.
Целевые требования:
| Параметр | Требование | | Параметр | Требование |
|---|---| |---|---|
| Дальность связи | до 10 км | | Дальность связи | до 10 км |
| Скорость ровера | до 25 км/ч | | Скорость ровера | до 25 км/ч |
| Прямая радиовидимость | может отсутствовать | | Прямая радиовидимость | может отсутствовать |
| Рабочие частоты | ниже 350 МГц | | Рабочий диапазон | 200250 МГц, см. Запись 018 журнала |
| Основной тип данных | телеметрия и отдельные изображения | | Основной тип данных | телеметрия, команды и изображения |
| Формат изображения | JPEG | | Формат изображения | JPEG |
| Частота передачи изображений | отдельные кадры, не видеопоток |
| Действие при потере связи | безопасная остановка ровера | | Действие при потере связи | безопасная остановка ровера |
Дальность 10 км без прямой видимости является целевым исследовательским требованием, а не гарантированной характеристикой первой версии системы. Дальность 10 км без прямой видимости целевое исследовательское требование, а не гарантированная характеристика первой версии.
--- ---
## 3. Почему не используется обычное FPV-видео ## 3. Почему не используется обычное FPV-видео
Типовые FPV-системы работают преимущественно в диапазонах 2,4 и 5,8 ГГц. Типовые FPV-системы работают в диапазонах 2,4 и 5,8 ГГц. Для наземного робота это плохо: велики потери у поверхности земли, сильное затенение рельефом и растительностью, а главное — на таких частотах практически нет дифракции, поэтому за препятствием связь пропадает.
Для наземного робота такие диапазоны имеют ряд ограничений: В этом проекте вместо непрерывного видеопотока передаются отдельные сжатые изображения, что резко снижает требуемую скорость канала.
- высокие потери при работе у поверхности земли; ---
- затенение рельефом, зданиями и растительностью;
- быстрое ухудшение изображения при слабом сигнале;
- высокая загруженность распространённых диапазонов;
- зависимость от постоянного широкополосного видеопотока.
В этом проекте вместо непрерывного видео предполагается передавать отдельные сжатые изображения. ## 4. Текущее состояние
Пример: **Выполнено:** лабораторные Lab001Lab041. Пройден путь от структуры пакета до сеансов связи с защитой от пакетов предыдущего сеанса.
```text Что реализовано и проверено:
Камера
- пакетный протокол с CRC32, фрагментация и сборка изображений;
JPEG-изображение - модуляция и демодуляция BPSK, формирующий фильтр, кадровая синхронизация, оценка и коррекция ухода несущей;
- блочное исправление стираний над GF(256), перемежение, подбор параметров;
Разбиение на пакеты - приоритетное обслуживание команд, телеметрии и видео;
- двухступенчатая безопасная остановка, сторожевой таймер, постоянное аварийное намерение, безопасный сброс;
Передача через SDR - идентификаторы сеанса, безопасный запуск, отклонение пакетов предыдущего сеанса.
Сборка изображения на наземной станции **Что ещё не сделано:** передатчик ни разу не включался. Весь тракт проверен на моделях и на приёме, но не в эфире.
**Ближайшая работа:** Lab042 — передача JPEG через кабельную петлю на одном PlutoSDR. Техническое задание: [docs/lab042_hardware_loopback_spec.md](docs/lab042_hardware_loopback_spec.md).
Хронология решений и результатов: [PROJECT_LOG.md](PROJECT_LOG.md).
---
## 5. Оборудование
| Позиция | Состояние |
|---|---|
| **Pluto+** — приёмопередатчик, чип AD9361, 70 МГц 6 ГГц | есть |
| RTL-SDR — приёмный донгл | есть |
| Аттенюатор AT30S, 30 дБ, SMA | есть |
| Кабели SMA, штыревые антенны | есть |
| Усилитель мощности около 1 Вт | планируется после первых испытаний |
| Raspberry Pi как бортовой вычислитель | планируется |
Устройство подключается по USB и появляется в системе как сетевой адаптер с адресом `192.168.2.1`.
**Проверять связь с Pluto командой `ping` бесполезно.** При активном VPN трафик уходит в туннель, и «успешный» отклик приходит даже от несуществующего адреса. Достоверна только успешная установка контекста `iio.Context("ip:192.168.2.1")`.
---
## 6. Установка окружения
Расчётная часть работает на компьютере без SDR:
```bash
python -m pip install -r requirements.txt
``` ```
Такой подход позволяет существенно снизить требуемую скорость радиоканала. Для лабораторных, работающих с устройством, дополнительно:
```bash
python -m pip install -r requirements-hardware.txt
```
Версии зафиксированы по проверенному окружению, Python 3.13.
--- ---
## 4. Текущее оборудование ## 7. Как запускать
### SDR-оборудование **Быстрые проверки ядра** — секунды, оборудование не нужно:
- RTL-SDR — приёмник; ```bash
- ADALM-PlutoSDR — приёмопередатчик, ожидается поступление; python -m pytest tests/ -q
- HackRF One — может временно использоваться при необходимости. ```
### Вычислительное оборудование **Дешёвый шлюз** — синтаксис, импорт `protocol`, функциональные проверки лабораторных:
- компьютер под управлением Windows; ```bash
- Raspberry Pi — планируется для установки на ровер; python tools/quick_gate.py
- бортовой вычислитель ровера — будет выбран позднее. ```
### Программное обеспечение **Лабораторный эксперимент** — минуты, пишет результаты в `data/processed/`:
- Python 3.12; ```bash
- Anaconda; python -m experiments.lab041_session_restart_safety
- Spyder; ```
- Git;
- GNU Radio — будет установлен на следующем этапе;
- libiio и драйверы PlutoSDR — будут установлены после получения устройства.
--- ---
## 5. Предварительно рассматриваемые диапазоны ## 8. Структура репозитория
В рамках проекта рассматриваются:
- 27 МГц;
- 50 МГц;
- 144 МГц;
- другие разрешённые для лабораторных испытаний частоты ниже 350 МГц.
Конкретный диапазон будет выбран после анализа:
- доступной полосы;
- требований законодательства;
- размеров антенны;
- потерь распространения;
- уровня внешних помех;
- возможностей выходного радиочастотного тракта;
- допустимой мощности передачи.
Передача по эфиру должна выполняться только на разрешённых частотах и с соблюдением допустимой мощности. Первые опыты следует проводить через аттенюатор, эквивалент нагрузки или в экранированной лабораторной конфигурации.
---
## 6. Основные этапы проекта
### Этап 0. Подготовка среды
- создание репозитория;
- настройка Git;
- настройка Python и Spyder;
- подготовка структуры каталогов;
- ведение документации.
### Этап 1. Пакетный протокол
- структура пакета;
- типы сообщений;
- порядковый номер пакета;
- длина данных;
- CRC;
- кодирование и декодирование.
### Этап 2. Виртуальный канал
- передача пакетов между Python-программами;
- имитация потерь;
- имитация повреждения битов;
- измерение числа ошибочных пакетов.
### Этап 3. Передача файлов
- разбиение файла на фрагменты;
- нумерация фрагментов;
- подтверждение приёма;
- повторная передача;
- сборка исходного файла.
### Этап 4. Передача изображений
- загрузка JPEG;
- разбиение JPEG на пакеты;
- передача через виртуальный канал;
- восстановление изображения;
- обработка потерянных фрагментов.
### Этап 5. Физический уровень
- BPSK;
- QPSK;
- формирование символов;
- IQ-сэмплы;
- синхронизация;
- фильтрация;
- оценка BER и PER.
### Этап 6. PlutoSDR
- подключение устройства;
- передача несущей;
- передача тестовой последовательности;
- передача цифрового пакета;
- приём сигнала RTL-SDR или вторым SDR.
### Этап 7. Радиоканал передачи изображений
- передача JPEG через SDR;
- измерение времени доставки;
- испытания при различных уровнях сигнала;
- испытания при наличии помех;
- подбор скорости и модуляции.
### Этап 8. Полевые испытания
- испытания на малой мощности;
- испытания на малой дистанции;
- постепенное увеличение расстояния;
- испытания с ретранслятором;
- испытания на наземном ровере.
---
## 7. Структура репозитория
```text ```text
SDR_Rover SDR_Rover
├── protocol/ реализация протокола и радиотракта
├── README.md ├── experiments/ лабораторные Lab001Lab041
├── docs ├── tests/ быстрые автоматические проверки
├── protocol ├── tools/ вспомогательные программы и шлюз
├── rover ├── docs/ технические задания и исследования
├── ground_station ├── data/ исходные данные и результаты
├── gnuradio ├── rover/ пока пусто
├── tests ├── ground_station/ пока пусто
└── tools └── gnuradio/ пока пусто
``` ```
### `docs`
Документация, лабораторные работы, схемы и отчёты.
### `protocol` ### `protocol`
Реализация пакетного протокола: Ядро системы. Пакет с CRC32, фрагментация изображений, кадр канала, исправление стираний, приоритеты, аварийная логика, сеансы связи, примитивы BPSK-радиотракта.
- структура пакета; ### `experiments`
- CRC;
- кодирование;
- декодирование;
- типы сообщений.
### `rover` Лабораторные работы. Это исследовательские программы: они моделируют канал, выполняют сотни повторов, строят CSV, графики и отчёты. **Быстрыми тестами они не являются.** При импорте создают каталоги и пишут файлы, поэтому импортировать их не следует — для повторного использования кода служит `protocol/`.
Программы, которые будут работать на борту ровера:
- получение изображения;
- сжатие JPEG;
- передача телеметрии;
- формирование радиопакетов.
### `ground_station`
Программы наземной станции:
- приём пакетов;
- сборка изображений;
- отображение телеметрии;
- управление передачей.
### `gnuradio`
Схемы GNU Radio Companion:
- передатчик;
- приёмник;
- BPSK-модем;
- QPSK-модем;
- тестовые генераторы.
### `tests` ### `tests`
Автоматические и лабораторные тесты. Настоящие быстрые проверки `protocol/`. Выполняются за доли секунды, оборудования не требуют, запускаются через `pytest`.
### `tools` ### `rover`, `ground_station`, `gnuradio`
Вспомогательные программы: Каталоги созданы под будущую прикладную часть и пока пусты. Бортовая программа ровера, программа наземной станции и схемы GNU Radio появятся после того, как радиоканал заработает в эфире.
- анализ пакетов;
- генераторы тестовых данных;
- построение графиков;
- анализ журналов.
--- ---
## 8. Принципы разработки ## 9. Данные
В проекте применяются следующие правила: - `data/raw` — исходные данные. Крупные записи отсчётов и видео в репозиторий не помещаются, исходные изображения лабораторных хранятся.
- `data/processed` — результаты лабораторных: CSV, отчёты и графики.
**Ограничение воспроизводимости.** Исходное видео `data/raw/lab026_rover_source.mp4` (около 7,8 МБ) в репозитории не хранится. Без него Lab026 и Lab027 не запускаются, файл нужно получить отдельно.
---
## 10. Принципы разработки
1. Каждый новый термин сначала объясняется, затем используется. 1. Каждый новый термин сначала объясняется, затем используется.
2. Каждый этап должен завершаться работающим результатом. 2. Каждый этап завершается работающим результатом.
3. Радиоканал и пакетный протокол разрабатываются отдельно. 3. Радиоканал и пакетный протокол разрабатываются отдельно.
4. Код проверяется автоматическими тестами. 4. Код проверяется автоматическими тестами.
5. Все существенные решения фиксируются в документации. 5. Все существенные решения фиксируются в журнале.
6. Сложность увеличивается постепенно. 6. Сложность увеличивается постепенно.
7. Испытания по эфиру начинаются только после проверки через виртуальный канал. 7. Испытания по эфиру начинаются только после проверки через модель.
8. Передатчик сначала проверяется через аттенюатор или эквивалент нагрузки. 8. Передатчик сначала проверяется через аттенюатор или эквивалент нагрузки.
9. **Каждое число в отчёте должно вычисляться из измерений текущего запуска.** Перенесённые из других лабораторных величины сопровождаются указанием источника. Вписанные вручную результаты недопустимы.
--- Девятое правило добавлено после аудита достоверности, см. Запись 017 журнала.
## 9. Текущий статус
Выполнено:
- установлен Python;
- установлена Anaconda;
- выбран Spyder;
- установлен Git;
- создан локальный Git-репозиторий;
- создана базовая структура каталогов.
Следующая задача:
> Создать первый Python-модуль пакетного протокола и передать сообщение через виртуальный канал без SDR-оборудования.
---
## 10. Ближайший контрольный результат
Первая рабочая версия должна выполнять следующий цикл:
```text
Текстовое сообщение
Преобразование в байты
Формирование пакета
Добавление CRC
Имитация радиоканала
Проверка CRC
Восстановление сообщения
```
Первое тестовое сообщение:
```text
HELLO SDR
```
--- ---

View File

@@ -324,7 +324,7 @@ Lab041 — сеансы связи, безопасный запуск и защ
Созданные файлы Созданные файлы
- protocol/control_messages.py - protocol/control_messages.py
- protocol/session_state.py - protocol/session_state.py
- tests/lab041_session_restart_safety.py - experiments/lab041_session_restart_safety.py
- data/processed/lab041/lab041_summary.csv - data/processed/lab041/lab041_summary.csv
- data/processed/lab041/lab041_session_metrics.csv - data/processed/lab041/lab041_session_metrics.csv
- data/processed/lab041/lab041_rejection_metrics.csv - data/processed/lab041/lab041_rejection_metrics.csv

View File

@@ -2,13 +2,10 @@
from __future__ import annotations from __future__ import annotations
import ast
import csv import csv
from dataclasses import asdict, dataclass from dataclasses import asdict, dataclass
from enum import IntEnum from enum import IntEnum
import inspect
from pathlib import Path from pathlib import Path
import re
from typing import Iterable from typing import Iterable
import cv2 import cv2
@@ -1486,12 +1483,11 @@ def validate_outputs(
assert not any(path.suffix.lower() in forbidden for path in actual) assert not any(path.suffix.lower() in forbidden for path in actual)
assert not any(path.name == "__pycache__" for path in OUTPUT_DIRECTORY.rglob("*")) assert not any(path.name == "__pycache__" for path in OUTPUT_DIRECTORY.rglob("*"))
source = inspect.getsource(save_plots) # Прежде здесь лабораторная разбирала собственный исходный код, чтобы
tree = ast.parse(source) # убедиться, что подписи на графиках русские. Проверка снята: она
for node in ast.walk(tree): # относится к оформлению, а не к корректности модели, и превращала
if isinstance(node, ast.Call) and isinstance(node.func, ast.Attribute) and node.func.attr in {"set_title", "set_xlabel", "set_ylabel"}: # эксперимент в анализатор своего же текста. Подписи видны на готовых
if node.args and isinstance(node.args[0], ast.Constant) and isinstance(node.args[0].value, str): # PNG и проверяются при просмотре результатов.
assert re.search("[А-Яа-яЁё]", node.args[0].value)
def main() -> None: def main() -> None:

20
requirements-hardware.txt Normal file
View File

@@ -0,0 +1,20 @@
# SDR Rover Link — аппаратное окружение.
#
# Нужно только для лабораторных, работающих с PlutoSDR:
# Lab024a, Lab024b, Lab025 и всё, начиная с Lab042.
#
# Устанавливается поверх расчётного окружения:
# python -m pip install -r requirements.txt
# python -m pip install -r requirements-hardware.txt
#
# Проверено 10 августа 2026 года на устройстве
# Analog Devices PlutoSDR Rev.C (Z7010-AD9361), прошивка v0.32,
# подключение по USB как RNDIS-адаптер, адрес ip:192.168.2.1.
#
# Замечание по диагностике: наличие связи с устройством проверяется
# только успешным подключением через iio.Context. Команда ping и проверка
# открытых портов недостоверны — при активном VPN трафик уходит в туннель
# и создаёт видимость доступности несуществующего адреса.
pyadi-iio==0.0.21
pylibiio==0.25

21
requirements.txt Normal file
View File

@@ -0,0 +1,21 @@
# SDR Rover Link — расчётное окружение.
#
# Достаточно для запуска быстрых проверок (pytest), всех расчётных
# лабораторных и построения графиков. Оборудование не требуется:
# проект поднимается на компьютере без SDR.
#
# Установка:
# python -m pip install -r requirements.txt
#
# Версии зафиксированы по фактически проверенному окружению
# от 10 августа 2026 года, Python 3.13.1.
#
# Аппаратные лабораторные (Lab024, Lab025, Lab042 и далее) требуют
# дополнительно requirements-hardware.txt.
numpy==2.2.6
scipy==1.18.0
matplotlib==3.11.1
opencv-python==4.12.0
Pillow==12.0.0
pytest==9.1.1