Lab038 — безопасная остановка при потере команд и подтверждаемая аварийная команда

Состояние Git до реализации
- Корень: C:/Users/user/Desktop/projects/SDR_Rover
- Ветка: main
- HEAD: 3e0ef5666eed6833818a731383220b2e15926889
- Известные незакоммиченные файлы: только результаты и исходники Lab037.
- Неизвестных изменений не обнаружено; fetch, pull и push не выполнялись.

Параметры модели
- Один опыт: 120 с; повторов: 100; сочетаний: 48.
- Канал: Bad≈2%, средние Bad=(10.0, 50.0, 200.0, 1000.0) мс, скорости=(300.0, 260.0, 230.0) кбит/с.
- Видео: 512 байт, FEC 12+3, блоки не пересекают составные кадры, 3 кадра/с.
- Команды: 20 Гц; телеметрия: 10 Гц; emergency: 30/60/90 с.
- Приоритет: emergency > ACK > control > telemetry > video; передача пакета не прерывается.
- Watchdog 100/150/250/500 мс вычисляется по одной последовательности приёма каждого опыта.
- CRC-пакетов при построении: 12356; FEC-блоков: 714.
- ACK использует неизменный LinkPacket, направление ROVER_TO_GROUND, отдельный stream_id и payload с identity emergency.

Таблица 48 сочетаний
rate | Bad ms | mode | load kbit/s | queue mean/max | command miss % | max gap ms | emergency <=50 ms % | ACK % | video % | image P95 ms
300 | 10 | single | 258.446 | 8.38/21 | 2.241 | 212.560 | 97.67 | 0.00 | 94.15 | 294.240
300 | 10 | lab037_repetition | 265.831 | 8.70/21 | 0.292 | 185.413 | 100.00 | 0.00 | 94.36 | 301.600
300 | 10 | spread_emergency | 258.574 | 8.39/21 | 2.243 | 212.560 | 97.67 | 0.00 | 94.14 | 294.240
300 | 10 | acknowledged_emergency | 258.455 | 8.38/21 | 2.240 | 212.560 | 97.67 | 100.00 | 94.15 | 294.240
300 | 50 | single | 258.446 | 8.38/21 | 2.087 | 535.067 | 96.33 | 0.00 | 94.18 | 292.293
300 | 50 | lab037_repetition | 265.831 | 8.70/21 | 1.275 | 530.480 | 98.00 | 0.00 | 94.16 | 299.653
300 | 50 | spread_emergency | 258.574 | 8.39/21 | 2.087 | 535.067 | 96.33 | 0.00 | 94.18 | 292.293
300 | 50 | acknowledged_emergency | 258.455 | 8.38/21 | 2.087 | 535.067 | 96.33 | 100.00 | 94.18 | 292.293
300 | 200 | single | 258.446 | 8.38/21 | 2.094 | 1402.427 | 97.00 | 0.00 | 96.12 | 292.293
300 | 200 | lab037_repetition | 265.831 | 8.70/21 | 1.861 | 1386.213 | 97.33 | 0.00 | 96.07 | 299.653
300 | 200 | spread_emergency | 258.574 | 8.39/21 | 2.094 | 1402.427 | 97.00 | 0.00 | 96.12 | 292.293
300 | 200 | acknowledged_emergency | 258.456 | 8.38/21 | 2.094 | 1402.427 | 97.00 | 99.67 | 96.12 | 292.293
300 | 1000 | single | 258.446 | 8.38/21 | 2.513 | 8554.426 | 97.33 | 0.00 | 97.03 | 292.293
300 | 1000 | lab037_repetition | 265.831 | 8.70/21 | 2.460 | 8550.746 | 97.67 | 0.00 | 97.03 | 299.653
300 | 1000 | spread_emergency | 258.574 | 8.39/21 | 2.513 | 8554.426 | 97.33 | 0.00 | 97.03 | 292.293
300 | 1000 | acknowledged_emergency | 258.457 | 8.38/21 | 2.513 | 8554.426 | 97.33 | 98.00 | 97.03 | 292.293
260 | 10 | single | 258.446 | 16.18/36 | 2.243 | 205.046 | 97.00 | 0.00 | 93.83 | 603.271
260 | 10 | lab037_repetition | 265.831 | 16.33/38 | 0.319 | 184.185 | 100.00 | 0.00 | 91.61 | 635.600
260 | 10 | spread_emergency | 258.574 | 16.37/37 | 2.247 | 205.046 | 97.00 | 0.00 | 93.78 | 610.329
260 | 10 | acknowledged_emergency | 258.455 | 16.19/37 | 2.244 | 207.200 | 97.00 | 100.00 | 93.81 | 604.267
260 | 50 | single | 258.446 | 16.18/36 | 2.098 | 501.785 | 98.00 | 0.00 | 94.07 | 603.271
260 | 50 | lab037_repetition | 265.831 | 16.33/38 | 1.327 | 510.585 | 98.67 | 0.00 | 91.40 | 635.098
260 | 50 | spread_emergency | 258.574 | 16.37/37 | 2.094 | 501.785 | 98.00 | 0.00 | 94.00 | 610.329
260 | 50 | acknowledged_emergency | 258.455 | 16.19/37 | 2.088 | 501.785 | 98.00 | 100.00 | 94.06 | 604.267
260 | 200 | single | 258.446 | 16.18/36 | 1.930 | 1867.846 | 98.33 | 0.00 | 96.21 | 603.271
260 | 200 | lab037_repetition | 265.831 | 16.33/38 | 1.718 | 1834.738 | 98.33 | 0.00 | 93.52 | 635.098
260 | 200 | spread_emergency | 258.574 | 16.37/37 | 1.931 | 1867.846 | 98.33 | 0.00 | 96.23 | 610.329
260 | 200 | acknowledged_emergency | 258.455 | 16.20/37 | 1.931 | 1867.846 | 98.33 | 100.00 | 96.21 | 604.267
260 | 1000 | single | 258.446 | 16.18/36 | 1.908 | 5454.092 | 98.00 | 0.00 | 97.63 | 603.271
260 | 1000 | lab037_repetition | 265.831 | 16.33/38 | 1.864 | 5423.631 | 98.33 | 0.00 | 94.91 | 635.098
260 | 1000 | spread_emergency | 258.574 | 16.37/37 | 1.908 | 5460.154 | 98.00 | 0.00 | 97.63 | 610.329
260 | 1000 | acknowledged_emergency | 258.456 | 16.20/37 | 1.908 | 5452.800 | 98.00 | 99.00 | 97.63 | 603.969
230 | 10 | single | 258.446 | 19.43/40 | 2.360 | 216.383 | 98.00 | 0.00 | 83.02 | 670.884
230 | 10 | lab037_repetition | 265.831 | 20.26/39 | 0.359 | 168.104 | 99.00 | 0.00 | 80.01 | 695.130
230 | 10 | spread_emergency | 258.574 | 19.67/39 | 2.371 | 216.383 | 98.33 | 0.00 | 82.95 | 671.803
230 | 10 | acknowledged_emergency | 258.454 | 19.42/40 | 2.351 | 216.383 | 98.33 | 100.00 | 83.02 | 670.122
230 | 50 | single | 258.446 | 19.43/40 | 2.018 | 502.539 | 98.67 | 0.00 | 83.57 | 669.867
230 | 50 | lab037_repetition | 265.831 | 20.26/39 | 1.304 | 467.965 | 98.67 | 0.00 | 80.33 | 695.130
230 | 50 | spread_emergency | 258.574 | 19.67/39 | 2.035 | 502.539 | 98.67 | 0.00 | 83.46 | 671.803
230 | 50 | acknowledged_emergency | 258.454 | 19.42/40 | 2.022 | 502.539 | 98.67 | 100.00 | 83.55 | 669.867
230 | 200 | single | 258.446 | 19.43/40 | 2.022 | 1663.200 | 98.00 | 0.00 | 84.90 | 669.867
230 | 200 | lab037_repetition | 265.831 | 20.26/39 | 1.818 | 1678.643 | 98.33 | 0.00 | 81.65 | 695.130
230 | 200 | spread_emergency | 258.574 | 19.67/39 | 2.022 | 1645.391 | 98.00 | 0.00 | 84.88 | 671.803
230 | 200 | acknowledged_emergency | 258.455 | 19.42/40 | 2.025 | 1619.304 | 98.33 | 100.00 | 84.90 | 669.867
230 | 1000 | single | 258.446 | 19.43/40 | 1.758 | 5994.330 | 99.00 | 0.00 | 86.66 | 669.867
230 | 1000 | lab037_repetition | 265.831 | 20.26/39 | 1.715 | 5998.504 | 99.33 | 0.00 | 83.33 | 695.130
230 | 1000 | spread_emergency | 258.574 | 19.67/39 | 1.752 | 5996.000 | 99.00 | 0.00 | 86.62 | 671.803
230 | 1000 | acknowledged_emergency | 258.455 | 19.42/40 | 1.757 | 5961.322 | 99.00 | 99.67 | 86.65 | 669.867

Обычные команды
- Доля недоставленных состояний: 0.292…2.513%.
- Максимальный промежуток без свежей команды: 8554.426 мс.
- Максимальная серия недоставленных состояний: 170.
- Поток 20 Гц сам создаёт естественное временное разнесение последовательных состояний.

Аварийные команды и подтверждения
- Доставка хотя бы одной emergency-копии: 94.00…100.00%.
- Доставка emergency за 50 мс: 94.00…100.00%.
- Получение ACK в режиме 4: 96.00…100.00%.
- Подтверждение информирует наземную станцию, но не является условием выполнения аварийной остановки.
- Потеря ACK не снимает уже выполненную остановку; дубликат emergency порождает новый ACK.

Сторожевой таймер и безопасность
threshold ms | distance at 25 km/h, m | triggers/min min..max | safe fraction min..max
100 | 0.694 | 1.045…15.370 | 0.000354…0.024072
150 | 1.042 | 0.015…4.380 | 0.000003…0.023038
250 | 1.736 | 0.000…2.405 | 0.000000…0.021092
500 | 3.472 | 0.000…0.895 | 0.000000…0.016968
- Максимальное использование устаревшей команды до локальной остановки: 500.000 мс.
- Превышение порога без включения остановки: 0.
- Снятие временной остановки старой/дублирующей командой: 0.
- Снятие аварийной остановки обычной командой: 0.
- Короткий watchdog чаще вызывает временные остановки; длинный увеличивает путь до остановки. Порог автоматически не выбирается.

Нагрузка, очередь, видео и телеметрия
- Предложенная нагрузка: 258.446…265.831 кбит/с.
- ACK-нагрузка: 0…0.008456 кбит/с.
- Максимальная очередь: 40 пакетов / 22402 байт; waiting video=1.
- Видео опубликовано: 80.01…97.63%; полезный поток 124.732…151.964 кбит/с.
- Телеметрия доставлена: 97.28…98.24%; максимальный разрыв 8592.613 мс.

Принципиальные выводы
- Повторение не гарантирует доставку во время полной физической недоступности канала.
- Срок удалённой аварийной команды 50 мс нельзя гарантировать при помехе длительнее 50 мс.
- Безопасное поведение при такой недоступности обеспечивает локальный сторожевой таймер.
- ACK подтверждает получение для наземной станции, но аварийная остановка выполняется до ACK.

Функциональные проверки
- PASS 01_stale_command_does_not_refresh_watchdog: old/equal sequence leaves timer unchanged
- PASS 02_new_command_refreshes_watchdog: new sequence refreshes timer
- PASS 03_watchdog_expiry_enters_safe_state: zero speed, braking, movement disabled
- PASS 04_new_command_releases_only_temporary_stop: fresh state releases temporary stop
- PASS 05_normal_command_cannot_release_emergency: latched emergency remains effective
- PASS 06_first_emergency_copy_latches_stop: first copy executes stop
- PASS 07_emergency_duplicate_does_not_repeat_action: duplicate counted without repeated action
- PASS 08_ack_contains_emergency_identity: ACK payload identifies stream and sequence
- PASS 09_lost_ack_continues_repetition: observed lost ACK followed by continued copies
- PASS 10_received_ack_stops_future_copies: received ACK removed/skipped future copies
- PASS 11_duplicate_emergency_can_repeat_ack: received duplicate generated another ACK
- PASS 12_late_old_command_no_rollback: late old state ignored
- PASS 13_emergency_has_highest_priority: scheduler rank emergency=1
- PASS 14_ack_above_normal_control: scheduler rank ACK=2, control=3
- PASS 15_current_packet_is_nonpreemptive: all serialization intervals are disjoint
- PASS 16_repetitions_and_acks_in_load: repeat and ACK bytes observed in accounting
- PASS 17_latest_unstarted_video_is_bounded: at most one unstarted video frame
- PASS 18_incomplete_video_not_published: k-1 symbols cannot publish a block
- PASS 19_crc_and_fec_validate_received_data: valid data decodes; both CRC layers reject damage
- PASS 20_fixed_seed_reproducibility: same seed gives identical Bad intervals

Созданные файлы
- protocol/control_failsafe.py
- protocol/emergency_ack.py
- tests/lab038_control_failsafe.py
- data/processed/lab038/lab038_summary.csv
- data/processed/lab038/lab038_command_metrics.csv
- data/processed/lab038/lab038_emergency_metrics.csv
- data/processed/lab038/lab038_failsafe_metrics.csv
- data/processed/lab038/lab038_video_metrics.csv
- data/processed/lab038/lab038_report.txt
- data/processed/lab038/lab038_command_gap.png
- data/processed/lab038/lab038_watchdog_triggers.png
- data/processed/lab038/lab038_safe_stop_time.png
- data/processed/lab038/lab038_emergency_timeliness.png
- data/processed/lab038/lab038_ack_time.png
- data/processed/lab038/lab038_additional_load.png
- data/processed/lab038/lab038_video_impact.png
- data/processed/lab038/lab038_mode_comparison.png

Итоговый git status
?? data/processed/lab037/
?? data/processed/lab038/
?? protocol/control_failsafe.py
?? protocol/control_repetition.py
?? protocol/emergency_ack.py
?? tests/lab037_lossy_full_link.py
?? tests/lab038_control_failsafe.py

Lab038 не добавлен в Git и не закоммичен. Двоичные пакеты, JPEG, дампы и подробные пакетные журналы не сохранялись.
