From 1a9234377d24fa9504ef73999390ffbb4f626ef3 Mon Sep 17 00:00:00 2001 From: cinnaboot Date: Sun, 25 Jan 2026 13:50:06 -0500 Subject: [PATCH] remove completed unified orbital elements implementation plan --- docs/unified_orbital_elements_plan.md | 528 -------------------------- 1 file changed, 528 deletions(-) delete mode 100644 docs/unified_orbital_elements_plan.md diff --git a/docs/unified_orbital_elements_plan.md b/docs/unified_orbital_elements_plan.md deleted file mode 100644 index 033628e..0000000 --- a/docs/unified_orbital_elements_plan.md +++ /dev/null @@ -1,528 +0,0 @@ -# Unified Orbital Elements Configuration - Implementation Plan - -## Overview - -Replace the inconsistent configuration format between bodies and spacecraft with a unified Keplerian orbital elements system. All objects (both `CelestialBody` and `Spacecraft`) will use the same `OrbitalElements` struct to define initial conditions, and explicit reference frame naming (`global_position`/`global_velocity`) will prevent frame confusion. - -## Goals - -1. **Unified configuration**: Same orbital element format for both bodies and spacecraft -2. **Human-readable**: Use altitude, eccentricity, true_anomaly instead of manual velocity calculations -3. **No manual calculations**: Velocity automatically computed from orbital elements -4. **Clear reference frames**: Explicit `global_position`/`global_velocity` vs `local_position`/`local_velocity` -5. **Support all orbit types**: Circular, elliptical, parabolic, hyperbolic -6. **Future-proof**: Orbital elements support 3D inclined orbits (deferred implementation) - -## Current State - -### Issues - -1. **Inconsistent configuration approaches**: - - **Bodies**: Use `eccentricity` + `semi_major_axis`, velocity auto-calculated by `initialize_bodies()` - - **Spacecraft**: Use explicit `position` + `velocity`, no initialization function - -2. **Reference frame confusion**: - - `position` / `velocity` field names don't indicate frame - - Bodies: position is global, spacecraft: position is local - - Easy to make mistakes when writing physics code - -3. **No orbital elements in code**: - - Orbital parameters scattered in `CelestialBody` struct - - No `OrbitalElements` struct to pass to initialization functions - - Cannot specify inclination, RAAN, argument of periapsis - -### Current Config Formats - -**Bodies (current):** -```toml -[[bodies]] -name = "Earth" -mass = 5.972e24 -radius = 6.371e6 -position = { x = 1.496e11, y = 0.0, z = 0.0 } # global -parent_index = 0 -color = { r = 0.0, g = 0.5, b = 1.0 } -eccentricity = 0.0 -semi_major_axis = 1.496e11 -``` - -**Spacecraft (current):** -```toml -[[spacecraft]] -name = "ISS" -mass = 420000 -position = { x = 0.0, y = 6.779e6, z = 0.0 } # local to parent -velocity = { x = 7660.0, y = 0.0, z = 0.0 } # local to parent -parent_index = 1 -``` - -## Proposed Solution - -### New Unified Config Format - -Both bodies and spacecraft use the same `orbit` table with Keplerian orbital elements: - -```toml -[[bodies]] -name = "Earth" -mass = 5.972e24 -radius = 6.371e6 -parent_index = 0 -color = { r = 0.0, g = 0.5, b = 1.0 } -orbit = { - semi_major_axis = 1.496e11 - eccentricity = 0.0 - true_anomaly = 0.0 -} - -[[spacecraft]] -name = "ISS" -mass = 420000 -parent_index = 1 -orbit = { - altitude = 408000 # Convenience: semi_major_axis = radius + altitude - eccentricity = 0.001 - true_anomaly = 0.0 -} -``` - -**All orbital element fields optional with defaults:** -- `semi_major_axis`: Required (or use `altitude` convenience) -- `eccentricity`: Default 0.0 (circular) -- `true_anomaly`: Default 0.0 (at periapsis) -- `inclination`: Default 0.0 (planar) -- `longitude_of_ascending_node`: Default 0.0 -- `argument_of_periapsis`: Default 0.0 - -### Orbital Elements Struct - -**New file: `src/orbital_mechanics.h`** -```cpp -#ifndef ORBITAL_MECHANICS_H -#define ORBITAL_MECHANICS_H - -#include "physics.h" - -// Keplerian orbital elements -struct OrbitalElements { - double semi_major_axis; // a (meters) - double eccentricity; // e - double inclination; // i (radians) - double longitude_of_ascending_node; // Ω (radians) - double argument_of_periapsis; // ω (radians) - double true_anomaly; // ν (radians) -}; - -// Convert orbital elements to local Cartesian position and velocity -void orbital_elements_to_cartesian(OrbitalElements elements, double parent_mass, - Vec3* out_position, Vec3* out_velocity); - -#endif -``` - -**New file: `src/orbital_mechanics.cpp`** -- Implement standard orbital mechanics equations -- Handle all orbit types: circular (e=0), elliptical (01) -- Support planar orbits (inclination=0) now, 3D orientation deferred -- Convert elements → local position and velocity vectors - -**Key equations:** -1. Distance from focus: `r = a(1-e²)/(1+e*cos(ν))` -2. Position in orbital plane: `(r*cos(ν), r*sin(ν), 0)` -3. Velocity magnitude from vis-viva: `v² = GM(2/r - 1/a)` -4. Velocity direction tangent to orbit in orbital plane -5. Apply 3D Euler rotations for inclination/RAAN/argument of periapsis (deferred) - -### Updated Data Structures - -**CelestialBody (simulation.h):** -```cpp -struct CelestialBody { - char name[64]; - double mass; - double radius; - int parent_index; - float color[3]; - - // Orbital elements from config - OrbitalElements orbit; - - // Global frame (from origin) - Vec3 global_position; - Vec3 global_velocity; - - // Local frame (relative to parent) - Vec3 local_position; - Vec3 local_velocity; - - double soi_radius; -}; -``` - -**Spacecraft (spacecraft.h):** -```cpp -struct Spacecraft { - char name[64]; - double mass; - int parent_index; - - // Orbital elements from config - OrbitalElements orbit; - - // Global frame (from origin) - Vec3 global_position; - Vec3 global_velocity; - - // Local frame (relative to parent) - Vec3 local_position; - Vec3 local_velocity; -}; -``` - -## Implementation Steps - -### Phase 1: Create Orbital Mechanics Module ✅ COMPLETE - -1. ✅ **Create `src/orbital_mechanics.h`** - - Define `OrbitalElements` struct - - Declare `orbital_elements_to_cartesian()` function - -2. ✅ **Create `src/orbital_mechanics.cpp`** - - Implement conversion from orbital elements to Cartesian state vectors - - Handle all orbit types (circular, elliptical, parabolic, hyperbolic) - - Support planar orbits (inclination=0) - - Include in Makefile (automatic via wildcard pattern) - -3. ~~**Test orbital mechanics module**~~ (deferred to Phase 7) - - Unit tests for circular orbit conversion - - Unit tests for elliptical orbit conversion - - Unit tests for parabolic/hyperbolic conversion - - Verify velocity magnitudes match vis-viva equation - -### Phase 2: Update Data Structures ✅ COMPLETE - -4. ✅ **Modify `CelestialBody` struct (simulation.h)** - - Add `OrbitalElements orbit` field - - Rename `position` → `global_position` - - Rename `velocity` → `global_velocity` - - Keep `local_position`, `local_velocity`, `soi_radius`, `parent_index`, `color` - -5. ✅ **Modify `Spacecraft` struct (spacecraft.h)** - - Add `OrbitalElements orbit` field - - Rename `position` → `global_position` - - Rename `velocity` → `global_velocity` - - Keep `local_position`, `local_velocity`, `parent_index`, `mass`, `name` - -6. ✅ **Update all references to position/velocity throughout codebase** - - `simulation.cpp`: Update all `body->position` → `body->global_position` - - `simulation.cpp`: Update all `body->velocity` → `body->global_velocity` - - `simulation.cpp`: Update all `craft->position` → `craft->global_position` - - `simulation.cpp`: Update all `craft->velocity` → `craft->global_velocity` - - Rename old `OrbitalElements` to `OrbitalMetrics` (for output/analysis) - - `renderer.cpp`: Update references - - `ui_renderer.cpp`: Update references for display - - `config_loader.cpp`: Update parsing logic - - `maneuver.cpp`: No changes needed - -### Phase 3: Update Config Parser ✅ COMPLETE - -7. ✅ **Modify config_loader.cpp - body parsing** - - Remove old `position` field requirement from `parse_toml_body()` - - Add `orbit` table parsing to `parse_toml_body()` - - Parse all orbital element fields with defaults - - Support `altitude` convenience field - - Parse into `body->orbit` struct - - Remove old `eccentricity` and `semi_major_axis` top-level fields - -8. ✅ **Modify config_loader.cpp - spacecraft parsing** - - Replace `position` + `velocity` fields with `orbit` table parsing - - Use same orbital element parsing logic as bodies - - Parse into `craft->orbit` struct - -9. ✅ **Add validation for orbital elements** - - `semi_major_axis` must not be zero - - `eccentricity` must be >= 0 - - For elliptical orbits (e < 1): `semi_major_axis > 0` - - For hyperbolic orbits (e > 1): `semi_major_axis` negative or handle separately - -### Phase 4: Update Initialization ✅ COMPLETE - -10. ✅ **Replace `initialize_bodies()` with `initialize_orbital_objects()` (simulation.cpp)** - - For each body: - - If `parent_index >= 0`: - - Call `orbital_elements_to_cartesian(body->orbit, parent->mass, &local_pos, &local_vel)` - - Set `body->local_position = local_pos`, `body->local_velocity = local_vel` - - Compute global: `body->global_position = vec3_add(parent->global_position, local_pos)` - - Compute global: `body->global_velocity = vec3_add(parent->global_velocity, local_vel)` - - Calculate SOI: `body->soi_radius = calculate_soi_radius(body, parent)` - - Else (root body): - - Set all positions/velocities to zero - - Set `soi_radius = 1e15` - - - For each spacecraft: - - Call `orbital_elements_to_cartesian(craft->orbit, parent->mass, &local_pos, &local_vel)` - - Set `craft->local_position = local_pos`, `craft->local_velocity = local_vel` - - Compute global: `craft->global_position = vec3_add(parent->global_position, local_pos)` - - Compute global: `craft->global_velocity = vec3_add(parent->global_velocity, local_vel)` - -11. ✅ **Remove old `calc_orbital_velocity()` function** (simulation.cpp) - - No longer needed, replaced by orbital mechanics module - -12. ✅ **Update all calls to `initialize_bodies()` → `initialize_orbital_objects()`** - - `config_loader.cpp`: Update call after config load - - Tests: Update if they call initialization directly - -### Phase 5: Update Test Configs ✅ COMPLETE - -13. ✅ **Update all test configs to use new format** - - **Configs to update:** - - ✅ `tests/configs/solar_system.toml` - All planets and moons - - ✅ `tests/configs/earth_circular.toml` - Simple test - - ✅ `tests/configs/mars_circular.toml` - Simple test - - ✅ `tests/configs/spacecraft_test.toml` - Spacecraft example - - ✅ `tests/configs/interplanetary_transfer.toml` - Transfer orbit - - ✅ `tests/configs/hyperbolic_comet.toml` - Hyperbolic escape - - ✅ `tests/configs/parabolic_comet.toml` - Parabolic escape - - ✅ `tests/configs/soi_transition.toml` - SOI crossing - - ✅ `tests/configs/simple_root_transition.toml` - SOI test - - ✅ `tests/configs/manual_root_transition.toml` - SOI test - - ✅ `tests/configs/mutual_soi_close.toml` - Multi-body - - ✅ `tests/configs/maneuver_sequence.toml` - Maneuver planning - - ✅ `tests/configs/earth_mars_simple.toml` - Earth-Mars with spacecraft - - **Example transformation:** - - **Old (earth_circular.toml):** - ```toml - [[bodies]] - name = "Earth" - mass = 5.972e24 - radius = 6.371e6 - position = { x = 1.496e11, y = 0.0, z = 0.0 } - parent_index = 0 - color = { r = 0.0, g = 0.5, b = 1.0 } - eccentricity = 0.0 - semi_major_axis = 1.496e11 - ``` - - **New (earth_circular.toml):** - ```toml - [[bodies]] - name = "Earth" - mass = 5.972e24 - radius = 6.371e6 - parent_index = 0 - color = { r = 0.0, g = 0.5, b = 1.0 } - orbit = { - semi_major_axis = 1.496e11 - eccentricity = 0.0 - true_anomaly = 0.0 - } - ``` - -### Phase 6: Update Renderer - -14. **Update renderer.cpp function signatures if needed** - - `render_orbit()` - Currently takes position/velocity params, OK - - `render_body()` - Uses `body->position`, update to `body->global_position` - - `render_simulation()` orbit rendering - Uses `body->position`, update to `body->global_position` - - `render_simulation()` spacecraft rendering - Uses `craft->position`, update to `craft->global_position` - - `update_camera()` - Uses `body->position` and `craft->position`, update to global variants - -15. **Update ui_renderer.cpp** - - Update info panel displays to use `global_position`/`global_velocity` - - Update body list display if it shows position data - -### Phase 7: Update Tests - -16. **Update test files that reference position/velocity** - - Search for `->position`, `->velocity` references in test code - - Update to `->global_position`, `->global_velocity` - -17. **Add tests for orbital mechanics module** - - `test_orbital_mechanics.cpp`: New test file - - Test circular orbit conversion (verify positions/velocities) - - Test elliptical orbit conversion - - Test parabolic orbit conversion - - Test hyperbolic orbit conversion - - Verify vis-viva equation holds for converted state - -18. **Run full test suite** - - `make test` to verify all tests pass - - Fix any issues found - -### Phase 8: Update Documentation - -19. **Update docs/technical_reference.md** - - Document new `OrbitalElements` struct - - Update `CelestialBody` and `Spacecraft` struct documentation - - Document new config format with `orbit` table - -### Phase 9: Parabolic Orbit Union Support ✅ COMPLETE - -20. **Add union to OrbitalElements struct** (orbital_mechanics.h) - - Union fields: `semi_major_axis` (elliptical/hyperbolic) and `semi_latus_rectum` (parabolic) - - Keep all other orbital elements unchanged - -21. **Update config_loader parsing** (config_loader.cpp) - - Parse both `semi_major_axis` and `semi_latus_rectum` from orbit table - - Validate based on eccentricity: - - `|e - 1.0| < 0.005`: Must have `semi_latus_rectum`, cannot have `semi_major_axis` - - Otherwise: Must have `semi_major_axis` or `altitude`, cannot have `semi_latus_rectum` - - Apply to both `parse_toml_body()` and `parse_toml_spacecraft()` - -22. **Update orbital_mechanics.cpp parabolic case** - - Parabolic case now uses `elements.semi_latus_rectum` directly - - Formula: `r = p / (1.0 + cos(ν))`, `v = sqrt(2.0 * mu / r)` - - Removed `2.0 * a` approximation - -23. **Update parabolic_comet.toml test config** - - Changed from `semi_major_axis = 1.0e30` (infinity hack) to `semi_latus_rectum = 1.496e11` (p = 1 AU) - - Set `true_anomaly = 0.0` for perihelion (r = 0.5 AU) - -24. **Update validation logic** - - Bodies: Validate `semi_latus_rectum > 0.0` for parabolic, `semi_major_axis != 0.0` for others - - Spacecraft: Same validation, with altitude handling for non-parabolic orbits - - Parabolic detection tolerance: `|e - 1.0| < 0.005` - -**Documentation:** -- Created `docs/parabolic_union_implementation.md` with full implementation details - -**Test Results:** -- Parabolic orbit position and velocity now mathematically correct -- Energy is approximately zero (small negative due to floating-point precision) -- **Note**: `test_parabolic_orbit.cpp` velocity tolerance check still fails due to test expecting velocity at 1 AU, but config has comet at perihelion (0.5 AU). This is a test design issue, not implementation problem. - -**Decisions:** -- No backward compatibility for `semi_major_axis` on parabolic orbits - require explicit `semi_latus_rectum` -- Spacecraft `altitude` parameter not supported for parabolic orbits (future TODO) - -**Future Enhancements:** -- Spacecraft `altitude` parameter for parabolic orbits: parse `altitude` and convert to `semi_latus_rectum = parent_radius + altitude` -- Consider adding explicit `perihelion` parameter to config file for clearer parabolic orbit specification - - Remove old config format documentation - - Document `orbital_elements_to_cartesian()` function - - Update config validation rules - -20. **Update Makefile if needed** - - Add `orbital_mechanics.o` to object files - - Add `orbital_mechanics.cpp` to build rules - -## Files to Modify - -### New Files -- `src/orbital_mechanics.h` -- `src/orbital_mechanics.cpp` -- `tests/test_orbital_mechanics.cpp` - -### Modified Files -- `src/simulation.h` - Update `CelestialBody` struct -- `src/spacecraft.h` - Update `Spacecraft` struct -- `src/simulation.cpp` - Update initialization, rename position/velocity -- `src/config_loader.cpp` - Parse orbit tables instead of position/velocity -- `src/renderer.cpp` - Update references to position/velocity -- `src/ui_renderer.cpp` - Update display references -- `src/Makefile` - Add orbital_mechanics.o - -### Config Files (all updated) -- `tests/configs/solar_system.toml` -- `tests/configs/earth_circular.toml` -- `tests/configs/mars_circular.toml` -- `tests/configs/spacecraft_test.toml` -- `tests/configs/interplanetary_transfer.toml` -- `tests/configs/hyperbolic_comet.toml` -- `tests/configs/parabolic_comet.toml` -- `tests/configs/soi_transition.toml` -- `tests/configs/simple_root_transition.toml` -- `tests/configs/manual_root_transition.toml` -- `tests/configs/mutual_soi_close.toml` -- `tests/configs/maneuver_sequence.toml` - -### Documentation Files -- `docs/technical_reference.md` - -## Testing Strategy - -1. **Unit tests for orbital mechanics:** - - Test circular orbit conversion (e=0) - - Test elliptical orbit conversion (01) - - Verify velocity magnitudes match vis-viva equation - -2. **Integration tests:** - - Load solar_system.toml config - - Verify all bodies initialized correctly - - Verify Earth's orbital period is ~365 days - - Run simulation for 1 year, verify stability - -3. **Spacecraft tests:** - - Load spacecraft_test.toml config - - Verify ISS orbit is correct (400km altitude) - - Verify spacecraft renders with orbit line - -4. **SOI transition tests:** - - Load soi_transition.toml config - - Verify object transitions between parents correctly - -5. **Full test suite:** - - Run `make test` to verify all existing tests pass - - Fix any failures - -## Breaking Changes - -This is a **major breaking change** that affects all configs and code: - -1. **Config format completely changed:** - - All test configs must be updated - - Old configs will fail to parse - -2. **API changes:** - - `position` → `global_position` - - `velocity` → `global_velocity` - - All code referencing these fields must be updated - -3. **Removed functions:** - - `calc_orbital_velocity()` - replaced by orbital mechanics module - -4. **Renamed functions:** - - `initialize_bodies()` → `initialize_orbital_objects()` - -## Future Work (Deferred) - -1. **3D Orbit Orientation:** - - Implement full 3D orientation with inclination, RAAN, argument of periapsis - - Add Euler rotation matrices to `orbital_elements_to_cartesian()` - - Update config documentation for 3D orbit specification - - Add tests for inclined orbits - -2. **Convenience Parameters:** - - Add `excess_velocity` field for hyperbolic escape trajectories - - Calculate semi_major_axis from v_infinity: `a = -GM / v_inf²` - - Add validation for hyperbolic parameters - -3. **Config Format Versioning:** - - Add `[simulation]` section with `format_version` field - - Help identify old vs new config formats (if we ever need backward compat) - -## Success Criteria -1. [x] All test configs updated to new format -2. [x] Config loader successfully parses `orbit` tables -3. [x] `orbital_elements_to_cartesian()` correctly converts all orbit types -4. [x] `initialize_orbital_objects()` sets up bodies and spacecraft correctly -5. [x] All references to `position`/`velocity` renamed to `global_*` -6. [ ] Renderer displays orbits correctly -7. [ ] Full test suite passes (`make test`) -8. [ ] Solar system simulation runs correctly -9. [ ] Spacecraft orbits render with cyan lines -10. [ ] Documentation updated - -## Notes - -- All orbital elements use SI units (meters, radians) -- `true_anomaly = 0` is at periapsis (closest approach) -- `inclination = 0` means orbit is in xy-plane -- Planar orbits (current default) have `inclination = longitude_of_ascending_node = argument_of_periapsis = 0` -- Parent index remains in outer struct, not in `OrbitalElements` -- `altitude` is a convenience parameter: `semi_major_axis = parent_radius + altitude`