Compare commits

..

40 Commits

Author SHA1 Message Date
LittleSam129
f0fa7e8a46 Lab043: validate pilot-aided short BPSK link 2026-08-19 18:14:13 +03:00
LittleSam129
fa2e473c6d Lab042: validate Pluto image hardware loopback 2026-08-17 18:30:16 +03:00
LittleSam129
fce14f038e Lab042: transmit an image over the air, add the air loopback mode
First transmission through a real radio path in the project. A 4756-byte
JPEG went from transmitter to receiver over two antennas 60 cm apart at
225 MHz and reassembled byte-identical, reproduced across three runs.

The cable loopback still needs an SMA male-to-male adapter that has not
arrived, so this air run is a track verification, not the controlled
measurement: room levels are not held the way a cable holds them. Its
purpose was to exercise the device wrapper the models cannot cover.

Four defects the software model passed but the hardware exposed, each
reproduced and fixed:

- a 566 528-sample frame did not fit the 262 144 receive buffer, and the
  sample stream is not continuous across separate reads, so a frame on the
  seam was destroyed. Reception now uses one buffer sized to the frame
- carrier correction was always applied, but with a shared reference the
  true offset is near zero and the 80-symbol marker estimate is noise;
  correcting by it rotated phase along the whole frame, 65% bit errors
  measured. Ported should_apply_cfo_correction from Lab023
- receiver gain of 20 dB left the signal at 0.0003 of full scale. Levels
  set by measurement: RX 50 dB, TX -10 dB give zero bit errors with margin
- the error-vector metric returned zero on a failed receive, reporting a
  perfect signal where there was none, the same class of defect as the
  written-in figures of Lab041. Replaced with an explicit not-computed value

The air TX gain ceiling is now derived from the link budget by antenna
distance rather than a constant. Three loopback modes: software, cable,
air. PROJECT_LOG entry 019 records the run and the defects.

Software and cable results stay reproducible; 125 tests pass, gate passes.
2026-08-17 11:50:04 +03:00
LittleSam129
13f183f7c7 Run the core tests from the gate and finish the layout rename
The gate now runs pytest as well, so one command answers whether the code
base is broken: syntax, protocol imports, the 125 core tests, then the lab
functional suites. It fails when a test fails, verified by feeding it a
deliberately broken test.

Two leftovers from moving the labs into experiments/ are fixed: the lab
command still pointed at tests/, and the hook only watched protocol and
tests, so edits under experiments/ and tools/ triggered nothing.

Profiling the 3.6 s gate: 0.24 s syntax, 0.12 s imports, 0.61 s pytest,
2.7 s lab functional suites, of which Lab042's software loopback is 1.14 s
because it pushes a whole image through the chain. The pytest addition is
the small part. prepare_jpeg is now cached, since six checks call it and
each call re-encoded the image at several qualities.

README described the gate without the tests it now runs.
2026-08-11 13:40:05 +03:00
LittleSam129
a37ad1f7b3 Lab042: transmit a JPEG through a cable loopback
First lab in the project that switches the transmitter on. Lab001-Lab041
built the whole chain but never called into an SDR to send anything.

Two modes. Software closes the channel in memory and needs no hardware;
it is the reference the hardware run is measured against, so the
difference between them is what the radio path contributes. Hardware
drives one PlutoSDR with its transmit output looped back through a 30 dB
attenuator into its own receive input.

Everything outside the device wrapper is reused from protocol/ unchanged:
image_fragments, packet and the primitives in bpsk_radio.

Software run: a 4756-byte JPEG in 10 fragments, 5 272 064 samples, 2.059 s
of signal, 10 of 10 fragments recovered, image byte-identical, repeatable
across runs. Channel rate 18.475 kbit/s, below the 20 kbit/s symbol rate
because of framing and guards.

Three defects found by the verifier and fixed:

- the guard interval was only appended after the frame. Lab018 puts one on
  both sides, and the leading one is the one that matters: the first
  samples of a transmission are unreliable, so the preamble would have
  landed exactly on the transient. Invisible in software mode, which has
  no converter and no transient
- transmission was started before reception, contradicting section 8 of
  the specification and its own trap 3. The receiver now runs first and
  the first buffer is discarded, as in Lab024a
- packet and frame size were reported from the first frame only, while
  the tenth is 172 bytes against 536. Sizes are now per frame in the CSV
  and the report gives the honest range

Also fixed before verification: the JPEG did not fit its own 5000-byte
limit, so quality is now lowered until it does and reported as a result;
and the wall-clock rate was presented as a channel rate, which in software
mode measures computation, not a channel.

Artifacts are left out deliberately. data/processed/lab042 currently holds
the software reference; the committed results should be the real
experiment, which needs the cable.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-11 13:28:47 +03:00
LittleSam129
46b10b1243 Add the GitLab CI pipeline
Three stages, all fast: the gate, then the core tests, then style.

Only the calculation environment is installed, no pyadi-iio or libiio, so
the pipeline needs no hardware. Laboratory experiments stay out of it:
they run for minutes, need inputs from data/raw that are not in the
repository, and some need a PlutoSDR attached. Those remain manual.

The style job is allow_failure for now. Lab001-Lab041 use a distinctive
layout with one argument per line, and normalising it would mean touching
50 files whose results are already recorded. The restriction lifts once
we agree on the rules.

Test results are published as a JUnit report so failures show up in the
merge request rather than only in the job log.

Both jobs verified locally: gate passes, 125 tests pass in 0.26 s.

Registering a runner on git.arconlab.ru is the one part that has to be
done on the server side.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-10 15:38:35 +03:00
LittleSam129
0ae04ae4a8 Close the remaining audit findings
Environment, README, gitignore and the source self-parsing in Lab041.

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

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

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

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

125 tests pass, gate passes.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-10 15:33:14 +03:00
LittleSam129
92289bdf7c Cover control messages and session state; record the RF decision
Two more suites, 69 checks, bringing the fast tests to 125 in 0.3 s.

test_control_messages: roundtrip for all ten message types, a guard that
fails if a type is added without a test, wrong version, unknown type,
truncation, the control-state range rules including negative and
non-finite speed, and sequence comparison across the 32-bit wrap and the
ambiguous 2^31 boundary.

test_session_state: the safety properties that previously only ran inside
Lab041. Safe boot on both sides, status and authorization not being a
movement command, a new operator command being required, stale session,
boot and epoch identifiers, replay, sequence wrap, ambiguity, persisted
emergency intent surviving a restart, acknowledgement not clearing it,
ordinary commands not releasing the latch, idempotent reset, and reset
not restoring the previous command.

Two of these were literal zeros in the Lab041 report and measured
nothing: negative speed and speed above the limit are now genuinely
exercised against the encoder.

PROJECT_LOG entry 018 records the RF architecture decision: 200-250 MHz
with frequency hopping, a directional ground antenna and spread spectrum
for the command channel, with the rejected alternatives and why.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-10 15:29:47 +03:00
LittleSam129
2da80d0908 Add the first real test suite for protocol/
56 fast checks, 0.2 s, covering packet.py and the new bpsk_radio.py.

test_bpsk_radio exists mainly to prove the extraction changed nothing. It
loads the original function definitions out of Lab018, Lab019 and Lab023
in isolation, compiling only the wanted AST nodes so the labs' module
level file writing never runs, then compares outputs: bit conversion,
modulation, shaping filter, frame marker and the carrier estimator over
random phase and frequency offsets.

It also covers the frame functions written fresh for the module:
roundtrip at four payload sizes, size and type rejection, broken sync
word, truncation, carrying a real CRC32 packet, and a shaped-signal
search that recovers the packet through matched filtering.

test_packet covers roundtrip across all four message types and five
payload sizes, sync word, length arithmetic, sequence range, truncation,
oversized payload, and single-bit corruption at six positions, which is
the property CRC32 is there to provide.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-10 14:38:12 +03:00
LittleSam129
c486039053 Split experiments from tests
The tests/ directory held 50 laboratory programs and no tests. They model
channels, run hundreds of repetitions and write CSV, PNG and reports;
calling that a test suite blocked introducing a real one, because any
pytest run would have collected the labs and re-executed every
experiment.

- move all 50 lab programs to experiments/ with git mv, preserving history
- rewrite the 38 cross-imports between labs from tests.labNNN to
  experiments.labNNN
- leave tests/ empty for actual fast checks of protocol/
- point quick_gate and the hook at the new layout and add experiments/ to
  the syntax sweep
- update the paths quoted in the Lab042 specification and the verifier
  agent definition

This also defuses the import-time work finding without touching 41 files:
the labs still create directories and write files on import, but nothing
imports them now except the gate, which does so deliberately.

Gate passes: syntax clean, protocol imports, 15 lab modules import, 2
functional suites run.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-10 14:34:58 +03:00
LittleSam129
c9569164e0 Add protocol/bpsk_radio: reusable BPSK radio primitives
Lab042 cannot reuse the DSP from the earlier labs the way its
specification assumed. Three blockers turned up on inspection:

- importing lab018, lab019 or lab023 creates directories and writes .npy,
  .png and report files at module level, so importing them silently
  re-runs their experiments
- build_radio_frame() takes no arguments and encodes a fixed text message
- decode_radio_frame() returns a status string rather than the payload

So the verified primitives move into a module that is safe to import and
does no work of its own. Function bodies are carried over verbatim, and
the source lab is named above each one:

- from Lab023: bytes_to_bits, bits_to_bytes, bpsk_modulate,
  bpsk_demodulate, estimate_carrier_parameters, correct_phase_and_frequency
- from Lab019: build_frame_marker, find_radio_frame
- from Lab018: root_raised_cosine_taps

build_radio_frame and parse_radio_frame are written fresh here to carry
arbitrary payloads; the on-air structure is unchanged, still preamble,
sync word, length, packet.

Verified against the originals by loading their function definitions in
isolation and comparing outputs: 31 comparisons, no divergence, including
the CFO estimator over random phase and frequency offsets.

End-to-end check with no hardware: a 5828-byte JPEG through fragments,
packets, frames, shaping at 128 samples per symbol and matched filtering
recovers 12 of 12 fragments and reassembles byte-identical.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-10 14:16:32 +03:00
LittleSam129
1e4adc0a98 Lab042: correct the sample rate against the real device
Queried the Pluto over IIO before writing any code. Three findings, one
of which invalidated the specification.

The AD9361 will not sample below 2 083 333 Hz, so the 640 kHz taken from
Lab018 is unreachable by a factor of three. Going lower needs the on-chip
FIR decimator, which would add an untested mechanism to the very first
transmit. Instead raise oversampling from 32 to 128 samples per symbol:
the symbol rate stays at 20 000, rolloff, preamble, sync word and guard
are untouched, and the rate becomes 2 560 000 Hz. Only the device
interface changes, not the signal.

Consequence recorded: the shaping filter grows to 1281 taps, so the
convolution has to go through scipy.signal.fftconvolve.

Also from the device:
- it reports as PlutoSDR Rev.C (Z7010-AD9361) with a single RX and a
  single TX buffer channel, so adi.Pluto is right and the adi.ad9361
  fallback is unnecessary
- the chip is a full AD9361: RX tunes 70 MHz to 6 GHz, TX from 46.9 MHz,
  so the sub-350 MHz target band is available without a firmware hack.
  That closes the open question flagged for Lab044
- firmware is v0.32, left alone for now

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-10 14:06:44 +03:00
LittleSam129
2a7a380875 Lab042: fix a cross-reference broken by renumbering
The TX cyclic buffer row pointed at section 7, which became the signal
parameters when the hardware and environment sections were inserted. It
means the traps section, now 9.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-10 13:38:50 +03:00
LittleSam129
49c7009ca5 Lab042: drop the regulatory framing, keep the technical reasons
The project owner holds the permits for over-the-air work, so legality is
not a constraint this document should be reasoning about.

- retitle the section from "safety requirements" to what it actually
  covers: circuit integrity and not destroying the hardware
- rewrite the antenna rule on its real technical ground. An antenna opens
  a radiating path in parallel with the cable, so the level at the
  receiver stops matching the budget and reflections appear; the value of
  a cable loopback is that everything in it is known
- reframe "no over-the-air" as a scope boundary against Lab044 rather
  than a prohibition
- note in the roadmap that Lab044 is purely a technical choice of band,
  power and antenna

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-10 13:34:07 +03:00
LittleSam129
9f7387ec2c Lab042: attenuator on hand, relax the gain restriction
The bench has an AT30S: 30 dB, SMA, rated to 200 W. That removes the last
hardware blocker and changes the safety analysis.

With 30 dB in line, TX at full 0 dB gain lands at about -23 dBm on the
receiver, some 25 dB below the +2.5 dBm damage threshold. The whole
tx_hardwaregain range is therefore safe, so the staged -60 dB start and
the -30 dB ceiling are no longer needed.

- record the attenuator in the inventory and note that its 200 W rating is
  irrelevant here, attenuation does not depend on level
- replace the interim procedure with a level budget table and a starting
  point of -30 dB, giving about -53 dBm at the receiver
- require a visual check that the attenuator is actually in the path
  before the first transmit
- keep the ban on running without it: it guards against operator error,
  not against the calculated level

Only the environment blocker is left: pyadi-iio and libiio are missing
from the interpreter on PATH.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-10 13:33:24 +03:00
LittleSam129
923e6bec78 Lab042: adapt spec to the actual hardware and environment
Hardware confirmed from a photo of the bench: the device is a Pluto+
(2RX/2TX, Gigabit Ethernet), not the stock ADALM-PLUTO, plus an RTL-SDR
dongle and several antennas. No attenuator on hand.

- record the actual inventory and the Pluto+ differences that matter:
  Ethernet transport, two channels, adi.Pluto first with adi.ad9361 as
  the only permitted fallback
- replace "use an attenuator" with numbers: TX puts out about +7 dBm at
  0 dB, the RX damage threshold is about +2.5 dBm, so give a staged gain
  procedure starting at -60 dB and capped at -30 dB until an attenuator
  arrives
- require the antennas to be physically removed from the bench rather
  than merely left unplugged
- add the environment blocker found on inspection: the interpreter on
  PATH is a standalone Python 3.13.1 without pyadi-iio, libiio or scipy,
  while Lab024a clearly ran somewhere else; identifying and recording
  that environment is now the first task
- renumber sections and align the TX gain figure with the safety section

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-10 13:03:17 +03:00
LittleSam129
3d14c75365 Lab042: add hardware loopback specification
Specification for the first transmission through real hardware. The
project has no TX call anywhere across Lab001-Lab041, so the whole chain
exists but has never been connected to a transmitter.

Scope is deliberately minimal: get a JPEG through a cable loopback on a
single PlutoSDR and see the picture. Single device means TX and RX share
a reference clock, which removes the carrier offset and clock drift that
the receiver chain handles weakest.

- reuse Lab018 signal parameters unchanged, so hardware is the only new
  variable
- reuse image_fragments, packet, build_radio_frame, find_radio_frame
- list the first-time traps: cyclic TX buffer, sample scaling, RX started
  after TX, undersized RX buffer, automatic gain, receiver saturation
- define acceptance criteria and required measurements
- state explicitly what is out of scope: retransmission, erasure coding,
  higher rate, two devices, over-the-air

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-10 11:39:39 +03:00
LittleSam129
28227e4228 Add quick gate and independent review pipeline
Introduce tools/quick_gate.py: a one-second check that parses every file
in protocol, tests and tools, imports each protocol module, and runs the
functional tests of the labs that need no experiment data.

Wire it to a PostToolUse hook so edits under protocol or tests are checked
automatically, and add two read-only review agents with slash commands that
drive them: verifier for independent re-derivation of results, adversary for
unsafe-state hunting in control, failsafe, session and reset code.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-07 17:33:46 +03:00
LittleSam129
7d122b53ed Lab041: remove non-modelled metrics and cite value sources
Audit found seven numbers in simulate_trial that were neither modelled by
Lab041 nor traceable to their claimed source. Video fraction 0.910 did not
match Lab040 (0.9603); base queue length 31 did not match Lab040 (36-38).

- drop video/telemetry/control delivered fractions and queue length: these
  belong to Lab037 and Lab040 and are not modelled here
- drop lab041_traffic_impact.png, which plotted only those metrics
- drop negative_speed_cases and speed_limit_exceeded_cases, never computed,
  along with the tautological asserts that checked them
- bind braking parameters to the Lab039 nominal profile via named constants
  instead of the literals 0.250 and the divisor 6.0
- cite Lab038 as the source of the transferred video and telemetry loads
- rewrite the invariants section: nine architecture-derived properties now
  carry functional-check references, five unmeasurable ones move to their
  own section
- extend check 04 with negative speed and the 15 m/s boundary
- state explicitly what the matrix rolls, what the architecture fixes and
  what is not modelled at all

Regenerated: 180 combinations, 24/24 checks, five CSV and seven PNG.
Six columns removed, no retained value changed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-07 17:32:51 +03:00
LittleSam129
e18200225b Lab041: correct generated Git status wording 2026-08-07 10:50:42 +03:00
LittleSam129
f26d7d74ef Lab041: add session and restart safety 2026-08-05 14:14:24 +03:00
LittleSam129
88addff5b6 Lab040: add persistent emergency intent and safe reset 2026-08-05 13:12:49 +03:00
LittleSam129
b3ebe1637f Lab039: model two-stage failsafe braking 2026-08-05 11:44:43 +03:00
LittleSam129
23cfdf581b Lab038: add control failsafe and emergency acknowledgement 2026-08-04 14:06:50 +03:00
LittleSam129
50e45ca611 Lab037: evaluate control repetition on lossy link 2026-08-04 13:18:49 +03:00
LittleSam129
3e0ef5666e Lab036: validate long-duration video scheduling 2026-08-03 17:10:17 +03:00
LittleSam129
22c2eeab8c Lab035: add proactive video frame admission 2026-08-03 15:42:16 +03:00
LittleSam129
b63e36abdb Lab034: evaluate stale video frame dropping 2026-08-03 13:17:55 +03:00
LittleSam129
21751f41dd Lab033: add priority link scheduler 2026-08-03 12:21:49 +03:00
LittleSam129
3dbb7afa83 Lab032: evaluate FEC block parameters 2026-07-29 12:47:10 +03:00
LittleSam129
2ac1571c40 Lab031: evaluate FEC packet interleaving 2026-07-29 12:25:51 +03:00
LittleSam129
edab87b5d2 Lab030: add packet erasure FEC 2026-07-29 11:40:37 +03:00
LittleSam129
f8575f4de3 Lab029B: simulate time-based burst losses 2026-07-27 16:28:54 +03:00
LittleSam129
a2dd58a44b Lab029: simulate packet loss and channel errors 2026-07-27 15:29:39 +03:00
LittleSam129
04ce66fdfe Lab028: add video packetization and CRC reassembly 2026-07-27 13:46:01 +03:00
LittleSam129
78258b5355 Lab027: optimize synchronized ROI video stream 2026-07-24 17:54:27 +03:00
LittleSam129
6d49036066 Lab026: benchmark low-bitrate video and 4-bit encoding 2026-07-24 11:56:41 +03:00
LittleSam129
557b082f2b lab025_wfm_audio_100_1mhz 2026-07-22 17:29:07 +03:00
LittleSam129
f3a11b29b3 Merge branch 'repair/project-layout' 2026-07-22 14:20:11 +03:00
LittleSam129
1ff04b12b9 Repair project layout and fix Lab024B spectrum detection 2026-07-21 13:51:41 +03:00
361 changed files with 59589 additions and 8596 deletions

View 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 не проверено`.

View 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
View 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
View 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: краткое описание на английском`.
Коммить только после явного согласия пользователя.

View 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
View 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
View File

@@ -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
View 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
# Проверка стиля. Пока не блокирует конвейер: в лабораторных Lab001Lab041
# принято своеобразное оформление с переносами аргументов, и приводить их
# к единому стилю сейчас означало бы тронуть 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
View 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: моделирование потерь и ошибок видеопакетов.
## Выполнено
- Исследованы независимые потери пакетов и независимые битовые ошибки.
- Проверены короткие, средние и длинные серии потерь по модели GilbertElliott.
- Выполнено сравнение 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 ГГц дифракция исчезает и для наземного ровера без прямой видимости эти каналы мертвы. Кроме того, подавление направлено на диапазон, в котором связь действительно работает, а не на тот, который способно настроить оборудование.
**Диапазоны 330433 МГц.** Отклонены как плотно занятые и общеизвестные.
## Принято
Рабочий диапазон **200250 МГц**. Обоснование: четвертьволновая антенна 33 см пригодна для установки на ровер, дифракция ещё эффективна, участок заметно свободнее любительского 144 МГц и УКВ выше 300 МГц. Потери на 10 км составляют около 99,5 дБ.
Совокупность мер против подавления:
1. **Скачки по частоте в пределах 200250 МГц.** Требуют от заградительной помехи на 22 дБ больше мощности при неизменной антенне и механике ровера.
2. **Направленная антенна наземной станции.** Даёт 1020 дБ усиления и пространственно подавляет помеху, приходящую с иного направления.
3. **Расширение спектра для команд управления.** Поток команд составляет 10,88 кбит/с, поэтому расширение для него реализуемо в узкой полосе, в отличие от видеопотока.
Видео остаётся некритичным классом: при подавлении управление сохраняется в узкой полосе, а ровер переходит к безопасному поведению по уже реализованной логике.
## Запрещённые участки
- 108137 МГц — авиационная связь.
- 243 МГц — международная аварийная частота.
## Ограничения решения
- Нижняя граница 70 МГц определяется приёмником Pluto и без смены оборудования не преодолевается.
- Скачки требуют согласованной последовательности у обеих сторон, то есть зависят от криптографической аутентификации, которая пока не реализована.
- Расчёты выполнены для свободного пространства. Потери на препятствиях 2040 дБ учтены оценочно и подлежат измерению.
- Дальность 10 км без усилителя мощности не достигается.
## Влияние на ближайшие работы
На Lab042 не влияет: там кабельная петля, несущая 435 МГц выбрана произвольно. Диапазон 200250 МГц вступает в силу начиная с эфирных испытаний.
---
# Запись 019
## Дата
10 августа 2026 года
## Тема
Lab042: первая передача изображения через реальный радиотракт. Эфирная проверка на паре антенн.
## Причина эфирного прогона
Кабельная петля требует переходника SMA папа-папа, которого пока нет: пигтейлы к антеннам оканчиваются папой, а разъёмы Pluto — мамы. Чтобы не простаивать, выполнена вспомогательная эфирная проверка на двух антеннах, разнесённых на 60 см. Она не заменяет кабельный опыт: уровни в помещении не контролируются строго, возможны переотражения. Её задача — снять последнюю неизвестность в коде, а именно обвязку вокруг устройства, которая в моделях не проверяется.
## Условия
- Устройство Analog Devices PlutoSDR Rev.C, чип AD9361, прошивка v0.32.
- Несущая 225 МГц, внутри целевого диапазона Записи 018.
- Антенны, рассчитанные на 108 МГц, работают на несущей как полуволновые. Частота передачи и частота, на которую рассчитана антенна, различны, поэтому в авиационный диапазон 108137 МГц опыт не заходит.
- Изображение 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.

View File

@@ -1,35 +0,0 @@
# Инженерный журнал SDR Rover Link
## Назначение журнала
Этот файл содержит хронологию разработки проекта SDR Rover Link.
В журнале фиксируются:
- выполненные работы;
- полученные результаты;
- обнаруженные ошибки;
- принятые технические решения;
- результаты экспериментов;
- планы следующего этапа.
Записи не следует удалять. Если решение изменилось, необходимо добавить новую запись и объяснить причину изменения.
---
# Запись 001
## Дата
10 июля 2026 года
## Тема
Создание структуры проекта и локального Git-репозитория.
## Выполнено
1. Проверена установленная версия Git:
```text
git version 2.51.1.windows.1

View File

@@ -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

View File

@@ -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 frequency_hz frequency_mhz relative_power_db prominence_db
2 98840137.685 98.840138 -16.363 14.939
3 99201367.853 99.201368 -8.578 21.049
4 99603613.612 99.603614 -5.852 194.148
5 100099316.323 100.099316 -0.641 27.938
6 100498925.365 100.498925 0.000 200.000
7 100896483.628 100.896484 -2.662 25.928
8 101159569.346 101.159569 -11.137 18.231

View File

@@ -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 дБ

Binary file not shown.

Before

Width:  |  Height:  |  Size: 187 KiB

180
README.md Normal file
View File

@@ -0,0 +1,180 @@
# SDR Rover Link
## 1. Назначение проекта
**SDR Rover Link** — учебно-исследовательский проект по разработке цифрового радиоканала для наземного робототехнического комплекса с использованием программно-определяемого радио — SDR, Software Defined Radio.
Проект должен пройти полный путь от передачи простого текстового пакета до передачи телеметрии и изображений через реальный радиоканал.
Основная задача — не только получить работающую систему, но и последовательно изучить все этапы цифровой радиосвязи: формирование данных, разбиение на пакеты, контроль целостности, исправление ошибок, цифровую модуляцию, формирование IQ-сигнала, передачу через SDR, приём, демодуляцию и восстановление исходных данных.
---
## 2. Целевой сценарий
| Параметр | Требование |
|---|---|
| Дальность связи | до 10 км |
| Скорость ровера | до 25 км/ч |
| Прямая радиовидимость | может отсутствовать |
| Рабочий диапазон | 200250 МГц, см. Запись 018 журнала |
| Основной тип данных | телеметрия, команды и изображения |
| Формат изображения | JPEG |
| Действие при потере связи | безопасная остановка ровера |
Дальность 10 км без прямой видимости — целевое исследовательское требование, а не гарантированная характеристика первой версии.
---
## 3. Почему не используется обычное FPV-видео
Типовые FPV-системы работают в диапазонах 2,4 и 5,8 ГГц. Для наземного робота это плохо: велики потери у поверхности земли, сильное затенение рельефом и растительностью, а главное — на таких частотах практически нет дифракции, поэтому за препятствием связь пропадает.
В этом проекте вместо непрерывного видеопотока передаются отдельные сжатые изображения, что резко снижает требуемую скорость канала.
---
## 4. Текущее состояние
**Выполнено:** лабораторные Lab001Lab042. Пройден путь от структуры пакета до первой передачи изображения через реальный радиотракт.
Что реализовано и проверено:
- пакетный протокол с 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/ лабораторные Lab001Lab041
├── 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

View File

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

View File

Before

Width:  |  Height:  |  Size: 9.3 KiB

After

Width:  |  Height:  |  Size: 9.3 KiB

View File

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

Before

Width:  |  Height:  |  Size: 6.3 KiB

After

Width:  |  Height:  |  Size: 6.3 KiB

View File

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

Before

Width:  |  Height:  |  Size: 91 KiB

After

Width:  |  Height:  |  Size: 91 KiB

View File

Before

Width:  |  Height:  |  Size: 6.2 KiB

After

Width:  |  Height:  |  Size: 6.2 KiB

View File

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View File

Before

Width:  |  Height:  |  Size: 133 KiB

After

Width:  |  Height:  |  Size: 133 KiB

View File

Before

Width:  |  Height:  |  Size: 5.3 KiB

After

Width:  |  Height:  |  Size: 5.3 KiB

View File

Before

Width:  |  Height:  |  Size: 4.7 KiB

After

Width:  |  Height:  |  Size: 4.7 KiB

View File

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

Before

Width:  |  Height:  |  Size: 129 KiB

After

Width:  |  Height:  |  Size: 129 KiB

View File

Before

Width:  |  Height:  |  Size: 144 KiB

After

Width:  |  Height:  |  Size: 144 KiB

View File

Before

Width:  |  Height:  |  Size: 101 KiB

After

Width:  |  Height:  |  Size: 101 KiB

View File

Before

Width:  |  Height:  |  Size: 103 KiB

After

Width:  |  Height:  |  Size: 103 KiB

View File

Before

Width:  |  Height:  |  Size: 102 KiB

After

Width:  |  Height:  |  Size: 102 KiB

View File

Before

Width:  |  Height:  |  Size: 73 KiB

After

Width:  |  Height:  |  Size: 73 KiB

View File

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 41 KiB

View File

Before

Width:  |  Height:  |  Size: 154 KiB

After

Width:  |  Height:  |  Size: 154 KiB

View File

Before

Width:  |  Height:  |  Size: 314 KiB

After

Width:  |  Height:  |  Size: 314 KiB

View File

Before

Width:  |  Height:  |  Size: 162 KiB

After

Width:  |  Height:  |  Size: 162 KiB

View File

Before

Width:  |  Height:  |  Size: 203 KiB

After

Width:  |  Height:  |  Size: 203 KiB

View File

Before

Width:  |  Height:  |  Size: 206 KiB

After

Width:  |  Height:  |  Size: 206 KiB

View File

Before

Width:  |  Height:  |  Size: 253 KiB

After

Width:  |  Height:  |  Size: 253 KiB

View File

Before

Width:  |  Height:  |  Size: 260 KiB

After

Width:  |  Height:  |  Size: 260 KiB

View 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
1 frequency_hz frequency_mhz relative_power_db prominence_db
2 99198731.136 99.198731 -5.071 30.671
3 99595703.462 99.595703 -2.354 32.308
4 100099316.323 100.099316 0.000 35.017
5 100479882.413 100.479882 -1.155 32.127
6 100895604.722 100.895605 -7.043 27.121

View 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 дБ

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 193 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 237 KiB

View 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-сэмплы на диск не сохранялись.

Binary file not shown.

After

Width:  |  Height:  |  Size: 138 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

View 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
1 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
2 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
3 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
4 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
5 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
6 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
7 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
8 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
9 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
10 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
11 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
12 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
13 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
14 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
15 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
16 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
17 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
18 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
19 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
20 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
21 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
22 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
23 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
24 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
25 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
26 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
27 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
28 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
29 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
30 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
31 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
32 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
33 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

View 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-профили.

Binary file not shown.

After

Width:  |  Height:  |  Size: 199 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

View 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."
1 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
2 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.
3 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.
4 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.
5 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.
6 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.
7 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.
8 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.
9 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.
10 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.
11 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.
12 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.
13 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.
14 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.
15 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.
16 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.
17 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.
18 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.
19 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.
20 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.
21 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.
22 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.
23 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.
24 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.
25 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.
26 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.
27 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.
28 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.
29 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.
30 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.
31 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.

View 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
Профили 7090 кбит/с:
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
Следующий шаг: ручная визуальная оценка пользователем.

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

View 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
1 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
2 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
3 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
4 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
5 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
6 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
7 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
8 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
9 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
10 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

View File

@@ -0,0 +1,74 @@
Lab027. Многомасштабная передача изображения: общий кадр и область интереса
Цель: проверить совместную передачу общего кадра и фиксированной ROI при payload около 80100 кбит/с.
Исходное видео: 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
Следующий шаг: ручная оценка пользователем.

View 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
1 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
2 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
3 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
4 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
5 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

View 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-видео.

View 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
1 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
2 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
3 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
4 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
5 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

View 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-видео.

View 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
1 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
2 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

View 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.
Следующий шаг: ручная оценка удобства управления пользователем.

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

View 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
1 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
2 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
3 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
4 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
5 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
6 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 107 KiB

View 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 и пакеты сохранялись только в памяти; бинарные дампы не создавались.

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 95 KiB

Some files were not shown because too many files have changed in this diff Show More