Skip to content

init simulation: #1

Merged
merged 1 commit into from
Feb 25, 2026
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -172,3 +172,11 @@ cython_debug/

# PyPI configuration file
.pypirc

# Nix
.direnv/
result

# IDE
.vscode/
.idea/
142 changes: 141 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,141 @@
# SatelittSim
# SatelittSim

Dette prosjektet simulerer satellitter i bane med fokus på deorbitering og atmosfærisk motstand.

## Rask Start

```bash
# Kjør basis simulering med 3D visualisering
python examples/basic_simulation.py

# Valider fysikkmodeller
python examples/validate_physics.py

# Visualisering med egendefinert STL-modell
python examples/custom_satellite_model.py
```

## 3D Visualisering

SatelittSim inkluderer interaktiv 3D-visualisering av satellittbaner ved hjelp av Pygame.

### Funksjoner

- **Interaktiv kamera**: Roter, panorér og zoom banen
- **Jorden som 3D-sfære**: Blå sfære med radius 6371 km
- **Banestrek**: Grønn linje som viser satellittens trajektorie
- **Satellittmodell**: Last inn din egen STL-fil for visualisering
- **Koordinatakser**: X (rød), Y (grønn), Z (blå)

### Kamera-kontroller

| Handling | Tast / Mus |
|----------|-----------|
| Roter visning | Venstre klikk + dra |
| Panorér | Høyre klikk + dra |
| Zoom | Scrollhjul |
| Start/pause animasjon | SPACE |
| Nullstill visning | R |

### Bruk med egendefinert STL-modell

```python
from src import Satellite, State, Simulation, SimulationConfig
from src.visualization import visualize_orbit

# Last inn din 3D-modell
sat = Satellite(
mass=10.0,
drag_area=10.0,
drag_coefficient=2.2,
stl_path="path/to/your/satellite.stl" # Din STL-fil
)

# ... kjør simulering ...

# Visualiser med 3D-modell
visualize_orbit(sim.history, sat, title="Min Satellitt")
```

### Eksempel: Lage enkel STL-modell

```python
from pathlib import Path
import struct

def create_simple_satellite_stl(output_path: Path):
"""Lag en enkel boks-formet satellitt STL."""
vertices = [
[-1, -0.5, -0.5], [1, -0.5, -0.5], [1, 0.5, -0.5], [-1, 0.5, -0.5],
[-1, -0.5, 0.5], [1, -0.5, 0.5], [1, 0.5, 0.5], [-1, 0.5, 0.5],
]
faces = [
[0, 1, 2], [0, 2, 3], # Front
[5, 4, 7], [5, 7, 6], # Back
# ... flere flater
]

with open(output_path, 'wb') as f:
f.write(b'STL header' + b'\x00' * 70)
f.write(struct.pack('<I', len(faces)))
for face in faces:
f.write(struct.pack('<3f', 0.0, 0.0, 0.0)) # Normal
for idx in face:
v = vertices[idx]
f.write(struct.pack('<3f', *v))
f.write(struct.pack('<H', 0))
```

### Tips for visualisering

1. **Lagre skjermbilde**: Bruk `save_path="orbit.png"` parameteren
2. **Justér skalering**: STL-modeller skaleres automatisk for synlighet
3. **Flere baner**: Bruk `visualize_multiple_orbits()` for sammenligning
4. **Ytelse**: Reduser `save_interval` for færre punkter i lange simuleringer

## Roadmap

1. **Basismodell**
2. **Støy og orientering** - Støy-modellering, dynamisk satellittorientering, effektivt tverrsnitt
3. **Deorbit sanalyse** - Areal vs. deorbiteringstid, maksimale krefter på seilet
4. **Avanserte krefter** - Magnetisk dreiemoment, Lorentz-krefter, J2-perturbasjon
5. **Komplekse luftmotstands-simuleringer** - Solaktivitetd, geomagnetiske effekter, dag/natt-variasjoner

---

## Teori

### Kjernemodeller

**Luftmotstand:** `F_d = -½ * ρ * v² * C_d * A`
**Tyngdekraft:** `F_g = -G * M_e * m / r²`
**Lorentz-kraft:** `F_L = q * (v × B)`
**Magnetisk dreiemoment:** `τ = m × B`

### Atmosfæremodeller

Alle modeller produserer lignende resultater over 300 km (NASA Report 1982).
**NRLMSISE-00** - Empirisk modell fra Naval Research Laboratory, tilgjengelig via [Pymsis](https://pypi.org/project/pymsis) Python-wrapper og [web viewer](https://swx-trec.com/msis).
**Harris-Priester** - Analytisk modell for døgnlig utbuling ved ekvator.
**Jacchia** - Empirisk modell for høyder over 300 km (Guiseppe Jacchia, 1965).

### Forutsetninger

Atmosfæremolekyler antas å stå i ro relativt til satellitten (Hughes 2004, s. 250).

### Solaktivitet

- **F10.7 indeks** - Måler solens radioemisjoner (2800 MHz), indikerer UV/EUV-stråling
- **Ap indeks** - Geomagnetisk aktivitet
- Høy solaktivitet → økt atmosfæretetthet → raskere baneforfall

### Referanser

**Biblioteker:** [Poliastro](https://docs.poliastro.space/en/stable/quickstart.html) (Python), [Orekit](https://www.orekit.org/) (Java), [Skyfield](https://rhodesmill.org/skyfield/) (Python), [Heyoka.py](https://bluescarni.github.io/heyoka.py/notebooks/sgp4_propagator.html) (C++), [Astroz](https://github.com/ATTron/astroz) (Python)

**Kilder:** NASA Report (1982) - [atmospheric density models](https://ntrs.nasa.gov/api/citations/19820002192/downloads/19820002192.pdf), [Jacchia model](https://agupubs.onlinelibrary.wiley.com/doi/epdf/10.1029/JZ065i009p02775), [isothermal atmospheric modelling](https://www.spaceacademy.net.au/watch/debris/atmosmod.htm), [orbital decay](https://en.wikipedia.org/wiki/Orbital_decay), [satellite orbital decay calculations](https://www.sws.bom.gov.au/Category/Educational/Space%20Weather/Space%20Weather%20Effects/SatelliteOrbitalDecayCalculations.pdf)

### Testing

- Dobling i areal = halv deorbiteringstid (validering ved 300 km)
- Deorbiteringskriterium: < 100 km
110 changes: 110 additions & 0 deletions docs/atmosphericmodel.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
Ai summary of deep reserach around atmospheric density models for satellite drag, integrating insights from the "Open-Source Thermospheric Density Models for LEO Satellite Drag" whitepaper with a comprehensive review of academic literature and technical assessments.

In Practice we ended upp utilizing the pymsis library, becasue the full models are very complex and the pymsis library provides a convenient interface to access the NRLMSIS-2.0 model, which is one of the most widely used and validated atmospheric density models for satellite drag calculations.

---

This report synthesizes previous research on high-fidelity drag modeling with new insights from the **"Open-Source Thermospheric Density Models for LEO Satellite Drag"** whitepaper.

The objective is to provide a roadmap for a **general-purpose, offline-capable simulation toolkit** that achieves maximum accuracy in orbital decay predictions by optimizing the three pillars of the drag equation: **Density ($\rho$)**, **Drag Coefficient ($C_d$)**, and **Relative Velocity ($v_{rel}$)**.

---

# Integrated Report: High-Fidelity Orbital Decay Modeling

## Density Model Selection ($\rho$)
The combined data reveals that no single model is superior at all altitudes. A high-accuracy toolkit should implement a **Switched-Model Architecture** or a user-selectable tiered approach.

### Comparative Analysis of Density Models
| Model | Altitude Strength | Key Advantage | Licensing/Constraint |
| :--- | :--- | :--- | :--- |
| **JB2008** | **< 300 km** | Lowest bias at low altitudes; uses 4 EUV proxies. | **Fully Open.** Best for re-entry. |
| **DTM-2020** | **300 – 500 km** | Least bias/best precision in research version. | **Academic Only** (CNES license). |
| **NRLMSIS-2.0** | **> 500 km** | Major upgrade in species coupling (O, He, N2). | **Public Domain.** Best for long-term LEO. |

### Key Insights from Combined Data
* **The Density Gap:** DTM-2020 densities are **20–30% lower** than NRLMSISE-00/JB2008 due to updated calibration against high-precision accelerometers (CHAMP/GRACE). A toolkit must warn users that swapping models will cause a step-change in decay rates.
* **NRLMSIS Evolution:** While NRLMSIS-2.0 is the modern standard, version 2.1 tends to underestimate density by ~10% compared to the original 00 model, especially during geomagnetic disturbances.
* **Storm Robustness:** For simulations involving geomagnetic storms, **JB2008** and **DTM** are significantly more robust than MSIS-series models, which frequently underestimate storm-induced density spikes by up to 70%.

---

## Offline Space Weather & Index Simulation
High-fidelity models require indices ($F_{10.7}, S_{10}, M_{10}, Y_{10}, F_{30}, Dst, Ap$). To remain offline, the toolkit must provide a **Synthetic Proxy Generator**.

* **Proxy Correlation:** Since $F_{10.7}$ is the only widely predicted index, the toolkit should implement scaling laws to derive $S_{10}, M_{10},$ and $Y_{10}$ (required for JB2008) and $F_{30}$ (required for DTM) from a primary $F_{10.7}$ input.
* **Climatological Envelopes:** Store 11-year solar cycle tables (NASA MSFC 5/50/95 percentiles). This allows users to run "Scenario A: Solar Max" without needing a live data connection.

---

## Physical Drag Coefficient ($C_d$) & GSI
The research highlights that density is only half the battle; the **Drag Coefficient** is highly dynamic.

* **Composition-Dependent $C_d$:** Use the species composition output from **NRLMSIS-2.0** (Atomic Oxygen vs. Helium concentration) as an input for the **CLL (Cercignani-Lampis-Lord)** GSI model.
* **The Adsorption Effect:** Implement a **Langmuir Isotherm** to model how atomic oxygen "sticks" to the satellite.
* *Low Alt (<400km):* Surface is "saturated," leading to diffuse reflection ($C_d \approx 2.1-2.4$).
* *High Alt (>600km):* Surface is "clean," leading to specular reflection and potentially higher $C_d$ values ($3.0+$) depending on geometry.
* **Macro-Modeling:** Move beyond the "cannonball." The toolkit should represent satellites as a **Box-Wing model**. This accounts for "shadowing," where solar panels shield the main body from the molecular flow.

---

## Relative Velocity & Environmental Factors ($v_{rel}$)
Accuracy is lost if the satellite's inertial velocity is used instead of its velocity relative to the rotating, blowing atmosphere.

* **Atmospheric Co-rotation:** Account for the Earth's rotation ($v_{rel} = v_{sat} - \omega \times r$).
* **Horizontal Wind Model (HWM14):** The new research confirms that thermospheric winds are critical. HWM14 provides these vectors analytically (no live data needed). Integrating HWM14 corrects for the "side-wind" effect that can alter the decay rate by several percent in polar or highly inclined orbits.

---

## Implementation Strategy for the Toolkit
To build a "Best-in-Class" general-purpose simulator, the following architecture is recommended:

### Phase 1: The Core Propagator
* **Numerical Engine:** Gauss-Jackson 8th order or RKF7/8.
* **Coordinate System:** ITRF (International Terrestrial Reference Frame) to handle the rotating atmosphere and wind vectors natively.

### Phase 2: Modular Physics Plugins
* **Tier 1 (Fast):** Harris-Priester Density + Constant $C_d$.
* **Tier 2 (Standard):** NRLMSISE-00 + Sentman $C_d$ + Co-rotation.
* **Tier 3 (Research Grade):** JB2008 (Low Alt) or DTM-2020 (Mid Alt) + CLL GSI + HWM14 Winds + Box-Wing Area modeling.

### Phase 3: Uncertainty Quantification
* Provide a "Monte Carlo" mode that varies the solar $F_{10.7}$ input within a $\pm 10\%$ range to produce a "Probability of Re-entry Window" rather than a single (likely incorrect) date.

---

## Summary of Sources & Documentation

### Atmospheric Density Model Specifications
* **NRLMSIS 2.0/2.1:** Emmert, J. T., et al. (2021). *A Whole-Atmosphere Empirical Model of Temperature and Neutral Species Densities.*
* https://www.researchgate.net/publication/345024073_NRLMSIS_20_A_Whole-Atmosphere_Empirical_Model_of_Temperature_and_Neutral_Species_Densities
* https://kauai.ccmc.gsfc.nasa.gov/CMR/view/model/SimulationModel?resourceID=spase://CCMC/SimulationModel/NRLMSIS/2.0
* **JB2008 (Jacchia-Bowman):** Bowman, B. R., et al. (2008). *A New Empirical Thermospheric Density Model JB2008.*
* https://sol.spacew.com/JB2008/
* https://arc.aiaa.org/doi/10.2514/6.2008-6438
* **DTM-2020 (Drag Temperature Model):** Bruinsma, S., et al. (2021). *The operational and research DTM-2020 thermosphere models.*
* https://swami-h2020-eu.github.io/mcm/license.html
* https://www.researchgate.net/publication/354128639_The_operational_and_research_DTM-2020_thermosphere_models

### Atmospheric Winds & Space Weather Proxies
* **HWM14 (Horizontal Wind Model):** Drob, D. P., et al. (2015). *Earth and Space Science.*
* https://agupubs.onlinelibrary.wiley.com/doi/full/10.1002/2014EA000089
* **HASDM (High Accuracy Satellite Drag Model):** Space Force/Air Force Research Lab briefing.
* https://spacewx.com/wp-content/uploads/2024/02/HASDM-slides.pdf
* **Solar Indices (F10.7, S10, M10, Y10):** Space Weather Technology archives.
* https://spacewx.com/data-center/

### Gas-Surface Interaction & Machine Learning Research
* **Physics-Informed Neural Networks (PINNs) for Drag:** Mehta, P., et al. (2022). *A New Paradigm for Accelerating Physics-Based Models.*
* https://agupubs.onlinelibrary.wiley.com/doi/full/10.1029/2022SW003161
* **NRLMSIS 2.1 Performance Analysis:** Guo, J., et al. (2024). *Performance analysis of NRLMSIS 2.1 using GRACE-A and SWARM-C.*
* https://www.sciencedirect.com/science/article/abs/pii/S0273117724005295
* **Satellite Drag Coefficient Modeling:** Pilinski, M., et al. (2011). *A Semi-Empirical Satellite Drag Coefficient Model.*
* https://arc.aiaa.org/doi/abs/10.2514/1.50348

### Technical Assessments
* **Thermosphere Modeling Capabilities Assessment:** NOAA/CCMC Neutral Density Workshop.
* https://repository.library.noaa.gov/view/noaa/44791

### Implementation Note for Toolkit Developers
When implementing these models in a general-purpose toolkit, use **NRLMSIS 2.0** or **JB2008** as the baseline for open-source compliance. If you include **DTM-2020**, add a disclaimer noting its **CNES Non-Commercial License**, which restricts use in proprietary commercial simulation software without a specific agreement from the SWAMI consortium.
58 changes: 58 additions & 0 deletions examples/basic_simulation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@

"""Simple satellite deorbit simulation with 3D visualization."""

import numpy as np
from src import Satellite, State, Simulation, SimulationConfig
from src.constants import EARTH_RADIUS, EARTH_GRAVITATIONAL_PARAMETER
from src.forces.gravity import NewtonianGravity
from src.forces.drag import AtmosphericDrag
from src.environment.atmosphere import Nrlmsise00Density
from src.events import DeorbitEvent, TimeLimitEvent
from src.visualization import visualize_orbit


def main():
# 1. Create satellite (10kg with 10m² drag area)
sat = Satellite(mass=2.0, drag_area=0.01, drag_coefficient=2.0)

# 2. Initial state: 400 km circular orbit
altitude = 400_000
r = EARTH_RADIUS + altitude
v = np.sqrt(EARTH_GRAVITATIONAL_PARAMETER / r)

state = State(position=[r, 0, 0], velocity=[0, v, 0], time=0.0)

# 3. Define forces
forces = [
NewtonianGravity(),
AtmosphericDrag(Nrlmsise00Density())
]

# 4. Define events
events = [
DeorbitEvent(),
TimeLimitEvent(max_time=86400 * 60)
]

# 5. Run simulation
print(f"Simulating deorbit from {altitude/1000:.0f} km...")
sim = Simulation(
state, sat, forces, events,
SimulationConfig(dt=10.0, save_interval=50)
)
sim.run()

# 6. Print results
print(f"\nDeorbit time: {sim.final_state.time/86400:.2f} days")
print(f"Final altitude: {sim.final_state.altitude()/1000:.1f} km")
print(f"Steps: {sim.step_count}, Trail points: {len(sim.history)}")

# 7. Visualize
if len(sim.history) > 1:
print("\nOpening 3D visualization...")
print("Controls: Left-drag=Rotate, Right-drag=Pan, Scroll=Zoom\n")
visualize_orbit(sim.history, sat, title="Satellite Deorbit")


if __name__ == "__main__":
main()
31 changes: 31 additions & 0 deletions examples/deorbit_simple.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
"""Deorbit simulation with scheduled parameter changes."""

from src import SatelliteParams, SimConfig, ScheduledChange, DeorbitSimulation


def main():
params = SatelliteParams(
name="Test-1",
mass=100.0,
area=1.0,
height_km=300.0,
f107=70.0,
ap=0.0
)

config = SimConfig(
dt_days=0.001,
print_interval_km=10.0,
reentry_altitude_km=180.0
)

changes = [
ScheduledChange(time_days=20.0, f107=150.0),
]

sim = DeorbitSimulation(params, config, changes)
sim.run_with_output()


if __name__ == "__main__":
main()
Loading