Skip to content

Commit 5e851ac

Browse files
Fix/harmonics (#272)
* Refactor GeopotentialGravitationalField for improved performance and accuracy in gravitational calculations * Add test for 24h propagation with degree-10 geopotential and validate position error * Enhance GeopotentialGravitationalField with detailed comments and improve Legendre function handling at poles; add new WebFetch domains in settings
1 parent 31841ee commit 5e851ac

13 files changed

Lines changed: 916 additions & 87 deletions

File tree

DEVELOPER_GUIDE.md

Lines changed: 139 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ public const double Rad2Deg = 180.0 / Math.PI; // Radians to degrees
6565
- **Time**: IERS Conventions, leap seconds from NAIF LSK kernels
6666
- **Ephemerides**: JPL Development Ephemeris (DE series)
6767
- **Reference Frames**: IAU/IAG standards, IERS conventions
68+
- **Gravity Models**: EGM2008 (Earth Gravitational Model 2008), geodesy-normalized spherical harmonics up to degree/order 70
6869
- **Atmospheric Models**: U.S. Standard Atmosphere 1976, NRLMSISE-00
6970
- **TLE Propagation**: SGP4/SDP4 (AFSPC compatibility)
7071

@@ -302,6 +303,7 @@ Represents a natural celestial body (planet, moon, star).
302303
| `Flattening` | Flattening coefficient |
303304
| `Frame` | Body-fixed reference frame |
304305
| `SphereOfInfluence` | Sphere of influence radius (m) |
306+
| `GravitationalField` | Gravity model (point-mass or geopotential) |
305307
| `InitialOrbitalParameters` | Initial orbital state |
306308

307309
| Method | Description |
@@ -1453,7 +1455,7 @@ Console.WriteLine($"Delta-V at arrival: {solution.ArrivalVelocity.Magnitude():F1
14531455

14541456
#### SpacecraftPropagator
14551457

1456-
Numerical orbit propagator with perturbations.
1458+
Numerical orbit propagator using a Velocity-Verlet (symplectic) integrator with configurable perturbation models.
14571459

14581460
| Constructor | Description |
14591461
|------------|-------------|
@@ -1463,6 +1465,37 @@ Numerical orbit propagator with perturbations.
14631465
|--------|-------------|
14641466
| `Propagate()` | Execute propagation |
14651467

1468+
**Force Models:**
1469+
- **Gravitational acceleration** from each body in the `bodies` list. If a body has a `GeopotentialModelParameters`, the full spherical harmonic model (EGM2008) is used; otherwise point-mass gravity is applied.
1470+
- **Atmospheric drag** (when `drag` is true): uses the body's atmospheric model
1471+
- **Solar radiation pressure** (when `srp` is true): cannonball model with eclipse detection
1472+
1473+
**Geopotential usage:**
1474+
1475+
```csharp
1476+
// Create Earth with degree-10 EGM2008 geopotential
1477+
var earth = new CelestialBody(PlanetsAndMoons.EARTH, Frames.Frame.ICRF, epoch,
1478+
new GeopotentialModelParameters("Data/SolarSystem/EGM2008_to70_TideFree", 10));
1479+
1480+
// Initial state in ICRF
1481+
var orbit = new StateVector(
1482+
new Vector3(6800000.0, 0, 0),
1483+
new Vector3(0, 7500.0, 0),
1484+
earth, epoch, Frames.Frame.ICRF);
1485+
1486+
var spacecraft = new Spacecraft(-1001, "Sat", 100.0, 10000.0, clock, orbit);
1487+
1488+
// Propagate with geopotential, Moon, and Sun perturbations
1489+
var propagator = new SpacecraftPropagator(
1490+
new Window(epoch, epoch.AddDays(1)),
1491+
spacecraft,
1492+
[earth, PlanetsAndMoons.MOON_BODY, Stars.SUN_BODY],
1493+
false, false, TimeSpan.FromSeconds(1.0));
1494+
propagator.Propagate();
1495+
```
1496+
1497+
**Accuracy:** With degree-10 EGM2008, Moon, and Sun perturbations, 24h LEO propagation achieves sub-kilometer position accuracy compared to STK HPOP reference solutions.
1498+
14661499
#### TLEPropagator
14671500

14681501
SGP4/SDP4 propagator for TLE elements.
@@ -1477,6 +1510,74 @@ SGP4/SDP4 propagator for TLE elements.
14771510

14781511
---
14791512

1513+
### Geopotential Gravity Models
1514+
1515+
The framework supports high-fidelity Earth gravity modeling using spherical harmonic expansion with the EGM2008 model (up to degree/order 70).
1516+
1517+
#### GeopotentialModelParameters
1518+
1519+
Configuration for enabling geopotential gravity on a `CelestialBody`.
1520+
1521+
| Constructor | Description |
1522+
|------------|-------------|
1523+
| `GeopotentialModelParameters(string path, ushort degree = 60)` | Load model from file path |
1524+
| `GeopotentialModelParameters(Stream stream, ushort degree = 60)` | Load model from stream |
1525+
1526+
| Property | Description |
1527+
|----------|-------------|
1528+
| `GeopotentialModelPath` | Stream reader for the model file |
1529+
| `GeopotentialDegree` | Maximum degree/order to use |
1530+
1531+
#### GeopotentialGravitationalField
1532+
1533+
Computes the full 3D gravitational acceleration including spherical harmonic perturbations using the Montenbruck & Gill spherical coordinate gradient formulation.
1534+
1535+
| Property | Description |
1536+
|----------|-------------|
1537+
| `MaxDegree` | Maximum harmonic degree |
1538+
1539+
| Method | Description |
1540+
|--------|-------------|
1541+
| `ComputeGravitationalAcceleration(StateVector sv)` | Compute full 3D acceleration including harmonics |
1542+
1543+
**Algorithm:**
1544+
1. Transform position to body-fixed frame
1545+
2. Compute geocentric latitude, longitude, and radius
1546+
3. Evaluate geodesy-normalized associated Legendre functions and derivatives via stable recursion
1547+
4. Sum radial, latitudinal, and longitudinal gradient components over all harmonic degrees/orders
1548+
5. Transform spherical acceleration to body-fixed Cartesian, then rotate to inertial frame
1549+
1550+
**Normalization convention:** Geodesy (fully-normalized) without Condon-Shortley phase:
1551+
`P_bar_nm = sqrt((2 - delta_0m)(2n+1)(n-m)!/(n+m)!) * P_nm`
1552+
1553+
**Supported model file:** EGM2008 (tide-free), included as `Data/SolarSystem/EGM2008_to70_TideFree`. The file provides coefficients C_nm and S_nm from degree 2 to degree 70.
1554+
1555+
**Thread safety:** `GeopotentialGravitationalField` is **not** thread-safe. Pre-allocated buffers (Legendre tables, trig arrays) are reused across calls. Create a separate `CelestialBody` instance per thread when propagating concurrently.
1556+
1557+
**Degree selection guidelines:**
1558+
1559+
| Degree | Use Case | Typical LEO Accuracy (24h) |
1560+
|--------|----------|---------------------------|
1561+
| 2 | J2-only, fast preliminary analysis | ~10 km |
1562+
| 10 | Good accuracy for most LEO missions | < 1 km vs STK HPOP |
1563+
| 20-30 | High-fidelity geodesy applications | Sub-100 m |
1564+
| 70 | Maximum available (EGM2008_to70) | Highest fidelity |
1565+
1566+
```csharp
1567+
// Degree-10 geopotential (good balance of accuracy and speed)
1568+
var earth = new CelestialBody(PlanetsAndMoons.EARTH, Frames.Frame.ICRF, epoch,
1569+
new GeopotentialModelParameters("Data/SolarSystem/EGM2008_to70_TideFree", 10));
1570+
1571+
// Degree-2 (J2-only) for quick analysis
1572+
var earthJ2 = new CelestialBody(PlanetsAndMoons.EARTH, Frames.Frame.ICRF, epoch,
1573+
new GeopotentialModelParameters("Data/SolarSystem/EGM2008_to70_TideFree", 2));
1574+
1575+
// Point-mass only (no geopotential)
1576+
var earthPointMass = new CelestialBody(PlanetsAndMoons.EARTH);
1577+
```
1578+
1579+
---
1580+
14801581
### IO.Astrodynamics.Atmosphere
14811582

14821583
The atmosphere subsystem provides a unified interface for atmospheric modeling across different planets and model complexities.
@@ -2455,6 +2556,43 @@ Console.WriteLine($" Position error: {positionError:F1} m");
24552556
Console.WriteLine($" Velocity error: {velocityError:F4} m/s");
24562557
```
24572558

2559+
### High-Fidelity LEO Propagation with Geopotential
2560+
2561+
Propagate a LEO satellite with EGM2008 spherical harmonics, Moon, and Sun perturbations:
2562+
2563+
```csharp
2564+
var epoch = new Time(2025, 8, 25, 11, 55, 44, frame: TimeFrame.UTCFrame);
2565+
2566+
// Earth with degree-10 EGM2008 geopotential
2567+
var earth = new CelestialBody(PlanetsAndMoons.EARTH, Frames.Frame.ICRF, epoch,
2568+
new GeopotentialModelParameters("Data/SolarSystem/EGM2008_to70_TideFree", 10));
2569+
2570+
// LEO orbit (~400 km altitude)
2571+
var orbit = new StateVector(
2572+
new Vector3(5442162.59, -4068949.85, -13456.85), // Position (m)
2573+
new Vector3(2858.20, 3809.79, 6002.13), // Velocity (m/s)
2574+
earth, epoch, Frames.Frame.ICRF);
2575+
2576+
var clock = new Clock("Clock", 256);
2577+
var spacecraft = new Spacecraft(-1001, "LEOSat", 100.0, 10000.0, clock, orbit);
2578+
2579+
var propagator = new SpacecraftPropagator(
2580+
new Window(epoch, epoch.AddDays(1)),
2581+
spacecraft,
2582+
[earth, PlanetsAndMoons.MOON_BODY, Stars.SUN_BODY],
2583+
false, false,
2584+
TimeSpan.FromSeconds(1.0));
2585+
2586+
propagator.Propagate();
2587+
2588+
// Get final state relative to Earth
2589+
var finalState = spacecraft.StateVectorsRelativeToICRF.Values.Last()
2590+
.RelativeTo(earth, Aberration.None) as StateVector;
2591+
2592+
Console.WriteLine($"Position after 24h: ({finalState.Position.X/1000:F3}, " +
2593+
$"{finalState.Position.Y/1000:F3}, {finalState.Position.Z/1000:F3}) km");
2594+
```
2595+
24582596
### Earth Observation with Attitude Maneuvers
24592597

24602598
Point instruments at ground targets during observation passes:

IO.Astrodynamics.Net/.claude/settings.local.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,10 @@
3131
"WebFetch(domain:en.wikipedia.org)",
3232
"WebFetch(domain:johannesbuchner.github.io)",
3333
"WebFetch(domain:www.scratchapixel.com)",
34-
"Bash(tee:*)"
34+
"Bash(tee:*)",
35+
"Bash(xargs cat:*)",
36+
"WebFetch(domain:shtools.github.io)",
37+
"WebFetch(domain:degenerateconic.com)"
3538
],
3639
"deny": [],
3740
"ask": []

IO.Astrodynamics.Net/CLAUDE.md

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,11 @@ dotnet tool install --global --add-source ./IO.Astrodynamics.CLI/bin/Debug IO.As
7171
- `IO.Astrodynamics.Maneuver`: Lambert solvers, launch windows, maneuver planning, attitude maneuvers
7272
- `IO.Astrodynamics.Frames`: Reference frames and transformations
7373
- `IO.Astrodynamics.TimeSystem`: Time frames (UTC, TDB, TAI, etc.)
74-
- `IO.Astrodynamics.Propagator`: Orbital propagation and integration
74+
- `IO.Astrodynamics.Propagator`: Orbital propagation and integration (Velocity-Verlet symplectic integrator)
75+
- `IO.Astrodynamics.Propagator.Forces`: Force models (gravitational, atmospheric drag, solar radiation pressure)
7576
- `IO.Astrodynamics.Atmosphere`: Atmospheric density, temperature, and pressure models for Earth and Mars
77+
- `IO.Astrodynamics.Math`: Vectors, matrices, quaternions, Legendre functions
78+
- `IO.Astrodynamics.Physics`: Geopotential model reader, coefficients
7679

7780
**External Dependencies**
7881
- MathNet.Numerics: Linear algebra operations
@@ -399,6 +402,36 @@ var atm = earth.GetAtmosphere(context); // Uses NRLMSISE-00 automatically
399402
- Use `CelestialBody.GetAtmosphere(context)` with full context for automatic NRLMSISE-00 selection
400403
- Use `MarsStandardAtmosphere` for preliminary Mars mission analysis
401404

405+
### Geopotential Gravity Model
406+
407+
The framework supports spherical harmonic gravity modeling using EGM2008 coefficients (up to degree/order 70).
408+
409+
**Key Classes**
410+
- `GeopotentialModelParameters`: Configuration (model file path + max degree)
411+
- `GeopotentialGravitationalField`: Computes full 3D acceleration via Montenbruck & Gill formulation
412+
- `GeopotentialModelReader`: Parses EGM2008 coefficient files
413+
- `GeopotentialCoefficient`: Holds C_nm, S_nm coefficients for a single (n,m) pair
414+
- `LegendreFunctions`: Geodesy-normalized associated Legendre functions and derivatives
415+
416+
**Conventions**
417+
- Geodesy normalization: `sqrt((2-delta_0m)(2n+1)(n-m)!/(n+m)!)` — no Condon-Shortley phase
418+
- Coefficients: fully-normalized C_nm and S_nm from EGM2008 (tide-free)
419+
- Model file starts at degree 2 (degrees 0 and 1 are absent; handled as zeros)
420+
421+
**Usage**
422+
```csharp
423+
// Create Earth with degree-10 geopotential
424+
var earth = new CelestialBody(PlanetsAndMoons.EARTH, Frames.Frame.ICRF, epoch,
425+
new GeopotentialModelParameters("Data/SolarSystem/EGM2008_to70_TideFree", 10));
426+
427+
// The propagator automatically uses the geopotential model when present
428+
var propagator = new SpacecraftPropagator(window, spacecraft,
429+
[earth, PlanetsAndMoons.MOON_BODY, Stars.SUN_BODY],
430+
false, false, TimeSpan.FromSeconds(1.0));
431+
```
432+
433+
**Thread Safety:** `GeopotentialGravitationalField` is NOT thread-safe (pre-allocated buffers). Create separate `CelestialBody` instances for concurrent propagation.
434+
402435
### Attitude Maneuvers
403436

404437
The framework provides a family of attitude maneuvers for spacecraft orientation control. All inherit from the abstract `Attitude` base class.
@@ -534,6 +567,13 @@ Test data files are in `Data/SolarSystem/` and copied to output directory.
534567
- Ensure body vectors and reference vectors are not collinear (minimum 5 degrees separation)
535568
- Use `Spacecraft.Front`, `Spacecraft.Up`, etc. for standard body frame directions
536569
- Use `Instrument.GetBoresightInSpacecraftFrame()` and `GetRefVectorInSpacecraftFrame()` for instrument-based pointing
570+
10. **Geopotential Gravity**: When working with spherical harmonic gravity models:
571+
- Pass `GeopotentialModelParameters` to `CelestialBody` constructor to enable geopotential
572+
- Use degree 10 for typical LEO accuracy; degree 2 for J2-only analysis
573+
- EGM2008 model file: `Data/SolarSystem/EGM2008_to70_TideFree` (degrees 2-70)
574+
- `GeopotentialGravitationalField` is NOT thread-safe — one instance per thread
575+
- Legendre functions use geodesy normalization without Condon-Shortley phase
576+
- The model file starts at degree 2; degrees 0 and 1 are handled as zeros internally
537577

538578
## Code Quality Standards
539579

IO.Astrodynamics.Net/IO.Astrodynamics.CLI/IO.Astrodynamics.CLI.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
<FileVersion>0.0.1</FileVersion>
1010
<PackAsTool>true</PackAsTool>
1111
<ToolCommandName>astro</ToolCommandName>
12-
<Version>0.8.3.0</Version>
12+
<Version>0.8.3.1</Version>
1313
<Title>Astrodynamics command line interface</Title>
1414
<Authors>Sylvain Guillet</Authors>
1515
<Description>This CLI allows end user to exploit IO.Astrodynamics framework </Description>

0 commit comments

Comments
 (0)