Browse Source

add breaking orbital elements update planning doc

main
cinnaboot 6 months ago
parent
commit
9b88825046
  1. 484
      docs/unified_orbital_elements_plan.md

484
docs/unified_orbital_elements_plan.md

@ -0,0 +1,484 @@
# 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 (0<e<1), parabolic (e=1), hyperbolic (e>1)
- 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
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
3. **Test orbital mechanics module**
- 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
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`
- `renderer.cpp`: Update references (mostly OK, uses `position` and `velocity` params)
- `ui_renderer.cpp`: Update references for display
- `config_loader.cpp`: Update parsing logic
- `maneuver.cpp`: Update if needed
### Phase 3: Update Config Parser
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
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
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
**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
- 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 (0<e<1)
- Test parabolic orbit conversion (e=1)
- Test hyperbolic orbit conversion (e>1)
- 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. [ ] All test configs updated to new format
2. [ ] Config loader successfully parses `orbit` tables
3. [ ] `orbital_elements_to_cartesian()` correctly converts all orbit types
4. [ ] `initialize_orbital_objects()` sets up bodies and spacecraft correctly
5. [ ] 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`
Loading…
Cancel
Save