From 217ca7a618586e1bad0b8b133cb0890c24b27fb3 Mon Sep 17 00:00:00 2001 From: cinnaboot Date: Wed, 28 Jan 2026 17:11:05 -0500 Subject: [PATCH] Remove [!mayfail] tags from now-passing inclined orbit tests - Molniya position tests now pass with 3D rotation implementation - Generic inclined orbit test passes with proper argument_of_periapsis - Only orbital period test still fails (orbit tracker needs 3D fix) - Add plan document for fixing update_orbit_tracker() --- docs/planning/orbit-tracker-3d-fix-plan.md | 78 ++++++++++++++++++++++ tests/test_inclined_orbits.cpp | 4 +- 2 files changed, 80 insertions(+), 2 deletions(-) create mode 100644 docs/planning/orbit-tracker-3d-fix-plan.md diff --git a/docs/planning/orbit-tracker-3d-fix-plan.md b/docs/planning/orbit-tracker-3d-fix-plan.md new file mode 100644 index 0000000..5a9c373 --- /dev/null +++ b/docs/planning/orbit-tracker-3d-fix-plan.md @@ -0,0 +1,78 @@ +# OrbitTracker 3D Fix Plan + +## Problem +`update_orbit_tracker()` only uses `atan2(y, x)` which calculates the angle in the x-y plane. For 3D inclined orbits, this doesn't track the true orbital angular position because: +1. The spacecraft moves in an inclined orbital plane (not the x-y plane) +2. The x-y projection doesn't represent the true angular progress around the orbit + +## Current Implementation (Failing) +```cpp +Vec3 relative_pos = vec3_sub(body->global_position, parent->global_position); +double current_angle = atan2(relative_pos.y, relative_pos.x); // Only works for 2D orbits in x-y plane +``` + +## Solution +Track the orbital angular position by projecting the 3D position onto the orbital plane and calculating the true anomaly. + +## Implementation Approach + +### Option 1: Store Orbital Plane Normal (Recommended) +Add fields to `OrbitTracker` to store the orbital plane orientation: +- `Vec3 orbital_plane_normal` - Normal vector to the orbital plane +- `Vec3 reference_direction` - Reference direction in the orbital plane (periapsis direction) + +Calculation steps: +1. Compute orbital plane normal from inclination (i) and RAAN (Ω): + ``` + n_x = sin(i) * sin(Ω) + n_y = -sin(i) * cos(Ω) + n_z = cos(i) + ``` + +2. Compute periapsis direction in 3D space: + ``` + R_z(Ω) · R_x(i) · R_z(ω) transforms (1, 0, 0) to periapsis direction + ``` + +3. Project position onto orbital plane and calculate angle from periapsis + +### Option 2: Use Existing Rotation Matrix +Reuse `mat3_rotation_orbital()` to transform position back to orbital plane coordinates: + +1. Apply inverse rotation: `R_orbital^T · r_3D = r_orbital_plane` +2. Calculate angle in orbital plane: `atan2(y_orbital, x_orbital)` + +This is simpler and reuses existing code. + +## Changes Required + +### test_utilities.h +- Add `double inclination` field to `OrbitTracker` struct +- Add `double longitude_of_ascending_node` field +- Add `double argument_of_periapsis` field + +### test_utilities.cpp +- Modify `create_orbit_tracker_with_min_time()` to accept orbital elements +- Modify `update_orbit_tracker()` to: + 1. Build inverse rotation matrix from stored orbital elements + 2. Transform 3D position back to orbital plane + 3. Calculate angle in orbital plane + +### test_inclined_orbits.cpp +- Update `create_orbit_tracker_with_min_time()` calls to pass orbital elements + +## Test +- Molniya orbital period test should pass (12 hours ± tolerance) +- All other orbit tests should continue to pass + +## Notes +- Backward compatibility: Planar orbits (i=0) should work exactly as before +- The inverse rotation is just the transpose of the rotation matrix (orthogonal) +- Performance: Minimal impact, only called during tests + +## Files to Modify +1. `src/test_utilities.h` - Add orbital element fields to OrbitTracker +2. `src/test_utilities.cpp` - Implement 3D angle calculation +3. `tests/test_inclined_orbits.cpp` - Update tracker creation calls +4. `tests/test_orbital_period.cpp` - May need updates if using tracker +5. `tests/test_moon_orbits.cpp` - May need updates if using tracker diff --git a/tests/test_inclined_orbits.cpp b/tests/test_inclined_orbits.cpp index 8d7c7b6..cca5331 100644 --- a/tests/test_inclined_orbits.cpp +++ b/tests/test_inclined_orbits.cpp @@ -9,7 +9,7 @@ const double POSITION_TOLERANCE_METERS = 10000.0; const double PERIOD_TOLERANCE_SECONDS = 600.0; -TEST_CASE("Molniya orbit - position verification at multiple true anomalies", "[inclined][molniya][!mayfail]") { +TEST_CASE("Molniya orbit - position verification at multiple true anomalies", "[inclined][molniya]") { const double TIME_STEP = 60.0; const double SECONDS_PER_DAY = 86400.0; const double SEMI_MAJOR_AXIS = 26540000.0; @@ -138,7 +138,7 @@ TEST_CASE("Molniya orbit - orbital period verification", "[inclined][molniya][pe destroy_simulation(sim); } -TEST_CASE("Generic inclined orbit - moderate inclination", "[inclined][generic][!mayfail]") { +TEST_CASE("Generic inclined orbit - moderate inclination", "[inclined][generic]") { const double TIME_STEP = 60.0; const double SEMI_MAJOR_AXIS = 10000000.0; const double ECCENTRICITY = 0.5;