Browse Source
Add dual coordinate storage to CelestialBody for hierarchical frames. Both local (relative to parent) and global (absolute) coordinates maintained. - Added local_position and local_velocity fields to CelestialBody - Added initialize_local_coordinates() to convert global→local - Added compute_global_coordinates() to convert local→global - Updated config_loader to initialize local coords after velocity calc - Updated update_simulation() to sync local coords after integration - Phase 1 complete: foundation for local frame integration Tests: Same 3 moon failures as before (no regression) Implements hierarchical_frames_plan.md Phase 1main
4 changed files with 326 additions and 2 deletions
@ -0,0 +1,285 @@ |
|||||||
|
# Hierarchical Coordinate Frames Implementation Plan |
||||||
|
|
||||||
|
## Goal |
||||||
|
Transform the simulation from global coordinate space to hierarchical local frames to: |
||||||
|
1. Improve numerical precision for moon orbits |
||||||
|
2. Isolate planetary perturbations from affecting moons |
||||||
|
3. Enable future patched conics implementation for satellites |
||||||
|
4. Support SOI transitions with proper coordinate transformations |
||||||
|
|
||||||
|
## Current System Analysis |
||||||
|
|
||||||
|
### Storage (Global Coordinates): |
||||||
|
- `CelestialBody.position` - absolute position in Sun-centered frame |
||||||
|
- `CelestialBody.velocity` - absolute velocity in Sun-centered frame |
||||||
|
- `CelestialBody.parent_index` - determines which body to calculate gravity from |
||||||
|
|
||||||
|
### Physics Integration: |
||||||
|
- `evaluate_acceleration()` - calculates gravity force from parent only (2-body approximation) |
||||||
|
- `rk4_step()` - integrates using global coordinates |
||||||
|
- SOI transitions change `parent_index`, but coordinates stay in global frame |
||||||
|
|
||||||
|
### Key Observation: |
||||||
|
Line 145 in simulation.cpp already composes velocities: `body->velocity = vec3_add(body->velocity, parent->velocity)` |
||||||
|
|
||||||
|
This indicates the system is **already partially thinking in local frames** during initialization, but integrates in global frame. |
||||||
|
|
||||||
|
## Proposed Architecture: "Local Frame Integration" |
||||||
|
|
||||||
|
### Data Structure: Dual Storage (Recommended) |
||||||
|
Store both local and global coordinates: |
||||||
|
```cpp |
||||||
|
struct CelestialBody { |
||||||
|
char name[64]; |
||||||
|
double mass; |
||||||
|
double radius; |
||||||
|
|
||||||
|
// NEW: Local coordinates (relative to parent) |
||||||
|
Vec3 local_position; // position relative to parent |
||||||
|
Vec3 local_velocity; // velocity relative to parent |
||||||
|
|
||||||
|
// Keep for rendering/backward compatibility |
||||||
|
Vec3 position; // global position (computed from local) |
||||||
|
Vec3 velocity; // global velocity (computed from local) |
||||||
|
|
||||||
|
double soi_radius; |
||||||
|
int parent_index; |
||||||
|
float color[3]; |
||||||
|
double eccentricity; |
||||||
|
double semi_major_axis; |
||||||
|
}; |
||||||
|
``` |
||||||
|
|
||||||
|
**Advantages:** |
||||||
|
- Easy rendering (global positions readily available) |
||||||
|
- Easy SOI checks (global positions) |
||||||
|
- Clear separation of concerns |
||||||
|
- Memory negligible for ~14 bodies (48 bytes per body) |
||||||
|
|
||||||
|
### Physics Integration Flow |
||||||
|
|
||||||
|
``` |
||||||
|
Current: |
||||||
|
body (global) → RK4 in global coords → body (global) |
||||||
|
|
||||||
|
Proposed: |
||||||
|
body (local) → RK4 in local coords → body (local) → compute global |
||||||
|
``` |
||||||
|
|
||||||
|
### Update Order: Parent-First (Recommended) |
||||||
|
```cpp |
||||||
|
void update_simulation(SimulationState* sim) { |
||||||
|
// 1. Update all root bodies (in their own frame = global) |
||||||
|
for (int i = 0; i < sim->body_count; i++) { |
||||||
|
if (sim->bodies[i].parent_index == -1) { |
||||||
|
rk4_step_local(&sim->bodies[i], ctx, sim->dt); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// 2. Compute global positions for roots |
||||||
|
compute_global_coordinates_for_roots(sim); |
||||||
|
|
||||||
|
// 3. Update all child bodies (in parent's frame) |
||||||
|
for (int i = 0; i < sim->body_count; i++) { |
||||||
|
CelestialBody* body = &sim->bodies[i]; |
||||||
|
if (body->parent_index >= 0) { |
||||||
|
// Check for SOI transition |
||||||
|
int new_parent = find_dominant_body(sim, i); |
||||||
|
if (new_parent != body->parent_index && new_parent != -1) { |
||||||
|
transition_to_new_parent(body, body->parent_index, |
||||||
|
new_parent, sim); |
||||||
|
} |
||||||
|
|
||||||
|
// Integrate in local frame |
||||||
|
rk4_step_local(body, ctx, sim->dt); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// 4. Compute global positions for all children |
||||||
|
compute_global_coordinates_for_children(sim); |
||||||
|
|
||||||
|
sim->time += sim->dt; |
||||||
|
} |
||||||
|
``` |
||||||
|
|
||||||
|
### SOI Transition with Frame Transform |
||||||
|
|
||||||
|
**Critical piece for satellites and patched conics:** |
||||||
|
|
||||||
|
```cpp |
||||||
|
void transition_to_new_parent(CelestialBody* body, int old_parent_idx, |
||||||
|
int new_parent_idx, SimulationState* sim) { |
||||||
|
// Current state is in old parent's frame |
||||||
|
Vec3 old_local_pos = body->local_position; |
||||||
|
Vec3 old_local_vel = body->local_velocity; |
||||||
|
|
||||||
|
// Get old and new parent |
||||||
|
CelestialBody* old_parent = (old_parent_idx >= 0) |
||||||
|
? &sim->bodies[old_parent_idx] : NULL; |
||||||
|
CelestialBody* new_parent = &sim->bodies[new_parent_idx]; |
||||||
|
|
||||||
|
// Compute global position (or use cached global coords) |
||||||
|
Vec3 global_pos = old_parent ? vec3_add(old_local_pos, old_parent->position) |
||||||
|
: old_local_pos; |
||||||
|
Vec3 global_vel = old_parent ? vec3_add(old_local_vel, old_parent->velocity) |
||||||
|
: old_local_vel; |
||||||
|
|
||||||
|
// Transform to new parent's frame |
||||||
|
body->local_position = vec3_sub(global_pos, new_parent->position); |
||||||
|
body->local_velocity = vec3_sub(global_vel, new_parent->velocity); |
||||||
|
body->parent_index = new_parent_idx; |
||||||
|
} |
||||||
|
``` |
||||||
|
|
||||||
|
## Implementation Phases |
||||||
|
|
||||||
|
### Phase 1: Foundation (No Behavior Change) |
||||||
|
**Goal:** Add local coordinate storage without changing physics |
||||||
|
|
||||||
|
**Tasks:** |
||||||
|
1. Add `local_position` and `local_velocity` to `CelestialBody` |
||||||
|
2. Add `initialize_local_coordinates()` - convert global→local on load |
||||||
|
3. Add `compute_global_coordinates()` - convert local→global after update |
||||||
|
4. Modify `update_simulation()` to call both functions |
||||||
|
5. **Verify:** All tests still pass (same behavior) |
||||||
|
|
||||||
|
**Files to modify:** |
||||||
|
- `src/simulation.h` (add fields) |
||||||
|
- `src/simulation.cpp` (add conversion functions) |
||||||
|
- `src/config_loader.cpp` (call initialize_local_coordinates) |
||||||
|
|
||||||
|
**Estimated complexity:** Low |
||||||
|
**Risk:** Very low (pure refactor, no logic change) |
||||||
|
|
||||||
|
**Expected outcome:** |
||||||
|
- ✅ Dual coordinate storage in place |
||||||
|
- ✅ No behavior change (all tests same status) |
||||||
|
- ✅ Foundation for local frame integration |
||||||
|
|
||||||
|
--- |
||||||
|
|
||||||
|
### Phase 2: Local Frame Integration |
||||||
|
**Goal:** Actually integrate in local frames |
||||||
|
|
||||||
|
**Tasks:** |
||||||
|
1. Create `rk4_step_local()` - integrates using local coordinates |
||||||
|
2. Modify `evaluate_acceleration()` to work in local frame (parent at origin) |
||||||
|
3. Update `update_simulation()` to use local frame integration |
||||||
|
4. **Verify:** Moon tests improve (should see reduced drift) |
||||||
|
|
||||||
|
**Files to modify:** |
||||||
|
- `src/physics.cpp` (modify rk4_step, evaluate_acceleration) |
||||||
|
- `src/simulation.cpp` (update call sites) |
||||||
|
|
||||||
|
**Estimated complexity:** Medium |
||||||
|
**Risk:** Medium (core physics change) |
||||||
|
|
||||||
|
**Expected outcome:** |
||||||
|
- ✅ Moon drift issues **should be fixed** (improved numerical precision) |
||||||
|
- ✅ Test failures reduced (Moon, Io, Titan tests should pass) |
||||||
|
- ✅ Physics happens in local frames |
||||||
|
|
||||||
|
--- |
||||||
|
|
||||||
|
### Phase 3: SOI Transition with Frame Transform |
||||||
|
**Goal:** Properly handle coordinate transformations during SOI crossings |
||||||
|
|
||||||
|
**Tasks:** |
||||||
|
1. Create `transition_to_new_parent()` function |
||||||
|
2. Modify SOI transition logic in `update_simulation()` |
||||||
|
3. Add tests for comet SOI transitions (Sun→Mars→Sun) |
||||||
|
4. **Verify:** Comet test still passes with smooth transitions |
||||||
|
|
||||||
|
**Files to modify:** |
||||||
|
- `src/simulation.cpp` (SOI transition logic) |
||||||
|
- `tests/test_comet_orbit.cpp` (verify transitions) |
||||||
|
|
||||||
|
**Estimated complexity:** Medium |
||||||
|
**Risk:** Medium (affects patched conics later) |
||||||
|
|
||||||
|
**Expected outcome:** |
||||||
|
- ✅ SOI transitions properly transform coordinates |
||||||
|
- ✅ Foundation for patched conics implementation |
||||||
|
- ✅ Comet transitions validated |
||||||
|
|
||||||
|
--- |
||||||
|
|
||||||
|
### Phase 4: Parent-First Update Order |
||||||
|
**Goal:** Update hierarchy in correct order |
||||||
|
|
||||||
|
**Tasks:** |
||||||
|
1. Refactor `update_simulation()` to update roots first, then children |
||||||
|
2. Ensure parent global positions are current before children update |
||||||
|
3. **Verify:** No regression in tests |
||||||
|
|
||||||
|
**Files to modify:** |
||||||
|
- `src/simulation.cpp` (update_simulation) |
||||||
|
|
||||||
|
**Estimated complexity:** Low-Medium |
||||||
|
**Risk:** Low |
||||||
|
|
||||||
|
**Expected outcome:** |
||||||
|
- ✅ Hierarchical update order implemented |
||||||
|
- ✅ Parent positions current when updating children |
||||||
|
|
||||||
|
--- |
||||||
|
|
||||||
|
### Phase 5: Validation & Optimization |
||||||
|
**Goal:** Ensure correctness and performance |
||||||
|
|
||||||
|
**Tasks:** |
||||||
|
1. Add test for frame transformations |
||||||
|
2. Profile performance (should be similar or better) |
||||||
|
3. Add documentation comments explaining coordinate systems |
||||||
|
4. Update implementation_plan.md |
||||||
|
|
||||||
|
**Files to modify:** |
||||||
|
- `tests/` (new frame transform tests) |
||||||
|
- `docs/implementation_plan.md` |
||||||
|
|
||||||
|
**Expected outcome:** |
||||||
|
- ✅ Fully validated hierarchical coordinate system |
||||||
|
- ✅ Documentation complete |
||||||
|
- ✅ Ready for satellite/spacecraft simulation |
||||||
|
|
||||||
|
## Design Decisions |
||||||
|
|
||||||
|
### Config Format |
||||||
|
Keep global positions in config (backward compatible). Convert to local coordinates on load via `initialize_local_coordinates()`. |
||||||
|
|
||||||
|
### Storage Strategy |
||||||
|
Dual storage (both local and global) for performance and simplicity. |
||||||
|
|
||||||
|
### Multi-level Hierarchies |
||||||
|
Not implementing at this time. Maximum 2 levels: Sun→Planet→Moon. |
||||||
|
Design allows future extension to Sun→Planet→Moon→Satellite if needed. |
||||||
|
|
||||||
|
### Timestep Strategy |
||||||
|
Single global timestep for entire simulation during initial implementation. |
||||||
|
Per-level timesteps deferred for future optimization. |
||||||
|
|
||||||
|
## Risk Assessment |
||||||
|
|
||||||
|
**Low Risk:** |
||||||
|
- Phase 1 (pure refactor, no logic change) |
||||||
|
- Phase 4 (update order change) |
||||||
|
|
||||||
|
**Medium Risk:** |
||||||
|
- Phase 2 (core physics change - but testable) |
||||||
|
- Phase 3 (frame transforms - complex but well-defined) |
||||||
|
|
||||||
|
**Mitigation:** |
||||||
|
- Implement phases incrementally with manual review after each phase |
||||||
|
- Keep old code commented for comparison |
||||||
|
- Add validation tests at each phase |
||||||
|
- Can roll back if tests regress |
||||||
|
|
||||||
|
## Expected Final Outcomes |
||||||
|
|
||||||
|
After all phases complete: |
||||||
|
- ✅ Moon orbital stability vastly improved (test failures fixed) |
||||||
|
- ✅ Numerical precision improved for nested orbits |
||||||
|
- ✅ SOI transitions with proper coordinate frame transformations |
||||||
|
- ✅ Foundation for patched conics and satellite simulation |
||||||
|
- ✅ Parent-first hierarchical update order |
||||||
|
- ✅ Fully documented coordinate system architecture |
||||||
Loading…
Reference in new issue