Skip to content

Commit b947f83

Browse files
rfonodclaude
andcommitted
Revamp repository presentation and fix Monte Carlo defects
Documentation: - Rewrite README with badges, hero figure, usage, results, and limitations - Add THIRD_PARTY.md attributing the bundled File Exchange functions and the NRLMSISE-00 model - Add .zenodo.json and update CITATION.cff (software + preferred citation) - Document that the weighted B-dot law of the paper lives in main_old.m (C_type = 1), not in the current main.m - Add assets/ with the Monte Carlo result figure and its generator Fixes: - run_mc.m called the non-existent main_new(); call main() instead - main.m packed the 3 x N_orb magnetorquer on-time matrix into N_orb rows, which errored in Monte Carlo mode; pack all 3*N_orb values, matching the layout Eval_MC_results.m decodes (same fix in Future/main.m) - main.m now accepts an optional N_orb argument so run_mc.m and main.m cannot disagree on the simulation horizon - Eval_MC_results.m used std(..., 0, 22) instead of dimension 2, silently returning zeros Testing: - Add tests/ with unit tests for the kinematics helpers and the attitude propagator; they require no toolboxes - Add GitHub Actions CI running them on MATLAB R2023b and latest Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 1453e01 commit b947f83

16 files changed

Lines changed: 693 additions & 39 deletions

.github/workflows/ci.yml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
name: "Continuous integration: MATLAB unit tests"
2+
3+
on:
4+
push:
5+
branches: [master, main]
6+
pull_request:
7+
workflow_dispatch:
8+
9+
jobs:
10+
test:
11+
name: Unit tests (MATLAB ${{ matrix.release }})
12+
runs-on: ubuntu-latest
13+
strategy:
14+
fail-fast: false
15+
matrix:
16+
release: [R2023b, latest]
17+
steps:
18+
- uses: actions/checkout@v4
19+
20+
# MATLAB Actions run without a license in public repositories.
21+
# Base MATLAB only: the unit tests deliberately avoid the add-on
22+
# toolboxes that main.m needs, so they run on a bare installation.
23+
- name: Set up MATLAB
24+
uses: matlab-actions/setup-matlab@v2
25+
with:
26+
release: ${{ matrix.release }}
27+
28+
- name: Run tests
29+
uses: matlab-actions/run-tests@v2
30+
with:
31+
source-folder: .
32+
select-by-folder: tests

.gitignore

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,14 @@
1+
# Cached orbit data, regenerated on demand by main.m (large, machine-specific)
2+
Existing_Orbits/
3+
4+
# parfor_progress scratch file
5+
parfor_progress.txt
6+
7+
# Figures and data exported by plots.m / main.m
8+
*.eps
9+
!MC_Results/*.eps
10+
data4test_*.csv
11+
112
# Windows default autosave extension
213
*.asv
314

.zenodo.json

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
{
2+
"title": "Detumbling Simulator: Magnetic Detumbling Control and Simulation for Fast-tumbling Picosatellites",
3+
"upload_type": "software",
4+
"version": "1.0.0",
5+
"publication_date": "2026-07-13",
6+
"description": "<p><a href=\"https://github.com/rfonod/detumbling-simulator/\" rel=\"noopener\"><strong>Detumbling Simulator</strong></a> is a MATLAB attitude-dynamics simulator for the pure magnetic detumbling of a fast-tumbling picosatellite: a spacecraft that leaves its deployer spinning at up to 180 deg/s and must be brought to rest using only three magnetorquers and two magnetometers, with no gyroscopes, no reaction wheels, and no attitude estimate. It closes the loop end to end (IGRF geomagnetic field, rigid-body dynamics, aerodynamic and residual-dipole disturbances, quantized and biased magnetometers, PWM-driven magnetorquers, and a B-dot control law with an autonomous detumbled/tumbling state machine) and wraps it in a Monte Carlo harness that disperses mass, inertia, actuator strength, and sensor errors across hundreds of runs. It is the simulator behind the IAC-18 paper <em>Magnetic Detumbling of Fast-tumbling Picosatellites</em>, developed for the Delfi-PQ picosatellite.</p>\n<h2>Features</h2>\n<ul>\n<li><strong>Sensor-realistic sensing</strong>: two magnetometers with independent noise, hard-iron bias, finite resolution, and mounting rotations, fused into a weighted average.</li>\n<li><strong>Actuator-realistic actuation</strong>: duty-cycled PWM magnetorquer commands with a finite rise time and a saturation limit.</li>\n<li><strong>Autonomous state machine</strong>: a filtered tumble parameter with hysteresis and confirmation timers decides when the satellite is detumbled or tumbling, requiring no rate sensor and no ground contact.</li>\n<li><strong>Environment models</strong>: IGRF-12 geomagnetic field, Keplerian LEO orbit with ECI/ECEF/body frame handling, six-face aerodynamic drag torque, residual magnetic dipole, and gravity-gradient torque.</li>\n<li><strong>Monte Carlo campaigns</strong>: dispersed mass, inertia, maximum dipole, residual dipole, and sensor biases drawn from 3-sigma truncated Gaussians, fanned out over parfor.</li>\n<li><strong>Reproducible results</strong>: the raw Monte Carlo data behind the paper's figures ships with the repository, together with the evaluation script that turns it into statistics and plots.</li>\n</ul>\n<h2>Citation</h2>\n<p>If you use this simulator in your research, please cite the conference paper:</p>\n<pre><code>@InProceedings{Fon18a,\n author = {Fonod, Robert and Gill, Eberhard},\n title = {Magnetic Detumbling of Fast-tumbling Picosatellites},\n booktitle = {69th International Astronautical Congress},\n year = {2018},\n month = {October},\n address = {Bremen, Germany},\n note = {IAC-18-C1.3.11}\n}</code></pre>\n<h2>License</h2>\n<p>This project is distributed under the MIT License. Bundled third-party code retains its original license, as listed in THIRD_PARTY.md.</p>",
7+
"creators": [
8+
{
9+
"name": "Fonod, Robert",
10+
"orcid": "0000-0002-9434-3156"
11+
}
12+
],
13+
"license": "MIT",
14+
"access_right": "open",
15+
"language": "eng",
16+
"keywords": [
17+
"Picosatellite",
18+
"PocketQube",
19+
"CubeSat",
20+
"Delfi-PQ",
21+
"Magnetic Detumbling",
22+
"B-dot Control",
23+
"Attitude Control",
24+
"Attitude Dynamics",
25+
"ADCS",
26+
"Magnetorquer",
27+
"Magnetometer",
28+
"IGRF",
29+
"Low Earth Orbit",
30+
"Monte Carlo Simulation",
31+
"Spacecraft Simulation",
32+
"MATLAB"
33+
],
34+
"related_identifiers": [
35+
{
36+
"identifier": "https://github.com/rfonod/detumbling-simulator/tree/v1.0.0",
37+
"relation": "isSupplementTo",
38+
"resource_type": "software"
39+
},
40+
{
41+
"identifier": "https://research.tudelft.nl/files/47149549/IAC_18_C1_3_11_x46290.pdf",
42+
"relation": "isSupplementTo",
43+
"resource_type": "publication-conferencepaper"
44+
}
45+
]
46+
}

CITATION.cff

Lines changed: 35 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,49 @@
11
cff-version: 1.2.0
2-
message: "If you use this software, please cite it as below."
2+
title: "Detumbling Simulator: Magnetic Detumbling Control and Simulation for Fast-tumbling Picosatellites"
3+
message: "If you use this software, please cite both the software and the preferred conference paper below."
4+
type: software
35
authors:
46
- family-names: Fonod
57
given-names: Robert
8+
email: robert.fonod@ieee.org
69
orcid: https://orcid.org/0000-0002-9434-3156
7-
title: "Magnetic Detumbling of Fast-tumbling Picosatellites"
8-
version: 0.8
9-
date-released: 2022-11-13
10+
repository-code: "https://github.com/rfonod/detumbling-simulator"
1011
url: "https://github.com/rfonod/detumbling-simulator"
1112
license: MIT
13+
version: 1.0.0
14+
date-released: "2026-07-13"
15+
keywords:
16+
- picosatellite
17+
- CubeSat
18+
- PocketQube
19+
- "magnetic detumbling"
20+
- B-dot
21+
- "attitude control"
22+
- "attitude dynamics"
23+
- ADCS
24+
- magnetorquer
25+
- magnetometer
26+
- "Monte Carlo simulation"
27+
- MATLAB
1228
preferred-citation:
1329
type: conference-paper
14-
authors:
15-
- family-names: "Fonod"
16-
given-names: "Robert"
17-
orcid: "https://orcid.org/0000-0002-9434-3156"
18-
- family-names: "Gill"
19-
given-names: "Eberhard"
2030
title: "Magnetic Detumbling of Fast-tumbling Picosatellites"
21-
booktitle: "69th International Astronautical Congress"
31+
authors:
32+
- family-names: Fonod
33+
given-names: Robert
34+
orcid: "https://orcid.org/0000-0002-9434-3156"
35+
- family-names: Gill
36+
given-names: Eberhard
37+
collection-title: "Proceedings of the 69th International Astronautical Congress (IAC)"
38+
conference:
39+
name: "69th International Astronautical Congress"
40+
city: Bremen
41+
country: DE
2242
month: 10
2343
year: 2018
24-
address: "Bremen, Germany"
44+
notes: "IAC-18-C1.3.11"
45+
url: "https://research.tudelft.nl/files/47149549/IAC_18_C1_3_11_x46290.pdf"
2546
identifiers:
26-
- description: "Post-print"
47+
- description: "Post-print of the conference paper"
2748
type: url
28-
value: https://repository.tudelft.nl/islandora/object/uuid:aedf23cb-a2d4-49e7-8244-1524aa6e0de3/datastream/OBJ/download
29-
keywords:
30-
- picosatellite
31-
- "magnetic detumbling"
32-
- B-dot
33-
- "attitude control"
34-
- stability
49+
value: "https://repository.tudelft.nl/islandora/object/uuid:aedf23cb-a2d4-49e7-8244-1524aa6e0de3/datastream/OBJ/download"

Future/main.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -510,7 +510,7 @@
510510
data(19:21,1) = t_on_sum_w;
511511
data(22:24,1) = t_on_sum_p;
512512

513-
data(25:25+N_orb-1,1) = t_on_orb;
513+
data(25:24+3*N_orb,1) = t_on_orb(:); % [x;y;z] per orbit, orbit by orbit
514514
else
515515
toc
516516
all_var = who;

Future/run_mc.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
tic
99
parfor_progress(N);
1010
parfor i=1:N
11-
data_tmp = main_new(i);
11+
data_tmp = main(i); % N_orb above must match the one set in Future/main.m
1212
data(:,i) = data_tmp;
1313

1414
parfor_progress;

MC_Results/Eval_MC_results.m

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@
6969
% in seconds
7070
t_on_p_mean = mean(t_on_p,2);
7171
t_on_p_med = median(t_on_p,2);
72-
t_on_p_std = std(t_on_p,0,22);
72+
t_on_p_std = std(t_on_p,0,2);
7373

7474
% in seconds
7575
if size(data,1) == 56
@@ -139,7 +139,7 @@
139139
% in seconds
140140
t_on_p_mean2 = mean(t_on_p2,2);
141141
t_on_p_med2 = median(t_on_p2,2);
142-
t_on_p_std2 = std(t_on_p2,0,22);
142+
t_on_p_std2 = std(t_on_p2,0,2);
143143

144144
% in seconds
145145
if ~data_ver2

0 commit comments

Comments
 (0)