Регламент CanSat (п. 3) штрафует на −20 баллов за «отсутствие ключевых данных после миссии». Этот документ фиксирует что именно считается ключевыми данными и где они хранятся в трёх независимых местах.
После миссии судьи получают три артефакта:
flight_<YYYYMMDD_HHMMSS>.csv — полная телеметрия с SD-карты борта (950 строк × 16 полей).radiation_profile_<YYYYMMDD>.csv — научный результат: высота → мощность дозы + ошибка.ground_capture.pcap — все принятые с борта LoRa-пакеты (для cross-validation).Если любой из трёх присутствует — ключевые данные считаются полученными. Тройное резервирование гарантирует, что хотя бы один источник переживёт любой частный сбой (потеря аппарата → CSV недоступен, но есть PCAP; потеря радио → PCAP пуст, но SD читаем; ошибка пост-обработки → сырой CSV всегда можно переразобрать).
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 юнит-тестах).
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). Это тот деливерабл, который команда защищает перед жюри. |
ground_capture.pcap (приёмник)LoRa-приёмник на ground-station пишет все входящие фреймы в PCAP с custom linktype:
Может быть прочитан scripts/replay_ground_capture.py → генерирует тот же CSV что на борту.
Минимальный пакет, который должен дойти до земли даже при частичных сбоях:
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:
phase_id — где аппарат в цикле.altitude_m — высотный профиль сырой.sbm20_rate — научный показатель в эфире real-time.gnss_lat/lon — recovery координаты.При потере радио — всё это есть на SD (см. §2).
# 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/
Файл baseline_sitl_dataset.csv — это эталонный результат SITL-симуляции тех же 95 с полёта. Если реальная миссия провалится полностью (нет SD, нет PCAP, нет CSV), команда представляет baseline как:
«Мы заранее проверили, что наш pipeline готов обработать именно такие данные — вот результат на эталонном полёте. К сожалению, реальные данные потеряны из-за [причина]. Наш пост-обработчик даёт корректный radiation_profile CSV из любого валидного flight CSV — что доказывает работоспособность ПО.»
Это не заменяет реальные данные в строгом смысле регламента (штраф всё равно возможен), но демонстрирует что ПО готово и работает — что судьи часто зачитывают в частичный зачёт.
Регламент CanSat, п. 3 штрафует на −20 за «отсутствие ключевых данных после миссии». Наш подход:
tools/playground.py → теряем 15–20 но тот же продукт.Вывод: формат ключевых данных зафиксирован, pipeline реализован и протестирован, есть резервный SITL-baseline. Штраф −20 неконстантный: при любом сценарии с хотя бы частичным успехом мы теряем не более 10.
Связанные документы:
CDR.md — общий CDR аппаратаSCIENCE_MISSION.md — научная задачаbaseline_sitl_dataset.csv — эталон SITL-полёта