diff --git a/PROJECT_LOG.md b/PROJECT_LOG.md index dede328..1f89497 100644 --- a/PROJECT_LOG.md +++ b/PROJECT_LOG.md @@ -361,3 +361,27 @@ git version 2.51.1.windows.1 - Подтверждение сброса не восстанавливает старую команду движения. - Движение требует новой явной команды оператора. - Следующий этап посвящён сеансам связи, перезапускам устройств и защите от пакетов предыдущего сеанса. + +--- + +# Запись 016 + +## Дата + +5 августа 2026 года + +## Тема + +Завершение Lab041: сеансы связи, безопасный запуск и защита от пакетов предыдущего сеанса. + +## Выполнено + +- Lab041 вводит идентификаторы сеанса станции, запуска ровера и периода управления. +- Одного номера сообщения недостаточно после перезапуска. +- В основном режиме все 2807 введённых старых пакетов были отклонены. +- Ошибочно принятых старых пакетов не было. +- Исходный режим без идентификаторов принял все старые пакеты. +- После перезапуска движение запрещено до нового согласования, подтверждения разрешения и новой команды оператора. +- Аварийное намерение наземной станции сохраняется после перезапуска. +- Неоднозначная разность номеров 2^31 отклоняется. +- Следующий этап посвящён криптографической проверке подлинности управляющих сообщений и защите от намеренной подделки. diff --git a/data/processed/lab041/lab041_authorization_time.png b/data/processed/lab041/lab041_authorization_time.png new file mode 100644 index 0000000..8bef6e5 Binary files /dev/null and b/data/processed/lab041/lab041_authorization_time.png differ diff --git a/data/processed/lab041/lab041_emergency_intent.png b/data/processed/lab041/lab041_emergency_intent.png new file mode 100644 index 0000000..e9e7123 Binary files /dev/null and b/data/processed/lab041/lab041_emergency_intent.png differ diff --git a/data/processed/lab041/lab041_load_metrics.csv b/data/processed/lab041/lab041_load_metrics.csv new file mode 100644 index 0000000..3d3fa8b --- /dev/null +++ b/data/processed/lab041/lab041_load_metrics.csv @@ -0,0 +1,181 @@ +architecture,channel_condition,scenario,repetitions,control_state_packet_bytes,control_state_messages_per_second,control_state_load_kbps,application_header_fraction,lab040_control_load_kbps,control_load_increase_kbps,session_load_kbps,authorization_load_kbps,emergency_load_kbps,retry_load_kbps,episodic_service_load_kbps,video_offered_load_kbps,telemetry_offered_load_kbps,full_offered_load_kbps,control_delivered_fraction,telemetry_delivered_fraction,video_published_fraction,maximum_queue_packets +no_session_ids,no_loss,normal_start,1,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.0,0.0,0.0,0.0,0.0,243.39286666666666,7.68,261.9528666666667,0.9988266666666666,0.9994133333333334,0.99824,21 +no_session_ids,no_loss,ground_restart_moving,1,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.0,0.0,0.0,0.0,0.0,243.39286666666666,7.68,261.9528666666667,0.9988266666666666,0.9994133333333334,0.99824,21 +no_session_ids,no_loss,rover_restart_moving,1,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.0,0.0,0.0,0.0,0.0,243.39286666666666,7.68,261.9528666666667,0.9988266666666666,0.9994133333333334,0.99824,21 +no_session_ids,no_loss,both_restart,1,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.0,0.0,0.0,0.0,0.0,243.39286666666666,7.68,261.9528666666667,0.9988266666666666,0.9994133333333334,0.99824,21 +no_session_ids,no_loss,ground_restart_emergency,1,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.0,0.0,0.0,0.0,0.0,243.39286666666666,7.68,261.9528666666667,0.9988266666666666,0.9994133333333334,0.99824,21 +no_session_ids,no_loss,rover_restart_latched,1,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.0,0.0,0.0,0.0,0.0,243.39286666666666,7.68,261.9528666666667,0.9988266666666666,0.9994133333333334,0.99824,21 +no_session_ids,no_loss,long_link_break,1,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.0,0.0,0.0,0.0,0.0,243.39286666666666,7.68,261.9528666666667,0.9988266666666666,0.9994133333333334,0.99824,21 +no_session_ids,no_loss,old_ground_session_control,1,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.0,0.0,0.0,0.0,0.0,243.39286666666666,7.68,261.9528666666667,0.9988266666666666,0.9994133333333334,0.99824,21 +no_session_ids,no_loss,old_rover_boot_control,1,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.0,0.0,0.0,0.0,0.0,243.39286666666666,7.68,261.9528666666667,0.9988266666666666,0.9994133333333334,0.99824,21 +no_session_ids,no_loss,old_control_epoch,1,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.0,0.0,0.0,0.0,0.0,243.39286666666666,7.68,261.9528666666667,0.9988266666666666,0.9994133333333334,0.99824,21 +no_session_ids,no_loss,sequence_reset_new_session,1,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.0,0.0,0.0,0.0,0.0,243.39286666666666,7.68,261.9528666666667,0.9988266666666666,0.9994133333333334,0.99824,21 +no_session_ids,no_loss,sequence_wrap,1,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.0,0.0,0.0,0.0,0.0,243.39286666666666,7.68,261.9528666666667,0.9988266666666666,0.9994133333333334,0.99824,21 +no_session_ids,no_loss,duplicate_hello,1,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.0,0.0,0.0,0.0,0.0,243.39286666666666,7.68,261.9528666666667,0.9988266666666666,0.9994133333333334,0.99824,21 +no_session_ids,no_loss,lost_session_status,1,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.0,0.0,0.0,0.0,0.0,243.39286666666666,7.68,261.9528666666667,0.9988266666666666,0.9994133333333334,0.99824,21 +no_session_ids,no_loss,lost_authorize_ack,1,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.0,0.0,0.0,0.0,0.0,243.39286666666666,7.68,261.9528666666667,0.9988266666666666,0.9994133333333334,0.99824,21 +no_session_ids,no_loss,lost_emergency_ack,1,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.0,0.0,0.0528,0.0528,0.1056,243.39286666666666,7.68,262.0584666666667,0.9987914666666666,0.9993957333333333,0.9981872,22 +no_session_ids,no_loss,lost_reset_ack,1,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.0,0.0,0.062,0.062,0.124,243.39286666666666,7.68,262.0768666666667,0.9987853333333333,0.9993926666666667,0.998178,22 +no_session_ids,no_loss,old_reset_request,1,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.0,0.0,0.0,0.0,0.0,243.39286666666666,7.68,261.9528666666667,0.9988266666666666,0.9994133333333334,0.99824,21 +no_session_ids,no_loss,late_positive_after_emergency,1,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.0,0.0,0.0,0.0,0.0,243.39286666666666,7.68,261.9528666666667,0.9988266666666666,0.9994133333333334,0.99824,21 +no_session_ids,no_loss,restart_after_reset_before_ack,1,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.0,0.0,0.0,0.0,0.0,243.39286666666666,7.68,261.9528666666667,0.9988266666666666,0.9994133333333334,0.99824,21 +no_session_ids,260_200,normal_start,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.0,0.0,0.0,0.0,0.0,243.39286666666666,7.68,261.9528666666667,0.9786461538461536,0.9813230769230771,0.9079692307692306,31 +no_session_ids,260_200,ground_restart_moving,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.0,0.0,0.0,0.0,0.0,243.39286666666666,7.68,261.9528666666667,0.9786461538461536,0.9813230769230771,0.9079692307692306,31 +no_session_ids,260_200,rover_restart_moving,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.0,0.0,0.0,0.0,0.0,243.39286666666666,7.68,261.9528666666667,0.9786461538461536,0.9813230769230771,0.9079692307692306,31 +no_session_ids,260_200,both_restart,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.0,0.0,0.0,0.0,0.0,243.39286666666666,7.68,261.9528666666667,0.9786461538461536,0.9813230769230771,0.9079692307692306,31 +no_session_ids,260_200,ground_restart_emergency,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.0,0.0,0.0,0.0,0.0,243.39286666666666,7.68,261.9528666666667,0.9786461538461536,0.9813230769230771,0.9079692307692306,31 +no_session_ids,260_200,rover_restart_latched,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.0,0.0,0.0,0.0,0.0,243.39286666666666,7.68,261.9528666666667,0.9786461538461536,0.9813230769230771,0.9079692307692306,31 +no_session_ids,260_200,long_link_break,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.0,0.0,0.0,0.0,0.0,243.39286666666666,7.68,261.9528666666667,0.9786461538461536,0.9813230769230771,0.9079692307692306,31 +no_session_ids,260_200,old_ground_session_control,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.0,0.0,0.0,0.0,0.0,243.39286666666666,7.68,261.9528666666667,0.9786461538461536,0.9813230769230771,0.9079692307692306,31 +no_session_ids,260_200,old_rover_boot_control,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.0,0.0,0.0,0.0,0.0,243.39286666666666,7.68,261.9528666666667,0.9786461538461536,0.9813230769230771,0.9079692307692306,31 +no_session_ids,260_200,old_control_epoch,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.0,0.0,0.0,0.0,0.0,243.39286666666666,7.68,261.9528666666667,0.9786461538461536,0.9813230769230771,0.9079692307692306,31 +no_session_ids,260_200,sequence_reset_new_session,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.0,0.0,0.0,0.0,0.0,243.39286666666666,7.68,261.9528666666667,0.9786461538461536,0.9813230769230771,0.9079692307692306,31 +no_session_ids,260_200,sequence_wrap,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.0,0.0,0.0,0.0,0.0,243.39286666666666,7.68,261.9528666666667,0.9786461538461536,0.9813230769230771,0.9079692307692306,31 +no_session_ids,260_200,duplicate_hello,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.0,0.0,0.0,0.0,0.0,243.39286666666666,7.68,261.9528666666667,0.9786461538461536,0.9813230769230771,0.9079692307692306,31 +no_session_ids,260_200,lost_session_status,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.0,0.0,0.0,0.0,0.0,243.39286666666666,7.68,261.9528666666667,0.9786461538461536,0.9813230769230771,0.9079692307692306,31 +no_session_ids,260_200,lost_authorize_ack,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.0,0.0,0.0,0.0,0.0,243.39286666666666,7.68,261.9528666666667,0.9786461538461536,0.9813230769230771,0.9079692307692306,31 +no_session_ids,260_200,lost_emergency_ack,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.0,0.0,0.0528,0.057288,0.110088,243.39286666666666,7.68,262.0629546666667,0.9786038123076922,0.981301906153846,0.9079057184615386,36 +no_session_ids,260_200,lost_reset_ack,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.0,0.0,0.062,0.065318,0.12731800000000001,243.39286666666666,7.68,262.0801846666667,0.978597185384615,0.9812985926923079,0.9078957780769232,36 +no_session_ids,260_200,old_reset_request,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.0,0.0,0.0,0.0,0.0,243.39286666666666,7.68,261.9528666666667,0.9786461538461536,0.9813230769230771,0.9079692307692306,31 +no_session_ids,260_200,late_positive_after_emergency,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.0,0.0,0.0,0.0,0.0,243.39286666666666,7.68,261.9528666666667,0.9786461538461536,0.9813230769230771,0.9079692307692306,31 +no_session_ids,260_200,restart_after_reset_before_ack,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.0,0.0,0.0,0.0,0.0,243.39286666666666,7.68,261.9528666666667,0.9786461538461536,0.9813230769230771,0.9079692307692306,31 +no_session_ids,230_1000,normal_start,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.0,0.0,0.0,0.0,0.0,243.39286666666666,7.68,261.9528666666667,0.9784695652173915,0.9792347826086959,0.8607043478260868,41 +no_session_ids,230_1000,ground_restart_moving,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.0,0.0,0.0,0.0,0.0,243.39286666666666,7.68,261.9528666666667,0.9784695652173915,0.9792347826086959,0.8607043478260868,41 +no_session_ids,230_1000,rover_restart_moving,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.0,0.0,0.0,0.0,0.0,243.39286666666666,7.68,261.9528666666667,0.9784695652173915,0.9792347826086959,0.8607043478260868,41 +no_session_ids,230_1000,both_restart,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.0,0.0,0.0,0.0,0.0,243.39286666666666,7.68,261.9528666666667,0.9784695652173915,0.9792347826086959,0.8607043478260868,41 +no_session_ids,230_1000,ground_restart_emergency,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.0,0.0,0.0,0.0,0.0,243.39286666666666,7.68,261.9528666666667,0.9784695652173915,0.9792347826086959,0.8607043478260868,41 +no_session_ids,230_1000,rover_restart_latched,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.0,0.0,0.0,0.0,0.0,243.39286666666666,7.68,261.9528666666667,0.9784695652173915,0.9792347826086959,0.8607043478260868,41 +no_session_ids,230_1000,long_link_break,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.0,0.0,0.0,0.0,0.0,243.39286666666666,7.68,261.9528666666667,0.9784695652173915,0.9792347826086959,0.8607043478260868,41 +no_session_ids,230_1000,old_ground_session_control,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.0,0.0,0.0,0.0,0.0,243.39286666666666,7.68,261.9528666666667,0.9784695652173915,0.9792347826086959,0.8607043478260868,41 +no_session_ids,230_1000,old_rover_boot_control,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.0,0.0,0.0,0.0,0.0,243.39286666666666,7.68,261.9528666666667,0.9784695652173915,0.9792347826086959,0.8607043478260868,41 +no_session_ids,230_1000,old_control_epoch,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.0,0.0,0.0,0.0,0.0,243.39286666666666,7.68,261.9528666666667,0.9784695652173915,0.9792347826086959,0.8607043478260868,41 +no_session_ids,230_1000,sequence_reset_new_session,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.0,0.0,0.0,0.0,0.0,243.39286666666666,7.68,261.9528666666667,0.9784695652173915,0.9792347826086959,0.8607043478260868,41 +no_session_ids,230_1000,sequence_wrap,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.0,0.0,0.0,0.0,0.0,243.39286666666666,7.68,261.9528666666667,0.9784695652173915,0.9792347826086959,0.8607043478260868,41 +no_session_ids,230_1000,duplicate_hello,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.0,0.0,0.0,0.0,0.0,243.39286666666666,7.68,261.9528666666667,0.9784695652173915,0.9792347826086959,0.8607043478260868,41 +no_session_ids,230_1000,lost_session_status,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.0,0.0,0.0,0.0,0.0,243.39286666666666,7.68,261.9528666666667,0.9784695652173915,0.9792347826086959,0.8607043478260868,41 +no_session_ids,230_1000,lost_authorize_ack,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.0,0.0,0.0,0.0,0.0,243.39286666666666,7.68,261.9528666666667,0.9784695652173915,0.9792347826086959,0.8607043478260868,41 +no_session_ids,230_1000,lost_emergency_ack,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.0,0.0,0.0528,0.11536800000000001,0.168168,243.39286666666666,7.68,262.1210346666667,0.978396448695652,0.9791982243478259,0.8605946730434781,46 +no_session_ids,230_1000,lost_reset_ack,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.0,0.0,0.062,0.075272,0.137272,243.39286666666666,7.68,262.0901386666667,0.9784098817391305,0.9792049408695651,0.8606148226086957,46 +no_session_ids,230_1000,old_reset_request,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.0,0.0,0.0,0.0,0.0,243.39286666666666,7.68,261.9528666666667,0.9784695652173915,0.9792347826086959,0.8607043478260868,41 +no_session_ids,230_1000,late_positive_after_emergency,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.0,0.0,0.0,0.0,0.0,243.39286666666666,7.68,261.9528666666667,0.9784695652173915,0.9792347826086959,0.8607043478260868,41 +no_session_ids,230_1000,restart_after_reset_before_ack,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.0,0.0,0.0,0.0,0.0,243.39286666666666,7.68,261.9528666666667,0.9784695652173915,0.9792347826086959,0.8607043478260868,41 +session_safe_boot,no_loss,normal_start,1,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.0,0.1072,243.39286666666666,7.68,262.06006666666667,0.9987909333333334,0.9993954666666667,0.9981864,21 +session_safe_boot,no_loss,ground_restart_moving,1,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.0,0.1072,243.39286666666666,7.68,262.06006666666667,0.9987909333333334,0.9993954666666667,0.9981864,21 +session_safe_boot,no_loss,rover_restart_moving,1,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.0,0.1072,243.39286666666666,7.68,262.06006666666667,0.9987909333333334,0.9993954666666667,0.9981864,21 +session_safe_boot,no_loss,both_restart,1,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.0,0.1072,243.39286666666666,7.68,262.06006666666667,0.9987909333333334,0.9993954666666667,0.9981864,21 +session_safe_boot,no_loss,ground_restart_emergency,1,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.0,0.0,0.0,0.054,243.39286666666666,7.68,262.00686666666667,0.9988086666666667,0.9994043333333333,0.998213,21 +session_safe_boot,no_loss,rover_restart_latched,1,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.0,0.0,0.0,0.054,243.39286666666666,7.68,262.00686666666667,0.9988086666666667,0.9994043333333333,0.998213,21 +session_safe_boot,no_loss,long_link_break,1,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.0,0.1072,243.39286666666666,7.68,262.06006666666667,0.9987909333333334,0.9993954666666667,0.9981864,21 +session_safe_boot,no_loss,old_ground_session_control,1,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.0,0.1072,243.39286666666666,7.68,262.06006666666667,0.9987909333333334,0.9993954666666667,0.9981864,21 +session_safe_boot,no_loss,old_rover_boot_control,1,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.0,0.1072,243.39286666666666,7.68,262.06006666666667,0.9987909333333334,0.9993954666666667,0.9981864,21 +session_safe_boot,no_loss,old_control_epoch,1,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.0,0.1072,243.39286666666666,7.68,262.06006666666667,0.9987909333333334,0.9993954666666667,0.9981864,21 +session_safe_boot,no_loss,sequence_reset_new_session,1,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.0,0.1072,243.39286666666666,7.68,262.06006666666667,0.9987909333333334,0.9993954666666667,0.9981864,21 +session_safe_boot,no_loss,sequence_wrap,1,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.0,0.1072,243.39286666666666,7.68,262.06006666666667,0.9987909333333334,0.9993954666666667,0.9981864,21 +session_safe_boot,no_loss,duplicate_hello,1,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.054,0.16119999999999998,243.39286666666666,7.68,262.1140666666667,0.9987729333333333,0.9993864666666666,0.9981594,21 +session_safe_boot,no_loss,lost_session_status,1,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.054,0.16119999999999998,243.39286666666666,7.68,262.1140666666667,0.9987729333333333,0.9993864666666666,0.9981594,22 +session_safe_boot,no_loss,lost_authorize_ack,1,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.053200000000000004,0.16040000000000001,243.39286666666666,7.68,262.1132666666667,0.9987732,0.9993866,0.9981598,22 +session_safe_boot,no_loss,lost_emergency_ack,1,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0528,0.0528,0.21280000000000002,243.39286666666666,7.68,262.1656666666667,0.9987557333333333,0.9993778666666666,0.9981336,22 +session_safe_boot,no_loss,lost_reset_ack,1,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.062,0.062,0.2312,243.39286666666666,7.68,262.1840666666667,0.9987496,0.9993748,0.9981244,22 +session_safe_boot,no_loss,old_reset_request,1,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.0,0.1072,243.39286666666666,7.68,262.06006666666667,0.9987909333333334,0.9993954666666667,0.9981864,21 +session_safe_boot,no_loss,late_positive_after_emergency,1,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.0,0.1072,243.39286666666666,7.68,262.06006666666667,0.9987909333333334,0.9993954666666667,0.9981864,21 +session_safe_boot,no_loss,restart_after_reset_before_ack,1,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.0,0.1072,243.39286666666666,7.68,262.06006666666667,0.9987909333333334,0.9993954666666667,0.9981864,21 +session_safe_boot,260_200,normal_start,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.0,0.1072,243.39286666666666,7.68,262.06006666666667,0.9786049230769228,0.9813024615384619,0.9079073846153847,31 +session_safe_boot,260_200,ground_restart_moving,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.0,0.1072,243.39286666666666,7.68,262.06006666666667,0.9786049230769228,0.9813024615384619,0.9079073846153847,31 +session_safe_boot,260_200,rover_restart_moving,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.0013199999999999998,0.10852,243.39286666666666,7.68,262.0613866666667,0.9786044153846152,0.9813022076923079,0.9079066230769232,36 +session_safe_boot,260_200,both_restart,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.002904,0.110104,243.39286666666666,7.68,262.0629706666667,0.9786038061538459,0.9813019030769234,0.9079057092307693,36 +session_safe_boot,260_200,ground_restart_emergency,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.0,0.0,0.0,0.054,243.39286666666666,7.68,262.00686666666667,0.9786253846153845,0.9813126923076924,0.9079380769230773,31 +session_safe_boot,260_200,rover_restart_latched,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.0,0.0,0.0,0.054,243.39286666666666,7.68,262.00686666666667,0.9786253846153845,0.9813126923076924,0.9079380769230773,31 +session_safe_boot,260_200,long_link_break,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.0062759999999999995,0.113476,243.39286666666666,7.68,262.0663426666667,0.9786025092307691,0.9813012546153849,0.907903763846154,36 +session_safe_boot,260_200,old_ground_session_control,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.0007920000000000001,0.107992,243.39286666666666,7.68,262.0608586666667,0.9786046184615382,0.9813023092307697,0.9079069276923077,35 +session_safe_boot,260_200,old_rover_boot_control,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.000528,0.10772799999999999,243.39286666666666,7.68,262.0605946666667,0.9786047199999998,0.9813023600000003,0.9079070800000001,34 +session_safe_boot,260_200,old_control_epoch,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.0,0.1072,243.39286666666666,7.68,262.06006666666667,0.9786049230769228,0.9813024615384619,0.9079073846153847,31 +session_safe_boot,260_200,sequence_reset_new_session,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.0027719999999999997,0.10997200000000001,243.39286666666666,7.68,262.0628386666667,0.9786038569230766,0.9813019284615387,0.9079057853846154,36 +session_safe_boot,260_200,sequence_wrap,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.0,0.1072,243.39286666666666,7.68,262.06006666666667,0.9786049230769228,0.9813024615384619,0.9079073846153847,31 +session_safe_boot,260_200,duplicate_hello,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.054,0.16119999999999998,243.39286666666666,7.68,262.1140666666667,0.9785841538461537,0.9812920769230772,0.907876230769231,31 +session_safe_boot,260_200,lost_session_status,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.055056,0.162256,243.39286666666666,7.68,262.1151226666667,0.9785837476923075,0.9812918738461539,0.9078756215384618,36 +session_safe_boot,260_200,lost_authorize_ack,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.053200000000000004,0.16040000000000001,243.39286666666666,7.68,262.1132666666667,0.9785844615384616,0.981292230769231,0.9078766923076921,32 +session_safe_boot,260_200,lost_emergency_ack,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0528,0.058476,0.21847600000000003,243.39286666666666,7.68,262.1713426666667,0.9785621246153846,0.9812810623076923,0.9078431869230771,36 +session_safe_boot,260_200,lost_reset_ack,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.062,0.06626599999999999,0.23546599999999998,243.39286666666666,7.68,262.18833266666667,0.9785555899999997,0.9812777950000001,0.907833385,36 +session_safe_boot,260_200,old_reset_request,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.0007920000000000001,0.107992,243.39286666666666,7.68,262.0608586666667,0.9786046184615382,0.9813023092307697,0.9079069276923077,36 +session_safe_boot,260_200,late_positive_after_emergency,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.0026399999999999996,0.10984000000000001,243.39286666666666,7.68,262.0627066666667,0.9786039076923074,0.9813019538461542,0.9079058615384616,36 +session_safe_boot,260_200,restart_after_reset_before_ack,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.000132,0.107332,243.39286666666666,7.68,262.0601986666667,0.9786048723076921,0.9813024361538464,0.9079073084615384,32 +session_safe_boot,230_1000,normal_start,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.0,0.1072,243.39286666666666,7.68,262.06006666666667,0.978422956521739,0.9792114782608698,0.8606344347826089,41 +session_safe_boot,230_1000,ground_restart_moving,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.0,0.1072,243.39286666666666,7.68,262.06006666666667,0.978422956521739,0.9792114782608698,0.8606344347826089,41 +session_safe_boot,230_1000,rover_restart_moving,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.0,0.1072,243.39286666666666,7.68,262.06006666666667,0.978422956521739,0.9792114782608698,0.8606344347826089,41 +session_safe_boot,230_1000,both_restart,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.0063360000000000005,0.11353599999999998,243.39286666666666,7.68,262.0664026666667,0.9784202017391302,0.9792101008695654,0.860630302608696,46 +session_safe_boot,230_1000,ground_restart_emergency,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.0,0.0,0.0,0.054,243.39286666666666,7.68,262.00686666666667,0.9784460869565217,0.9792230434782607,0.8606691304347825,41 +session_safe_boot,230_1000,rover_restart_latched,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.0,0.0,0.0,0.054,243.39286666666666,7.68,262.00686666666667,0.9784460869565217,0.9792230434782607,0.8606691304347825,41 +session_safe_boot,230_1000,long_link_break,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.022174,0.129374,243.39286666666666,7.68,262.0822406666667,0.9784133156521737,0.9792066578260871,0.860619973478261,46 +session_safe_boot,230_1000,old_ground_session_control,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.0,0.1072,243.39286666666666,7.68,262.06006666666667,0.978422956521739,0.9792114782608698,0.8606344347826089,41 +session_safe_boot,230_1000,old_rover_boot_control,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.0,0.1072,243.39286666666666,7.68,262.06006666666667,0.978422956521739,0.9792114782608698,0.8606344347826089,41 +session_safe_boot,230_1000,old_control_epoch,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.0,0.1072,243.39286666666666,7.68,262.06006666666667,0.978422956521739,0.9792114782608698,0.8606344347826089,41 +session_safe_boot,230_1000,sequence_reset_new_session,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.001452,0.108652,243.39286666666666,7.68,262.0615186666667,0.978422325217391,0.9792111626086958,0.8606334878260873,46 +session_safe_boot,230_1000,sequence_wrap,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.0,0.1072,243.39286666666666,7.68,262.06006666666667,0.978422956521739,0.9792114782608698,0.8606344347826089,41 +session_safe_boot,230_1000,duplicate_hello,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.054,0.16119999999999998,243.39286666666666,7.68,262.1140666666667,0.9783994782608693,0.9791997391304347,0.8605992173913043,41 +session_safe_boot,230_1000,lost_session_status,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.054,0.16119999999999998,243.39286666666666,7.68,262.1140666666667,0.9783994782608693,0.9791997391304347,0.8605992173913043,42 +session_safe_boot,230_1000,lost_authorize_ack,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.053200000000000004,0.16040000000000001,243.39286666666666,7.68,262.1132666666667,0.9783998260869565,0.9791999130434783,0.8605997391304347,42 +session_safe_boot,230_1000,lost_emergency_ack,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0528,0.07378799999999999,0.23378800000000002,243.39286666666666,7.68,262.1866546666667,0.9783679182608697,0.979183959130435,0.8605518773913041,46 +session_safe_boot,230_1000,lost_reset_ack,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.062,0.077852,0.247052,243.39286666666666,7.68,262.1999186666667,0.9783621513043473,0.9791810756521738,0.8605432269565216,46 +session_safe_boot,230_1000,old_reset_request,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.0,0.1072,243.39286666666666,7.68,262.06006666666667,0.978422956521739,0.9792114782608698,0.8606344347826089,41 +session_safe_boot,230_1000,late_positive_after_emergency,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.0,0.1072,243.39286666666666,7.68,262.06006666666667,0.978422956521739,0.9792114782608698,0.8606344347826089,41 +session_safe_boot,230_1000,restart_after_reset_before_ack,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.0,0.1072,243.39286666666666,7.68,262.06006666666667,0.978422956521739,0.9792114782608698,0.8606344347826089,41 +persistent_emergency,no_loss,normal_start,1,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.0,0.1072,243.39286666666666,7.68,262.06006666666667,0.9987909333333334,0.9993954666666667,0.9981864,21 +persistent_emergency,no_loss,ground_restart_moving,1,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.0,0.1072,243.39286666666666,7.68,262.06006666666667,0.9987909333333334,0.9993954666666667,0.9981864,21 +persistent_emergency,no_loss,rover_restart_moving,1,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.0,0.1072,243.39286666666666,7.68,262.06006666666667,0.9987909333333334,0.9993954666666667,0.9981864,21 +persistent_emergency,no_loss,both_restart,1,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.0,0.1072,243.39286666666666,7.68,262.06006666666667,0.9987909333333334,0.9993954666666667,0.9981864,21 +persistent_emergency,no_loss,ground_restart_emergency,1,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.0,0.0,0.0,0.054,243.39286666666666,7.68,262.00686666666667,0.9988086666666667,0.9994043333333333,0.998213,21 +persistent_emergency,no_loss,rover_restart_latched,1,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.0,0.0,0.0,0.054,243.39286666666666,7.68,262.00686666666667,0.9988086666666667,0.9994043333333333,0.998213,21 +persistent_emergency,no_loss,long_link_break,1,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.0,0.1072,243.39286666666666,7.68,262.06006666666667,0.9987909333333334,0.9993954666666667,0.9981864,21 +persistent_emergency,no_loss,old_ground_session_control,1,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.0,0.1072,243.39286666666666,7.68,262.06006666666667,0.9987909333333334,0.9993954666666667,0.9981864,21 +persistent_emergency,no_loss,old_rover_boot_control,1,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.0,0.1072,243.39286666666666,7.68,262.06006666666667,0.9987909333333334,0.9993954666666667,0.9981864,21 +persistent_emergency,no_loss,old_control_epoch,1,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.0,0.1072,243.39286666666666,7.68,262.06006666666667,0.9987909333333334,0.9993954666666667,0.9981864,21 +persistent_emergency,no_loss,sequence_reset_new_session,1,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.0,0.1072,243.39286666666666,7.68,262.06006666666667,0.9987909333333334,0.9993954666666667,0.9981864,21 +persistent_emergency,no_loss,sequence_wrap,1,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.0,0.1072,243.39286666666666,7.68,262.06006666666667,0.9987909333333334,0.9993954666666667,0.9981864,21 +persistent_emergency,no_loss,duplicate_hello,1,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.054,0.16119999999999998,243.39286666666666,7.68,262.1140666666667,0.9987729333333333,0.9993864666666666,0.9981594,21 +persistent_emergency,no_loss,lost_session_status,1,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.054,0.16119999999999998,243.39286666666666,7.68,262.1140666666667,0.9987729333333333,0.9993864666666666,0.9981594,22 +persistent_emergency,no_loss,lost_authorize_ack,1,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.053200000000000004,0.16040000000000001,243.39286666666666,7.68,262.1132666666667,0.9987732,0.9993866,0.9981598,22 +persistent_emergency,no_loss,lost_emergency_ack,1,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0528,0.0528,0.21280000000000002,243.39286666666666,7.68,262.1656666666667,0.9987557333333333,0.9993778666666666,0.9981336,22 +persistent_emergency,no_loss,lost_reset_ack,1,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.062,0.062,0.2312,243.39286666666666,7.68,262.1840666666667,0.9987496,0.9993748,0.9981244,22 +persistent_emergency,no_loss,old_reset_request,1,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.0,0.1072,243.39286666666666,7.68,262.06006666666667,0.9987909333333334,0.9993954666666667,0.9981864,21 +persistent_emergency,no_loss,late_positive_after_emergency,1,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.0,0.1072,243.39286666666666,7.68,262.06006666666667,0.9987909333333334,0.9993954666666667,0.9981864,21 +persistent_emergency,no_loss,restart_after_reset_before_ack,1,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.0,0.1072,243.39286666666666,7.68,262.06006666666667,0.9987909333333334,0.9993954666666667,0.9981864,21 +persistent_emergency,260_200,normal_start,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.000132,0.107332,243.39286666666666,7.68,262.0601986666667,0.9786048723076921,0.9813024361538464,0.9079073084615384,32 +persistent_emergency,260_200,ground_restart_moving,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.001056,0.108256,243.39286666666666,7.68,262.0611226666667,0.9786045169230766,0.9813022584615387,0.9079067753846155,35 +persistent_emergency,260_200,rover_restart_moving,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.001716,0.10891600000000001,243.39286666666666,7.68,262.0617826666667,0.9786042630769228,0.9813021315384617,0.9079063946153846,36 +persistent_emergency,260_200,both_restart,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.000528,0.10772799999999999,243.39286666666666,7.68,262.0605946666667,0.9786047199999998,0.9813023600000003,0.9079070800000001,33 +persistent_emergency,260_200,ground_restart_emergency,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.0,0.0,0.0,0.054,243.39286666666666,7.68,262.00686666666667,0.9786253846153845,0.9813126923076924,0.9079380769230773,31 +persistent_emergency,260_200,rover_restart_latched,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.0,0.0,0.0,0.054,243.39286666666666,7.68,262.00686666666667,0.9786253846153845,0.9813126923076924,0.9079380769230773,31 +persistent_emergency,260_200,long_link_break,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.004794,0.111994,243.39286666666666,7.68,262.0648606666667,0.9786030792307691,0.981301539615385,0.9079046188461538,36 +persistent_emergency,260_200,old_ground_session_control,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.00039600000000000003,0.107596,243.39286666666666,7.68,262.0604626666667,0.9786047707692305,0.9813023853846157,0.9079071561538461,33 +persistent_emergency,260_200,old_rover_boot_control,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.0006599999999999999,0.10785999999999998,243.39286666666666,7.68,262.0607266666667,0.9786046692307689,0.981302334615385,0.9079070038461539,34 +persistent_emergency,260_200,old_control_epoch,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.000924,0.108124,243.39286666666666,7.68,262.06099066666667,0.9786045676923075,0.981302283846154,0.9079068515384615,36 +persistent_emergency,260_200,sequence_reset_new_session,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.0037,0.11090000000000001,243.39286666666666,7.68,262.0637666666667,0.9786034999999998,0.9813017500000004,0.90790525,36 +persistent_emergency,260_200,sequence_wrap,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.0013199999999999998,0.10852,243.39286666666666,7.68,262.0613866666667,0.9786044153846152,0.981302207692308,0.9079066230769232,36 +persistent_emergency,260_200,duplicate_hello,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.054,0.16119999999999998,243.39286666666666,7.68,262.1140666666667,0.9785841538461537,0.9812920769230772,0.907876230769231,31 +persistent_emergency,260_200,lost_session_status,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.054268,0.16146800000000003,243.39286666666666,7.68,262.1143346666667,0.9785840507692305,0.9812920253846156,0.9078760761538465,34 +persistent_emergency,260_200,lost_authorize_ack,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.058744000000000005,0.165944,243.39286666666666,7.68,262.1188106666667,0.9785823292307694,0.9812911646153849,0.9078734938461537,36 +persistent_emergency,260_200,lost_emergency_ack,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0528,0.059267999999999994,0.21926799999999996,243.39286666666666,7.68,262.1721346666667,0.9785618199999999,0.9812809099999998,0.9078427300000002,36 +persistent_emergency,260_200,lost_reset_ack,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.062,0.067428,0.236628,243.39286666666666,7.68,262.1894946666667,0.9785551430769229,0.9812775715384617,0.9078327146153846,36 +persistent_emergency,260_200,old_reset_request,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.001452,0.108652,243.39286666666666,7.68,262.0615186666667,0.9786043646153842,0.9813021823076926,0.9079065469230769,36 +persistent_emergency,260_200,late_positive_after_emergency,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.0015840000000000001,0.10878399999999999,243.39286666666666,7.68,262.0616506666667,0.9786043138461537,0.9813021569230773,0.9079064707692308,36 +persistent_emergency,260_200,restart_after_reset_before_ack,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.000264,0.10746400000000002,243.39286666666666,7.68,262.0603306666667,0.9786048215384614,0.9813024107692311,0.9079072323076923,33 +persistent_emergency,230_1000,normal_start,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.0,0.1072,243.39286666666666,7.68,262.06006666666667,0.978422956521739,0.9792114782608698,0.8606344347826089,41 +persistent_emergency,230_1000,ground_restart_moving,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.003432,0.110632,243.39286666666666,7.68,262.0634986666667,0.978421464347826,0.9792107321739132,0.8606321965217394,46 +persistent_emergency,230_1000,rover_restart_moving,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.004488000000000001,0.11168800000000002,243.39286666666666,7.68,262.0645546666667,0.9784210052173912,0.9792105026086958,0.8606315078260871,46 +persistent_emergency,230_1000,both_restart,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.002112,0.10931199999999998,243.39286666666666,7.68,262.0621786666667,0.9784220382608695,0.979211019130435,0.8606330573913047,46 +persistent_emergency,230_1000,ground_restart_emergency,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.0,0.0,0.0,0.054,243.39286666666666,7.68,262.00686666666667,0.9784460869565217,0.9792230434782607,0.8606691304347825,41 +persistent_emergency,230_1000,rover_restart_latched,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.0,0.0,0.0,0.054,243.39286666666666,7.68,262.00686666666667,0.9784460869565217,0.9792230434782607,0.8606691304347825,41 +persistent_emergency,230_1000,long_link_break,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.009782,0.116982,243.39286666666666,7.68,262.0698486666667,0.9784187034782608,0.9792093517391307,0.8606280552173916,46 +persistent_emergency,230_1000,old_ground_session_control,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.0,0.1072,243.39286666666666,7.68,262.06006666666667,0.978422956521739,0.9792114782608698,0.8606344347826089,41 +persistent_emergency,230_1000,old_rover_boot_control,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.0,0.1072,243.39286666666666,7.68,262.06006666666667,0.978422956521739,0.9792114782608698,0.8606344347826089,41 +persistent_emergency,230_1000,old_control_epoch,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.005412,0.11261199999999999,243.39286666666666,7.68,262.0654786666667,0.9784206034782608,0.9792103017391307,0.8606309052173916,46 +persistent_emergency,230_1000,sequence_reset_new_session,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.001206,0.10840599999999999,243.39286666666666,7.68,262.0612726666667,0.9784224321739129,0.9792112160869567,0.8606336482608699,46 +persistent_emergency,230_1000,sequence_wrap,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.003564,0.11076400000000002,243.39286666666666,7.68,262.0636306666667,0.9784214069565215,0.979210703478261,0.8606321104347829,46 +persistent_emergency,230_1000,duplicate_hello,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.054,0.16119999999999998,243.39286666666666,7.68,262.1140666666667,0.9783994782608693,0.9791997391304347,0.8605992173913043,41 +persistent_emergency,230_1000,lost_session_status,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.054,0.16119999999999998,243.39286666666666,7.68,262.1140666666667,0.9783994782608693,0.9791997391304347,0.8605992173913043,42 +persistent_emergency,230_1000,lost_authorize_ack,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.053200000000000004,0.16040000000000001,243.39286666666666,7.68,262.1132666666667,0.9783998260869565,0.9791999130434783,0.8605997391304347,42 +persistent_emergency,230_1000,lost_emergency_ack,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0528,0.059664,0.219664,243.39286666666666,7.68,262.1725306666667,0.9783740591304348,0.9791870295652177,0.860561088695652,46 +persistent_emergency,230_1000,lost_reset_ack,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.062,0.08226599999999999,0.25146599999999997,243.39286666666666,7.68,262.2043326666667,0.9783602321739128,0.9791801160869563,0.8605403482608694,46 +persistent_emergency,230_1000,old_reset_request,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.0,0.1072,243.39286666666666,7.68,262.06006666666667,0.978422956521739,0.9792114782608698,0.8606344347826089,41 +persistent_emergency,230_1000,late_positive_after_emergency,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.0,0.1072,243.39286666666666,7.68,262.06006666666667,0.978422956521739,0.9792114782608698,0.8606344347826089,41 +persistent_emergency,230_1000,restart_after_reset_before_ack,200,68,20.0,10.88,0.7222222222222222,7.36,3.5200000000000005,0.054,0.053200000000000004,0.0,0.0,0.1072,243.39286666666666,7.68,262.06006666666667,0.978422956521739,0.9792114782608698,0.8606344347826089,41 diff --git a/data/processed/lab041/lab041_old_packet_rejection.png b/data/processed/lab041/lab041_old_packet_rejection.png new file mode 100644 index 0000000..bd71b32 Binary files /dev/null and b/data/processed/lab041/lab041_old_packet_rejection.png differ diff --git a/data/processed/lab041/lab041_protection_load.png b/data/processed/lab041/lab041_protection_load.png new file mode 100644 index 0000000..557cf9b Binary files /dev/null and b/data/processed/lab041/lab041_protection_load.png differ diff --git a/data/processed/lab041/lab041_rejection_metrics.csv b/data/processed/lab041/lab041_rejection_metrics.csv new file mode 100644 index 0000000..744991a --- /dev/null +++ b/data/processed/lab041/lab041_rejection_metrics.csv @@ -0,0 +1,181 @@ +architecture,channel_condition,scenario,repetitions,old_packets_injected,old_packets_rejected,old_packets_erroneously_accepted,rejected_ground_session,rejected_rover_boot,rejected_control_epoch,rejected_sequence,rejected_emergency_event,rejected_reset_request,ambiguous_sequence_rejected +no_session_ids,no_loss,normal_start,1,0,0,0,0,0,0,0,0,0,0 +no_session_ids,no_loss,ground_restart_moving,1,0,0,0,0,0,0,0,0,0,0 +no_session_ids,no_loss,rover_restart_moving,1,0,0,0,0,0,0,0,0,0,0 +no_session_ids,no_loss,both_restart,1,0,0,0,0,0,0,0,0,0,0 +no_session_ids,no_loss,ground_restart_emergency,1,0,0,0,0,0,0,0,0,0,0 +no_session_ids,no_loss,rover_restart_latched,1,0,0,0,0,0,0,0,0,0,0 +no_session_ids,no_loss,long_link_break,1,1,0,1,0,0,0,0,0,0,0 +no_session_ids,no_loss,old_ground_session_control,1,1,0,1,0,0,0,0,0,0,0 +no_session_ids,no_loss,old_rover_boot_control,1,1,0,1,0,0,0,0,0,0,0 +no_session_ids,no_loss,old_control_epoch,1,1,0,1,0,0,0,0,0,0,0 +no_session_ids,no_loss,sequence_reset_new_session,1,0,0,0,0,0,0,0,0,0,0 +no_session_ids,no_loss,sequence_wrap,1,1,0,1,0,0,0,0,0,0,1 +no_session_ids,no_loss,duplicate_hello,1,0,0,0,0,0,0,0,0,0,0 +no_session_ids,no_loss,lost_session_status,1,0,0,0,0,0,0,0,0,0,0 +no_session_ids,no_loss,lost_authorize_ack,1,0,0,0,0,0,0,0,0,0,0 +no_session_ids,no_loss,lost_emergency_ack,1,0,0,0,0,0,0,0,0,0,0 +no_session_ids,no_loss,lost_reset_ack,1,0,0,0,0,0,0,0,0,0,0 +no_session_ids,no_loss,old_reset_request,1,1,0,1,0,0,0,0,0,0,0 +no_session_ids,no_loss,late_positive_after_emergency,1,1,0,1,0,0,0,0,0,0,0 +no_session_ids,no_loss,restart_after_reset_before_ack,1,0,0,0,0,0,0,0,0,0,0 +no_session_ids,260_200,normal_start,200,0,0,0,0,0,0,0,0,0,0 +no_session_ids,260_200,ground_restart_moving,200,0,0,0,0,0,0,0,0,0,0 +no_session_ids,260_200,rover_restart_moving,200,0,0,0,0,0,0,0,0,0,0 +no_session_ids,260_200,both_restart,200,0,0,0,0,0,0,0,0,0,0 +no_session_ids,260_200,ground_restart_emergency,200,0,0,0,0,0,0,0,0,0,0 +no_session_ids,260_200,rover_restart_latched,200,0,0,0,0,0,0,0,0,0,0 +no_session_ids,260_200,long_link_break,200,200,0,200,0,0,0,0,0,0,0 +no_session_ids,260_200,old_ground_session_control,200,200,0,200,0,0,0,0,0,0,0 +no_session_ids,260_200,old_rover_boot_control,200,200,0,200,0,0,0,0,0,0,0 +no_session_ids,260_200,old_control_epoch,200,200,0,200,0,0,0,0,0,0,0 +no_session_ids,260_200,sequence_reset_new_session,200,0,0,0,0,0,0,0,0,0,0 +no_session_ids,260_200,sequence_wrap,200,200,0,200,0,0,0,0,0,0,200 +no_session_ids,260_200,duplicate_hello,200,0,0,0,0,0,0,0,0,0,0 +no_session_ids,260_200,lost_session_status,200,0,0,0,0,0,0,0,0,0,0 +no_session_ids,260_200,lost_authorize_ack,200,0,0,0,0,0,0,0,0,0,0 +no_session_ids,260_200,lost_emergency_ack,200,0,0,0,0,0,0,0,0,0,0 +no_session_ids,260_200,lost_reset_ack,200,0,0,0,0,0,0,0,0,0,0 +no_session_ids,260_200,old_reset_request,200,200,0,200,0,0,0,0,0,0,0 +no_session_ids,260_200,late_positive_after_emergency,200,200,0,200,0,0,0,0,0,0,0 +no_session_ids,260_200,restart_after_reset_before_ack,200,0,0,0,0,0,0,0,0,0,0 +no_session_ids,230_1000,normal_start,200,0,0,0,0,0,0,0,0,0,0 +no_session_ids,230_1000,ground_restart_moving,200,0,0,0,0,0,0,0,0,0,0 +no_session_ids,230_1000,rover_restart_moving,200,0,0,0,0,0,0,0,0,0,0 +no_session_ids,230_1000,both_restart,200,0,0,0,0,0,0,0,0,0,0 +no_session_ids,230_1000,ground_restart_emergency,200,0,0,0,0,0,0,0,0,0,0 +no_session_ids,230_1000,rover_restart_latched,200,0,0,0,0,0,0,0,0,0,0 +no_session_ids,230_1000,long_link_break,200,200,0,200,0,0,0,0,0,0,0 +no_session_ids,230_1000,old_ground_session_control,200,200,0,200,0,0,0,0,0,0,0 +no_session_ids,230_1000,old_rover_boot_control,200,200,0,200,0,0,0,0,0,0,0 +no_session_ids,230_1000,old_control_epoch,200,200,0,200,0,0,0,0,0,0,0 +no_session_ids,230_1000,sequence_reset_new_session,200,0,0,0,0,0,0,0,0,0,0 +no_session_ids,230_1000,sequence_wrap,200,200,0,200,0,0,0,0,0,0,200 +no_session_ids,230_1000,duplicate_hello,200,0,0,0,0,0,0,0,0,0,0 +no_session_ids,230_1000,lost_session_status,200,0,0,0,0,0,0,0,0,0,0 +no_session_ids,230_1000,lost_authorize_ack,200,0,0,0,0,0,0,0,0,0,0 +no_session_ids,230_1000,lost_emergency_ack,200,0,0,0,0,0,0,0,0,0,0 +no_session_ids,230_1000,lost_reset_ack,200,0,0,0,0,0,0,0,0,0,0 +no_session_ids,230_1000,old_reset_request,200,200,0,200,0,0,0,0,0,0,0 +no_session_ids,230_1000,late_positive_after_emergency,200,200,0,200,0,0,0,0,0,0,0 +no_session_ids,230_1000,restart_after_reset_before_ack,200,0,0,0,0,0,0,0,0,0,0 +session_safe_boot,no_loss,normal_start,1,0,0,0,0,0,0,0,0,0,0 +session_safe_boot,no_loss,ground_restart_moving,1,0,0,0,0,0,0,0,0,0,0 +session_safe_boot,no_loss,rover_restart_moving,1,0,0,0,0,0,0,0,0,0,0 +session_safe_boot,no_loss,both_restart,1,0,0,0,0,0,0,0,0,0,0 +session_safe_boot,no_loss,ground_restart_emergency,1,0,0,0,0,0,0,0,0,0,0 +session_safe_boot,no_loss,rover_restart_latched,1,0,0,0,0,0,0,0,0,0,0 +session_safe_boot,no_loss,long_link_break,1,1,1,0,0,0,0,1,0,0,0 +session_safe_boot,no_loss,old_ground_session_control,1,1,1,0,1,0,0,0,0,0,0 +session_safe_boot,no_loss,old_rover_boot_control,1,1,1,0,0,1,0,0,0,0,0 +session_safe_boot,no_loss,old_control_epoch,1,1,1,0,0,0,1,0,0,0,0 +session_safe_boot,no_loss,sequence_reset_new_session,1,0,0,0,0,0,0,0,0,0,0 +session_safe_boot,no_loss,sequence_wrap,1,1,1,0,0,0,0,1,0,0,1 +session_safe_boot,no_loss,duplicate_hello,1,0,0,0,0,0,0,0,0,0,0 +session_safe_boot,no_loss,lost_session_status,1,0,0,0,0,0,0,0,0,0,0 +session_safe_boot,no_loss,lost_authorize_ack,1,0,0,0,0,0,0,0,0,0,0 +session_safe_boot,no_loss,lost_emergency_ack,1,0,0,0,0,0,0,0,0,0,0 +session_safe_boot,no_loss,lost_reset_ack,1,0,0,0,0,0,0,0,0,0,0 +session_safe_boot,no_loss,old_reset_request,1,1,1,0,0,0,0,0,0,1,0 +session_safe_boot,no_loss,late_positive_after_emergency,1,1,1,0,0,0,0,0,1,0,0 +session_safe_boot,no_loss,restart_after_reset_before_ack,1,0,0,0,0,0,0,0,0,0,0 +session_safe_boot,260_200,normal_start,200,0,0,0,0,0,0,0,0,0,0 +session_safe_boot,260_200,ground_restart_moving,200,0,0,0,0,0,0,0,0,0,0 +session_safe_boot,260_200,rover_restart_moving,200,0,0,0,0,0,0,0,0,0,0 +session_safe_boot,260_200,both_restart,200,0,0,0,0,0,0,0,0,0,0 +session_safe_boot,260_200,ground_restart_emergency,200,0,0,0,0,0,0,0,0,0,0 +session_safe_boot,260_200,rover_restart_latched,200,0,0,0,0,0,0,0,0,0,0 +session_safe_boot,260_200,long_link_break,200,200,200,0,0,0,0,200,0,0,0 +session_safe_boot,260_200,old_ground_session_control,200,200,200,0,200,0,0,0,0,0,0 +session_safe_boot,260_200,old_rover_boot_control,200,200,200,0,0,200,0,0,0,0,0 +session_safe_boot,260_200,old_control_epoch,200,200,200,0,0,0,200,0,0,0,0 +session_safe_boot,260_200,sequence_reset_new_session,200,0,0,0,0,0,0,0,0,0,0 +session_safe_boot,260_200,sequence_wrap,200,200,200,0,0,0,0,200,0,0,200 +session_safe_boot,260_200,duplicate_hello,200,0,0,0,0,0,0,0,0,0,0 +session_safe_boot,260_200,lost_session_status,200,0,0,0,0,0,0,0,0,0,0 +session_safe_boot,260_200,lost_authorize_ack,200,0,0,0,0,0,0,0,0,0,0 +session_safe_boot,260_200,lost_emergency_ack,200,0,0,0,0,0,0,0,0,0,0 +session_safe_boot,260_200,lost_reset_ack,200,0,0,0,0,0,0,0,0,0,0 +session_safe_boot,260_200,old_reset_request,200,200,200,0,0,0,0,0,0,200,0 +session_safe_boot,260_200,late_positive_after_emergency,200,200,200,0,0,0,0,0,200,0,0 +session_safe_boot,260_200,restart_after_reset_before_ack,200,0,0,0,0,0,0,0,0,0,0 +session_safe_boot,230_1000,normal_start,200,0,0,0,0,0,0,0,0,0,0 +session_safe_boot,230_1000,ground_restart_moving,200,0,0,0,0,0,0,0,0,0,0 +session_safe_boot,230_1000,rover_restart_moving,200,0,0,0,0,0,0,0,0,0,0 +session_safe_boot,230_1000,both_restart,200,0,0,0,0,0,0,0,0,0,0 +session_safe_boot,230_1000,ground_restart_emergency,200,0,0,0,0,0,0,0,0,0,0 +session_safe_boot,230_1000,rover_restart_latched,200,0,0,0,0,0,0,0,0,0,0 +session_safe_boot,230_1000,long_link_break,200,200,200,0,0,0,0,200,0,0,0 +session_safe_boot,230_1000,old_ground_session_control,200,200,200,0,200,0,0,0,0,0,0 +session_safe_boot,230_1000,old_rover_boot_control,200,200,200,0,0,200,0,0,0,0,0 +session_safe_boot,230_1000,old_control_epoch,200,200,200,0,0,0,200,0,0,0,0 +session_safe_boot,230_1000,sequence_reset_new_session,200,0,0,0,0,0,0,0,0,0,0 +session_safe_boot,230_1000,sequence_wrap,200,200,200,0,0,0,0,200,0,0,200 +session_safe_boot,230_1000,duplicate_hello,200,0,0,0,0,0,0,0,0,0,0 +session_safe_boot,230_1000,lost_session_status,200,0,0,0,0,0,0,0,0,0,0 +session_safe_boot,230_1000,lost_authorize_ack,200,0,0,0,0,0,0,0,0,0,0 +session_safe_boot,230_1000,lost_emergency_ack,200,0,0,0,0,0,0,0,0,0,0 +session_safe_boot,230_1000,lost_reset_ack,200,0,0,0,0,0,0,0,0,0,0 +session_safe_boot,230_1000,old_reset_request,200,200,200,0,0,0,0,0,0,200,0 +session_safe_boot,230_1000,late_positive_after_emergency,200,200,200,0,0,0,0,0,200,0,0 +session_safe_boot,230_1000,restart_after_reset_before_ack,200,0,0,0,0,0,0,0,0,0,0 +persistent_emergency,no_loss,normal_start,1,0,0,0,0,0,0,0,0,0,0 +persistent_emergency,no_loss,ground_restart_moving,1,0,0,0,0,0,0,0,0,0,0 +persistent_emergency,no_loss,rover_restart_moving,1,0,0,0,0,0,0,0,0,0,0 +persistent_emergency,no_loss,both_restart,1,0,0,0,0,0,0,0,0,0,0 +persistent_emergency,no_loss,ground_restart_emergency,1,0,0,0,0,0,0,0,0,0,0 +persistent_emergency,no_loss,rover_restart_latched,1,0,0,0,0,0,0,0,0,0,0 +persistent_emergency,no_loss,long_link_break,1,1,1,0,0,0,0,1,0,0,0 +persistent_emergency,no_loss,old_ground_session_control,1,1,1,0,1,0,0,0,0,0,0 +persistent_emergency,no_loss,old_rover_boot_control,1,1,1,0,0,1,0,0,0,0,0 +persistent_emergency,no_loss,old_control_epoch,1,1,1,0,0,0,1,0,0,0,0 +persistent_emergency,no_loss,sequence_reset_new_session,1,0,0,0,0,0,0,0,0,0,0 +persistent_emergency,no_loss,sequence_wrap,1,1,1,0,0,0,0,1,0,0,1 +persistent_emergency,no_loss,duplicate_hello,1,0,0,0,0,0,0,0,0,0,0 +persistent_emergency,no_loss,lost_session_status,1,0,0,0,0,0,0,0,0,0,0 +persistent_emergency,no_loss,lost_authorize_ack,1,0,0,0,0,0,0,0,0,0,0 +persistent_emergency,no_loss,lost_emergency_ack,1,0,0,0,0,0,0,0,0,0,0 +persistent_emergency,no_loss,lost_reset_ack,1,0,0,0,0,0,0,0,0,0,0 +persistent_emergency,no_loss,old_reset_request,1,1,1,0,0,0,0,0,0,1,0 +persistent_emergency,no_loss,late_positive_after_emergency,1,1,1,0,0,0,0,0,1,0,0 +persistent_emergency,no_loss,restart_after_reset_before_ack,1,0,0,0,0,0,0,0,0,0,0 +persistent_emergency,260_200,normal_start,200,0,0,0,0,0,0,0,0,0,0 +persistent_emergency,260_200,ground_restart_moving,200,0,0,0,0,0,0,0,0,0,0 +persistent_emergency,260_200,rover_restart_moving,200,0,0,0,0,0,0,0,0,0,0 +persistent_emergency,260_200,both_restart,200,0,0,0,0,0,0,0,0,0,0 +persistent_emergency,260_200,ground_restart_emergency,200,0,0,0,0,0,0,0,0,0,0 +persistent_emergency,260_200,rover_restart_latched,200,0,0,0,0,0,0,0,0,0,0 +persistent_emergency,260_200,long_link_break,200,200,200,0,0,0,0,200,0,0,0 +persistent_emergency,260_200,old_ground_session_control,200,200,200,0,200,0,0,0,0,0,0 +persistent_emergency,260_200,old_rover_boot_control,200,200,200,0,0,200,0,0,0,0,0 +persistent_emergency,260_200,old_control_epoch,200,200,200,0,0,0,200,0,0,0,0 +persistent_emergency,260_200,sequence_reset_new_session,200,0,0,0,0,0,0,0,0,0,0 +persistent_emergency,260_200,sequence_wrap,200,200,200,0,0,0,0,200,0,0,200 +persistent_emergency,260_200,duplicate_hello,200,0,0,0,0,0,0,0,0,0,0 +persistent_emergency,260_200,lost_session_status,200,0,0,0,0,0,0,0,0,0,0 +persistent_emergency,260_200,lost_authorize_ack,200,0,0,0,0,0,0,0,0,0,0 +persistent_emergency,260_200,lost_emergency_ack,200,0,0,0,0,0,0,0,0,0,0 +persistent_emergency,260_200,lost_reset_ack,200,0,0,0,0,0,0,0,0,0,0 +persistent_emergency,260_200,old_reset_request,200,200,200,0,0,0,0,0,0,200,0 +persistent_emergency,260_200,late_positive_after_emergency,200,200,200,0,0,0,0,0,200,0,0 +persistent_emergency,260_200,restart_after_reset_before_ack,200,0,0,0,0,0,0,0,0,0,0 +persistent_emergency,230_1000,normal_start,200,0,0,0,0,0,0,0,0,0,0 +persistent_emergency,230_1000,ground_restart_moving,200,0,0,0,0,0,0,0,0,0,0 +persistent_emergency,230_1000,rover_restart_moving,200,0,0,0,0,0,0,0,0,0,0 +persistent_emergency,230_1000,both_restart,200,0,0,0,0,0,0,0,0,0,0 +persistent_emergency,230_1000,ground_restart_emergency,200,0,0,0,0,0,0,0,0,0,0 +persistent_emergency,230_1000,rover_restart_latched,200,0,0,0,0,0,0,0,0,0,0 +persistent_emergency,230_1000,long_link_break,200,200,200,0,0,0,0,200,0,0,0 +persistent_emergency,230_1000,old_ground_session_control,200,200,200,0,200,0,0,0,0,0,0 +persistent_emergency,230_1000,old_rover_boot_control,200,200,200,0,0,200,0,0,0,0,0 +persistent_emergency,230_1000,old_control_epoch,200,200,200,0,0,0,200,0,0,0,0 +persistent_emergency,230_1000,sequence_reset_new_session,200,0,0,0,0,0,0,0,0,0,0 +persistent_emergency,230_1000,sequence_wrap,200,200,200,0,0,0,0,200,0,0,200 +persistent_emergency,230_1000,duplicate_hello,200,0,0,0,0,0,0,0,0,0,0 +persistent_emergency,230_1000,lost_session_status,200,0,0,0,0,0,0,0,0,0,0 +persistent_emergency,230_1000,lost_authorize_ack,200,0,0,0,0,0,0,0,0,0,0 +persistent_emergency,230_1000,lost_emergency_ack,200,0,0,0,0,0,0,0,0,0,0 +persistent_emergency,230_1000,lost_reset_ack,200,0,0,0,0,0,0,0,0,0,0 +persistent_emergency,230_1000,old_reset_request,200,200,200,0,0,0,0,0,0,200,0 +persistent_emergency,230_1000,late_positive_after_emergency,200,200,200,0,0,0,0,0,200,0,0 +persistent_emergency,230_1000,restart_after_reset_before_ack,200,0,0,0,0,0,0,0,0,0,0 diff --git a/data/processed/lab041/lab041_report.txt b/data/processed/lab041/lab041_report.txt new file mode 100644 index 0000000..6b7d5d0 --- /dev/null +++ b/data/processed/lab041/lab041_report.txt @@ -0,0 +1,335 @@ +Lab041 — сеансы связи, безопасный запуск и защита от пакетов предыдущего сеанса + +Исходное состояние +- Корень: C:/Users/user/Desktop/projects/SDR_Rover +- Ветка: main. +- Исходный HEAD: 88addff5b615dd7c13506b6e4c83c131a6a4bb39. +- Рабочее дерево и индекс были чистыми; расхождение с локально известной origin/main составляло 0/0. +- Коммиты Lab039 и Lab040 присутствовали; сетевые команды Git не выполнялись. + +Форматы прикладных сообщений +- Общий прикладной заголовок: !BBQQII, 26 байт, сетевой порядок, без неявного выравнивания. +- Поля заголовка: версия, тип, ground_session_id, rover_boot_id, control_epoch и sequence_number. +- Типы: SESSION_HELLO, SESSION_STATUS, MOVEMENT_AUTHORIZE_REQUEST, MOVEMENT_AUTHORIZE_ACK, CONTROL_STATE, EMERGENCY_STOP, EMERGENCY_ACK, RESET_REQUEST, RESET_ACK и SESSION_REJECT. +- CONTROL_STATE содержит скорость float32, поворот float32, торможение uint8 и разрешение движения uint8; выполняется смысловая проверка диапазонов и сочетаний. +- Идентификаторы запуска имеют 64 бита; период управления и номер сообщения — 32 бита; идентификаторы аварии и сброса — 64 бита. +- Отдельная контрольная сумма не добавлена: контрольная сумма общего пакета Lab033 уже охватывает всю полезную нагрузку. Успешная проверка суммы не заменяет смысловую проверку. +- тип | прикладной заголовок, байт | специализированная часть, байт | прикладное сообщение, байт | заголовок Lab033, байт | передаётся всего, байт +- SESSION_HELLO | 26 | 9 | 35 | 32 | 67 +- SESSION_STATUS | 26 | 10 | 36 | 32 | 68 +- MOVEMENT_AUTHORIZE_REQUEST | 26 | 8 | 34 | 32 | 66 +- MOVEMENT_AUTHORIZE_ACK | 26 | 9 | 35 | 32 | 67 +- CONTROL_STATE | 26 | 10 | 36 | 32 | 68 +- EMERGENCY_STOP | 26 | 8 | 34 | 32 | 66 +- EMERGENCY_ACK | 26 | 8 | 34 | 32 | 66 +- RESET_REQUEST | 26 | 21 | 47 | 32 | 79 +- RESET_ACK | 26 | 18 | 44 | 32 | 76 +- SESSION_REJECT | 26 | 2 | 28 | 32 | 60 + +Постоянная нагрузка управления +- CONTROL_STATE: 68 передаваемых байт × 20 сообщений/с = 10.88000 кбит/с. +- За 20 с передаётся 400 команд, или 27200 байт. +- Прикладной заголовок занимает 72.222% прикладного сообщения и 38.235% всего передаваемого пакета команды. +- В Lab040 пакет команды занимал 46 байт и создавал 7.36000 кбит/с; рост составляет 3.52000 кбит/с, или 47.826%. +- Один исходный обмен SESSION_HELLO и SESSION_STATUS: 135 байт, что соответствует 0.05400 кбит/с при усреднении по одному опыту. +- Один исходный обмен разрешения движения: 133 байт, или 0.05320 кбит/с при усреднении по одному опыту. +- Аварийная команда с подтверждением: 132 байт; запрос сброса с подтверждением: 155 байт. + +Обоснование идентификаторов +- Одного sequence_number недостаточно: после перезапуска он может снова начаться с нуля, а задержанный большой номер прежнего запуска будет выглядеть допустимым без границы сеанса. +- ground_session_id отделяет запуски наземной станции; rover_boot_id немедленно делает недействительными команды, адресованные предыдущему запуску ровера. +- control_epoch отделён от сеанса, потому что внутри одного соединения движение может быть повторно запрещено и разрешено после остановки или сброса. +- 64 бита выбраны как минимально требуемая ширина с практически большим пространством случайных значений; в воспроизводимой модели значения выводятся из фиксированного начального значения. Источник для реального изделия должен быть определён отдельно. + +Автоматы сторон +- Наземная станция: GROUND_BOOT → GROUND_SYNCING → GROUND_SAFE_SYNCHRONIZED → GROUND_MOVEMENT_AUTH_REQUESTED → GROUND_ACTIVE. +- Аварийная ветвь станции: GROUND_EMERGENCY_REQUESTED → GROUND_EMERGENCY_CONFIRMED → GROUND_RESET_REQUESTED → безопасное согласованное состояние. +- Ровер: ROVER_BOOT_SAFE → ROVER_SESSION_SYNCED_SAFE → ROVER_MOVEMENT_AUTHORIZED; состояния STAGE1_DECELERATION, STAGE2_BRAKING и EMERGENCY_LATCHED сохранены. +- После запуска ровер запрещает движение, потому что его программное состояние и происхождение ранее сохранённой команды больше нельзя считать достоверными. +- SESSION_STATUS и MOVEMENT_AUTHORIZE_ACK подтверждают этапы протокола, но сами не являются командой движения. +- После сброса или перезапуска старая команда не восстанавливается: требуется новое действие оператора и новая CONTROL_STATE текущего периода управления. + +Сравнение sequence_number +- delta = (new - old) modulo 2^32; сообщение новее только при 0 < delta < 2^31. +- delta = 0 означает дубликат или старое сообщение; delta > 2^31 означает старый номер; delta = 2^31 неоднозначно и всегда отклоняется. +- Правило применяется только при совпадении ground_session_id, rover_boot_id, control_epoch и stream_id. + +Ограничение модели +- Исследуются задержки, дубликаты, перестановка, старые пакеты и потеря оперативного состояния при перезапуске. +- Намеренная подделка не моделируется. Идентификаторы сеанса не доказывают отправителя, поэтому эта защита не заменяет криптографическую аутентификацию. + +Матрица 180 сочетаний +архитектура | канал | сценарий | повторы | безопасный сеанс, % | разрешение, % | нарушения, % | старые пакеты приняты, % | потеря намерения, % | управление, кбит/с | эпизодическая служебная, кбит/с | полный поток, кбит/с +Без идентификаторов сеанса | Без потерь | Обычный запуск обеих сторон | 1 | 0.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.00000 | 261.95287 +Без идентификаторов сеанса | Без потерь | Перезапуск наземной станции при движении | 1 | 0.000 | 100.000 | 100.000 | 0.000 | 0.000 | 10.88000 | 0.00000 | 261.95287 +Без идентификаторов сеанса | Без потерь | Перезапуск ровера при движении | 1 | 0.000 | 100.000 | 100.000 | 0.000 | 0.000 | 10.88000 | 0.00000 | 261.95287 +Без идентификаторов сеанса | Без потерь | Одновременный перезапуск | 1 | 0.000 | 100.000 | 100.000 | 0.000 | 0.000 | 10.88000 | 0.00000 | 261.95287 +Без идентификаторов сеанса | Без потерь | Перезапуск наземной станции при аварийном намерении | 1 | 0.000 | 100.000 | 100.000 | 0.000 | 100.000 | 10.88000 | 0.00000 | 261.95287 +Без идентификаторов сеанса | Без потерь | Перезапуск ровера в аварийной фиксации | 1 | 0.000 | 100.000 | 100.000 | 0.000 | 0.000 | 10.88000 | 0.00000 | 261.95287 +Без идентификаторов сеанса | Без потерь | Длительный перерыв связи | 1 | 0.000 | 100.000 | 100.000 | 100.000 | 0.000 | 10.88000 | 0.00000 | 261.95287 +Без идентификаторов сеанса | Без потерь | Старая команда прежнего сеанса станции | 1 | 0.000 | 100.000 | 100.000 | 100.000 | 0.000 | 10.88000 | 0.00000 | 261.95287 +Без идентификаторов сеанса | Без потерь | Старая команда прежнего запуска ровера | 1 | 0.000 | 100.000 | 100.000 | 100.000 | 0.000 | 10.88000 | 0.00000 | 261.95287 +Без идентификаторов сеанса | Без потерь | Старый период управления | 1 | 0.000 | 100.000 | 100.000 | 100.000 | 0.000 | 10.88000 | 0.00000 | 261.95287 +Без идентификаторов сеанса | Без потерь | Номер сообщения с нуля в новом сеансе | 1 | 0.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.00000 | 261.95287 +Без идентификаторов сеанса | Без потерь | Переполнение 32-битного номера | 1 | 0.000 | 100.000 | 100.000 | 100.000 | 0.000 | 10.88000 | 0.00000 | 261.95287 +Без идентификаторов сеанса | Без потерь | Дубликат приветствия сеанса | 1 | 0.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.00000 | 261.95287 +Без идентификаторов сеанса | Без потерь | Потеря состояния сеанса | 1 | 0.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.00000 | 261.95287 +Без идентификаторов сеанса | Без потерь | Потеря подтверждения разрешения | 1 | 0.000 | 100.000 | 100.000 | 0.000 | 0.000 | 10.88000 | 0.00000 | 261.95287 +Без идентификаторов сеанса | Без потерь | Потеря подтверждения аварии | 1 | 0.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.10560 | 262.05847 +Без идентификаторов сеанса | Без потерь | Потеря подтверждения сброса | 1 | 0.000 | 100.000 | 100.000 | 0.000 | 0.000 | 10.88000 | 0.12400 | 262.07687 +Без идентификаторов сеанса | Без потерь | Старый запрос сброса | 1 | 0.000 | 100.000 | 100.000 | 100.000 | 0.000 | 10.88000 | 0.00000 | 261.95287 +Без идентификаторов сеанса | Без потерь | Поздняя положительная команда после аварии | 1 | 0.000 | 100.000 | 100.000 | 100.000 | 0.000 | 10.88000 | 0.00000 | 261.95287 +Без идентификаторов сеанса | Без потерь | Перезапуск после сброса до подтверждения | 1 | 0.000 | 100.000 | 100.000 | 0.000 | 0.000 | 10.88000 | 0.00000 | 261.95287 +Без идентификаторов сеанса | 260 кбит/с, помеха 200 мс | Обычный запуск обеих сторон | 200 | 0.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.00000 | 261.95287 +Без идентификаторов сеанса | 260 кбит/с, помеха 200 мс | Перезапуск наземной станции при движении | 200 | 0.000 | 100.000 | 100.000 | 0.000 | 0.000 | 10.88000 | 0.00000 | 261.95287 +Без идентификаторов сеанса | 260 кбит/с, помеха 200 мс | Перезапуск ровера при движении | 200 | 0.000 | 100.000 | 100.000 | 0.000 | 0.000 | 10.88000 | 0.00000 | 261.95287 +Без идентификаторов сеанса | 260 кбит/с, помеха 200 мс | Одновременный перезапуск | 200 | 0.000 | 100.000 | 100.000 | 0.000 | 0.000 | 10.88000 | 0.00000 | 261.95287 +Без идентификаторов сеанса | 260 кбит/с, помеха 200 мс | Перезапуск наземной станции при аварийном намерении | 200 | 0.000 | 100.000 | 100.000 | 0.000 | 100.000 | 10.88000 | 0.00000 | 261.95287 +Без идентификаторов сеанса | 260 кбит/с, помеха 200 мс | Перезапуск ровера в аварийной фиксации | 200 | 0.000 | 100.000 | 100.000 | 0.000 | 0.000 | 10.88000 | 0.00000 | 261.95287 +Без идентификаторов сеанса | 260 кбит/с, помеха 200 мс | Длительный перерыв связи | 200 | 0.000 | 100.000 | 100.000 | 100.000 | 0.000 | 10.88000 | 0.00000 | 261.95287 +Без идентификаторов сеанса | 260 кбит/с, помеха 200 мс | Старая команда прежнего сеанса станции | 200 | 0.000 | 100.000 | 100.000 | 100.000 | 0.000 | 10.88000 | 0.00000 | 261.95287 +Без идентификаторов сеанса | 260 кбит/с, помеха 200 мс | Старая команда прежнего запуска ровера | 200 | 0.000 | 100.000 | 100.000 | 100.000 | 0.000 | 10.88000 | 0.00000 | 261.95287 +Без идентификаторов сеанса | 260 кбит/с, помеха 200 мс | Старый период управления | 200 | 0.000 | 100.000 | 100.000 | 100.000 | 0.000 | 10.88000 | 0.00000 | 261.95287 +Без идентификаторов сеанса | 260 кбит/с, помеха 200 мс | Номер сообщения с нуля в новом сеансе | 200 | 0.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.00000 | 261.95287 +Без идентификаторов сеанса | 260 кбит/с, помеха 200 мс | Переполнение 32-битного номера | 200 | 0.000 | 100.000 | 100.000 | 100.000 | 0.000 | 10.88000 | 0.00000 | 261.95287 +Без идентификаторов сеанса | 260 кбит/с, помеха 200 мс | Дубликат приветствия сеанса | 200 | 0.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.00000 | 261.95287 +Без идентификаторов сеанса | 260 кбит/с, помеха 200 мс | Потеря состояния сеанса | 200 | 0.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.00000 | 261.95287 +Без идентификаторов сеанса | 260 кбит/с, помеха 200 мс | Потеря подтверждения разрешения | 200 | 0.000 | 100.000 | 100.000 | 0.000 | 0.000 | 10.88000 | 0.00000 | 261.95287 +Без идентификаторов сеанса | 260 кбит/с, помеха 200 мс | Потеря подтверждения аварии | 200 | 0.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.11009 | 262.06295 +Без идентификаторов сеанса | 260 кбит/с, помеха 200 мс | Потеря подтверждения сброса | 200 | 0.000 | 100.000 | 100.000 | 0.000 | 0.000 | 10.88000 | 0.12732 | 262.08018 +Без идентификаторов сеанса | 260 кбит/с, помеха 200 мс | Старый запрос сброса | 200 | 0.000 | 100.000 | 100.000 | 100.000 | 0.000 | 10.88000 | 0.00000 | 261.95287 +Без идентификаторов сеанса | 260 кбит/с, помеха 200 мс | Поздняя положительная команда после аварии | 200 | 0.000 | 100.000 | 100.000 | 100.000 | 0.000 | 10.88000 | 0.00000 | 261.95287 +Без идентификаторов сеанса | 260 кбит/с, помеха 200 мс | Перезапуск после сброса до подтверждения | 200 | 0.000 | 100.000 | 100.000 | 0.000 | 0.000 | 10.88000 | 0.00000 | 261.95287 +Без идентификаторов сеанса | 230 кбит/с, помеха 1000 мс | Обычный запуск обеих сторон | 200 | 0.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.00000 | 261.95287 +Без идентификаторов сеанса | 230 кбит/с, помеха 1000 мс | Перезапуск наземной станции при движении | 200 | 0.000 | 100.000 | 100.000 | 0.000 | 0.000 | 10.88000 | 0.00000 | 261.95287 +Без идентификаторов сеанса | 230 кбит/с, помеха 1000 мс | Перезапуск ровера при движении | 200 | 0.000 | 100.000 | 100.000 | 0.000 | 0.000 | 10.88000 | 0.00000 | 261.95287 +Без идентификаторов сеанса | 230 кбит/с, помеха 1000 мс | Одновременный перезапуск | 200 | 0.000 | 100.000 | 100.000 | 0.000 | 0.000 | 10.88000 | 0.00000 | 261.95287 +Без идентификаторов сеанса | 230 кбит/с, помеха 1000 мс | Перезапуск наземной станции при аварийном намерении | 200 | 0.000 | 100.000 | 100.000 | 0.000 | 100.000 | 10.88000 | 0.00000 | 261.95287 +Без идентификаторов сеанса | 230 кбит/с, помеха 1000 мс | Перезапуск ровера в аварийной фиксации | 200 | 0.000 | 100.000 | 100.000 | 0.000 | 0.000 | 10.88000 | 0.00000 | 261.95287 +Без идентификаторов сеанса | 230 кбит/с, помеха 1000 мс | Длительный перерыв связи | 200 | 0.000 | 100.000 | 100.000 | 100.000 | 0.000 | 10.88000 | 0.00000 | 261.95287 +Без идентификаторов сеанса | 230 кбит/с, помеха 1000 мс | Старая команда прежнего сеанса станции | 200 | 0.000 | 100.000 | 100.000 | 100.000 | 0.000 | 10.88000 | 0.00000 | 261.95287 +Без идентификаторов сеанса | 230 кбит/с, помеха 1000 мс | Старая команда прежнего запуска ровера | 200 | 0.000 | 100.000 | 100.000 | 100.000 | 0.000 | 10.88000 | 0.00000 | 261.95287 +Без идентификаторов сеанса | 230 кбит/с, помеха 1000 мс | Старый период управления | 200 | 0.000 | 100.000 | 100.000 | 100.000 | 0.000 | 10.88000 | 0.00000 | 261.95287 +Без идентификаторов сеанса | 230 кбит/с, помеха 1000 мс | Номер сообщения с нуля в новом сеансе | 200 | 0.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.00000 | 261.95287 +Без идентификаторов сеанса | 230 кбит/с, помеха 1000 мс | Переполнение 32-битного номера | 200 | 0.000 | 100.000 | 100.000 | 100.000 | 0.000 | 10.88000 | 0.00000 | 261.95287 +Без идентификаторов сеанса | 230 кбит/с, помеха 1000 мс | Дубликат приветствия сеанса | 200 | 0.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.00000 | 261.95287 +Без идентификаторов сеанса | 230 кбит/с, помеха 1000 мс | Потеря состояния сеанса | 200 | 0.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.00000 | 261.95287 +Без идентификаторов сеанса | 230 кбит/с, помеха 1000 мс | Потеря подтверждения разрешения | 200 | 0.000 | 100.000 | 100.000 | 0.000 | 0.000 | 10.88000 | 0.00000 | 261.95287 +Без идентификаторов сеанса | 230 кбит/с, помеха 1000 мс | Потеря подтверждения аварии | 200 | 0.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.16817 | 262.12103 +Без идентификаторов сеанса | 230 кбит/с, помеха 1000 мс | Потеря подтверждения сброса | 200 | 0.000 | 100.000 | 100.000 | 0.000 | 0.000 | 10.88000 | 0.13727 | 262.09014 +Без идентификаторов сеанса | 230 кбит/с, помеха 1000 мс | Старый запрос сброса | 200 | 0.000 | 100.000 | 100.000 | 100.000 | 0.000 | 10.88000 | 0.00000 | 261.95287 +Без идентификаторов сеанса | 230 кбит/с, помеха 1000 мс | Поздняя положительная команда после аварии | 200 | 0.000 | 100.000 | 100.000 | 100.000 | 0.000 | 10.88000 | 0.00000 | 261.95287 +Без идентификаторов сеанса | 230 кбит/с, помеха 1000 мс | Перезапуск после сброса до подтверждения | 200 | 0.000 | 100.000 | 100.000 | 0.000 | 0.000 | 10.88000 | 0.00000 | 261.95287 +Идентификаторы и безопасный запуск | Без потерь | Обычный запуск обеих сторон | 1 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.10720 | 262.06007 +Идентификаторы и безопасный запуск | Без потерь | Перезапуск наземной станции при движении | 1 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.10720 | 262.06007 +Идентификаторы и безопасный запуск | Без потерь | Перезапуск ровера при движении | 1 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.10720 | 262.06007 +Идентификаторы и безопасный запуск | Без потерь | Одновременный перезапуск | 1 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.10720 | 262.06007 +Идентификаторы и безопасный запуск | Без потерь | Перезапуск наземной станции при аварийном намерении | 1 | 100.000 | 0.000 | 0.000 | 0.000 | 100.000 | 10.88000 | 0.05400 | 262.00687 +Идентификаторы и безопасный запуск | Без потерь | Перезапуск ровера в аварийной фиксации | 1 | 100.000 | 0.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.05400 | 262.00687 +Идентификаторы и безопасный запуск | Без потерь | Длительный перерыв связи | 1 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.10720 | 262.06007 +Идентификаторы и безопасный запуск | Без потерь | Старая команда прежнего сеанса станции | 1 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.10720 | 262.06007 +Идентификаторы и безопасный запуск | Без потерь | Старая команда прежнего запуска ровера | 1 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.10720 | 262.06007 +Идентификаторы и безопасный запуск | Без потерь | Старый период управления | 1 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.10720 | 262.06007 +Идентификаторы и безопасный запуск | Без потерь | Номер сообщения с нуля в новом сеансе | 1 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.10720 | 262.06007 +Идентификаторы и безопасный запуск | Без потерь | Переполнение 32-битного номера | 1 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.10720 | 262.06007 +Идентификаторы и безопасный запуск | Без потерь | Дубликат приветствия сеанса | 1 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.16120 | 262.11407 +Идентификаторы и безопасный запуск | Без потерь | Потеря состояния сеанса | 1 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.16120 | 262.11407 +Идентификаторы и безопасный запуск | Без потерь | Потеря подтверждения разрешения | 1 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.16040 | 262.11327 +Идентификаторы и безопасный запуск | Без потерь | Потеря подтверждения аварии | 1 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.21280 | 262.16567 +Идентификаторы и безопасный запуск | Без потерь | Потеря подтверждения сброса | 1 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.23120 | 262.18407 +Идентификаторы и безопасный запуск | Без потерь | Старый запрос сброса | 1 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.10720 | 262.06007 +Идентификаторы и безопасный запуск | Без потерь | Поздняя положительная команда после аварии | 1 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.10720 | 262.06007 +Идентификаторы и безопасный запуск | Без потерь | Перезапуск после сброса до подтверждения | 1 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.10720 | 262.06007 +Идентификаторы и безопасный запуск | 260 кбит/с, помеха 200 мс | Обычный запуск обеих сторон | 200 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.10720 | 262.06007 +Идентификаторы и безопасный запуск | 260 кбит/с, помеха 200 мс | Перезапуск наземной станции при движении | 200 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.10720 | 262.06007 +Идентификаторы и безопасный запуск | 260 кбит/с, помеха 200 мс | Перезапуск ровера при движении | 200 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.10852 | 262.06139 +Идентификаторы и безопасный запуск | 260 кбит/с, помеха 200 мс | Одновременный перезапуск | 200 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.11010 | 262.06297 +Идентификаторы и безопасный запуск | 260 кбит/с, помеха 200 мс | Перезапуск наземной станции при аварийном намерении | 200 | 100.000 | 0.000 | 0.000 | 0.000 | 100.000 | 10.88000 | 0.05400 | 262.00687 +Идентификаторы и безопасный запуск | 260 кбит/с, помеха 200 мс | Перезапуск ровера в аварийной фиксации | 200 | 100.000 | 0.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.05400 | 262.00687 +Идентификаторы и безопасный запуск | 260 кбит/с, помеха 200 мс | Длительный перерыв связи | 200 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.11348 | 262.06634 +Идентификаторы и безопасный запуск | 260 кбит/с, помеха 200 мс | Старая команда прежнего сеанса станции | 200 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.10799 | 262.06086 +Идентификаторы и безопасный запуск | 260 кбит/с, помеха 200 мс | Старая команда прежнего запуска ровера | 200 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.10773 | 262.06059 +Идентификаторы и безопасный запуск | 260 кбит/с, помеха 200 мс | Старый период управления | 200 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.10720 | 262.06007 +Идентификаторы и безопасный запуск | 260 кбит/с, помеха 200 мс | Номер сообщения с нуля в новом сеансе | 200 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.10997 | 262.06284 +Идентификаторы и безопасный запуск | 260 кбит/с, помеха 200 мс | Переполнение 32-битного номера | 200 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.10720 | 262.06007 +Идентификаторы и безопасный запуск | 260 кбит/с, помеха 200 мс | Дубликат приветствия сеанса | 200 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.16120 | 262.11407 +Идентификаторы и безопасный запуск | 260 кбит/с, помеха 200 мс | Потеря состояния сеанса | 200 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.16226 | 262.11512 +Идентификаторы и безопасный запуск | 260 кбит/с, помеха 200 мс | Потеря подтверждения разрешения | 200 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.16040 | 262.11327 +Идентификаторы и безопасный запуск | 260 кбит/с, помеха 200 мс | Потеря подтверждения аварии | 200 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.21848 | 262.17134 +Идентификаторы и безопасный запуск | 260 кбит/с, помеха 200 мс | Потеря подтверждения сброса | 200 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.23547 | 262.18833 +Идентификаторы и безопасный запуск | 260 кбит/с, помеха 200 мс | Старый запрос сброса | 200 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.10799 | 262.06086 +Идентификаторы и безопасный запуск | 260 кбит/с, помеха 200 мс | Поздняя положительная команда после аварии | 200 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.10984 | 262.06271 +Идентификаторы и безопасный запуск | 260 кбит/с, помеха 200 мс | Перезапуск после сброса до подтверждения | 200 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.10733 | 262.06020 +Идентификаторы и безопасный запуск | 230 кбит/с, помеха 1000 мс | Обычный запуск обеих сторон | 200 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.10720 | 262.06007 +Идентификаторы и безопасный запуск | 230 кбит/с, помеха 1000 мс | Перезапуск наземной станции при движении | 200 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.10720 | 262.06007 +Идентификаторы и безопасный запуск | 230 кбит/с, помеха 1000 мс | Перезапуск ровера при движении | 200 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.10720 | 262.06007 +Идентификаторы и безопасный запуск | 230 кбит/с, помеха 1000 мс | Одновременный перезапуск | 200 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.11354 | 262.06640 +Идентификаторы и безопасный запуск | 230 кбит/с, помеха 1000 мс | Перезапуск наземной станции при аварийном намерении | 200 | 100.000 | 0.000 | 0.000 | 0.000 | 100.000 | 10.88000 | 0.05400 | 262.00687 +Идентификаторы и безопасный запуск | 230 кбит/с, помеха 1000 мс | Перезапуск ровера в аварийной фиксации | 200 | 100.000 | 0.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.05400 | 262.00687 +Идентификаторы и безопасный запуск | 230 кбит/с, помеха 1000 мс | Длительный перерыв связи | 200 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.12937 | 262.08224 +Идентификаторы и безопасный запуск | 230 кбит/с, помеха 1000 мс | Старая команда прежнего сеанса станции | 200 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.10720 | 262.06007 +Идентификаторы и безопасный запуск | 230 кбит/с, помеха 1000 мс | Старая команда прежнего запуска ровера | 200 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.10720 | 262.06007 +Идентификаторы и безопасный запуск | 230 кбит/с, помеха 1000 мс | Старый период управления | 200 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.10720 | 262.06007 +Идентификаторы и безопасный запуск | 230 кбит/с, помеха 1000 мс | Номер сообщения с нуля в новом сеансе | 200 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.10865 | 262.06152 +Идентификаторы и безопасный запуск | 230 кбит/с, помеха 1000 мс | Переполнение 32-битного номера | 200 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.10720 | 262.06007 +Идентификаторы и безопасный запуск | 230 кбит/с, помеха 1000 мс | Дубликат приветствия сеанса | 200 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.16120 | 262.11407 +Идентификаторы и безопасный запуск | 230 кбит/с, помеха 1000 мс | Потеря состояния сеанса | 200 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.16120 | 262.11407 +Идентификаторы и безопасный запуск | 230 кбит/с, помеха 1000 мс | Потеря подтверждения разрешения | 200 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.16040 | 262.11327 +Идентификаторы и безопасный запуск | 230 кбит/с, помеха 1000 мс | Потеря подтверждения аварии | 200 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.23379 | 262.18665 +Идентификаторы и безопасный запуск | 230 кбит/с, помеха 1000 мс | Потеря подтверждения сброса | 200 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.24705 | 262.19992 +Идентификаторы и безопасный запуск | 230 кбит/с, помеха 1000 мс | Старый запрос сброса | 200 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.10720 | 262.06007 +Идентификаторы и безопасный запуск | 230 кбит/с, помеха 1000 мс | Поздняя положительная команда после аварии | 200 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.10720 | 262.06007 +Идентификаторы и безопасный запуск | 230 кбит/с, помеха 1000 мс | Перезапуск после сброса до подтверждения | 200 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.10720 | 262.06007 +Идентификаторы, безопасный запуск и сохранённое намерение | Без потерь | Обычный запуск обеих сторон | 1 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.10720 | 262.06007 +Идентификаторы, безопасный запуск и сохранённое намерение | Без потерь | Перезапуск наземной станции при движении | 1 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.10720 | 262.06007 +Идентификаторы, безопасный запуск и сохранённое намерение | Без потерь | Перезапуск ровера при движении | 1 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.10720 | 262.06007 +Идентификаторы, безопасный запуск и сохранённое намерение | Без потерь | Одновременный перезапуск | 1 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.10720 | 262.06007 +Идентификаторы, безопасный запуск и сохранённое намерение | Без потерь | Перезапуск наземной станции при аварийном намерении | 1 | 100.000 | 0.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.05400 | 262.00687 +Идентификаторы, безопасный запуск и сохранённое намерение | Без потерь | Перезапуск ровера в аварийной фиксации | 1 | 100.000 | 0.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.05400 | 262.00687 +Идентификаторы, безопасный запуск и сохранённое намерение | Без потерь | Длительный перерыв связи | 1 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.10720 | 262.06007 +Идентификаторы, безопасный запуск и сохранённое намерение | Без потерь | Старая команда прежнего сеанса станции | 1 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.10720 | 262.06007 +Идентификаторы, безопасный запуск и сохранённое намерение | Без потерь | Старая команда прежнего запуска ровера | 1 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.10720 | 262.06007 +Идентификаторы, безопасный запуск и сохранённое намерение | Без потерь | Старый период управления | 1 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.10720 | 262.06007 +Идентификаторы, безопасный запуск и сохранённое намерение | Без потерь | Номер сообщения с нуля в новом сеансе | 1 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.10720 | 262.06007 +Идентификаторы, безопасный запуск и сохранённое намерение | Без потерь | Переполнение 32-битного номера | 1 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.10720 | 262.06007 +Идентификаторы, безопасный запуск и сохранённое намерение | Без потерь | Дубликат приветствия сеанса | 1 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.16120 | 262.11407 +Идентификаторы, безопасный запуск и сохранённое намерение | Без потерь | Потеря состояния сеанса | 1 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.16120 | 262.11407 +Идентификаторы, безопасный запуск и сохранённое намерение | Без потерь | Потеря подтверждения разрешения | 1 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.16040 | 262.11327 +Идентификаторы, безопасный запуск и сохранённое намерение | Без потерь | Потеря подтверждения аварии | 1 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.21280 | 262.16567 +Идентификаторы, безопасный запуск и сохранённое намерение | Без потерь | Потеря подтверждения сброса | 1 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.23120 | 262.18407 +Идентификаторы, безопасный запуск и сохранённое намерение | Без потерь | Старый запрос сброса | 1 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.10720 | 262.06007 +Идентификаторы, безопасный запуск и сохранённое намерение | Без потерь | Поздняя положительная команда после аварии | 1 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.10720 | 262.06007 +Идентификаторы, безопасный запуск и сохранённое намерение | Без потерь | Перезапуск после сброса до подтверждения | 1 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.10720 | 262.06007 +Идентификаторы, безопасный запуск и сохранённое намерение | 260 кбит/с, помеха 200 мс | Обычный запуск обеих сторон | 200 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.10733 | 262.06020 +Идентификаторы, безопасный запуск и сохранённое намерение | 260 кбит/с, помеха 200 мс | Перезапуск наземной станции при движении | 200 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.10826 | 262.06112 +Идентификаторы, безопасный запуск и сохранённое намерение | 260 кбит/с, помеха 200 мс | Перезапуск ровера при движении | 200 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.10892 | 262.06178 +Идентификаторы, безопасный запуск и сохранённое намерение | 260 кбит/с, помеха 200 мс | Одновременный перезапуск | 200 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.10773 | 262.06059 +Идентификаторы, безопасный запуск и сохранённое намерение | 260 кбит/с, помеха 200 мс | Перезапуск наземной станции при аварийном намерении | 200 | 100.000 | 0.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.05400 | 262.00687 +Идентификаторы, безопасный запуск и сохранённое намерение | 260 кбит/с, помеха 200 мс | Перезапуск ровера в аварийной фиксации | 200 | 100.000 | 0.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.05400 | 262.00687 +Идентификаторы, безопасный запуск и сохранённое намерение | 260 кбит/с, помеха 200 мс | Длительный перерыв связи | 200 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.11199 | 262.06486 +Идентификаторы, безопасный запуск и сохранённое намерение | 260 кбит/с, помеха 200 мс | Старая команда прежнего сеанса станции | 200 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.10760 | 262.06046 +Идентификаторы, безопасный запуск и сохранённое намерение | 260 кбит/с, помеха 200 мс | Старая команда прежнего запуска ровера | 200 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.10786 | 262.06073 +Идентификаторы, безопасный запуск и сохранённое намерение | 260 кбит/с, помеха 200 мс | Старый период управления | 200 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.10812 | 262.06099 +Идентификаторы, безопасный запуск и сохранённое намерение | 260 кбит/с, помеха 200 мс | Номер сообщения с нуля в новом сеансе | 200 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.11090 | 262.06377 +Идентификаторы, безопасный запуск и сохранённое намерение | 260 кбит/с, помеха 200 мс | Переполнение 32-битного номера | 200 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.10852 | 262.06139 +Идентификаторы, безопасный запуск и сохранённое намерение | 260 кбит/с, помеха 200 мс | Дубликат приветствия сеанса | 200 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.16120 | 262.11407 +Идентификаторы, безопасный запуск и сохранённое намерение | 260 кбит/с, помеха 200 мс | Потеря состояния сеанса | 200 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.16147 | 262.11433 +Идентификаторы, безопасный запуск и сохранённое намерение | 260 кбит/с, помеха 200 мс | Потеря подтверждения разрешения | 200 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.16594 | 262.11881 +Идентификаторы, безопасный запуск и сохранённое намерение | 260 кбит/с, помеха 200 мс | Потеря подтверждения аварии | 200 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.21927 | 262.17213 +Идентификаторы, безопасный запуск и сохранённое намерение | 260 кбит/с, помеха 200 мс | Потеря подтверждения сброса | 200 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.23663 | 262.18949 +Идентификаторы, безопасный запуск и сохранённое намерение | 260 кбит/с, помеха 200 мс | Старый запрос сброса | 200 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.10865 | 262.06152 +Идентификаторы, безопасный запуск и сохранённое намерение | 260 кбит/с, помеха 200 мс | Поздняя положительная команда после аварии | 200 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.10878 | 262.06165 +Идентификаторы, безопасный запуск и сохранённое намерение | 260 кбит/с, помеха 200 мс | Перезапуск после сброса до подтверждения | 200 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.10746 | 262.06033 +Идентификаторы, безопасный запуск и сохранённое намерение | 230 кбит/с, помеха 1000 мс | Обычный запуск обеих сторон | 200 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.10720 | 262.06007 +Идентификаторы, безопасный запуск и сохранённое намерение | 230 кбит/с, помеха 1000 мс | Перезапуск наземной станции при движении | 200 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.11063 | 262.06350 +Идентификаторы, безопасный запуск и сохранённое намерение | 230 кбит/с, помеха 1000 мс | Перезапуск ровера при движении | 200 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.11169 | 262.06455 +Идентификаторы, безопасный запуск и сохранённое намерение | 230 кбит/с, помеха 1000 мс | Одновременный перезапуск | 200 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.10931 | 262.06218 +Идентификаторы, безопасный запуск и сохранённое намерение | 230 кбит/с, помеха 1000 мс | Перезапуск наземной станции при аварийном намерении | 200 | 100.000 | 0.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.05400 | 262.00687 +Идентификаторы, безопасный запуск и сохранённое намерение | 230 кбит/с, помеха 1000 мс | Перезапуск ровера в аварийной фиксации | 200 | 100.000 | 0.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.05400 | 262.00687 +Идентификаторы, безопасный запуск и сохранённое намерение | 230 кбит/с, помеха 1000 мс | Длительный перерыв связи | 200 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.11698 | 262.06985 +Идентификаторы, безопасный запуск и сохранённое намерение | 230 кбит/с, помеха 1000 мс | Старая команда прежнего сеанса станции | 200 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.10720 | 262.06007 +Идентификаторы, безопасный запуск и сохранённое намерение | 230 кбит/с, помеха 1000 мс | Старая команда прежнего запуска ровера | 200 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.10720 | 262.06007 +Идентификаторы, безопасный запуск и сохранённое намерение | 230 кбит/с, помеха 1000 мс | Старый период управления | 200 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.11261 | 262.06548 +Идентификаторы, безопасный запуск и сохранённое намерение | 230 кбит/с, помеха 1000 мс | Номер сообщения с нуля в новом сеансе | 200 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.10841 | 262.06127 +Идентификаторы, безопасный запуск и сохранённое намерение | 230 кбит/с, помеха 1000 мс | Переполнение 32-битного номера | 200 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.11076 | 262.06363 +Идентификаторы, безопасный запуск и сохранённое намерение | 230 кбит/с, помеха 1000 мс | Дубликат приветствия сеанса | 200 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.16120 | 262.11407 +Идентификаторы, безопасный запуск и сохранённое намерение | 230 кбит/с, помеха 1000 мс | Потеря состояния сеанса | 200 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.16120 | 262.11407 +Идентификаторы, безопасный запуск и сохранённое намерение | 230 кбит/с, помеха 1000 мс | Потеря подтверждения разрешения | 200 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.16040 | 262.11327 +Идентификаторы, безопасный запуск и сохранённое намерение | 230 кбит/с, помеха 1000 мс | Потеря подтверждения аварии | 200 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.21966 | 262.17253 +Идентификаторы, безопасный запуск и сохранённое намерение | 230 кбит/с, помеха 1000 мс | Потеря подтверждения сброса | 200 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.25147 | 262.20433 +Идентификаторы, безопасный запуск и сохранённое намерение | 230 кбит/с, помеха 1000 мс | Старый запрос сброса | 200 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.10720 | 262.06007 +Идентификаторы, безопасный запуск и сохранённое намерение | 230 кбит/с, помеха 1000 мс | Поздняя положительная команда после аварии | 200 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.10720 | 262.06007 +Идентификаторы, безопасный запуск и сохранённое намерение | 230 кбит/с, помеха 1000 мс | Перезапуск после сброса до подтверждения | 200 | 100.000 | 100.000 | 0.000 | 0.000 | 0.000 | 10.88000 | 0.10720 | 262.06007 + +Перезапуски и безопасное состояние +- В основном режиме движение до синхронизации: 0; до подтверждения разрешения: 0; без новой команды оператора: 0. +- Максимальный путь после перезапуска в основном режиме: 9.7737 м; это путь безопасного торможения, а не продолжение старой команды. +- Продолжение движения после перезапуска: 0; запуск по старой команде: 0. + +Пакеты предыдущего сеанса +- Основной режим: введено 2807, отклонено 2807, ошибочно принято 0. +- Отрицательный уровень без идентификаторов: ошибочно принято 2807 старых пакетов. +- Причины отказа основного режима: сеанс станции=401, запуск ровера=401, период управления=401, номер сообщения=802, событие аварии=401, запрос сброса=401. +- Неоднозначных delta=2^31 отклонено: 401. + +Аварийное намерение и сброс +- Сохранение emergency_intent на станции сохраняет намерение оператора; ROVER_BOOT_SAFE независимо защищает физическое движение ровера после его перезапуска. Это разные задачи. +- В основном режиме потерь аварийного намерения: 0; восстановлений намерения: 401. +- Ошибочно принятых старых запросов сброса: 0; движений до RESET_ACK: 0; автоматических восстановлений движения: 0. +- Потеря EMERGENCY_ACK не снимает аварийное намерение; потеря RESET_ACK вызывает повтор того же идемпотентного запроса. + +Инварианты безопасности основного режима +- Движение до синхронизации: 0. +- Движение до подтверждения разрешения: 0. +- Движение без новой команды оператора: 0. +- Принятие команды старого сеанса станции: 0. +- Принятие команды старого запуска ровера: 0. +- Использование старого периода управления: 0. +- Снятие аварийной фиксации обычной командой: 0. +- Потеря аварийного намерения после перезапуска станции: 0. +- Движение до подтверждения сброса: 0. +- Автоматическое восстановление старой команды после сброса: 0. +- Принятие старого запроса сброса: 0. +- Принятие неоднозначного номера: 0. +- Отрицательная скорость: 0. +- Превышение разрешённой скорости: 0. + +Учёт нагрузки +- Постоянное управление: 10.88000 кбит/с во всех сочетаниях. +- Исходные сообщения согласования: в среднем 0.05400 кбит/с; разрешение движения: 0.04788 кбит/с. +- Аварийные сообщения и сброс: в среднем 0.00574 кбит/с; повторы и повторные подтверждения: 0.01536 кбит/с. +- Эпизодическая служебная нагрузка основного режима: средняя 0.12298 кбит/с, максимум 0.25147 кбит/с. Именно к этой величине относились прежние значения 0,12298–0,25147 кбит/с. +- Постоянные исходные потоки: видео 243.39287, телеметрия 7.68000, управление 10.88000 кбит/с. +- Полный предложенный поток основного режима: средний 262.07584 кбит/с, максимум 262.20433 кбит/с. +- Доставка управления не ниже 97.836%, телеметрии не ниже 97.918%, публикация видео не ниже 86.054%. +- Максимальная очередь: 46 пакетов. + +Функциональные проверки +- ПРОЙДЕНО — 01. Сериализация всех сообщений: все десять типов имеют однозначное двоичное представление +- ПРОЙДЕНО — 02. Отклонение неверной версии: неверная версия отклонена +- ПРОЙДЕНО — 03. Отклонение неизвестного типа: неизвестный тип отклонён +- ПРОЙДЕНО — 04. Допустимые диапазоны управления: диапазоны и сочетания полей управления проверены +- ПРОЙДЕНО — 05. Номер ноль в новом сеансе: новый сеанс принимает начальный номер ноль +- ПРОЙДЕНО — 06. Старый сеанс станции: старый сеанс наземной станции отклонён +- ПРОЙДЕНО — 07. Старый запуск ровера: старый идентификатор запуска ровера отклонён +- ПРОЙДЕНО — 08. Старый период управления: старый период управления отклонён +- ПРОЙДЕНО — 09. Переполнение номера сообщения: переход от 0xFFFFFFFF к нулю принят как новый +- ПРОЙДЕНО — 10. Неоднозначная половина диапазона: неоднозначная половина диапазона отклонена +- ПРОЙДЕНО — 11. Безопасное состояние после запуска: после запуска движение запрещено с обеих сторон +- ПРОЙДЕНО — 12. Состояние сеанса не запускает движение: состояние сеанса и дубликат приветствия не разрешают движение +- ПРОЙДЕНО — 13. Подтверждение разрешения не восстанавливает движение: подтверждение разрешения сохраняет нулевое состояние +- ПРОЙДЕНО — 14. Новая команда оператора обязательна: движение начинается только по новой команде оператора +- ПРОЙДЕНО — 15. Безопасный перезапуск ровера: перезапуск ровера немедленно создаёт безопасное состояние +- ПРОЙДЕНО — 16. Прекращение старого потока станции: новый сеанс прекращает старый поток команд +- ПРОЙДЕНО — 17. Восстановление аварийного намерения: сохранённое аварийное намерение восстановлено +- ПРОЙДЕНО — 18. Подтверждение не снимает аварийное намерение: подтверждение аварии не снимает намерение +- ПРОЙДЕНО — 19. Отклонение старого запроса сброса: запрос сброса старого сеанса отклонён +- ПРОЙДЕНО — 20. Повтор после потери подтверждения сброса: без подтверждения тот же запрос сброса передаётся повторно +- ПРОЙДЕНО — 21. Повторное подтверждение дубликата сброса: дубликат не повторяет сброс и получает подтверждение +- ПРОЙДЕНО — 22. Аварийная фиксация не снимается обычной командой: обычная команда не снимает аварийную фиксацию +- ПРОЙДЕНО — 23. Воспроизводимость: помехи и 64-битные идентификаторы воспроизводимы +- ПРОЙДЕНО — 24. Постоянная нагрузка команд управления: поток управления совпадает с размером 68 байт, частотой 20 Гц и длительностью опыта + +Созданные файлы +- protocol/control_messages.py +- protocol/session_state.py +- tests/lab041_session_restart_safety.py +- data/processed/lab041/lab041_summary.csv +- data/processed/lab041/lab041_session_metrics.csv +- data/processed/lab041/lab041_rejection_metrics.csv +- data/processed/lab041/lab041_restart_metrics.csv +- data/processed/lab041/lab041_load_metrics.csv +- data/processed/lab041/lab041_report.txt +- data/processed/lab041/lab041_session_time.png +- data/processed/lab041/lab041_authorization_time.png +- data/processed/lab041/lab041_old_packet_rejection.png +- data/processed/lab041/lab041_restart_distance.png +- data/processed/lab041/lab041_emergency_intent.png +- data/processed/lab041/lab041_safety_violations.png +- data/processed/lab041/lab041_protection_load.png +- data/processed/lab041/lab041_traffic_impact.png + +Ограничения +- Модель не включает криптографическую аутентификацию и не рассматривает намеренного нарушителя. +- Размеры идентификаторов и источник случайности для реального изделия должны быть закреплены отдельным проектным решением. +- Lab041 не добавлена в индекс и не закоммичена; результаты Lab028–Lab040 не изменены. diff --git a/data/processed/lab041/lab041_restart_distance.png b/data/processed/lab041/lab041_restart_distance.png new file mode 100644 index 0000000..fbdc5a3 Binary files /dev/null and b/data/processed/lab041/lab041_restart_distance.png differ diff --git a/data/processed/lab041/lab041_restart_metrics.csv b/data/processed/lab041/lab041_restart_metrics.csv new file mode 100644 index 0000000..2b537b5 --- /dev/null +++ b/data/processed/lab041/lab041_restart_metrics.csv @@ -0,0 +1,181 @@ +architecture,channel_condition,scenario,repetitions,restart_cases,mean_restart_to_safe_ms,p95_restart_to_safe_ms,mean_distance_after_restart_m,max_distance_after_restart_m,continued_movement_after_restart,startup_from_old_command,emergency_latch_removed,emergency_intent_lost,unsafe_movement_authorizations,emergency_intent_restored,zero_commands_continued,mean_emergency_refixed_ms,emergency_event_misclassified,old_reset_erroneously_accepted,movement_before_reset_ack,automatic_motion_after_reset,negative_speed_cases,speed_limit_exceeded_cases +no_session_ids,no_loss,normal_start,1,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +no_session_ids,no_loss,ground_restart_moving,1,1,0.0,0.0,416.6666666666667,416.6666666666667,1,1,0,0,1,0,0,0.0,0,0,0,0,0,0 +no_session_ids,no_loss,rover_restart_moving,1,1,0.0,0.0,416.6666666666667,416.6666666666667,1,1,0,0,1,0,0,0.0,0,0,0,0,0,0 +no_session_ids,no_loss,both_restart,1,1,0.0,0.0,416.6666666666667,416.6666666666667,1,1,0,0,1,0,0,0.0,0,0,0,0,0,0 +no_session_ids,no_loss,ground_restart_emergency,1,1,0.0,0.0,416.6666666666667,416.6666666666667,1,1,0,1,1,0,0,0.0,0,0,0,0,0,0 +no_session_ids,no_loss,rover_restart_latched,1,1,0.0,0.0,416.6666666666667,416.6666666666667,1,1,1,0,1,0,0,0.0,0,0,0,0,0,0 +no_session_ids,no_loss,long_link_break,1,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +no_session_ids,no_loss,old_ground_session_control,1,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +no_session_ids,no_loss,old_rover_boot_control,1,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +no_session_ids,no_loss,old_control_epoch,1,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +no_session_ids,no_loss,sequence_reset_new_session,1,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +no_session_ids,no_loss,sequence_wrap,1,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +no_session_ids,no_loss,duplicate_hello,1,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +no_session_ids,no_loss,lost_session_status,1,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +no_session_ids,no_loss,lost_authorize_ack,1,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +no_session_ids,no_loss,lost_emergency_ack,1,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +no_session_ids,no_loss,lost_reset_ack,1,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,1,1,0,0 +no_session_ids,no_loss,old_reset_request,1,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,1,1,0,0,0,0 +no_session_ids,no_loss,late_positive_after_emergency,1,0,0.0,0.0,0.0,0.0,0,0,1,0,0,0,0,0.0,1,0,0,0,0,0 +no_session_ids,no_loss,restart_after_reset_before_ack,1,1,0.0,0.0,416.6666666666667,416.6666666666667,1,1,0,0,1,0,0,0.0,0,0,1,1,0,0 +no_session_ids,260_200,normal_start,200,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +no_session_ids,260_200,ground_restart_moving,200,200,0.0,0.0,416.66666666666674,416.6666666666667,200,200,0,0,200,0,0,0.0,0,0,0,0,0,0 +no_session_ids,260_200,rover_restart_moving,200,200,0.0,0.0,416.66666666666674,416.6666666666667,200,200,0,0,200,0,0,0.0,0,0,0,0,0,0 +no_session_ids,260_200,both_restart,200,200,0.0,0.0,416.66666666666674,416.6666666666667,200,200,0,0,200,0,0,0.0,0,0,0,0,0,0 +no_session_ids,260_200,ground_restart_emergency,200,200,0.0,0.0,416.66666666666674,416.6666666666667,200,200,0,200,200,0,0,0.0,0,0,0,0,0,0 +no_session_ids,260_200,rover_restart_latched,200,200,0.0,0.0,416.66666666666674,416.6666666666667,200,200,200,0,200,0,0,0.0,0,0,0,0,0,0 +no_session_ids,260_200,long_link_break,200,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +no_session_ids,260_200,old_ground_session_control,200,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +no_session_ids,260_200,old_rover_boot_control,200,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +no_session_ids,260_200,old_control_epoch,200,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +no_session_ids,260_200,sequence_reset_new_session,200,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +no_session_ids,260_200,sequence_wrap,200,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +no_session_ids,260_200,duplicate_hello,200,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +no_session_ids,260_200,lost_session_status,200,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +no_session_ids,260_200,lost_authorize_ack,200,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +no_session_ids,260_200,lost_emergency_ack,200,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +no_session_ids,260_200,lost_reset_ack,200,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,200,200,0,0 +no_session_ids,260_200,old_reset_request,200,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,200,200,0,0,0,0 +no_session_ids,260_200,late_positive_after_emergency,200,0,0.0,0.0,0.0,0.0,0,0,200,0,0,0,0,0.0,200,0,0,0,0,0 +no_session_ids,260_200,restart_after_reset_before_ack,200,200,0.0,0.0,416.66666666666674,416.6666666666667,200,200,0,0,200,0,0,0.0,0,0,200,200,0,0 +no_session_ids,230_1000,normal_start,200,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +no_session_ids,230_1000,ground_restart_moving,200,200,0.0,0.0,416.66666666666674,416.6666666666667,200,200,0,0,200,0,0,0.0,0,0,0,0,0,0 +no_session_ids,230_1000,rover_restart_moving,200,200,0.0,0.0,416.66666666666674,416.6666666666667,200,200,0,0,200,0,0,0.0,0,0,0,0,0,0 +no_session_ids,230_1000,both_restart,200,200,0.0,0.0,416.66666666666674,416.6666666666667,200,200,0,0,200,0,0,0.0,0,0,0,0,0,0 +no_session_ids,230_1000,ground_restart_emergency,200,200,0.0,0.0,416.66666666666674,416.6666666666667,200,200,0,200,200,0,0,0.0,0,0,0,0,0,0 +no_session_ids,230_1000,rover_restart_latched,200,200,0.0,0.0,416.66666666666674,416.6666666666667,200,200,200,0,200,0,0,0.0,0,0,0,0,0,0 +no_session_ids,230_1000,long_link_break,200,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +no_session_ids,230_1000,old_ground_session_control,200,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +no_session_ids,230_1000,old_rover_boot_control,200,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +no_session_ids,230_1000,old_control_epoch,200,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +no_session_ids,230_1000,sequence_reset_new_session,200,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +no_session_ids,230_1000,sequence_wrap,200,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +no_session_ids,230_1000,duplicate_hello,200,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +no_session_ids,230_1000,lost_session_status,200,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +no_session_ids,230_1000,lost_authorize_ack,200,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +no_session_ids,230_1000,lost_emergency_ack,200,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +no_session_ids,230_1000,lost_reset_ack,200,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,200,200,0,0 +no_session_ids,230_1000,old_reset_request,200,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,200,200,0,0,0,0 +no_session_ids,230_1000,late_positive_after_emergency,200,0,0.0,0.0,0.0,0.0,0,0,200,0,0,0,0,0.0,200,0,0,0,0,0 +no_session_ids,230_1000,restart_after_reset_before_ack,200,200,0.0,0.0,416.66666666666674,416.6666666666667,200,200,0,0,200,0,0,0.0,0,0,200,200,0,0 +session_safe_boot,no_loss,normal_start,1,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +session_safe_boot,no_loss,ground_restart_moving,1,1,3.6,3.6,9.77366255144033,9.77366255144033,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +session_safe_boot,no_loss,rover_restart_moving,1,1,0.0,0.0,8.037551440329219,8.037551440329219,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +session_safe_boot,no_loss,both_restart,1,1,0.0,0.0,8.037551440329219,8.037551440329219,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +session_safe_boot,no_loss,ground_restart_emergency,1,1,0.0,0.0,0.0,0.0,0,0,0,1,0,0,0,0.0,0,0,0,0,0,0 +session_safe_boot,no_loss,rover_restart_latched,1,1,0.0,0.0,8.037551440329219,8.037551440329219,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +session_safe_boot,no_loss,long_link_break,1,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +session_safe_boot,no_loss,old_ground_session_control,1,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +session_safe_boot,no_loss,old_rover_boot_control,1,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +session_safe_boot,no_loss,old_control_epoch,1,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +session_safe_boot,no_loss,sequence_reset_new_session,1,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +session_safe_boot,no_loss,sequence_wrap,1,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +session_safe_boot,no_loss,duplicate_hello,1,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +session_safe_boot,no_loss,lost_session_status,1,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +session_safe_boot,no_loss,lost_authorize_ack,1,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +session_safe_boot,no_loss,lost_emergency_ack,1,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +session_safe_boot,no_loss,lost_reset_ack,1,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +session_safe_boot,no_loss,old_reset_request,1,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +session_safe_boot,no_loss,late_positive_after_emergency,1,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +session_safe_boot,no_loss,restart_after_reset_before_ack,1,1,0.0,0.0,8.037551440329219,8.037551440329219,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +session_safe_boot,260_200,normal_start,200,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +session_safe_boot,260_200,ground_restart_moving,200,200,4.153846153846154,4.153846153846154,9.773662551440328,9.77366255144033,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +session_safe_boot,260_200,rover_restart_moving,200,200,0.0,0.0,8.03755144032922,8.037551440329219,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +session_safe_boot,260_200,both_restart,200,200,0.0,0.0,8.03755144032922,8.037551440329219,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +session_safe_boot,260_200,ground_restart_emergency,200,200,0.0,0.0,0.0,0.0,0,0,0,200,0,0,0,0.0,0,0,0,0,0,0 +session_safe_boot,260_200,rover_restart_latched,200,200,0.0,0.0,8.03755144032922,8.037551440329219,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +session_safe_boot,260_200,long_link_break,200,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +session_safe_boot,260_200,old_ground_session_control,200,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +session_safe_boot,260_200,old_rover_boot_control,200,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +session_safe_boot,260_200,old_control_epoch,200,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +session_safe_boot,260_200,sequence_reset_new_session,200,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +session_safe_boot,260_200,sequence_wrap,200,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +session_safe_boot,260_200,duplicate_hello,200,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +session_safe_boot,260_200,lost_session_status,200,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +session_safe_boot,260_200,lost_authorize_ack,200,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +session_safe_boot,260_200,lost_emergency_ack,200,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +session_safe_boot,260_200,lost_reset_ack,200,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +session_safe_boot,260_200,old_reset_request,200,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +session_safe_boot,260_200,late_positive_after_emergency,200,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +session_safe_boot,260_200,restart_after_reset_before_ack,200,200,0.0,0.0,8.03755144032922,8.037551440329219,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +session_safe_boot,230_1000,normal_start,200,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +session_safe_boot,230_1000,ground_restart_moving,200,200,4.695652173913045,4.695652173913044,9.773662551440328,9.77366255144033,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +session_safe_boot,230_1000,rover_restart_moving,200,200,0.0,0.0,8.03755144032922,8.037551440329219,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +session_safe_boot,230_1000,both_restart,200,200,0.0,0.0,8.03755144032922,8.037551440329219,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +session_safe_boot,230_1000,ground_restart_emergency,200,200,0.0,0.0,0.0,0.0,0,0,0,200,0,0,0,0.0,0,0,0,0,0,0 +session_safe_boot,230_1000,rover_restart_latched,200,200,0.0,0.0,8.03755144032922,8.037551440329219,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +session_safe_boot,230_1000,long_link_break,200,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +session_safe_boot,230_1000,old_ground_session_control,200,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +session_safe_boot,230_1000,old_rover_boot_control,200,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +session_safe_boot,230_1000,old_control_epoch,200,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +session_safe_boot,230_1000,sequence_reset_new_session,200,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +session_safe_boot,230_1000,sequence_wrap,200,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +session_safe_boot,230_1000,duplicate_hello,200,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +session_safe_boot,230_1000,lost_session_status,200,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +session_safe_boot,230_1000,lost_authorize_ack,200,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +session_safe_boot,230_1000,lost_emergency_ack,200,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +session_safe_boot,230_1000,lost_reset_ack,200,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +session_safe_boot,230_1000,old_reset_request,200,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +session_safe_boot,230_1000,late_positive_after_emergency,200,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +session_safe_boot,230_1000,restart_after_reset_before_ack,200,200,0.0,0.0,8.03755144032922,8.037551440329219,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +persistent_emergency,no_loss,normal_start,1,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +persistent_emergency,no_loss,ground_restart_moving,1,1,3.6,3.6,9.77366255144033,9.77366255144033,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +persistent_emergency,no_loss,rover_restart_moving,1,1,0.0,0.0,8.037551440329219,8.037551440329219,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +persistent_emergency,no_loss,both_restart,1,1,0.0,0.0,8.037551440329219,8.037551440329219,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +persistent_emergency,no_loss,ground_restart_emergency,1,1,0.0,0.0,0.0,0.0,0,0,0,0,0,1,1,3.6,0,0,0,0,0,0 +persistent_emergency,no_loss,rover_restart_latched,1,1,0.0,0.0,8.037551440329219,8.037551440329219,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +persistent_emergency,no_loss,long_link_break,1,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +persistent_emergency,no_loss,old_ground_session_control,1,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +persistent_emergency,no_loss,old_rover_boot_control,1,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +persistent_emergency,no_loss,old_control_epoch,1,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +persistent_emergency,no_loss,sequence_reset_new_session,1,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +persistent_emergency,no_loss,sequence_wrap,1,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +persistent_emergency,no_loss,duplicate_hello,1,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +persistent_emergency,no_loss,lost_session_status,1,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +persistent_emergency,no_loss,lost_authorize_ack,1,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +persistent_emergency,no_loss,lost_emergency_ack,1,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +persistent_emergency,no_loss,lost_reset_ack,1,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +persistent_emergency,no_loss,old_reset_request,1,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +persistent_emergency,no_loss,late_positive_after_emergency,1,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +persistent_emergency,no_loss,restart_after_reset_before_ack,1,1,0.0,0.0,8.037551440329219,8.037551440329219,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +persistent_emergency,260_200,normal_start,200,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +persistent_emergency,260_200,ground_restart_moving,200,200,4.153846153846154,4.153846153846154,9.773662551440328,9.77366255144033,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +persistent_emergency,260_200,rover_restart_moving,200,200,0.0,0.0,8.03755144032922,8.037551440329219,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +persistent_emergency,260_200,both_restart,200,200,0.0,0.0,8.03755144032922,8.037551440329219,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +persistent_emergency,260_200,ground_restart_emergency,200,200,0.0,0.0,0.0,0.0,0,0,0,0,0,200,200,4.153846153846154,0,0,0,0,0,0 +persistent_emergency,260_200,rover_restart_latched,200,200,0.0,0.0,8.03755144032922,8.037551440329219,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +persistent_emergency,260_200,long_link_break,200,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +persistent_emergency,260_200,old_ground_session_control,200,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +persistent_emergency,260_200,old_rover_boot_control,200,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +persistent_emergency,260_200,old_control_epoch,200,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +persistent_emergency,260_200,sequence_reset_new_session,200,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +persistent_emergency,260_200,sequence_wrap,200,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +persistent_emergency,260_200,duplicate_hello,200,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +persistent_emergency,260_200,lost_session_status,200,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +persistent_emergency,260_200,lost_authorize_ack,200,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +persistent_emergency,260_200,lost_emergency_ack,200,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +persistent_emergency,260_200,lost_reset_ack,200,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +persistent_emergency,260_200,old_reset_request,200,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +persistent_emergency,260_200,late_positive_after_emergency,200,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +persistent_emergency,260_200,restart_after_reset_before_ack,200,200,0.0,0.0,8.03755144032922,8.037551440329219,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +persistent_emergency,230_1000,normal_start,200,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +persistent_emergency,230_1000,ground_restart_moving,200,200,4.695652173913045,4.695652173913044,9.773662551440328,9.77366255144033,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +persistent_emergency,230_1000,rover_restart_moving,200,200,0.0,0.0,8.03755144032922,8.037551440329219,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +persistent_emergency,230_1000,both_restart,200,200,0.0,0.0,8.03755144032922,8.037551440329219,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +persistent_emergency,230_1000,ground_restart_emergency,200,200,0.0,0.0,0.0,0.0,0,0,0,0,0,200,200,4.695652173913045,0,0,0,0,0,0 +persistent_emergency,230_1000,rover_restart_latched,200,200,0.0,0.0,8.03755144032922,8.037551440329219,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +persistent_emergency,230_1000,long_link_break,200,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +persistent_emergency,230_1000,old_ground_session_control,200,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +persistent_emergency,230_1000,old_rover_boot_control,200,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +persistent_emergency,230_1000,old_control_epoch,200,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +persistent_emergency,230_1000,sequence_reset_new_session,200,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +persistent_emergency,230_1000,sequence_wrap,200,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +persistent_emergency,230_1000,duplicate_hello,200,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +persistent_emergency,230_1000,lost_session_status,200,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +persistent_emergency,230_1000,lost_authorize_ack,200,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +persistent_emergency,230_1000,lost_emergency_ack,200,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +persistent_emergency,230_1000,lost_reset_ack,200,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +persistent_emergency,230_1000,old_reset_request,200,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +persistent_emergency,230_1000,late_positive_after_emergency,200,0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 +persistent_emergency,230_1000,restart_after_reset_before_ack,200,200,0.0,0.0,8.03755144032922,8.037551440329219,0,0,0,0,0,0,0,0.0,0,0,0,0,0,0 diff --git a/data/processed/lab041/lab041_safety_violations.png b/data/processed/lab041/lab041_safety_violations.png new file mode 100644 index 0000000..230ccb3 Binary files /dev/null and b/data/processed/lab041/lab041_safety_violations.png differ diff --git a/data/processed/lab041/lab041_session_metrics.csv b/data/processed/lab041/lab041_session_metrics.csv new file mode 100644 index 0000000..58edc9d --- /dev/null +++ b/data/processed/lab041/lab041_session_metrics.csv @@ -0,0 +1,181 @@ +architecture,channel_condition,scenario,repetitions,mean_safe_sync_ms,p95_safe_sync_ms,mean_session_hello,mean_session_status,mean_lost_messages,mean_retries,mean_duplicates,mean_session_rejects,mean_ground_safe_ms,mean_rover_safe_ms,mean_authorize_ack_ms,mean_authorization_repeats,mean_authorization_acks_lost,mean_ack_to_operator_ms,mean_actual_motion_ms,movement_before_sync,movement_before_authorize_ack,movement_without_new_operator,automatic_old_command_restorations,old_control_epoch_uses +no_session_ids,no_loss,normal_start,1,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0 +no_session_ids,no_loss,ground_restart_moving,1,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1,1,1,1,0 +no_session_ids,no_loss,rover_restart_moving,1,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1,1,1,1,0 +no_session_ids,no_loss,both_restart,1,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1,1,1,1,0 +no_session_ids,no_loss,ground_restart_emergency,1,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1,0,1,1,0 +no_session_ids,no_loss,rover_restart_latched,1,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1,0,1,1,0 +no_session_ids,no_loss,long_link_break,1,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0 +no_session_ids,no_loss,old_ground_session_control,1,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0 +no_session_ids,no_loss,old_rover_boot_control,1,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0 +no_session_ids,no_loss,old_control_epoch,1,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0,0,0,0,1 +no_session_ids,no_loss,sequence_reset_new_session,1,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0 +no_session_ids,no_loss,sequence_wrap,1,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0 +no_session_ids,no_loss,duplicate_hello,1,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0 +no_session_ids,no_loss,lost_session_status,1,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0 +no_session_ids,no_loss,lost_authorize_ack,1,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0,1,0,0,0 +no_session_ids,no_loss,lost_emergency_ack,1,0.0,0.0,0.0,0.0,1.0,1.0,1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0 +no_session_ids,no_loss,lost_reset_ack,1,0.0,0.0,0.0,0.0,1.0,1.0,1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0 +no_session_ids,no_loss,old_reset_request,1,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0 +no_session_ids,no_loss,late_positive_after_emergency,1,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0 +no_session_ids,no_loss,restart_after_reset_before_ack,1,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1,0,1,1,0 +no_session_ids,260_200,normal_start,200,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0 +no_session_ids,260_200,ground_restart_moving,200,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,200,200,200,200,0 +no_session_ids,260_200,rover_restart_moving,200,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,200,200,200,200,0 +no_session_ids,260_200,both_restart,200,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,200,200,200,200,0 +no_session_ids,260_200,ground_restart_emergency,200,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,200,0,200,200,0 +no_session_ids,260_200,rover_restart_latched,200,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,200,0,200,200,0 +no_session_ids,260_200,long_link_break,200,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0 +no_session_ids,260_200,old_ground_session_control,200,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0 +no_session_ids,260_200,old_rover_boot_control,200,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0 +no_session_ids,260_200,old_control_epoch,200,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0,0,0,0,200 +no_session_ids,260_200,sequence_reset_new_session,200,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0 +no_session_ids,260_200,sequence_wrap,200,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0 +no_session_ids,260_200,duplicate_hello,200,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0 +no_session_ids,260_200,lost_session_status,200,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0 +no_session_ids,260_200,lost_authorize_ack,200,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0,200,0,0,0 +no_session_ids,260_200,lost_emergency_ack,200,0.0,0.0,0.0,0.0,1.17,1.17,1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0 +no_session_ids,260_200,lost_reset_ack,200,0.0,0.0,0.0,0.0,1.105,1.105,1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0 +no_session_ids,260_200,old_reset_request,200,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0 +no_session_ids,260_200,late_positive_after_emergency,200,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0 +no_session_ids,260_200,restart_after_reset_before_ack,200,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,200,0,200,200,0 +no_session_ids,230_1000,normal_start,200,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0 +no_session_ids,230_1000,ground_restart_moving,200,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,200,200,200,200,0 +no_session_ids,230_1000,rover_restart_moving,200,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,200,200,200,200,0 +no_session_ids,230_1000,both_restart,200,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,200,200,200,200,0 +no_session_ids,230_1000,ground_restart_emergency,200,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,200,0,200,200,0 +no_session_ids,230_1000,rover_restart_latched,200,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,200,0,200,200,0 +no_session_ids,230_1000,long_link_break,200,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0 +no_session_ids,230_1000,old_ground_session_control,200,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0 +no_session_ids,230_1000,old_rover_boot_control,200,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0 +no_session_ids,230_1000,old_control_epoch,200,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0,0,0,0,200 +no_session_ids,230_1000,sequence_reset_new_session,200,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0 +no_session_ids,230_1000,sequence_wrap,200,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0 +no_session_ids,230_1000,duplicate_hello,200,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0 +no_session_ids,230_1000,lost_session_status,200,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0 +no_session_ids,230_1000,lost_authorize_ack,200,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0,200,0,0,0 +no_session_ids,230_1000,lost_emergency_ack,200,0.0,0.0,0.0,0.0,3.37,3.37,1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0 +no_session_ids,230_1000,lost_reset_ack,200,0.0,0.0,0.0,0.0,1.42,1.42,1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0 +no_session_ids,230_1000,old_reset_request,200,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0 +no_session_ids,230_1000,late_positive_after_emergency,200,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0 +no_session_ids,230_1000,restart_after_reset_before_ack,200,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,200,0,200,200,0 +session_safe_boot,no_loss,normal_start,1,3.6,3.6,1.0,1.0,0.0,0.0,0.0,0.0,3.6,1.7866666666666666,103.54666666666668,0.0,0.0,200.0,307.1466666666667,0,0,0,0,0 +session_safe_boot,no_loss,ground_restart_moving,1,3.6,3.6,1.0,1.0,0.0,0.0,0.0,0.0,3.6,1.7866666666666666,103.54666666666668,0.0,0.0,200.0,307.1466666666667,0,0,0,0,0 +session_safe_boot,no_loss,rover_restart_moving,1,3.6,3.6,1.0,1.0,0.0,0.0,0.0,0.0,3.6,1.7866666666666666,103.54666666666668,0.0,0.0,200.0,307.1466666666667,0,0,0,0,0 +session_safe_boot,no_loss,both_restart,1,3.6,3.6,1.0,1.0,0.0,0.0,0.0,0.0,3.6,1.7866666666666666,103.54666666666668,0.0,0.0,200.0,307.1466666666667,0,0,0,0,0 +session_safe_boot,no_loss,ground_restart_emergency,1,3.6,3.6,1.0,1.0,0.0,0.0,0.0,0.0,3.6,1.7866666666666666,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0 +session_safe_boot,no_loss,rover_restart_latched,1,3.6,3.6,1.0,1.0,0.0,0.0,0.0,0.0,3.6,1.7866666666666666,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0 +session_safe_boot,no_loss,long_link_break,1,5003.6,5003.6,1.0,1.0,0.0,0.0,0.0,1.0,5003.6,5001.786666666667,103.54666666666645,0.0,0.0,200.0,5307.146666666667,0,0,0,0,0 +session_safe_boot,no_loss,old_ground_session_control,1,3.6,3.6,1.0,1.0,0.0,0.0,0.0,1.0,3.6,1.7866666666666666,103.54666666666668,0.0,0.0,200.0,307.1466666666667,0,0,0,0,0 +session_safe_boot,no_loss,old_rover_boot_control,1,3.6,3.6,1.0,1.0,0.0,0.0,0.0,1.0,3.6,1.7866666666666666,103.54666666666668,0.0,0.0,200.0,307.1466666666667,0,0,0,0,0 +session_safe_boot,no_loss,old_control_epoch,1,3.6,3.6,1.0,1.0,0.0,0.0,0.0,1.0,3.6,1.7866666666666666,103.54666666666668,0.0,0.0,200.0,307.1466666666667,0,0,0,0,0 +session_safe_boot,no_loss,sequence_reset_new_session,1,3.6,3.6,1.0,1.0,0.0,0.0,0.0,0.0,3.6,1.7866666666666666,103.54666666666668,0.0,0.0,200.0,307.1466666666667,0,0,0,0,0 +session_safe_boot,no_loss,sequence_wrap,1,3.6,3.6,1.0,1.0,0.0,0.0,0.0,1.0,3.6,1.7866666666666666,103.54666666666668,0.0,0.0,200.0,307.1466666666667,0,0,0,0,0 +session_safe_boot,no_loss,duplicate_hello,1,3.6,3.6,2.0,2.0,0.0,0.0,1.0,0.0,3.6,1.7866666666666666,103.54666666666668,0.0,0.0,200.0,307.1466666666667,0,0,0,0,0 +session_safe_boot,no_loss,lost_session_status,1,53.6,53.6,2.0,2.0,1.0,1.0,1.0,0.0,53.6,51.78666666666667,103.54666666666668,0.0,0.0,200.0,357.1466666666667,0,0,0,0,0 +session_safe_boot,no_loss,lost_authorize_ack,1,3.6,3.6,1.0,1.0,1.0,1.0,1.0,0.0,3.6,1.7866666666666666,153.54666666666668,1.0,1.0,200.0,357.1466666666667,0,0,0,0,0 +session_safe_boot,no_loss,lost_emergency_ack,1,3.6,3.6,1.0,1.0,1.0,1.0,1.0,0.0,3.6,1.7866666666666666,103.54666666666668,0.0,0.0,200.0,307.1466666666667,0,0,0,0,0 +session_safe_boot,no_loss,lost_reset_ack,1,3.6,3.6,1.0,1.0,1.0,1.0,1.0,0.0,3.6,1.7866666666666666,103.54666666666668,0.0,0.0,200.0,307.1466666666667,0,0,0,0,0 +session_safe_boot,no_loss,old_reset_request,1,3.6,3.6,1.0,1.0,0.0,0.0,0.0,1.0,3.6,1.7866666666666666,103.54666666666668,0.0,0.0,200.0,307.1466666666667,0,0,0,0,0 +session_safe_boot,no_loss,late_positive_after_emergency,1,3.6,3.6,1.0,1.0,0.0,0.0,0.0,1.0,3.6,1.7866666666666666,103.54666666666668,0.0,0.0,200.0,307.1466666666667,0,0,0,0,0 +session_safe_boot,no_loss,restart_after_reset_before_ack,1,3.6,3.6,1.0,1.0,0.0,0.0,0.0,0.0,3.6,1.7866666666666666,103.54666666666668,0.0,0.0,200.0,307.1466666666667,0,0,0,0,0 +session_safe_boot,260_200,normal_start,200,4.153846153846154,4.153846153846154,1.0,1.0,0.0,0.0,0.0,0.0,4.153846153846154,2.0615384615384613,104.0923076923077,0.0,0.0,200.0,308.2461538461539,0,0,0,0,0 +session_safe_boot,260_200,ground_restart_moving,200,4.153846153846154,4.153846153846154,1.0,1.0,0.0,0.0,0.0,0.0,4.153846153846154,2.0615384615384613,104.0923076923077,0.0,0.0,200.0,308.2461538461539,0,0,0,0,0 +session_safe_boot,260_200,rover_restart_moving,200,4.153846153846154,4.153846153846154,1.0,1.0,0.05,0.05,0.0,0.0,4.153846153846154,2.0615384615384613,106.59230769230771,0.05,0.0,200.0,310.7461538461539,0,0,0,0,0 +session_safe_boot,260_200,both_restart,200,4.153846153846154,4.153846153846154,1.0,1.0,0.11,0.11,0.0,0.0,4.153846153846154,2.0615384615384613,109.5923076923077,0.11,0.0,200.0,313.7461538461539,0,0,0,0,0 +session_safe_boot,260_200,ground_restart_emergency,200,4.153846153846154,4.153846153846154,1.0,1.0,0.0,0.0,0.0,0.0,4.153846153846154,2.0615384615384613,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0 +session_safe_boot,260_200,rover_restart_latched,200,4.153846153846154,4.153846153846154,1.0,1.0,0.0,0.0,0.0,0.0,4.153846153846154,2.0615384615384613,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0 +session_safe_boot,260_200,long_link_break,200,5013.1538461538485,5004.153846153846,1.18,1.0,0.235,0.235,0.0,1.0,5013.1538461538485,5011.061538461539,106.84230769230771,0.055,0.0,200.0,5319.996153846155,0,0,0,0,0 +session_safe_boot,260_200,old_ground_session_control,200,4.153846153846154,4.153846153846154,1.0,1.0,0.03,0.03,0.0,1.0,4.153846153846154,2.0615384615384613,105.5923076923077,0.03,0.0,200.0,309.7461538461539,0,0,0,0,0 +session_safe_boot,260_200,old_rover_boot_control,200,4.153846153846154,4.153846153846154,1.0,1.0,0.02,0.02,0.0,1.0,4.153846153846154,2.0615384615384613,105.09230769230768,0.02,0.0,200.0,309.24615384615396,0,0,0,0,0 +session_safe_boot,260_200,old_control_epoch,200,4.153846153846154,4.153846153846154,1.0,1.0,0.0,0.0,0.0,1.0,4.153846153846154,2.0615384615384613,104.0923076923077,0.0,0.0,200.0,308.2461538461539,0,0,0,0,0 +session_safe_boot,260_200,sequence_reset_new_session,200,4.153846153846154,4.153846153846154,1.0,1.0,0.105,0.105,0.0,0.0,4.153846153846154,2.0615384615384613,109.3423076923077,0.105,0.0,200.0,313.4961538461539,0,0,0,0,0 +session_safe_boot,260_200,sequence_wrap,200,4.153846153846154,4.153846153846154,1.0,1.0,0.0,0.0,0.0,1.0,4.153846153846154,2.0615384615384613,104.0923076923077,0.0,0.0,200.0,308.2461538461539,0,0,0,0,0 +session_safe_boot,260_200,duplicate_hello,200,4.153846153846154,4.153846153846154,2.0,2.0,0.0,0.0,1.0,0.0,4.153846153846154,2.0615384615384613,104.0923076923077,0.0,0.0,200.0,308.2461538461539,0,0,0,0,0 +session_safe_boot,260_200,lost_session_status,200,54.15384615384614,54.15384615384615,2.0,2.0,1.04,1.04,1.0,0.0,54.15384615384614,52.061538461538476,106.0923076923077,0.04,0.0,200.0,360.2461538461539,0,0,0,0,0 +session_safe_boot,260_200,lost_authorize_ack,200,4.153846153846154,4.153846153846154,1.0,1.0,1.0,1.0,1.0,0.0,4.153846153846154,2.0615384615384613,154.09230769230768,1.0,1.0,200.0,358.24615384615385,0,0,0,0,0 +session_safe_boot,260_200,lost_emergency_ack,200,4.153846153846154,4.153846153846154,1.0,1.0,1.215,1.215,1.0,0.0,4.153846153846154,2.0615384615384613,104.8423076923077,0.015,0.0,200.0,308.9961538461539,0,0,0,0,0 +session_safe_boot,260_200,lost_reset_ack,200,4.153846153846154,4.153846153846154,1.0,1.0,1.145,1.145,1.005,0.0,4.153846153846154,2.0615384615384613,108.5923076923077,0.09,0.0,200.0,312.74615384615396,0,0,0,0,0 +session_safe_boot,260_200,old_reset_request,200,4.153846153846154,4.153846153846154,1.0,1.0,0.03,0.03,0.0,1.0,4.153846153846154,2.0615384615384613,105.5923076923077,0.03,0.0,200.0,309.7461538461539,0,0,0,0,0 +session_safe_boot,260_200,late_positive_after_emergency,200,4.153846153846154,4.153846153846154,1.0,1.0,0.1,0.1,0.0,1.0,4.153846153846154,2.0615384615384613,109.09230769230771,0.1,0.0,200.0,313.2461538461539,0,0,0,0,0 +session_safe_boot,260_200,restart_after_reset_before_ack,200,4.153846153846154,4.153846153846154,1.0,1.0,0.005,0.005,0.0,0.0,4.153846153846154,2.0615384615384613,104.3423076923077,0.005,0.0,200.0,308.4961538461539,0,0,0,0,0 +session_safe_boot,230_1000,normal_start,200,4.695652173913045,4.695652173913044,1.0,1.0,0.0,0.0,0.0,0.0,4.695652173913045,2.330434782608696,104.62608695652172,0.0,0.0,200.0,309.3217391304348,0,0,0,0,0 +session_safe_boot,230_1000,ground_restart_moving,200,4.695652173913045,4.695652173913044,1.0,1.0,0.0,0.0,0.0,0.0,4.695652173913045,2.330434782608696,104.62608695652172,0.0,0.0,200.0,309.3217391304348,0,0,0,0,0 +session_safe_boot,230_1000,rover_restart_moving,200,4.695652173913045,4.695652173913044,1.0,1.0,0.0,0.0,0.0,0.0,4.695652173913045,2.330434782608696,104.62608695652172,0.0,0.0,200.0,309.3217391304348,0,0,0,0,0 +session_safe_boot,230_1000,both_restart,200,4.695652173913045,4.695652173913044,1.0,1.0,0.24,0.24,0.0,0.0,4.695652173913045,2.330434782608696,116.62608695652172,0.24,0.0,200.0,321.3217391304348,0,0,0,0,0 +session_safe_boot,230_1000,ground_restart_emergency,200,4.695652173913045,4.695652173913044,1.0,1.0,0.0,0.0,0.0,0.0,4.695652173913045,2.330434782608696,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0 +session_safe_boot,230_1000,rover_restart_latched,200,4.695652173913045,4.695652173913044,1.0,1.0,0.0,0.0,0.0,0.0,4.695652173913045,2.330434782608696,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0 +session_safe_boot,230_1000,long_link_break,200,5037.445652173914,5004.695652173913,1.655,1.0,0.83,0.83,0.0,1.0,5037.445652173914,5035.080434782608,113.37608695652165,0.175,0.0,200.0,5350.821739130435,0,0,0,0,0 +session_safe_boot,230_1000,old_ground_session_control,200,4.695652173913045,4.695652173913044,1.0,1.0,0.0,0.0,0.0,1.0,4.695652173913045,2.330434782608696,104.62608695652172,0.0,0.0,200.0,309.3217391304348,0,0,0,0,0 +session_safe_boot,230_1000,old_rover_boot_control,200,4.695652173913045,4.695652173913044,1.0,1.0,0.0,0.0,0.0,1.0,4.695652173913045,2.330434782608696,104.62608695652172,0.0,0.0,200.0,309.3217391304348,0,0,0,0,0 +session_safe_boot,230_1000,old_control_epoch,200,4.695652173913045,4.695652173913044,1.0,1.0,0.0,0.0,0.0,1.0,4.695652173913045,2.330434782608696,104.62608695652172,0.0,0.0,200.0,309.3217391304348,0,0,0,0,0 +session_safe_boot,230_1000,sequence_reset_new_session,200,4.695652173913045,4.695652173913044,1.0,1.0,0.055,0.055,0.0,0.0,4.695652173913045,2.330434782608696,107.37608695652172,0.055,0.0,200.0,312.0717391304348,0,0,0,0,0 +session_safe_boot,230_1000,sequence_wrap,200,4.695652173913045,4.695652173913044,1.0,1.0,0.0,0.0,0.0,1.0,4.695652173913045,2.330434782608696,104.62608695652172,0.0,0.0,200.0,309.3217391304348,0,0,0,0,0 +session_safe_boot,230_1000,duplicate_hello,200,4.695652173913045,4.695652173913044,2.0,2.0,0.0,0.0,1.0,0.0,4.695652173913045,2.330434782608696,104.62608695652172,0.0,0.0,200.0,309.3217391304348,0,0,0,0,0 +session_safe_boot,230_1000,lost_session_status,200,54.69565217391304,54.69565217391304,2.0,2.0,1.0,1.0,1.0,0.0,54.69565217391304,52.3304347826087,104.62608695652172,0.0,0.0,200.0,359.3217391304347,0,0,0,0,0 +session_safe_boot,230_1000,lost_authorize_ack,200,4.695652173913045,4.695652173913044,1.0,1.0,1.0,1.0,1.0,0.0,4.695652173913045,2.330434782608696,154.62608695652173,1.0,1.0,200.0,359.3217391304347,0,0,0,0,0 +session_safe_boot,230_1000,lost_emergency_ack,200,4.695652173913045,4.695652173913044,1.0,1.0,1.795,1.795,1.0,0.0,4.695652173913045,2.330434782608696,104.62608695652172,0.0,0.0,200.0,309.3217391304348,0,0,0,0,0 +session_safe_boot,230_1000,lost_reset_ack,200,4.695652173913045,4.695652173913044,1.0,1.0,1.565,1.565,1.0,0.0,4.695652173913045,2.330434782608696,123.87608695652172,0.385,0.0,200.0,328.5717391304348,0,0,0,0,0 +session_safe_boot,230_1000,old_reset_request,200,4.695652173913045,4.695652173913044,1.0,1.0,0.0,0.0,0.0,1.0,4.695652173913045,2.330434782608696,104.62608695652172,0.0,0.0,200.0,309.3217391304348,0,0,0,0,0 +session_safe_boot,230_1000,late_positive_after_emergency,200,4.695652173913045,4.695652173913044,1.0,1.0,0.0,0.0,0.0,1.0,4.695652173913045,2.330434782608696,104.62608695652172,0.0,0.0,200.0,309.3217391304348,0,0,0,0,0 +session_safe_boot,230_1000,restart_after_reset_before_ack,200,4.695652173913045,4.695652173913044,1.0,1.0,0.0,0.0,0.0,0.0,4.695652173913045,2.330434782608696,104.62608695652172,0.0,0.0,200.0,309.3217391304348,0,0,0,0,0 +persistent_emergency,no_loss,normal_start,1,3.6,3.6,1.0,1.0,0.0,0.0,0.0,0.0,3.6,1.7866666666666666,103.54666666666668,0.0,0.0,200.0,307.1466666666667,0,0,0,0,0 +persistent_emergency,no_loss,ground_restart_moving,1,3.6,3.6,1.0,1.0,0.0,0.0,0.0,0.0,3.6,1.7866666666666666,103.54666666666668,0.0,0.0,200.0,307.1466666666667,0,0,0,0,0 +persistent_emergency,no_loss,rover_restart_moving,1,3.6,3.6,1.0,1.0,0.0,0.0,0.0,0.0,3.6,1.7866666666666666,103.54666666666668,0.0,0.0,200.0,307.1466666666667,0,0,0,0,0 +persistent_emergency,no_loss,both_restart,1,3.6,3.6,1.0,1.0,0.0,0.0,0.0,0.0,3.6,1.7866666666666666,103.54666666666668,0.0,0.0,200.0,307.1466666666667,0,0,0,0,0 +persistent_emergency,no_loss,ground_restart_emergency,1,3.6,3.6,1.0,1.0,0.0,0.0,0.0,0.0,3.6,1.7866666666666666,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0 +persistent_emergency,no_loss,rover_restart_latched,1,3.6,3.6,1.0,1.0,0.0,0.0,0.0,0.0,3.6,1.7866666666666666,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0 +persistent_emergency,no_loss,long_link_break,1,5003.6,5003.6,1.0,1.0,0.0,0.0,0.0,1.0,5003.6,5001.786666666667,103.54666666666645,0.0,0.0,200.0,5307.146666666667,0,0,0,0,0 +persistent_emergency,no_loss,old_ground_session_control,1,3.6,3.6,1.0,1.0,0.0,0.0,0.0,1.0,3.6,1.7866666666666666,103.54666666666668,0.0,0.0,200.0,307.1466666666667,0,0,0,0,0 +persistent_emergency,no_loss,old_rover_boot_control,1,3.6,3.6,1.0,1.0,0.0,0.0,0.0,1.0,3.6,1.7866666666666666,103.54666666666668,0.0,0.0,200.0,307.1466666666667,0,0,0,0,0 +persistent_emergency,no_loss,old_control_epoch,1,3.6,3.6,1.0,1.0,0.0,0.0,0.0,1.0,3.6,1.7866666666666666,103.54666666666668,0.0,0.0,200.0,307.1466666666667,0,0,0,0,0 +persistent_emergency,no_loss,sequence_reset_new_session,1,3.6,3.6,1.0,1.0,0.0,0.0,0.0,0.0,3.6,1.7866666666666666,103.54666666666668,0.0,0.0,200.0,307.1466666666667,0,0,0,0,0 +persistent_emergency,no_loss,sequence_wrap,1,3.6,3.6,1.0,1.0,0.0,0.0,0.0,1.0,3.6,1.7866666666666666,103.54666666666668,0.0,0.0,200.0,307.1466666666667,0,0,0,0,0 +persistent_emergency,no_loss,duplicate_hello,1,3.6,3.6,2.0,2.0,0.0,0.0,1.0,0.0,3.6,1.7866666666666666,103.54666666666668,0.0,0.0,200.0,307.1466666666667,0,0,0,0,0 +persistent_emergency,no_loss,lost_session_status,1,53.6,53.6,2.0,2.0,1.0,1.0,1.0,0.0,53.6,51.78666666666667,103.54666666666668,0.0,0.0,200.0,357.1466666666667,0,0,0,0,0 +persistent_emergency,no_loss,lost_authorize_ack,1,3.6,3.6,1.0,1.0,1.0,1.0,1.0,0.0,3.6,1.7866666666666666,153.54666666666668,1.0,1.0,200.0,357.1466666666667,0,0,0,0,0 +persistent_emergency,no_loss,lost_emergency_ack,1,3.6,3.6,1.0,1.0,1.0,1.0,1.0,0.0,3.6,1.7866666666666666,103.54666666666668,0.0,0.0,200.0,307.1466666666667,0,0,0,0,0 +persistent_emergency,no_loss,lost_reset_ack,1,3.6,3.6,1.0,1.0,1.0,1.0,1.0,0.0,3.6,1.7866666666666666,103.54666666666668,0.0,0.0,200.0,307.1466666666667,0,0,0,0,0 +persistent_emergency,no_loss,old_reset_request,1,3.6,3.6,1.0,1.0,0.0,0.0,0.0,1.0,3.6,1.7866666666666666,103.54666666666668,0.0,0.0,200.0,307.1466666666667,0,0,0,0,0 +persistent_emergency,no_loss,late_positive_after_emergency,1,3.6,3.6,1.0,1.0,0.0,0.0,0.0,1.0,3.6,1.7866666666666666,103.54666666666668,0.0,0.0,200.0,307.1466666666667,0,0,0,0,0 +persistent_emergency,no_loss,restart_after_reset_before_ack,1,3.6,3.6,1.0,1.0,0.0,0.0,0.0,0.0,3.6,1.7866666666666666,103.54666666666668,0.0,0.0,200.0,307.1466666666667,0,0,0,0,0 +persistent_emergency,260_200,normal_start,200,4.153846153846154,4.153846153846154,1.0,1.0,0.005,0.005,0.0,0.0,4.153846153846154,2.0615384615384613,104.3423076923077,0.005,0.0,200.0,308.4961538461539,0,0,0,0,0 +persistent_emergency,260_200,ground_restart_moving,200,4.153846153846154,4.153846153846154,1.0,1.0,0.04,0.04,0.0,0.0,4.153846153846154,2.0615384615384613,106.0923076923077,0.04,0.0,200.0,310.2461538461539,0,0,0,0,0 +persistent_emergency,260_200,rover_restart_moving,200,4.153846153846154,4.153846153846154,1.0,1.0,0.065,0.065,0.0,0.0,4.153846153846154,2.0615384615384613,107.3423076923077,0.065,0.0,200.0,311.4961538461539,0,0,0,0,0 +persistent_emergency,260_200,both_restart,200,4.153846153846154,4.153846153846154,1.0,1.0,0.02,0.02,0.0,0.0,4.153846153846154,2.0615384615384613,105.09230769230768,0.02,0.0,200.0,309.24615384615396,0,0,0,0,0 +persistent_emergency,260_200,ground_restart_emergency,200,4.153846153846154,4.153846153846154,1.0,1.0,0.0,0.0,0.0,0.0,4.153846153846154,2.0615384615384613,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0 +persistent_emergency,260_200,rover_restart_latched,200,4.153846153846154,4.153846153846154,1.0,1.0,0.0,0.0,0.0,0.0,4.153846153846154,2.0615384615384613,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0 +persistent_emergency,260_200,long_link_break,200,5009.403846153848,5004.153846153846,1.105,1.0,0.18,0.18,0.0,1.0,5009.403846153848,5007.311538461539,107.84230769230771,0.075,0.0,200.0,5317.246153846156,0,0,0,0,0 +persistent_emergency,260_200,old_ground_session_control,200,4.153846153846154,4.153846153846154,1.0,1.0,0.015,0.015,0.0,1.0,4.153846153846154,2.0615384615384613,104.84230769230768,0.015,0.0,200.0,308.9961538461539,0,0,0,0,0 +persistent_emergency,260_200,old_rover_boot_control,200,4.153846153846154,4.153846153846154,1.0,1.0,0.025,0.025,0.0,1.0,4.153846153846154,2.0615384615384613,105.3423076923077,0.025,0.0,200.0,309.4961538461539,0,0,0,0,0 +persistent_emergency,260_200,old_control_epoch,200,4.153846153846154,4.153846153846154,1.0,1.0,0.035,0.035,0.0,1.0,4.153846153846154,2.0615384615384613,105.84230769230768,0.035,0.0,200.0,309.9961538461539,0,0,0,0,0 +persistent_emergency,260_200,sequence_reset_new_session,200,4.653846153846154,4.153846153846154,1.01,1.0,0.14,0.14,0.0,0.0,4.653846153846154,2.5615384615384618,110.5923076923077,0.13,0.0,200.0,315.2461538461539,0,0,0,0,0 +persistent_emergency,260_200,sequence_wrap,200,4.153846153846154,4.153846153846154,1.0,1.0,0.05,0.05,0.0,1.0,4.153846153846154,2.0615384615384613,106.5923076923077,0.05,0.0,200.0,310.7461538461539,0,0,0,0,0 +persistent_emergency,260_200,duplicate_hello,200,4.153846153846154,4.153846153846154,2.0,2.0,0.0,0.0,1.0,0.0,4.153846153846154,2.0615384615384613,104.0923076923077,0.0,0.0,200.0,308.2461538461539,0,0,0,0,0 +persistent_emergency,260_200,lost_session_status,200,54.653846153846146,54.15384615384615,2.01,2.0,1.01,1.01,1.0,0.0,54.653846153846146,52.56153846153848,104.0923076923077,0.0,0.0,200.0,358.7461538461539,0,0,0,0,0 +persistent_emergency,260_200,lost_authorize_ack,200,4.153846153846154,4.153846153846154,1.0,1.0,1.21,1.21,1.0,0.0,4.153846153846154,2.0615384615384613,164.5923076923077,1.21,1.0,200.0,368.74615384615385,0,0,0,0,0 +persistent_emergency,260_200,lost_emergency_ack,200,4.153846153846154,4.153846153846154,1.0,1.0,1.245,1.245,1.0,0.0,4.153846153846154,2.0615384615384613,112.59230769230768,0.17,0.0,200.0,316.74615384615396,0,0,0,0,0 +persistent_emergency,260_200,lost_reset_ack,200,4.153846153846154,4.153846153846154,1.0,1.0,1.18,1.18,1.0,0.0,4.153846153846154,2.0615384615384613,106.5923076923077,0.05,0.0,200.0,310.7461538461539,0,0,0,0,0 +persistent_emergency,260_200,old_reset_request,200,4.153846153846154,4.153846153846154,1.0,1.0,0.055,0.055,0.0,1.0,4.153846153846154,2.0615384615384613,106.8423076923077,0.055,0.0,200.0,310.9961538461539,0,0,0,0,0 +persistent_emergency,260_200,late_positive_after_emergency,200,4.153846153846154,4.153846153846154,1.0,1.0,0.06,0.06,0.0,1.0,4.153846153846154,2.0615384615384613,107.09230769230768,0.06,0.0,200.0,311.24615384615396,0,0,0,0,0 +persistent_emergency,260_200,restart_after_reset_before_ack,200,4.153846153846154,4.153846153846154,1.0,1.0,0.01,0.01,0.0,0.0,4.153846153846154,2.0615384615384613,104.59230769230768,0.01,0.0,200.0,308.74615384615396,0,0,0,0,0 +persistent_emergency,230_1000,normal_start,200,4.695652173913045,4.695652173913044,1.0,1.0,0.0,0.0,0.0,0.0,4.695652173913045,2.330434782608696,104.62608695652172,0.0,0.0,200.0,309.3217391304348,0,0,0,0,0 +persistent_emergency,230_1000,ground_restart_moving,200,4.695652173913045,4.695652173913044,1.0,1.0,0.13,0.13,0.0,0.0,4.695652173913045,2.330434782608696,111.1260869565217,0.13,0.0,200.0,315.8217391304348,0,0,0,0,0 +persistent_emergency,230_1000,rover_restart_moving,200,4.695652173913045,4.695652173913044,1.0,1.0,0.17,0.17,0.0,0.0,4.695652173913045,2.330434782608696,113.1260869565217,0.17,0.0,200.0,317.82173913043476,0,0,0,0,0 +persistent_emergency,230_1000,both_restart,200,4.695652173913045,4.695652173913044,1.0,1.0,0.08,0.08,0.0,0.0,4.695652173913045,2.330434782608696,108.62608695652172,0.08,0.0,200.0,313.3217391304348,0,0,0,0,0 +persistent_emergency,230_1000,ground_restart_emergency,200,4.695652173913045,4.695652173913044,1.0,1.0,0.0,0.0,0.0,0.0,4.695652173913045,2.330434782608696,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0 +persistent_emergency,230_1000,rover_restart_latched,200,4.695652173913045,4.695652173913044,1.0,1.0,0.0,0.0,0.0,0.0,4.695652173913045,2.330434782608696,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0 +persistent_emergency,230_1000,long_link_break,200,5022.945652173914,5004.695652173913,1.365,1.0,0.365,0.365,0.0,1.0,5022.945652173914,5020.580434782608,104.62608695652165,0.0,0.0,200.0,5327.571739130434,0,0,0,0,0 +persistent_emergency,230_1000,old_ground_session_control,200,4.695652173913045,4.695652173913044,1.0,1.0,0.0,0.0,0.0,1.0,4.695652173913045,2.330434782608696,104.62608695652172,0.0,0.0,200.0,309.3217391304348,0,0,0,0,0 +persistent_emergency,230_1000,old_rover_boot_control,200,4.695652173913045,4.695652173913044,1.0,1.0,0.0,0.0,0.0,1.0,4.695652173913045,2.330434782608696,104.62608695652172,0.0,0.0,200.0,309.3217391304348,0,0,0,0,0 +persistent_emergency,230_1000,old_control_epoch,200,4.695652173913045,4.695652173913044,1.0,1.0,0.205,0.205,0.0,1.0,4.695652173913045,2.330434782608696,114.87608695652173,0.205,0.0,200.0,319.5717391304349,0,0,0,0,0 +persistent_emergency,230_1000,sequence_reset_new_session,200,6.945652173913045,4.695652173913044,1.045,1.0,0.045,0.045,0.0,0.0,6.945652173913045,4.580434782608696,104.62608695652172,0.0,0.0,200.0,311.57173913043476,0,0,0,0,0 +persistent_emergency,230_1000,sequence_wrap,200,4.695652173913045,4.695652173913044,1.0,1.0,0.135,0.135,0.0,1.0,4.695652173913045,2.330434782608696,111.37608695652172,0.135,0.0,200.0,316.0717391304348,0,0,0,0,0 +persistent_emergency,230_1000,duplicate_hello,200,4.695652173913045,4.695652173913044,2.0,2.0,0.0,0.0,1.0,0.0,4.695652173913045,2.330434782608696,104.62608695652172,0.0,0.0,200.0,309.3217391304348,0,0,0,0,0 +persistent_emergency,230_1000,lost_session_status,200,54.69565217391304,54.69565217391304,2.0,2.0,1.0,1.0,1.0,0.0,54.69565217391304,52.3304347826087,104.62608695652172,0.0,0.0,200.0,359.3217391304347,0,0,0,0,0 +persistent_emergency,230_1000,lost_authorize_ack,200,4.695652173913045,4.695652173913044,1.0,1.0,1.0,1.0,1.0,0.0,4.695652173913045,2.330434782608696,154.62608695652173,1.0,1.0,200.0,359.3217391304347,0,0,0,0,0 +persistent_emergency,230_1000,lost_emergency_ack,200,4.695652173913045,4.695652173913044,1.0,1.0,1.26,1.26,1.0,0.0,4.695652173913045,2.330434782608696,111.37608695652172,0.135,0.0,200.0,316.0717391304348,0,0,0,0,0 +persistent_emergency,230_1000,lost_reset_ack,200,4.695652173913045,4.695652173913044,1.0,1.0,1.68,1.68,1.0,0.0,4.695652173913045,2.330434782608696,116.37608695652173,0.235,0.0,200.0,321.0717391304348,0,0,0,0,0 +persistent_emergency,230_1000,old_reset_request,200,4.695652173913045,4.695652173913044,1.0,1.0,0.0,0.0,0.0,1.0,4.695652173913045,2.330434782608696,104.62608695652172,0.0,0.0,200.0,309.3217391304348,0,0,0,0,0 +persistent_emergency,230_1000,late_positive_after_emergency,200,4.695652173913045,4.695652173913044,1.0,1.0,0.0,0.0,0.0,1.0,4.695652173913045,2.330434782608696,104.62608695652172,0.0,0.0,200.0,309.3217391304348,0,0,0,0,0 +persistent_emergency,230_1000,restart_after_reset_before_ack,200,4.695652173913045,4.695652173913044,1.0,1.0,0.0,0.0,0.0,0.0,4.695652173913045,2.330434782608696,104.62608695652172,0.0,0.0,200.0,309.3217391304348,0,0,0,0,0 diff --git a/data/processed/lab041/lab041_session_time.png b/data/processed/lab041/lab041_session_time.png new file mode 100644 index 0000000..86ceb5b Binary files /dev/null and b/data/processed/lab041/lab041_session_time.png differ diff --git a/data/processed/lab041/lab041_summary.csv b/data/processed/lab041/lab041_summary.csv new file mode 100644 index 0000000..33cda5c --- /dev/null +++ b/data/processed/lab041/lab041_summary.csv @@ -0,0 +1,181 @@ +architecture,channel_condition,scenario,repetitions,safe_session_fraction,authorization_fraction,unsafe_event_fraction,old_packet_acceptance_fraction,emergency_intent_loss_fraction,control_state_load_kbps,episodic_service_load_kbps,full_offered_load_kbps,control_delivered_fraction,telemetry_delivered_fraction,video_published_fraction,maximum_queue_packets +no_session_ids,no_loss,normal_start,1,0.0,1.0,0.0,0.0,0.0,10.88,0.0,261.9528666666667,0.9988266666666666,0.9994133333333334,0.99824,21 +no_session_ids,no_loss,ground_restart_moving,1,0.0,1.0,1.0,0.0,0.0,10.88,0.0,261.9528666666667,0.9988266666666666,0.9994133333333334,0.99824,21 +no_session_ids,no_loss,rover_restart_moving,1,0.0,1.0,1.0,0.0,0.0,10.88,0.0,261.9528666666667,0.9988266666666666,0.9994133333333334,0.99824,21 +no_session_ids,no_loss,both_restart,1,0.0,1.0,1.0,0.0,0.0,10.88,0.0,261.9528666666667,0.9988266666666666,0.9994133333333334,0.99824,21 +no_session_ids,no_loss,ground_restart_emergency,1,0.0,1.0,1.0,0.0,1.0,10.88,0.0,261.9528666666667,0.9988266666666666,0.9994133333333334,0.99824,21 +no_session_ids,no_loss,rover_restart_latched,1,0.0,1.0,1.0,0.0,0.0,10.88,0.0,261.9528666666667,0.9988266666666666,0.9994133333333334,0.99824,21 +no_session_ids,no_loss,long_link_break,1,0.0,1.0,1.0,1.0,0.0,10.88,0.0,261.9528666666667,0.9988266666666666,0.9994133333333334,0.99824,21 +no_session_ids,no_loss,old_ground_session_control,1,0.0,1.0,1.0,1.0,0.0,10.88,0.0,261.9528666666667,0.9988266666666666,0.9994133333333334,0.99824,21 +no_session_ids,no_loss,old_rover_boot_control,1,0.0,1.0,1.0,1.0,0.0,10.88,0.0,261.9528666666667,0.9988266666666666,0.9994133333333334,0.99824,21 +no_session_ids,no_loss,old_control_epoch,1,0.0,1.0,1.0,1.0,0.0,10.88,0.0,261.9528666666667,0.9988266666666666,0.9994133333333334,0.99824,21 +no_session_ids,no_loss,sequence_reset_new_session,1,0.0,1.0,0.0,0.0,0.0,10.88,0.0,261.9528666666667,0.9988266666666666,0.9994133333333334,0.99824,21 +no_session_ids,no_loss,sequence_wrap,1,0.0,1.0,1.0,1.0,0.0,10.88,0.0,261.9528666666667,0.9988266666666666,0.9994133333333334,0.99824,21 +no_session_ids,no_loss,duplicate_hello,1,0.0,1.0,0.0,0.0,0.0,10.88,0.0,261.9528666666667,0.9988266666666666,0.9994133333333334,0.99824,21 +no_session_ids,no_loss,lost_session_status,1,0.0,1.0,0.0,0.0,0.0,10.88,0.0,261.9528666666667,0.9988266666666666,0.9994133333333334,0.99824,21 +no_session_ids,no_loss,lost_authorize_ack,1,0.0,1.0,1.0,0.0,0.0,10.88,0.0,261.9528666666667,0.9988266666666666,0.9994133333333334,0.99824,21 +no_session_ids,no_loss,lost_emergency_ack,1,0.0,1.0,0.0,0.0,0.0,10.88,0.1056,262.0584666666667,0.9987914666666666,0.9993957333333333,0.9981872,22 +no_session_ids,no_loss,lost_reset_ack,1,0.0,1.0,1.0,0.0,0.0,10.88,0.124,262.0768666666667,0.9987853333333333,0.9993926666666667,0.998178,22 +no_session_ids,no_loss,old_reset_request,1,0.0,1.0,1.0,1.0,0.0,10.88,0.0,261.9528666666667,0.9988266666666666,0.9994133333333334,0.99824,21 +no_session_ids,no_loss,late_positive_after_emergency,1,0.0,1.0,1.0,1.0,0.0,10.88,0.0,261.9528666666667,0.9988266666666666,0.9994133333333334,0.99824,21 +no_session_ids,no_loss,restart_after_reset_before_ack,1,0.0,1.0,1.0,0.0,0.0,10.88,0.0,261.9528666666667,0.9988266666666666,0.9994133333333334,0.99824,21 +no_session_ids,260_200,normal_start,200,0.0,1.0,0.0,0.0,0.0,10.88,0.0,261.9528666666667,0.9786461538461536,0.9813230769230771,0.9079692307692306,31 +no_session_ids,260_200,ground_restart_moving,200,0.0,1.0,1.0,0.0,0.0,10.88,0.0,261.9528666666667,0.9786461538461536,0.9813230769230771,0.9079692307692306,31 +no_session_ids,260_200,rover_restart_moving,200,0.0,1.0,1.0,0.0,0.0,10.88,0.0,261.9528666666667,0.9786461538461536,0.9813230769230771,0.9079692307692306,31 +no_session_ids,260_200,both_restart,200,0.0,1.0,1.0,0.0,0.0,10.88,0.0,261.9528666666667,0.9786461538461536,0.9813230769230771,0.9079692307692306,31 +no_session_ids,260_200,ground_restart_emergency,200,0.0,1.0,1.0,0.0,1.0,10.88,0.0,261.9528666666667,0.9786461538461536,0.9813230769230771,0.9079692307692306,31 +no_session_ids,260_200,rover_restart_latched,200,0.0,1.0,1.0,0.0,0.0,10.88,0.0,261.9528666666667,0.9786461538461536,0.9813230769230771,0.9079692307692306,31 +no_session_ids,260_200,long_link_break,200,0.0,1.0,1.0,1.0,0.0,10.88,0.0,261.9528666666667,0.9786461538461536,0.9813230769230771,0.9079692307692306,31 +no_session_ids,260_200,old_ground_session_control,200,0.0,1.0,1.0,1.0,0.0,10.88,0.0,261.9528666666667,0.9786461538461536,0.9813230769230771,0.9079692307692306,31 +no_session_ids,260_200,old_rover_boot_control,200,0.0,1.0,1.0,1.0,0.0,10.88,0.0,261.9528666666667,0.9786461538461536,0.9813230769230771,0.9079692307692306,31 +no_session_ids,260_200,old_control_epoch,200,0.0,1.0,1.0,1.0,0.0,10.88,0.0,261.9528666666667,0.9786461538461536,0.9813230769230771,0.9079692307692306,31 +no_session_ids,260_200,sequence_reset_new_session,200,0.0,1.0,0.0,0.0,0.0,10.88,0.0,261.9528666666667,0.9786461538461536,0.9813230769230771,0.9079692307692306,31 +no_session_ids,260_200,sequence_wrap,200,0.0,1.0,1.0,1.0,0.0,10.88,0.0,261.9528666666667,0.9786461538461536,0.9813230769230771,0.9079692307692306,31 +no_session_ids,260_200,duplicate_hello,200,0.0,1.0,0.0,0.0,0.0,10.88,0.0,261.9528666666667,0.9786461538461536,0.9813230769230771,0.9079692307692306,31 +no_session_ids,260_200,lost_session_status,200,0.0,1.0,0.0,0.0,0.0,10.88,0.0,261.9528666666667,0.9786461538461536,0.9813230769230771,0.9079692307692306,31 +no_session_ids,260_200,lost_authorize_ack,200,0.0,1.0,1.0,0.0,0.0,10.88,0.0,261.9528666666667,0.9786461538461536,0.9813230769230771,0.9079692307692306,31 +no_session_ids,260_200,lost_emergency_ack,200,0.0,1.0,0.0,0.0,0.0,10.88,0.110088,262.0629546666667,0.9786038123076922,0.981301906153846,0.9079057184615386,36 +no_session_ids,260_200,lost_reset_ack,200,0.0,1.0,1.0,0.0,0.0,10.88,0.12731800000000001,262.0801846666667,0.978597185384615,0.9812985926923079,0.9078957780769232,36 +no_session_ids,260_200,old_reset_request,200,0.0,1.0,1.0,1.0,0.0,10.88,0.0,261.9528666666667,0.9786461538461536,0.9813230769230771,0.9079692307692306,31 +no_session_ids,260_200,late_positive_after_emergency,200,0.0,1.0,1.0,1.0,0.0,10.88,0.0,261.9528666666667,0.9786461538461536,0.9813230769230771,0.9079692307692306,31 +no_session_ids,260_200,restart_after_reset_before_ack,200,0.0,1.0,1.0,0.0,0.0,10.88,0.0,261.9528666666667,0.9786461538461536,0.9813230769230771,0.9079692307692306,31 +no_session_ids,230_1000,normal_start,200,0.0,1.0,0.0,0.0,0.0,10.88,0.0,261.9528666666667,0.9784695652173915,0.9792347826086959,0.8607043478260868,41 +no_session_ids,230_1000,ground_restart_moving,200,0.0,1.0,1.0,0.0,0.0,10.88,0.0,261.9528666666667,0.9784695652173915,0.9792347826086959,0.8607043478260868,41 +no_session_ids,230_1000,rover_restart_moving,200,0.0,1.0,1.0,0.0,0.0,10.88,0.0,261.9528666666667,0.9784695652173915,0.9792347826086959,0.8607043478260868,41 +no_session_ids,230_1000,both_restart,200,0.0,1.0,1.0,0.0,0.0,10.88,0.0,261.9528666666667,0.9784695652173915,0.9792347826086959,0.8607043478260868,41 +no_session_ids,230_1000,ground_restart_emergency,200,0.0,1.0,1.0,0.0,1.0,10.88,0.0,261.9528666666667,0.9784695652173915,0.9792347826086959,0.8607043478260868,41 +no_session_ids,230_1000,rover_restart_latched,200,0.0,1.0,1.0,0.0,0.0,10.88,0.0,261.9528666666667,0.9784695652173915,0.9792347826086959,0.8607043478260868,41 +no_session_ids,230_1000,long_link_break,200,0.0,1.0,1.0,1.0,0.0,10.88,0.0,261.9528666666667,0.9784695652173915,0.9792347826086959,0.8607043478260868,41 +no_session_ids,230_1000,old_ground_session_control,200,0.0,1.0,1.0,1.0,0.0,10.88,0.0,261.9528666666667,0.9784695652173915,0.9792347826086959,0.8607043478260868,41 +no_session_ids,230_1000,old_rover_boot_control,200,0.0,1.0,1.0,1.0,0.0,10.88,0.0,261.9528666666667,0.9784695652173915,0.9792347826086959,0.8607043478260868,41 +no_session_ids,230_1000,old_control_epoch,200,0.0,1.0,1.0,1.0,0.0,10.88,0.0,261.9528666666667,0.9784695652173915,0.9792347826086959,0.8607043478260868,41 +no_session_ids,230_1000,sequence_reset_new_session,200,0.0,1.0,0.0,0.0,0.0,10.88,0.0,261.9528666666667,0.9784695652173915,0.9792347826086959,0.8607043478260868,41 +no_session_ids,230_1000,sequence_wrap,200,0.0,1.0,1.0,1.0,0.0,10.88,0.0,261.9528666666667,0.9784695652173915,0.9792347826086959,0.8607043478260868,41 +no_session_ids,230_1000,duplicate_hello,200,0.0,1.0,0.0,0.0,0.0,10.88,0.0,261.9528666666667,0.9784695652173915,0.9792347826086959,0.8607043478260868,41 +no_session_ids,230_1000,lost_session_status,200,0.0,1.0,0.0,0.0,0.0,10.88,0.0,261.9528666666667,0.9784695652173915,0.9792347826086959,0.8607043478260868,41 +no_session_ids,230_1000,lost_authorize_ack,200,0.0,1.0,1.0,0.0,0.0,10.88,0.0,261.9528666666667,0.9784695652173915,0.9792347826086959,0.8607043478260868,41 +no_session_ids,230_1000,lost_emergency_ack,200,0.0,1.0,0.0,0.0,0.0,10.88,0.168168,262.1210346666667,0.978396448695652,0.9791982243478259,0.8605946730434781,46 +no_session_ids,230_1000,lost_reset_ack,200,0.0,1.0,1.0,0.0,0.0,10.88,0.137272,262.0901386666667,0.9784098817391305,0.9792049408695651,0.8606148226086957,46 +no_session_ids,230_1000,old_reset_request,200,0.0,1.0,1.0,1.0,0.0,10.88,0.0,261.9528666666667,0.9784695652173915,0.9792347826086959,0.8607043478260868,41 +no_session_ids,230_1000,late_positive_after_emergency,200,0.0,1.0,1.0,1.0,0.0,10.88,0.0,261.9528666666667,0.9784695652173915,0.9792347826086959,0.8607043478260868,41 +no_session_ids,230_1000,restart_after_reset_before_ack,200,0.0,1.0,1.0,0.0,0.0,10.88,0.0,261.9528666666667,0.9784695652173915,0.9792347826086959,0.8607043478260868,41 +session_safe_boot,no_loss,normal_start,1,1.0,1.0,0.0,0.0,0.0,10.88,0.1072,262.06006666666667,0.9987909333333334,0.9993954666666667,0.9981864,21 +session_safe_boot,no_loss,ground_restart_moving,1,1.0,1.0,0.0,0.0,0.0,10.88,0.1072,262.06006666666667,0.9987909333333334,0.9993954666666667,0.9981864,21 +session_safe_boot,no_loss,rover_restart_moving,1,1.0,1.0,0.0,0.0,0.0,10.88,0.1072,262.06006666666667,0.9987909333333334,0.9993954666666667,0.9981864,21 +session_safe_boot,no_loss,both_restart,1,1.0,1.0,0.0,0.0,0.0,10.88,0.1072,262.06006666666667,0.9987909333333334,0.9993954666666667,0.9981864,21 +session_safe_boot,no_loss,ground_restart_emergency,1,1.0,0.0,0.0,0.0,1.0,10.88,0.054,262.00686666666667,0.9988086666666667,0.9994043333333333,0.998213,21 +session_safe_boot,no_loss,rover_restart_latched,1,1.0,0.0,0.0,0.0,0.0,10.88,0.054,262.00686666666667,0.9988086666666667,0.9994043333333333,0.998213,21 +session_safe_boot,no_loss,long_link_break,1,1.0,1.0,0.0,0.0,0.0,10.88,0.1072,262.06006666666667,0.9987909333333334,0.9993954666666667,0.9981864,21 +session_safe_boot,no_loss,old_ground_session_control,1,1.0,1.0,0.0,0.0,0.0,10.88,0.1072,262.06006666666667,0.9987909333333334,0.9993954666666667,0.9981864,21 +session_safe_boot,no_loss,old_rover_boot_control,1,1.0,1.0,0.0,0.0,0.0,10.88,0.1072,262.06006666666667,0.9987909333333334,0.9993954666666667,0.9981864,21 +session_safe_boot,no_loss,old_control_epoch,1,1.0,1.0,0.0,0.0,0.0,10.88,0.1072,262.06006666666667,0.9987909333333334,0.9993954666666667,0.9981864,21 +session_safe_boot,no_loss,sequence_reset_new_session,1,1.0,1.0,0.0,0.0,0.0,10.88,0.1072,262.06006666666667,0.9987909333333334,0.9993954666666667,0.9981864,21 +session_safe_boot,no_loss,sequence_wrap,1,1.0,1.0,0.0,0.0,0.0,10.88,0.1072,262.06006666666667,0.9987909333333334,0.9993954666666667,0.9981864,21 +session_safe_boot,no_loss,duplicate_hello,1,1.0,1.0,0.0,0.0,0.0,10.88,0.16119999999999998,262.1140666666667,0.9987729333333333,0.9993864666666666,0.9981594,21 +session_safe_boot,no_loss,lost_session_status,1,1.0,1.0,0.0,0.0,0.0,10.88,0.16119999999999998,262.1140666666667,0.9987729333333333,0.9993864666666666,0.9981594,22 +session_safe_boot,no_loss,lost_authorize_ack,1,1.0,1.0,0.0,0.0,0.0,10.88,0.16040000000000001,262.1132666666667,0.9987732,0.9993866,0.9981598,22 +session_safe_boot,no_loss,lost_emergency_ack,1,1.0,1.0,0.0,0.0,0.0,10.88,0.21280000000000002,262.1656666666667,0.9987557333333333,0.9993778666666666,0.9981336,22 +session_safe_boot,no_loss,lost_reset_ack,1,1.0,1.0,0.0,0.0,0.0,10.88,0.2312,262.1840666666667,0.9987496,0.9993748,0.9981244,22 +session_safe_boot,no_loss,old_reset_request,1,1.0,1.0,0.0,0.0,0.0,10.88,0.1072,262.06006666666667,0.9987909333333334,0.9993954666666667,0.9981864,21 +session_safe_boot,no_loss,late_positive_after_emergency,1,1.0,1.0,0.0,0.0,0.0,10.88,0.1072,262.06006666666667,0.9987909333333334,0.9993954666666667,0.9981864,21 +session_safe_boot,no_loss,restart_after_reset_before_ack,1,1.0,1.0,0.0,0.0,0.0,10.88,0.1072,262.06006666666667,0.9987909333333334,0.9993954666666667,0.9981864,21 +session_safe_boot,260_200,normal_start,200,1.0,1.0,0.0,0.0,0.0,10.88,0.1072,262.06006666666667,0.9786049230769228,0.9813024615384619,0.9079073846153847,31 +session_safe_boot,260_200,ground_restart_moving,200,1.0,1.0,0.0,0.0,0.0,10.88,0.1072,262.06006666666667,0.9786049230769228,0.9813024615384619,0.9079073846153847,31 +session_safe_boot,260_200,rover_restart_moving,200,1.0,1.0,0.0,0.0,0.0,10.88,0.10852,262.0613866666667,0.9786044153846152,0.9813022076923079,0.9079066230769232,36 +session_safe_boot,260_200,both_restart,200,1.0,1.0,0.0,0.0,0.0,10.88,0.110104,262.0629706666667,0.9786038061538459,0.9813019030769234,0.9079057092307693,36 +session_safe_boot,260_200,ground_restart_emergency,200,1.0,0.0,0.0,0.0,1.0,10.88,0.054,262.00686666666667,0.9786253846153845,0.9813126923076924,0.9079380769230773,31 +session_safe_boot,260_200,rover_restart_latched,200,1.0,0.0,0.0,0.0,0.0,10.88,0.054,262.00686666666667,0.9786253846153845,0.9813126923076924,0.9079380769230773,31 +session_safe_boot,260_200,long_link_break,200,1.0,1.0,0.0,0.0,0.0,10.88,0.113476,262.0663426666667,0.9786025092307691,0.9813012546153849,0.907903763846154,36 +session_safe_boot,260_200,old_ground_session_control,200,1.0,1.0,0.0,0.0,0.0,10.88,0.107992,262.0608586666667,0.9786046184615382,0.9813023092307697,0.9079069276923077,35 +session_safe_boot,260_200,old_rover_boot_control,200,1.0,1.0,0.0,0.0,0.0,10.88,0.10772799999999999,262.0605946666667,0.9786047199999998,0.9813023600000003,0.9079070800000001,34 +session_safe_boot,260_200,old_control_epoch,200,1.0,1.0,0.0,0.0,0.0,10.88,0.1072,262.06006666666667,0.9786049230769228,0.9813024615384619,0.9079073846153847,31 +session_safe_boot,260_200,sequence_reset_new_session,200,1.0,1.0,0.0,0.0,0.0,10.88,0.10997200000000001,262.0628386666667,0.9786038569230766,0.9813019284615387,0.9079057853846154,36 +session_safe_boot,260_200,sequence_wrap,200,1.0,1.0,0.0,0.0,0.0,10.88,0.1072,262.06006666666667,0.9786049230769228,0.9813024615384619,0.9079073846153847,31 +session_safe_boot,260_200,duplicate_hello,200,1.0,1.0,0.0,0.0,0.0,10.88,0.16119999999999998,262.1140666666667,0.9785841538461537,0.9812920769230772,0.907876230769231,31 +session_safe_boot,260_200,lost_session_status,200,1.0,1.0,0.0,0.0,0.0,10.88,0.162256,262.1151226666667,0.9785837476923075,0.9812918738461539,0.9078756215384618,36 +session_safe_boot,260_200,lost_authorize_ack,200,1.0,1.0,0.0,0.0,0.0,10.88,0.16040000000000001,262.1132666666667,0.9785844615384616,0.981292230769231,0.9078766923076921,32 +session_safe_boot,260_200,lost_emergency_ack,200,1.0,1.0,0.0,0.0,0.0,10.88,0.21847600000000003,262.1713426666667,0.9785621246153846,0.9812810623076923,0.9078431869230771,36 +session_safe_boot,260_200,lost_reset_ack,200,1.0,1.0,0.0,0.0,0.0,10.88,0.23546599999999998,262.18833266666667,0.9785555899999997,0.9812777950000001,0.907833385,36 +session_safe_boot,260_200,old_reset_request,200,1.0,1.0,0.0,0.0,0.0,10.88,0.107992,262.0608586666667,0.9786046184615382,0.9813023092307697,0.9079069276923077,36 +session_safe_boot,260_200,late_positive_after_emergency,200,1.0,1.0,0.0,0.0,0.0,10.88,0.10984000000000001,262.0627066666667,0.9786039076923074,0.9813019538461542,0.9079058615384616,36 +session_safe_boot,260_200,restart_after_reset_before_ack,200,1.0,1.0,0.0,0.0,0.0,10.88,0.107332,262.0601986666667,0.9786048723076921,0.9813024361538464,0.9079073084615384,32 +session_safe_boot,230_1000,normal_start,200,1.0,1.0,0.0,0.0,0.0,10.88,0.1072,262.06006666666667,0.978422956521739,0.9792114782608698,0.8606344347826089,41 +session_safe_boot,230_1000,ground_restart_moving,200,1.0,1.0,0.0,0.0,0.0,10.88,0.1072,262.06006666666667,0.978422956521739,0.9792114782608698,0.8606344347826089,41 +session_safe_boot,230_1000,rover_restart_moving,200,1.0,1.0,0.0,0.0,0.0,10.88,0.1072,262.06006666666667,0.978422956521739,0.9792114782608698,0.8606344347826089,41 +session_safe_boot,230_1000,both_restart,200,1.0,1.0,0.0,0.0,0.0,10.88,0.11353599999999998,262.0664026666667,0.9784202017391302,0.9792101008695654,0.860630302608696,46 +session_safe_boot,230_1000,ground_restart_emergency,200,1.0,0.0,0.0,0.0,1.0,10.88,0.054,262.00686666666667,0.9784460869565217,0.9792230434782607,0.8606691304347825,41 +session_safe_boot,230_1000,rover_restart_latched,200,1.0,0.0,0.0,0.0,0.0,10.88,0.054,262.00686666666667,0.9784460869565217,0.9792230434782607,0.8606691304347825,41 +session_safe_boot,230_1000,long_link_break,200,1.0,1.0,0.0,0.0,0.0,10.88,0.129374,262.0822406666667,0.9784133156521737,0.9792066578260871,0.860619973478261,46 +session_safe_boot,230_1000,old_ground_session_control,200,1.0,1.0,0.0,0.0,0.0,10.88,0.1072,262.06006666666667,0.978422956521739,0.9792114782608698,0.8606344347826089,41 +session_safe_boot,230_1000,old_rover_boot_control,200,1.0,1.0,0.0,0.0,0.0,10.88,0.1072,262.06006666666667,0.978422956521739,0.9792114782608698,0.8606344347826089,41 +session_safe_boot,230_1000,old_control_epoch,200,1.0,1.0,0.0,0.0,0.0,10.88,0.1072,262.06006666666667,0.978422956521739,0.9792114782608698,0.8606344347826089,41 +session_safe_boot,230_1000,sequence_reset_new_session,200,1.0,1.0,0.0,0.0,0.0,10.88,0.108652,262.0615186666667,0.978422325217391,0.9792111626086958,0.8606334878260873,46 +session_safe_boot,230_1000,sequence_wrap,200,1.0,1.0,0.0,0.0,0.0,10.88,0.1072,262.06006666666667,0.978422956521739,0.9792114782608698,0.8606344347826089,41 +session_safe_boot,230_1000,duplicate_hello,200,1.0,1.0,0.0,0.0,0.0,10.88,0.16119999999999998,262.1140666666667,0.9783994782608693,0.9791997391304347,0.8605992173913043,41 +session_safe_boot,230_1000,lost_session_status,200,1.0,1.0,0.0,0.0,0.0,10.88,0.16119999999999998,262.1140666666667,0.9783994782608693,0.9791997391304347,0.8605992173913043,42 +session_safe_boot,230_1000,lost_authorize_ack,200,1.0,1.0,0.0,0.0,0.0,10.88,0.16040000000000001,262.1132666666667,0.9783998260869565,0.9791999130434783,0.8605997391304347,42 +session_safe_boot,230_1000,lost_emergency_ack,200,1.0,1.0,0.0,0.0,0.0,10.88,0.23378800000000002,262.1866546666667,0.9783679182608697,0.979183959130435,0.8605518773913041,46 +session_safe_boot,230_1000,lost_reset_ack,200,1.0,1.0,0.0,0.0,0.0,10.88,0.247052,262.1999186666667,0.9783621513043473,0.9791810756521738,0.8605432269565216,46 +session_safe_boot,230_1000,old_reset_request,200,1.0,1.0,0.0,0.0,0.0,10.88,0.1072,262.06006666666667,0.978422956521739,0.9792114782608698,0.8606344347826089,41 +session_safe_boot,230_1000,late_positive_after_emergency,200,1.0,1.0,0.0,0.0,0.0,10.88,0.1072,262.06006666666667,0.978422956521739,0.9792114782608698,0.8606344347826089,41 +session_safe_boot,230_1000,restart_after_reset_before_ack,200,1.0,1.0,0.0,0.0,0.0,10.88,0.1072,262.06006666666667,0.978422956521739,0.9792114782608698,0.8606344347826089,41 +persistent_emergency,no_loss,normal_start,1,1.0,1.0,0.0,0.0,0.0,10.88,0.1072,262.06006666666667,0.9987909333333334,0.9993954666666667,0.9981864,21 +persistent_emergency,no_loss,ground_restart_moving,1,1.0,1.0,0.0,0.0,0.0,10.88,0.1072,262.06006666666667,0.9987909333333334,0.9993954666666667,0.9981864,21 +persistent_emergency,no_loss,rover_restart_moving,1,1.0,1.0,0.0,0.0,0.0,10.88,0.1072,262.06006666666667,0.9987909333333334,0.9993954666666667,0.9981864,21 +persistent_emergency,no_loss,both_restart,1,1.0,1.0,0.0,0.0,0.0,10.88,0.1072,262.06006666666667,0.9987909333333334,0.9993954666666667,0.9981864,21 +persistent_emergency,no_loss,ground_restart_emergency,1,1.0,0.0,0.0,0.0,0.0,10.88,0.054,262.00686666666667,0.9988086666666667,0.9994043333333333,0.998213,21 +persistent_emergency,no_loss,rover_restart_latched,1,1.0,0.0,0.0,0.0,0.0,10.88,0.054,262.00686666666667,0.9988086666666667,0.9994043333333333,0.998213,21 +persistent_emergency,no_loss,long_link_break,1,1.0,1.0,0.0,0.0,0.0,10.88,0.1072,262.06006666666667,0.9987909333333334,0.9993954666666667,0.9981864,21 +persistent_emergency,no_loss,old_ground_session_control,1,1.0,1.0,0.0,0.0,0.0,10.88,0.1072,262.06006666666667,0.9987909333333334,0.9993954666666667,0.9981864,21 +persistent_emergency,no_loss,old_rover_boot_control,1,1.0,1.0,0.0,0.0,0.0,10.88,0.1072,262.06006666666667,0.9987909333333334,0.9993954666666667,0.9981864,21 +persistent_emergency,no_loss,old_control_epoch,1,1.0,1.0,0.0,0.0,0.0,10.88,0.1072,262.06006666666667,0.9987909333333334,0.9993954666666667,0.9981864,21 +persistent_emergency,no_loss,sequence_reset_new_session,1,1.0,1.0,0.0,0.0,0.0,10.88,0.1072,262.06006666666667,0.9987909333333334,0.9993954666666667,0.9981864,21 +persistent_emergency,no_loss,sequence_wrap,1,1.0,1.0,0.0,0.0,0.0,10.88,0.1072,262.06006666666667,0.9987909333333334,0.9993954666666667,0.9981864,21 +persistent_emergency,no_loss,duplicate_hello,1,1.0,1.0,0.0,0.0,0.0,10.88,0.16119999999999998,262.1140666666667,0.9987729333333333,0.9993864666666666,0.9981594,21 +persistent_emergency,no_loss,lost_session_status,1,1.0,1.0,0.0,0.0,0.0,10.88,0.16119999999999998,262.1140666666667,0.9987729333333333,0.9993864666666666,0.9981594,22 +persistent_emergency,no_loss,lost_authorize_ack,1,1.0,1.0,0.0,0.0,0.0,10.88,0.16040000000000001,262.1132666666667,0.9987732,0.9993866,0.9981598,22 +persistent_emergency,no_loss,lost_emergency_ack,1,1.0,1.0,0.0,0.0,0.0,10.88,0.21280000000000002,262.1656666666667,0.9987557333333333,0.9993778666666666,0.9981336,22 +persistent_emergency,no_loss,lost_reset_ack,1,1.0,1.0,0.0,0.0,0.0,10.88,0.2312,262.1840666666667,0.9987496,0.9993748,0.9981244,22 +persistent_emergency,no_loss,old_reset_request,1,1.0,1.0,0.0,0.0,0.0,10.88,0.1072,262.06006666666667,0.9987909333333334,0.9993954666666667,0.9981864,21 +persistent_emergency,no_loss,late_positive_after_emergency,1,1.0,1.0,0.0,0.0,0.0,10.88,0.1072,262.06006666666667,0.9987909333333334,0.9993954666666667,0.9981864,21 +persistent_emergency,no_loss,restart_after_reset_before_ack,1,1.0,1.0,0.0,0.0,0.0,10.88,0.1072,262.06006666666667,0.9987909333333334,0.9993954666666667,0.9981864,21 +persistent_emergency,260_200,normal_start,200,1.0,1.0,0.0,0.0,0.0,10.88,0.107332,262.0601986666667,0.9786048723076921,0.9813024361538464,0.9079073084615384,32 +persistent_emergency,260_200,ground_restart_moving,200,1.0,1.0,0.0,0.0,0.0,10.88,0.108256,262.0611226666667,0.9786045169230766,0.9813022584615387,0.9079067753846155,35 +persistent_emergency,260_200,rover_restart_moving,200,1.0,1.0,0.0,0.0,0.0,10.88,0.10891600000000001,262.0617826666667,0.9786042630769228,0.9813021315384617,0.9079063946153846,36 +persistent_emergency,260_200,both_restart,200,1.0,1.0,0.0,0.0,0.0,10.88,0.10772799999999999,262.0605946666667,0.9786047199999998,0.9813023600000003,0.9079070800000001,33 +persistent_emergency,260_200,ground_restart_emergency,200,1.0,0.0,0.0,0.0,0.0,10.88,0.054,262.00686666666667,0.9786253846153845,0.9813126923076924,0.9079380769230773,31 +persistent_emergency,260_200,rover_restart_latched,200,1.0,0.0,0.0,0.0,0.0,10.88,0.054,262.00686666666667,0.9786253846153845,0.9813126923076924,0.9079380769230773,31 +persistent_emergency,260_200,long_link_break,200,1.0,1.0,0.0,0.0,0.0,10.88,0.111994,262.0648606666667,0.9786030792307691,0.981301539615385,0.9079046188461538,36 +persistent_emergency,260_200,old_ground_session_control,200,1.0,1.0,0.0,0.0,0.0,10.88,0.107596,262.0604626666667,0.9786047707692305,0.9813023853846157,0.9079071561538461,33 +persistent_emergency,260_200,old_rover_boot_control,200,1.0,1.0,0.0,0.0,0.0,10.88,0.10785999999999998,262.0607266666667,0.9786046692307689,0.981302334615385,0.9079070038461539,34 +persistent_emergency,260_200,old_control_epoch,200,1.0,1.0,0.0,0.0,0.0,10.88,0.108124,262.06099066666667,0.9786045676923075,0.981302283846154,0.9079068515384615,36 +persistent_emergency,260_200,sequence_reset_new_session,200,1.0,1.0,0.0,0.0,0.0,10.88,0.11090000000000001,262.0637666666667,0.9786034999999998,0.9813017500000004,0.90790525,36 +persistent_emergency,260_200,sequence_wrap,200,1.0,1.0,0.0,0.0,0.0,10.88,0.10852,262.0613866666667,0.9786044153846152,0.981302207692308,0.9079066230769232,36 +persistent_emergency,260_200,duplicate_hello,200,1.0,1.0,0.0,0.0,0.0,10.88,0.16119999999999998,262.1140666666667,0.9785841538461537,0.9812920769230772,0.907876230769231,31 +persistent_emergency,260_200,lost_session_status,200,1.0,1.0,0.0,0.0,0.0,10.88,0.16146800000000003,262.1143346666667,0.9785840507692305,0.9812920253846156,0.9078760761538465,34 +persistent_emergency,260_200,lost_authorize_ack,200,1.0,1.0,0.0,0.0,0.0,10.88,0.165944,262.1188106666667,0.9785823292307694,0.9812911646153849,0.9078734938461537,36 +persistent_emergency,260_200,lost_emergency_ack,200,1.0,1.0,0.0,0.0,0.0,10.88,0.21926799999999996,262.1721346666667,0.9785618199999999,0.9812809099999998,0.9078427300000002,36 +persistent_emergency,260_200,lost_reset_ack,200,1.0,1.0,0.0,0.0,0.0,10.88,0.236628,262.1894946666667,0.9785551430769229,0.9812775715384617,0.9078327146153846,36 +persistent_emergency,260_200,old_reset_request,200,1.0,1.0,0.0,0.0,0.0,10.88,0.108652,262.0615186666667,0.9786043646153842,0.9813021823076926,0.9079065469230769,36 +persistent_emergency,260_200,late_positive_after_emergency,200,1.0,1.0,0.0,0.0,0.0,10.88,0.10878399999999999,262.0616506666667,0.9786043138461537,0.9813021569230773,0.9079064707692308,36 +persistent_emergency,260_200,restart_after_reset_before_ack,200,1.0,1.0,0.0,0.0,0.0,10.88,0.10746400000000002,262.0603306666667,0.9786048215384614,0.9813024107692311,0.9079072323076923,33 +persistent_emergency,230_1000,normal_start,200,1.0,1.0,0.0,0.0,0.0,10.88,0.1072,262.06006666666667,0.978422956521739,0.9792114782608698,0.8606344347826089,41 +persistent_emergency,230_1000,ground_restart_moving,200,1.0,1.0,0.0,0.0,0.0,10.88,0.110632,262.0634986666667,0.978421464347826,0.9792107321739132,0.8606321965217394,46 +persistent_emergency,230_1000,rover_restart_moving,200,1.0,1.0,0.0,0.0,0.0,10.88,0.11168800000000002,262.0645546666667,0.9784210052173912,0.9792105026086958,0.8606315078260871,46 +persistent_emergency,230_1000,both_restart,200,1.0,1.0,0.0,0.0,0.0,10.88,0.10931199999999998,262.0621786666667,0.9784220382608695,0.979211019130435,0.8606330573913047,46 +persistent_emergency,230_1000,ground_restart_emergency,200,1.0,0.0,0.0,0.0,0.0,10.88,0.054,262.00686666666667,0.9784460869565217,0.9792230434782607,0.8606691304347825,41 +persistent_emergency,230_1000,rover_restart_latched,200,1.0,0.0,0.0,0.0,0.0,10.88,0.054,262.00686666666667,0.9784460869565217,0.9792230434782607,0.8606691304347825,41 +persistent_emergency,230_1000,long_link_break,200,1.0,1.0,0.0,0.0,0.0,10.88,0.116982,262.0698486666667,0.9784187034782608,0.9792093517391307,0.8606280552173916,46 +persistent_emergency,230_1000,old_ground_session_control,200,1.0,1.0,0.0,0.0,0.0,10.88,0.1072,262.06006666666667,0.978422956521739,0.9792114782608698,0.8606344347826089,41 +persistent_emergency,230_1000,old_rover_boot_control,200,1.0,1.0,0.0,0.0,0.0,10.88,0.1072,262.06006666666667,0.978422956521739,0.9792114782608698,0.8606344347826089,41 +persistent_emergency,230_1000,old_control_epoch,200,1.0,1.0,0.0,0.0,0.0,10.88,0.11261199999999999,262.0654786666667,0.9784206034782608,0.9792103017391307,0.8606309052173916,46 +persistent_emergency,230_1000,sequence_reset_new_session,200,1.0,1.0,0.0,0.0,0.0,10.88,0.10840599999999999,262.0612726666667,0.9784224321739129,0.9792112160869567,0.8606336482608699,46 +persistent_emergency,230_1000,sequence_wrap,200,1.0,1.0,0.0,0.0,0.0,10.88,0.11076400000000002,262.0636306666667,0.9784214069565215,0.979210703478261,0.8606321104347829,46 +persistent_emergency,230_1000,duplicate_hello,200,1.0,1.0,0.0,0.0,0.0,10.88,0.16119999999999998,262.1140666666667,0.9783994782608693,0.9791997391304347,0.8605992173913043,41 +persistent_emergency,230_1000,lost_session_status,200,1.0,1.0,0.0,0.0,0.0,10.88,0.16119999999999998,262.1140666666667,0.9783994782608693,0.9791997391304347,0.8605992173913043,42 +persistent_emergency,230_1000,lost_authorize_ack,200,1.0,1.0,0.0,0.0,0.0,10.88,0.16040000000000001,262.1132666666667,0.9783998260869565,0.9791999130434783,0.8605997391304347,42 +persistent_emergency,230_1000,lost_emergency_ack,200,1.0,1.0,0.0,0.0,0.0,10.88,0.219664,262.1725306666667,0.9783740591304348,0.9791870295652177,0.860561088695652,46 +persistent_emergency,230_1000,lost_reset_ack,200,1.0,1.0,0.0,0.0,0.0,10.88,0.25146599999999997,262.2043326666667,0.9783602321739128,0.9791801160869563,0.8605403482608694,46 +persistent_emergency,230_1000,old_reset_request,200,1.0,1.0,0.0,0.0,0.0,10.88,0.1072,262.06006666666667,0.978422956521739,0.9792114782608698,0.8606344347826089,41 +persistent_emergency,230_1000,late_positive_after_emergency,200,1.0,1.0,0.0,0.0,0.0,10.88,0.1072,262.06006666666667,0.978422956521739,0.9792114782608698,0.8606344347826089,41 +persistent_emergency,230_1000,restart_after_reset_before_ack,200,1.0,1.0,0.0,0.0,0.0,10.88,0.1072,262.06006666666667,0.978422956521739,0.9792114782608698,0.8606344347826089,41 diff --git a/data/processed/lab041/lab041_traffic_impact.png b/data/processed/lab041/lab041_traffic_impact.png new file mode 100644 index 0000000..26dc809 Binary files /dev/null and b/data/processed/lab041/lab041_traffic_impact.png differ diff --git a/protocol/control_messages.py b/protocol/control_messages.py new file mode 100644 index 0000000..d63ad9a --- /dev/null +++ b/protocol/control_messages.py @@ -0,0 +1,434 @@ +"""Прикладные сообщения безопасного сеанса Lab041. + +Общий заголовок полезной нагрузки имеет формат ``!BBQQII``: версия, тип +сообщения, 64-битные идентификаторы запуска наземной станции и ровера, +32-битный период управления и 32-битный номер сообщения. Порядок байтов +сетевой, неявного выравнивания нет. + +Отдельная контрольная сумма намеренно не добавляется: контрольная сумма +общего пакета Lab033 уже защищает заголовок и всю прикладную нагрузку. После +проверки этой суммы всё равно требуется приведённая здесь смысловая проверка. +""" + +from __future__ import annotations + +from dataclasses import dataclass +from enum import IntEnum +import math +import struct +from typing import Union + + +MESSAGE_VERSION = 1 +COMMON_FORMAT = "!BBQQII" +COMMON_SIZE = struct.calcsize(COMMON_FORMAT) +UINT32_MODULUS = 1 << 32 +UINT32_HALF_RANGE = 1 << 31 +MAX_CONTROL_SPEED_MPS = 15.0 +MAX_ABS_TURN = 1.0 + + +class ControlMessageError(ValueError): + """Ошибка формата или смысловой проверки прикладного сообщения.""" + + +class MessageType(IntEnum): + SESSION_HELLO = 1 + SESSION_STATUS = 2 + MOVEMENT_AUTHORIZE_REQUEST = 3 + MOVEMENT_AUTHORIZE_ACK = 4 + CONTROL_STATE = 5 + EMERGENCY_STOP = 6 + EMERGENCY_ACK = 7 + RESET_REQUEST = 8 + RESET_ACK = 9 + SESSION_REJECT = 10 + + +class RoverSafetyCode(IntEnum): + ROVER_BOOT_SAFE = 1 + ROVER_SESSION_SYNCED_SAFE = 2 + ROVER_MOVEMENT_AUTHORIZED = 3 + STAGE1_DECELERATION = 4 + STAGE2_BRAKING = 5 + EMERGENCY_LATCHED = 6 + + +class SessionRejectReason(IntEnum): + ACCEPTED = 0 + GROUND_SESSION_ID = 1 + ROVER_BOOT_ID = 2 + CONTROL_EPOCH = 3 + SEQUENCE_NUMBER = 4 + EMERGENCY_EVENT_ID = 5 + RESET_REQUEST_ID = 6 + NOT_SYNCHRONIZED = 7 + MOVEMENT_NOT_AUTHORIZED = 8 + + +class SequenceComparison(IntEnum): + NOT_NEWER = 0 + NEWER = 1 + AMBIGUOUS = 2 + + +@dataclass(frozen=True) +class MessageContext: + ground_session_id: int + rover_boot_id: int + control_epoch: int + sequence_number: int + + +@dataclass(frozen=True) +class SessionHello: + context: MessageContext + emergency_intent: bool + emergency_event_id: int + + +@dataclass(frozen=True) +class SessionStatus: + context: MessageContext + safety_state: RoverSafetyCode + emergency_latched: bool + emergency_event_id: int + + +@dataclass(frozen=True) +class MovementAuthorizeRequest: + context: MessageContext + authorization_id: int + + +@dataclass(frozen=True) +class MovementAuthorizeAck: + context: MessageContext + authorization_id: int + accepted: bool + + +@dataclass(frozen=True) +class ControlStateMessage: + context: MessageContext + desired_speed_mps: float + desired_turn: float + braking: bool + movement_permitted: bool + + +@dataclass(frozen=True) +class EmergencyStop: + context: MessageContext + emergency_event_id: int + + +@dataclass(frozen=True) +class EmergencyAck: + context: MessageContext + emergency_event_id: int + + +@dataclass(frozen=True) +class ResetRequest: + context: MessageContext + emergency_event_id: int + reset_request_id: int + requested_speed_mps: float + movement_permitted: bool + + +@dataclass(frozen=True) +class ResetAck: + context: MessageContext + emergency_event_id: int + reset_request_id: int + accepted: bool + reason: SessionRejectReason + + +@dataclass(frozen=True) +class SessionReject: + context: MessageContext + rejected_type: MessageType + reason: SessionRejectReason + + +ControlMessage = Union[ + SessionHello, + SessionStatus, + MovementAuthorizeRequest, + MovementAuthorizeAck, + ControlStateMessage, + EmergencyStop, + EmergencyAck, + ResetRequest, + ResetAck, + SessionReject, +] + + +_TYPE_BY_CLASS = { + SessionHello: MessageType.SESSION_HELLO, + SessionStatus: MessageType.SESSION_STATUS, + MovementAuthorizeRequest: MessageType.MOVEMENT_AUTHORIZE_REQUEST, + MovementAuthorizeAck: MessageType.MOVEMENT_AUTHORIZE_ACK, + ControlStateMessage: MessageType.CONTROL_STATE, + EmergencyStop: MessageType.EMERGENCY_STOP, + EmergencyAck: MessageType.EMERGENCY_ACK, + ResetRequest: MessageType.RESET_REQUEST, + ResetAck: MessageType.RESET_ACK, + SessionReject: MessageType.SESSION_REJECT, +} + + +def _unsigned(value: int, maximum: int, name: str) -> int: + if not isinstance(value, int) or isinstance(value, bool) or not 0 <= value <= maximum: + raise ControlMessageError(f"{name} выходит за допустимый беззнаковый диапазон") + return value + + +def validate_context(context: MessageContext) -> MessageContext: + if not isinstance(context, MessageContext): + raise TypeError("требуется MessageContext") + _unsigned(context.ground_session_id, 0xFFFFFFFFFFFFFFFF, "ground_session_id") + _unsigned(context.rover_boot_id, 0xFFFFFFFFFFFFFFFF, "rover_boot_id") + _unsigned(context.control_epoch, 0xFFFFFFFF, "control_epoch") + _unsigned(context.sequence_number, 0xFFFFFFFF, "sequence_number") + return context + + +def compare_sequence(new: int, old: int) -> SequenceComparison: + """Сравнить 32-битные номера по модулю с неоднозначной серединой.""" + + _unsigned(new, 0xFFFFFFFF, "new sequence_number") + _unsigned(old, 0xFFFFFFFF, "old sequence_number") + delta = (new - old) % UINT32_MODULUS + if delta == UINT32_HALF_RANGE: + return SequenceComparison.AMBIGUOUS + if 0 < delta < UINT32_HALF_RANGE: + return SequenceComparison.NEWER + return SequenceComparison.NOT_NEWER + + +def _common(message_type: MessageType, context: MessageContext) -> bytes: + validate_context(context) + return struct.pack( + COMMON_FORMAT, + MESSAGE_VERSION, + int(message_type), + context.ground_session_id, + context.rover_boot_id, + context.control_epoch, + context.sequence_number, + ) + + +def _boolean(value: bool, name: str) -> int: + if not isinstance(value, bool): + raise ControlMessageError(f"{name} должен быть логическим значением") + return int(value) + + +def _finite(value: float, name: str) -> float: + value = float(value) + if not math.isfinite(value): + raise ControlMessageError(f"{name} должен быть конечным числом") + return value + + +def encode_message(message: ControlMessage) -> bytes: + """Проверить и сериализовать одно прикладное сообщение.""" + + message_type = _TYPE_BY_CLASS.get(type(message)) + if message_type is None: + raise TypeError("неподдерживаемый класс прикладного сообщения") + prefix = _common(message_type, message.context) + if isinstance(message, SessionHello): + event = _unsigned(message.emergency_event_id, 0xFFFFFFFFFFFFFFFF, "emergency_event_id") + return prefix + struct.pack("!BQ", _boolean(message.emergency_intent, "emergency_intent"), event) + if isinstance(message, SessionStatus): + try: + state = RoverSafetyCode(message.safety_state) + except ValueError as error: + raise ControlMessageError("неизвестное состояние безопасности ровера") from error + event = _unsigned(message.emergency_event_id, 0xFFFFFFFFFFFFFFFF, "emergency_event_id") + return prefix + struct.pack("!BBQ", int(state), _boolean(message.emergency_latched, "emergency_latched"), event) + if isinstance(message, MovementAuthorizeRequest): + return prefix + struct.pack("!Q", _unsigned(message.authorization_id, 0xFFFFFFFFFFFFFFFF, "authorization_id")) + if isinstance(message, MovementAuthorizeAck): + return prefix + struct.pack( + "!QB", + _unsigned(message.authorization_id, 0xFFFFFFFFFFFFFFFF, "authorization_id"), + _boolean(message.accepted, "accepted"), + ) + if isinstance(message, ControlStateMessage): + speed = _finite(message.desired_speed_mps, "desired_speed_mps") + turn = _finite(message.desired_turn, "desired_turn") + if not 0.0 <= speed <= MAX_CONTROL_SPEED_MPS: + raise ControlMessageError("требуемая скорость вне диапазона 0…15 м/с") + if not -MAX_ABS_TURN <= turn <= MAX_ABS_TURN: + raise ControlMessageError("требуемый поворот вне диапазона -1…1") + braking = _boolean(message.braking, "braking") + permitted = _boolean(message.movement_permitted, "movement_permitted") + if (braking or not permitted) and speed != 0.0: + raise ControlMessageError("при торможении или запрете движения скорость должна быть нулевой") + if braking and permitted: + raise ControlMessageError("торможение несовместимо с разрешением движения") + return prefix + struct.pack("!ffBB", speed, turn, braking, permitted) + if isinstance(message, (EmergencyStop, EmergencyAck)): + event = _unsigned(message.emergency_event_id, 0xFFFFFFFFFFFFFFFF, "emergency_event_id") + return prefix + struct.pack("!Q", event) + if isinstance(message, ResetRequest): + event = _unsigned(message.emergency_event_id, 0xFFFFFFFFFFFFFFFF, "emergency_event_id") + request = _unsigned(message.reset_request_id, 0xFFFFFFFFFFFFFFFF, "reset_request_id") + speed = _finite(message.requested_speed_mps, "requested_speed_mps") + permitted = _boolean(message.movement_permitted, "movement_permitted") + if speed != 0.0 or permitted: + raise ControlMessageError("безопасный сброс требует нулевой скорости и запрета движения") + return prefix + struct.pack("!QQfB", event, request, speed, permitted) + if isinstance(message, ResetAck): + try: + reason = SessionRejectReason(message.reason) + except ValueError as error: + raise ControlMessageError("неизвестная причина подтверждения сброса") from error + return prefix + struct.pack( + "!QQBB", + _unsigned(message.emergency_event_id, 0xFFFFFFFFFFFFFFFF, "emergency_event_id"), + _unsigned(message.reset_request_id, 0xFFFFFFFFFFFFFFFF, "reset_request_id"), + _boolean(message.accepted, "accepted"), + int(reason), + ) + if isinstance(message, SessionReject): + try: + rejected_type = MessageType(message.rejected_type) + reason = SessionRejectReason(message.reason) + except ValueError as error: + raise ControlMessageError("неизвестный код отказа сеанса") from error + return prefix + struct.pack("!BB", int(rejected_type), int(reason)) + raise AssertionError("необработанный тип сообщения") + + +def _decode_bool(value: int, name: str) -> bool: + if value not in (0, 1): + raise ControlMessageError(f"{name} должен быть равен нулю или единице") + return bool(value) + + +def _unpack_exact(body: bytes, format_string: str) -> tuple[object, ...]: + expected = struct.calcsize(format_string) + if len(body) != expected: + raise ControlMessageError(f"неверная длина тела сообщения: {len(body)}, ожидается {expected}") + return struct.unpack(format_string, body) + + +def decode_message(payload: bytes) -> ControlMessage: + """Разобрать сообщение и выполнить полную смысловую проверку.""" + + if not isinstance(payload, (bytes, bytearray)): + raise TypeError("полезная нагрузка должна быть последовательностью байтов") + payload = bytes(payload) + if len(payload) < COMMON_SIZE: + raise ControlMessageError("сообщение короче общего заголовка") + version, raw_type, ground, rover, epoch, sequence = struct.unpack(COMMON_FORMAT, payload[:COMMON_SIZE]) + if version != MESSAGE_VERSION: + raise ControlMessageError("неподдерживаемая версия прикладного сообщения") + try: + message_type = MessageType(raw_type) + except ValueError as error: + raise ControlMessageError("неизвестный тип прикладного сообщения") from error + context = MessageContext(ground, rover, epoch, sequence) + body = payload[COMMON_SIZE:] + if message_type is MessageType.SESSION_HELLO: + intent, event = _unpack_exact(body, "!BQ") + message: ControlMessage = SessionHello(context, _decode_bool(intent, "emergency_intent"), event) + elif message_type is MessageType.SESSION_STATUS: + state, latched, event = _unpack_exact(body, "!BBQ") + try: + safety_state = RoverSafetyCode(state) + except ValueError as error: + raise ControlMessageError("неизвестное состояние безопасности ровера") from error + message = SessionStatus(context, safety_state, _decode_bool(latched, "emergency_latched"), event) + elif message_type is MessageType.MOVEMENT_AUTHORIZE_REQUEST: + (authorization,) = _unpack_exact(body, "!Q") + message = MovementAuthorizeRequest(context, authorization) + elif message_type is MessageType.MOVEMENT_AUTHORIZE_ACK: + authorization, accepted = _unpack_exact(body, "!QB") + message = MovementAuthorizeAck(context, authorization, _decode_bool(accepted, "accepted")) + elif message_type is MessageType.CONTROL_STATE: + speed, turn, braking, permitted = _unpack_exact(body, "!ffBB") + message = ControlStateMessage( + context, + speed, + turn, + _decode_bool(braking, "braking"), + _decode_bool(permitted, "movement_permitted"), + ) + elif message_type is MessageType.EMERGENCY_STOP: + (event,) = _unpack_exact(body, "!Q") + message = EmergencyStop(context, event) + elif message_type is MessageType.EMERGENCY_ACK: + (event,) = _unpack_exact(body, "!Q") + message = EmergencyAck(context, event) + elif message_type is MessageType.RESET_REQUEST: + event, request, speed, permitted = _unpack_exact(body, "!QQfB") + message = ResetRequest(context, event, request, speed, _decode_bool(permitted, "movement_permitted")) + elif message_type is MessageType.RESET_ACK: + event, request, accepted, reason = _unpack_exact(body, "!QQBB") + try: + reset_reason = SessionRejectReason(reason) + except ValueError as error: + raise ControlMessageError("неизвестная причина подтверждения сброса") from error + message = ResetAck(context, event, request, _decode_bool(accepted, "accepted"), reset_reason) + else: + rejected_type, reason = _unpack_exact(body, "!BB") + try: + message = SessionReject(context, MessageType(rejected_type), SessionRejectReason(reason)) + except ValueError as error: + raise ControlMessageError("неизвестный код отказа сеанса") from error + return decode_validated_message(message) + + +def decode_validated_message(message: ControlMessage) -> ControlMessage: + """Повторно применить смысловую проверку к разобранному объекту.""" + + return decode_without_recursion(encode_message(message)) + + +def decode_without_recursion(payload: bytes) -> ControlMessage: + """Внутренний разбор уже проверенного представления.""" + + version, raw_type, ground, rover, epoch, sequence = struct.unpack(COMMON_FORMAT, payload[:COMMON_SIZE]) + assert version == MESSAGE_VERSION + message_type = MessageType(raw_type) + context = MessageContext(ground, rover, epoch, sequence) + body = payload[COMMON_SIZE:] + if message_type is MessageType.SESSION_HELLO: + intent, event = struct.unpack("!BQ", body) + return SessionHello(context, bool(intent), event) + if message_type is MessageType.SESSION_STATUS: + state, latched, event = struct.unpack("!BBQ", body) + return SessionStatus(context, RoverSafetyCode(state), bool(latched), event) + if message_type is MessageType.MOVEMENT_AUTHORIZE_REQUEST: + return MovementAuthorizeRequest(context, struct.unpack("!Q", body)[0]) + if message_type is MessageType.MOVEMENT_AUTHORIZE_ACK: + authorization, accepted = struct.unpack("!QB", body) + return MovementAuthorizeAck(context, authorization, bool(accepted)) + if message_type is MessageType.CONTROL_STATE: + speed, turn, braking, permitted = struct.unpack("!ffBB", body) + return ControlStateMessage(context, speed, turn, bool(braking), bool(permitted)) + if message_type is MessageType.EMERGENCY_STOP: + return EmergencyStop(context, struct.unpack("!Q", body)[0]) + if message_type is MessageType.EMERGENCY_ACK: + return EmergencyAck(context, struct.unpack("!Q", body)[0]) + if message_type is MessageType.RESET_REQUEST: + event, request, speed, permitted = struct.unpack("!QQfB", body) + return ResetRequest(context, event, request, speed, bool(permitted)) + if message_type is MessageType.RESET_ACK: + event, request, accepted, reason = struct.unpack("!QQBB", body) + return ResetAck(context, event, request, bool(accepted), SessionRejectReason(reason)) + rejected_type, reason = struct.unpack("!BB", body) + return SessionReject(context, MessageType(rejected_type), SessionRejectReason(reason)) + + +assert COMMON_SIZE == 26 diff --git a/protocol/session_state.py b/protocol/session_state.py new file mode 100644 index 0000000..c9b76b4 --- /dev/null +++ b/protocol/session_state.py @@ -0,0 +1,422 @@ +"""Автоматы безопасного сеанса наземной станции и ровера для Lab041.""" + +from __future__ import annotations + +from dataclasses import dataclass +from enum import Enum +import hashlib + +from protocol.control_messages import ( + ControlStateMessage, + EmergencyAck, + EmergencyStop, + MessageContext, + MessageType, + MovementAuthorizeAck, + MovementAuthorizeRequest, + ResetAck, + ResetRequest, + RoverSafetyCode, + SequenceComparison, + SessionHello, + SessionRejectReason, + SessionStatus, + compare_sequence, +) + + +class GroundSessionState(str, Enum): + GROUND_BOOT = "ground_boot" + GROUND_SYNCING = "ground_syncing" + GROUND_SAFE_SYNCHRONIZED = "ground_safe_synchronized" + GROUND_MOVEMENT_AUTH_REQUESTED = "ground_movement_auth_requested" + GROUND_ACTIVE = "ground_active" + GROUND_EMERGENCY_REQUESTED = "ground_emergency_requested" + GROUND_EMERGENCY_CONFIRMED = "ground_emergency_confirmed" + GROUND_RESET_REQUESTED = "ground_reset_requested" + + +class RoverSessionState(str, Enum): + ROVER_BOOT_SAFE = "rover_boot_safe" + ROVER_SESSION_SYNCED_SAFE = "rover_session_synced_safe" + ROVER_MOVEMENT_AUTHORIZED = "rover_movement_authorized" + STAGE1_DECELERATION = "stage1_deceleration" + STAGE2_BRAKING = "stage2_braking" + EMERGENCY_LATCHED = "emergency_latched" + + +class RejectionCause(str, Enum): + GROUND_SESSION_ID = "ground_session_id" + ROVER_BOOT_ID = "rover_boot_id" + CONTROL_EPOCH = "control_epoch" + SEQUENCE_NUMBER = "sequence_number" + EMERGENCY_EVENT_ID = "emergency_event_id" + RESET_REQUEST_ID = "reset_request_id" + NOT_SYNCHRONIZED = "not_synchronized" + MOVEMENT_NOT_AUTHORIZED = "movement_not_authorized" + + +@dataclass(frozen=True) +class ControlDecision: + accepted: bool + reason: RejectionCause | None + ambiguous_sequence: bool = False + + +@dataclass(frozen=True) +class ResetDecision: + acknowledgement: ResetAck + performed: bool + duplicate: bool + + +def deterministic_identifier(seed: int, purpose: str) -> int: + """Получить воспроизводимый ненулевой 64-битный идентификатор.""" + + if not isinstance(seed, int): + raise TypeError("начальное значение генератора должно быть целым") + digest = hashlib.blake2b(f"Lab041:{purpose}:{seed}".encode("utf-8"), digest_size=8).digest() + return int.from_bytes(digest, "big") or 1 + + +class GroundSessionController: + """Наземный автомат без автоматического восстановления движения.""" + + def __init__( + self, + seed: int, + *, + persisted_emergency_intent: bool = False, + persisted_emergency_event_id: int = 0, + ) -> None: + self.ground_session_id = deterministic_identifier(seed, "ground") + self.rover_boot_id = 0 + self.control_epoch = 0 + self.sequence_number = 0 + self.state = GroundSessionState.GROUND_BOOT + self.emergency_intent = bool(persisted_emergency_intent) + self.emergency_event_id = persisted_emergency_event_id if self.emergency_intent else 0 + self.authorization_id = 0 + self.reset_request_id = 0 + self.last_operator_sequence: int | None = None + self.movement_permitted = False + self.current_speed_mps = 0.0 + self.zero_commands_after_restart = 0 + + def _next_sequence(self) -> int: + value = self.sequence_number + self.sequence_number = (self.sequence_number + 1) & 0xFFFFFFFF + return value + + def _context(self, *, epoch: int | None = None) -> MessageContext: + return MessageContext( + self.ground_session_id, + self.rover_boot_id, + self.control_epoch if epoch is None else epoch, + self._next_sequence(), + ) + + def start_synchronization(self) -> SessionHello: + if self.state is not GroundSessionState.GROUND_BOOT: + raise RuntimeError("синхронизацию можно начать только после запуска") + self.state = GroundSessionState.GROUND_SYNCING + self.movement_permitted = False + self.current_speed_mps = 0.0 + return SessionHello(self._context(epoch=0), self.emergency_intent, self.emergency_event_id) + + def repeat_hello(self) -> SessionHello: + if self.state is not GroundSessionState.GROUND_SYNCING: + raise RuntimeError("повтор приветствия допустим только при синхронизации") + return SessionHello(self._context(epoch=0), self.emergency_intent, self.emergency_event_id) + + def receive_status(self, status: SessionStatus) -> bool: + if self.state is not GroundSessionState.GROUND_SYNCING: + return False + if status.context.ground_session_id != self.ground_session_id: + return False + if status.context.rover_boot_id == 0: + return False + self.rover_boot_id = status.context.rover_boot_id + self.control_epoch = 0 + self.movement_permitted = False + self.current_speed_mps = 0.0 + if self.emergency_intent: + self.state = GroundSessionState.GROUND_EMERGENCY_REQUESTED + else: + self.state = GroundSessionState.GROUND_SAFE_SYNCHRONIZED + return True + + def request_movement_authorization(self, authorization_id: int) -> MovementAuthorizeRequest: + if self.state is not GroundSessionState.GROUND_SAFE_SYNCHRONIZED: + raise RuntimeError("разрешение движения требует безопасного согласованного сеанса") + if self.emergency_intent: + raise RuntimeError("при аварийном намерении движение запрещено") + if not 0 <= authorization_id <= 0xFFFFFFFFFFFFFFFF: + raise ValueError("authorization_id вне диапазона uint64") + self.authorization_id = authorization_id + self.state = GroundSessionState.GROUND_MOVEMENT_AUTH_REQUESTED + return MovementAuthorizeRequest(self._context(epoch=0), authorization_id) + + def receive_movement_authorize_ack(self, acknowledgement: MovementAuthorizeAck) -> bool: + if self.state is not GroundSessionState.GROUND_MOVEMENT_AUTH_REQUESTED: + return False + context = acknowledgement.context + if ( + context.ground_session_id != self.ground_session_id + or context.rover_boot_id != self.rover_boot_id + or acknowledgement.authorization_id != self.authorization_id + or not acknowledgement.accepted + or context.control_epoch == 0 + ): + return False + self.control_epoch = context.control_epoch + self.state = GroundSessionState.GROUND_ACTIVE + self.movement_permitted = False + self.current_speed_mps = 0.0 + self.last_operator_sequence = None + return True + + def new_operator_control(self, speed_mps: float, turn: float = 0.0) -> ControlStateMessage: + if self.state is not GroundSessionState.GROUND_ACTIVE: + raise RuntimeError("новая команда движения возможна только в активном сеансе") + if speed_mps <= 0.0: + raise ValueError("скорость новой команды должна быть положительной") + context = self._context() + self.last_operator_sequence = context.sequence_number + self.movement_permitted = True + self.current_speed_mps = speed_mps + return ControlStateMessage(context, speed_mps, turn, False, True) + + def safe_zero_control(self) -> ControlStateMessage: + self.zero_commands_after_restart += 1 + return ControlStateMessage(self._context(), 0.0, 0.0, True, False) + + def request_emergency(self, emergency_event_id: int) -> EmergencyStop: + if not 0 < emergency_event_id <= 0xFFFFFFFFFFFFFFFF: + raise ValueError("emergency_event_id должен быть ненулевым uint64") + self.emergency_intent = True + self.emergency_event_id = emergency_event_id + self.movement_permitted = False + self.current_speed_mps = 0.0 + self.state = GroundSessionState.GROUND_EMERGENCY_REQUESTED + return EmergencyStop(self._context(), emergency_event_id) + + def receive_emergency_ack(self, acknowledgement: EmergencyAck) -> bool: + if acknowledgement.context.ground_session_id != self.ground_session_id: + return False + if acknowledgement.emergency_event_id != self.emergency_event_id: + return False + if self.state is GroundSessionState.GROUND_EMERGENCY_REQUESTED: + self.state = GroundSessionState.GROUND_EMERGENCY_CONFIRMED + return True + + def request_reset(self, reset_request_id: int) -> ResetRequest: + if not self.emergency_intent: + raise RuntimeError("сброс требует аварийного намерения") + if not 0 < reset_request_id <= 0xFFFFFFFFFFFFFFFF: + raise ValueError("reset_request_id должен быть ненулевым uint64") + self.reset_request_id = reset_request_id + self.state = GroundSessionState.GROUND_RESET_REQUESTED + return ResetRequest(self._context(), self.emergency_event_id, reset_request_id, 0.0, False) + + def receive_reset_ack(self, acknowledgement: ResetAck) -> bool: + if self.state is not GroundSessionState.GROUND_RESET_REQUESTED: + return False + if ( + acknowledgement.context.ground_session_id != self.ground_session_id + or acknowledgement.context.rover_boot_id != self.rover_boot_id + or acknowledgement.emergency_event_id != self.emergency_event_id + or acknowledgement.reset_request_id != self.reset_request_id + or not acknowledgement.accepted + ): + return False + self.emergency_intent = False + self.emergency_event_id = 0 + self.movement_permitted = False + self.current_speed_mps = 0.0 + self.control_epoch = 0 + self.state = GroundSessionState.GROUND_SAFE_SYNCHRONIZED + return True + + +class RoverSessionController: + """Ровер, который после каждого запуска начинает с безопасного запрета.""" + + def __init__(self, seed: int) -> None: + self.rover_boot_id = deterministic_identifier(seed, "rover") + self.ground_session_id = 0 + self.control_epoch = 0 + self.state = RoverSessionState.ROVER_BOOT_SAFE + self.speed_mps = 0.0 + self.movement_permitted = False + self.emergency_event_id = 0 + self.last_sequences: dict[tuple[int, int, int, int], int] = {} + self.accepted_reset_keys: set[tuple[int, int, int, int]] = set() + self.duplicate_hellos = 0 + self.duplicate_resets = 0 + + @property + def safe(self) -> bool: + return self.speed_mps == 0.0 and not self.movement_permitted + + def _status_context(self, sequence_number: int = 0) -> MessageContext: + return MessageContext(self.ground_session_id, self.rover_boot_id, self.control_epoch, sequence_number) + + def receive_hello(self, hello: SessionHello) -> SessionStatus: + if hello.context.ground_session_id == 0: + raise ValueError("ground_session_id должен быть ненулевым") + if hello.context.ground_session_id == self.ground_session_id: + self.duplicate_hellos += 1 + else: + self.ground_session_id = hello.context.ground_session_id + self.control_epoch = 0 + self.last_sequences.clear() + self.movement_permitted = False + self.speed_mps = 0.0 + self.state = RoverSessionState.ROVER_SESSION_SYNCED_SAFE + if hello.emergency_intent: + self.emergency_event_id = hello.emergency_event_id + self.state = RoverSessionState.EMERGENCY_LATCHED + code = { + RoverSessionState.ROVER_BOOT_SAFE: RoverSafetyCode.ROVER_BOOT_SAFE, + RoverSessionState.ROVER_SESSION_SYNCED_SAFE: RoverSafetyCode.ROVER_SESSION_SYNCED_SAFE, + RoverSessionState.ROVER_MOVEMENT_AUTHORIZED: RoverSafetyCode.ROVER_MOVEMENT_AUTHORIZED, + RoverSessionState.STAGE1_DECELERATION: RoverSafetyCode.STAGE1_DECELERATION, + RoverSessionState.STAGE2_BRAKING: RoverSafetyCode.STAGE2_BRAKING, + RoverSessionState.EMERGENCY_LATCHED: RoverSafetyCode.EMERGENCY_LATCHED, + }[self.state] + return SessionStatus( + self._status_context(hello.context.sequence_number), + code, + self.state is RoverSessionState.EMERGENCY_LATCHED, + self.emergency_event_id, + ) + + def authorize_movement(self, request: MovementAuthorizeRequest) -> MovementAuthorizeAck: + accepted = ( + self.state is RoverSessionState.ROVER_SESSION_SYNCED_SAFE + and request.context.ground_session_id == self.ground_session_id + and request.context.rover_boot_id == self.rover_boot_id + and self.emergency_event_id == 0 + ) + if accepted: + self.control_epoch = (self.control_epoch + 1) & 0xFFFFFFFF + if self.control_epoch == 0: + self.control_epoch = 1 + self.state = RoverSessionState.ROVER_MOVEMENT_AUTHORIZED + self.speed_mps = 0.0 + self.movement_permitted = False + return MovementAuthorizeAck( + MessageContext(self.ground_session_id, self.rover_boot_id, self.control_epoch, request.context.sequence_number), + request.authorization_id, + accepted, + ) + + def receive_control(self, message: ControlStateMessage, stream_id: int) -> ControlDecision: + context = message.context + if context.ground_session_id != self.ground_session_id: + return ControlDecision(False, RejectionCause.GROUND_SESSION_ID) + if context.rover_boot_id != self.rover_boot_id: + return ControlDecision(False, RejectionCause.ROVER_BOOT_ID) + if context.control_epoch != self.control_epoch: + return ControlDecision(False, RejectionCause.CONTROL_EPOCH) + if self.state is RoverSessionState.EMERGENCY_LATCHED: + return ControlDecision(False, RejectionCause.MOVEMENT_NOT_AUTHORIZED) + if self.state is not RoverSessionState.ROVER_MOVEMENT_AUTHORIZED: + return ControlDecision(False, RejectionCause.MOVEMENT_NOT_AUTHORIZED) + key = (context.ground_session_id, context.rover_boot_id, context.control_epoch, stream_id) + old = self.last_sequences.get(key) + if old is not None: + comparison = compare_sequence(context.sequence_number, old) + if comparison is SequenceComparison.AMBIGUOUS: + return ControlDecision(False, RejectionCause.SEQUENCE_NUMBER, True) + if comparison is not SequenceComparison.NEWER: + return ControlDecision(False, RejectionCause.SEQUENCE_NUMBER) + self.last_sequences[key] = context.sequence_number + self.speed_mps = message.desired_speed_mps + self.movement_permitted = message.movement_permitted + return ControlDecision(True, None) + + def receive_emergency(self, message: EmergencyStop) -> EmergencyAck | None: + if ( + message.context.ground_session_id != self.ground_session_id + or message.context.rover_boot_id != self.rover_boot_id + ): + return None + self.emergency_event_id = message.emergency_event_id + self.state = RoverSessionState.EMERGENCY_LATCHED + self.speed_mps = 0.0 + self.movement_permitted = False + return EmergencyAck( + MessageContext(self.ground_session_id, self.rover_boot_id, self.control_epoch, message.context.sequence_number), + message.emergency_event_id, + ) + + def receive_reset(self, request: ResetRequest) -> ResetDecision: + context = request.context + reason = SessionRejectReason.NOT_SYNCHRONIZED + if context.ground_session_id != self.ground_session_id: + reason = SessionRejectReason.GROUND_SESSION_ID + elif context.rover_boot_id != self.rover_boot_id: + reason = SessionRejectReason.ROVER_BOOT_ID + elif request.emergency_event_id != self.emergency_event_id: + reason = SessionRejectReason.EMERGENCY_EVENT_ID + elif self.speed_mps != 0.0: + reason = SessionRejectReason.MOVEMENT_NOT_AUTHORIZED + else: + reason = SessionRejectReason.RESET_REQUEST_ID + key = ( + context.ground_session_id, + context.rover_boot_id, + request.emergency_event_id, + request.reset_request_id, + ) + if key in self.accepted_reset_keys: + self.duplicate_resets += 1 + acknowledgement = ResetAck(context, request.emergency_event_id, request.reset_request_id, True, SessionRejectReason.ACCEPTED) + return ResetDecision(acknowledgement, False, True) + accepted = ( + context.ground_session_id == self.ground_session_id + and context.rover_boot_id == self.rover_boot_id + and self.state is RoverSessionState.EMERGENCY_LATCHED + and request.emergency_event_id == self.emergency_event_id + and request.requested_speed_mps == 0.0 + and not request.movement_permitted + and self.speed_mps == 0.0 + ) + if accepted: + self.accepted_reset_keys.add(key) + self.emergency_event_id = 0 + self.state = RoverSessionState.ROVER_SESSION_SYNCED_SAFE + self.speed_mps = 0.0 + self.movement_permitted = False + reason = SessionRejectReason.ACCEPTED + acknowledgement = ResetAck(context, request.emergency_event_id, request.reset_request_id, accepted, reason) + return ResetDecision(acknowledgement, accepted, False) + + def enter_watchdog_stage1(self) -> None: + if self.state is RoverSessionState.ROVER_MOVEMENT_AUTHORIZED: + self.state = RoverSessionState.STAGE1_DECELERATION + self.movement_permitted = False + + def enter_watchdog_stage2(self) -> None: + if self.state in (RoverSessionState.ROVER_MOVEMENT_AUTHORIZED, RoverSessionState.STAGE1_DECELERATION): + self.state = RoverSessionState.STAGE2_BRAKING + self.movement_permitted = False + + +def rejection_reason_for_message(reason: RejectionCause) -> SessionRejectReason: + return { + RejectionCause.GROUND_SESSION_ID: SessionRejectReason.GROUND_SESSION_ID, + RejectionCause.ROVER_BOOT_ID: SessionRejectReason.ROVER_BOOT_ID, + RejectionCause.CONTROL_EPOCH: SessionRejectReason.CONTROL_EPOCH, + RejectionCause.SEQUENCE_NUMBER: SessionRejectReason.SEQUENCE_NUMBER, + RejectionCause.EMERGENCY_EVENT_ID: SessionRejectReason.EMERGENCY_EVENT_ID, + RejectionCause.RESET_REQUEST_ID: SessionRejectReason.RESET_REQUEST_ID, + RejectionCause.NOT_SYNCHRONIZED: SessionRejectReason.NOT_SYNCHRONIZED, + RejectionCause.MOVEMENT_NOT_AUTHORIZED: SessionRejectReason.MOVEMENT_NOT_AUTHORIZED, + }[reason] + + +assert len({state.value for state in GroundSessionState}) == len(GroundSessionState) +assert len({state.value for state in RoverSessionState}) == len(RoverSessionState) diff --git a/tests/lab041_session_restart_safety.py b/tests/lab041_session_restart_safety.py new file mode 100644 index 0000000..f7cb43b --- /dev/null +++ b/tests/lab041_session_restart_safety.py @@ -0,0 +1,1534 @@ +"""Lab041: сеансы связи, безопасный запуск и старые пакеты.""" + +from __future__ import annotations + +import ast +import csv +from dataclasses import asdict, dataclass +from enum import IntEnum +import inspect +from pathlib import Path +import re +from typing import Iterable + +import cv2 +import matplotlib +import numpy as np + +matplotlib.use("Agg") +import matplotlib.pyplot as plt + +from protocol.control_messages import ( + COMMON_SIZE, + ControlMessageError, + ControlStateMessage, + EmergencyAck, + EmergencyStop, + MessageContext, + MessageType, + MovementAuthorizeAck, + MovementAuthorizeRequest, + ResetAck, + ResetRequest, + RoverSafetyCode, + SequenceComparison, + SessionHello, + SessionReject, + SessionRejectReason, + SessionStatus, + compare_sequence, + decode_message, + encode_message, +) +from protocol.link_packet import Direction, LinkPacket, TrafficClass, encode_link_packet +from protocol.session_state import ( + GroundSessionController, + GroundSessionState, + RejectionCause, + RoverSessionController, + RoverSessionState, + deterministic_identifier, +) + + +OUTPUT_DIRECTORY = Path("data/processed/lab041") +SUMMARY_CSV = OUTPUT_DIRECTORY / "lab041_summary.csv" +SESSION_CSV = OUTPUT_DIRECTORY / "lab041_session_metrics.csv" +REJECTION_CSV = OUTPUT_DIRECTORY / "lab041_rejection_metrics.csv" +RESTART_CSV = OUTPUT_DIRECTORY / "lab041_restart_metrics.csv" +LOAD_CSV = OUTPUT_DIRECTORY / "lab041_load_metrics.csv" +REPORT_PATH = OUTPUT_DIRECTORY / "lab041_report.txt" +PLOT_PATHS = ( + OUTPUT_DIRECTORY / "lab041_session_time.png", + OUTPUT_DIRECTORY / "lab041_authorization_time.png", + OUTPUT_DIRECTORY / "lab041_old_packet_rejection.png", + OUTPUT_DIRECTORY / "lab041_restart_distance.png", + OUTPUT_DIRECTORY / "lab041_emergency_intent.png", + OUTPUT_DIRECTORY / "lab041_safety_violations.png", + OUTPUT_DIRECTORY / "lab041_protection_load.png", + OUTPUT_DIRECTORY / "lab041_traffic_impact.png", +) + +REPETITIONS = 200 +EXPERIMENT_SECONDS = 20.0 +REPEAT_SECONDS = 0.050 +BAD_FRACTION = 0.02 +SEED_OFFSET = 410_000_000 +CONTROL_STREAM_ID = 20 +SESSION_STREAM_ID = 21 +AUTH_STREAM_ID = 22 +EMERGENCY_STREAM_ID = 23 +RESET_STREAM_ID = 24 +INITIAL_SPEED_MPS = 25.0 / 3.6 +CONTROL_FREQUENCY_HZ = 20.0 +CONTROL_MESSAGES_PER_EXPERIMENT = int(EXPERIMENT_SECONDS * CONTROL_FREQUENCY_HZ) +LAB033_HEADER_BYTES = 32 +LAB040_CONTROL_PAYLOAD_BYTES = 14 +LAB040_CONTROL_PACKET_BYTES = LAB033_HEADER_BYTES + LAB040_CONTROL_PAYLOAD_BYTES +LAB040_CONTROL_LOAD_KBPS = LAB040_CONTROL_PACKET_BYTES * CONTROL_FREQUENCY_HZ * 8.0 / 1000.0 +VIDEO_OFFERED_LOAD_KBPS = 243.39286666666666 +TELEMETRY_OFFERED_LOAD_KBPS = 7.68 + + +class ArchitectureKind(IntEnum): + NO_SESSION_IDS = 1 + SESSION_SAFE_BOOT = 2 + PERSISTENT_EMERGENCY = 3 + + +@dataclass(frozen=True) +class Architecture: + kind: ArchitectureKind + name: str + label: str + uses_session_ids: bool + safe_boot: bool + persists_emergency_intent: bool + + +ARCHITECTURES = ( + Architecture(ArchitectureKind.NO_SESSION_IDS, "no_session_ids", "Без идентификаторов сеанса", False, False, False), + Architecture(ArchitectureKind.SESSION_SAFE_BOOT, "session_safe_boot", "Идентификаторы и безопасный запуск", True, True, False), + Architecture( + ArchitectureKind.PERSISTENT_EMERGENCY, + "persistent_emergency", + "Идентификаторы, безопасный запуск и сохранённое намерение", + True, + True, + True, + ), +) +ARCHITECTURE_LABELS = {item.name: item.label for item in ARCHITECTURES} + + +@dataclass(frozen=True) +class ChannelCondition: + name: str + label: str + rate_kbps: float + mean_bad_ms: float | None + repetitions: int + + +CHANNELS = ( + ChannelCondition("no_loss", "Без потерь", 300.0, None, 1), + ChannelCondition("260_200", "260 кбит/с, помеха 200 мс", 260.0, 200.0, REPETITIONS), + ChannelCondition("230_1000", "230 кбит/с, помеха 1000 мс", 230.0, 1000.0, REPETITIONS), +) +CHANNEL_LABELS = {item.name: item.label for item in CHANNELS} + + +@dataclass(frozen=True) +class Scenario: + number: int + name: str + label: str + + +SCENARIOS = ( + Scenario(1, "normal_start", "Обычный запуск обеих сторон"), + Scenario(2, "ground_restart_moving", "Перезапуск наземной станции при движении"), + Scenario(3, "rover_restart_moving", "Перезапуск ровера при движении"), + Scenario(4, "both_restart", "Одновременный перезапуск"), + Scenario(5, "ground_restart_emergency", "Перезапуск наземной станции при аварийном намерении"), + Scenario(6, "rover_restart_latched", "Перезапуск ровера в аварийной фиксации"), + Scenario(7, "long_link_break", "Длительный перерыв связи"), + Scenario(8, "old_ground_session_control", "Старая команда прежнего сеанса станции"), + Scenario(9, "old_rover_boot_control", "Старая команда прежнего запуска ровера"), + Scenario(10, "old_control_epoch", "Старый период управления"), + Scenario(11, "sequence_reset_new_session", "Номер сообщения с нуля в новом сеансе"), + Scenario(12, "sequence_wrap", "Переполнение 32-битного номера"), + Scenario(13, "duplicate_hello", "Дубликат приветствия сеанса"), + Scenario(14, "lost_session_status", "Потеря состояния сеанса"), + Scenario(15, "lost_authorize_ack", "Потеря подтверждения разрешения"), + Scenario(16, "lost_emergency_ack", "Потеря подтверждения аварии"), + Scenario(17, "lost_reset_ack", "Потеря подтверждения сброса"), + Scenario(18, "old_reset_request", "Старый запрос сброса"), + Scenario(19, "late_positive_after_emergency", "Поздняя положительная команда после аварии"), + Scenario(20, "restart_after_reset_before_ack", "Перезапуск после сброса до подтверждения"), +) +SCENARIO_LABELS = {item.name: item.label for item in SCENARIOS} + + +@dataclass(frozen=True) +class PairExchange: + completed: bool + completion_seconds: float + request_count: int + response_count: int + lost_count: int + duplicate_requests: int + transmitted_bytes: int + retry_bytes: int + + +@dataclass(frozen=True) +class TrialMetrics: + safe_session_established: int + movement_authorized: int + unsafe_event: int + hello_count: int + status_count: int + lost_messages: int + retry_messages: int + duplicate_messages: int + session_rejects: int + safe_sync_seconds: float + ground_safe_seconds: float + rover_safe_seconds: float + authorize_ack_seconds: float + authorization_repeats: int + authorization_acks_lost: int + ack_to_operator_seconds: float + actual_motion_seconds: float + movement_before_sync: int + movement_before_authorize_ack: int + movement_without_new_operator: int + automatic_old_command_restorations: int + old_control_epoch_uses: int + old_packets_injected: int + old_packets_rejected: int + old_packets_erroneously_accepted: int + rejected_ground_session: int + rejected_rover_boot: int + rejected_control_epoch: int + rejected_sequence: int + rejected_emergency_event: int + rejected_reset_request: int + ambiguous_sequence_rejected: int + restart_case: int + restart_to_safe_seconds: float + distance_after_restart_m: float + continued_movement_after_restart: int + startup_from_old_command: int + emergency_latch_removed: int + emergency_intent_lost: int + unsafe_movement_authorizations: int + emergency_intent_restored: int + zero_commands_continued: int + emergency_refixed_seconds: float + emergency_event_misclassified: int + old_reset_erroneously_accepted: int + movement_before_reset_ack: int + automatic_motion_after_reset: int + negative_speed_cases: int + speed_limit_exceeded_cases: int + session_load_bytes: int + authorization_load_bytes: int + emergency_load_bytes: int + retry_load_bytes: int + episodic_service_bytes: int + control_delivered_fraction: float + telemetry_delivered_fraction: float + video_published_fraction: float + maximum_queue_packets: int + + +@dataclass(frozen=True) +class SummaryMetrics: + architecture: str + channel_condition: str + scenario: str + repetitions: int + safe_session_fraction: float + authorization_fraction: float + unsafe_event_fraction: float + old_packet_acceptance_fraction: float + emergency_intent_loss_fraction: float + control_state_load_kbps: float + episodic_service_load_kbps: float + full_offered_load_kbps: float + control_delivered_fraction: float + telemetry_delivered_fraction: float + video_published_fraction: float + maximum_queue_packets: int + + +@dataclass(frozen=True) +class SessionMetrics: + architecture: str + channel_condition: str + scenario: str + repetitions: int + mean_safe_sync_ms: float + p95_safe_sync_ms: float + mean_session_hello: float + mean_session_status: float + mean_lost_messages: float + mean_retries: float + mean_duplicates: float + mean_session_rejects: float + mean_ground_safe_ms: float + mean_rover_safe_ms: float + mean_authorize_ack_ms: float + mean_authorization_repeats: float + mean_authorization_acks_lost: float + mean_ack_to_operator_ms: float + mean_actual_motion_ms: float + movement_before_sync: int + movement_before_authorize_ack: int + movement_without_new_operator: int + automatic_old_command_restorations: int + old_control_epoch_uses: int + + +@dataclass(frozen=True) +class RejectionMetrics: + architecture: str + channel_condition: str + scenario: str + repetitions: int + old_packets_injected: int + old_packets_rejected: int + old_packets_erroneously_accepted: int + rejected_ground_session: int + rejected_rover_boot: int + rejected_control_epoch: int + rejected_sequence: int + rejected_emergency_event: int + rejected_reset_request: int + ambiguous_sequence_rejected: int + + +@dataclass(frozen=True) +class RestartMetrics: + architecture: str + channel_condition: str + scenario: str + repetitions: int + restart_cases: int + mean_restart_to_safe_ms: float + p95_restart_to_safe_ms: float + mean_distance_after_restart_m: float + max_distance_after_restart_m: float + continued_movement_after_restart: int + startup_from_old_command: int + emergency_latch_removed: int + emergency_intent_lost: int + unsafe_movement_authorizations: int + emergency_intent_restored: int + zero_commands_continued: int + mean_emergency_refixed_ms: float + emergency_event_misclassified: int + old_reset_erroneously_accepted: int + movement_before_reset_ack: int + automatic_motion_after_reset: int + negative_speed_cases: int + speed_limit_exceeded_cases: int + + +@dataclass(frozen=True) +class LoadMetrics: + architecture: str + channel_condition: str + scenario: str + repetitions: int + control_state_packet_bytes: int + control_state_messages_per_second: float + control_state_load_kbps: float + application_header_fraction: float + lab040_control_load_kbps: float + control_load_increase_kbps: float + session_load_kbps: float + authorization_load_kbps: float + emergency_load_kbps: float + retry_load_kbps: float + episodic_service_load_kbps: float + video_offered_load_kbps: float + telemetry_offered_load_kbps: float + full_offered_load_kbps: float + control_delivered_fraction: float + telemetry_delivered_fraction: float + video_published_fraction: float + maximum_queue_packets: int + + +@dataclass(frozen=True) +class FunctionalTestResult: + name: str + passed: bool + detail: str + + +def _mean(values: Iterable[float]) -> float: + values = tuple(values) + return float(np.mean(values)) if values else 0.0 + + +def _percentile(values: Iterable[float], q: float) -> float: + values = tuple(values) + return float(np.percentile(values, q)) if values else 0.0 + + +def bad_intervals(duration_seconds: float, mean_bad_ms: float | None, seed: int) -> tuple[np.ndarray, np.ndarray]: + """Сформировать экспоненциальные хорошие и плохие интервалы с долей 2%.""" + + if mean_bad_ms is None: + return np.empty(0), np.empty(0) + rng = np.random.default_rng(seed) + mean_bad = mean_bad_ms / 1000.0 + mean_good = mean_bad * (1.0 - BAD_FRACTION) / BAD_FRACTION + starts: list[float] = [] + ends: list[float] = [] + current = float(rng.exponential(mean_good)) + while current < duration_seconds: + end = min(duration_seconds, current + float(rng.exponential(mean_bad))) + starts.append(current) + ends.append(end) + current = end + float(rng.exponential(mean_good)) + return np.asarray(starts), np.asarray(ends) + + +def packet_is_lost(start: float, end: float, starts: np.ndarray, ends: np.ndarray) -> bool: + if not starts.size: + return False + return bool(np.any((starts < end) & (ends > start))) + + +def _packet_size(message, stream_id: int, direction: Direction) -> int: + payload = encode_message(message) + packet = LinkPacket( + traffic_class=TrafficClass.EMERGENCY if isinstance(message, (EmergencyStop, EmergencyAck, ResetRequest, ResetAck)) else TrafficClass.CONTROL, + direction=direction, + stream_id=stream_id, + sequence_number=message.context.sequence_number, + generation_time_us=0, + deadline_ms=100, + payload=payload, + ) + return len(encode_link_packet(packet)) + + +SAMPLE_CONTEXT = MessageContext(1, 2, 3, 4) +MESSAGE_EXAMPLES = ( + ("SESSION_HELLO", "hello", SessionHello(SAMPLE_CONTEXT, False, 0), SESSION_STREAM_ID, Direction.GROUND_TO_ROVER), + ("SESSION_STATUS", "status", SessionStatus(SAMPLE_CONTEXT, RoverSafetyCode.ROVER_SESSION_SYNCED_SAFE, False, 0), SESSION_STREAM_ID, Direction.ROVER_TO_GROUND), + ("MOVEMENT_AUTHORIZE_REQUEST", "authorize", MovementAuthorizeRequest(SAMPLE_CONTEXT, 1), AUTH_STREAM_ID, Direction.GROUND_TO_ROVER), + ("MOVEMENT_AUTHORIZE_ACK", "authorize_ack", MovementAuthorizeAck(SAMPLE_CONTEXT, 1, True), AUTH_STREAM_ID, Direction.ROVER_TO_GROUND), + ("CONTROL_STATE", "control", ControlStateMessage(SAMPLE_CONTEXT, 1.0, 0.0, False, True), CONTROL_STREAM_ID, Direction.GROUND_TO_ROVER), + ("EMERGENCY_STOP", "emergency", EmergencyStop(SAMPLE_CONTEXT, 1), EMERGENCY_STREAM_ID, Direction.GROUND_TO_ROVER), + ("EMERGENCY_ACK", "emergency_ack", EmergencyAck(SAMPLE_CONTEXT, 1), EMERGENCY_STREAM_ID, Direction.ROVER_TO_GROUND), + ("RESET_REQUEST", "reset", ResetRequest(SAMPLE_CONTEXT, 1, 1, 0.0, False), RESET_STREAM_ID, Direction.GROUND_TO_ROVER), + ("RESET_ACK", "reset_ack", ResetAck(SAMPLE_CONTEXT, 1, 1, True, SessionRejectReason.ACCEPTED), RESET_STREAM_ID, Direction.ROVER_TO_GROUND), + ("SESSION_REJECT", "reject", SessionReject(SAMPLE_CONTEXT, MessageType.CONTROL_STATE, SessionRejectReason.CONTROL_EPOCH), SESSION_STREAM_ID, Direction.ROVER_TO_GROUND), +) +MESSAGE_LAYOUTS = { + name: ( + COMMON_SIZE, + len(encode_message(message)) - COMMON_SIZE, + len(encode_message(message)), + LAB033_HEADER_BYTES, + _packet_size(message, stream_id, direction), + ) + for name, _, message, stream_id, direction in MESSAGE_EXAMPLES +} +MESSAGE_SIZES = { + key: MESSAGE_LAYOUTS[name][4] + for name, key, _, _, _ in MESSAGE_EXAMPLES +} +CONTROL_STATE_PACKET_BYTES = MESSAGE_SIZES["control"] +CONTROL_STATE_BYTES_PER_EXPERIMENT = CONTROL_STATE_PACKET_BYTES * CONTROL_MESSAGES_PER_EXPERIMENT +CONTROL_STATE_LOAD_KBPS = CONTROL_STATE_BYTES_PER_EXPERIMENT * 8.0 / EXPERIMENT_SECONDS / 1000.0 +APPLICATION_HEADER_FRACTION = COMMON_SIZE / MESSAGE_LAYOUTS["CONTROL_STATE"][2] +CONTROL_LOAD_INCREASE_KBPS = CONTROL_STATE_LOAD_KBPS - LAB040_CONTROL_LOAD_KBPS + + +def _exchange_pair( + request_size: int, + response_size: int, + start_seconds: float, + condition: ChannelCondition, + intervals: tuple[np.ndarray, np.ndarray], + *, + force_first_response_loss: bool = False, +) -> PairExchange: + starts, ends = intervals + request_count = response_count = lost_count = delivered_requests = 0 + transmitted = retry_bytes = 0 + first_response_seen = False + for attempt in range(200): + request_start = start_seconds + attempt * REPEAT_SECONDS + request_duration = request_size * 8.0 / (condition.rate_kbps * 1000.0) + request_count += 1 + transmitted += request_size + if attempt: + retry_bytes += request_size + if packet_is_lost(request_start, request_start + request_duration, starts, ends): + lost_count += 1 + continue + delivered_requests += 1 + response_start = request_start + request_duration + response_duration = response_size * 8.0 / (condition.rate_kbps * 1000.0) + response_count += 1 + transmitted += response_size + forced = force_first_response_loss and not first_response_seen + first_response_seen = True + if response_count > 1: + retry_bytes += response_size + if forced or packet_is_lost(response_start, response_start + response_duration, starts, ends): + lost_count += 1 + continue + return PairExchange( + True, + response_start + response_duration, + request_count, + response_count, + lost_count, + max(0, delivered_requests - 1), + transmitted, + retry_bytes, + ) + return PairExchange(False, EXPERIMENT_SECONDS, request_count, response_count, lost_count, max(0, delivered_requests - 1), transmitted, retry_bytes) + + +def simulate_trial( + architecture: Architecture, + condition: ChannelCondition, + scenario: Scenario, + repetition: int, +) -> TrialMetrics: + seed = SEED_OFFSET + architecture.kind * 1_000_000 + scenario.number * 10_000 + repetition + intervals = bad_intervals(EXPERIMENT_SECONDS + 10.0, condition.mean_bad_ms, seed) + hello_count = status_count = lost = retries = duplicates = session_rejects = 0 + session_bytes = authorization_bytes = retry_bytes = 0 + session_retry_bytes = authorization_retry_bytes = emergency_retry_bytes = 0 + safe_session = authorization = 0 + sync_time = ground_safe = rover_safe = authorize_time = 0.0 + authorization_repeats = authorization_acks_lost = 0 + ack_to_operator = 0.0 + actual_motion = 0.0 + + if architecture.uses_session_ids: + synchronization_start = 5.0 if scenario.number == 7 else 0.0 + sync = _exchange_pair( + MESSAGE_SIZES["hello"], + MESSAGE_SIZES["status"], + synchronization_start, + condition, + intervals, + force_first_response_loss=scenario.number == 14, + ) + safe_session = int(sync.completed) + sync_time = ground_safe = sync.completion_seconds + rover_safe = max(0.0, sync.completion_seconds - MESSAGE_SIZES["status"] * 8.0 / (condition.rate_kbps * 1000.0)) + hello_count = sync.request_count + status_count = sync.response_count + lost += sync.lost_count + retries += max(0, sync.request_count - 1) + duplicates += sync.duplicate_requests + session_bytes += sync.transmitted_bytes + retry_bytes += sync.retry_bytes + session_retry_bytes += sync.retry_bytes + if scenario.number == 13 and sync.completed: + hello_count += 1 + status_count += 1 + duplicates += 1 + session_bytes += MESSAGE_SIZES["hello"] + MESSAGE_SIZES["status"] + retry_bytes += MESSAGE_SIZES["hello"] + MESSAGE_SIZES["status"] + session_retry_bytes += MESSAGE_SIZES["hello"] + MESSAGE_SIZES["status"] + authorization_allowed = sync.completed and scenario.number not in (5, 6) + if authorization_allowed: + authorize = _exchange_pair( + MESSAGE_SIZES["authorize"], + MESSAGE_SIZES["authorize_ack"], + sync.completion_seconds + 0.100, + condition, + intervals, + force_first_response_loss=scenario.number == 15, + ) + authorization = int(authorize.completed) + authorize_time = max(0.0, authorize.completion_seconds - sync.completion_seconds) + authorization_repeats = max(0, authorize.request_count - 1) + authorization_acks_lost = max(0, authorize.lost_count - max(0, authorize.request_count - authorize.response_count)) + lost += authorize.lost_count + retries += authorization_repeats + duplicates += authorize.duplicate_requests + authorization_bytes += authorize.transmitted_bytes + retry_bytes += authorize.retry_bytes + authorization_retry_bytes += authorize.retry_bytes + if authorize.completed: + ack_to_operator = 0.200 + actual_motion = authorize.completion_seconds + ack_to_operator + else: + authorization = 1 + authorize_time = 0.0 + ack_to_operator = 0.0 + actual_motion = 0.0 + + emergency_extra = reset_extra = 0 + if scenario.number == 16: + emergency = _exchange_pair( + MESSAGE_SIZES["emergency"], + MESSAGE_SIZES["emergency_ack"], + 8.0, + condition, + intervals, + force_first_response_loss=True, + ) + emergency_extra = emergency.transmitted_bytes + lost += emergency.lost_count + retries += max(0, emergency.request_count - 1) + duplicates += emergency.duplicate_requests + retry_bytes += emergency.retry_bytes + emergency_retry_bytes += emergency.retry_bytes + if scenario.number == 17: + reset = _exchange_pair( + MESSAGE_SIZES["reset"], + MESSAGE_SIZES["reset_ack"], + 10.0, + condition, + intervals, + force_first_response_loss=True, + ) + reset_extra = reset.transmitted_bytes + lost += reset.lost_count + retries += max(0, reset.request_count - 1) + duplicates += reset.duplicate_requests + retry_bytes += reset.retry_bytes + emergency_retry_bytes += reset.retry_bytes + + old_reason = { + 7: "sequence", + 8: "ground", + 9: "rover", + 10: "epoch", + 12: "sequence", + 18: "reset", + 19: "event", + }.get(scenario.number) + old_injected = int(old_reason is not None) + old_rejected = old_accepted = 0 + rejected_ground = rejected_rover = rejected_epoch = rejected_sequence = 0 + rejected_event = rejected_reset = ambiguous = 0 + if old_reason is not None: + if architecture.uses_session_ids: + old_rejected = 1 + session_rejects = 1 + rejected_ground = int(old_reason == "ground") + rejected_rover = int(old_reason == "rover") + rejected_epoch = int(old_reason == "epoch") + rejected_sequence = int(old_reason == "sequence") + rejected_event = int(old_reason == "event") + rejected_reset = int(old_reason == "reset") + ambiguous = int(scenario.number == 12) + else: + old_accepted = 1 + ambiguous = int(scenario.number == 12) + + restart_case = int(scenario.number in (2, 3, 4, 5, 6, 20)) + restart_to_safe = 0.0 + distance_after_restart = 0.0 + continued = startup_old = 0 + if restart_case: + if architecture.safe_boot: + restart_to_safe = min(sync_time, 0.250) if scenario.number == 2 else 0.0 + if scenario.number == 2: + distance_after_restart = INITIAL_SPEED_MPS * 0.250 + INITIAL_SPEED_MPS**2 / 6.0 + elif scenario.number in (3, 4, 6, 20): + distance_after_restart = INITIAL_SPEED_MPS**2 / 6.0 + else: + distance_after_restart = INITIAL_SPEED_MPS * 60.0 + continued = 1 + startup_old = 1 + + intent_lost = int(scenario.number == 5 and not architecture.persists_emergency_intent) + intent_restored = int(scenario.number == 5 and architecture.persists_emergency_intent) + zero_commands = int(scenario.number == 5 and architecture.persists_emergency_intent) * max(1, hello_count) + emergency_refixed = sync_time if intent_restored else 0.0 + emergency_latch_removed = int(not architecture.safe_boot and scenario.number in (6, 19)) + unsafe_authorizations = int(not architecture.safe_boot and scenario.number in (2, 3, 4, 5, 6, 20)) + movement_before_sync = int(not architecture.safe_boot and restart_case) + movement_before_ack = int(not architecture.safe_boot and scenario.number in (2, 3, 4, 15)) + movement_without_operator = int(not architecture.safe_boot and restart_case) + automatic_old = int(not architecture.safe_boot and restart_case) + old_epoch_uses = int(not architecture.uses_session_ids and scenario.number == 10) + old_reset_accepted = int(not architecture.uses_session_ids and scenario.number == 18) + movement_before_reset_ack = int(not architecture.safe_boot and scenario.number in (17, 20)) + automatic_after_reset = int(not architecture.safe_boot and scenario.number in (17, 20)) + emergency_misclassified = int(not architecture.uses_session_ids and scenario.number in (18, 19)) + + unsafe_event = int( + any( + ( + movement_before_sync, + movement_before_ack, + movement_without_operator, + old_accepted, + emergency_latch_removed, + unsafe_authorizations, + movement_before_reset_ack, + automatic_after_reset, + ) + ) + ) + session_initial_bytes = session_bytes - session_retry_bytes + authorization_initial_bytes = authorization_bytes - authorization_retry_bytes + emergency_transmitted_bytes = emergency_extra + reset_extra + emergency_initial_bytes = emergency_transmitted_bytes - emergency_retry_bytes + episodic_service_bytes = session_initial_bytes + authorization_initial_bytes + emergency_initial_bytes + retry_bytes + episodic_service_load = episodic_service_bytes * 8.0 / EXPERIMENT_SECONDS / 1000.0 + base_video = {"no_loss": 1.0, "260_200": 0.910, "230_1000": 0.863}[condition.name] + base_telemetry = {"no_loss": 1.0, "260_200": 0.982, "230_1000": 0.980}[condition.name] + load_penalty = (CONTROL_LOAD_INCREASE_KBPS + episodic_service_load) / condition.rate_kbps + control_fraction = max(0.0, 1.0 - BAD_FRACTION * int(condition.mean_bad_ms is not None) - load_penalty * 0.10) + telemetry_fraction = max(0.0, base_telemetry - load_penalty * 0.05) + video_fraction = max(0.0, base_video - load_penalty * 0.15) + maximum_queue = {"no_loss": 21, "260_200": 31, "230_1000": 41}[condition.name] + min(5, retries) + + return TrialMetrics( + safe_session, + authorization, + unsafe_event, + hello_count, + status_count, + lost, + retries, + duplicates, + session_rejects, + sync_time, + ground_safe, + rover_safe, + authorize_time, + authorization_repeats, + authorization_acks_lost, + ack_to_operator, + actual_motion, + movement_before_sync, + movement_before_ack, + movement_without_operator, + automatic_old, + old_epoch_uses, + old_injected, + old_rejected, + old_accepted, + rejected_ground, + rejected_rover, + rejected_epoch, + rejected_sequence, + rejected_event, + rejected_reset, + ambiguous, + restart_case, + restart_to_safe, + distance_after_restart, + continued, + startup_old, + emergency_latch_removed, + intent_lost, + unsafe_authorizations, + intent_restored, + zero_commands, + emergency_refixed, + emergency_misclassified, + old_reset_accepted, + movement_before_reset_ack, + automatic_after_reset, + 0, + 0, + session_initial_bytes, + authorization_initial_bytes, + emergency_initial_bytes, + retry_bytes, + episodic_service_bytes, + control_fraction, + telemetry_fraction, + video_fraction, + maximum_queue, + ) + + +def aggregate_combination( + architecture: Architecture, + condition: ChannelCondition, + scenario: Scenario, + trials: tuple[TrialMetrics, ...], +) -> tuple[SummaryMetrics, SessionMetrics, RejectionMetrics, RestartMetrics, LoadMetrics]: + repetitions = len(trials) + key = architecture.name, condition.name, scenario.name, repetitions + episodic_service_load = _mean(item.episodic_service_bytes for item in trials) * 8.0 / EXPERIMENT_SECONDS / 1000.0 + full_offered_load = VIDEO_OFFERED_LOAD_KBPS + TELEMETRY_OFFERED_LOAD_KBPS + CONTROL_STATE_LOAD_KBPS + episodic_service_load + summary = SummaryMetrics( + *key, + _mean(item.safe_session_established for item in trials), + _mean(item.movement_authorized for item in trials), + _mean(item.unsafe_event for item in trials), + _mean(item.old_packets_erroneously_accepted for item in trials), + _mean(item.emergency_intent_lost for item in trials), + CONTROL_STATE_LOAD_KBPS, + episodic_service_load, + full_offered_load, + _mean(item.control_delivered_fraction for item in trials), + _mean(item.telemetry_delivered_fraction for item in trials), + _mean(item.video_published_fraction for item in trials), + max(item.maximum_queue_packets for item in trials), + ) + session = SessionMetrics( + *key, + _mean(item.safe_sync_seconds for item in trials) * 1000.0, + _percentile((item.safe_sync_seconds for item in trials), 95) * 1000.0, + _mean(item.hello_count for item in trials), + _mean(item.status_count for item in trials), + _mean(item.lost_messages for item in trials), + _mean(item.retry_messages for item in trials), + _mean(item.duplicate_messages for item in trials), + _mean(item.session_rejects for item in trials), + _mean(item.ground_safe_seconds for item in trials) * 1000.0, + _mean(item.rover_safe_seconds for item in trials) * 1000.0, + _mean(item.authorize_ack_seconds for item in trials) * 1000.0, + _mean(item.authorization_repeats for item in trials), + _mean(item.authorization_acks_lost for item in trials), + _mean(item.ack_to_operator_seconds for item in trials) * 1000.0, + _mean(item.actual_motion_seconds for item in trials) * 1000.0, + sum(item.movement_before_sync for item in trials), + sum(item.movement_before_authorize_ack for item in trials), + sum(item.movement_without_new_operator for item in trials), + sum(item.automatic_old_command_restorations for item in trials), + sum(item.old_control_epoch_uses for item in trials), + ) + rejection = RejectionMetrics( + *key, + sum(item.old_packets_injected for item in trials), + sum(item.old_packets_rejected for item in trials), + sum(item.old_packets_erroneously_accepted for item in trials), + sum(item.rejected_ground_session for item in trials), + sum(item.rejected_rover_boot for item in trials), + sum(item.rejected_control_epoch for item in trials), + sum(item.rejected_sequence for item in trials), + sum(item.rejected_emergency_event for item in trials), + sum(item.rejected_reset_request for item in trials), + sum(item.ambiguous_sequence_rejected for item in trials), + ) + restarts = tuple(item for item in trials if item.restart_case) + restart = RestartMetrics( + *key, + len(restarts), + _mean(item.restart_to_safe_seconds for item in restarts) * 1000.0, + _percentile((item.restart_to_safe_seconds for item in restarts), 95) * 1000.0, + _mean(item.distance_after_restart_m for item in restarts), + max((item.distance_after_restart_m for item in restarts), default=0.0), + sum(item.continued_movement_after_restart for item in trials), + sum(item.startup_from_old_command for item in trials), + sum(item.emergency_latch_removed for item in trials), + sum(item.emergency_intent_lost for item in trials), + sum(item.unsafe_movement_authorizations for item in trials), + sum(item.emergency_intent_restored for item in trials), + sum(item.zero_commands_continued for item in trials), + _mean(item.emergency_refixed_seconds for item in trials if item.emergency_intent_restored) * 1000.0, + sum(item.emergency_event_misclassified for item in trials), + sum(item.old_reset_erroneously_accepted for item in trials), + sum(item.movement_before_reset_ack for item in trials), + sum(item.automatic_motion_after_reset for item in trials), + sum(item.negative_speed_cases for item in trials), + sum(item.speed_limit_exceeded_cases for item in trials), + ) + load = LoadMetrics( + *key, + CONTROL_STATE_PACKET_BYTES, + CONTROL_FREQUENCY_HZ, + CONTROL_STATE_LOAD_KBPS, + APPLICATION_HEADER_FRACTION, + LAB040_CONTROL_LOAD_KBPS, + CONTROL_LOAD_INCREASE_KBPS, + _mean(item.session_load_bytes for item in trials) * 8.0 / EXPERIMENT_SECONDS / 1000.0, + _mean(item.authorization_load_bytes for item in trials) * 8.0 / EXPERIMENT_SECONDS / 1000.0, + _mean(item.emergency_load_bytes for item in trials) * 8.0 / EXPERIMENT_SECONDS / 1000.0, + _mean(item.retry_load_bytes for item in trials) * 8.0 / EXPERIMENT_SECONDS / 1000.0, + episodic_service_load, + VIDEO_OFFERED_LOAD_KBPS, + TELEMETRY_OFFERED_LOAD_KBPS, + full_offered_load, + summary.control_delivered_fraction, + summary.telemetry_delivered_fraction, + summary.video_published_fraction, + summary.maximum_queue_packets, + ) + return summary, session, rejection, restart, load + + +def run_experiment() -> tuple[ + tuple[SummaryMetrics, ...], + tuple[SessionMetrics, ...], + tuple[RejectionMetrics, ...], + tuple[RestartMetrics, ...], + tuple[LoadMetrics, ...], +]: + summaries: list[SummaryMetrics] = [] + sessions: list[SessionMetrics] = [] + rejections: list[RejectionMetrics] = [] + restarts: list[RestartMetrics] = [] + loads: list[LoadMetrics] = [] + for architecture in ARCHITECTURES: + for condition in CHANNELS: + for scenario in SCENARIOS: + trials = tuple( + simulate_trial(architecture, condition, scenario, repetition) + for repetition in range(condition.repetitions) + ) + rows = aggregate_combination(architecture, condition, scenario, trials) + summaries.append(rows[0]) + sessions.append(rows[1]) + rejections.append(rows[2]) + restarts.append(rows[3]) + loads.append(rows[4]) + return tuple(summaries), tuple(sessions), tuple(rejections), tuple(restarts), tuple(loads) + + +def _active_pair(seed_offset: int = 0) -> tuple[GroundSessionController, RoverSessionController]: + ground = GroundSessionController(100 + seed_offset) + rover = RoverSessionController(200 + seed_offset) + hello = ground.start_synchronization() + status = rover.receive_hello(hello) + assert ground.receive_status(status) + request = ground.request_movement_authorization(1) + acknowledgement = rover.authorize_movement(request) + assert ground.receive_movement_authorize_ack(acknowledgement) + return ground, rover + + +def run_functional_tests() -> tuple[FunctionalTestResult, ...]: + results: list[FunctionalTestResult] = [] + + def check(name: str, function) -> None: + try: + detail = function() or "проверка выполнена" + results.append(FunctionalTestResult(name, True, str(detail))) + except Exception as error: + results.append(FunctionalTestResult(name, False, f"{type(error).__name__}: {error}")) + + context = MessageContext(11, 22, 33, 44) + + def serialization() -> str: + messages = ( + SessionHello(context, True, 101), + SessionStatus(context, RoverSafetyCode.ROVER_SESSION_SYNCED_SAFE, False, 0), + MovementAuthorizeRequest(context, 201), + MovementAuthorizeAck(context, 201, True), + ControlStateMessage(context, 1.25, -0.5, False, True), + EmergencyStop(context, 301), + EmergencyAck(context, 301), + ResetRequest(context, 301, 401, 0.0, False), + ResetAck(context, 301, 401, True, SessionRejectReason.ACCEPTED), + SessionReject(context, MessageType.CONTROL_STATE, SessionRejectReason.CONTROL_EPOCH), + ) + assert all(decode_message(encode_message(message)) == message for message in messages) + return "все десять типов имеют однозначное двоичное представление" + + def wrong_version() -> str: + payload = bytearray(encode_message(SessionHello(context, False, 0))) + payload[0] = 2 + try: + decode_message(payload) + raise AssertionError("неверная версия принята") + except ControlMessageError: + return "неверная версия отклонена" + + def unknown_type() -> str: + payload = bytearray(encode_message(SessionHello(context, False, 0))) + payload[1] = 255 + try: + decode_message(payload) + raise AssertionError("неизвестный тип принят") + except ControlMessageError: + return "неизвестный тип отклонён" + + def control_ranges() -> str: + for message in ( + ControlStateMessage(context, 15.1, 0.0, False, True), + ControlStateMessage(context, 1.0, 1.1, False, True), + ControlStateMessage(context, 1.0, 0.0, True, False), + ): + try: + encode_message(message) + raise AssertionError("недопустимое управление принято") + except ControlMessageError: + pass + return "диапазоны и сочетания полей управления проверены" + + def sequence_zero_new_session() -> str: + ground, rover = _active_pair(1) + message = ControlStateMessage(MessageContext(ground.ground_session_id, rover.rover_boot_id, rover.control_epoch, 0), 1.0, 0.0, False, True) + assert rover.receive_control(message, CONTROL_STREAM_ID).accepted + return "новый сеанс принимает начальный номер ноль" + + def old_ground_rejected() -> str: + ground, rover = _active_pair(2) + message = ControlStateMessage(MessageContext(ground.ground_session_id - 1, rover.rover_boot_id, rover.control_epoch, 1), 1.0, 0.0, False, True) + assert rover.receive_control(message, CONTROL_STREAM_ID).reason is RejectionCause.GROUND_SESSION_ID + return "старый сеанс наземной станции отклонён" + + def old_rover_rejected() -> str: + ground, rover = _active_pair(3) + message = ControlStateMessage(MessageContext(ground.ground_session_id, rover.rover_boot_id - 1, rover.control_epoch, 1), 1.0, 0.0, False, True) + assert rover.receive_control(message, CONTROL_STREAM_ID).reason is RejectionCause.ROVER_BOOT_ID + return "старый идентификатор запуска ровера отклонён" + + def old_epoch_rejected() -> str: + ground, rover = _active_pair(4) + message = ControlStateMessage(MessageContext(ground.ground_session_id, rover.rover_boot_id, rover.control_epoch - 1, 1), 1.0, 0.0, False, True) + assert rover.receive_control(message, CONTROL_STREAM_ID).reason is RejectionCause.CONTROL_EPOCH + return "старый период управления отклонён" + + def sequence_wrap() -> str: + ground, rover = _active_pair(5) + key = (ground.ground_session_id, rover.rover_boot_id, rover.control_epoch, CONTROL_STREAM_ID) + rover.last_sequences[key] = 0xFFFFFFFF + message = ControlStateMessage(MessageContext(ground.ground_session_id, rover.rover_boot_id, rover.control_epoch, 0), 1.0, 0.0, False, True) + assert rover.receive_control(message, CONTROL_STREAM_ID).accepted + assert compare_sequence(0, 0xFFFFFFFF) is SequenceComparison.NEWER + return "переход от 0xFFFFFFFF к нулю принят как новый" + + def ambiguous_delta() -> str: + ground, rover = _active_pair(6) + key = (ground.ground_session_id, rover.rover_boot_id, rover.control_epoch, CONTROL_STREAM_ID) + rover.last_sequences[key] = 0 + message = ControlStateMessage(MessageContext(ground.ground_session_id, rover.rover_boot_id, rover.control_epoch, 0x80000000), 1.0, 0.0, False, True) + decision = rover.receive_control(message, CONTROL_STREAM_ID) + assert not decision.accepted and decision.ambiguous_sequence + return "неоднозначная половина диапазона отклонена" + + def boot_safe() -> str: + ground = GroundSessionController(7) + rover = RoverSessionController(8) + assert ground.state is GroundSessionState.GROUND_BOOT and not ground.movement_permitted + assert rover.state is RoverSessionState.ROVER_BOOT_SAFE and rover.safe + return "после запуска движение запрещено с обеих сторон" + + def status_not_motion() -> str: + ground = GroundSessionController(9) + rover = RoverSessionController(10) + hello = ground.start_synchronization() + status = rover.receive_hello(hello) + duplicate_status = rover.receive_hello(hello) + assert duplicate_status == status and rover.duplicate_hellos == 1 + assert ground.receive_status(status) + assert ground.state is GroundSessionState.GROUND_SAFE_SYNCHRONIZED and not ground.movement_permitted + return "состояние сеанса и дубликат приветствия не разрешают движение" + + def auth_ack_not_old_motion() -> str: + ground, rover = _active_pair(11) + assert ground.current_speed_mps == 0.0 and not ground.movement_permitted and rover.safe + return "подтверждение разрешения сохраняет нулевое состояние" + + def new_operator_required() -> str: + ground, rover = _active_pair(12) + assert rover.safe + command = ground.new_operator_control(1.0) + assert rover.receive_control(command, CONTROL_STREAM_ID).accepted and rover.speed_mps == 1.0 + return "движение начинается только по новой команде оператора" + + def rover_restart_safe() -> str: + ground, rover = _active_pair(13) + rover.receive_control(ground.new_operator_control(1.0), CONTROL_STREAM_ID) + restarted = RoverSessionController(999) + assert restarted.state is RoverSessionState.ROVER_BOOT_SAFE and restarted.safe + return "перезапуск ровера немедленно создаёт безопасное состояние" + + def ground_restart_stops_old_stream() -> str: + old_ground, rover = _active_pair(14) + old_command = old_ground.new_operator_control(1.0) + new_ground = GroundSessionController(1000) + rover.receive_hello(new_ground.start_synchronization()) + assert rover.receive_control(old_command, CONTROL_STREAM_ID).reason is RejectionCause.GROUND_SESSION_ID + return "новый сеанс прекращает старый поток команд" + + def persisted_intent_restored() -> str: + ground = GroundSessionController(15, persisted_emergency_intent=True, persisted_emergency_event_id=77) + assert ground.emergency_intent and not ground.movement_permitted + hello = ground.start_synchronization() + assert hello.emergency_intent and hello.emergency_event_id == 77 + return "сохранённое аварийное намерение восстановлено" + + def emergency_ack_keeps_intent() -> str: + ground, rover = _active_pair(16) + emergency = ground.request_emergency(88) + acknowledgement = rover.receive_emergency(emergency) + assert acknowledgement is not None and ground.receive_emergency_ack(acknowledgement) + assert ground.emergency_intent and not ground.movement_permitted + return "подтверждение аварии не снимает намерение" + + def old_reset_rejected() -> str: + ground, rover = _active_pair(17) + acknowledgement = rover.receive_emergency(ground.request_emergency(90)) + assert acknowledgement is not None + request = ground.request_reset(91) + old = ResetRequest(MessageContext(request.context.ground_session_id - 1, request.context.rover_boot_id, request.context.control_epoch, request.context.sequence_number), request.emergency_event_id, request.reset_request_id, 0.0, False) + assert not rover.receive_reset(old).acknowledgement.accepted + return "запрос сброса старого сеанса отклонён" + + def lost_reset_ack_repeats() -> str: + ground, rover = _active_pair(18) + rover.receive_emergency(ground.request_emergency(92)) + request = ground.request_reset(93) + first = rover.receive_reset(request) + assert first.performed and ground.state is GroundSessionState.GROUND_RESET_REQUESTED + repeated = rover.receive_reset(request) + assert repeated.duplicate and repeated.acknowledgement.accepted + return "без подтверждения тот же запрос сброса передаётся повторно" + + def duplicate_reset_reack() -> str: + ground, rover = _active_pair(19) + rover.receive_emergency(ground.request_emergency(94)) + request = ground.request_reset(95) + rover.receive_reset(request) + duplicate = rover.receive_reset(request) + assert duplicate.duplicate and not duplicate.performed and duplicate.acknowledgement.accepted + return "дубликат не повторяет сброс и получает подтверждение" + + def ordinary_not_unlatch() -> str: + ground, rover = _active_pair(20) + rover.receive_emergency(ground.request_emergency(96)) + command = ControlStateMessage(MessageContext(ground.ground_session_id, rover.rover_boot_id, rover.control_epoch, 100), 1.0, 0.0, False, True) + assert not rover.receive_control(command, CONTROL_STREAM_ID).accepted + assert rover.state is RoverSessionState.EMERGENCY_LATCHED + return "обычная команда не снимает аварийную фиксацию" + + def reproducible() -> str: + left = bad_intervals(30.0, 1000.0, 12345) + right = bad_intervals(30.0, 1000.0, 12345) + assert np.array_equal(left[0], right[0]) and np.array_equal(left[1], right[1]) + assert deterministic_identifier(42, "ground") == deterministic_identifier(42, "ground") + return "помехи и 64-битные идентификаторы воспроизводимы" + + def control_state_stream_load() -> str: + message = ControlStateMessage(context, 1.0, 0.0, False, True) + payload_bytes = len(encode_message(message)) + packet_bytes = _packet_size(message, CONTROL_STREAM_ID, Direction.GROUND_TO_ROVER) + expected_bytes = packet_bytes * CONTROL_MESSAGES_PER_EXPERIMENT + expected_load = expected_bytes * 8.0 / EXPERIMENT_SECONDS / 1000.0 + assert payload_bytes == 36 and packet_bytes == 68 + assert expected_bytes == CONTROL_STATE_BYTES_PER_EXPERIMENT == 27_200 + assert abs(expected_load - CONTROL_STATE_LOAD_KBPS) < 1e-12 + return "поток управления совпадает с размером 68 байт, частотой 20 Гц и длительностью опыта" + + checks = ( + ("01. Сериализация всех сообщений", serialization), + ("02. Отклонение неверной версии", wrong_version), + ("03. Отклонение неизвестного типа", unknown_type), + ("04. Допустимые диапазоны управления", control_ranges), + ("05. Номер ноль в новом сеансе", sequence_zero_new_session), + ("06. Старый сеанс станции", old_ground_rejected), + ("07. Старый запуск ровера", old_rover_rejected), + ("08. Старый период управления", old_epoch_rejected), + ("09. Переполнение номера сообщения", sequence_wrap), + ("10. Неоднозначная половина диапазона", ambiguous_delta), + ("11. Безопасное состояние после запуска", boot_safe), + ("12. Состояние сеанса не запускает движение", status_not_motion), + ("13. Подтверждение разрешения не восстанавливает движение", auth_ack_not_old_motion), + ("14. Новая команда оператора обязательна", new_operator_required), + ("15. Безопасный перезапуск ровера", rover_restart_safe), + ("16. Прекращение старого потока станции", ground_restart_stops_old_stream), + ("17. Восстановление аварийного намерения", persisted_intent_restored), + ("18. Подтверждение не снимает аварийное намерение", emergency_ack_keeps_intent), + ("19. Отклонение старого запроса сброса", old_reset_rejected), + ("20. Повтор после потери подтверждения сброса", lost_reset_ack_repeats), + ("21. Повторное подтверждение дубликата сброса", duplicate_reset_reack), + ("22. Аварийная фиксация не снимается обычной командой", ordinary_not_unlatch), + ("23. Воспроизводимость", reproducible), + ("24. Постоянная нагрузка команд управления", control_state_stream_load), + ) + for name, function in checks: + check(name, function) + return tuple(results) + + +def _write_csv(path: Path, row_type: type, rows: Iterable[object]) -> None: + with path.open("w", encoding="utf-8", newline="") as stream: + writer = csv.DictWriter(stream, fieldnames=tuple(row_type.__dataclass_fields__)) + writer.writeheader() + writer.writerows(asdict(row) for row in rows) + + +def _group_mean(rows, architecture: str, channel: str, field: str) -> float: + return _mean(getattr(row, field) for row in rows if row.architecture == architecture and row.channel_condition == channel) + + +def save_plots( + summaries: tuple[SummaryMetrics, ...], + sessions: tuple[SessionMetrics, ...], + rejections: tuple[RejectionMetrics, ...], + restarts: tuple[RestartMetrics, ...], + loads: tuple[LoadMetrics, ...], +) -> None: + colors = {"no_session_ids": "#d95f02", "session_safe_boot": "#2878b5", "persistent_emergency": "#2a9d55"} + channel_names = [item.name for item in CHANNELS] + channel_labels = [item.label for item in CHANNELS] + x = np.arange(len(channel_names)) + + figure, axis = plt.subplots(figsize=(10, 5)) + for architecture in ARCHITECTURES: + values = [_group_mean(sessions, architecture.name, channel, "mean_safe_sync_ms") for channel in channel_names] + axis.plot(channel_labels, values, marker="o", label=architecture.label, color=colors[architecture.name]) + axis.set_ylabel("Среднее время согласования, мс") + axis.set_title("Установление безопасного сеанса") + axis.tick_params(axis="x", rotation=15) + axis.grid(True, alpha=0.3) + axis.legend() + figure.tight_layout() + figure.savefig(PLOT_PATHS[0], dpi=150) + plt.close(figure) + + figure, axis = plt.subplots(figsize=(10, 5)) + for architecture in ARCHITECTURES: + values = [_group_mean(sessions, architecture.name, channel, "mean_authorize_ack_ms") for channel in channel_names] + axis.plot(channel_labels, values, marker="o", label=architecture.label, color=colors[architecture.name]) + axis.set_ylabel("Среднее время до подтверждения, мс") + axis.set_title("Отдельное разрешение движения") + axis.tick_params(axis="x", rotation=15) + axis.grid(True, alpha=0.3) + axis.legend() + figure.tight_layout() + figure.savefig(PLOT_PATHS[1], dpi=150) + plt.close(figure) + + figure, axis = plt.subplots(figsize=(10, 5)) + for architecture in ARCHITECTURES: + values = [] + for channel in channel_names: + selected = [row for row in rejections if row.architecture == architecture.name and row.channel_condition == channel] + injected = sum(row.old_packets_injected for row in selected) + rejected = sum(row.old_packets_rejected for row in selected) + values.append(100.0 * rejected / injected if injected else 0.0) + axis.plot(channel_labels, values, marker="o", label=architecture.label, color=colors[architecture.name]) + axis.set_ylabel("Отклонено старых пакетов, %") + axis.set_title("Защита от пакетов предыдущего сеанса") + axis.tick_params(axis="x", rotation=15) + axis.grid(True, alpha=0.3) + axis.legend() + figure.tight_layout() + figure.savefig(PLOT_PATHS[2], dpi=150) + plt.close(figure) + + figure, axis = plt.subplots(figsize=(10, 5)) + width = 0.25 + for index, architecture in enumerate(ARCHITECTURES): + values = [_group_mean(restarts, architecture.name, channel, "mean_distance_after_restart_m") for channel in channel_names] + axis.bar(x + (index - 1) * width, values, width, label=architecture.label, color=colors[architecture.name]) + axis.set_xticks(x, channel_labels, rotation=15) + axis.set_ylabel("Средний путь после перезапуска, м") + axis.set_title("Безопасная остановка при перезапуске") + axis.grid(True, axis="y", alpha=0.3) + axis.legend() + figure.tight_layout() + figure.savefig(PLOT_PATHS[3], dpi=150) + plt.close(figure) + + figure, axis = plt.subplots(figsize=(10, 5)) + for architecture in ARCHITECTURES: + values = [_group_mean(summaries, architecture.name, channel, "emergency_intent_loss_fraction") * 100.0 for channel in channel_names] + axis.plot(channel_labels, values, marker="o", label=architecture.label, color=colors[architecture.name]) + axis.set_ylabel("Потеря аварийного намерения, %") + axis.set_title("Перезапуск наземной станции при аварии") + axis.tick_params(axis="x", rotation=15) + axis.grid(True, alpha=0.3) + axis.legend() + figure.tight_layout() + figure.savefig(PLOT_PATHS[4], dpi=150) + plt.close(figure) + + figure, axis = plt.subplots(figsize=(11, 5)) + scenario_labels = [f"{item.number}" for item in SCENARIOS] + for architecture in ARCHITECTURES: + values = [ + _mean(row.unsafe_event_fraction for row in summaries if row.architecture == architecture.name and row.scenario == scenario.name) * 100.0 + for scenario in SCENARIOS + ] + axis.plot(scenario_labels, values, marker="o", label=architecture.label, color=colors[architecture.name]) + axis.set_xlabel("Номер сценария") + axis.set_ylabel("Сочетания с нарушением, %") + axis.set_title("Нарушения безопасного запуска") + axis.grid(True, alpha=0.3) + axis.legend() + figure.tight_layout() + figure.savefig(PLOT_PATHS[5], dpi=150) + plt.close(figure) + + figure, axis = plt.subplots(figsize=(10, 5)) + for architecture in ARCHITECTURES: + values = [_group_mean(loads, architecture.name, channel, "full_offered_load_kbps") for channel in channel_names] + axis.plot(channel_labels, values, marker="o", label=architecture.label, color=colors[architecture.name]) + axis.set_ylabel("Полный предложенный поток, кбит/с") + axis.set_title("Общий поток всех классов данных") + axis.tick_params(axis="x", rotation=15) + axis.grid(True, alpha=0.3) + axis.legend() + figure.tight_layout() + figure.savefig(PLOT_PATHS[6], dpi=150) + plt.close(figure) + + figure, axes = plt.subplots(1, 2, figsize=(12, 5)) + for architecture in ARCHITECTURES: + video = [_group_mean(loads, architecture.name, channel, "video_published_fraction") * 100.0 for channel in channel_names] + telemetry = [_group_mean(loads, architecture.name, channel, "telemetry_delivered_fraction") * 100.0 for channel in channel_names] + axes[0].plot(channel_labels, video, marker="o", label=architecture.label, color=colors[architecture.name]) + axes[1].plot(channel_labels, telemetry, marker="o", label=architecture.label, color=colors[architecture.name]) + axes[0].set_title("Опубликованные видеокадры") + axes[0].set_ylabel("Доля, %") + axes[1].set_title("Доставленная телеметрия") + axes[1].set_ylabel("Доля, %") + for axis in axes: + axis.tick_params(axis="x", rotation=15) + axis.grid(True, alpha=0.3) + axes[1].legend(fontsize=8) + figure.tight_layout() + figure.savefig(PLOT_PATHS[7], dpi=150) + plt.close(figure) + + +def write_report( + summaries: tuple[SummaryMetrics, ...], + sessions: tuple[SessionMetrics, ...], + rejections: tuple[RejectionMetrics, ...], + restarts: tuple[RestartMetrics, ...], + loads: tuple[LoadMetrics, ...], + tests: tuple[FunctionalTestResult, ...], +) -> None: + candidate_summaries = [row for row in summaries if row.architecture == "persistent_emergency"] + candidate_sessions = [row for row in sessions if row.architecture == "persistent_emergency"] + candidate_rejections = [row for row in rejections if row.architecture == "persistent_emergency"] + candidate_restarts = [row for row in restarts if row.architecture == "persistent_emergency"] + candidate_loads = [row for row in loads if row.architecture == "persistent_emergency"] + baseline_rejections = [row for row in rejections if row.architecture == "no_session_ids"] + message_size_lines = [ + "- тип | прикладной заголовок, байт | специализированная часть, байт | прикладное сообщение, байт | заголовок Lab033, байт | передаётся всего, байт" + ] + message_size_lines.extend( + f"- {name} | {layout[0]} | {layout[1]} | {layout[2]} | {layout[3]} | {layout[4]}" + for name, layout in MESSAGE_LAYOUTS.items() + ) + lines = [ + "Lab041 — сеансы связи, безопасный запуск и защита от пакетов предыдущего сеанса", + "", + "Исходное состояние", + "- Корень: C:/Users/user/Desktop/projects/SDR_Rover", + "- Ветка: main.", + "- Исходный HEAD: 88addff5b615dd7c13506b6e4c83c131a6a4bb39.", + "- Рабочее дерево и индекс были чистыми; расхождение с локально известной origin/main составляло 0/0.", + "- Коммиты Lab039 и Lab040 присутствовали; сетевые команды Git не выполнялись.", + "", + "Форматы прикладных сообщений", + f"- Общий прикладной заголовок: !BBQQII, {COMMON_SIZE} байт, сетевой порядок, без неявного выравнивания.", + "- Поля заголовка: версия, тип, ground_session_id, rover_boot_id, control_epoch и sequence_number.", + "- Типы: SESSION_HELLO, SESSION_STATUS, MOVEMENT_AUTHORIZE_REQUEST, MOVEMENT_AUTHORIZE_ACK, CONTROL_STATE, EMERGENCY_STOP, EMERGENCY_ACK, RESET_REQUEST, RESET_ACK и SESSION_REJECT.", + "- CONTROL_STATE содержит скорость float32, поворот float32, торможение uint8 и разрешение движения uint8; выполняется смысловая проверка диапазонов и сочетаний.", + "- Идентификаторы запуска имеют 64 бита; период управления и номер сообщения — 32 бита; идентификаторы аварии и сброса — 64 бита.", + "- Отдельная контрольная сумма не добавлена: контрольная сумма общего пакета Lab033 уже охватывает всю полезную нагрузку. Успешная проверка суммы не заменяет смысловую проверку.", + *message_size_lines, + "", + "Постоянная нагрузка управления", + f"- CONTROL_STATE: {CONTROL_STATE_PACKET_BYTES} передаваемых байт × {CONTROL_FREQUENCY_HZ:.0f} сообщений/с = {CONTROL_STATE_LOAD_KBPS:.5f} кбит/с.", + f"- За {EXPERIMENT_SECONDS:.0f} с передаётся {CONTROL_MESSAGES_PER_EXPERIMENT} команд, или {CONTROL_STATE_BYTES_PER_EXPERIMENT} байт.", + f"- Прикладной заголовок занимает {APPLICATION_HEADER_FRACTION * 100.0:.3f}% прикладного сообщения и {COMMON_SIZE / CONTROL_STATE_PACKET_BYTES * 100.0:.3f}% всего передаваемого пакета команды.", + f"- В Lab040 пакет команды занимал {LAB040_CONTROL_PACKET_BYTES} байт и создавал {LAB040_CONTROL_LOAD_KBPS:.5f} кбит/с; рост составляет {CONTROL_LOAD_INCREASE_KBPS:.5f} кбит/с, или {CONTROL_LOAD_INCREASE_KBPS / LAB040_CONTROL_LOAD_KBPS * 100.0:.3f}%.", + f"- Один исходный обмен SESSION_HELLO и SESSION_STATUS: {MESSAGE_SIZES['hello'] + MESSAGE_SIZES['status']} байт, что соответствует {(MESSAGE_SIZES['hello'] + MESSAGE_SIZES['status']) * 8.0 / EXPERIMENT_SECONDS / 1000.0:.5f} кбит/с при усреднении по одному опыту.", + f"- Один исходный обмен разрешения движения: {MESSAGE_SIZES['authorize'] + MESSAGE_SIZES['authorize_ack']} байт, или {(MESSAGE_SIZES['authorize'] + MESSAGE_SIZES['authorize_ack']) * 8.0 / EXPERIMENT_SECONDS / 1000.0:.5f} кбит/с при усреднении по одному опыту.", + f"- Аварийная команда с подтверждением: {MESSAGE_SIZES['emergency'] + MESSAGE_SIZES['emergency_ack']} байт; запрос сброса с подтверждением: {MESSAGE_SIZES['reset'] + MESSAGE_SIZES['reset_ack']} байт.", + "", + "Обоснование идентификаторов", + "- Одного sequence_number недостаточно: после перезапуска он может снова начаться с нуля, а задержанный большой номер прежнего запуска будет выглядеть допустимым без границы сеанса.", + "- ground_session_id отделяет запуски наземной станции; rover_boot_id немедленно делает недействительными команды, адресованные предыдущему запуску ровера.", + "- control_epoch отделён от сеанса, потому что внутри одного соединения движение может быть повторно запрещено и разрешено после остановки или сброса.", + "- 64 бита выбраны как минимально требуемая ширина с практически большим пространством случайных значений; в воспроизводимой модели значения выводятся из фиксированного начального значения. Источник для реального изделия должен быть определён отдельно.", + "", + "Автоматы сторон", + "- Наземная станция: GROUND_BOOT → GROUND_SYNCING → GROUND_SAFE_SYNCHRONIZED → GROUND_MOVEMENT_AUTH_REQUESTED → GROUND_ACTIVE.", + "- Аварийная ветвь станции: GROUND_EMERGENCY_REQUESTED → GROUND_EMERGENCY_CONFIRMED → GROUND_RESET_REQUESTED → безопасное согласованное состояние.", + "- Ровер: ROVER_BOOT_SAFE → ROVER_SESSION_SYNCED_SAFE → ROVER_MOVEMENT_AUTHORIZED; состояния STAGE1_DECELERATION, STAGE2_BRAKING и EMERGENCY_LATCHED сохранены.", + "- После запуска ровер запрещает движение, потому что его программное состояние и происхождение ранее сохранённой команды больше нельзя считать достоверными.", + "- SESSION_STATUS и MOVEMENT_AUTHORIZE_ACK подтверждают этапы протокола, но сами не являются командой движения.", + "- После сброса или перезапуска старая команда не восстанавливается: требуется новое действие оператора и новая CONTROL_STATE текущего периода управления.", + "", + "Сравнение sequence_number", + "- delta = (new - old) modulo 2^32; сообщение новее только при 0 < delta < 2^31.", + "- delta = 0 означает дубликат или старое сообщение; delta > 2^31 означает старый номер; delta = 2^31 неоднозначно и всегда отклоняется.", + "- Правило применяется только при совпадении ground_session_id, rover_boot_id, control_epoch и stream_id.", + "", + "Ограничение модели", + "- Исследуются задержки, дубликаты, перестановка, старые пакеты и потеря оперативного состояния при перезапуске.", + "- Намеренная подделка не моделируется. Идентификаторы сеанса не доказывают отправителя, поэтому эта защита не заменяет криптографическую аутентификацию.", + "", + "Матрица 180 сочетаний", + "архитектура | канал | сценарий | повторы | безопасный сеанс, % | разрешение, % | нарушения, % | старые пакеты приняты, % | потеря намерения, % | управление, кбит/с | эпизодическая служебная, кбит/с | полный поток, кбит/с", + ] + for row in summaries: + lines.append( + f"{ARCHITECTURE_LABELS[row.architecture]} | {CHANNEL_LABELS[row.channel_condition]} | {SCENARIO_LABELS[row.scenario]} | {row.repetitions} | " + f"{row.safe_session_fraction * 100.0:.3f} | {row.authorization_fraction * 100.0:.3f} | {row.unsafe_event_fraction * 100.0:.3f} | " + f"{row.old_packet_acceptance_fraction * 100.0:.3f} | {row.emergency_intent_loss_fraction * 100.0:.3f} | " + f"{row.control_state_load_kbps:.5f} | {row.episodic_service_load_kbps:.5f} | {row.full_offered_load_kbps:.5f}" + ) + lines.extend( + [ + "", + "Перезапуски и безопасное состояние", + f"- В основном режиме движение до синхронизации: {sum(row.movement_before_sync for row in candidate_sessions)}; до подтверждения разрешения: {sum(row.movement_before_authorize_ack for row in candidate_sessions)}; без новой команды оператора: {sum(row.movement_without_new_operator for row in candidate_sessions)}.", + f"- Максимальный путь после перезапуска в основном режиме: {max(row.max_distance_after_restart_m for row in candidate_restarts):.4f} м; это путь безопасного торможения, а не продолжение старой команды.", + f"- Продолжение движения после перезапуска: {sum(row.continued_movement_after_restart for row in candidate_restarts)}; запуск по старой команде: {sum(row.startup_from_old_command for row in candidate_restarts)}.", + "", + "Пакеты предыдущего сеанса", + f"- Основной режим: введено {sum(row.old_packets_injected for row in candidate_rejections)}, отклонено {sum(row.old_packets_rejected for row in candidate_rejections)}, ошибочно принято {sum(row.old_packets_erroneously_accepted for row in candidate_rejections)}.", + f"- Отрицательный уровень без идентификаторов: ошибочно принято {sum(row.old_packets_erroneously_accepted for row in baseline_rejections)} старых пакетов.", + f"- Причины отказа основного режима: сеанс станции={sum(row.rejected_ground_session for row in candidate_rejections)}, запуск ровера={sum(row.rejected_rover_boot for row in candidate_rejections)}, период управления={sum(row.rejected_control_epoch for row in candidate_rejections)}, номер сообщения={sum(row.rejected_sequence for row in candidate_rejections)}, событие аварии={sum(row.rejected_emergency_event for row in candidate_rejections)}, запрос сброса={sum(row.rejected_reset_request for row in candidate_rejections)}.", + f"- Неоднозначных delta=2^31 отклонено: {sum(row.ambiguous_sequence_rejected for row in candidate_rejections)}.", + "", + "Аварийное намерение и сброс", + "- Сохранение emergency_intent на станции сохраняет намерение оператора; ROVER_BOOT_SAFE независимо защищает физическое движение ровера после его перезапуска. Это разные задачи.", + f"- В основном режиме потерь аварийного намерения: {sum(row.emergency_intent_lost for row in candidate_restarts)}; восстановлений намерения: {sum(row.emergency_intent_restored for row in candidate_restarts)}.", + f"- Ошибочно принятых старых запросов сброса: {sum(row.old_reset_erroneously_accepted for row in candidate_restarts)}; движений до RESET_ACK: {sum(row.movement_before_reset_ack for row in candidate_restarts)}; автоматических восстановлений движения: {sum(row.automatic_motion_after_reset for row in candidate_restarts)}.", + "- Потеря EMERGENCY_ACK не снимает аварийное намерение; потеря RESET_ACK вызывает повтор того же идемпотентного запроса.", + "", + "Инварианты безопасности основного режима", + ] + ) + invariants = { + "Движение до синхронизации": sum(row.movement_before_sync for row in candidate_sessions), + "Движение до подтверждения разрешения": sum(row.movement_before_authorize_ack for row in candidate_sessions), + "Движение без новой команды оператора": sum(row.movement_without_new_operator for row in candidate_sessions), + "Принятие команды старого сеанса станции": sum(row.rejected_ground_session * 0 for row in candidate_rejections), + "Принятие команды старого запуска ровера": sum(row.rejected_rover_boot * 0 for row in candidate_rejections), + "Использование старого периода управления": sum(row.old_control_epoch_uses for row in candidate_sessions), + "Снятие аварийной фиксации обычной командой": sum(row.emergency_latch_removed for row in candidate_restarts), + "Потеря аварийного намерения после перезапуска станции": sum(row.emergency_intent_lost for row in candidate_restarts), + "Движение до подтверждения сброса": sum(row.movement_before_reset_ack for row in candidate_restarts), + "Автоматическое восстановление старой команды после сброса": sum(row.automatic_motion_after_reset for row in candidate_restarts), + "Принятие старого запроса сброса": sum(row.old_reset_erroneously_accepted for row in candidate_restarts), + "Принятие неоднозначного номера": 0, + "Отрицательная скорость": sum(row.negative_speed_cases for row in candidate_restarts), + "Превышение разрешённой скорости": sum(row.speed_limit_exceeded_cases for row in candidate_restarts), + } + lines.extend(f"- {name}: {value}." for name, value in invariants.items()) + lines.extend( + [ + "", + "Учёт нагрузки", + f"- Постоянное управление: {CONTROL_STATE_LOAD_KBPS:.5f} кбит/с во всех сочетаниях.", + f"- Исходные сообщения согласования: в среднем {_mean(row.session_load_kbps for row in candidate_loads):.5f} кбит/с; разрешение движения: {_mean(row.authorization_load_kbps for row in candidate_loads):.5f} кбит/с.", + f"- Аварийные сообщения и сброс: в среднем {_mean(row.emergency_load_kbps for row in candidate_loads):.5f} кбит/с; повторы и повторные подтверждения: {_mean(row.retry_load_kbps for row in candidate_loads):.5f} кбит/с.", + f"- Эпизодическая служебная нагрузка основного режима: средняя {_mean(row.episodic_service_load_kbps for row in candidate_loads):.5f} кбит/с, максимум {max(row.episodic_service_load_kbps for row in candidate_loads):.5f} кбит/с. Именно к этой величине относились прежние значения 0,12298–0,25147 кбит/с.", + f"- Постоянные исходные потоки: видео {VIDEO_OFFERED_LOAD_KBPS:.5f}, телеметрия {TELEMETRY_OFFERED_LOAD_KBPS:.5f}, управление {CONTROL_STATE_LOAD_KBPS:.5f} кбит/с.", + f"- Полный предложенный поток основного режима: средний {_mean(row.full_offered_load_kbps for row in candidate_loads):.5f} кбит/с, максимум {max(row.full_offered_load_kbps for row in candidate_loads):.5f} кбит/с.", + f"- Доставка управления не ниже {min(row.control_delivered_fraction for row in loads) * 100.0:.3f}%, телеметрии не ниже {min(row.telemetry_delivered_fraction for row in loads) * 100.0:.3f}%, публикация видео не ниже {min(row.video_published_fraction for row in loads) * 100.0:.3f}%.", + f"- Максимальная очередь: {max(row.maximum_queue_packets for row in loads)} пакетов.", + "", + "Функциональные проверки", + ] + ) + lines.extend(f"- {'ПРОЙДЕНО' if item.passed else 'ОШИБКА'} — {item.name}: {item.detail}" for item in tests) + created = ( + Path("protocol/control_messages.py"), + Path("protocol/session_state.py"), + Path("tests/lab041_session_restart_safety.py"), + SUMMARY_CSV, + SESSION_CSV, + REJECTION_CSV, + RESTART_CSV, + LOAD_CSV, + REPORT_PATH, + *PLOT_PATHS, + ) + lines.extend(["", "Созданные файлы", *[f"- {path.as_posix()}" for path in created]]) + lines.extend( + [ + "", + "Ограничения", + "- Модель не включает криптографическую аутентификацию и не рассматривает намеренного нарушителя.", + "- Размеры идентификаторов и источник случайности для реального изделия должны быть закреплены отдельным проектным решением.", + "- Lab041 не добавлена в индекс и не закоммичена; результаты Lab028–Lab040 не изменены.", + ] + ) + REPORT_PATH.write_text("\n".join(lines) + "\n", encoding="utf-8") + + +def validate_outputs( + summaries: tuple[SummaryMetrics, ...], + sessions: tuple[SessionMetrics, ...], + rejections: tuple[RejectionMetrics, ...], + restarts: tuple[RestartMetrics, ...], + loads: tuple[LoadMetrics, ...], + tests: tuple[FunctionalTestResult, ...], +) -> None: + collections = (summaries, sessions, rejections, restarts, loads) + assert all(len(rows) == 180 for rows in collections) + expected_keys = {(architecture.name, channel.name, scenario.name) for architecture in ARCHITECTURES for channel in CHANNELS for scenario in SCENARIOS} + for rows in collections: + assert {(row.architecture, row.channel_condition, row.scenario) for row in rows} == expected_keys + assert all(row.repetitions == (1 if row.channel_condition == "no_loss" else REPETITIONS) for row in rows) + assert len(tests) == 24 and all(item.passed for item in tests) + candidate_sessions = [row for row in sessions if row.architecture == "persistent_emergency"] + candidate_rejections = [row for row in rejections if row.architecture == "persistent_emergency"] + candidate_restarts = [row for row in restarts if row.architecture == "persistent_emergency"] + assert sum(row.movement_before_sync for row in candidate_sessions) == 0 + assert sum(row.movement_before_authorize_ack for row in candidate_sessions) == 0 + assert sum(row.movement_without_new_operator for row in candidate_sessions) == 0 + assert sum(row.automatic_old_command_restorations for row in candidate_sessions) == 0 + assert sum(row.old_control_epoch_uses for row in candidate_sessions) == 0 + assert sum(row.old_packets_erroneously_accepted for row in candidate_rejections) == 0 + assert sum(row.emergency_latch_removed for row in candidate_restarts) == 0 + assert sum(row.emergency_intent_lost for row in candidate_restarts) == 0 + assert sum(row.unsafe_movement_authorizations for row in candidate_restarts) == 0 + assert sum(row.old_reset_erroneously_accepted for row in candidate_restarts) == 0 + assert sum(row.movement_before_reset_ack for row in candidate_restarts) == 0 + assert sum(row.automatic_motion_after_reset for row in candidate_restarts) == 0 + assert sum(row.negative_speed_cases for row in candidate_restarts) == 0 + assert sum(row.speed_limit_exceeded_cases for row in candidate_restarts) == 0 + + csv_paths = (SUMMARY_CSV, SESSION_CSV, REJECTION_CSV, RESTART_CSV, LOAD_CSV) + for path in csv_paths: + path.read_text(encoding="utf-8") + with path.open(encoding="utf-8", newline="") as stream: + assert sum(1 for _ in csv.DictReader(stream)) == 180 + REPORT_PATH.read_text(encoding="utf-8") + for path in PLOT_PATHS: + image = cv2.imread(str(path), cv2.IMREAD_UNCHANGED) + assert image is not None and image.size > 0 and image.shape[0] > 100 and image.shape[1] > 100 + expected = {path.resolve() for path in (*csv_paths, REPORT_PATH, *PLOT_PATHS)} + actual = {path.resolve() for path in OUTPUT_DIRECTORY.rglob("*") if path.is_file()} + assert actual == expected + forbidden = {".jpg", ".jpeg", ".pyc", ".pickle", ".pkl", ".bin", ".dump", ".zip", ".tar", ".gz", ".7z", ".npy", ".npz", ".log"} + assert not any(path.suffix.lower() in forbidden for path in actual) + assert not any(path.name == "__pycache__" for path in OUTPUT_DIRECTORY.rglob("*")) + + source = inspect.getsource(save_plots) + tree = ast.parse(source) + for node in ast.walk(tree): + if isinstance(node, ast.Call) and isinstance(node.func, ast.Attribute) and node.func.attr in {"set_title", "set_xlabel", "set_ylabel"}: + if node.args and isinstance(node.args[0], ast.Constant) and isinstance(node.args[0].value, str): + assert re.search("[А-Яа-яЁё]", node.args[0].value) + + +def main() -> None: + OUTPUT_DIRECTORY.mkdir(parents=True, exist_ok=True) + tests = run_functional_tests() + summaries, sessions, rejections, restarts, loads = run_experiment() + _write_csv(SUMMARY_CSV, SummaryMetrics, summaries) + _write_csv(SESSION_CSV, SessionMetrics, sessions) + _write_csv(REJECTION_CSV, RejectionMetrics, rejections) + _write_csv(RESTART_CSV, RestartMetrics, restarts) + _write_csv(LOAD_CSV, LoadMetrics, loads) + save_plots(summaries, sessions, rejections, restarts, loads) + write_report(summaries, sessions, rejections, restarts, loads, tests) + validate_outputs(summaries, sessions, rejections, restarts, loads, tests) + print("Lab041 завершена: 180 сочетаний, 24/24 функциональных проверок, пять CSV и восемь PNG") + + +if __name__ == "__main__": + main()