Skip to main content

Open-source spacecraft software validation facility — SIL campaigns, physics-in-the-loop, HTML reports

Project description

OpenSVF

Open-core spacecraft Software Validation Facility

OpenSVF is a Python-based platform for validating spacecraft flight software against a 6-DOF physics engine and a real PUS ground station. It is aimed at small satellite teams who write flight software in C and need a structured, traceable way to test it before hardware integration.

The core idea: your flight software binary runs inside the SVF. The SVF feeds it sensor data from a physics simulation, receives its actuator commands, closes the loop, and records everything. You write test procedures in Python that send telecommands and assert on telemetry. At the end you get an HTML campaign report with a requirement traceability matrix.


What it looks like

opensvf-kde (C++/Eigen3)        openobsw (C11)
  6-DOF rigid body dynamics        PUS S1/3/5/6/8/17/20
  Euler equations                  b-dot detumbling
  Magnetic field model             ADCS PD controller
        │                          FDIR + watchdog
        │  FMI 2.0 Co-Simulation         │
        ▼                                ▼
              OpenSVF (Python)
         ┌────────────────────────────┐
         │  Sensor models             │  magnetometer, gyroscope,
         │  (noise, bias, FDIR faults)│  star tracker, CSS, GPS, RW
         │                            │
         │  Bus adapters              │  MIL-STD-1553B, SpaceWire,
         │                            │  CAN 2.0B (ECSS)
         │                            │
         │  PUS TM/TC stack           │  ECSS-E-ST-70-41C
         │                            │
         │  Campaign runner           │  Procedure → verdict → HTML
         └────────────────────────────┘
                    │ PUS TM/TC
                    ▼
             YAMCS 5.12.6
          (ground station)

Compatibility

Package Version Notes
opensvf v0.6.0 Python 3.12
openobsw v0.7.0+ C11
opensvf-kde v0.1.0 C++ / Eigen3
YAMCS 5.12.6 Java 21+

Prerequisites

  • Linux (Ubuntu 22.04+), WSL2 (Ubuntu 24.04), or GitHub Codespaces
  • Python 3.11+
  • Eclipse Cyclone DDS (pip install cyclonedds)
  • Java 21+ (for YAMCS ground station)
  • Docker Desktop + VS Code Dev Containers extension (for local development)

The setup script handles the rest.


Quick start

git clone https://github.com/lipofefeyt/opensvf
cd opensvf
pip install -e ".[dev]"                                           # install SVF and dev dependencies

testosvf                                                          # ~453 unit + integration tests
checkcov                                                          # requirement coverage report
svf profiles                                                      # list bundled hardware profiles
svf check mission_mysat1/spacecraft.yaml
svf campaign mission_mysat1/campaigns/quickstart_campaign.yaml --report

The campaign produces results/report.html — open it in a browser.

To start the YAMCS ground station:

bash scripts/start-yamcs.sh     # downloads YAMCS 5.12.6 if not present, starts on port 8090

Validation pyramid

OpenSVF is structured around a four-level validation pyramid:

Level Name Requires What it covers
L1 Unit No FMU binaries Equipment physics, bus logic, stores, PUS packets
L2 Integration SimpleCounter.fmu Closed-loop wiring, FmuEquipment adapter, simulation master
L3 System SpacecraftDynamics.fmu + OBSW binary Full SIL: flight software in the loop, dynamics, PUS over YAMCS
L4 Campaign Mission spacecraft.yaml Operator-level test procedures with HTML verdict reports

CI runs L1 + L2 (no compiled flight software needed). L3 and L4 require the openobsw binary and opensvf-kde FMU.


Three modes of operation

1. Stub mode (unit testing, no binary)

# spacecraft.yaml
obsw:
  type: stub

The OBC is replaced by a rule-based stub. All sensors and actuators run. Use this for rapid iteration on test procedures before you have a flight binary.

2. Pipe mode (host simulation, CI)

obsw:
  type: pipe
  binary: ./bin/obsw_sim        # x86_64 or aarch64 via QEMU

The real flight software binary runs as a subprocess. SVF feeds it sensor frames over stdin/stdout using wire protocol v3. This is the primary SIL validation mode and runs in CI with no special hardware.

3. Socket mode (Renode ZynqMP emulation)

obsw:
  type: socket
  host: localhost
  port: 3456

The flight software runs inside Renode emulating a ZynqMP Cortex-A53. SVF connects to the Renode UART terminal over TCP. Same wire protocol — the flight binary never knows the difference.


Writing a test procedure

from svf.campaign.procedure import Procedure, ProcedureContext

class BdotConvergence(Procedure):
    id          = "TC-AOCS-001"
    title       = "B-dot detumbling convergence"
    requirement = "MIS-AOCS-042"

    def run(self, ctx: ProcedureContext) -> None:
        self.step("Power on sensors")
        ctx.inject("aocs.mag.power_enable", 1.0)
        ctx.inject("aocs.gyro.power_enable", 1.0)

        self.step("Monitor angular rate for 60s")
        monitor = ctx.monitor("aocs.gyro.rate_x", less_than=0.5)
        ctx.wait(60.0)
        monitor.assert_no_violations()

        self.step("Verify convergence")
        ctx.assert_parameter("aocs.gyro.status", greater_than=0.5)
# campaign.yaml
campaign: MySat-1 AOCS Validation
spacecraft: mission_mysat1/spacecraft.yaml
procedures:
  - procedures/test_bdot.py
svf campaign campaign.yaml --report

Fault injection

# Star tracker stuck fault for 10 seconds
ctx.inject_equipment_fault(
    "str1", "aocs.str1.quaternion_w",
    fault_type="stuck", value=0.0, duration_s=10.0
)

# Magnetometer bias
ctx.inject_equipment_fault(
    "mag1", "aocs.mag.field_x",
    fault_type="bias", value=1e-5, duration_s=30.0
)

Fault types: stuck | noise | bias | scale | fail


Temporal assertions

# "Angular rate shall never exceed 0.1 rad/s during detumbling"
monitor = ctx.monitor("aocs.truth.rate_magnitude", less_than=0.1)
ctx.wait(60.0)
monitor.assert_no_violations()

result = monitor.summary()
# result.compliant, result.violations, result.min_value, result.max_value

Hardware profiles

Ten bundled profiles cover common small satellite components:

Profile Component
mag_default Generic 3-axis magnetometer
gyro_default Generic MEMS gyroscope
rw_default Generic reaction wheel
rw_sinclair_rw003 Sinclair RW-003
mtq_default Generic magnetorquer
str_default Generic star tracker
gps_default Generic GPS receiver
gps_novatel_oem7 NovAtel OEM7
thr_default Generic thruster
thr_moog_monarc_1 Moog Monarc-1
thermal_default Generic thermal model
svf profiles          # list all available

Bus adapters

Bus Fault injection
MIL-STD-1553B BUS_ERROR, NO_RESPONSE, LATE_RESPONSE, BAD_PARITY
SpaceWire + RMAP link error, invalid address, RMAP error codes
CAN 2.0B (ECSS) bus-off, node error, bad parity

YAMCS ground station

OpenSVF integrates with YAMCS 5.12.6 as an optional ground station. The XTCE mission database is generated automatically from the SRDB.

bash scripts/start-yamcs.sh     # start YAMCS on port 8090
python3 scripts/demo_yamcs.py   # run a demo TC/TM exchange
bash scripts/stop-yamcs.sh      # stop YAMCS

The YAMCS UI is available at http://localhost:8090 (default credentials: admin / password).

TC pipeline: YAMCS UI → UDP port 10025 → SVF → obsw_sim TM pipeline: obsw_sim → SVF → UDP port 10015 → YAMCS packet viewer


Developer tools

testosvf                              # full test suite (~453 tests, L1+L2)
checkosvf                             # mypy strict type check
svf validate spacecraft.yaml          # fast pre-flight config check (no DDS, no FMU)
checkcov                              # requirement coverage + equipment fidelity report
checkcons                             # SRDB consistency: 7 checks including namespace lint
regen-xtce                            # regenerate YAMCS XTCE database from SRDB

Local development (WSL2 + Dev Containers)

# Windows (PowerShell admin)
wsl --install -d Ubuntu-24.04
winget install -e --id Docker.DockerDesktop --source winget
winget install -e --id dorssel.usbipd-win --source winget

# WSL2
git clone https://github.com/lipofefeyt/opensvf ~/workspace/opensvf
git clone https://github.com/lipofefeyt/openobsw ~/workspace/openobsw
git clone https://github.com/lipofefeyt/opensvf-kde ~/workspace/opensvf-kde
code ~/workspace/opensvf   # VS Code detects .devcontainer/ → Reopen in Container

The dev container mounts openobsw and opensvf-kde as sibling workspaces at /workspace/.


Repository layout

src/svf/
├── campaign/       CampaignRunner, Procedure, HTML reporter
├── models/
│   ├── aocs/       magnetometer, gyroscope, star_tracker, magnetorquer,
│   │               reaction_wheel, css, bdot_controller, thruster, gps
│   ├── dynamics/   KDE FMU wrapper (6-DOF physics, external C++ project)
│   ├── eps/        solar_array, battery, pcdu  (NativeEquipment factories)
│   ├── dhs/        OBCStub, OBCEmulatorAdapter (pipe + socket)
│   └── ttc/        TTC, S-band transponder
├── bus/            MIL-STD-1553B, SpaceWire, CAN
├── pus/            PUS-C TM/TC packet builder/parser
├── stores/         ParameterStore, CommandStore
└── config/         SpacecraftLoader, HardwareProfile, SRDB

mission_mysat1/     Reference mission configuration
tools/              check_coverage.py, srdb_consistency_check.py, generate_xtce.py
yamcs/              YAMCS config, XTCE MDB, processor config
scripts/            start-yamcs.sh, stop-yamcs.sh, activate.sh

Related projects

Project What it is
openobsw C11 flight software: PUS stack, b-dot, ADCS PD, FDIR. Runs on MSP430, STM32H750, ZynqMP, x86_64
opensvf-kde C++ 6-DOF kinematics and dynamics engine (FMI 2.0 FMU)

Roadmap

Milestone Status
M1–M18 — Core platform, FMI, DDS sync, PUS stack, equipment models ✅ Done
M19 — Spacecraft configuration DSL (YAML zero-Python entry point) ✅ Done
M20 — Structured test procedure API ✅ Done
M21 — Mission-level HTML reporting ✅ Done
M22 — OBSW integration guide ✅ Done
M23 — Temporal assertions + equipment fault engine ✅ Done
M24 — ZynqMP SIL (aarch64 QEMU + Renode socket transport) ✅ Done
M25 — YAMCS ground segment integration (TM/TC pipeline, XTCE MDB) ✅ Done
M26 — EPS/AOCS/thermal native models + full test pyramid restructure ✅ Done
M27 — Dual-OBC topology (ZynqMP + MSP430 Renode lockstep) 🔄 Planned
M28 — UART/serial wire protocol transport (MSP430, STM32H750 HIL) 🔄 Planned
M29 — Time-tagged parameter init file (OBT-format startup state) ✅ Done
M30 — CAN 2.0B full validation + SpaceWire RMAP completion ✅ Done
M31 — Equipment fidelity levels + SRDB calibration curves (raw→engineering) ✅ Done
M32 — SpacecraftValidator: pre-flight config check without DDS (svf validate) ✅ Done
M33 — SRDB namespace linting (checkcons check [7/7]) ✅ Done
M34 — Equipment fidelity coverage in checkcov (F1–F4 per model, upgrade paths) ✅ Done
M35 — EquipmentTickError + on_tick_error callback (record-and-continue) ✅ Done
M36 — Campaign L4 scaffolding: INCONCLUSIVE verdict + declared requirements ✅ Done
M37 — MySat-1 reference mission: narrative example project ✅ Done

License

Apache 2.0

Built by lipofefeyt

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

opensvf-0.7.1.tar.gz (125.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

opensvf-0.7.1-py3-none-any.whl (165.3 kB view details)

Uploaded Python 3

File details

Details for the file opensvf-0.7.1.tar.gz.

File metadata

  • Download URL: opensvf-0.7.1.tar.gz
  • Upload date:
  • Size: 125.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for opensvf-0.7.1.tar.gz
Algorithm Hash digest
SHA256 b56645756adc67ff47c9f8c0291bf6f11545a28f65ef14ac609ac7c624ebaa4b
MD5 645425c4b60caeeaa73653f5fc7b9934
BLAKE2b-256 c693f04de09124a9a892a5c8aad5c25f9835dcdedaf72f7509bdeaa8f403981c

See more details on using hashes here.

Provenance

The following attestation bundles were made for opensvf-0.7.1.tar.gz:

Publisher: publish.yml on lipofefeyt/opensvf

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file opensvf-0.7.1-py3-none-any.whl.

File metadata

  • Download URL: opensvf-0.7.1-py3-none-any.whl
  • Upload date:
  • Size: 165.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for opensvf-0.7.1-py3-none-any.whl
Algorithm Hash digest
SHA256 ccaedaa4abda9dbb4fd0ff7865f42679b979f34f49e54f370671c9b02c87bd7d
MD5 dae6ee705c1e555261238c8a386f9010
BLAKE2b-256 2efabd7f38e064eb561bf78f08a6d954fe98b061d9508583f10b246ffe8b032e

See more details on using hashes here.

Provenance

The following attestation bundles were made for opensvf-0.7.1-py3-none-any.whl:

Publisher: publish.yml on lipofefeyt/opensvf

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page