Skip to content

Repository files navigation

UniSat — universal modular satellite platform

VerifyAX.25C testsPython testsLatest releaseStarsOpen issuesCoverageARMLicensePythonSTM32Platforms

Version 1.5.1 — Universal Platform (CanSat + CubeSat 1U–12U + HAB + Rocket + Drone + Rover)
Professional open-source flight software for any small-satellite class

UniSat key capabilities


60-second tour

git clone https://github.com/root3315/unisat.git &&cd unisat
./scripts/verify.sh # full green pipeline (Docker)
cp mission_templates/cubesat_3u.json mission_config.json
make target-cubesat_3u # → firmware/build-arm-cubesat_3u/cd ground-station && streamlit run app.py # → http://localhost:8501

Prefer CanSat? Replace cubesat_3u with cansat_standard. Going to a specific competition? Pick the preset that matches its rulebook — e.g. cansat_uzcansat.json for 🇺🇿 UzCanSat 2026. The firmware, flight-software, and ground-station all reconfigure themselves from mission_config.json.

Full step-by-step: docs/guides/USAGE_GUIDE.md · per-profile playbooks: docs/ops/ · full docs index: docs/README.md · mission templates: mission_templates/.


Overview

UniSat is a complete, modular flight-software platform that targets the full spectrum of student and research vehicles in a single codebase:

  • CanSat — minimal / standard / advanced (≤350 g, ≤500 g)
  • CubeSat — 1U, 1.5U, 2U, 3U, 6U, 12U
  • Suborbital rockets, high-altitude balloons, drones and rovers

The same STM32 firmware, the same Python flight controller, and the same Streamlit ground station reconfigure themselves automatically from mission_config.json. A form-factor registry enforces mass/volume/power envelopes (CDS Rev. 14 for CubeSats, ESA CanSat regulations for CanSats), and a deterministic feature-flag resolver gates every optional subsystem so the build contains only what the mission actually needs.


Обзор (Русский)

UniSat — универсальная программная платформа, которая из одного репозитория запускает:

  • CanSat — minimal / standard / advanced (≤350 г и ≤500 г);
  • CubeSat — 1U, 1.5U, 2U, 3U, 6U, 12U;
  • суборбитальные ракеты, стратосферные зонды, БПЛА и роверы.

Одна и та же прошивка STM32, один и тот же полётный контроллер на Python и одна и та же наземная станция на Streamlit сами подстраиваются под активную миссию через mission_config.json. Реестр форм-факторов проверяет массу/объём/энергетику (CDS Rev. 14 для CubeSat, правила ESA для CanSat), а детерминированный резолвер фич-флагов включает только те подсистемы, которые нужны конкретному аппарату.


🔒 What's new in v1.2.0 — TRL-5 hardening

Version 1.2.0 landed an eight-phase hardening sweep (75 commits on feat/trl5-hardening) that promotes UniSat from "competition- ready template" to TRL-5-capable software platform. Full details in CHANGELOG.md — summary:

Phase 1 — Real ARM target build

  • STM32F446RE LD script, startup.s, SystemInit/clock at 168 MHz
  • FreeRTOS kernel + CMSIS-RTOSv2 + HAL autodetect in CMake
  • make setup-all && make target produces a real .elf
  • Verified footprint: 31.6 KB flash (6 %) / 36.3 KB RAM (28 %)

Phase 2 — Security (T1 + T2 both closed)

  • T1 (injection): HMAC-SHA256 + constant-time verify
  • T2 (replay): 32-bit counter + 64-bit sliding-window bitmap
  • Persistent key store (A/B flash slots + CRC + monotonic gen)
  • Python CounterSender — thread-safe ground-side pair

Phase 3 — FDIR (NASA-style three-tier)

  • 12 fault IDs + 60s escalation window + 6-level severity ladder
  • Advisor (fdir.c) / commander (mode_manager.c) split (ADR-005)
  • Persistent fault log in .noinit SRAM — survives warm reboot

Phase 4 — Tboard + mission scenario

  • Live TMP117 reading in beacon bytes 14-15 (was zero-padded)
  • End-to-end mission lifecycle test (startup → nominal → safe → recovery) + 48-hour soak harness

Phase 5 — Quality gates

  • make cppcheck (CI-blocking) + MISRA advisory
  • make coverage85.3 % C lines
  • make sanitizers — ASAN + UBSAN clean
  • cmake -DSTRICT=ON-Werror -Wshadow -Wconversion clean

Phase 6 — Documentation (CDR-level)

  • SRS with 44 REQ + traceability CSV
  • 8 ADRs for architectural decisions
  • HIL test plan + characterization templates
  • Threat model v2 with T1+T2 closed

Phase 7 — Python + release plumbing

  • make coverage-py85.15 % Python lines (gate ≥ 80 % MUST)
  • make lint-py — mypy strict clean across 21 files
  • make sbom — auto-generated SPDX bill of materials
  • make pin-docker — release-engineering digest pin

Phase 8 — Final polish

  • ARM build fully verified end-to-end
  • Zero warnings in any build profile
  • Total tests: 27 C + 329 Python = 356 checks
  • Migrated MIT → Apache 2.0 for patent-grant protection (§3)

Test + coverage progression

Before (v1.1.0)After (v1.2.0)
C test executables1627
Python tests34329
C line coveragenot measured85.3 %
Python line coveragenot measured85.15 %
ARM target .elfnot verified6 % flash / 28 % RAM
ADRs28
Quality gates19 (all green)
LicenseMITApache 2.0

Architecture

┌─────────────────────────────────────────────────────────────┐
│ GROUND STATION (Python/Streamlit) │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌───────────────┐ │
│ │Dashboard │ │Telemetry │ │ Orbit │ │Command Center │ │
│ │ │ │ Charts │ │ Tracker │ │ (HMAC-AUTH) │ │
│ └──────────┘ └──────────┘ └──────────┘ └───────────────┘ │
└─────────────────────────┬───────────────────────────────────┘
│ UHF 437 MHz / S-band 2.4 GHz
│ AX.25 / CCSDS Protocol
┌─────────────────────────┴───────────────────────────────────┐
│ CUBESAT (1U-6U) │
│ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ FLIGHT CONTROLLER (Raspberry Pi Zero 2 W) │ │
│ │ ┌────────┐ ┌────────┐ ┌────────┐ ┌──────────────┐ │ │
│ │ │Camera │ │Orbit │ │Health │ │ Scheduler │ │ │
│ │ │Handler │ │Predict │ │Monitor │ │ (asyncio) │ │ │
│ │ └────────┘ └────────┘ └────────┘ └──────────────┘ │ │
│ └──────────────────────┬───────────────────────────────┘ │
│ │ UART │
│ ┌──────────────────────┴───────────────────────────────┐ │
│ │ OBC FIRMWARE (STM32F4 + FreeRTOS) │ │
│ │ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────────┐ │ │
│ │ │ADCS │ │EPS │ │COMM │ │GNSS │ │Telemetry │ │ │
│ │ │B-dot │ │MPPT │ │UHF │ │u-blox│ │ CCSDS │ │ │
│ │ │Sun │ │BatMgr│ │S-band│ │ │ │ │ │ │
│ │ └──────┘ └──────┘ └──────┘ └──────┘ └──────────┘ │ │
│ └──────────────────────────────────────────────────────┘ │
│ │
│ ┌────────────────────┐ ┌───────────────────────────────┐ │
│ │ SOLAR PANELS │ │ PAYLOAD (swappable) │ │
│ │ GaAs 29.5% eff. │ │ Radiation / Camera / IoT / │ │
│ │ 6 panels (3U) │ │ Magnetometer / Spectrometer │ │
│ └────────────────────┘ └───────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘

Features

SubsystemDescriptionTechnology
OBC FirmwareReal-time task management, watchdog, safe modeSTM32F4 + FreeRTOS (C)
ADCSB-dot detumbling, sun/nadir/target pointingQuaternion math, PID control
EPSMPPT solar charging, battery managementPerturb & Observe algorithm
CommunicationUHF 9600 bps + S-band 256 kbpsAX.25 v2.2 full (streaming decoder, bit-stuffing, CRC-16/X.25, §3.12 addresses) + CCSDS Space Packet + HMAC-SHA256
Flight SoftwareAsync mission control, imaging, orbit predictionPython 3.11+ asyncio
Ground Station10-page dashboard with real-time telemetryStreamlit + Plotly
SimulationOrbit, power, thermal, link budgetPython scientific stack
ConfiguratorWeb-based mission builder with validationStreamlit
Payloads5 swappable payload modulesPlugin architecture

Quick Start

1. Clone the repository

git clone https://github.com/root3315/unisat.git
cd unisat

2. Install dependencies

chmod +x scripts/setup.sh
./scripts/setup.sh

3. Run the ground station

cd ground-station
pip install -r requirements.txt
streamlit run app.py

4. Run simulation

cd simulation
pip install -r requirements.txt
python mission_analyzer.py

Подробное руководство:docs/guides/USAGE_GUIDE.md — от выбора типа миссии (CanSat / CubeSat / HAB / Rocket / Drone) до подачи на конкурс.

Что ещё можно добавить:docs/project/GAPS_AND_ROADMAP.md — честный статус, приоритизированный список открытых задач.

5. End-to-end AX.25 SITL demo (one command)

# Requires Docker Desktop running. No local gcc/cmake/pytest needed.
./scripts/verify.sh

That script builds the unisat-ci Docker image once (~30 s), then runs the full green pipeline inside it: firmware host build → ctest → pytest → end-to-end SITL beacon demo. Expected final line: ✓ UniSat green. Ready to submit.

For more granular control:

  • make all — build + tests
  • make ci — same, inside Docker
  • make demo — just the SITL beacon path
  • make test-c / make test-py — split suites
  • make help — list all targets

Project Status

TRL-5 hardening: all 6 phases on feat/trl5-hardening closed.

CheckStatus
Firmware host build (all subsystems)✅ clean (unisat_core)
Firmware target build (STM32F446RE .elf/.bin/.hex)verified: 31.6 KB flash (6%) / 36.3 KB RAM (28%) under 90% budget
C unit tests (ctest)28 / 28 passing (100+ sub-tests)
Python tests (pytest, full suite)420 passing — 262 flight-software + 82 ground-station + 57 simulation + 19 configurator
Python coverage (MUST gate)85.15 % (make coverage-py, ≥ 80 % enforced)
Streamlit page import smoke✅ 12/13 passing (1 skipped — streamlit not installed)
Universal platform (v1.3.1)✅ 14 form factors: CanSat min/std/adv + CubeSat 1U/1.5U/2U/3U/6U/12U + rocket/HAB/drone/rover/custom
SBOM (SPDX)make sbom generates docs/sbom/sbom-summary.md
FreeRTOS autodetect in CMakemake setup-freertos + make setup-all
AX.25 golden vectors cross-validation✅ 28/28 byte-identical C ↔ Python
SHA-256 FIPS 180-4 oracle"abc" + "" canonical digests
HMAC-SHA256 RFC 4231 vectors✅ §4.2 + §4.3 on both C and Python
End-to-end SITL demo✅ C encoder → TCP → Python decoder
E2E mission scenario (startup → nominal → safe)✅ flight-software/tests/test_mission_e2e.py
Long-soak harness (48 h gated via UNISAT_SOAK_SECONDS)✅ test_long_soak.py
Driver reality audit✅ all 9 drivers verified real (incl. BoardTemp)
Threat T1 (command injection)✅ HMAC dispatcher
Threat T2 (replay)✅ 32-bit counter + 64-bit sliding window
Persistent key store (A/B + CRC + rotation)✅ 10/10 tests
Boot-time key_store → dispatcher wiring in main.c✅ 4/4 integration tests
Python counter-aware HMAC frame builder (CounterSender)✅ 22/22 pytest
FDIR fault advisor + watchdog integration✅ 9/9 tests, 12 fault IDs
FDIR mode supervisor (SAFE/DEGRADED/REBOOT wiring)✅ 9/9 tests
Persistent fault log (.noinit, survives warm reboot)✅ 6/6 tests
Tboard (TMP117) facade in beacon bytes 14–15✅ 6/6 tests
cppcheck static-analysis gate✅ clean (make cppcheck)
Line coverage (C)85.3 % / functions 84.0 % (make coverage)
ASAN + UBSAN under ctest✅ 28/28 clean (make sanitizers)
STRICT mode (-Werror -Wshadow -Wconversion)✅ 28/28 clean (cmake -DSTRICT=ON)
ADRs for architectural decisions8 ADRs under docs/adr/
Full SRS + traceability CSV✅ docs/requirements/SRS.md
HIL test plan + characterization templates✅ docs/testing + docs/characterization
Requirement traceability (AX.25 subset)✅ auto-generated (docs/verification/ax25_trace_matrix.md)

Deferred (not TRL-5 blockers) — see docs/project/GAPS_AND_ROADMAP.md: Streamlit↔AX.25 live bridge, CC1125 radio config doc, MISRA backlog cleanup (~1000 Rule 8.7/10.x style deviations).

6. Build firmware manually (optional)

If you don't want to use Docker:

cd firmware
cmake -B build -S .
cmake --build build
ctest --test-dir build --output-on-failure

Cross-compile for STM32F446 (requires arm-none-eabi-gcc):

cd firmware
cmake -B build-arm -S . -DCMAKE_TOOLCHAIN_FILE=arm.cmake
cmake --build build-arm
# Output: build-arm/unisat_firmware.{elf,bin,hex}

Supported Form Factors

UniSat supported form factors

UniSat's form-factor registry is the single source of truth for every supported class. Every envelope in the tables below is enforced at runtime; each row also ships a mission template, a hardware BOM, a compile-time firmware profile, and a dedicated ops guide.

Form factorMax massDimensions (mm)ADCS tiersTypical radiosBOMOps guide
CanSat minimal350 gØ66 × 115 cyl.noneISM 433/868/915, LoRacansat_minimal.csvcansat_minimal.md
CanSat standard500 gØ68 × 80 cyl.noneISM, LoRacansat_standard.csvcansat_standard.md
CanSat advanced500 gØ68 × 115 cyl.passive-spinISM, UHF amateurcansat_advanced.csvcansat_advanced.md
CubeSat 1U2.0 kg100 × 100 × 113.5passive-magneticVHF/UHF amateurcubesat_1u.csvcubesat_1u.md
CubeSat 1.5U3.0 kg100 × 100 × 170.25magnetorquerUHF amateurcubesat_1_5u.csvcubesat_1_5u.md
CubeSat 2U4.0 kg100 × 100 × 227.0magnetorquer + sensorsUHF + optional S-bandcubesat_2u.csvcubesat_2u.md
CubeSat 3U ← TRL-5 ref6.0 kg100 × 100 × 340.5reaction wheels 3-axisUHF + S-band + X-bandcubesat_3u.csvcubesat_3u.md
CubeSat 6U12.0 kg226.3 × 100 × 366star tracker fine-pointingUHF + S + X + Kacubesat_6u.csvcubesat_6u.md
CubeSat 12U24.0 kg226.3 × 226.3 × 366star tracker + propulsionUHF + S + X + Ka + opticalcubesat_12u.csvcubesat_12u.md
Rocket payload10 kgØ100 × 300 cyl.none / passive-spinISM, UHF, S-bandrocket_avionics.md
HAB payload4 kg150 × 150 × 150noneISM, APRS, UHF amateurhab_payload.md
Small drone (UAS)5 kg500 × 500 × 200IMU attitude controlISM 2.4 GHzdrone.md

Mission templates live in mission_templates/ — copy the one you want into mission_config.json and the flight controller, firmware, and ground station all follow along. Profile-selection flowchart + trade-offs in docs/ops/README.md.

Picking a profile

# 1. Choose a template (CanSat, CubeSat 1U … 12U, rocket, HAB, drone).
cp mission_templates/cubesat_3u.json mission_config.json
# 2. Build the matching firmware image.
make target-cubesat-3u # → firmware/build-arm-cubesat-3u/# 3. Launch the flight controller and ground station — they read# mission_config.json and configure themselves automatically.cd flight-software && python3 flight_controller.py
cd ground-station && streamlit run app.py

Build every profile at once with make target-all-profiles (produces nine separate build-arm-<profile>/ trees).

Feature flags

mission_config.json accepts a top-level features block whose keys are defined in flight-software/core/feature_flags.py. The resolver combines explicit overrides with platform / form-factor / ADCS-tier / radio-band gates so the final enabled set is deterministic and logged. Examples:

"features": {
"orbit_predictor": true, // CubeSat-only → disabled for CanSat"reaction_wheels": true, // requires 2U+ and an RW tier"star_tracker": false, // explicit disable always wins"descent_controller": true, // CanSat / rocket / HAB only"parachute_pyro": true,
"s_band_radio": true// requires s_band radio configured
}

Competition Adaptation

Ready-to-submit adaptations for aerospace competitions. Detailed per-profile guides live in docs/ops/ (one file per form factor) + short form in USAGE_GUIDE.md §7.

CompetitionTemplateHighlightsOps guidePrep time
CanSat (beginner)cansat_minimal.jsonRP2040, ISM 433 MHz, ≤350 gcansat_minimal.md1 evening
🇺🇿 UzCanSat 2026 (cmspace.uz)cansat_uzcansat.json1 Hz telemetry, buzzer locator, camera 640×480 @ 30 fps — preset full compliant with cmspace.uz rulebookUZCANSAT_COMPLIANCE.md2–3 days
ESERO / national CanSatcansat_standard.jsonParachute, IMU, Ø68 × 80 mm, ≤500 gcansat_standard.md2–3 days
NASA CanSatcansat_advanced.jsonPyro deploy, camera, guided descentcansat_advanced.md1 week
CubeSat Designcubesat_3u.json3U LEO, CDR docs, HMAC authcubesat_3u.md1 week
CubeSat 6U/12U researchcubesat_6u.json / cubesat_12u.jsonX/Ka-band, propulsion slotcubesat_6u.md2–3 weeks
NASA Space AppsAny CubeSat + NDVIEarth observationcubesat_6u.md48 h
IREC / SA Cup rocketrocket_competition.jsonDual-deploy, HMAC telemetryrocket_avionics.md2–3 days
HAB flighthab_standard.jsonGNSS + camerahab_payload.md1 day
UAV surveydrone_survey.jsonMission plannerdrone.md1–2 days

Also: COMPETITION_GUIDE.md (short form), docs/ops/README.md (profile-selection flowchart).


Project Structure

unisat/
├── firmware/ # STM32F446 firmware (C11 + FreeRTOS)
│ ├── stm32/Core/ # OBC, COMM, GNSS, CCSDS, telemetry,
│ │ # command_dispatcher (HMAC-auth)
│ ├── stm32/Drivers/ # 9 sensor drivers + AX25 + Crypto +
│ │ # VirtualUART (SITL TCP shim)
│ ├── stm32/ADCS/ # B-dot, quaternion, sun/target pointing
│ ├── stm32/EPS/ # MPPT, battery manager
│ └── tests/ # 28 Unity test targets
├── flight-software/ # Python async flight controller (RPi Zero 2 W)
│ ├── core/ # form_factors.py, feature_flags.py, mission_types.py
│ └── tests/ # 262 pytest incl. e2e + soak + hypothesis
├── ground-station/ # Streamlit UI + AX.25 CLI + HMAC tooling
│ ├── utils/ax25.py # AX.25 v2.2 Python mirror
│ ├── utils/hmac_auth.py# HMAC-SHA256 mirror (RFC 4231)
│ ├── utils/profile_gate.py # hides orbit/image/ADCS pages by profile
│ ├── cli/ # ax25_listen / ax25_send TCP tools
│ └── tests/ # 82 pytest incl. hypothesis + fuzz
├── simulation/ # 10 simulators (orbit, power, thermal, link) — 57 tests
├── configurator/ # Web-based mission configurator + BOM gen — 19 tests
├── hardware/
│ ├── bom/by_form_factor/ # 7 per-class BOMs with real masses
│ └── kicad/ # 4 KiCad boards (OBC, EPS, Comm, Sensor)
├── payloads/ # 5 swappable payload templates
├── mission_templates/ # 8 ready-to-use presets (CanSat min/std/adv + CubeSat 1U-12U)
├── tests/golden/ # Shared AX.25 test vectors (C + Python)
├── docs/ # 25+ md docs (USAGE_GUIDE, TECHNICAL_DOC,
│ # ADRs, threat model, tutorials, verification)
├── docker/Dockerfile.ci # Reusable CI image (cmake + pytest baked)
├── scripts/verify.sh # One-command reproducibility
├── Makefile # make all / test / demo / ci / help
├── CHANGELOG.md # Semantic-versioned history
└── README.md # This file

Documentation

Full index:docs/README.md — every doc in the repo, grouped by purpose.

Start here

Per-profile operations guides (docs/ops/)

One file per form factor covering setup → build → bench test → flight → post-flight:

Design & architecture (docs/design/)

Quantitative budgets (docs/budgets/, 3U reference)

Per-profile envelopes (mass / volume / power) are in flight-software/core/form_factors.py; per-class BOMs are under hardware/bom/by_form_factor/.

Reference (docs/reference/)

Architecture decisions (docs/adr/ — 8 ADRs)

Hardware (docs/hardware/)

Verification, testing, reliability

Project state & regulatory (docs/project/)

Tutorials, operations, SBOM, diagrams

Contributing & security


Testing

One command:

./scripts/verify.sh # Docker-based, no local toolchain needed

Via Makefile:

make all # build + test (C + Python)
make test-c # ctest only (28 targets, 100+ sub-tests)
make test-py # pytest only (420 tests across all 4 Python packages)
make demo # end-to-end SITL AX.25 beacon demo
make help# list all targets

Quality gates:

# C firmware
make cppcheck # static-analysis gate (zero issues)
make cppcheck-strict # + MISRA-C:2012 advisory report
make coverage # lcov html report (85.3 % lines)
make sanitizers # ASAN + UBSAN under ctest# Python
make coverage-py # pytest + coverage (≥ 50 % MUST gate, 80 % SHOULD)
make lint-py # mypy type check on flight-software# supply-chain
make sbom # SPDX bill-of-materials under docs/sbom/

STM32 target (Phase 1):

make setup-all # fetch STM32Cube HAL + FreeRTOS kernel (one-time)
make target # cross-compile .elf / .bin / .hex
make size # per-section flash / RAM usage
make flash # st-flash to Nucleo-F446RE

Manual:

cd firmware && cmake -B build -S .&& cmake --build build
ctest --test-dir build --output-on-failure
cd ../ground-station && python -m pytest tests/test_ax25.py -v

Contributing

See CONTRIBUTING.md for guidelines on how to contribute to UniSat.


License

This project is licensed under the Apache License, Version 2.0 — see LICENSE and NOTICE for the full terms and the third-party attribution summary.

License history: the project was initially published under MIT (2026-02-15 — 2026-04-18) and migrated to Apache-2.0 on 2026-04-18 for its patent-grant clause (§3) and the defensive-termination language (retaliation against a patent suit terminates the aggressor's patent licence). Copies obtained during the MIT window stay MIT-licensed; new releases from 2026-04-18 onward are Apache-2.0 only.


Acknowledgments

  • CCSDS (Consultative Committee for Space Data Systems) for protocol standards
  • FreeRTOS for the real-time operating system
  • SGP4 algorithm authors for orbit prediction
  • CubeSat Design Specification (CalPoly) for mechanical standards

About

🛰️ Universal satellite software platform — CanSat, CubeSat 1U-12U, HAB, rocket, drone. One codebase → 14 form factors. 471 tests green, TRL-5 hardened.

Topics

Resources

Contributing

Security policy

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages