Compare commits
40 Commits
35cb25fccc
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f0fa7e8a46 | ||
|
|
fa2e473c6d | ||
|
|
fce14f038e | ||
|
|
13f183f7c7 | ||
|
|
a37ad1f7b3 | ||
|
|
46b10b1243 | ||
|
|
0ae04ae4a8 | ||
|
|
92289bdf7c | ||
|
|
2da80d0908 | ||
|
|
c486039053 | ||
|
|
c9569164e0 | ||
|
|
1e4adc0a98 | ||
|
|
2a7a380875 | ||
|
|
49c7009ca5 | ||
|
|
9f7387ec2c | ||
|
|
923e6bec78 | ||
|
|
3d14c75365 | ||
|
|
28227e4228 | ||
|
|
7d122b53ed | ||
|
|
e18200225b | ||
|
|
f26d7d74ef | ||
|
|
88addff5b6 | ||
|
|
b3ebe1637f | ||
|
|
23cfdf581b | ||
|
|
50e45ca611 | ||
|
|
3e0ef5666e | ||
|
|
22c2eeab8c | ||
|
|
b63e36abdb | ||
|
|
21751f41dd | ||
|
|
3dbb7afa83 | ||
|
|
2ac1571c40 | ||
|
|
edab87b5d2 | ||
|
|
f8575f4de3 | ||
|
|
a2dd58a44b | ||
|
|
04ce66fdfe | ||
|
|
78258b5355 | ||
|
|
6d49036066 | ||
|
|
557b082f2b | ||
|
|
f3a11b29b3 | ||
|
|
1ff04b12b9 |
73
.claude/agents/adversary.md
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
---
|
||||||
|
name: adversary
|
||||||
|
description: Ищет состояния, в которых протокол ровера ведёт себя небезопасно — потери связи, перезапуски, гонки, старые и поддельные пакеты. Вызывать для модулей, связанных с управлением, аварийной остановкой, сеансами и сбросом.
|
||||||
|
tools: Read, Grep, Glob, Bash
|
||||||
|
model: sonnet
|
||||||
|
---
|
||||||
|
|
||||||
|
Ты ищешь способы довести протокол SDR Rover Link до небезопасного состояния.
|
||||||
|
|
||||||
|
Ровер — физическая машина массой в сотни килограммов, движущаяся со скоростью
|
||||||
|
до 25 км/ч по радиоканалу с потерями. Небезопасное состояние — это не «некрасивый
|
||||||
|
код». Это состояние, в котором ровер едет, когда ехать не должен, или не тормозит,
|
||||||
|
когда должен.
|
||||||
|
|
||||||
|
## Ты не занимаешься ревью кода
|
||||||
|
|
||||||
|
Обычные замечания по качеству — не твоя работа, ими занимается `verifier`.
|
||||||
|
Ты работаешь по брифу на атаку. Если брифа в задаче нет, составь его сам
|
||||||
|
из списка ниже и явно напиши, какие пункты взял.
|
||||||
|
|
||||||
|
## Базовый бриф на атаку
|
||||||
|
|
||||||
|
**Потери и задержки**
|
||||||
|
- Полная потеря аварийной команды: ни один экземпляр не дошёл.
|
||||||
|
- Потеря подтверждения при дошедшей команде.
|
||||||
|
- Пакет, дошедший после того, как состояние уже сменилось.
|
||||||
|
- Задержка, превышающая период управления, но меньше порога failsafe.
|
||||||
|
|
||||||
|
**Перезапуски и сеансы**
|
||||||
|
- Перезапуск ровера с сохранённым аварийным намерением станции.
|
||||||
|
- Перезапуск станции при живом сеансе ровера.
|
||||||
|
- Пакеты предыдущего сеанса с валидной контрольной суммой.
|
||||||
|
- Идентификаторы сеанса, совпавшие случайно после перезапуска.
|
||||||
|
|
||||||
|
**Границы и переполнения**
|
||||||
|
- Разность номеров последовательности ровно 2^31 — неоднозначность направления.
|
||||||
|
- Переполнение счётчика с переходом через ноль.
|
||||||
|
- Нулевая, отрицательная и максимальная скорость.
|
||||||
|
- Порог failsafe, совпавший с периодом управления с точностью до тика.
|
||||||
|
|
||||||
|
**Совмещение**
|
||||||
|
- Два аварийных сценария одновременно: watchdog и явная аварийная команда.
|
||||||
|
- Запрос сброса, пришедший в момент торможения.
|
||||||
|
- Разрешение движения, пришедшее одновременно с потерей связи.
|
||||||
|
|
||||||
|
**Намеренная подделка**
|
||||||
|
- Повтор перехваченного валидного пакета.
|
||||||
|
- Подмена поля при сохранении корректной контрольной суммы.
|
||||||
|
|
||||||
|
## Правило доказательства
|
||||||
|
|
||||||
|
Сценарий засчитывается, только если ты его **воспроизвёл кодом**. Напиши короткий
|
||||||
|
скрипт во временной папке, дёрни модуль из `protocol/` напрямую, покажи вывод.
|
||||||
|
Ненаписанный сценарий — это фантазия, и её место в отдельном разделе «не проверено».
|
||||||
|
|
||||||
|
## Формат находки
|
||||||
|
|
||||||
|
Сценарий: название атаки
|
||||||
|
Шаги: последовательность состояний
|
||||||
|
Итог: что делает ровер и почему это опасно
|
||||||
|
Скрипт: команда воспроизведения и её вывод
|
||||||
|
Серьёзность: движение при запрете / отсутствие торможения / некорректное состояние
|
||||||
|
|
||||||
|
## Чего не делать
|
||||||
|
|
||||||
|
- Не предлагай исправления. Твоя работа — найти, чинит другой.
|
||||||
|
- Не изобретай угрозы вне модели: физический доступ к роверу, глушение всего
|
||||||
|
диапазона, компрометация наземной станции — вне области.
|
||||||
|
- Не растягивай отчёт. Три воспроизведённых сценария лучше пятнадцати описанных.
|
||||||
|
|
||||||
|
## Итог
|
||||||
|
|
||||||
|
Заверши отчёт строкой: `АТАКА: N воспроизведено, M не проверено`.
|
||||||
58
.claude/agents/verifier.md
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
---
|
||||||
|
name: verifier
|
||||||
|
description: Независимая проверка готовой работы по лабе или модулю protocol — запускает код, пересчитывает числа вторым способом, оформляет находки как воспроизводимые сценарии отказа. Вызывать после того, как реализация написана.
|
||||||
|
tools: Read, Grep, Glob, Bash
|
||||||
|
model: sonnet
|
||||||
|
---
|
||||||
|
|
||||||
|
Ты проверяешь чужую работу в проекте SDR Rover Link: учебно-исследовательский
|
||||||
|
цифровой радиоканал для наземного ровера. Python, модули протокола в `protocol/`,
|
||||||
|
лабораторные работы в `experiments/labNNN_*.py`, журнал проекта в `PROJECT_LOG.md`.
|
||||||
|
|
||||||
|
Ты не автор кода. Твоя ценность именно в том, что ты не участвовал в его написании.
|
||||||
|
|
||||||
|
## Порядок работы
|
||||||
|
|
||||||
|
1. **Сначала прочитай требование из первоисточника** — из `README.md`, из `PROJECT_LOG.md`,
|
||||||
|
из постановки задачи в шапке файла лабы. Не из пересказа того, кто писал код.
|
||||||
|
Если пересказ расходится с первоисточником — это находка, и часто самая важная.
|
||||||
|
|
||||||
|
2. **Запусти сам.** Быстрая проверка: `python tools/quick_gate.py`.
|
||||||
|
Полный прогон лабы: `python experiments/labNNN_имя.py`. Не верь чужому «тесты проходят».
|
||||||
|
|
||||||
|
3. **Пересчитай ключевые числа независимым способом.** Это главный инструмент.
|
||||||
|
Симуляция BER проверяется аналитической формулой, счётчик отброшенных пакетов —
|
||||||
|
пересчётом из журнала событий, тайминг failsafe — прямым арифметическим расчётом
|
||||||
|
из периода и порога. Если второй способ дал другое число, разбирайся, какой врёт.
|
||||||
|
|
||||||
|
4. **Проверь края.** Ноль, единица, пустой вход, максимум диапазона, переполнение
|
||||||
|
счётчика последовательности, разность номеров ровно 2^31.
|
||||||
|
|
||||||
|
5. **Проверь соответствие стилю проекта.** Русские докстроки и подписи осей,
|
||||||
|
`from __future__ import annotations`, датаклассы, CSV и PNG в `data/processed`,
|
||||||
|
именование как у соседних лаб.
|
||||||
|
|
||||||
|
## Формат находки
|
||||||
|
|
||||||
|
Каждая находка — строго так:
|
||||||
|
|
||||||
|
Файл и строка
|
||||||
|
Вход: что подаём
|
||||||
|
Ожидалось: что должно быть, со ссылкой на требование
|
||||||
|
Получено: что на деле, с выводом запуска
|
||||||
|
Проверено: команда, которой это воспроизводится
|
||||||
|
|
||||||
|
Формулировки «возможно», «стоило бы рассмотреть», «может быть проблемой» запрещены.
|
||||||
|
Если не смог воспроизвести — это не находка, а гипотеза, и помечай её отдельно в конце.
|
||||||
|
|
||||||
|
## Чего не делать
|
||||||
|
|
||||||
|
- Не редактируй файлы. У тебя нет на это инструментов и не должно быть.
|
||||||
|
- Не пиши замечания по стилю кода ради объёма. Одна подтверждённая находка
|
||||||
|
ценнее десяти рассуждений.
|
||||||
|
- Если всё чисто — так и напиши: что именно ты запустил, какие числа сверил,
|
||||||
|
и что расхождений нет. Пустой честный отчёт лучше выдуманного.
|
||||||
|
|
||||||
|
## Итог
|
||||||
|
|
||||||
|
Заверши отчёт одной строкой: `ВЕРДИКТ: чисто` либо `ВЕРДИКТ: N подтверждённых находок`.
|
||||||
35
.claude/commands/check.md
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
---
|
||||||
|
description: Независимая проверка уже сделанной работы — verifier и, при необходимости, adversary
|
||||||
|
argument-hint: [что проверяем: номер лабы, модуль или «текущие изменения»]
|
||||||
|
---
|
||||||
|
|
||||||
|
Проверяем: $ARGUMENTS
|
||||||
|
|
||||||
|
Если аргумент не задан, проверяем незакоммиченные изменения — возьми их из
|
||||||
|
`git status --porcelain` и `git diff`.
|
||||||
|
|
||||||
|
## Что сделать
|
||||||
|
|
||||||
|
1. Собери фактуру: какие файлы затронуты, какая лаба или модуль за это отвечает,
|
||||||
|
какой командой прогоняется полный тест.
|
||||||
|
|
||||||
|
2. Запусти `python tools/quick_gate.py`. Если шлюз не пройден — дальше не иди,
|
||||||
|
сначала почини, агентов дёргать бессмысленно.
|
||||||
|
|
||||||
|
3. Запусти агента `verifier`. Передай ему:
|
||||||
|
- список затронутых файлов,
|
||||||
|
- команду полного прогона,
|
||||||
|
- указание брать требование из `README.md` и `PROJECT_LOG.md`, а не из твоих слов.
|
||||||
|
|
||||||
|
4. Агента `adversary` запускай **только** если затронуто что-то из списка:
|
||||||
|
управление, failsafe, аварийная остановка, сеансы, перезапуск, сброс,
|
||||||
|
подлинность сообщений. Для видео, сжатия, FEC и модуляции он бесполезен —
|
||||||
|
не трать лимит.
|
||||||
|
|
||||||
|
5. Разбери находки как арбитр: воспроизведи, отклони невоспроизводимые вслух,
|
||||||
|
почини подтверждённые.
|
||||||
|
|
||||||
|
## Отчёт пользователю
|
||||||
|
|
||||||
|
Коротко: что запускалось, что нашли, что починили, что отклонили и почему.
|
||||||
|
Отчёты агентов пользователь не видит — пересказывай сам, не отсылай к ним.
|
||||||
68
.claude/commands/lab.md
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
---
|
||||||
|
description: Полный цикл работы над лабой — аудит, план, реализация, независимая проверка
|
||||||
|
argument-hint: <номер лабы> [краткая постановка]
|
||||||
|
---
|
||||||
|
|
||||||
|
Работаем над лабой: $ARGUMENTS
|
||||||
|
|
||||||
|
Порядок обязательный. Не перескакивай через этапы и не начинай писать код,
|
||||||
|
пока пользователь не согласовал план.
|
||||||
|
|
||||||
|
## Этап 1. Аудит
|
||||||
|
|
||||||
|
Запусти агента `Explore` с запросом: что в `protocol/` уже относится к этой задаче,
|
||||||
|
какие модули придётся трогать, где есть пересечение или дублирование, как устроены
|
||||||
|
две-три ближайшие по смыслу лабы в `experiments/`.
|
||||||
|
|
||||||
|
Прочитай сам последние записи в `PROJECT_LOG.md` — там указано, чем должен
|
||||||
|
заниматься следующий этап.
|
||||||
|
|
||||||
|
Выдай карту: что есть, чего нет, что придётся изменить. Только карта, без решений.
|
||||||
|
|
||||||
|
## Этап 2. План
|
||||||
|
|
||||||
|
На основе карты предложи план: какие модули создаются, какие меняются, что именно
|
||||||
|
измеряет лаба, какие CSV и PNG появятся в `data/processed`, какие функциональные
|
||||||
|
проверки будут в `run_functional_tests`.
|
||||||
|
|
||||||
|
**Остановись и дождись согласования.** Это прямое требование пользователя.
|
||||||
|
|
||||||
|
## Этап 3. Реализация
|
||||||
|
|
||||||
|
Пишешь ты, в этом же треде. Отдельного агента-кодера не запускай — у тебя уже есть
|
||||||
|
весь контекст, а он начнёт с нуля и потратит лимит впустую.
|
||||||
|
|
||||||
|
Держи стиль проекта: русские докстроки и подписи осей, `from __future__ import annotations`,
|
||||||
|
датаклассы для метрик, CSV и PNG в `data/processed`, `run_functional_tests` и `main`
|
||||||
|
как в соседних лабах.
|
||||||
|
|
||||||
|
После каждой заметной правки: `python tools/quick_gate.py`.
|
||||||
|
|
||||||
|
## Этап 4. Проверка
|
||||||
|
|
||||||
|
Запусти агента `verifier`. В задании передай:
|
||||||
|
- номер и постановку лабы своими словами,
|
||||||
|
- список созданных и изменённых файлов,
|
||||||
|
- команду полного прогона,
|
||||||
|
- прямое указание читать требование из `README.md` и `PROJECT_LOG.md`, а не из твоего пересказа.
|
||||||
|
|
||||||
|
Если лаба касается управления, аварийной остановки, сеансов, сброса или подлинности
|
||||||
|
сообщений — параллельно запусти `adversary` с брифом на атаку под эту тему.
|
||||||
|
|
||||||
|
Оба агента read-only. Правки вносишь ты.
|
||||||
|
|
||||||
|
## Этап 5. Разбор находок
|
||||||
|
|
||||||
|
Ты арбитр. По каждой находке:
|
||||||
|
- воспроизведи её сам, прежде чем чинить;
|
||||||
|
- невоспроизводимую отклони и скажи об этом вслух;
|
||||||
|
- подтверждённую почини и перезапусти проверку.
|
||||||
|
|
||||||
|
Не чини всё подряд из вежливости к агенту.
|
||||||
|
|
||||||
|
## Этап 6. Завершение
|
||||||
|
|
||||||
|
Полный прогон лабы, затем `python tools/quick_gate.py`.
|
||||||
|
Запись в `PROJECT_LOG.md` в том же формате, что предыдущие записи.
|
||||||
|
Коммит в стиле проекта: `LabNNN: краткое описание на английском`.
|
||||||
|
Коммить только после явного согласия пользователя.
|
||||||
59
.claude/hooks/quick_gate_hook.py
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
"""
|
||||||
|
Обёртка быстрого шлюза для хука PostToolUse.
|
||||||
|
|
||||||
|
Читает JSON события со стандартного ввода. Если правка затронула файл Python
|
||||||
|
в protocol или tests, запускает tools/quick_gate.py.
|
||||||
|
|
||||||
|
Коды возврата:
|
||||||
|
0 — правка не по теме либо шлюз пройден, вывода нет;
|
||||||
|
2 — шлюз не пройден, текст ошибки уходит в stderr и возвращается модели.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
from pathlib import Path
|
||||||
|
import re
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
|
||||||
|
PROJECT_ROOT = Path(__file__).resolve().parents[2]
|
||||||
|
WATCHED = re.compile(r"[\\/](?:protocol|experiments|tests|tools)[\\/][^\\/]+\.py$")
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> int:
|
||||||
|
try:
|
||||||
|
event = json.load(sys.stdin)
|
||||||
|
except (json.JSONDecodeError, ValueError):
|
||||||
|
return 0
|
||||||
|
|
||||||
|
tool_input = event.get("tool_input") or {}
|
||||||
|
tool_response = event.get("tool_response") or {}
|
||||||
|
file_path = tool_response.get("filePath") or tool_input.get("file_path") or ""
|
||||||
|
|
||||||
|
if not WATCHED.search(str(file_path)):
|
||||||
|
return 0
|
||||||
|
|
||||||
|
environment = dict(os.environ, PYTHONIOENCODING="utf-8")
|
||||||
|
|
||||||
|
completed = subprocess.run(
|
||||||
|
[sys.executable, str(PROJECT_ROOT / "tools" / "quick_gate.py")],
|
||||||
|
cwd=PROJECT_ROOT,
|
||||||
|
capture_output=True,
|
||||||
|
text=True,
|
||||||
|
encoding="utf-8",
|
||||||
|
errors="replace",
|
||||||
|
env=environment,
|
||||||
|
)
|
||||||
|
|
||||||
|
if completed.returncode == 0:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
output = (completed.stdout + completed.stderr).strip()
|
||||||
|
print(output, file=sys.stderr)
|
||||||
|
return 2
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
raise SystemExit(main())
|
||||||
18
.claude/settings.json
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://json.schemastore.org/claude-code-settings.json",
|
||||||
|
"hooks": {
|
||||||
|
"PostToolUse": [
|
||||||
|
{
|
||||||
|
"matcher": "Edit|Write|MultiEdit",
|
||||||
|
"hooks": [
|
||||||
|
{
|
||||||
|
"type": "command",
|
||||||
|
"command": "python .claude/hooks/quick_gate_hook.py",
|
||||||
|
"timeout": 60,
|
||||||
|
"statusMessage": "Быстрый шлюз"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
21
.gitignore
vendored
@@ -6,11 +6,14 @@
|
|||||||
# Python: скомпилированные и временные файлы
|
# Python: скомпилированные и временные файлы
|
||||||
__pycache__/
|
__pycache__/
|
||||||
*.py[cod]
|
*.py[cod]
|
||||||
|
*.pyc
|
||||||
|
*.pyo
|
||||||
*$py.class
|
*$py.class
|
||||||
|
|
||||||
# Кэш инструментов проверки и тестирования
|
# Кэш инструментов проверки и тестирования
|
||||||
.pytest_cache/
|
.pytest_cache/
|
||||||
.mypy_cache/
|
.mypy_cache/
|
||||||
|
.ruff_cache/
|
||||||
.coverage
|
.coverage
|
||||||
|
|
||||||
# Spyder
|
# Spyder
|
||||||
@@ -26,6 +29,24 @@ __pycache__/
|
|||||||
venv/
|
venv/
|
||||||
env/
|
env/
|
||||||
|
|
||||||
|
# Необработанные данные и IQ-записи.
|
||||||
|
# Правило закрывает крупные записи отсчётов и видео: они воспроизводятся
|
||||||
|
# заново и в историю не помещаются.
|
||||||
|
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
|
||||||
|
|||||||
60
.gitlab-ci.yml
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
# Непрерывная проверка SDR Rover Link.
|
||||||
|
#
|
||||||
|
# Здесь выполняются только быстрые проверки: они должны укладываться в
|
||||||
|
# секунды. Лабораторные эксперименты сюда не помещаются — они длятся
|
||||||
|
# минутами, требуют исходных данных из data/raw и в части случаев
|
||||||
|
# подключённого PlutoSDR. Их запуск остаётся ручным.
|
||||||
|
#
|
||||||
|
# Оборудование конвейеру не нужно: устанавливается только расчётное
|
||||||
|
# окружение, без pyadi-iio и libiio.
|
||||||
|
|
||||||
|
stages:
|
||||||
|
- gate
|
||||||
|
- test
|
||||||
|
- lint
|
||||||
|
|
||||||
|
default:
|
||||||
|
image: python:3.13
|
||||||
|
before_script:
|
||||||
|
- python --version
|
||||||
|
- python -m pip install --quiet --upgrade pip
|
||||||
|
- python -m pip install --quiet -r requirements.txt
|
||||||
|
cache:
|
||||||
|
key: "python-$CI_COMMIT_REF_SLUG"
|
||||||
|
paths:
|
||||||
|
- .cache/pip
|
||||||
|
|
||||||
|
variables:
|
||||||
|
PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip"
|
||||||
|
PYTHONIOENCODING: "utf-8"
|
||||||
|
|
||||||
|
# Дешёвый шлюз: синтаксис всех файлов, импорт protocol и функциональные
|
||||||
|
# проверки тех лабораторных, которым не нужны данные эксперимента.
|
||||||
|
# Выполняется первым, потому что ловит самые грубые поломки за секунду.
|
||||||
|
быстрый-шлюз:
|
||||||
|
stage: gate
|
||||||
|
script:
|
||||||
|
- python tools/quick_gate.py
|
||||||
|
|
||||||
|
# Быстрые проверки ядра протокола.
|
||||||
|
тесты-ядра:
|
||||||
|
stage: test
|
||||||
|
script:
|
||||||
|
- python -m pytest tests/ -q --junitxml=report.xml
|
||||||
|
artifacts:
|
||||||
|
when: always
|
||||||
|
reports:
|
||||||
|
junit: report.xml
|
||||||
|
expire_in: 1 week
|
||||||
|
|
||||||
|
# Проверка стиля. Пока не блокирует конвейер: в лабораторных Lab001–Lab041
|
||||||
|
# принято своеобразное оформление с переносами аргументов, и приводить их
|
||||||
|
# к единому стилю сейчас означало бы тронуть 50 файлов с зафиксированными
|
||||||
|
# результатами. Ограничение снимается, когда договоримся о правилах.
|
||||||
|
стиль:
|
||||||
|
stage: lint
|
||||||
|
allow_failure: true
|
||||||
|
before_script:
|
||||||
|
- python -m pip install --quiet ruff
|
||||||
|
script:
|
||||||
|
- ruff check protocol/ tests/ tools/
|
||||||
593
PROJECT_LOG.md
Normal file
@@ -0,0 +1,593 @@
|
|||||||
|
# Инженерный журнал SDR Rover Link
|
||||||
|
|
||||||
|
## Назначение журнала
|
||||||
|
|
||||||
|
Этот файл содержит хронологию разработки проекта SDR Rover Link.
|
||||||
|
|
||||||
|
В журнале фиксируются:
|
||||||
|
|
||||||
|
- выполненные работы;
|
||||||
|
- полученные результаты;
|
||||||
|
- обнаруженные ошибки;
|
||||||
|
- принятые технические решения;
|
||||||
|
- результаты экспериментов;
|
||||||
|
- планы следующего этапа.
|
||||||
|
|
||||||
|
Записи не следует удалять. Если решение изменилось, необходимо добавить новую запись и объяснить причину изменения.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Запись 001
|
||||||
|
|
||||||
|
## Дата
|
||||||
|
|
||||||
|
10 июля 2026 года
|
||||||
|
|
||||||
|
## Тема
|
||||||
|
|
||||||
|
Создание структуры проекта и локального Git-репозитория.
|
||||||
|
|
||||||
|
## Выполнено
|
||||||
|
|
||||||
|
1. Проверена установленная версия Git:
|
||||||
|
|
||||||
|
```text
|
||||||
|
git version 2.51.1.windows.1
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Запись 002
|
||||||
|
|
||||||
|
## Дата
|
||||||
|
|
||||||
|
27 июля 2026 года
|
||||||
|
|
||||||
|
## Тема
|
||||||
|
|
||||||
|
Завершение Lab028: пакетирование синхронного BASE + ROI.
|
||||||
|
|
||||||
|
## Выполнено
|
||||||
|
|
||||||
|
- Реализован фиксированный бинарный заголовок размером 32 байта.
|
||||||
|
- Добавлены packet CRC32 для заголовка и payload и object CRC32 для полного JPEG.
|
||||||
|
- Исследованы размеры payload 64, 128, 256, 512 и 1024 байта.
|
||||||
|
- Размер payload 512 байт принят как рабочий кандидат.
|
||||||
|
- Окончательный выбор размера пакета перенесён в Lab029.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Запись 003
|
||||||
|
|
||||||
|
## Дата
|
||||||
|
|
||||||
|
27 июля 2026 года
|
||||||
|
|
||||||
|
## Тема
|
||||||
|
|
||||||
|
Завершение Lab029: моделирование потерь и ошибок видеопакетов.
|
||||||
|
|
||||||
|
## Выполнено
|
||||||
|
|
||||||
|
- Исследованы независимые потери пакетов и независимые битовые ошибки.
|
||||||
|
- Проверены короткие, средние и длинные серии потерь по модели Gilbert–Elliott.
|
||||||
|
- Выполнено сравнение payload 256, 512 и 1024 байта.
|
||||||
|
- Подтверждены packet CRC32, изоляция соседних кадров и атомарная сборка BASE + ROI.
|
||||||
|
- Зафиксировано ограничение пакетной временной шкалы Lab029.
|
||||||
|
- Сравнение помех одинаковой физической длительности перенесено в Lab029B.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Запись 004
|
||||||
|
|
||||||
|
## Дата
|
||||||
|
|
||||||
|
27 июля 2026 года
|
||||||
|
|
||||||
|
## Тема
|
||||||
|
|
||||||
|
Завершение Lab029B: временная модель серийных потерь.
|
||||||
|
|
||||||
|
## Выполнено
|
||||||
|
|
||||||
|
- Помехи смоделированы на непрерывной временной шкале.
|
||||||
|
- Контрольная скорость передачи установлена равной 300 кбит/с.
|
||||||
|
- Исследованы средние длительности Bad 10, 50, 200 и 1000 мс.
|
||||||
|
- Payload 512 байт выбран для дальнейшей разработки.
|
||||||
|
- Payload 1024 байта оставлен резервным вариантом.
|
||||||
|
- Подтверждено, что без исправления ошибок возможны длительные прерывания видеопотока.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Запись 005
|
||||||
|
|
||||||
|
## Дата
|
||||||
|
|
||||||
|
29 июля 2026 года
|
||||||
|
|
||||||
|
## Тема
|
||||||
|
|
||||||
|
Завершение Lab030: блочное исправление стираний.
|
||||||
|
|
||||||
|
## Выполнено
|
||||||
|
|
||||||
|
- Реализовано блочное исправление стираний над GF(256).
|
||||||
|
- Проверены режимы без исправления, 8+1, 8+2 и 8+4.
|
||||||
|
- Режим 8+2 выбран основным рабочим режимом.
|
||||||
|
- Режим 8+4 оставлен контрольным.
|
||||||
|
- Подтверждено, что без перемежения продолжительные серии потерь не исправляются.
|
||||||
|
- Следующая лабораторная посвящена перемежению пакетов.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Запись 006
|
||||||
|
|
||||||
|
## Дата
|
||||||
|
|
||||||
|
29 июля 2026 года
|
||||||
|
|
||||||
|
## Тема
|
||||||
|
|
||||||
|
Завершение Lab031: перемежение блоков исправления ошибок.
|
||||||
|
|
||||||
|
## Выполнено
|
||||||
|
|
||||||
|
- Исследовано перемежение блоков исправления ошибок.
|
||||||
|
- Проверены глубины D=1, 2, 4 и 8.
|
||||||
|
- Подтверждено, что глубокое перемежение повышает задержку сильнее, чем полезность для операторского видеопотока.
|
||||||
|
- D=1 оставлен основным режимом.
|
||||||
|
- D=2 сохранён как резервный вариант.
|
||||||
|
- D=4 и D=8 исключены из основной линии разработки.
|
||||||
|
- Следующая лабораторная подбирает размер блока и количество проверочных пакетов.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Запись 007
|
||||||
|
|
||||||
|
## Дата
|
||||||
|
|
||||||
|
29 июля 2026 года
|
||||||
|
|
||||||
|
## Тема
|
||||||
|
|
||||||
|
Завершение Lab032: параметры блочного исправления потерянных пакетов.
|
||||||
|
|
||||||
|
## Выполнено
|
||||||
|
|
||||||
|
- Исследованы параметры блочного исправления потерянных пакетов.
|
||||||
|
- Сравнивались режимы без исправления, 4+1, 8+2, 12+3, 6+2, 8+3, 4+2 и 8+4.
|
||||||
|
- Режим 12+3 выбран основным.
|
||||||
|
- Его транспортный поток составляет 226,951 кбит/с.
|
||||||
|
- Запас до контрольных 300 кбит/с составляет 73,049 кбит/с.
|
||||||
|
- Режим 8+4 оставлен усиленным экспериментальным вариантом.
|
||||||
|
- Режим 8+3 не принят из-за отсутствия устойчивого преимущества.
|
||||||
|
- Подтверждено, что продолжительные помехи нельзя компенсировать только увеличением числа проверочных пакетов.
|
||||||
|
- Следующий этап посвящён совместной передаче команд, телеметрии и видео с приоритетным обслуживанием.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Запись 008
|
||||||
|
|
||||||
|
## Дата
|
||||||
|
|
||||||
|
3 августа 2026 года
|
||||||
|
|
||||||
|
## Тема
|
||||||
|
|
||||||
|
Завершение Lab033: общий пакет канала и приоритетное обслуживание.
|
||||||
|
|
||||||
|
## Выполнено
|
||||||
|
|
||||||
|
- Добавлен общий 32-байтный заголовок канала для команд, телеметрии и видео.
|
||||||
|
- Общая предложенная нагрузка составляет 258,214 кбит/с.
|
||||||
|
- Подтверждено, что FIFO не обеспечивает требуемую задержку команд.
|
||||||
|
- Выбран строгий приоритет с заменой устаревших состояний.
|
||||||
|
- Аварийная команда имеет наивысший приоритет.
|
||||||
|
- Скорость 260 кбит/с практически полностью загружена.
|
||||||
|
- При 230 кбит/с видеоданные накапливаются и устаревают.
|
||||||
|
- Итоговое восстановление всех кадров после освобождения очереди не означает работу видео в реальном времени.
|
||||||
|
- Расчёты и графики выполнены с Matplotlib 3.11.1.
|
||||||
|
- Следующий этап посвящён отбрасыванию устаревших видеокадров.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Запись 009
|
||||||
|
|
||||||
|
## Дата
|
||||||
|
|
||||||
|
3 августа 2026 года
|
||||||
|
|
||||||
|
## Тема
|
||||||
|
|
||||||
|
Завершение Lab034: реактивное отбрасывание устаревших видеокадров.
|
||||||
|
|
||||||
|
## Выполнено
|
||||||
|
|
||||||
|
- Сравнены непрерывные FEC-блоки и блоки, выровненные по составным кадрам.
|
||||||
|
- Выравнивание увеличивает видеопоток на 5,975 кбит/с, или на 2,633%.
|
||||||
|
- При 300 кбит/с удаление кадров не требуется.
|
||||||
|
- При 260 кбит/с ограничения 1000 и 1500 мс не срабатывают, а ограничение 500 мс уже чрезмерно.
|
||||||
|
- При 230 кбит/с реактивное удаление устаревших кадров уменьшает очередь, но резко снижает частоту обновления.
|
||||||
|
- Ограничение 500 мс оставляет только 3 из 63 кадров.
|
||||||
|
- Ограничение 1500 мс оставляет 27 из 63 кадров.
|
||||||
|
- Подтверждено, что короткая очередь сама по себе не означает свежее изображение.
|
||||||
|
- Текущая реактивная политика не принята.
|
||||||
|
- Следующий этап посвящён упреждающему допуску кадров и обслуживанию видео целыми кадрами.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Запись 010
|
||||||
|
|
||||||
|
## Дата
|
||||||
|
|
||||||
|
3 августа 2026 года
|
||||||
|
|
||||||
|
## Тема
|
||||||
|
|
||||||
|
Завершение Lab035: упреждающий допуск и обслуживание видео целыми составными кадрами.
|
||||||
|
|
||||||
|
## Выполнено
|
||||||
|
|
||||||
|
- Lab035 исследует упреждающий допуск и обслуживание видео целыми составными кадрами.
|
||||||
|
- Начатый кадр всегда передаётся полностью.
|
||||||
|
- Команды и телеметрия могут передаваться между его пакетами.
|
||||||
|
- Реактивное удаление Lab034 окончательно не принято.
|
||||||
|
- Основная политика — хранение только самого свежего не начатого кадра.
|
||||||
|
- При 230 кбит/с опубликовано 56 из 63 кадров с частотой около 2,6 кадра/с.
|
||||||
|
- Бесполезно переданных видеобайтов нет.
|
||||||
|
- Очередь из двух кадров увеличивает возраст изображения.
|
||||||
|
- Прогноз 1000 мс не дал преимущества над более простой политикой.
|
||||||
|
- Прогноз 500 мс чрезмерно снижает частоту обновления.
|
||||||
|
- Следующая лабораторная проверяет долговременную устойчивость и изменение пропускной способности канала.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Запись 011
|
||||||
|
|
||||||
|
## Дата
|
||||||
|
|
||||||
|
3 августа 2026 года
|
||||||
|
|
||||||
|
## Тема
|
||||||
|
|
||||||
|
Завершение Lab036: долговременная устойчивость видеопланировщика при изменении пропускной способности.
|
||||||
|
|
||||||
|
## Выполнено
|
||||||
|
|
||||||
|
- Lab036 проверяет видеопланировщик на протяжении 600 секунд.
|
||||||
|
- Расчётный рост очереди без удаления совпал с моделью.
|
||||||
|
- При 230 кбит/с очередь без удаления выросла до 4139 пакетов.
|
||||||
|
- 95-й процентиль возраста изображения достиг 74,6 секунды.
|
||||||
|
- Плавное поступление сильно устаревших кадров непригодно для управления.
|
||||||
|
- Политика хранения только самого свежего не начатого кадра ограничивает очередь.
|
||||||
|
- При 230 кбит/с она обеспечила около 2,615 кадра/с.
|
||||||
|
- После восстановления скорости возраст изображения снизился ниже 500 мс за 0,077 секунды.
|
||||||
|
- Политика двух ожидающих кадров оставлена резервной.
|
||||||
|
- Следующая лабораторная объединяет планировщик с моделью ошибок радиоканала и защитой команд управления.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Запись 012
|
||||||
|
|
||||||
|
## Дата
|
||||||
|
|
||||||
|
4 августа 2026 года
|
||||||
|
|
||||||
|
## Тема
|
||||||
|
|
||||||
|
Завершение Lab037: полный транспорт с серийными потерями и повторением критических команд.
|
||||||
|
|
||||||
|
## Выполнено
|
||||||
|
|
||||||
|
- Lab037 объединяет видеопоток, обычные и аварийные команды, телеметрию и временные серийные потери пакетов.
|
||||||
|
- Близкие повторные копии команд часто попадают в один и тот же интервал помехи.
|
||||||
|
- Повторение Lab037 лишь умеренно уменьшило долю недоставленных управляющих состояний.
|
||||||
|
- Максимальный промежуток без свежей команды остался более одной секунды.
|
||||||
|
- Своевременная доставка аварийной команды по радиоканалу не гарантируется.
|
||||||
|
- Для безопасного поведения при потере связи требуется локальный сторожевой таймер на ровере.
|
||||||
|
- Следующий этап исследует сторожевой таймер, временно разнесённую аварийную команду и подтверждение получения.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Запись 013
|
||||||
|
|
||||||
|
## Дата
|
||||||
|
|
||||||
|
4 августа 2026 года
|
||||||
|
|
||||||
|
## Тема
|
||||||
|
|
||||||
|
Завершение Lab038: локальный сторожевой таймер и подтверждаемая аварийная команда.
|
||||||
|
|
||||||
|
## Выполнено
|
||||||
|
|
||||||
|
- Lab038 исследует локальный сторожевой таймер, разнесённую аварийную команду и подтверждение получения.
|
||||||
|
- Три инварианта безопасности не нарушены ни разу.
|
||||||
|
- Подтверждение не является условием выполнения аварийной остановки.
|
||||||
|
- Режим с подтверждением сохранил итоговую доставку аварийной команды 99,694%.
|
||||||
|
- Среднее число аварийных копий уменьшилось с 11 до 1,071.
|
||||||
|
- Дополнительная нагрузка подтверждаемого режима составляет около 0,0093 кбит/с.
|
||||||
|
- Дополнительное повторение обычных команд не принято как основной режим.
|
||||||
|
- Порог 100 мс вызывает слишком частые безопасные остановки.
|
||||||
|
- Порог 500 мс допускает слишком большой путь до реакции.
|
||||||
|
- Для следующей проверки принята двухступенчатая логика: предварительная реакция после 150 мс и обязательная остановка после 250 мс.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Запись 014
|
||||||
|
|
||||||
|
## Дата
|
||||||
|
|
||||||
|
5 августа 2026 года
|
||||||
|
|
||||||
|
## Тема
|
||||||
|
|
||||||
|
Завершение Lab039: двухступенчатая безопасная реакция и оценка пути до остановки.
|
||||||
|
|
||||||
|
## Выполнено
|
||||||
|
|
||||||
|
- Lab039 реализует состояния NORMAL, STAGE1_DECELERATION, STAGE2_BRAKING и EMERGENCY_LATCHED.
|
||||||
|
- Используется точное событийное интегрирование движения.
|
||||||
|
- Аналитические значения совпали с моделью с нулевой ошибкой.
|
||||||
|
- Максимальный полный путь составил 13,9642 м.
|
||||||
|
- При 25 км/ч и номинальном профиле политика 150/250 мс дала полный путь около 9,5388 м.
|
||||||
|
- Основную часть пути составляет торможение после реакции.
|
||||||
|
- Пара 150/250 мс сохраняется как предварительный кандидат, но окончательно не утверждается.
|
||||||
|
- Фактические замедления должны быть измерены на реальном ровере.
|
||||||
|
- Локальный сторожевой таймер сохранил безопасную реакцию в опытах, где аварийная команда не была доставлена.
|
||||||
|
- Следующий этап исследует постоянное аварийное намерение наземной станции и безопасное разрешение повторного движения.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Запись 015
|
||||||
|
|
||||||
|
## Дата
|
||||||
|
|
||||||
|
5 августа 2026 года
|
||||||
|
|
||||||
|
## Тема
|
||||||
|
|
||||||
|
Завершение Lab040: постоянное аварийное намерение и безопасное повторное разрешение движения.
|
||||||
|
|
||||||
|
## Выполнено
|
||||||
|
|
||||||
|
- Lab040 реализует постоянное аварийное намерение наземной станции.
|
||||||
|
- Ограниченное окно повторения 500 мс признано небезопасным.
|
||||||
|
- При полностью потерянной аварийной передаче ограниченный режим допускал последующее возобновление движения.
|
||||||
|
- В одном из тяжёлых условий путь после такого восстановления достигал в среднем около 490 м при 25 км/ч.
|
||||||
|
- Постоянное аварийное намерение исключило положительные задания скорости и небезопасные возобновления движения.
|
||||||
|
- Подтверждение аварийной команды не снимает аварийное намерение.
|
||||||
|
- Сброс принимается только после остановки, при свежей связи и корректных идентификаторах.
|
||||||
|
- Подтверждение сброса не восстанавливает старую команду движения.
|
||||||
|
- Движение требует новой явной команды оператора.
|
||||||
|
- Следующий этап посвящён сеансам связи, перезапускам устройств и защите от пакетов предыдущего сеанса.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Запись 016
|
||||||
|
|
||||||
|
## Дата
|
||||||
|
|
||||||
|
5 августа 2026 года
|
||||||
|
|
||||||
|
## Тема
|
||||||
|
|
||||||
|
Завершение Lab041: сеансы связи, безопасный запуск и защита от пакетов предыдущего сеанса.
|
||||||
|
|
||||||
|
## Выполнено
|
||||||
|
|
||||||
|
- Lab041 вводит идентификаторы сеанса станции, запуска ровера и периода управления.
|
||||||
|
- Одного номера сообщения недостаточно после перезапуска.
|
||||||
|
- В основном режиме все 2807 введённых старых пакетов были отклонены.
|
||||||
|
- Ошибочно принятых старых пакетов не было.
|
||||||
|
- Исходный режим без идентификаторов принял все старые пакеты.
|
||||||
|
- После перезапуска движение запрещено до нового согласования, подтверждения разрешения и новой команды оператора.
|
||||||
|
- Аварийное намерение наземной станции сохраняется после перезапуска.
|
||||||
|
- Неоднозначная разность номеров 2^31 отклоняется.
|
||||||
|
- Следующий этап посвящён криптографической проверке подлинности управляющих сообщений и защите от намеренной подделки.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Запись 017
|
||||||
|
|
||||||
|
## Дата
|
||||||
|
|
||||||
|
7 августа 2026 года
|
||||||
|
|
||||||
|
## Тема
|
||||||
|
|
||||||
|
Аудит достоверности Lab041 и удаление показателей, не выводимых из модели. Начало этапа стабилизации после Lab041.
|
||||||
|
|
||||||
|
## Причина записи
|
||||||
|
|
||||||
|
Запись 016 не отменяется, но нуждается в уточнении. Машинный аудит репозитория показал, что часть числовых результатов Lab041 не выводилась ни из модели этой лабораторной, ни из указанного источника. Согласно правилу журнала прежняя запись сохранена, а изменение зафиксировано отдельно.
|
||||||
|
|
||||||
|
## Что обнаружено
|
||||||
|
|
||||||
|
- В функции `simulate_trial` доли публикации видео, доставки телеметрии и доставки управления, а также базовая длина очереди задавались вписанными таблицами, а не вычислялись.
|
||||||
|
- Значение доли видео 0,910 для канала 260 кбит/с не соответствовало заявленному источнику: Lab040 даёт 0,9603, Lab037 — разброс 0,9026...0,9174.
|
||||||
|
- Базовая длина очереди 31 для того же канала не соответствовала Lab040, где получено 36...38 пакетов.
|
||||||
|
- Коэффициенты влияния нагрузки 0,15, 0,10 и 0,05 не выводились ни из какой модели.
|
||||||
|
- Параметры торможения были зашиты литералами `0.250` и делителем `6.0` без связи с профилем `nominal` Lab039, откуда они происходят.
|
||||||
|
- Пять из четырнадцати инвариантов безопасности не измерялись: два вычислялись выражением с умножением на ноль, один был литеральным нулём, ещё два опирались на поля, которые никогда не заполнялись. Проверка `validate_outputs` подтверждала эти константы, то есть проверяла тождество.
|
||||||
|
- Формулировка «все 2807 введённых старых пакетов были отклонены» описывает перебор таблицы сценариев, а не измеренную вероятность отклонения. Число раскладывается как семь сценариев на 401 повтор.
|
||||||
|
|
||||||
|
## Выполнено
|
||||||
|
|
||||||
|
- Из Lab041 удалены четыре показателя: доли доставки видео, телеметрии и управления и максимальная длина очереди. Они относятся к Lab037 и Lab040 и в Lab041 не моделируются.
|
||||||
|
- Удалён график `lab041_traffic_impact.png`, потерявший основание. Осталось семь графиков.
|
||||||
|
- Удалены поля `negative_speed_cases` и `speed_limit_exceeded_cases`, которые никогда не вычислялись, и тождественные проверки в `validate_outputs`.
|
||||||
|
- Параметры торможения связаны с профилем `nominal` Lab039 через именованные константы `LAB039_NOMINAL_STAGE2_MPS2` и `LAB039_STAGE2_THRESHOLD_SECONDS`; горизонт незащищённого движения выделен как явно принятое допущение.
|
||||||
|
- Перенесённые величины `VIDEO_OFFERED_LOAD_KBPS` и `TELEMETRY_OFFERED_LOAD_KBPS` снабжены указанием источника: Lab038, поля `video_load_kbps` и `telemetry_load_kbps`.
|
||||||
|
- Секция инвариантов переписана: девять свойств, следующих из архитектуры, снабжены ссылками на подтверждающие функциональные проверки; пять свойств, которые матрица не может измерить, вынесены в отдельный раздел со ссылками на проверки 04, 06, 07, 10, 16 и 19.
|
||||||
|
- В отчёт добавлено разграничение того, что моделируется розыгрышем, что задано архитектурой и что не моделируется вовсе.
|
||||||
|
- Проверка 04 расширена отрицательной скоростью и границей 15 м/с, поэтому соответствующее свойство теперь подтверждается реально, а не константой.
|
||||||
|
- Оценка пути после перезапуска помечена как расчёт по замкнутой формуле, одинаковый во всех повторах, а не как результат розыгрыша.
|
||||||
|
|
||||||
|
## Результат
|
||||||
|
|
||||||
|
- Lab041 перезапущена полностью: 180 сочетаний, 24 из 24 функциональных проверок пройдены, пять CSV и семь PNG.
|
||||||
|
- Сверка с прежними файлами показала, что удалено ровно шесть столбцов, а все сохранённые значения совпали до последнего знака. Расхождений в общих столбцах ноль.
|
||||||
|
- Научные выводы Lab041 не изменились. Максимальный путь после перезапуска остался 9,7737 м, постоянная нагрузка управления 10,88000 кбит/с, полный предложенный поток 262,076 кбит/с.
|
||||||
|
- Выводы Записи 016 о сеансах, безопасном запуске и отклонении старых пакетов остаются в силе. Уточняется их основание: доказательством служат 24 функциональные проверки, работающие с настоящими автоматами, а не счётчики матрицы из 180 сочетаний.
|
||||||
|
|
||||||
|
## Следующий этап
|
||||||
|
|
||||||
|
Криптографическая аутентификация отложена. Сначала выполняется этап стабилизации: быстрые тесты `protocol/` вместо единственной точки входа через лабораторную, разделение быстрых проверок и экспериментов, воспроизводимое описание окружения.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Запись 018
|
||||||
|
|
||||||
|
## Дата
|
||||||
|
|
||||||
|
10 августа 2026 года
|
||||||
|
|
||||||
|
## Тема
|
||||||
|
|
||||||
|
Выбор радиочастотной архитектуры: рабочий диапазон, скачки по частоте и меры против подавления.
|
||||||
|
|
||||||
|
## Исходные данные
|
||||||
|
|
||||||
|
- Устройство опрошено напрямую: `Analog Devices PlutoSDR Rev.C (Z7010-AD9361)`. Приёмник перестраивается от 70 МГц до 6 ГГц, передатчик от 46,9 МГц. Минимальная частота дискретизации 2 083 333 Гц.
|
||||||
|
- Ограничений по разрешённым частотам у проекта нет.
|
||||||
|
- Усилителя мощности нет, покупка отложена до первых испытаний.
|
||||||
|
|
||||||
|
## Отвергнутые варианты и причины
|
||||||
|
|
||||||
|
**Выбор редкой фиксированной частоты.** Рассматривался как защита от подавления. Отклонён: одиночная несущая в пустом эфире обнаруживается сканирующим приёмником тривиально. Уязвимость создаёт не значение частоты, а её неизменность.
|
||||||
|
|
||||||
|
**Скачки по всему диапазону 70 МГц – 6 ГГц.** Теоретически требуют от заградительной помехи на 42 дБ больше мощности, но выигрыш недостижим. Отношение крайних частот 86:1, одна антенна такой полосы не перекрывает; разброс потерь на 10 км составляет 39 дБ, проектировать пришлось бы по худшему краю; выше примерно 1 ГГц дифракция исчезает и для наземного ровера без прямой видимости эти каналы мертвы. Кроме того, подавление направлено на диапазон, в котором связь действительно работает, а не на тот, который способно настроить оборудование.
|
||||||
|
|
||||||
|
**Диапазоны 330–433 МГц.** Отклонены как плотно занятые и общеизвестные.
|
||||||
|
|
||||||
|
## Принято
|
||||||
|
|
||||||
|
Рабочий диапазон **200–250 МГц**. Обоснование: четвертьволновая антенна 33 см пригодна для установки на ровер, дифракция ещё эффективна, участок заметно свободнее любительского 144 МГц и УКВ выше 300 МГц. Потери на 10 км составляют около 99,5 дБ.
|
||||||
|
|
||||||
|
Совокупность мер против подавления:
|
||||||
|
|
||||||
|
1. **Скачки по частоте в пределах 200–250 МГц.** Требуют от заградительной помехи на 22 дБ больше мощности при неизменной антенне и механике ровера.
|
||||||
|
2. **Направленная антенна наземной станции.** Даёт 10–20 дБ усиления и пространственно подавляет помеху, приходящую с иного направления.
|
||||||
|
3. **Расширение спектра для команд управления.** Поток команд составляет 10,88 кбит/с, поэтому расширение для него реализуемо в узкой полосе, в отличие от видеопотока.
|
||||||
|
|
||||||
|
Видео остаётся некритичным классом: при подавлении управление сохраняется в узкой полосе, а ровер переходит к безопасному поведению по уже реализованной логике.
|
||||||
|
|
||||||
|
## Запрещённые участки
|
||||||
|
|
||||||
|
- 108–137 МГц — авиационная связь.
|
||||||
|
- 243 МГц — международная аварийная частота.
|
||||||
|
|
||||||
|
## Ограничения решения
|
||||||
|
|
||||||
|
- Нижняя граница 70 МГц определяется приёмником Pluto и без смены оборудования не преодолевается.
|
||||||
|
- Скачки требуют согласованной последовательности у обеих сторон, то есть зависят от криптографической аутентификации, которая пока не реализована.
|
||||||
|
- Расчёты выполнены для свободного пространства. Потери на препятствиях 20–40 дБ учтены оценочно и подлежат измерению.
|
||||||
|
- Дальность 10 км без усилителя мощности не достигается.
|
||||||
|
|
||||||
|
## Влияние на ближайшие работы
|
||||||
|
|
||||||
|
На Lab042 не влияет: там кабельная петля, несущая 435 МГц выбрана произвольно. Диапазон 200–250 МГц вступает в силу начиная с эфирных испытаний.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Запись 019
|
||||||
|
|
||||||
|
## Дата
|
||||||
|
|
||||||
|
10 августа 2026 года
|
||||||
|
|
||||||
|
## Тема
|
||||||
|
|
||||||
|
Lab042: первая передача изображения через реальный радиотракт. Эфирная проверка на паре антенн.
|
||||||
|
|
||||||
|
## Причина эфирного прогона
|
||||||
|
|
||||||
|
Кабельная петля требует переходника SMA папа-папа, которого пока нет: пигтейлы к антеннам оканчиваются папой, а разъёмы Pluto — мамы. Чтобы не простаивать, выполнена вспомогательная эфирная проверка на двух антеннах, разнесённых на 60 см. Она не заменяет кабельный опыт: уровни в помещении не контролируются строго, возможны переотражения. Её задача — снять последнюю неизвестность в коде, а именно обвязку вокруг устройства, которая в моделях не проверяется.
|
||||||
|
|
||||||
|
## Условия
|
||||||
|
|
||||||
|
- Устройство Analog Devices PlutoSDR Rev.C, чип AD9361, прошивка v0.32.
|
||||||
|
- Несущая 225 МГц, внутри целевого диапазона Записи 018.
|
||||||
|
- Антенны, рассчитанные на 108 МГц, работают на несущей как полуволновые. Частота передачи и частота, на которую рассчитана антенна, различны, поэтому в авиационный диапазон 108–137 МГц опыт не заходит.
|
||||||
|
- Изображение 320x180 в градациях серого, JPEG 4756 байт при качестве 35, десять фрагментов.
|
||||||
|
|
||||||
|
## Результат
|
||||||
|
|
||||||
|
- Изображение передано и собрано побайтово идентично исходному. Контрольная сумма MD5 переданного и принятого файла совпала.
|
||||||
|
- Десять фрагментов из десяти, ни одной несошедшейся контрольной суммы.
|
||||||
|
- Средняя нормированная корреляция при поиске кадра 0,99951.
|
||||||
|
- Средняя оценка ухода несущей минус 0,368 Гц, что отражает общий опорный генератор передатчика и приёмника.
|
||||||
|
- Канальная скорость 18,404 кбит/с при длительности сигнала в эфире около 2,07 секунды.
|
||||||
|
- Результат воспроизведён тремя запусками подряд с одинаковой контрольной суммой.
|
||||||
|
|
||||||
|
## Дефекты, вскрытые железом
|
||||||
|
|
||||||
|
Программная модель проходила чисто, но на устройстве обнаружились четыре дефекта, каждый воспроизведён и устранён.
|
||||||
|
|
||||||
|
- Кадр длиной 566 528 отсчётов не помещался в приёмный буфер 262 144. Между отдельными чтениями поток отсчётов не является непрерывным, и кадр на стыке разрушался. Приём переведён на один буфер, размер которого рассчитывается по длине кадра.
|
||||||
|
- Частотная коррекция применялась всегда, тогда как при общем опорном генераторе истинный уход близок к нулю. Оценка по маркеру длиной 80 символов состояла из шума, и коррекция им поворачивала фазу вдоль всего кадра: измерено 65 процентов ошибочных битов. Перенесена защита should_apply_cfo_correction из Lab023, разрешающая коррекцию только вне мёртвой зоны.
|
||||||
|
- Усиление приёмника 20 дБ давало сигнал около 0,0003 от шкалы АЦП. Рабочие уровни подобраны измерением: приёмник 50 дБ, передатчик минус 10 дБ дают ноль ошибочных битов с запасом.
|
||||||
|
- Величина вектора ошибки при неудачном приёме возвращала ноль, то есть показывала идеальный сигнал там, где сигнала не было. Это тот же класс ошибки, что вписанные показатели Lab041: метрика при отказе рапортует лучшее значение. Заменена на явный признак невычислимости.
|
||||||
|
|
||||||
|
## Ограничения
|
||||||
|
|
||||||
|
- Эфирный прогон является проверкой тракта, а не измерением: уровни не контролируются как в кабельной сборке.
|
||||||
|
- Потолок усиления передатчика в эфирном режиме рассчитывается из бюджета линии по расстоянию между антеннами, а не задан константой.
|
||||||
|
|
||||||
|
## Следующий этап
|
||||||
|
|
||||||
|
Кабельная петля через аттенюатор 30 дБ после получения переходника папа-папа. Это и есть заявленный опыт Lab042 с контролируемыми уровнями, его результат станет основным для лабораторной. Затем Lab043 — разведение на два устройства.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Запись 020
|
||||||
|
|
||||||
|
## Дата
|
||||||
|
|
||||||
|
11 августа 2026 года
|
||||||
|
|
||||||
|
## Тема
|
||||||
|
|
||||||
|
Lab042 завершена: кабельная петля через аттенюатор, зависимость доставки от мощности, устранение трёх дефектов отчётности.
|
||||||
|
|
||||||
|
## Схема опыта
|
||||||
|
|
||||||
|
Выход передатчика PlutoSDR через кабель SMA, аттенюатор AT30S 30 дБ, переходник и второй кабель на вход приёмника того же устройства. Антенны сняты. Это заявленный основной опыт лабораторной с контролируемыми уровнями, в отличие от вспомогательной эфирной проверки Записи 019.
|
||||||
|
|
||||||
|
## Зависимость доставки от мощности передатчика
|
||||||
|
|
||||||
|
Кабельный тракт при неизменной схеме исследован по усилению передатчика. Получен отчётливый переход от отказа к устойчивой передаче:
|
||||||
|
|
||||||
|
- TX минус 30 дБ: 0 из 10 фрагментов, контрольная сумма не сходится ни разу, средняя корреляция 0,936. Сигнал ниже порога уверенного приёма.
|
||||||
|
- TX минус 20 дБ: 8 из 10 фрагментов, средняя корреляция 0,992. Пограничный режим: часть кадров проходит.
|
||||||
|
- TX минус 10 дБ: 10 из 10 фрагментов, изображение собрано побайтово. Устойчивая передача.
|
||||||
|
|
||||||
|
Значения TX минус 30 и минус 20 дБ — исследование порога, повторять их не требуется. Рабочая точка кабельной петли: TX минус 10 дБ, RX плюс 20 дБ, аттенюатор 30 дБ, несущая 435 МГц.
|
||||||
|
|
||||||
|
Начальные умолчания кабельного режима TX минус 30 и RX плюс 20 дБ на железе прежде не проверялись; отказ первого прогона объяснялся именно этим, а не дефектом обработки.
|
||||||
|
|
||||||
|
## Результат рабочей точки
|
||||||
|
|
||||||
|
- Найдено 10 кадров из 10, контрольная сумма сошлась у всех десяти, восстановлены все фрагменты.
|
||||||
|
- Изображение собрано и совпадает с переданным. Совпадение подтверждено независимо: SHA-256 принятого файла сверен с SHA-256 переданного JPEG, пересобранного из исходника отдельно от прогона. Оба равны 751d7ea0d8711e2ef54fc5cf209a809cfee5bbb14916dd20aa201d5285b40286.
|
||||||
|
- Размер JPEG 4756 байт, качество 30, десять фрагментов.
|
||||||
|
- Длительность сигнала около 2,07 секунды, канальная скорость 18,404 кбит/с.
|
||||||
|
- Кадр 8 прошёл контрольную сумму при пониженной корреляции поиска 0,866 против 0,998 у остальных: низкая корреляция маркера не означает испорченных данных, фаза дискретизации была подобрана и кадр демодулировался чисто.
|
||||||
|
|
||||||
|
## Устранённые дефекты отчётности
|
||||||
|
|
||||||
|
Разбор кабельного прогона вскрыл три дефекта, при которых провал мог быть принят за успех. Все три устранены, каждый закрыт быстрым тестом в tests/test_lab042_reporting.py.
|
||||||
|
|
||||||
|
- Величина вектора ошибки нормировалась на единичный эталон, из-за чего при слабом сигнале становилась искусственно малой: провалившийся прогон показывал EVM меньше, чем успешный. Нормировка исправлена на мощность подогнанного сигнала. При невозможности вычислить величину возвращается признак невычислимости, а не ноль.
|
||||||
|
- Отчёт перечислял lab042_received.jpg среди созданных файлов безусловно, даже когда изображение не собрано и файла нет. Теперь файл указывается только при фактической сборке.
|
||||||
|
- Программа завершалась кодом ноль при полном отказе передачи. Введён критерий приёмки: при несобранном изображении код завершения ненулевой, чтобы автоматика не приняла провал за успех.
|
||||||
|
|
||||||
|
## Проверки
|
||||||
|
|
||||||
|
- Быстрые тесты ядра расширены с 125 до 135. Добавленные проверяют неуспешный путь: провал даёт ненулевой код, отсутствующий файл не объявляется созданным, невычислимая метрика не превращается в ноль.
|
||||||
|
- Окончательный кабельный прогон рабочей точки выполнен уже исправленной версией программы, поэтому итоговый отчёт сформирован ею.
|
||||||
|
|
||||||
|
## Следующий этап
|
||||||
|
|
||||||
|
Lab043: передаёт PlutoSDR, принимает RTL-SDR. Общий опорный генератор исчезает, впервые появляется реальное рассогласование несущей и частоты дискретизации двух независимых устройств. Здесь понадобится защищённая частотная коррекция, перенесённая в Записи 019.
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
# Инженерный журнал SDR Rover Link
|
|
||||||
|
|
||||||
## Назначение журнала
|
|
||||||
|
|
||||||
Этот файл содержит хронологию разработки проекта SDR Rover Link.
|
|
||||||
|
|
||||||
В журнале фиксируются:
|
|
||||||
|
|
||||||
- выполненные работы;
|
|
||||||
- полученные результаты;
|
|
||||||
- обнаруженные ошибки;
|
|
||||||
- принятые технические решения;
|
|
||||||
- результаты экспериментов;
|
|
||||||
- планы следующего этапа.
|
|
||||||
|
|
||||||
Записи не следует удалять. Если решение изменилось, необходимо добавить новую запись и объяснить причину изменения.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# Запись 001
|
|
||||||
|
|
||||||
## Дата
|
|
||||||
|
|
||||||
10 июля 2026 года
|
|
||||||
|
|
||||||
## Тема
|
|
||||||
|
|
||||||
Создание структуры проекта и локального Git-репозитория.
|
|
||||||
|
|
||||||
## Выполнено
|
|
||||||
|
|
||||||
1. Проверена установленная версия Git:
|
|
||||||
|
|
||||||
```text
|
|
||||||
git version 2.51.1.windows.1
|
|
||||||
@@ -1,340 +0,0 @@
|
|||||||
# SDR Rover Link
|
|
||||||
|
|
||||||
## 1. Назначение проекта
|
|
||||||
|
|
||||||
**SDR Rover Link** — учебно-исследовательский проект по разработке цифрового радиоканала для наземного робототехнического комплекса с использованием программно-определяемого радио — SDR, Software Defined Radio.
|
|
||||||
|
|
||||||
Проект должен пройти полный путь от передачи простого текстового пакета до передачи телеметрии и отдельных JPEG-изображений через реальный радиоканал.
|
|
||||||
|
|
||||||
Основная задача проекта — не только получить работающую систему, но и последовательно изучить все этапы цифровой радиосвязи:
|
|
||||||
|
|
||||||
- формирование данных;
|
|
||||||
- разбиение данных на пакеты;
|
|
||||||
- контроль целостности;
|
|
||||||
- исправление ошибок;
|
|
||||||
- цифровую модуляцию;
|
|
||||||
- формирование IQ-сигнала;
|
|
||||||
- передачу через SDR;
|
|
||||||
- приём и демодуляцию;
|
|
||||||
- восстановление исходных данных.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 2. Целевой сценарий
|
|
||||||
|
|
||||||
Разрабатываемая система предназначена для исследовательского наземного ровера.
|
|
||||||
|
|
||||||
Целевые требования:
|
|
||||||
|
|
||||||
| Параметр | Требование |
|
|
||||||
|---|---|
|
|
||||||
| Дальность связи | до 10 км |
|
|
||||||
| Скорость ровера | до 25 км/ч |
|
|
||||||
| Прямая радиовидимость | может отсутствовать |
|
|
||||||
| Рабочие частоты | ниже 350 МГц |
|
|
||||||
| Основной тип данных | телеметрия и отдельные изображения |
|
|
||||||
| Формат изображения | JPEG |
|
|
||||||
| Частота передачи изображений | отдельные кадры, не видеопоток |
|
|
||||||
| Действие при потере связи | безопасная остановка ровера |
|
|
||||||
|
|
||||||
Дальность 10 км без прямой видимости является целевым исследовательским требованием, а не гарантированной характеристикой первой версии системы.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 3. Почему не используется обычное FPV-видео
|
|
||||||
|
|
||||||
Типовые FPV-системы работают преимущественно в диапазонах 2,4 и 5,8 ГГц.
|
|
||||||
|
|
||||||
Для наземного робота такие диапазоны имеют ряд ограничений:
|
|
||||||
|
|
||||||
- высокие потери при работе у поверхности земли;
|
|
||||||
- затенение рельефом, зданиями и растительностью;
|
|
||||||
- быстрое ухудшение изображения при слабом сигнале;
|
|
||||||
- высокая загруженность распространённых диапазонов;
|
|
||||||
- зависимость от постоянного широкополосного видеопотока.
|
|
||||||
|
|
||||||
В этом проекте вместо непрерывного видео предполагается передавать отдельные сжатые изображения.
|
|
||||||
|
|
||||||
Пример:
|
|
||||||
|
|
||||||
```text
|
|
||||||
Камера
|
|
||||||
↓
|
|
||||||
JPEG-изображение
|
|
||||||
↓
|
|
||||||
Разбиение на пакеты
|
|
||||||
↓
|
|
||||||
Передача через SDR
|
|
||||||
↓
|
|
||||||
Сборка изображения на наземной станции
|
|
||||||
```
|
|
||||||
|
|
||||||
Такой подход позволяет существенно снизить требуемую скорость радиоканала.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 4. Текущее оборудование
|
|
||||||
|
|
||||||
### SDR-оборудование
|
|
||||||
|
|
||||||
- RTL-SDR — приёмник;
|
|
||||||
- ADALM-PlutoSDR — приёмопередатчик, ожидается поступление;
|
|
||||||
- HackRF One — может временно использоваться при необходимости.
|
|
||||||
|
|
||||||
### Вычислительное оборудование
|
|
||||||
|
|
||||||
- компьютер под управлением Windows;
|
|
||||||
- Raspberry Pi — планируется для установки на ровер;
|
|
||||||
- бортовой вычислитель ровера — будет выбран позднее.
|
|
||||||
|
|
||||||
### Программное обеспечение
|
|
||||||
|
|
||||||
- Python 3.12;
|
|
||||||
- Anaconda;
|
|
||||||
- Spyder;
|
|
||||||
- Git;
|
|
||||||
- GNU Radio — будет установлен на следующем этапе;
|
|
||||||
- libiio и драйверы PlutoSDR — будут установлены после получения устройства.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 5. Предварительно рассматриваемые диапазоны
|
|
||||||
|
|
||||||
В рамках проекта рассматриваются:
|
|
||||||
|
|
||||||
- 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
|
|
||||||
SDR_Rover
|
|
||||||
│
|
|
||||||
├── README.md
|
|
||||||
├── docs
|
|
||||||
├── protocol
|
|
||||||
├── rover
|
|
||||||
├── ground_station
|
|
||||||
├── gnuradio
|
|
||||||
├── tests
|
|
||||||
└── tools
|
|
||||||
```
|
|
||||||
|
|
||||||
### `docs`
|
|
||||||
|
|
||||||
Документация, лабораторные работы, схемы и отчёты.
|
|
||||||
|
|
||||||
### `protocol`
|
|
||||||
|
|
||||||
Реализация пакетного протокола:
|
|
||||||
|
|
||||||
- структура пакета;
|
|
||||||
- CRC;
|
|
||||||
- кодирование;
|
|
||||||
- декодирование;
|
|
||||||
- типы сообщений.
|
|
||||||
|
|
||||||
### `rover`
|
|
||||||
|
|
||||||
Программы, которые будут работать на борту ровера:
|
|
||||||
|
|
||||||
- получение изображения;
|
|
||||||
- сжатие JPEG;
|
|
||||||
- передача телеметрии;
|
|
||||||
- формирование радиопакетов.
|
|
||||||
|
|
||||||
### `ground_station`
|
|
||||||
|
|
||||||
Программы наземной станции:
|
|
||||||
|
|
||||||
- приём пакетов;
|
|
||||||
- сборка изображений;
|
|
||||||
- отображение телеметрии;
|
|
||||||
- управление передачей.
|
|
||||||
|
|
||||||
### `gnuradio`
|
|
||||||
|
|
||||||
Схемы GNU Radio Companion:
|
|
||||||
|
|
||||||
- передатчик;
|
|
||||||
- приёмник;
|
|
||||||
- BPSK-модем;
|
|
||||||
- QPSK-модем;
|
|
||||||
- тестовые генераторы.
|
|
||||||
|
|
||||||
### `tests`
|
|
||||||
|
|
||||||
Автоматические и лабораторные тесты.
|
|
||||||
|
|
||||||
### `tools`
|
|
||||||
|
|
||||||
Вспомогательные программы:
|
|
||||||
|
|
||||||
- анализ пакетов;
|
|
||||||
- генераторы тестовых данных;
|
|
||||||
- построение графиков;
|
|
||||||
- анализ журналов.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 8. Принципы разработки
|
|
||||||
|
|
||||||
В проекте применяются следующие правила:
|
|
||||||
|
|
||||||
1. Каждый новый термин сначала объясняется, затем используется.
|
|
||||||
2. Каждый этап должен завершаться работающим результатом.
|
|
||||||
3. Радиоканал и пакетный протокол разрабатываются отдельно.
|
|
||||||
4. Код проверяется автоматическими тестами.
|
|
||||||
5. Все существенные решения фиксируются в документации.
|
|
||||||
6. Сложность увеличивается постепенно.
|
|
||||||
7. Испытания по эфиру начинаются только после проверки через виртуальный канал.
|
|
||||||
8. Передатчик сначала проверяется через аттенюатор или эквивалент нагрузки.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 9. Текущий статус
|
|
||||||
|
|
||||||
Выполнено:
|
|
||||||
|
|
||||||
- установлен Python;
|
|
||||||
- установлена Anaconda;
|
|
||||||
- выбран Spyder;
|
|
||||||
- установлен Git;
|
|
||||||
- создан локальный Git-репозиторий;
|
|
||||||
- создана базовая структура каталогов.
|
|
||||||
|
|
||||||
Следующая задача:
|
|
||||||
|
|
||||||
> Создать первый Python-модуль пакетного протокола и передать сообщение через виртуальный канал без SDR-оборудования.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 10. Ближайший контрольный результат
|
|
||||||
|
|
||||||
Первая рабочая версия должна выполнять следующий цикл:
|
|
||||||
|
|
||||||
```text
|
|
||||||
Текстовое сообщение
|
|
||||||
↓
|
|
||||||
Преобразование в байты
|
|
||||||
↓
|
|
||||||
Формирование пакета
|
|
||||||
↓
|
|
||||||
Добавление CRC
|
|
||||||
↓
|
|
||||||
Имитация радиоканала
|
|
||||||
↓
|
|
||||||
Проверка CRC
|
|
||||||
↓
|
|
||||||
Восстановление сообщения
|
|
||||||
```
|
|
||||||
|
|
||||||
Первое тестовое сообщение:
|
|
||||||
|
|
||||||
```text
|
|
||||||
HELLO SDR
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 11. Автор
|
|
||||||
|
|
||||||
Антон
|
|
||||||
|
|
||||||
НИЯУ МИФИ
|
|
||||||
|
|
||||||
2026
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
frequency_hz,frequency_mhz,relative_power_db,prominence_db
|
|
||||||
98840137.685,98.840138,-16.363,14.939
|
|
||||||
99201367.853,99.201368,-8.578,21.049
|
|
||||||
99603613.612,99.603614,-5.852,194.148
|
|
||||||
100099316.323,100.099316,-0.641,27.938
|
|
||||||
100498925.365,100.498925,0.000,200.000
|
|
||||||
100896483.628,100.896484,-2.662,25.928
|
|
||||||
101159569.346,101.159569,-11.137,18.231
|
|
||||||
|
@@ -1,19 +0,0 @@
|
|||||||
Lab024B. Усреднённый спектр Pluto+ методом Уэлча
|
|
||||||
|
|
||||||
URI: ip:192.168.2.1
|
|
||||||
Центральная частота: 100.000 МГц
|
|
||||||
Частота дискретизации: 2.400 Мвыб/с
|
|
||||||
Полоса RX: 2.000 МГц
|
|
||||||
Количество IQ-сэмплов: 1048576
|
|
||||||
Размер сегмента Уэлча: 8192
|
|
||||||
Перекрытие сегментов: 4096
|
|
||||||
|
|
||||||
Найдено кандидатов: 7
|
|
||||||
|
|
||||||
01. 98.840138 МГц, уровень -16.36 дБ, выраженность 14.94 дБ
|
|
||||||
02. 99.201368 МГц, уровень -8.58 дБ, выраженность 21.05 дБ
|
|
||||||
03. 99.603614 МГц, уровень -5.85 дБ, выраженность 194.15 дБ
|
|
||||||
04. 100.099316 МГц, уровень -0.64 дБ, выраженность 27.94 дБ
|
|
||||||
05. 100.498925 МГц, уровень 0.00 дБ, выраженность 200.00 дБ
|
|
||||||
06. 100.896484 МГц, уровень -2.66 дБ, выраженность 25.93 дБ
|
|
||||||
07. 101.159569 МГц, уровень -11.14 дБ, выраженность 18.23 дБ
|
|
||||||
|
Before Width: | Height: | Size: 187 KiB |
180
README.md
Normal file
@@ -0,0 +1,180 @@
|
|||||||
|
# SDR Rover Link
|
||||||
|
|
||||||
|
## 1. Назначение проекта
|
||||||
|
|
||||||
|
**SDR Rover Link** — учебно-исследовательский проект по разработке цифрового радиоканала для наземного робототехнического комплекса с использованием программно-определяемого радио — SDR, Software Defined Radio.
|
||||||
|
|
||||||
|
Проект должен пройти полный путь от передачи простого текстового пакета до передачи телеметрии и изображений через реальный радиоканал.
|
||||||
|
|
||||||
|
Основная задача — не только получить работающую систему, но и последовательно изучить все этапы цифровой радиосвязи: формирование данных, разбиение на пакеты, контроль целостности, исправление ошибок, цифровую модуляцию, формирование IQ-сигнала, передачу через SDR, приём, демодуляцию и восстановление исходных данных.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Целевой сценарий
|
||||||
|
|
||||||
|
| Параметр | Требование |
|
||||||
|
|---|---|
|
||||||
|
| Дальность связи | до 10 км |
|
||||||
|
| Скорость ровера | до 25 км/ч |
|
||||||
|
| Прямая радиовидимость | может отсутствовать |
|
||||||
|
| Рабочий диапазон | 200–250 МГц, см. Запись 018 журнала |
|
||||||
|
| Основной тип данных | телеметрия, команды и изображения |
|
||||||
|
| Формат изображения | JPEG |
|
||||||
|
| Действие при потере связи | безопасная остановка ровера |
|
||||||
|
|
||||||
|
Дальность 10 км без прямой видимости — целевое исследовательское требование, а не гарантированная характеристика первой версии.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Почему не используется обычное FPV-видео
|
||||||
|
|
||||||
|
Типовые FPV-системы работают в диапазонах 2,4 и 5,8 ГГц. Для наземного робота это плохо: велики потери у поверхности земли, сильное затенение рельефом и растительностью, а главное — на таких частотах практически нет дифракции, поэтому за препятствием связь пропадает.
|
||||||
|
|
||||||
|
В этом проекте вместо непрерывного видеопотока передаются отдельные сжатые изображения, что резко снижает требуемую скорость канала.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Текущее состояние
|
||||||
|
|
||||||
|
**Выполнено:** лабораторные Lab001–Lab042. Пройден путь от структуры пакета до первой передачи изображения через реальный радиотракт.
|
||||||
|
|
||||||
|
Что реализовано и проверено:
|
||||||
|
|
||||||
|
- пакетный протокол с CRC32, фрагментация и сборка изображений;
|
||||||
|
- модуляция и демодуляция BPSK, формирующий фильтр, кадровая синхронизация, оценка и коррекция ухода несущей;
|
||||||
|
- блочное исправление стираний над GF(256), перемежение, подбор параметров;
|
||||||
|
- приоритетное обслуживание команд, телеметрии и видео;
|
||||||
|
- двухступенчатая безопасная остановка, сторожевой таймер, постоянное аварийное намерение, безопасный сброс;
|
||||||
|
- идентификаторы сеанса, безопасный запуск, отклонение пакетов предыдущего сеанса;
|
||||||
|
- передача JPEG через настоящий радиотракт на одном PlutoSDR: сначала по эфиру на паре антенн, затем по кабелю через аттенюатор 30 дБ. Принятое изображение совпало с переданным побайтово (Записи 019 и 020).
|
||||||
|
|
||||||
|
**Что ещё не сделано:** два независимых устройства пока не разведены. Все передачи выполнены в петле одного PlutoSDR, где передатчик и приёмник делят опорный генератор, поэтому рассогласования несущей и частоты дискретизации между сторонами почти нет.
|
||||||
|
|
||||||
|
**Ближайшая работа:** Lab043 — передача с PlutoSDR на приём RTL-SDR. Общий опорный генератор исчезает, впервые появляется реальное рассогласование двух устройств. Техническое задание на завершённую Lab042: [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.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. Как запускать
|
||||||
|
|
||||||
|
**Быстрые проверки ядра** — секунды, оборудование не нужно:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python -m pytest tests/ -q
|
||||||
|
```
|
||||||
|
|
||||||
|
**Дешёвый шлюз** — синтаксис, импорт `protocol`, быстрые проверки ядра и функциональные проверки лабораторных. Отвечает на один вопрос: не сломана ли кодовая база прямо сейчас:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python tools/quick_gate.py
|
||||||
|
```
|
||||||
|
|
||||||
|
**Лабораторный эксперимент** — минуты, пишет результаты в `data/processed/`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python -m experiments.lab041_session_restart_safety
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. Структура репозитория
|
||||||
|
|
||||||
|
```text
|
||||||
|
SDR_Rover
|
||||||
|
├── protocol/ реализация протокола и радиотракта
|
||||||
|
├── experiments/ лабораторные Lab001–Lab041
|
||||||
|
├── tests/ быстрые автоматические проверки
|
||||||
|
├── tools/ вспомогательные программы и шлюз
|
||||||
|
├── docs/ технические задания и исследования
|
||||||
|
├── data/ исходные данные и результаты
|
||||||
|
├── rover/ пока пусто
|
||||||
|
├── ground_station/ пока пусто
|
||||||
|
└── gnuradio/ пока пусто
|
||||||
|
```
|
||||||
|
|
||||||
|
### `protocol`
|
||||||
|
|
||||||
|
Ядро системы. Пакет с CRC32, фрагментация изображений, кадр канала, исправление стираний, приоритеты, аварийная логика, сеансы связи, примитивы BPSK-радиотракта.
|
||||||
|
|
||||||
|
### `experiments`
|
||||||
|
|
||||||
|
Лабораторные работы. Это исследовательские программы: они моделируют канал, выполняют сотни повторов, строят CSV, графики и отчёты. **Быстрыми тестами они не являются.** При импорте создают каталоги и пишут файлы, поэтому импортировать их не следует — для повторного использования кода служит `protocol/`.
|
||||||
|
|
||||||
|
### `tests`
|
||||||
|
|
||||||
|
Настоящие быстрые проверки `protocol/`. Выполняются за доли секунды, оборудования не требуют, запускаются через `pytest`.
|
||||||
|
|
||||||
|
### `rover`, `ground_station`, `gnuradio`
|
||||||
|
|
||||||
|
Каталоги созданы под будущую прикладную часть и пока пусты. Бортовая программа ровера, программа наземной станции и схемы GNU Radio появятся после того, как радиоканал заработает в эфире.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 9. Данные
|
||||||
|
|
||||||
|
- `data/raw` — исходные данные. Крупные записи отсчётов и видео в репозиторий не помещаются, исходные изображения лабораторных хранятся.
|
||||||
|
- `data/processed` — результаты лабораторных: CSV, отчёты и графики.
|
||||||
|
|
||||||
|
**Ограничение воспроизводимости.** Исходное видео `data/raw/lab026_rover_source.mp4` (около 7,8 МБ) в репозитории не хранится. Без него Lab026 и Lab027 не запускаются, файл нужно получить отдельно.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 10. Принципы разработки
|
||||||
|
|
||||||
|
1. Каждый новый термин сначала объясняется, затем используется.
|
||||||
|
2. Каждый этап завершается работающим результатом.
|
||||||
|
3. Радиоканал и пакетный протокол разрабатываются отдельно.
|
||||||
|
4. Код проверяется автоматическими тестами.
|
||||||
|
5. Все существенные решения фиксируются в журнале.
|
||||||
|
6. Сложность увеличивается постепенно.
|
||||||
|
7. Испытания по эфиру начинаются только после проверки через модель.
|
||||||
|
8. Передатчик сначала проверяется через аттенюатор или эквивалент нагрузки.
|
||||||
|
9. **Каждое число в отчёте должно вычисляться из измерений текущего запуска.** Перенесённые из других лабораторных величины сопровождаются указанием источника. Вписанные вручную результаты недопустимы.
|
||||||
|
|
||||||
|
Девятое правило добавлено после аудита достоверности, см. Запись 017 журнала.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 11. Автор
|
||||||
|
|
||||||
|
Антон
|
||||||
|
|
||||||
|
НИЯУ МИФИ
|
||||||
|
|
||||||
|
2026
|
||||||
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 9.3 KiB After Width: | Height: | Size: 9.3 KiB |
|
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 6.3 KiB |
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 91 KiB After Width: | Height: | Size: 91 KiB |
|
Before Width: | Height: | Size: 6.2 KiB After Width: | Height: | Size: 6.2 KiB |
|
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.5 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 133 KiB After Width: | Height: | Size: 133 KiB |
|
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 5.3 KiB |
|
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 4.7 KiB |
|
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.5 KiB |
|
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 3.0 KiB |
|
Before Width: | Height: | Size: 129 KiB After Width: | Height: | Size: 129 KiB |
|
Before Width: | Height: | Size: 144 KiB After Width: | Height: | Size: 144 KiB |
|
Before Width: | Height: | Size: 101 KiB After Width: | Height: | Size: 101 KiB |
|
Before Width: | Height: | Size: 103 KiB After Width: | Height: | Size: 103 KiB |
|
Before Width: | Height: | Size: 102 KiB After Width: | Height: | Size: 102 KiB |
|
Before Width: | Height: | Size: 73 KiB After Width: | Height: | Size: 73 KiB |
|
Before Width: | Height: | Size: 41 KiB After Width: | Height: | Size: 41 KiB |
|
Before Width: | Height: | Size: 154 KiB After Width: | Height: | Size: 154 KiB |
|
Before Width: | Height: | Size: 314 KiB After Width: | Height: | Size: 314 KiB |
|
Before Width: | Height: | Size: 162 KiB After Width: | Height: | Size: 162 KiB |
|
Before Width: | Height: | Size: 203 KiB After Width: | Height: | Size: 203 KiB |
|
Before Width: | Height: | Size: 206 KiB After Width: | Height: | Size: 206 KiB |
|
Before Width: | Height: | Size: 253 KiB After Width: | Height: | Size: 253 KiB |
|
Before Width: | Height: | Size: 260 KiB After Width: | Height: | Size: 260 KiB |
6
data/processed/lab024b/lab024b_fm_candidates.csv
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
frequency_hz,frequency_mhz,relative_power_db,prominence_db
|
||||||
|
99198731.136,99.198731,-5.071,30.671
|
||||||
|
99595703.462,99.595703,-2.354,32.308
|
||||||
|
100099316.323,100.099316,0.000,35.017
|
||||||
|
100479882.413,100.479882,-1.155,32.127
|
||||||
|
100895604.722,100.895605,-7.043,27.121
|
||||||
|
17
data/processed/lab024b/lab024b_report.txt
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
Lab024B. Усреднённый спектр Pluto+ методом Уэлча
|
||||||
|
|
||||||
|
URI: ip:192.168.2.1
|
||||||
|
Центральная частота: 100.000 МГц
|
||||||
|
Частота дискретизации: 2.400 Мвыб/с
|
||||||
|
Полоса RX: 2.000 МГц
|
||||||
|
Количество IQ-сэмплов: 1048576
|
||||||
|
Размер сегмента Уэлча: 8192
|
||||||
|
Перекрытие сегментов: 4096
|
||||||
|
|
||||||
|
Найдено кандидатов: 5
|
||||||
|
|
||||||
|
01. 99.198731 МГц, уровень -5.07 дБ, выраженность 30.67 дБ
|
||||||
|
02. 99.595703 МГц, уровень -2.35 дБ, выраженность 32.31 дБ
|
||||||
|
03. 100.099316 МГц, уровень 0.00 дБ, выраженность 35.02 дБ
|
||||||
|
04. 100.479882 МГц, уровень -1.15 дБ, выраженность 32.13 дБ
|
||||||
|
05. 100.895605 МГц, уровень -7.04 дБ, выраженность 27.12 дБ
|
||||||
8193
data/processed/lab024b/lab024b_welch_spectrum.csv
Normal file
BIN
data/processed/lab024b/lab024b_welch_spectrum.png
Normal file
|
After Width: | Height: | Size: 193 KiB |
BIN
data/processed/lab025/lab025_audio_spectrum.png
Normal file
|
After Width: | Height: | Size: 136 KiB |
BIN
data/processed/lab025/lab025_audio_waveform.png
Normal file
|
After Width: | Height: | Size: 237 KiB |
29
data/processed/lab025/lab025_report.txt
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
Lab025. Приём и программная WFM-демодуляция
|
||||||
|
|
||||||
|
URI Pluto+: ip:192.168.2.1
|
||||||
|
Частота станции: 100100000 Гц
|
||||||
|
RX LO: 100350000 Гц
|
||||||
|
Цифровое смещение: +250000 Гц
|
||||||
|
Частота дискретизации RX: 2400000 Гц
|
||||||
|
Полоса RX: 1500000 Гц
|
||||||
|
Количество рабочих буферов: 128
|
||||||
|
Количество IQ-сэмплов: 8388608
|
||||||
|
Длительность IQ-записи: 3.495253 с
|
||||||
|
Частота канального сигнала после децимации: 240000 Гц
|
||||||
|
Длительность итогового WAV: 3.445250 с
|
||||||
|
Частота WAV: 48000 Гц
|
||||||
|
Тип PCM: signed PCM16, mono
|
||||||
|
RMS итогового аудио: 0.389148
|
||||||
|
Пиковая амплитуда: 0.974792
|
||||||
|
Отсчёты на границе PCM16: 0.000000 %
|
||||||
|
|
||||||
|
Выходные файлы:
|
||||||
|
WAV: data\processed\lab025\lab025_wfm_audio_100_1mhz.wav
|
||||||
|
Радиоспектр: data\processed\lab025\lab025_rf_spectrum.png
|
||||||
|
Звуковая волна: data\processed\lab025\lab025_audio_waveform.png
|
||||||
|
Спектр звука: data\processed\lab025\lab025_audio_spectrum.png
|
||||||
|
Отчёт: data\processed\lab025\lab025_report.txt
|
||||||
|
|
||||||
|
Использован только приёмный канал RX1.
|
||||||
|
Передатчики TX1 и TX2 не использовались.
|
||||||
|
Необработанные IQ-сэмплы на диск не сохранялись.
|
||||||
BIN
data/processed/lab025/lab025_rf_spectrum.png
Normal file
|
After Width: | Height: | Size: 138 KiB |
BIN
data/processed/lab025/lab025_wfm_audio_100_1mhz.wav
Normal file
BIN
data/processed/lab026/lab026_bitrate_vs_fps.png
Normal file
|
After Width: | Height: | Size: 81 KiB |
BIN
data/processed/lab026/lab026_bitrate_vs_jpeg_quality.png
Normal file
|
After Width: | Height: | Size: 100 KiB |
BIN
data/processed/lab026/lab026_bitrate_vs_resolution.png
Normal file
|
After Width: | Height: | Size: 81 KiB |
BIN
data/processed/lab026/lab026_candidate_profiles.png
Normal file
|
After Width: | Height: | Size: 1.9 MiB |
33
data/processed/lab026/lab026_profiles.csv
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
experiment,profile_name,width,height,target_fps,actual_fps,color_mode,jpeg_quality,source_duration_s,selected_frames,total_bytes,mean_frame_bytes,median_frame_bytes,p95_frame_bytes,max_frame_bytes,payload_bitrate_bps,payload_bitrate_kbps,source_file_bitrate_kbps,reduction_ratio,percent_of_source,mean_psnr_db
|
||||||
|
fps_sweep,fps_30,640,360,30.000000,30.000000,grayscale,50,20.766667,623,10219569,16403.803,16282.000,18471.500,21081,3936912.616,3936.912616,3001.342536,0.762359,131.171720,37.349661
|
||||||
|
fps_sweep,fps_10,640,360,10.000000,10.016051,grayscale,50,20.766667,208,3641634,17507.856,17509.500,18958.400,21081,1402876.661,1402.876661,3001.342536,2.139420,46.741638,36.369592
|
||||||
|
fps_sweep,fps_5,640,360,5.000000,5.008026,grayscale,50,20.766667,104,1822387,17522.952,17547.000,18910.400,21081,702043.146,702.043146,3001.342536,4.275154,23.390970,36.352519
|
||||||
|
fps_sweep,fps_2,640,360,2.000000,2.022472,grayscale,50,20.766667,42,737435,17557.976,17476.500,18926.800,21081,284084.109,284.084109,3001.342536,10.564979,9.465234,36.319782
|
||||||
|
fps_sweep,fps_1,640,360,1.000000,1.011236,grayscale,50,20.766667,21,369317,17586.524,17483.000,18935.000,21081,142273.002,142.273002,3001.342536,21.095658,4.740312,36.287711
|
||||||
|
fps_sweep,fps_0_5,640,360,0.500000,0.529695,grayscale,50,20.766667,11,191626,17420.545,17040.000,19774.000,21081,73820.610,73.820610,3001.342536,40.657244,2.459586,36.371684
|
||||||
|
fps_sweep,fps_0_2,640,360,0.200000,0.240770,grayscale,50,20.766667,5,91496,18299.200,18467.000,20651.800,21081,35247.255,35.247255,3001.342536,85.151100,1.174383,35.860330
|
||||||
|
resolution_sweep,resolution_1280x720,1280,720,5.000000,5.008026,grayscale,50,20.766667,104,5506628,52948.346,52634.000,57821.150,73994,2121333.419,2121.333419,3001.342536,1.414838,70.679484,39.607731
|
||||||
|
resolution_sweep,resolution_960x540,960,540,5.000000,5.008026,grayscale,50,20.766667,104,3411900,32806.731,32634.500,35501.600,41897,1314375.602,1314.375602,3001.342536,2.283474,43.792922,38.632041
|
||||||
|
resolution_sweep,resolution_640x360,640,360,5.000000,5.008026,grayscale,50,20.766667,104,1822387,17522.952,17547.000,18910.400,21081,702043.146,702.043146,3001.342536,4.275154,23.390970,36.352519
|
||||||
|
resolution_sweep,resolution_480x270,480,270,5.000000,5.008026,grayscale,50,20.766667,104,1120944,10778.308,10786.000,11463.200,12395,431824.334,431.824334,3001.342536,6.950378,14.387706,36.172087
|
||||||
|
resolution_sweep,resolution_320x180,320,180,5.000000,5.008026,grayscale,50,20.766667,104,590018,5673.250,5679.000,5995.750,6191,227294.254,227.294254,3001.342536,13.204656,7.573086,35.069392
|
||||||
|
resolution_sweep,resolution_160x90,160,90,5.000000,5.008026,grayscale,50,20.766667,104,210050,2019.712,2017.000,2103.400,2156,80918.138,80.918138,3001.342536,37.091097,2.696065,33.585930
|
||||||
|
quality_sweep,quality_color_q90,640,360,5.000000,5.008026,color,90,20.766667,104,5486654,52756.288,52645.500,57012.750,66227,2113638.780,2113.638780,3001.342536,1.419988,70.423111,39.694424
|
||||||
|
quality_sweep,quality_color_q70,640,360,5.000000,5.008026,color,70,20.766667,104,2901304,27897.154,27815.500,30080.600,33877,1117677.303,1117.677303,3001.342536,2.685339,37.239245,36.029412
|
||||||
|
quality_sweep,quality_color_q50,640,360,5.000000,5.008026,color,50,20.766667,104,2137169,20549.702,20514.000,22026.250,24396,823307.480,823.307480,3001.342536,3.645470,27.431307,34.439250
|
||||||
|
quality_sweep,quality_color_q30,640,360,5.000000,5.008026,color,30,20.766667,104,1572112,15116.462,15105.500,16167.600,17386,605629.021,605.629021,3001.342536,4.955744,20.178604,32.766254
|
||||||
|
quality_sweep,quality_color_q20,640,360,5.000000,5.008026,color,20,20.766667,104,1224535,11774.375,11797.000,12633.050,13098,471730.979,471.730979,3001.342536,6.362403,15.717332,31.298703
|
||||||
|
quality_sweep,quality_grayscale_q90,640,360,5.000000,5.008026,grayscale,90,20.766667,104,4697004,45163.500,44959.000,48937.750,57535,1809439.743,1809.439743,3001.342536,1.658714,60.287679,42.574562
|
||||||
|
quality_sweep,quality_grayscale_q70,640,360,5.000000,5.008026,grayscale,70,20.766667,104,2484781,23892.125,23853.000,25744.950,29385,957219.005,957.219005,3001.342536,3.135482,31.893028,38.031656
|
||||||
|
quality_sweep,quality_grayscale_q50,640,360,5.000000,5.008026,grayscale,50,20.766667,104,1822387,17522.952,17547.000,18910.400,21081,702043.146,702.043146,3001.342536,4.275154,23.390970,36.352519
|
||||||
|
quality_sweep,quality_grayscale_q30,640,360,5.000000,5.008026,grayscale,30,20.766667,104,1328179,12770.952,12821.500,13834.150,14903,511658.042,511.658042,3001.342536,5.865915,17.047639,34.701951
|
||||||
|
quality_sweep,quality_grayscale_q20,640,360,5.000000,5.008026,grayscale,20,20.766667,104,1017957,9788.048,9832.500,10597.450,11027,392150.369,392.150369,3001.342536,7.653550,13.065832,33.304362
|
||||||
|
candidate_profiles,candidate_640x360_gray_5fps_q50,640,360,5.000000,5.008026,grayscale,50,20.766667,104,1822387,17522.952,17547.000,18910.400,21081,702043.146,702.043146,3001.342536,4.275154,23.390970,36.352519
|
||||||
|
candidate_profiles,candidate_640x360_gray_2fps_q40,640,360,2.000000,2.022472,grayscale,40,20.766667,42,639531,15226.929,15187.500,16381.750,18122,246368.283,246.368283,3001.342536,12.182341,8.208603,35.588581
|
||||||
|
candidate_profiles,candidate_320x180_color_5fps_q50,320,180,5.000000,5.008026,color,50,20.766667,104,717676,6900.731,6919.500,7309.850,7475,276472.295,276.472295,3001.342536,10.855853,9.211621,32.413850
|
||||||
|
candidate_profiles,candidate_320x180_gray_5fps_q50,320,180,5.000000,5.008026,grayscale,50,20.766667,104,590018,5673.250,5679.000,5995.750,6191,227294.254,227.294254,3001.342536,13.204656,7.573086,35.069392
|
||||||
|
candidate_profiles,candidate_320x180_gray_2fps_q40,320,180,2.000000,2.022472,grayscale,40,20.766667,42,208403,4961.976,4965.000,5224.700,5400,80283.660,80.283660,3001.342536,37.384227,2.674925,34.362114
|
||||||
|
candidate_profiles,candidate_320x180_gray_1fps_q35,320,180,1.000000,1.011236,grayscale,35,20.766667,21,96733,4606.333,4611.000,4836.000,4992,37264.719,37.264719,3001.342536,80.541129,1.241602,34.035117
|
||||||
|
candidate_profiles,candidate_320x180_gray_0_5fps_q35,320,180,0.500000,0.529695,grayscale,35,20.766667,11,50124,4556.727,4493.000,4914.000,4992,19309.406,19.309406,3001.342536,155.434223,0.643359,34.165852
|
||||||
|
candidate_profiles,candidate_320x180_gray_0_2fps_q35,320,180,0.200000,0.240770,grayscale,35,20.766667,5,23618,4723.600,4815.000,4960.800,4992,9098.427,9.098427,3001.342536,329.874884,0.303145,33.741044
|
||||||
|
candidate_profiles,candidate_160x90_gray_1fps_q30,160,90,1.000000,1.011236,grayscale,30,20.766667,21,32743,1559.190,1561.000,1623.000,1632,12613.676,12.613676,3001.342536,237.943530,0.420268,32.031480
|
||||||
|
82
data/processed/lab026/lab026_report.txt
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
Lab026. Исследование уменьшения видеопотока для радиоуправления ровером
|
||||||
|
|
||||||
|
Цель: исследовать уменьшение полезной нагрузки видеоканала для передачи через ретранслятор.
|
||||||
|
Исходный файл: data\raw\lab026_rover_source.mp4
|
||||||
|
Размер исходного файла: 7790985 байт
|
||||||
|
Исходное разрешение: 1280x720
|
||||||
|
Исходный FPS: 30.000000
|
||||||
|
Число кадров: 623
|
||||||
|
Длительность: 20.766667 с
|
||||||
|
Приблизительный исходный файловый битрейт: 3001.343 кбит/с
|
||||||
|
|
||||||
|
Исследуется независимое покадровое JPEG-сжатие. JPEG хранится и декодируется только в памяти.
|
||||||
|
Рассчитанный bitrate учитывает только JPEG payload.
|
||||||
|
Не учитываются заголовки радиопакетов, CRC, FEC, преамбула, интервалы, повторы и команды управления.
|
||||||
|
|
||||||
|
Результаты fps_sweep:
|
||||||
|
fps_30: 640x360, 30 кадр/с, grayscale, Q=50, кадров=623, payload=3936.913 кбит/с, PSNR=37.350 дБ, уменьшение=0.76x
|
||||||
|
fps_10: 640x360, 10 кадр/с, grayscale, Q=50, кадров=208, payload=1402.877 кбит/с, PSNR=36.370 дБ, уменьшение=2.14x
|
||||||
|
fps_5: 640x360, 5 кадр/с, grayscale, Q=50, кадров=104, payload=702.043 кбит/с, PSNR=36.353 дБ, уменьшение=4.28x
|
||||||
|
fps_2: 640x360, 2 кадр/с, grayscale, Q=50, кадров=42, payload=284.084 кбит/с, PSNR=36.320 дБ, уменьшение=10.56x
|
||||||
|
fps_1: 640x360, 1 кадр/с, grayscale, Q=50, кадров=21, payload=142.273 кбит/с, PSNR=36.288 дБ, уменьшение=21.10x
|
||||||
|
fps_0_5: 640x360, 0.5 кадр/с, grayscale, Q=50, кадров=11, payload=73.821 кбит/с, PSNR=36.372 дБ, уменьшение=40.66x
|
||||||
|
fps_0_2: 640x360, 0.2 кадр/с, grayscale, Q=50, кадров=5, payload=35.247 кбит/с, PSNR=35.860 дБ, уменьшение=85.15x
|
||||||
|
|
||||||
|
Результаты resolution_sweep:
|
||||||
|
resolution_1280x720: 1280x720, 5 кадр/с, grayscale, Q=50, кадров=104, payload=2121.333 кбит/с, PSNR=39.608 дБ, уменьшение=1.41x
|
||||||
|
resolution_960x540: 960x540, 5 кадр/с, grayscale, Q=50, кадров=104, payload=1314.376 кбит/с, PSNR=38.632 дБ, уменьшение=2.28x
|
||||||
|
resolution_640x360: 640x360, 5 кадр/с, grayscale, Q=50, кадров=104, payload=702.043 кбит/с, PSNR=36.353 дБ, уменьшение=4.28x
|
||||||
|
resolution_480x270: 480x270, 5 кадр/с, grayscale, Q=50, кадров=104, payload=431.824 кбит/с, PSNR=36.172 дБ, уменьшение=6.95x
|
||||||
|
resolution_320x180: 320x180, 5 кадр/с, grayscale, Q=50, кадров=104, payload=227.294 кбит/с, PSNR=35.069 дБ, уменьшение=13.20x
|
||||||
|
resolution_160x90: 160x90, 5 кадр/с, grayscale, Q=50, кадров=104, payload=80.918 кбит/с, PSNR=33.586 дБ, уменьшение=37.09x
|
||||||
|
|
||||||
|
Результаты quality_sweep:
|
||||||
|
quality_color_q90: 640x360, 5 кадр/с, color, Q=90, кадров=104, payload=2113.639 кбит/с, PSNR=39.694 дБ, уменьшение=1.42x
|
||||||
|
quality_color_q70: 640x360, 5 кадр/с, color, Q=70, кадров=104, payload=1117.677 кбит/с, PSNR=36.029 дБ, уменьшение=2.69x
|
||||||
|
quality_color_q50: 640x360, 5 кадр/с, color, Q=50, кадров=104, payload=823.307 кбит/с, PSNR=34.439 дБ, уменьшение=3.65x
|
||||||
|
quality_color_q30: 640x360, 5 кадр/с, color, Q=30, кадров=104, payload=605.629 кбит/с, PSNR=32.766 дБ, уменьшение=4.96x
|
||||||
|
quality_color_q20: 640x360, 5 кадр/с, color, Q=20, кадров=104, payload=471.731 кбит/с, PSNR=31.299 дБ, уменьшение=6.36x
|
||||||
|
quality_grayscale_q90: 640x360, 5 кадр/с, grayscale, Q=90, кадров=104, payload=1809.440 кбит/с, PSNR=42.575 дБ, уменьшение=1.66x
|
||||||
|
quality_grayscale_q70: 640x360, 5 кадр/с, grayscale, Q=70, кадров=104, payload=957.219 кбит/с, PSNR=38.032 дБ, уменьшение=3.14x
|
||||||
|
quality_grayscale_q50: 640x360, 5 кадр/с, grayscale, Q=50, кадров=104, payload=702.043 кбит/с, PSNR=36.353 дБ, уменьшение=4.28x
|
||||||
|
quality_grayscale_q30: 640x360, 5 кадр/с, grayscale, Q=30, кадров=104, payload=511.658 кбит/с, PSNR=34.702 дБ, уменьшение=5.87x
|
||||||
|
quality_grayscale_q20: 640x360, 5 кадр/с, grayscale, Q=20, кадров=104, payload=392.150 кбит/с, PSNR=33.304 дБ, уменьшение=7.65x
|
||||||
|
|
||||||
|
Результаты candidate_profiles:
|
||||||
|
candidate_640x360_gray_5fps_q50: 640x360, 5 кадр/с, grayscale, Q=50, кадров=104, payload=702.043 кбит/с, PSNR=36.353 дБ, уменьшение=4.28x
|
||||||
|
candidate_640x360_gray_2fps_q40: 640x360, 2 кадр/с, grayscale, Q=40, кадров=42, payload=246.368 кбит/с, PSNR=35.589 дБ, уменьшение=12.18x
|
||||||
|
candidate_320x180_color_5fps_q50: 320x180, 5 кадр/с, color, Q=50, кадров=104, payload=276.472 кбит/с, PSNR=32.414 дБ, уменьшение=10.86x
|
||||||
|
candidate_320x180_gray_5fps_q50: 320x180, 5 кадр/с, grayscale, Q=50, кадров=104, payload=227.294 кбит/с, PSNR=35.069 дБ, уменьшение=13.20x
|
||||||
|
candidate_320x180_gray_2fps_q40: 320x180, 2 кадр/с, grayscale, Q=40, кадров=42, payload=80.284 кбит/с, PSNR=34.362 дБ, уменьшение=37.38x
|
||||||
|
candidate_320x180_gray_1fps_q35: 320x180, 1 кадр/с, grayscale, Q=35, кадров=21, payload=37.265 кбит/с, PSNR=34.035 дБ, уменьшение=80.54x
|
||||||
|
candidate_320x180_gray_0_5fps_q35: 320x180, 0.5 кадр/с, grayscale, Q=35, кадров=11, payload=19.309 кбит/с, PSNR=34.166 дБ, уменьшение=155.43x
|
||||||
|
candidate_320x180_gray_0_2fps_q35: 320x180, 0.2 кадр/с, grayscale, Q=35, кадров=5, payload=9.098 кбит/с, PSNR=33.741 дБ, уменьшение=329.87x
|
||||||
|
candidate_160x90_gray_1fps_q30: 160x90, 1 кадр/с, grayscale, Q=30, кадров=21, payload=12.614 кбит/с, PSNR=32.031 дБ, уменьшение=237.94x
|
||||||
|
|
||||||
|
Candidate-профили с payload bitrate не более 100 кбит/с:
|
||||||
|
candidate_320x180_gray_2fps_q40: 320x180, 2 кадр/с, grayscale, Q=40, кадров=42, payload=80.284 кбит/с, PSNR=34.362 дБ, уменьшение=37.38x
|
||||||
|
candidate_320x180_gray_1fps_q35: 320x180, 1 кадр/с, grayscale, Q=35, кадров=21, payload=37.265 кбит/с, PSNR=34.035 дБ, уменьшение=80.54x
|
||||||
|
candidate_320x180_gray_0_5fps_q35: 320x180, 0.5 кадр/с, grayscale, Q=35, кадров=11, payload=19.309 кбит/с, PSNR=34.166 дБ, уменьшение=155.43x
|
||||||
|
candidate_320x180_gray_0_2fps_q35: 320x180, 0.2 кадр/с, grayscale, Q=35, кадров=5, payload=9.098 кбит/с, PSNR=33.741 дБ, уменьшение=329.87x
|
||||||
|
candidate_160x90_gray_1fps_q30: 160x90, 1 кадр/с, grayscale, Q=30, кадров=21, payload=12.614 кбит/с, PSNR=32.031 дБ, уменьшение=237.94x
|
||||||
|
|
||||||
|
Candidate-профили с payload bitrate не более 50 кбит/с:
|
||||||
|
candidate_320x180_gray_1fps_q35: 320x180, 1 кадр/с, grayscale, Q=35, кадров=21, payload=37.265 кбит/с, PSNR=34.035 дБ, уменьшение=80.54x
|
||||||
|
candidate_320x180_gray_0_5fps_q35: 320x180, 0.5 кадр/с, grayscale, Q=35, кадров=11, payload=19.309 кбит/с, PSNR=34.166 дБ, уменьшение=155.43x
|
||||||
|
candidate_320x180_gray_0_2fps_q35: 320x180, 0.2 кадр/с, grayscale, Q=35, кадров=5, payload=9.098 кбит/с, PSNR=33.741 дБ, уменьшение=329.87x
|
||||||
|
candidate_160x90_gray_1fps_q30: 160x90, 1 кадр/с, grayscale, Q=30, кадров=21, payload=12.614 кбит/с, PSNR=32.031 дБ, уменьшение=237.94x
|
||||||
|
|
||||||
|
Candidate-профили с payload bitrate не более 20 кбит/с:
|
||||||
|
candidate_320x180_gray_0_5fps_q35: 320x180, 0.5 кадр/с, grayscale, Q=35, кадров=11, payload=19.309 кбит/с, PSNR=34.166 дБ, уменьшение=155.43x
|
||||||
|
candidate_320x180_gray_0_2fps_q35: 320x180, 0.2 кадр/с, grayscale, Q=35, кадров=5, payload=9.098 кбит/с, PSNR=33.741 дБ, уменьшение=329.87x
|
||||||
|
candidate_160x90_gray_1fps_q30: 160x90, 1 кадр/с, grayscale, Q=30, кадров=21, payload=12.614 кбит/с, PSNR=32.031 дБ, уменьшение=237.94x
|
||||||
|
|
||||||
|
Candidate-профили с payload bitrate не более 10 кбит/с:
|
||||||
|
candidate_320x180_gray_0_2fps_q35: 320x180, 0.2 кадр/с, grayscale, Q=35, кадров=5, payload=9.098 кбит/с, PSNR=33.741 дБ, уменьшение=329.87x
|
||||||
|
|
||||||
|
Профиль с минимальным измеренным битрейтом:
|
||||||
|
candidate_320x180_gray_0_2fps_q35: 320x180, 0.2 кадр/с, grayscale, Q=35, кадров=5, payload=9.098 кбит/с, PSNR=33.741 дБ, уменьшение=329.87x
|
||||||
|
|
||||||
|
Автоматические метрики не заменяют визуальную оценку пригодности изображения для управления ровером.
|
||||||
|
Сравнительное изображение: data\processed\lab026\lab026_candidate_profiles.png
|
||||||
|
Следующий шаг: пользователь должен визуально выбрать пригодные candidate-профили.
|
||||||
BIN
data/processed/lab026b/lab026b_bitrate_vs_resolution.png
Normal file
|
After Width: | Height: | Size: 199 KiB |
BIN
data/processed/lab026b/lab026b_codec_comparison.png
Normal file
|
After Width: | Height: | Size: 103 KiB |
BIN
data/processed/lab026b/lab026b_equal_bitrate_candidates.png
Normal file
|
After Width: | Height: | Size: 1.3 MiB |
31
data/processed/lab026b/lab026b_profiles.csv
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
experiment,profile_name,mode,width,height,pixel_count,target_fps,actual_fps,bits_per_pixel_before_compression,maximum_gray_levels,maximum_colors,selected_frames,total_payload_bytes,mean_frame_bytes,median_frame_bytes,p95_frame_bytes,max_frame_bytes,payload_bitrate_bps,payload_bitrate_kbps,baseline_bitrate_kbps,difference_from_baseline_kbps,percent_of_baseline_bitrate,compression_ratio_from_unpacked_source,mean_psnr_db,header_bytes_per_frame,palette_bytes_per_frame,notes
|
||||||
|
four_bit_resolution_sweep,320x180_gray8_jpeg_2fps,gray8_jpeg,320,180,57600,2.000000,2.022472,8,256,0,42,208403,4961.976,4965.000,5224.700,5400,80283.660,80.283660,80.283660,-0.000000,100.000000,11.608278,34.362114,0,0,"Grayscale 8 bit, JPEG quality 40."
|
||||||
|
four_bit_resolution_sweep,320x180_gray4_jpeg_2fps,gray4_jpeg,320,180,57600,2.000000,2.022472,4,16,0,42,229518,5464.714,5466.000,5727.250,5822,88417.849,88.417849,80.283660,8.134189,110.131812,10.540350,32.588941,0,0,"Grayscale quantized to 16 levels, restored to uint8, JPEG quality 40."
|
||||||
|
four_bit_resolution_sweep,320x180_gray4_packed_zlib_2fps,gray4_packed_zlib,320,180,57600,2.000000,2.022472,4,16,0,42,441074,10501.762,10444.000,11194.300,12317,169916.148,169.916148,80.283660,89.632488,211.644745,5.484794,34.397012,16,0,"Two 4-bit grayscale indices per byte, zlib level 9, 16-byte frame header."
|
||||||
|
four_bit_resolution_sweep,320x180_color16_png_2fps,color16_png,320,180,57600,2.000000,2.022472,4,0,16,42,371520,8845.714,8607.500,10578.350,10794,143121.669,143.121669,80.283660,62.838009,178.269986,19.534884,25.384724,0,0,"Pillow palette image, maximum 16 colors, no dithering, optimized indexed PNG."
|
||||||
|
four_bit_resolution_sweep,320x180_color16_packed_zlib_2fps,color16_packed_zlib,320,180,57600,2.000000,2.022472,4,0,16,42,364892,8687.905,8452.000,10414.800,10652,140568.347,140.568347,80.283660,60.284687,175.089609,19.889721,25.384724,16,48,"Two 4-bit palette indices per byte, zlib level 9, 16-byte header and fixed 48-byte palette."
|
||||||
|
four_bit_resolution_sweep,400x225_gray8_jpeg_2fps,gray8_jpeg,400,225,90000,2.000000,2.022472,8,256,0,42,297273,7077.929,7063.500,7473.000,7841,114519.294,114.519294,80.283660,34.235634,142.643340,12.715585,34.942886,0,0,"Grayscale 8 bit, JPEG quality 40."
|
||||||
|
four_bit_resolution_sweep,400x225_gray4_jpeg_2fps,gray4_jpeg,400,225,90000,2.000000,2.022472,4,16,0,42,332268,7911.143,7920.500,8353.700,8554,128000.514,128.000514,80.283660,47.716854,159.435324,11.376359,32.883090,0,0,"Grayscale quantized to 16 levels, restored to uint8, JPEG quality 40."
|
||||||
|
four_bit_resolution_sweep,400x225_gray4_packed_zlib_2fps,gray4_packed_zlib,400,225,90000,2.000000,2.022472,4,16,0,42,636862,15163.381,15120.500,16266.050,18356,245340.096,245.340096,80.283660,165.056436,305.591569,5.935352,34.399552,16,0,"Two 4-bit grayscale indices per byte, zlib level 9, 16-byte frame header."
|
||||||
|
four_bit_resolution_sweep,400x225_color16_png_2fps,color16_png,400,225,90000,2.000000,2.022472,4,0,16,42,528261,12577.643,12153.000,15191.650,16128,203503.435,203.503435,80.283660,123.219775,253.480515,21.466661,25.344339,0,0,"Pillow palette image, maximum 16 colors, no dithering, optimized indexed PNG."
|
||||||
|
four_bit_resolution_sweep,400x225_color16_packed_zlib_2fps,color16_packed_zlib,400,225,90000,2.000000,2.022472,4,0,16,42,520725,12398.214,11977.000,15015.100,15966,200600.321,200.600321,80.283660,120.316661,249.864444,21.777330,25.344339,16,48,"Two 4-bit palette indices per byte, zlib level 9, 16-byte header and fixed 48-byte palette."
|
||||||
|
four_bit_resolution_sweep,448x252_gray8_jpeg_2fps,gray8_jpeg,448,252,112896,2.000000,2.022472,8,256,0,42,353578,8418.524,8413.000,8885.950,9512,136209.823,136.209823,80.283660,55.926163,169.660705,13.410427,35.301071,0,0,"Grayscale 8 bit, JPEG quality 40."
|
||||||
|
four_bit_resolution_sweep,448x252_gray4_jpeg_2fps,gray4_jpeg,448,252,112896,2.000000,2.022472,4,16,0,42,397126,9455.381,9467.500,9996.400,10450,152985.939,152.985939,80.283660,72.702279,190.556757,11.939868,33.060439,0,0,"Grayscale quantized to 16 levels, restored to uint8, JPEG quality 40."
|
||||||
|
four_bit_resolution_sweep,448x252_gray4_packed_zlib_2fps,gray4_packed_zlib,448,252,112896,2.000000,2.022472,4,16,0,42,762082,18144.810,18111.500,19504.750,22433,293578.941,293.578941,80.283660,213.295281,365.677076,6.221945,34.399841,16,0,"Two 4-bit grayscale indices per byte, zlib level 9, 16-byte frame header."
|
||||||
|
four_bit_resolution_sweep,448x252_color16_png_2fps,color16_png,448,252,112896,2.000000,2.022472,4,0,16,42,626516,14917.048,14409.500,18239.600,18695,241354.478,241.354478,80.283660,161.070818,300.627149,22.704761,25.369963,0,0,"Pillow palette image, maximum 16 colors, no dithering, optimized indexed PNG."
|
||||||
|
four_bit_resolution_sweep,448x252_color16_packed_zlib_2fps,color16_packed_zlib,448,252,112896,2.000000,2.022472,4,0,16,42,618164,14718.190,14221.500,18022.000,18517,238137.014,238.137014,80.283660,157.853354,296.619529,23.011524,25.369963,16,48,"Two 4-bit palette indices per byte, zlib level 9, 16-byte header and fixed 48-byte palette."
|
||||||
|
four_bit_resolution_sweep,480x270_gray8_jpeg_2fps,gray8_jpeg,480,270,129600,2.000000,2.022472,8,256,0,42,393752,9375.048,9365.500,9919.950,10678,151686.164,151.686164,80.283660,71.402504,188.937779,13.823930,35.412999,0,0,"Grayscale 8 bit, JPEG quality 40."
|
||||||
|
four_bit_resolution_sweep,480x270_gray4_jpeg_2fps,gray4_jpeg,480,270,129600,2.000000,2.022472,4,16,0,42,443419,10557.595,10575.500,11152.550,11737,170819.518,170.819518,80.283660,90.535858,212.769969,12.275523,33.099458,0,0,"Grayscale quantized to 16 levels, restored to uint8, JPEG quality 40."
|
||||||
|
four_bit_resolution_sweep,480x270_gray4_packed_zlib_2fps,gray4_packed_zlib,480,270,129600,2.000000,2.022472,4,16,0,42,854354,20341.762,20276.500,21857.900,25369,329125.136,329.125136,80.283660,248.841476,409.952830,6.371130,34.401420,16,0,"Two 4-bit grayscale indices per byte, zlib level 9, 16-byte frame header."
|
||||||
|
four_bit_resolution_sweep,480x270_color16_png_2fps,color16_png,480,270,129600,2.000000,2.022472,4,0,16,42,701871,16711.214,16249.500,20469.850,21005,270383.692,270.383692,80.283660,190.100032,336.785458,23.265814,25.368870,0,0,"Pillow palette image, maximum 16 colors, no dithering, optimized indexed PNG."
|
||||||
|
four_bit_resolution_sweep,480x270_color16_packed_zlib_2fps,color16_packed_zlib,480,270,129600,2.000000,2.022472,4,0,16,42,693190,16504.524,16007.500,20249.750,20809,267039.486,267.039486,80.283660,186.755826,332.619971,23.557178,25.368870,16,48,"Two 4-bit palette indices per byte, zlib level 9, 16-byte header and fixed 48-byte palette."
|
||||||
|
four_bit_resolution_sweep,560x315_gray8_jpeg_2fps,gray8_jpeg,560,315,176400,2.000000,2.022472,8,256,0,42,507535,12084.167,12068.500,12860.900,13999,195519.101,195.519101,80.283660,115.235441,243.535361,14.597614,35.954946,0,0,"Grayscale 8 bit, JPEG quality 40."
|
||||||
|
four_bit_resolution_sweep,560x315_gray4_jpeg_2fps,gray4_jpeg,560,315,176400,2.000000,2.022472,4,16,0,42,575350,13698.810,13674.500,14558.450,15458,221643.660,221.643660,80.283660,141.360000,276.075679,12.877031,33.337152,0,0,"Grayscale quantized to 16 levels, restored to uint8, JPEG quality 40."
|
||||||
|
four_bit_resolution_sweep,560x315_gray4_packed_zlib_2fps,gray4_packed_zlib,560,315,176400,2.000000,2.022472,4,16,0,42,1093024,26024.381,25851.500,28055.650,33171,421068.636,421.068636,80.283660,340.784976,524.476133,6.778259,34.403027,16,0,"Two 4-bit grayscale indices per byte, zlib level 9, 16-byte frame header."
|
||||||
|
four_bit_resolution_sweep,560x315_color16_png_2fps,color16_png,560,315,176400,2.000000,2.022472,4,0,16,42,894967,21308.738,20851.500,25906.100,27345,344770.594,344.770594,80.283660,264.486934,429.440554,24.834882,25.323519,0,0,"Pillow palette image, maximum 16 colors, no dithering, optimized indexed PNG."
|
||||||
|
four_bit_resolution_sweep,560x315_color16_packed_zlib_2fps,color16_packed_zlib,560,315,176400,2.000000,2.022472,4,0,16,42,885156,21075.143,20622.000,25686.650,27166,340991.075,340.991075,80.283660,260.707415,424.732848,25.110150,25.323519,16,48,"Two 4-bit palette indices per byte, zlib level 9, 16-byte header and fixed 48-byte palette."
|
||||||
|
four_bit_resolution_sweep,640x360_gray8_jpeg_2fps,gray8_jpeg,640,360,230400,2.000000,2.022472,8,256,0,42,639531,15226.929,15187.500,16381.750,18122,246368.283,246.368283,80.283660,166.084623,306.872261,15.131088,35.588581,0,0,"Grayscale 8 bit, JPEG quality 40."
|
||||||
|
four_bit_resolution_sweep,640x360_gray4_jpeg_2fps,gray4_jpeg,640,360,230400,2.000000,2.022472,4,16,0,42,726335,17293.690,17220.500,18557.350,19938,279808.026,279.808026,80.283660,199.524366,348.524252,13.322778,33.048695,0,0,"Grayscale quantized to 16 levels, restored to uint8, JPEG quality 40."
|
||||||
|
four_bit_resolution_sweep,640x360_gray4_packed_zlib_2fps,gray4_packed_zlib,640,360,230400,2.000000,2.022472,4,16,0,42,1394769,33208.786,32974.500,35959.800,43514,537310.690,537.310690,80.283660,457.027030,669.265315,6.937923,34.404228,16,0,"Two 4-bit grayscale indices per byte, zlib level 9, 16-byte frame header."
|
||||||
|
four_bit_resolution_sweep,640x360_color16_png_2fps,color16_png,640,360,230400,2.000000,2.022472,4,0,16,42,1140488,27154.476,26267.500,33424.950,36017,439353.323,439.353323,80.283660,359.069663,547.251237,25.454367,25.259621,0,0,"Pillow palette image, maximum 16 colors, no dithering, optimized indexed PNG."
|
||||||
|
four_bit_resolution_sweep,640x360_color16_packed_zlib_2fps,color16_packed_zlib,640,360,230400,2.000000,2.022472,4,0,16,42,1128711,26874.071,25978.500,33021.450,35603,434816.437,434.816437,80.283660,354.532777,541.600167,25.719958,25.259621,16,48,"Two 4-bit palette indices per byte, zlib level 9, 16-byte header and fixed 48-byte palette."
|
||||||
|
90
data/processed/lab026b/lab026b_report.txt
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
Lab026B. Увеличение разрешения кадра за счёт глубины цвета 4 бита
|
||||||
|
|
||||||
|
Цель: проверить увеличение разрешения при битрейте, близком к контрольным 80.283660 кбит/с.
|
||||||
|
Исходное видео: data\raw\lab026_rover_source.mp4
|
||||||
|
Размер исходного видео: 7790985 байт
|
||||||
|
Исходное разрешение: 1280×720
|
||||||
|
Исходный FPS: 30.000000
|
||||||
|
Число кадров: 623
|
||||||
|
Длительность: 20.766667 с
|
||||||
|
|
||||||
|
4-битная яркость: индекс 0...15, то есть 16 уровней серого на пиксель.
|
||||||
|
4-битный индексированный цвет: один индекс 0...15 на пиксель и палитра максимум из 16 RGB-цветов.
|
||||||
|
Это не RGB444: RGB444 требует по 4 бита на каждый из трёх каналов, то есть 12 бит на пиксель.
|
||||||
|
|
||||||
|
Режимы:
|
||||||
|
gray8_jpeg — контрольный grayscale JPEG Q40.
|
||||||
|
gray4_jpeg — 16 уровней серого, восстановление uint8, JPEG Q40.
|
||||||
|
gray4_packed_zlib — 4-битные индексы, два на байт, zlib level 9 и заголовок 16 байт.
|
||||||
|
color16_png — палитра максимум 16 цветов, без дизеринга, индексированный PNG в памяти.
|
||||||
|
color16_packed_zlib — 4-битные индексы, zlib level 9, заголовок 16 байт и фиксированная палитра 48 байт.
|
||||||
|
|
||||||
|
Контрольный baseline: 80.283660 кбит/с.
|
||||||
|
CRC, FEC, радиозаголовки и пакетирование пока не учтены.
|
||||||
|
Статические метрики не учитывают задержку видеоканала.
|
||||||
|
|
||||||
|
Полные результаты 30 профилей:
|
||||||
|
320x180_gray8_jpeg_2fps: mode=gray8_jpeg, 320x180, frames=42, actual_fps=2.022472, total=208403 bytes, mean=4961.976, median=4965.000, p95=5224.700, max=5400, bitrate=80.283660 kbit/s, baseline_diff=-0.000000, baseline_percent=100.000%, compression=11.608x, PSNR=34.362114 dB
|
||||||
|
320x180_gray4_jpeg_2fps: mode=gray4_jpeg, 320x180, frames=42, actual_fps=2.022472, total=229518 bytes, mean=5464.714, median=5466.000, p95=5727.250, max=5822, bitrate=88.417849 kbit/s, baseline_diff=8.134189, baseline_percent=110.132%, compression=10.540x, PSNR=32.588941 dB
|
||||||
|
320x180_gray4_packed_zlib_2fps: mode=gray4_packed_zlib, 320x180, frames=42, actual_fps=2.022472, total=441074 bytes, mean=10501.762, median=10444.000, p95=11194.300, max=12317, bitrate=169.916148 kbit/s, baseline_diff=89.632488, baseline_percent=211.645%, compression=5.485x, PSNR=34.397012 dB
|
||||||
|
320x180_color16_png_2fps: mode=color16_png, 320x180, frames=42, actual_fps=2.022472, total=371520 bytes, mean=8845.714, median=8607.500, p95=10578.350, max=10794, bitrate=143.121669 kbit/s, baseline_diff=62.838009, baseline_percent=178.270%, compression=19.535x, PSNR=25.384724 dB
|
||||||
|
320x180_color16_packed_zlib_2fps: mode=color16_packed_zlib, 320x180, frames=42, actual_fps=2.022472, total=364892 bytes, mean=8687.905, median=8452.000, p95=10414.800, max=10652, bitrate=140.568347 kbit/s, baseline_diff=60.284687, baseline_percent=175.090%, compression=19.890x, PSNR=25.384724 dB
|
||||||
|
400x225_gray8_jpeg_2fps: mode=gray8_jpeg, 400x225, frames=42, actual_fps=2.022472, total=297273 bytes, mean=7077.929, median=7063.500, p95=7473.000, max=7841, bitrate=114.519294 kbit/s, baseline_diff=34.235634, baseline_percent=142.643%, compression=12.716x, PSNR=34.942886 dB
|
||||||
|
400x225_gray4_jpeg_2fps: mode=gray4_jpeg, 400x225, frames=42, actual_fps=2.022472, total=332268 bytes, mean=7911.143, median=7920.500, p95=8353.700, max=8554, bitrate=128.000514 kbit/s, baseline_diff=47.716854, baseline_percent=159.435%, compression=11.376x, PSNR=32.883090 dB
|
||||||
|
400x225_gray4_packed_zlib_2fps: mode=gray4_packed_zlib, 400x225, frames=42, actual_fps=2.022472, total=636862 bytes, mean=15163.381, median=15120.500, p95=16266.050, max=18356, bitrate=245.340096 kbit/s, baseline_diff=165.056436, baseline_percent=305.592%, compression=5.935x, PSNR=34.399552 dB
|
||||||
|
400x225_color16_png_2fps: mode=color16_png, 400x225, frames=42, actual_fps=2.022472, total=528261 bytes, mean=12577.643, median=12153.000, p95=15191.650, max=16128, bitrate=203.503435 kbit/s, baseline_diff=123.219775, baseline_percent=253.481%, compression=21.467x, PSNR=25.344339 dB
|
||||||
|
400x225_color16_packed_zlib_2fps: mode=color16_packed_zlib, 400x225, frames=42, actual_fps=2.022472, total=520725 bytes, mean=12398.214, median=11977.000, p95=15015.100, max=15966, bitrate=200.600321 kbit/s, baseline_diff=120.316661, baseline_percent=249.864%, compression=21.777x, PSNR=25.344339 dB
|
||||||
|
448x252_gray8_jpeg_2fps: mode=gray8_jpeg, 448x252, frames=42, actual_fps=2.022472, total=353578 bytes, mean=8418.524, median=8413.000, p95=8885.950, max=9512, bitrate=136.209823 kbit/s, baseline_diff=55.926163, baseline_percent=169.661%, compression=13.410x, PSNR=35.301071 dB
|
||||||
|
448x252_gray4_jpeg_2fps: mode=gray4_jpeg, 448x252, frames=42, actual_fps=2.022472, total=397126 bytes, mean=9455.381, median=9467.500, p95=9996.400, max=10450, bitrate=152.985939 kbit/s, baseline_diff=72.702279, baseline_percent=190.557%, compression=11.940x, PSNR=33.060439 dB
|
||||||
|
448x252_gray4_packed_zlib_2fps: mode=gray4_packed_zlib, 448x252, frames=42, actual_fps=2.022472, total=762082 bytes, mean=18144.810, median=18111.500, p95=19504.750, max=22433, bitrate=293.578941 kbit/s, baseline_diff=213.295281, baseline_percent=365.677%, compression=6.222x, PSNR=34.399841 dB
|
||||||
|
448x252_color16_png_2fps: mode=color16_png, 448x252, frames=42, actual_fps=2.022472, total=626516 bytes, mean=14917.048, median=14409.500, p95=18239.600, max=18695, bitrate=241.354478 kbit/s, baseline_diff=161.070818, baseline_percent=300.627%, compression=22.705x, PSNR=25.369963 dB
|
||||||
|
448x252_color16_packed_zlib_2fps: mode=color16_packed_zlib, 448x252, frames=42, actual_fps=2.022472, total=618164 bytes, mean=14718.190, median=14221.500, p95=18022.000, max=18517, bitrate=238.137014 kbit/s, baseline_diff=157.853354, baseline_percent=296.620%, compression=23.012x, PSNR=25.369963 dB
|
||||||
|
480x270_gray8_jpeg_2fps: mode=gray8_jpeg, 480x270, frames=42, actual_fps=2.022472, total=393752 bytes, mean=9375.048, median=9365.500, p95=9919.950, max=10678, bitrate=151.686164 kbit/s, baseline_diff=71.402504, baseline_percent=188.938%, compression=13.824x, PSNR=35.412999 dB
|
||||||
|
480x270_gray4_jpeg_2fps: mode=gray4_jpeg, 480x270, frames=42, actual_fps=2.022472, total=443419 bytes, mean=10557.595, median=10575.500, p95=11152.550, max=11737, bitrate=170.819518 kbit/s, baseline_diff=90.535858, baseline_percent=212.770%, compression=12.276x, PSNR=33.099458 dB
|
||||||
|
480x270_gray4_packed_zlib_2fps: mode=gray4_packed_zlib, 480x270, frames=42, actual_fps=2.022472, total=854354 bytes, mean=20341.762, median=20276.500, p95=21857.900, max=25369, bitrate=329.125136 kbit/s, baseline_diff=248.841476, baseline_percent=409.953%, compression=6.371x, PSNR=34.401420 dB
|
||||||
|
480x270_color16_png_2fps: mode=color16_png, 480x270, frames=42, actual_fps=2.022472, total=701871 bytes, mean=16711.214, median=16249.500, p95=20469.850, max=21005, bitrate=270.383692 kbit/s, baseline_diff=190.100032, baseline_percent=336.785%, compression=23.266x, PSNR=25.368870 dB
|
||||||
|
480x270_color16_packed_zlib_2fps: mode=color16_packed_zlib, 480x270, frames=42, actual_fps=2.022472, total=693190 bytes, mean=16504.524, median=16007.500, p95=20249.750, max=20809, bitrate=267.039486 kbit/s, baseline_diff=186.755826, baseline_percent=332.620%, compression=23.557x, PSNR=25.368870 dB
|
||||||
|
560x315_gray8_jpeg_2fps: mode=gray8_jpeg, 560x315, frames=42, actual_fps=2.022472, total=507535 bytes, mean=12084.167, median=12068.500, p95=12860.900, max=13999, bitrate=195.519101 kbit/s, baseline_diff=115.235441, baseline_percent=243.535%, compression=14.598x, PSNR=35.954946 dB
|
||||||
|
560x315_gray4_jpeg_2fps: mode=gray4_jpeg, 560x315, frames=42, actual_fps=2.022472, total=575350 bytes, mean=13698.810, median=13674.500, p95=14558.450, max=15458, bitrate=221.643660 kbit/s, baseline_diff=141.360000, baseline_percent=276.076%, compression=12.877x, PSNR=33.337152 dB
|
||||||
|
560x315_gray4_packed_zlib_2fps: mode=gray4_packed_zlib, 560x315, frames=42, actual_fps=2.022472, total=1093024 bytes, mean=26024.381, median=25851.500, p95=28055.650, max=33171, bitrate=421.068636 kbit/s, baseline_diff=340.784976, baseline_percent=524.476%, compression=6.778x, PSNR=34.403027 dB
|
||||||
|
560x315_color16_png_2fps: mode=color16_png, 560x315, frames=42, actual_fps=2.022472, total=894967 bytes, mean=21308.738, median=20851.500, p95=25906.100, max=27345, bitrate=344.770594 kbit/s, baseline_diff=264.486934, baseline_percent=429.441%, compression=24.835x, PSNR=25.323519 dB
|
||||||
|
560x315_color16_packed_zlib_2fps: mode=color16_packed_zlib, 560x315, frames=42, actual_fps=2.022472, total=885156 bytes, mean=21075.143, median=20622.000, p95=25686.650, max=27166, bitrate=340.991075 kbit/s, baseline_diff=260.707415, baseline_percent=424.733%, compression=25.110x, PSNR=25.323519 dB
|
||||||
|
640x360_gray8_jpeg_2fps: mode=gray8_jpeg, 640x360, frames=42, actual_fps=2.022472, total=639531 bytes, mean=15226.929, median=15187.500, p95=16381.750, max=18122, bitrate=246.368283 kbit/s, baseline_diff=166.084623, baseline_percent=306.872%, compression=15.131x, PSNR=35.588581 dB
|
||||||
|
640x360_gray4_jpeg_2fps: mode=gray4_jpeg, 640x360, frames=42, actual_fps=2.022472, total=726335 bytes, mean=17293.690, median=17220.500, p95=18557.350, max=19938, bitrate=279.808026 kbit/s, baseline_diff=199.524366, baseline_percent=348.524%, compression=13.323x, PSNR=33.048695 dB
|
||||||
|
640x360_gray4_packed_zlib_2fps: mode=gray4_packed_zlib, 640x360, frames=42, actual_fps=2.022472, total=1394769 bytes, mean=33208.786, median=32974.500, p95=35959.800, max=43514, bitrate=537.310690 kbit/s, baseline_diff=457.027030, baseline_percent=669.265%, compression=6.938x, PSNR=34.404228 dB
|
||||||
|
640x360_color16_png_2fps: mode=color16_png, 640x360, frames=42, actual_fps=2.022472, total=1140488 bytes, mean=27154.476, median=26267.500, p95=33424.950, max=36017, bitrate=439.353323 kbit/s, baseline_diff=359.069663, baseline_percent=547.251%, compression=25.454x, PSNR=25.259621 dB
|
||||||
|
640x360_color16_packed_zlib_2fps: mode=color16_packed_zlib, 640x360, frames=42, actual_fps=2.022472, total=1128711 bytes, mean=26874.071, median=25978.500, p95=33021.450, max=35603, bitrate=434.816437 kbit/s, baseline_diff=354.532777, baseline_percent=541.600%, compression=25.720x, PSNR=25.259621 dB
|
||||||
|
|
||||||
|
Профили 70–90 кбит/с:
|
||||||
|
320x180_gray8_jpeg_2fps: mode=gray8_jpeg, 320x180, frames=42, actual_fps=2.022472, total=208403 bytes, mean=4961.976, median=4965.000, p95=5224.700, max=5400, bitrate=80.283660 kbit/s, baseline_diff=-0.000000, baseline_percent=100.000%, compression=11.608x, PSNR=34.362114 dB
|
||||||
|
320x180_gray4_jpeg_2fps: mode=gray4_jpeg, 320x180, frames=42, actual_fps=2.022472, total=229518 bytes, mean=5464.714, median=5466.000, p95=5727.250, max=5822, bitrate=88.417849 kbit/s, baseline_diff=8.134189, baseline_percent=110.132%, compression=10.540x, PSNR=32.588941 dB
|
||||||
|
|
||||||
|
Профили до baseline:
|
||||||
|
320x180_gray8_jpeg_2fps: mode=gray8_jpeg, 320x180, frames=42, actual_fps=2.022472, total=208403 bytes, mean=4961.976, median=4965.000, p95=5224.700, max=5400, bitrate=80.283660 kbit/s, baseline_diff=-0.000000, baseline_percent=100.000%, compression=11.608x, PSNR=34.362114 dB
|
||||||
|
|
||||||
|
Профили до 100 кбит/с:
|
||||||
|
320x180_gray8_jpeg_2fps: mode=gray8_jpeg, 320x180, frames=42, actual_fps=2.022472, total=208403 bytes, mean=4961.976, median=4965.000, p95=5224.700, max=5400, bitrate=80.283660 kbit/s, baseline_diff=-0.000000, baseline_percent=100.000%, compression=11.608x, PSNR=34.362114 dB
|
||||||
|
320x180_gray4_jpeg_2fps: mode=gray4_jpeg, 320x180, frames=42, actual_fps=2.022472, total=229518 bytes, mean=5464.714, median=5466.000, p95=5727.250, max=5822, bitrate=88.417849 kbit/s, baseline_diff=8.134189, baseline_percent=110.132%, compression=10.540x, PSNR=32.588941 dB
|
||||||
|
|
||||||
|
Цветные color16-профили до 100 кбит/с:
|
||||||
|
Нет.
|
||||||
|
|
||||||
|
Профили больше 320x180 и не выше baseline:
|
||||||
|
Нет.
|
||||||
|
|
||||||
|
Максимальное разрешение до baseline:
|
||||||
|
320x180_gray8_jpeg_2fps: mode=gray8_jpeg, 320x180, frames=42, actual_fps=2.022472, total=208403 bytes, mean=4961.976, median=4965.000, p95=5224.700, max=5400, bitrate=80.283660 kbit/s, baseline_diff=-0.000000, baseline_percent=100.000%, compression=11.608x, PSNR=34.362114 dB
|
||||||
|
|
||||||
|
Максимальное разрешение до 100 кбит/с:
|
||||||
|
320x180_gray8_jpeg_2fps: mode=gray8_jpeg, 320x180, frames=42, actual_fps=2.022472, total=208403 bytes, mean=4961.976, median=4965.000, p95=5224.700, max=5400, bitrate=80.283660 kbit/s, baseline_diff=-0.000000, baseline_percent=100.000%, compression=11.608x, PSNR=34.362114 dB
|
||||||
|
320x180_gray4_jpeg_2fps: mode=gray4_jpeg, 320x180, frames=42, actual_fps=2.022472, total=229518 bytes, mean=5464.714, median=5466.000, p95=5727.250, max=5822, bitrate=88.417849 kbit/s, baseline_diff=8.134189, baseline_percent=110.132%, compression=10.540x, PSNR=32.588941 dB
|
||||||
|
|
||||||
|
Сравнение gray4 и color16:
|
||||||
|
Минимальный gray4 bitrate: 88.417849 кбит/с.
|
||||||
|
Минимальный color16 bitrate: 140.568347 кбит/с.
|
||||||
|
Размер палитры packed color16: 48 байт на кадр.
|
||||||
|
Размер компактного заголовка packed-режимов: 16 байт на кадр.
|
||||||
|
|
||||||
|
Нельзя автоматически объявлять профиль безопасным для управления ровером по одной статической метрике.
|
||||||
|
Сравнительное изображение: data\processed\lab026b\lab026b_equal_bitrate_candidates.png
|
||||||
|
Следующий шаг: ручная визуальная оценка пользователем.
|
||||||
BIN
data/processed/lab027/lab027_bitrate_comparison.png
Normal file
|
After Width: | Height: | Size: 122 KiB |
BIN
data/processed/lab027/lab027_candidate_profiles.png
Normal file
|
After Width: | Height: | Size: 1.1 MiB |
10
data/processed/lab027/lab027_profiles.csv
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
profile_name,base_width,base_height,base_fps,base_quality,roi_enabled,roi_x_min,roi_y_min,roi_x_max,roi_y_max,roi_width,roi_height,roi_fps,roi_quality,source_duration_s,selected_base_frames,selected_roi_frames,actual_base_fps,actual_roi_fps,total_base_bytes,total_roi_bytes,total_payload_bytes,mean_base_frame_bytes,mean_roi_frame_bytes,p95_base_frame_bytes,p95_roi_frame_bytes,max_base_frame_bytes,max_roi_frame_bytes,base_bitrate_kbps,roi_bitrate_kbps,total_payload_bitrate_kbps,baseline_bitrate_kbps,difference_from_baseline_kbps,percent_of_baseline,mean_base_jpeg_psnr_db,mean_roi_jpeg_psnr_db,mean_reconstructed_full_psnr_db,mean_reconstructed_roi_psnr_db
|
||||||
|
baseline_320x180_gray_2fps_q40,320,180,2.000000,40,0,0.000000,0.000000,0.000000,0.000000,0,0,0.000000,0,20.766667,42,0,2.022472,0.000000,208368,0,208368,4961.143,0.000,5226.950,0.000,5390,0,80.270177,0.000000,80.270177,80.283660,-0.013483,99.983205,34.364165,,20.757991,
|
||||||
|
base240_1fps_q25_roi320_2fps_q35,240,135,1.000000,25,1,0.200000,0.420000,0.800000,1.000000,320,180,2.000000,35,20.766667,21,42,1.011236,2.022472,50858,191270,242128,2421.810,4554.048,2554.000,5044.500,2569,5172,19.592167,73.683467,93.275634,80.283660,12.991974,116.182588,32.370927,34.103745,19.657187,19.574377
|
||||||
|
base240_0_5fps_q25_roi320_2fps_q35,240,135,0.500000,25,1,0.200000,0.420000,0.800000,1.000000,320,180,2.000000,35,20.766667,11,42,0.529695,2.022472,26348,191270,217618,2395.273,4554.048,2561.500,5044.500,2569,5172,10.150112,73.683467,83.833579,80.283660,3.549919,104.421721,32.474572,34.103745,18.613817,19.574377
|
||||||
|
base160_1fps_q25_roi320_2fps_q35,160,90,1.000000,25,1,0.200000,0.420000,0.800000,1.000000,320,180,2.000000,35,20.766667,21,42,1.011236,2.022472,29882,191270,221152,1422.952,4554.048,1484.000,5044.500,1492,5172,11.511525,73.683467,85.194992,80.283660,4.911332,106.117474,31.458773,34.103745,19.701304,19.574377
|
||||||
|
base240_1fps_q25_roi448_1fps_q30,240,135,1.000000,25,1,0.200000,0.420000,0.800000,1.000000,448,252,1.000000,30,20.766667,21,21,1.011236,1.011236,50858,147787,198645,2421.810,7037.476,2554.000,7860.000,2569,8507,19.592167,56.932392,76.524559,80.283660,-3.759101,95.317725,32.370927,34.666932,19.098790,17.871555
|
||||||
|
base240_0_5fps_q25_roi448_1fps_q30,240,135,0.500000,25,1,0.200000,0.420000,0.800000,1.000000,448,252,1.000000,30,20.766667,11,21,0.529695,1.011236,26348,147787,174135,2395.273,7037.476,2561.500,7860.000,2569,8507,10.150112,56.932392,67.082504,80.283660,-13.201156,83.556858,32.474572,34.666932,18.113877,17.871555
|
||||||
|
base320_1fps_q30_roi320_1fps_q35,320,180,1.000000,30,1,0.200000,0.420000,0.800000,1.000000,320,180,1.000000,35,20.766667,21,21,1.011236,1.011236,87901,95367,183268,4185.762,4541.286,4391.000,5048.000,4537,5172,33.862343,36.738491,70.600835,80.283660,-9.682825,87.939233,33.539230,34.103514,19.121457,17.888190
|
||||||
|
base240_1fps_q20_roi320_1fps_q30,240,135,1.000000,20,1,0.200000,0.420000,0.800000,1.000000,320,180,1.000000,30,20.766667,21,21,1.011236,1.011236,44598,86458,131056,2123.714,4117.048,2231.000,4551.000,2251,4614,17.180610,33.306453,50.487063,80.283660,-29.796597,62.885851,31.643522,33.598412,19.107784,17.873870
|
||||||
|
base160_0_5fps_q20_roi320_2fps_q30,160,90,0.500000,20,1,0.200000,0.420000,0.800000,1.000000,320,180,2.000000,30,20.766667,11,42,0.529695,2.022472,13820,173455,187275,1256.364,4129.881,1326.000,4548.450,1347,4614,5.323917,66.820546,72.144462,80.283660,-8.139198,89.861950,30.823518,33.595566,18.664976,19.549559
|
||||||
|
BIN
data/processed/lab027/lab027_quality_comparison.png
Normal file
|
After Width: | Height: | Size: 106 KiB |
74
data/processed/lab027/lab027_report.txt
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
Lab027. Многомасштабная передача изображения: общий кадр и область интереса
|
||||||
|
|
||||||
|
Цель: проверить совместную передачу общего кадра и фиксированной ROI при payload около 80–100 кбит/с.
|
||||||
|
Исходное видео: data\raw\lab026_rover_source.mp4
|
||||||
|
Размер файла: 7790985 байт
|
||||||
|
Исходное разрешение: 1280×720
|
||||||
|
Исходный FPS: 30.000000
|
||||||
|
Число кадров: 623
|
||||||
|
Длительность: 20.766667 с
|
||||||
|
|
||||||
|
BASE: полный grayscale-кадр пониженного разрешения с собственной частотой и JPEG quality.
|
||||||
|
ROI: фиксированная центральная нижняя область исходного grayscale-кадра с независимыми разрешением, частотой и JPEG quality.
|
||||||
|
Нормализованные координаты ROI: x=0.20...0.80, y=0.42...1.00.
|
||||||
|
Пиксельные координаты ROI исходного кадра: x=256...1024, y=302...720.
|
||||||
|
|
||||||
|
Контрольный профиль: 320×180 grayscale, 2 fps, JPEG Q40.
|
||||||
|
Контрольный baseline: 80.283660 кбит/с.
|
||||||
|
|
||||||
|
Результаты всех девяти профилей:
|
||||||
|
baseline_320x180_gray_2fps_q40: BASE=320x180, 2.000 fps, Q40, base_frames=42, base=80.270177 kbit/s; ROI=0x0, 0.000 fps, Q0, roi_frames=0, roi=0.000000 kbit/s; total=80.270177 kbit/s, baseline_diff=-0.013483, baseline_percent=99.983%, BASE_JPEG_PSNR=34.364165 dB, ROI_JPEG_PSNR=нет dB, full_reconstructed_PSNR=20.757991 dB, ROI_reconstructed_PSNR=нет dB
|
||||||
|
base240_1fps_q25_roi320_2fps_q35: BASE=240x135, 1.000 fps, Q25, base_frames=21, base=19.592167 kbit/s; ROI=320x180, 2.000 fps, Q35, roi_frames=42, roi=73.683467 kbit/s; total=93.275634 kbit/s, baseline_diff=12.991974, baseline_percent=116.183%, BASE_JPEG_PSNR=32.370927 dB, ROI_JPEG_PSNR=34.103745 dB, full_reconstructed_PSNR=19.657187 dB, ROI_reconstructed_PSNR=19.574377 dB
|
||||||
|
base240_0_5fps_q25_roi320_2fps_q35: BASE=240x135, 0.500 fps, Q25, base_frames=11, base=10.150112 kbit/s; ROI=320x180, 2.000 fps, Q35, roi_frames=42, roi=73.683467 kbit/s; total=83.833579 kbit/s, baseline_diff=3.549919, baseline_percent=104.422%, BASE_JPEG_PSNR=32.474572 dB, ROI_JPEG_PSNR=34.103745 dB, full_reconstructed_PSNR=18.613817 dB, ROI_reconstructed_PSNR=19.574377 dB
|
||||||
|
base160_1fps_q25_roi320_2fps_q35: BASE=160x90, 1.000 fps, Q25, base_frames=21, base=11.511525 kbit/s; ROI=320x180, 2.000 fps, Q35, roi_frames=42, roi=73.683467 kbit/s; total=85.194992 kbit/s, baseline_diff=4.911332, baseline_percent=106.117%, BASE_JPEG_PSNR=31.458773 dB, ROI_JPEG_PSNR=34.103745 dB, full_reconstructed_PSNR=19.701304 dB, ROI_reconstructed_PSNR=19.574377 dB
|
||||||
|
base240_1fps_q25_roi448_1fps_q30: BASE=240x135, 1.000 fps, Q25, base_frames=21, base=19.592167 kbit/s; ROI=448x252, 1.000 fps, Q30, roi_frames=21, roi=56.932392 kbit/s; total=76.524559 kbit/s, baseline_diff=-3.759101, baseline_percent=95.318%, BASE_JPEG_PSNR=32.370927 dB, ROI_JPEG_PSNR=34.666932 dB, full_reconstructed_PSNR=19.098790 dB, ROI_reconstructed_PSNR=17.871555 dB
|
||||||
|
base240_0_5fps_q25_roi448_1fps_q30: BASE=240x135, 0.500 fps, Q25, base_frames=11, base=10.150112 kbit/s; ROI=448x252, 1.000 fps, Q30, roi_frames=21, roi=56.932392 kbit/s; total=67.082504 kbit/s, baseline_diff=-13.201156, baseline_percent=83.557%, BASE_JPEG_PSNR=32.474572 dB, ROI_JPEG_PSNR=34.666932 dB, full_reconstructed_PSNR=18.113877 dB, ROI_reconstructed_PSNR=17.871555 dB
|
||||||
|
base320_1fps_q30_roi320_1fps_q35: BASE=320x180, 1.000 fps, Q30, base_frames=21, base=33.862343 kbit/s; ROI=320x180, 1.000 fps, Q35, roi_frames=21, roi=36.738491 kbit/s; total=70.600835 kbit/s, baseline_diff=-9.682825, baseline_percent=87.939%, BASE_JPEG_PSNR=33.539230 dB, ROI_JPEG_PSNR=34.103514 dB, full_reconstructed_PSNR=19.121457 dB, ROI_reconstructed_PSNR=17.888190 dB
|
||||||
|
base240_1fps_q20_roi320_1fps_q30: BASE=240x135, 1.000 fps, Q20, base_frames=21, base=17.180610 kbit/s; ROI=320x180, 1.000 fps, Q30, roi_frames=21, roi=33.306453 kbit/s; total=50.487063 kbit/s, baseline_diff=-29.796597, baseline_percent=62.886%, BASE_JPEG_PSNR=31.643522 dB, ROI_JPEG_PSNR=33.598412 dB, full_reconstructed_PSNR=19.107784 dB, ROI_reconstructed_PSNR=17.873870 dB
|
||||||
|
base160_0_5fps_q20_roi320_2fps_q30: BASE=160x90, 0.500 fps, Q20, base_frames=11, base=5.323917 kbit/s; ROI=320x180, 2.000 fps, Q30, roi_frames=42, roi=66.820546 kbit/s; total=72.144462 kbit/s, baseline_diff=-8.139198, baseline_percent=89.862%, BASE_JPEG_PSNR=30.823518 dB, ROI_JPEG_PSNR=33.595566 dB, full_reconstructed_PSNR=18.664976 dB, ROI_reconstructed_PSNR=19.549559 dB
|
||||||
|
|
||||||
|
Профили до 80.283660 кбит/с:
|
||||||
|
baseline_320x180_gray_2fps_q40: BASE=320x180, 2.000 fps, Q40, base_frames=42, base=80.270177 kbit/s; ROI=0x0, 0.000 fps, Q0, roi_frames=0, roi=0.000000 kbit/s; total=80.270177 kbit/s, baseline_diff=-0.013483, baseline_percent=99.983%, BASE_JPEG_PSNR=34.364165 dB, ROI_JPEG_PSNR=нет dB, full_reconstructed_PSNR=20.757991 dB, ROI_reconstructed_PSNR=нет dB
|
||||||
|
base240_1fps_q25_roi448_1fps_q30: BASE=240x135, 1.000 fps, Q25, base_frames=21, base=19.592167 kbit/s; ROI=448x252, 1.000 fps, Q30, roi_frames=21, roi=56.932392 kbit/s; total=76.524559 kbit/s, baseline_diff=-3.759101, baseline_percent=95.318%, BASE_JPEG_PSNR=32.370927 dB, ROI_JPEG_PSNR=34.666932 dB, full_reconstructed_PSNR=19.098790 dB, ROI_reconstructed_PSNR=17.871555 dB
|
||||||
|
base240_0_5fps_q25_roi448_1fps_q30: BASE=240x135, 0.500 fps, Q25, base_frames=11, base=10.150112 kbit/s; ROI=448x252, 1.000 fps, Q30, roi_frames=21, roi=56.932392 kbit/s; total=67.082504 kbit/s, baseline_diff=-13.201156, baseline_percent=83.557%, BASE_JPEG_PSNR=32.474572 dB, ROI_JPEG_PSNR=34.666932 dB, full_reconstructed_PSNR=18.113877 dB, ROI_reconstructed_PSNR=17.871555 dB
|
||||||
|
base320_1fps_q30_roi320_1fps_q35: BASE=320x180, 1.000 fps, Q30, base_frames=21, base=33.862343 kbit/s; ROI=320x180, 1.000 fps, Q35, roi_frames=21, roi=36.738491 kbit/s; total=70.600835 kbit/s, baseline_diff=-9.682825, baseline_percent=87.939%, BASE_JPEG_PSNR=33.539230 dB, ROI_JPEG_PSNR=34.103514 dB, full_reconstructed_PSNR=19.121457 dB, ROI_reconstructed_PSNR=17.888190 dB
|
||||||
|
base240_1fps_q20_roi320_1fps_q30: BASE=240x135, 1.000 fps, Q20, base_frames=21, base=17.180610 kbit/s; ROI=320x180, 1.000 fps, Q30, roi_frames=21, roi=33.306453 kbit/s; total=50.487063 kbit/s, baseline_diff=-29.796597, baseline_percent=62.886%, BASE_JPEG_PSNR=31.643522 dB, ROI_JPEG_PSNR=33.598412 dB, full_reconstructed_PSNR=19.107784 dB, ROI_reconstructed_PSNR=17.873870 dB
|
||||||
|
base160_0_5fps_q20_roi320_2fps_q30: BASE=160x90, 0.500 fps, Q20, base_frames=11, base=5.323917 kbit/s; ROI=320x180, 2.000 fps, Q30, roi_frames=42, roi=66.820546 kbit/s; total=72.144462 kbit/s, baseline_diff=-8.139198, baseline_percent=89.862%, BASE_JPEG_PSNR=30.823518 dB, ROI_JPEG_PSNR=33.595566 dB, full_reconstructed_PSNR=18.664976 dB, ROI_reconstructed_PSNR=19.549559 dB
|
||||||
|
|
||||||
|
Профили до 100 кбит/с:
|
||||||
|
baseline_320x180_gray_2fps_q40: BASE=320x180, 2.000 fps, Q40, base_frames=42, base=80.270177 kbit/s; ROI=0x0, 0.000 fps, Q0, roi_frames=0, roi=0.000000 kbit/s; total=80.270177 kbit/s, baseline_diff=-0.013483, baseline_percent=99.983%, BASE_JPEG_PSNR=34.364165 dB, ROI_JPEG_PSNR=нет dB, full_reconstructed_PSNR=20.757991 dB, ROI_reconstructed_PSNR=нет dB
|
||||||
|
base240_1fps_q25_roi320_2fps_q35: BASE=240x135, 1.000 fps, Q25, base_frames=21, base=19.592167 kbit/s; ROI=320x180, 2.000 fps, Q35, roi_frames=42, roi=73.683467 kbit/s; total=93.275634 kbit/s, baseline_diff=12.991974, baseline_percent=116.183%, BASE_JPEG_PSNR=32.370927 dB, ROI_JPEG_PSNR=34.103745 dB, full_reconstructed_PSNR=19.657187 dB, ROI_reconstructed_PSNR=19.574377 dB
|
||||||
|
base240_0_5fps_q25_roi320_2fps_q35: BASE=240x135, 0.500 fps, Q25, base_frames=11, base=10.150112 kbit/s; ROI=320x180, 2.000 fps, Q35, roi_frames=42, roi=73.683467 kbit/s; total=83.833579 kbit/s, baseline_diff=3.549919, baseline_percent=104.422%, BASE_JPEG_PSNR=32.474572 dB, ROI_JPEG_PSNR=34.103745 dB, full_reconstructed_PSNR=18.613817 dB, ROI_reconstructed_PSNR=19.574377 dB
|
||||||
|
base160_1fps_q25_roi320_2fps_q35: BASE=160x90, 1.000 fps, Q25, base_frames=21, base=11.511525 kbit/s; ROI=320x180, 2.000 fps, Q35, roi_frames=42, roi=73.683467 kbit/s; total=85.194992 kbit/s, baseline_diff=4.911332, baseline_percent=106.117%, BASE_JPEG_PSNR=31.458773 dB, ROI_JPEG_PSNR=34.103745 dB, full_reconstructed_PSNR=19.701304 dB, ROI_reconstructed_PSNR=19.574377 dB
|
||||||
|
base240_1fps_q25_roi448_1fps_q30: BASE=240x135, 1.000 fps, Q25, base_frames=21, base=19.592167 kbit/s; ROI=448x252, 1.000 fps, Q30, roi_frames=21, roi=56.932392 kbit/s; total=76.524559 kbit/s, baseline_diff=-3.759101, baseline_percent=95.318%, BASE_JPEG_PSNR=32.370927 dB, ROI_JPEG_PSNR=34.666932 dB, full_reconstructed_PSNR=19.098790 dB, ROI_reconstructed_PSNR=17.871555 dB
|
||||||
|
base240_0_5fps_q25_roi448_1fps_q30: BASE=240x135, 0.500 fps, Q25, base_frames=11, base=10.150112 kbit/s; ROI=448x252, 1.000 fps, Q30, roi_frames=21, roi=56.932392 kbit/s; total=67.082504 kbit/s, baseline_diff=-13.201156, baseline_percent=83.557%, BASE_JPEG_PSNR=32.474572 dB, ROI_JPEG_PSNR=34.666932 dB, full_reconstructed_PSNR=18.113877 dB, ROI_reconstructed_PSNR=17.871555 dB
|
||||||
|
base320_1fps_q30_roi320_1fps_q35: BASE=320x180, 1.000 fps, Q30, base_frames=21, base=33.862343 kbit/s; ROI=320x180, 1.000 fps, Q35, roi_frames=21, roi=36.738491 kbit/s; total=70.600835 kbit/s, baseline_diff=-9.682825, baseline_percent=87.939%, BASE_JPEG_PSNR=33.539230 dB, ROI_JPEG_PSNR=34.103514 dB, full_reconstructed_PSNR=19.121457 dB, ROI_reconstructed_PSNR=17.888190 dB
|
||||||
|
base240_1fps_q20_roi320_1fps_q30: BASE=240x135, 1.000 fps, Q20, base_frames=21, base=17.180610 kbit/s; ROI=320x180, 1.000 fps, Q30, roi_frames=21, roi=33.306453 kbit/s; total=50.487063 kbit/s, baseline_diff=-29.796597, baseline_percent=62.886%, BASE_JPEG_PSNR=31.643522 dB, ROI_JPEG_PSNR=33.598412 dB, full_reconstructed_PSNR=19.107784 dB, ROI_reconstructed_PSNR=17.873870 dB
|
||||||
|
base160_0_5fps_q20_roi320_2fps_q30: BASE=160x90, 0.500 fps, Q20, base_frames=11, base=5.323917 kbit/s; ROI=320x180, 2.000 fps, Q30, roi_frames=42, roi=66.820546 kbit/s; total=72.144462 kbit/s, baseline_diff=-8.139198, baseline_percent=89.862%, BASE_JPEG_PSNR=30.823518 dB, ROI_JPEG_PSNR=33.595566 dB, full_reconstructed_PSNR=18.664976 dB, ROI_reconstructed_PSNR=19.549559 dB
|
||||||
|
|
||||||
|
Профиль с максимальным ROI-разрешением до 100 кбит/с:
|
||||||
|
base240_1fps_q25_roi448_1fps_q30: BASE=240x135, 1.000 fps, Q25, base_frames=21, base=19.592167 kbit/s; ROI=448x252, 1.000 fps, Q30, roi_frames=21, roi=56.932392 kbit/s; total=76.524559 kbit/s, baseline_diff=-3.759101, baseline_percent=95.318%, BASE_JPEG_PSNR=32.370927 dB, ROI_JPEG_PSNR=34.666932 dB, full_reconstructed_PSNR=19.098790 dB, ROI_reconstructed_PSNR=17.871555 dB
|
||||||
|
|
||||||
|
Профиль с максимальным ROI PSNR до 100 кбит/с:
|
||||||
|
base240_1fps_q25_roi320_2fps_q35: BASE=240x135, 1.000 fps, Q25, base_frames=21, base=19.592167 kbit/s; ROI=320x180, 2.000 fps, Q35, roi_frames=42, roi=73.683467 kbit/s; total=93.275634 kbit/s, baseline_diff=12.991974, baseline_percent=116.183%, BASE_JPEG_PSNR=32.370927 dB, ROI_JPEG_PSNR=34.103745 dB, full_reconstructed_PSNR=19.657187 dB, ROI_reconstructed_PSNR=19.574377 dB
|
||||||
|
|
||||||
|
Профиль с максимальным full-frame PSNR до 100 кбит/с:
|
||||||
|
baseline_320x180_gray_2fps_q40: BASE=320x180, 2.000 fps, Q40, base_frames=42, base=80.270177 kbit/s; ROI=0x0, 0.000 fps, Q0, roi_frames=0, roi=0.000000 kbit/s; total=80.270177 kbit/s, baseline_diff=-0.013483, baseline_percent=99.983%, BASE_JPEG_PSNR=34.364165 dB, ROI_JPEG_PSNR=нет dB, full_reconstructed_PSNR=20.757991 dB, ROI_reconstructed_PSNR=нет dB
|
||||||
|
|
||||||
|
Разделение битрейта BASE/ROI:
|
||||||
|
baseline_320x180_gray_2fps_q40: BASE=80.270177 кбит/с, ROI=0.000000 кбит/с, total=80.270177 кбит/с.
|
||||||
|
base240_1fps_q25_roi320_2fps_q35: BASE=19.592167 кбит/с, ROI=73.683467 кбит/с, total=93.275634 кбит/с.
|
||||||
|
base240_0_5fps_q25_roi320_2fps_q35: BASE=10.150112 кбит/с, ROI=73.683467 кбит/с, total=83.833579 кбит/с.
|
||||||
|
base160_1fps_q25_roi320_2fps_q35: BASE=11.511525 кбит/с, ROI=73.683467 кбит/с, total=85.194992 кбит/с.
|
||||||
|
base240_1fps_q25_roi448_1fps_q30: BASE=19.592167 кбит/с, ROI=56.932392 кбит/с, total=76.524559 кбит/с.
|
||||||
|
base240_0_5fps_q25_roi448_1fps_q30: BASE=10.150112 кбит/с, ROI=56.932392 кбит/с, total=67.082504 кбит/с.
|
||||||
|
base320_1fps_q30_roi320_1fps_q35: BASE=33.862343 кбит/с, ROI=36.738491 кбит/с, total=70.600835 кбит/с.
|
||||||
|
base240_1fps_q20_roi320_1fps_q30: BASE=17.180610 кбит/с, ROI=33.306453 кбит/с, total=50.487063 кбит/с.
|
||||||
|
base160_0_5fps_q20_roi320_2fps_q30: BASE=5.323917 кбит/с, ROI=66.820546 кбит/с, total=72.144462 кбит/с.
|
||||||
|
|
||||||
|
Фиксированная ROI не гарантирует попадания препятствия в область интереса.
|
||||||
|
PSNR не заменяет ручную оценку пригодности изображения.
|
||||||
|
Нельзя автоматически объявлять профиль безопасным для управления ровером.
|
||||||
|
Радиопротокол, радиозаголовки, CRC, FEC, фрагментация и повторные передачи не учтены.
|
||||||
|
Сравнительное изображение: data\processed\lab027\lab027_candidate_profiles.png
|
||||||
|
Следующий шаг: ручная оценка пользователем.
|
||||||
5
data/processed/lab027c/lab027c_preview_profiles.csv
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
profile_name,update_mode,base_width,base_height,base_fps,base_quality,roi_width,roi_height,roi_fps,roi_quality,source_duration_s,selected_base_frames,selected_roi_frames,synchronized_composite_frames,total_base_bytes,total_roi_bytes,total_payload_bytes,mean_base_frame_bytes,mean_roi_frame_bytes,mean_composite_frame_bytes,p95_composite_frame_bytes,max_composite_frame_bytes,base_bitrate_kbps,roi_bitrate_kbps,total_payload_bitrate_kbps,timestamp_mismatch_count,frame_id_mismatch_count
|
||||||
|
async_reference,asynchronous,240,135,1.000000,25,320,180,2.000000,35,20.766667,21,42,N/A,50858,191270,242128,2421.810,4554.048,5764.952,7477.600,7741,19.592167,73.683467,93.275634,N/A,N/A
|
||||||
|
sync_base160_q25_roi320_q35,synchronous,160,90,2.000000,25,320,180,2.000000,35,20.766667,42,42,42,59958,191270,251228,1427.571,4554.048,5981.619,6519.900,6656,23.097785,73.683467,96.781252,0,0
|
||||||
|
sync_base240_q20_roi320_q30,synchronous,240,135,2.000000,20,320,180,2.000000,30,20.766667,42,42,42,89696,173455,263151,2135.619,4129.881,6265.500,6780.400,6842,34.553836,66.820546,101.374382,0,0
|
||||||
|
sync_base240_q25_roi320_q35,synchronous,240,135,2.000000,25,320,180,2.000000,35,20.766667,42,42,42,102283,191270,293553,2435.310,4554.048,6989.357,7572.350,7741,39.402761,73.683467,113.086228,0,0
|
||||||
|
44
data/processed/lab027c/lab027c_preview_report.txt
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
Lab027C. Динамическое сравнение асинхронного и синхронного BASE + ROI
|
||||||
|
|
||||||
|
Цель: визуально сравнить ранее выбранный асинхронный профиль BASE 1 fps + ROI 2 fps с тремя синхронными профилями BASE 2 fps + ROI 2 fps.
|
||||||
|
|
||||||
|
Исходное видео: data\raw\lab026_rover_source.mp4
|
||||||
|
Исходное разрешение: 1280x720
|
||||||
|
Исходный FPS: 30.000000
|
||||||
|
Число кадров: 623
|
||||||
|
Длительность: 20.766667 с
|
||||||
|
ROI: x=0.20...0.80, y=0.42...1.00; пиксели x=256...1024, y=302...720.
|
||||||
|
|
||||||
|
Результат ручной оценки предыдущей Lab027:
|
||||||
|
- пользователь выбрал вариант B;
|
||||||
|
- граница ROI не мешает;
|
||||||
|
- обновление BASE один раз в секунду мешает;
|
||||||
|
- рассинхронное движение BASE и ROI мешает;
|
||||||
|
- принято решение сравнить с синхронным обновлением 2 fps.
|
||||||
|
|
||||||
|
async_reference: BASE и ROI обновляются независимо. Единого logical_frame_id нет; используются отдельные BASE ID и ROI ID. Mismatch для этого режима неприменим.
|
||||||
|
Синхронные профили: BASE и ROI формируются из одного source frame, получают единые composite ID и timestamp и атомарно заменяют отображаемый составной кадр.
|
||||||
|
|
||||||
|
Фактические результаты четырёх профилей:
|
||||||
|
async_reference: mode=asynchronous, BASE=240x135, 1.000 fps, Q25, base_frames=21, base_bytes=50858, base_bitrate=19.592167 kbit/s; ROI=320x180, 2.000 fps, Q35, roi_frames=42, roi_bytes=191270, roi_bitrate=73.683467 kbit/s; total_bytes=242128, total_bitrate=93.275634 kbit/s, sync_frames=N/A, timestamp_mismatch=N/A, frame_id_mismatch=N/A
|
||||||
|
sync_base160_q25_roi320_q35: mode=synchronous, BASE=160x90, 2.000 fps, Q25, base_frames=42, base_bytes=59958, base_bitrate=23.097785 kbit/s; ROI=320x180, 2.000 fps, Q35, roi_frames=42, roi_bytes=191270, roi_bitrate=73.683467 kbit/s; total_bytes=251228, total_bitrate=96.781252 kbit/s, sync_frames=42, timestamp_mismatch=0, frame_id_mismatch=0
|
||||||
|
sync_base240_q20_roi320_q30: mode=synchronous, BASE=240x135, 2.000 fps, Q20, base_frames=42, base_bytes=89696, base_bitrate=34.553836 kbit/s; ROI=320x180, 2.000 fps, Q30, roi_frames=42, roi_bytes=173455, roi_bitrate=66.820546 kbit/s; total_bytes=263151, total_bitrate=101.374382 kbit/s, sync_frames=42, timestamp_mismatch=0, frame_id_mismatch=0
|
||||||
|
sync_base240_q25_roi320_q35: mode=synchronous, BASE=240x135, 2.000 fps, Q25, base_frames=42, base_bytes=102283, base_bitrate=39.402761 kbit/s; ROI=320x180, 2.000 fps, Q35, roi_frames=42, roi_bytes=191270, roi_bitrate=73.683467 kbit/s; total_bytes=293553, total_bitrate=113.086228 kbit/s, sync_frames=42, timestamp_mismatch=0, frame_id_mismatch=0
|
||||||
|
|
||||||
|
Количество обновлений:
|
||||||
|
async_reference: BASE=21, ROI=42, synchronized=N/A.
|
||||||
|
sync_base160_q25_roi320_q35: BASE=42, ROI=42, synchronized=42.
|
||||||
|
sync_base240_q20_roi320_q30: BASE=42, ROI=42, synchronized=42.
|
||||||
|
sync_base240_q25_roi320_q35: BASE=42, ROI=42, synchronized=42.
|
||||||
|
|
||||||
|
Mismatch-проверка:
|
||||||
|
async_reference: timestamp=N/A, frame_id=N/A.
|
||||||
|
sync_base160_q25_roi320_q35: timestamp=0, frame_id=0.
|
||||||
|
sync_base240_q20_roi320_q30: timestamp=0, frame_id=0.
|
||||||
|
sync_base240_q25_roi320_q35: timestamp=0, frame_id=0.
|
||||||
|
|
||||||
|
Preview: data\raw\lab027c_previews\lab027c_synchronous_roi_preview.mp4
|
||||||
|
Формат: MP4/mp4v.
|
||||||
|
Радиопротокол, CRC, FEC, фрагментация и служебный трафик пока не учитываются.
|
||||||
|
Программа не выбирает лучший профиль и не объявляет режим безопасным автоматически.
|
||||||
|
Следующий шаг: ручной выбор пользователем после просмотра preview-видео.
|
||||||
5
data/processed/lab027d/lab027d_profiles.csv
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
profile_name,base_width,base_height,fps,base_quality,roi_width,roi_height,roi_quality,source_duration_s,selected_base_frames,selected_roi_frames,synchronized_composite_frames,total_base_bytes,total_roi_bytes,total_payload_bytes,mean_base_frame_bytes,mean_roi_frame_bytes,mean_composite_frame_bytes,p95_composite_frame_bytes,max_composite_frame_bytes,base_bitrate_kbps,roi_bitrate_kbps,total_payload_bitrate_kbps,channel_rate_fec_2_3_kbps,channel_rate_fec_1_2_kbps,timestamp_mismatch_count,frame_id_mismatch_count
|
||||||
|
sync_2fps_base_q20_roi_q30,240,135,2.000000,20,320,180,30,20.766667,42,42,42,89696,173455,263151,2135.619,4129.881,6265.500,6780.400,6842,34.553836,66.820546,101.374382,167.267730,223.023640,0,0
|
||||||
|
sync_3fps_base_q20_roi_q30,240,135,3.000000,20,320,180,30,20.766667,63,63,63,133076,249436,382512,2112.317,3959.302,6071.619,6640.800,6842,51.265233,96.090915,147.356148,243.137644,324.183525,0,0
|
||||||
|
sync_3fps_base_q23_roi_q33,240,135,3.000000,23,320,180,33,20.766667,63,63,63,144649,264895,409544,2296.016,4204.683,6500.698,7125.400,7383,55.723531,102.046228,157.769759,260.320103,347.093470,0,0
|
||||||
|
sync_3fps_base_q25_roi_q35,240,135,3.000000,25,320,180,35,20.766667,63,63,63,151516,274486,426002,2405.016,4356.921,6761.937,7421.700,7741,58.368925,105.740995,164.109920,270.781368,361.041823,0,0
|
||||||
|
37
data/processed/lab027d/lab027d_report.txt
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
Lab027D. Синхронный BASE + ROI при 2 и 3 fps
|
||||||
|
|
||||||
|
Цель: сравнить текущий синхронный профиль 2 fps с тремя профилями 3 fps при разных JPEG Quality.
|
||||||
|
|
||||||
|
Результат ручной оценки Lab027C:
|
||||||
|
- лучший из показанных вариантов — нижний левый;
|
||||||
|
- синхронизация BASE и ROI устранила рассогласование;
|
||||||
|
- 2 fps недостаточно;
|
||||||
|
- BASE 160x90 слишком грубый;
|
||||||
|
- BASE 240x135 Q20 немного недостаточен по качеству.
|
||||||
|
|
||||||
|
Причина повышения FPS: ручная оценка показала, что синхронное обновление устраняет рассогласование, но частота 2 fps недостаточна для динамической сцены.
|
||||||
|
|
||||||
|
Исходное видео: data\raw\lab026_rover_source.mp4
|
||||||
|
Разрешение: 1280x720
|
||||||
|
FPS: 30.000000
|
||||||
|
Кадров: 623
|
||||||
|
Длительность: 20.766667 с
|
||||||
|
ROI: x=0.20...0.80, y=0.42...1.00; пиксели x=256...1024, y=302...720.
|
||||||
|
|
||||||
|
Все профили синхронные: BASE и ROI формируются из одного source frame, получают единый timestamp и composite frame ID и публикуются атомарно.
|
||||||
|
|
||||||
|
Фактические результаты:
|
||||||
|
sync_2fps_base_q20_roi_q30: 2.000 fps; BASE=240x135, Q20, frames=42, bytes=89696, bitrate=34.553836 kbit/s; ROI=320x180, Q30, frames=42, bytes=173455, bitrate=66.820546 kbit/s; total_bytes=263151, payload=101.374382 kbit/s; channel FEC 2/3=167.267730 kbit/s; channel FEC 1/2=223.023640 kbit/s; sync_frames=42; timestamp_mismatch=0; frame_id_mismatch=0
|
||||||
|
sync_3fps_base_q20_roi_q30: 3.000 fps; BASE=240x135, Q20, frames=63, bytes=133076, bitrate=51.265233 kbit/s; ROI=320x180, Q30, frames=63, bytes=249436, bitrate=96.090915 kbit/s; total_bytes=382512, payload=147.356148 kbit/s; channel FEC 2/3=243.137644 kbit/s; channel FEC 1/2=324.183525 kbit/s; sync_frames=63; timestamp_mismatch=0; frame_id_mismatch=0
|
||||||
|
sync_3fps_base_q23_roi_q33: 3.000 fps; BASE=240x135, Q23, frames=63, bytes=144649, bitrate=55.723531 kbit/s; ROI=320x180, Q33, frames=63, bytes=264895, bitrate=102.046228 kbit/s; total_bytes=409544, payload=157.769759 kbit/s; channel FEC 2/3=260.320103 kbit/s; channel FEC 1/2=347.093470 kbit/s; sync_frames=63; timestamp_mismatch=0; frame_id_mismatch=0
|
||||||
|
sync_3fps_base_q25_roi_q35: 3.000 fps; BASE=240x135, Q25, frames=63, bytes=151516, bitrate=58.368925 kbit/s; ROI=320x180, Q35, frames=63, bytes=274486, bitrate=105.740995 kbit/s; total_bytes=426002, payload=164.109920 kbit/s; channel FEC 2/3=270.781368 kbit/s; channel FEC 1/2=361.041823 kbit/s; sync_frames=63; timestamp_mismatch=0; frame_id_mismatch=0
|
||||||
|
|
||||||
|
Оценки channel rate иллюстративны: к payload добавлено 10% служебных данных, затем применена оценка FEC 2/3 или FEC 1/2.
|
||||||
|
Эти значения не являются окончательной архитектурой радиоканала.
|
||||||
|
|
||||||
|
Preview: data\raw\lab027d_previews\lab027d_fps_quality_preview.mp4
|
||||||
|
Формат: MP4/mp4v.
|
||||||
|
|
||||||
|
Предупреждение: оценки пока не включают окончательную модуляцию, полосу сигнала, интерливинг, повторы и команды управления.
|
||||||
|
Программа не выбирает лучший профиль автоматически.
|
||||||
|
Следующий шаг: ручной выбор пользователя после просмотра preview-видео.
|
||||||
2
data/processed/lab027e/lab027e_profile.csv
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
profile_name,playback_speed_factor,source_width,source_height,source_fps,source_frames,source_duration_s,output_width,output_height,output_fps,output_frames,output_duration_s,composite_fps,base_width,base_height,base_quality,roi_width,roi_height,roi_quality,selected_composite_frames,total_base_bytes,total_roi_bytes,total_payload_bytes,mean_base_frame_bytes,mean_roi_frame_bytes,mean_composite_frame_bytes,p95_composite_frame_bytes,max_composite_frame_bytes,base_bitrate_kbps,roi_bitrate_kbps,total_payload_bitrate_kbps,channel_rate_fec_2_3_kbps,channel_rate_fec_1_2_kbps,timestamp_mismatch_count,frame_id_mismatch_count
|
||||||
|
sync_3fps_base240_q23_roi320_q33_speed_0_5x,0.500000,1280,720,30.000000,623,20.766667,1280,720,30.000000,1246,41.533333,3.000000,240,135,23,320,180,33,125,286715,524962,811677,2293.720,4199.696,6493.416,7125.400,7890,55.226003,101.116276,156.342279,257.964761,343.953014,0,0
|
||||||
|
50
data/processed/lab027e/lab027e_report.txt
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
Lab027E. Операторское preview при playback 0.5x
|
||||||
|
|
||||||
|
Результаты ручной оценки Lab027D:
|
||||||
|
- 3 fps достаточно на исходном быстром видео;
|
||||||
|
- Q20/Q30 приемлем;
|
||||||
|
- Q23/Q33 приемлем;
|
||||||
|
- разница Q23/Q33 и Q25/Q35 практически отсутствует.
|
||||||
|
|
||||||
|
Предварительно выбран профиль Q23/Q33.
|
||||||
|
От Q25/Q35 предварительно отказались, поскольку визуальный выигрыш почти отсутствует.
|
||||||
|
Профиль не считается окончательно утверждённым до ручного просмотра этого preview.
|
||||||
|
|
||||||
|
Исходная сцена замедлена для имитации более медленного движения ровера и оценки удобства управления.
|
||||||
|
Коэффициент playback: 0.500x.
|
||||||
|
Предупреждение: реальная скорость исходного автомобиля неизвестна.
|
||||||
|
|
||||||
|
Исходное видео:
|
||||||
|
- путь: data\raw\lab026_rover_source.mp4;
|
||||||
|
- разрешение: 1280x720;
|
||||||
|
- FPS: 30.000000;
|
||||||
|
- кадров: 623;
|
||||||
|
- длительность: 20.766667 с.
|
||||||
|
|
||||||
|
Выходное preview:
|
||||||
|
- разрешение: 1280x720;
|
||||||
|
- FPS: 30.000000;
|
||||||
|
- кадров: 1246;
|
||||||
|
- длительность: 41.533333 с;
|
||||||
|
- composite FPS: 3.000000.
|
||||||
|
|
||||||
|
Профиль:
|
||||||
|
- BASE 240x135 Q23;
|
||||||
|
- ROI 320x180 Q33;
|
||||||
|
- составных обновлений: 125.
|
||||||
|
|
||||||
|
Фактические скорости:
|
||||||
|
- BASE: 55.226003 kbit/s;
|
||||||
|
- ROI: 101.116276 kbit/s;
|
||||||
|
- total payload: 156.342279 kbit/s;
|
||||||
|
- channel rate FEC 2/3: 257.964761 kbit/s;
|
||||||
|
- channel rate FEC 1/2: 343.953014 kbit/s.
|
||||||
|
|
||||||
|
Оценки канальной скорости иллюстративны и не являются окончательной архитектурой радиоканала.
|
||||||
|
Mismatch-проверка:
|
||||||
|
- timestamp mismatch: 0;
|
||||||
|
- frame ID mismatch: 0.
|
||||||
|
|
||||||
|
Preview: data\raw\lab027e_previews\lab027e_operator_view_0_5x.mp4
|
||||||
|
Формат: MP4/mp4v.
|
||||||
|
Следующий шаг: ручная оценка удобства управления пользователем.
|
||||||
BIN
data/processed/lab028/lab028_overhead_efficiency.png
Normal file
|
After Width: | Height: | Size: 70 KiB |
6
data/processed/lab028/lab028_packet_payload_results.csv
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
max_payload_bytes,composite_frames,mean_base_packets_per_frame,mean_roi_packets_per_frame,mean_total_packets_per_frame,max_total_packets_per_frame,packets_per_second,jpeg_payload_bytes,jpeg_payload_bitrate_kbps,header_bytes_per_second,header_bitrate_kbps,wire_bytes,wire_bitrate_kbps,service_data_percent,efficiency_percent,mean_wire_packet_bytes,p95_wire_packet_bytes,max_wire_packet_bytes
|
||||||
|
64,63,36.428571,66.174603,102.603175,117,311.268058,409544,157.769759,9960.577849,79.684623,616392,237.454382,33.557866,66.442134,95.357673,96.000000,96
|
||||||
|
128,63,18.428571,33.269841,51.698413,59,156.837881,409544,157.769759,5018.812199,40.150498,513768,197.920257,20.286199,79.713801,157.742708,160.000000,160
|
||||||
|
256,63,9.428571,16.920635,26.349206,30,79.935795,409544,157.769759,2557.945425,20.463563,462664,178.233323,11.481334,88.518666,278.713253,288.000000,288
|
||||||
|
512,63,5.000000,8.682540,13.682540,15,41.508828,409544,157.769759,1328.282504,10.626260,437128,168.396019,6.310280,93.689720,507.109049,544.000000,544
|
||||||
|
1024,63,3.000000,4.587302,7.587302,8,23.017657,409544,157.769759,736.565008,5.892520,424840,163.662279,3.600414,96.399586,888.786611,1056.000000,1056
|
||||||
|
BIN
data/processed/lab028/lab028_packets_wire_bitrate.png
Normal file
|
After Width: | Height: | Size: 107 KiB |
52
data/processed/lab028/lab028_report.txt
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
Lab028. Пакетирование синхронного BASE + ROI
|
||||||
|
|
||||||
|
Профиль и исходные данные
|
||||||
|
- Видео: data\raw\lab026_rover_source.mp4
|
||||||
|
- Источник: 1280x720, 30.000000 fps, 623 кадров, 20.766667 с.
|
||||||
|
- ROI: x=0.20...0.80, y=0.42...1.00; пиксели x=256...1024, y=302...720.
|
||||||
|
- Синхронные составные кадры: 63 при 3.000 fps.
|
||||||
|
- BASE: 240x135, grayscale JPEG Q23; средний размер 2296.016 B, min/max 2122/2476 B.
|
||||||
|
- ROI: 320x180, grayscale JPEG Q33; средний размер 4204.683 B, min/max 3457/4938 B.
|
||||||
|
- BASE и ROI формируются из одного source frame и имеют общий composite_frame_id.
|
||||||
|
|
||||||
|
Бинарный заголовок
|
||||||
|
- struct format: !4sBBHIHHHHIII
|
||||||
|
- Размер: 32 байта; network byte order; padding нет.
|
||||||
|
- Layout: magic[4] @0, version:u8 @4, object_type:u8 @5, header_size:u16 @6, composite_frame_id:u32 @8, fragment_index:u16 @12, fragment_count:u16 @14, payload_length:u16 @16, flags:u16 @18, jpeg_size:u32 @20, object_crc32:u32 @24, packet_crc32:u32 @28.
|
||||||
|
- object_type: 1=BASE, 2=ROI; flags зарезервирован и равен 0.
|
||||||
|
|
||||||
|
CRC32
|
||||||
|
- object_crc32 = zlib.crc32(полный JPEG) & 0xFFFFFFFF; значение помещается во все фрагменты объекта и проверяется после полной сборки.
|
||||||
|
- packet_crc32: сначала поле packet_crc32 заголовка обнуляется, затем CRC считается как zlib.crc32(header_with_zero_crc + payload) & 0xFFFFFFFF.
|
||||||
|
- Таким образом packet CRC защищает все поля заголовка и payload.
|
||||||
|
|
||||||
|
Функциональные проверки
|
||||||
|
- PASS header_serialization_round_trip: fixed 32-byte header round trip is exact
|
||||||
|
- PASS ordered_lossless_transfer: BASE and ROI match original JPEG bytes
|
||||||
|
- PASS random_packet_order: arbitrary packet order reconstructed correctly
|
||||||
|
- PASS exact_duplicate_packets: 2 exact duplicates ignored
|
||||||
|
- PASS packet_crc_corruption: payload bit flip rejected; composite not emitted
|
||||||
|
- PASS missing_fragment: ROI fragment 10 reported missing
|
||||||
|
- PASS object_crc_corruption: valid packet CRCs still failed full-object CRC
|
||||||
|
- PASS adjacent_frame_isolation: two interleaved frame IDs remained independent
|
||||||
|
- PASS base_without_roi_atomicity: complete BASE retained while composite stayed unpublished
|
||||||
|
|
||||||
|
Результаты размеров packet payload
|
||||||
|
payload | BASE pkt/frame | ROI pkt/frame | all pkt/frame | max pkt/frame | pkt/s | JPEG kbit/s | headers B/s | wire kbit/s | service % | efficiency % | packet mean/p95/max
|
||||||
|
-------:|---------------:|--------------:|--------------:|--------------:|------:|------------:|------------:|------------:|----------:|-------------:|--------------------:
|
||||||
|
64 | 36.429 | 66.175 | 102.603 | 117 | 311.268 | 157.770 | 9960.578 | 237.454 | 33.558 | 66.442 | 95.4/96.0/96
|
||||||
|
128 | 18.429 | 33.270 | 51.698 | 59 | 156.838 | 157.770 | 5018.812 | 197.920 | 20.286 | 79.714 | 157.7/160.0/160
|
||||||
|
256 | 9.429 | 16.921 | 26.349 | 30 | 79.936 | 157.770 | 2557.945 | 178.233 | 11.481 | 88.519 | 278.7/288.0/288
|
||||||
|
512 | 5.000 | 8.683 | 13.683 | 15 | 41.509 | 157.770 | 1328.283 | 168.396 | 6.310 | 93.690 | 507.1/544.0/544
|
||||||
|
1024 | 3.000 | 4.587 | 7.587 | 8 | 23.018 | 157.770 | 736.565 | 163.662 | 3.600 | 96.400 | 888.8/1056.0/1056
|
||||||
|
|
||||||
|
JPEG payload bitrate одинаков для всех строк, потому что исходные JPEG не меняются при выборе размера фрагмента.
|
||||||
|
Wire bitrate включает только JPEG payload и 32-байтные заголовки каждого пакета.
|
||||||
|
Wire bitrate пока НЕ включает FEC, преамбулу, синхронизацию, модуляцию, интервалы, повторные передачи, команды управления и телеметрию.
|
||||||
|
Лучший размер packet payload автоматически не выбирается: таблица показывает только транспортный компромисс.
|
||||||
|
|
||||||
|
Артефакты
|
||||||
|
- CSV: data\processed\lab028\lab028_packet_payload_results.csv
|
||||||
|
- Overhead/efficiency: data\processed\lab028\lab028_overhead_efficiency.png
|
||||||
|
- Packet count/wire bitrate: data\processed\lab028\lab028_packets_wire_bitrate.png
|
||||||
|
- Промежуточные JPEG и пакеты сохранялись только в памяти; бинарные дампы не создавались.
|
||||||
BIN
data/processed/lab029/lab029_ber_success.png
Normal file
|
After Width: | Height: | Size: 96 KiB |
BIN
data/processed/lab029/lab029_burst_loss_results.png
Normal file
|
After Width: | Height: | Size: 95 KiB |