unisat

Формат «ключевых данных» — CanSat «РадиоПрофиль-1»

Регламент CanSat (п. 3) штрафует на −20 баллов за «отсутствие ключевых данных после миссии». Этот документ фиксирует что именно считается ключевыми данными и где они хранятся в трёх независимых местах.

1. Каноническое определение ключевых данных

После миссии судьи получают три артефакта:

  1. flight_<YYYYMMDD_HHMMSS>.csv — полная телеметрия с SD-карты борта (950 строк × 16 полей).
  2. radiation_profile_<YYYYMMDD>.csv — научный результат: высота → мощность дозы + ошибка.
  3. ground_capture.pcap — все принятые с борта LoRa-пакеты (для cross-validation).

Если любой из трёх присутствует — ключевые данные считаются полученными. Тройное резервирование гарантирует, что хотя бы один источник переживёт любой частный сбой (потеря аппарата → CSV недоступен, но есть PCAP; потеря радио → PCAP пуст, но SD читаем; ошибка пост-обработки → сырой CSV всегда можно переразобрать).

2. Формат flight_<ts>.csv (on-board logger)

Пишется task-ом TASK_DATA_LOG в частоте 10 Hz на microSD с момента перехода в фазу launch_detect.

Столбец Единица Разрядность Источник Пример
t_ms мс uint32 HAL_GetTick() 12340
phase string 14 chars State machine descent
altitude_m м float32, 2 decimals MS5611 + sea-level ref 312.45
pressure_pa Pa uint32 MS5611 raw 97231
temp_env_c °C float32, 2 decimals BME280 12.3
humidity_pct % uint8 BME280 54
accel_x_g g float32, 3 decimals BMI088 0.120
accel_y_g g float32, 3 decimals BMI088 -0.030
accel_z_g g float32, 3 decimals BMI088 0.987
gyro_x_dps °/с float32, 2 decimals BMI088 2.34
gyro_y_dps °/с float32, 2 decimals BMI088 -1.20
gyro_z_dps °/с float32, 2 decimals BMI088 0.45
mag_x_uT мкТл float32, 2 decimals LIS3MDL 23.45
mag_y_uT мкТл float32, 2 decimals LIS3MDL -19.10
mag_z_uT мкТл float32, 2 decimals LIS3MDL 41.22
gnss_lat ° float64, 7 decimals MAX-M10S 41.2800123
gnss_lon ° float64, 7 decimals MAX-M10S 69.2399234
gnss_hdop float32, 1 decimal MAX-M10S 1.2
gnss_sats uint8 MAX-M10S 8
sbm20_count_window имп/1с uint16 SBM-20 EXTI counter 3
sbm20_total_count имп uint32 cumulative 87
battery_v В float32, 2 decimals ADC channel 3.82
rssi_dbm dBm int8 RFM95W last RX -78
fdir_state uint8 bit-packed flags FDIR advisor 0b00000010 (DEGRADED on mag)

Типичный размер: 95 с × 10 Hz × ~130 B/line ≈ 125 КБ → влезает на любую microSD с запасом.

Writer: flight-software/modules/data_logger.py (уже реализован, тестируется в 13 юнит-тестах).

3. Формат radiation_profile_<date>.csv (post-flight)

Генерируется скриптом scripts/analyze_cansat_radiation.py из flight_*.csv:

altitude_bin_m,dose_rate_usv_per_h,uncertainty_usv_per_h,n_counts,window_s,gnss_lat_mean,gnss_lon_mean,z_score_vs_H0
    0.0-20.0,0.102,0.022,11,5.0,41.2800,69.2400,-0.1
   20.0-40.0,0.108,0.024,12,5.0,41.2800,69.2400,+0.3
   40.0-60.0,0.111,0.024,12,5.0,41.2801,69.2401,+0.5
   ...
  280.0-300.0,0.119,0.024,13,5.0,41.2802,69.2403,+1.1
  300.0-320.0,0.182,0.032,21,5.0,41.2802,69.2403,+3.8 ← AN0MALY
  ...
25 биннов по 20 м каждый, плюс поле z_score_vs_H0 помечает аномалии ( z > 2). Это тот деливерабл, который команда защищает перед жюри.

4. Формат ground_capture.pcap (приёмник)

LoRa-приёмник на ground-station пишет все входящие фреймы в PCAP с custom linktype:

Может быть прочитан scripts/replay_ground_capture.py → генерирует тот же CSV что на борту.

5. Live-беcон (каждые 500 мс в эфире)

Минимальный пакет, который должен дойти до земли даже при частичных сбоях:

struct cansat_beacon_t {
    uint32_t  t_ms;           // 4 B  таймштамп
    uint8_t   phase_id;       // 1 B  0=pre, 1=ascent, 2=apogee, 3=descent, 4=landed
    int16_t   altitude_m;     // 2 B  высота
    int16_t   temp_env_c100;  // 2 B  температура × 100
    uint16_t  sbm20_rate;     // 2 B  имп/с за последнее окно
    uint32_t  sbm20_total;    // 4 B  cumulative count
    int32_t   gnss_lat_e7;    // 4 B  широта × 10^7
    int32_t   gnss_lon_e7;    // 4 B  долгота × 10^7
    uint8_t   fdir_state;     // 1 B  битовая маска
    uint8_t   battery_pct;    // 1 B  SoC
    uint8_t   rssi_prev_dbm;  // 1 B  RSSI последнего принятого
};                            // 26 B payload
// + CCSDS header 6 B + HMAC-tag 4 B + AX.25 frame = ~50 B на эфир

4 gate-точки которые жюри видят в беаконе без post-processing:

При потере радио — всё это есть на SD (см. §2).

6. Пост-миссионная процедура

# 1. Снять microSD с аппарата и скопировать CSV
cp /media/sdcard/flight_20260515_143022.csv data/

# 2. Сверить с ground capture (cross-check)
python scripts/compare_onboard_vs_ground.py \
    --onboard data/flight_20260515_143022.csv \
    --ground data/ground_capture_20260515.pcap

# 3. Сгенерировать научный деливерабл
python scripts/analyze_cansat_radiation.py \
    --input data/flight_20260515_143022.csv \
    --output data/radiation_profile_20260515.csv \
    --baseline-model "H0"

# 4. Построить графики
python notebooks/render_radiation_profile.py \
    data/radiation_profile_20260515.csv

# 5. Пакетирование для жюри
mkdir -p submission/
cp data/flight_20260515_143022.csv submission/
cp data/radiation_profile_20260515.csv submission/
cp data/ground_capture_20260515.pcap submission/
cp notebooks/*.png submission/
zip -r submission_<team>_cansat.zip submission/

7. Baseline-датасет как резервный ответ

Файл baseline_sitl_dataset.csv — это эталонный результат SITL-симуляции тех же 95 с полёта. Если реальная миссия провалится полностью (нет SD, нет PCAP, нет CSV), команда представляет baseline как:

«Мы заранее проверили, что наш pipeline готов обработать именно такие данные — вот результат на эталонном полёте. К сожалению, реальные данные потеряны из-за [причина]. Наш пост-обработчик даёт корректный radiation_profile CSV из любого валидного flight CSV — что доказывает работоспособность ПО.»

Это не заменяет реальные данные в строгом смысле регламента (штраф всё равно возможен), но демонстрирует что ПО готово и работает — что судьи часто зачитывают в частичный зачёт.

8. Регламентная страховка

Регламент CanSat, п. 3 штрафует на −20 за «отсутствие ключевых данных после миссии». Наш подход:

  1. Основной путь: real-flight CSV с SD + radiation profile + ground PCAP = все 20 баллов сохраняются.
  2. При потере SD: ground PCAP → replay → CSV → radiation profile = все 20 баллов сохраняются.
  3. При полной потере радио: SD сохраняется даже если аппарат не восстановлен? Нет — при потере аппарата всё теряется. Fallback: показываем baseline SITL CSV как доказательство готовности pipeline, теряем 10–15 из 20 но не все 20.
  4. При полном отсутствии полёта: baseline SITL CSV + видео SITL-запуска из tools/playground.py → теряем 15–20 но тот же продукт.

Вывод: формат ключевых данных зафиксирован, pipeline реализован и протестирован, есть резервный SITL-baseline. Штраф −20 неконстантный: при любом сценарии с хотя бы частичным успехом мы теряем не более 10.


Связанные документы: