opensvf 0.7.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. opensvf-0.7.0/LICENSE +17 -0
  2. opensvf-0.7.0/NOTICE +5 -0
  3. opensvf-0.7.0/PKG-INFO +386 -0
  4. opensvf-0.7.0/README.md +358 -0
  5. opensvf-0.7.0/pyproject.toml +86 -0
  6. opensvf-0.7.0/setup.cfg +4 -0
  7. opensvf-0.7.0/setup.py +2 -0
  8. opensvf-0.7.0/src/opensvf.egg-info/PKG-INFO +386 -0
  9. opensvf-0.7.0/src/opensvf.egg-info/SOURCES.txt +92 -0
  10. opensvf-0.7.0/src/opensvf.egg-info/dependency_links.txt +1 -0
  11. opensvf-0.7.0/src/opensvf.egg-info/entry_points.txt +5 -0
  12. opensvf-0.7.0/src/opensvf.egg-info/requires.txt +16 -0
  13. opensvf-0.7.0/src/opensvf.egg-info/top_level.txt +1 -0
  14. opensvf-0.7.0/src/svf/__init__.py +0 -0
  15. opensvf-0.7.0/src/svf/bus/__init__.py +0 -0
  16. opensvf-0.7.0/src/svf/bus/bus.py +231 -0
  17. opensvf-0.7.0/src/svf/bus/can.py +223 -0
  18. opensvf-0.7.0/src/svf/bus/mil1553.py +247 -0
  19. opensvf-0.7.0/src/svf/bus/py.typed +0 -0
  20. opensvf-0.7.0/src/svf/bus/spw.py +240 -0
  21. opensvf-0.7.0/src/svf/campaign/__init__.py +0 -0
  22. opensvf-0.7.0/src/svf/campaign/campaign_runner.py +401 -0
  23. opensvf-0.7.0/src/svf/campaign/cli.py +230 -0
  24. opensvf-0.7.0/src/svf/campaign/procedure.py +440 -0
  25. opensvf-0.7.0/src/svf/campaign/reporter.py +179 -0
  26. opensvf-0.7.0/src/svf/config/__init__.py +0 -0
  27. opensvf-0.7.0/src/svf/config/hardware_profile.py +100 -0
  28. opensvf-0.7.0/src/svf/config/py.typed +0 -0
  29. opensvf-0.7.0/src/svf/config/spacecraft.py +621 -0
  30. opensvf-0.7.0/src/svf/config/validator.py +261 -0
  31. opensvf-0.7.0/src/svf/config/wiring.py +265 -0
  32. opensvf-0.7.0/src/svf/core/__init__.py +0 -0
  33. opensvf-0.7.0/src/svf/core/abstractions.py +149 -0
  34. opensvf-0.7.0/src/svf/core/equipment.py +361 -0
  35. opensvf-0.7.0/src/svf/core/equipment_fault.py +162 -0
  36. opensvf-0.7.0/src/svf/core/fmu_equipment.py +176 -0
  37. opensvf-0.7.0/src/svf/core/native_equipment.py +86 -0
  38. opensvf-0.7.0/src/svf/core/py.typed +0 -0
  39. opensvf-0.7.0/src/svf/ground/__init__.py +0 -0
  40. opensvf-0.7.0/src/svf/ground/dds_sync.py +122 -0
  41. opensvf-0.7.0/src/svf/ground/py.typed +0 -0
  42. opensvf-0.7.0/src/svf/ground/yamcs_bridge.py +145 -0
  43. opensvf-0.7.0/src/svf/logging.py +95 -0
  44. opensvf-0.7.0/src/svf/models/__init__.py +0 -0
  45. opensvf-0.7.0/src/svf/models/aocs/__init__.py +0 -0
  46. opensvf-0.7.0/src/svf/models/aocs/bdot_controller.py +179 -0
  47. opensvf-0.7.0/src/svf/models/aocs/css.py +140 -0
  48. opensvf-0.7.0/src/svf/models/aocs/gps.py +181 -0
  49. opensvf-0.7.0/src/svf/models/aocs/gyroscope.py +163 -0
  50. opensvf-0.7.0/src/svf/models/aocs/magnetometer.py +154 -0
  51. opensvf-0.7.0/src/svf/models/aocs/magnetorquer.py +157 -0
  52. opensvf-0.7.0/src/svf/models/aocs/reaction_wheel.py +133 -0
  53. opensvf-0.7.0/src/svf/models/aocs/star_tracker.py +268 -0
  54. opensvf-0.7.0/src/svf/models/aocs/thruster.py +159 -0
  55. opensvf-0.7.0/src/svf/models/dhs/__init__.py +0 -0
  56. opensvf-0.7.0/src/svf/models/dhs/obc.py +465 -0
  57. opensvf-0.7.0/src/svf/models/dhs/obc_emulator.py +652 -0
  58. opensvf-0.7.0/src/svf/models/dhs/obc_stub.py +190 -0
  59. opensvf-0.7.0/src/svf/models/dynamics/__init__.py +0 -0
  60. opensvf-0.7.0/src/svf/models/dynamics/fmu/DynamicsFmu.py +67 -0
  61. opensvf-0.7.0/src/svf/models/dynamics/fmu/__init__.py +0 -0
  62. opensvf-0.7.0/src/svf/models/dynamics/kde_equipment.py +132 -0
  63. opensvf-0.7.0/src/svf/models/eps/__init__.py +0 -0
  64. opensvf-0.7.0/src/svf/models/eps/battery.py +94 -0
  65. opensvf-0.7.0/src/svf/models/eps/pcdu.py +155 -0
  66. opensvf-0.7.0/src/svf/models/eps/solar_array.py +66 -0
  67. opensvf-0.7.0/src/svf/models/thermal/__init__.py +0 -0
  68. opensvf-0.7.0/src/svf/models/thermal/thermal.py +234 -0
  69. opensvf-0.7.0/src/svf/models/ttc/__init__.py +0 -0
  70. opensvf-0.7.0/src/svf/models/ttc/sbt.py +164 -0
  71. opensvf-0.7.0/src/svf/models/ttc/ttc.py +148 -0
  72. opensvf-0.7.0/src/svf/monte_carlo.py +297 -0
  73. opensvf-0.7.0/src/svf/plugin/__init__.py +178 -0
  74. opensvf-0.7.0/src/svf/plugin/fixtures.py +278 -0
  75. opensvf-0.7.0/src/svf/plugin/observable.py +143 -0
  76. opensvf-0.7.0/src/svf/plugin/verdict.py +85 -0
  77. opensvf-0.7.0/src/svf/pus/__init__.py +0 -0
  78. opensvf-0.7.0/src/svf/pus/services.py +399 -0
  79. opensvf-0.7.0/src/svf/pus/tc.py +245 -0
  80. opensvf-0.7.0/src/svf/pus/tm.py +155 -0
  81. opensvf-0.7.0/src/svf/py.typed +0 -0
  82. opensvf-0.7.0/src/svf/sim/__init__.py +0 -0
  83. opensvf-0.7.0/src/svf/sim/obt_param_file.py +114 -0
  84. opensvf-0.7.0/src/svf/sim/py.typed +0 -0
  85. opensvf-0.7.0/src/svf/sim/replay.py +101 -0
  86. opensvf-0.7.0/src/svf/sim/simulation.py +328 -0
  87. opensvf-0.7.0/src/svf/sim/software_tick.py +105 -0
  88. opensvf-0.7.0/src/svf/srdb/__init__.py +0 -0
  89. opensvf-0.7.0/src/svf/srdb/definitions.py +221 -0
  90. opensvf-0.7.0/src/svf/srdb/loader.py +418 -0
  91. opensvf-0.7.0/src/svf/stores/__init__.py +0 -0
  92. opensvf-0.7.0/src/svf/stores/command_store.py +144 -0
  93. opensvf-0.7.0/src/svf/stores/parameter_store.py +140 -0
  94. opensvf-0.7.0/src/svf/stores/py.typed +0 -0
opensvf-0.7.0/LICENSE ADDED
@@ -0,0 +1,17 @@
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ Copyright 2026 lipofefeyt
6
+
7
+ Licensed under the Apache License, Version 2.0 (the "License");
8
+ you may not use this file except in compliance with the License.
9
+ You may obtain a copy of the License at
10
+
11
+ http://www.apache.org/licenses/LICENSE-2.0
12
+
13
+ Unless required by applicable law or agreed to in writing, software
14
+ distributed under the License is distributed on an "AS IS" BASIS,
15
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ See the License for the specific language governing permissions and
17
+ limitations under the License.
opensvf-0.7.0/NOTICE ADDED
@@ -0,0 +1,5 @@
1
+ OpenSVF
2
+ Copyright 2026 lipofefeyt
3
+
4
+ This product includes software developed by lipofefeyt.
5
+ https://github.com/lipofefeyt/opensvf
opensvf-0.7.0/PKG-INFO ADDED
@@ -0,0 +1,386 @@
1
+ Metadata-Version: 2.4
2
+ Name: opensvf
3
+ Version: 0.7.0
4
+ Summary: Open-source spacecraft software validation facility — SIL campaigns, physics-in-the-loop, HTML reports
5
+ License: Apache-2.0
6
+ Project-URL: Homepage, https://github.com/lipofefeyt/opensvf
7
+ Project-URL: Documentation, https://opensvf.readthedocs.io
8
+ Project-URL: Repository, https://github.com/lipofefeyt/opensvf
9
+ Requires-Python: >=3.10
10
+ Description-Content-Type: text/markdown
11
+ License-File: LICENSE
12
+ License-File: NOTICE
13
+ Requires-Dist: fmpy>=0.3.20
14
+ Requires-Dist: requests>=2.31
15
+ Requires-Dist: pythonfmu>=0.6
16
+ Requires-Dist: cyclonedds>=0.11
17
+ Requires-Dist: pyyaml>=6.0
18
+ Requires-Dist: pytest-timeout>=2.3
19
+ Requires-Dist: jinja2>=3.1
20
+ Provides-Extra: dev
21
+ Requires-Dist: pytest>=7.4; extra == "dev"
22
+ Requires-Dist: pytest-xdist; extra == "dev"
23
+ Requires-Dist: mypy>=1.8; extra == "dev"
24
+ Requires-Dist: types-PyYAML>=6.0; extra == "dev"
25
+ Provides-Extra: docs
26
+ Requires-Dist: mkdocs-material>=9.5; extra == "docs"
27
+ Dynamic: license-file
28
+
29
+ # OpenSVF
30
+
31
+ **Open-core spacecraft Software Validation Facility**
32
+
33
+ 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.
34
+
35
+ 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.
36
+
37
+ ---
38
+
39
+ ## What it looks like
40
+
41
+ ```
42
+ opensvf-kde (C++/Eigen3) openobsw (C11)
43
+ 6-DOF rigid body dynamics PUS S1/3/5/6/8/17/20
44
+ Euler equations b-dot detumbling
45
+ Magnetic field model ADCS PD controller
46
+ │ FDIR + watchdog
47
+ │ FMI 2.0 Co-Simulation │
48
+ ▼ ▼
49
+ OpenSVF (Python)
50
+ ┌────────────────────────────┐
51
+ │ Sensor models │ magnetometer, gyroscope,
52
+ │ (noise, bias, FDIR faults)│ star tracker, CSS, GPS, RW
53
+ │ │
54
+ │ Bus adapters │ MIL-STD-1553B, SpaceWire,
55
+ │ │ CAN 2.0B (ECSS)
56
+ │ │
57
+ │ PUS TM/TC stack │ ECSS-E-ST-70-41C
58
+ │ │
59
+ │ Campaign runner │ Procedure → verdict → HTML
60
+ └────────────────────────────┘
61
+ │ PUS TM/TC
62
+
63
+ YAMCS 5.12.6
64
+ (ground station)
65
+ ```
66
+
67
+ ---
68
+
69
+ ## Compatibility
70
+
71
+ | Package | Version | Notes |
72
+ |---|---|---|
73
+ | opensvf | v0.6.0 | Python 3.12 |
74
+ | openobsw | v0.7.0+ | C11 |
75
+ | opensvf-kde | v0.1.0 | C++ / Eigen3 |
76
+ | YAMCS | 5.12.6 | Java 21+ |
77
+
78
+ ---
79
+
80
+ ## Prerequisites
81
+
82
+ - Linux (Ubuntu 22.04+), WSL2 (Ubuntu 24.04), or GitHub Codespaces
83
+ - Python 3.11+
84
+ - Eclipse Cyclone DDS (`pip install cyclonedds`)
85
+ - Java 21+ (for YAMCS ground station)
86
+ - Docker Desktop + VS Code Dev Containers extension (for local development)
87
+
88
+ The setup script handles the rest.
89
+
90
+ ---
91
+
92
+ ## Quick start
93
+
94
+ ```bash
95
+ git clone https://github.com/lipofefeyt/opensvf
96
+ cd opensvf
97
+ pip install -e ".[dev]" # install SVF and dev dependencies
98
+
99
+ testosvf # ~453 unit + integration tests
100
+ checkcov # requirement coverage report
101
+ svf profiles # list bundled hardware profiles
102
+ svf check mission_mysat1/spacecraft.yaml
103
+ svf campaign mission_mysat1/campaigns/quickstart_campaign.yaml --report
104
+ ```
105
+
106
+ The campaign produces `results/report.html` — open it in a browser.
107
+
108
+ To start the YAMCS ground station:
109
+
110
+ ```bash
111
+ bash scripts/start-yamcs.sh # downloads YAMCS 5.12.6 if not present, starts on port 8090
112
+ ```
113
+
114
+ ---
115
+
116
+ ## Validation pyramid
117
+
118
+ OpenSVF is structured around a four-level validation pyramid:
119
+
120
+ | Level | Name | Requires | What it covers |
121
+ |---|---|---|---|
122
+ | L1 | Unit | No FMU binaries | Equipment physics, bus logic, stores, PUS packets |
123
+ | L2 | Integration | SimpleCounter.fmu | Closed-loop wiring, FmuEquipment adapter, simulation master |
124
+ | L3 | System | SpacecraftDynamics.fmu + OBSW binary | Full SIL: flight software in the loop, dynamics, PUS over YAMCS |
125
+ | L4 | Campaign | Mission spacecraft.yaml | Operator-level test procedures with HTML verdict reports |
126
+
127
+ CI runs L1 + L2 (no compiled flight software needed). L3 and L4 require the `openobsw` binary and `opensvf-kde` FMU.
128
+
129
+ ---
130
+
131
+ ## Three modes of operation
132
+
133
+ ### 1. Stub mode (unit testing, no binary)
134
+
135
+ ```yaml
136
+ # spacecraft.yaml
137
+ obsw:
138
+ type: stub
139
+ ```
140
+
141
+ 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.
142
+
143
+ ### 2. Pipe mode (host simulation, CI)
144
+
145
+ ```yaml
146
+ obsw:
147
+ type: pipe
148
+ binary: ./bin/obsw_sim # x86_64 or aarch64 via QEMU
149
+ ```
150
+
151
+ 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.
152
+
153
+ ### 3. Socket mode (Renode ZynqMP emulation)
154
+
155
+ ```yaml
156
+ obsw:
157
+ type: socket
158
+ host: localhost
159
+ port: 3456
160
+ ```
161
+
162
+ 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.
163
+
164
+ ---
165
+
166
+ ## Writing a test procedure
167
+
168
+ ```python
169
+ from svf.campaign.procedure import Procedure, ProcedureContext
170
+
171
+ class BdotConvergence(Procedure):
172
+ id = "TC-AOCS-001"
173
+ title = "B-dot detumbling convergence"
174
+ requirement = "MIS-AOCS-042"
175
+
176
+ def run(self, ctx: ProcedureContext) -> None:
177
+ self.step("Power on sensors")
178
+ ctx.inject("aocs.mag.power_enable", 1.0)
179
+ ctx.inject("aocs.gyro.power_enable", 1.0)
180
+
181
+ self.step("Monitor angular rate for 60s")
182
+ monitor = ctx.monitor("aocs.gyro.rate_x", less_than=0.5)
183
+ ctx.wait(60.0)
184
+ monitor.assert_no_violations()
185
+
186
+ self.step("Verify convergence")
187
+ ctx.assert_parameter("aocs.gyro.status", greater_than=0.5)
188
+ ```
189
+
190
+ ```yaml
191
+ # campaign.yaml
192
+ campaign: MySat-1 AOCS Validation
193
+ spacecraft: mission_mysat1/spacecraft.yaml
194
+ procedures:
195
+ - procedures/test_bdot.py
196
+ ```
197
+
198
+ ```bash
199
+ svf campaign campaign.yaml --report
200
+ ```
201
+
202
+ ---
203
+
204
+ ## Fault injection
205
+
206
+ ```python
207
+ # Star tracker stuck fault for 10 seconds
208
+ ctx.inject_equipment_fault(
209
+ "str1", "aocs.str1.quaternion_w",
210
+ fault_type="stuck", value=0.0, duration_s=10.0
211
+ )
212
+
213
+ # Magnetometer bias
214
+ ctx.inject_equipment_fault(
215
+ "mag1", "aocs.mag.field_x",
216
+ fault_type="bias", value=1e-5, duration_s=30.0
217
+ )
218
+ ```
219
+
220
+ Fault types: `stuck` | `noise` | `bias` | `scale` | `fail`
221
+
222
+ ---
223
+
224
+ ## Temporal assertions
225
+
226
+ ```python
227
+ # "Angular rate shall never exceed 0.1 rad/s during detumbling"
228
+ monitor = ctx.monitor("aocs.truth.rate_magnitude", less_than=0.1)
229
+ ctx.wait(60.0)
230
+ monitor.assert_no_violations()
231
+
232
+ result = monitor.summary()
233
+ # result.compliant, result.violations, result.min_value, result.max_value
234
+ ```
235
+
236
+ ---
237
+
238
+ ## Hardware profiles
239
+
240
+ Ten bundled profiles cover common small satellite components:
241
+
242
+ | Profile | Component |
243
+ |---|---|
244
+ | `mag_default` | Generic 3-axis magnetometer |
245
+ | `gyro_default` | Generic MEMS gyroscope |
246
+ | `rw_default` | Generic reaction wheel |
247
+ | `rw_sinclair_rw003` | Sinclair RW-003 |
248
+ | `mtq_default` | Generic magnetorquer |
249
+ | `str_default` | Generic star tracker |
250
+ | `gps_default` | Generic GPS receiver |
251
+ | `gps_novatel_oem7` | NovAtel OEM7 |
252
+ | `thr_default` | Generic thruster |
253
+ | `thr_moog_monarc_1` | Moog Monarc-1 |
254
+ | `thermal_default` | Generic thermal model |
255
+
256
+ ```bash
257
+ svf profiles # list all available
258
+ ```
259
+
260
+ ---
261
+
262
+ ## Bus adapters
263
+
264
+ | Bus | Fault injection |
265
+ |---|---|
266
+ | MIL-STD-1553B | `BUS_ERROR`, `NO_RESPONSE`, `LATE_RESPONSE`, `BAD_PARITY` |
267
+ | SpaceWire + RMAP | link error, invalid address, RMAP error codes |
268
+ | CAN 2.0B (ECSS) | bus-off, node error, bad parity |
269
+
270
+ ---
271
+
272
+ ## YAMCS ground station
273
+
274
+ OpenSVF integrates with [YAMCS 5.12.6](https://yamcs.org) as an optional ground station. The XTCE mission database is generated automatically from the SRDB.
275
+
276
+ ```bash
277
+ bash scripts/start-yamcs.sh # start YAMCS on port 8090
278
+ python3 scripts/demo_yamcs.py # run a demo TC/TM exchange
279
+ bash scripts/stop-yamcs.sh # stop YAMCS
280
+ ```
281
+
282
+ The YAMCS UI is available at `http://localhost:8090` (default credentials: `admin` / `password`).
283
+
284
+ TC pipeline: YAMCS UI → UDP port 10025 → SVF → obsw_sim
285
+ TM pipeline: obsw_sim → SVF → UDP port 10015 → YAMCS packet viewer
286
+
287
+ ---
288
+
289
+ ## Developer tools
290
+
291
+ ```bash
292
+ testosvf # full test suite (~453 tests, L1+L2)
293
+ checkosvf # mypy strict type check
294
+ svf validate spacecraft.yaml # fast pre-flight config check (no DDS, no FMU)
295
+ checkcov # requirement coverage + equipment fidelity report
296
+ checkcons # SRDB consistency: 7 checks including namespace lint
297
+ regen-xtce # regenerate YAMCS XTCE database from SRDB
298
+ ```
299
+
300
+ ---
301
+
302
+ ## Local development (WSL2 + Dev Containers)
303
+
304
+ ```bash
305
+ # Windows (PowerShell admin)
306
+ wsl --install -d Ubuntu-24.04
307
+ winget install -e --id Docker.DockerDesktop --source winget
308
+ winget install -e --id dorssel.usbipd-win --source winget
309
+
310
+ # WSL2
311
+ git clone https://github.com/lipofefeyt/opensvf ~/workspace/opensvf
312
+ git clone https://github.com/lipofefeyt/openobsw ~/workspace/openobsw
313
+ git clone https://github.com/lipofefeyt/opensvf-kde ~/workspace/opensvf-kde
314
+ code ~/workspace/opensvf # VS Code detects .devcontainer/ → Reopen in Container
315
+ ```
316
+
317
+ The dev container mounts `openobsw` and `opensvf-kde` as sibling workspaces at `/workspace/`.
318
+
319
+ ---
320
+
321
+ ## Repository layout
322
+
323
+ ```
324
+ src/svf/
325
+ ├── campaign/ CampaignRunner, Procedure, HTML reporter
326
+ ├── models/
327
+ │ ├── aocs/ magnetometer, gyroscope, star_tracker, magnetorquer,
328
+ │ │ reaction_wheel, css, bdot_controller, thruster, gps
329
+ │ ├── dynamics/ KDE FMU wrapper (6-DOF physics, external C++ project)
330
+ │ ├── eps/ solar_array, battery, pcdu (NativeEquipment factories)
331
+ │ ├── dhs/ OBCStub, OBCEmulatorAdapter (pipe + socket)
332
+ │ └── ttc/ TTC, S-band transponder
333
+ ├── bus/ MIL-STD-1553B, SpaceWire, CAN
334
+ ├── pus/ PUS-C TM/TC packet builder/parser
335
+ ├── stores/ ParameterStore, CommandStore
336
+ └── config/ SpacecraftLoader, HardwareProfile, SRDB
337
+
338
+ mission_mysat1/ Reference mission configuration
339
+ tools/ check_coverage.py, srdb_consistency_check.py, generate_xtce.py
340
+ yamcs/ YAMCS config, XTCE MDB, processor config
341
+ scripts/ start-yamcs.sh, stop-yamcs.sh, activate.sh
342
+ ```
343
+
344
+ ---
345
+
346
+ ## Related projects
347
+
348
+ | Project | What it is |
349
+ |---|---|
350
+ | [openobsw](https://github.com/lipofefeyt/openobsw) | C11 flight software: PUS stack, b-dot, ADCS PD, FDIR. Runs on MSP430, STM32H750, ZynqMP, x86_64 |
351
+ | [opensvf-kde](https://github.com/lipofefeyt/opensvf-kde) | C++ 6-DOF kinematics and dynamics engine (FMI 2.0 FMU) |
352
+
353
+ ---
354
+
355
+ ## Roadmap
356
+
357
+ | Milestone | Status |
358
+ |---|---|
359
+ | M1–M18 — Core platform, FMI, DDS sync, PUS stack, equipment models | ✅ Done |
360
+ | M19 — Spacecraft configuration DSL (YAML zero-Python entry point) | ✅ Done |
361
+ | M20 — Structured test procedure API | ✅ Done |
362
+ | M21 — Mission-level HTML reporting | ✅ Done |
363
+ | M22 — OBSW integration guide | ✅ Done |
364
+ | M23 — Temporal assertions + equipment fault engine | ✅ Done |
365
+ | M24 — ZynqMP SIL (aarch64 QEMU + Renode socket transport) | ✅ Done |
366
+ | M25 — YAMCS ground segment integration (TM/TC pipeline, XTCE MDB) | ✅ Done |
367
+ | M26 — EPS/AOCS/thermal native models + full test pyramid restructure | ✅ Done |
368
+ | M27 — Dual-OBC topology (ZynqMP + MSP430 Renode lockstep) | 🔄 Planned |
369
+ | M28 — UART/serial wire protocol transport (MSP430, STM32H750 HIL) | 🔄 Planned |
370
+ | M29 — Time-tagged parameter init file (OBT-format startup state) | ✅ Done |
371
+ | M30 — CAN 2.0B full validation + SpaceWire RMAP completion | ✅ Done |
372
+ | M31 — Equipment fidelity levels + SRDB calibration curves (raw→engineering) | ✅ Done |
373
+ | M32 — SpacecraftValidator: pre-flight config check without DDS (`svf validate`) | ✅ Done |
374
+ | M33 — SRDB namespace linting (checkcons check [7/7]) | ✅ Done |
375
+ | M34 — Equipment fidelity coverage in checkcov (F1–F4 per model, upgrade paths) | ✅ Done |
376
+ | M35 — EquipmentTickError + on_tick_error callback (record-and-continue) | ✅ Done |
377
+ | M36 — Campaign L4 scaffolding: INCONCLUSIVE verdict + declared requirements | ✅ Done |
378
+ | M37 — MySat-1 reference mission: narrative example project | ✅ Done |
379
+
380
+ ---
381
+
382
+ ## License
383
+
384
+ Apache 2.0
385
+
386
+ *Built by [lipofefeyt](https://github.com/lipofefeyt)*