Browse Source

Add adaptive timestepping to mission planning and remove obsolete patched_conics_plan

- Extract adaptive timestepping section from patched_conics_plan.md
- Add to mission_planning.md Future Work section (after Capture Burns)
- Problem: Fixed 60s timestep too coarse/fast for different orbital phases
- Solution: Adaptive timestep based on orbital period using Kepler's third law
- Implementation: calculate_adaptive_timestep() with 10s-600s clamping
- Delete obsolete patched_conics_plan.md (689 lines, superseded by implementation)
- Renumber sections 5-11 to accommodate new section 5
- Net reduction: ~645 lines of documentation
main
cinnaboot 6 months ago
parent
commit
fdd4ec3040
  1. 56
      docs/mission_planning.md
  2. 688
      docs/patched_conics_plan.md

56
docs/mission_planning.md

@ -370,22 +370,66 @@ Spacecraft may not enter Mars SOI due to:
- Support parking orbits at arrival body
- Validate Mars capture burns (~1.4 km/s for Mars)
#### 5. Adaptive Timestepping
**Problem:** Fixed 60s timestep is:
- Too coarse for fast orbital phases (moon capture, close approaches)
- Too slow for deep-space phases (interplanetary transfers)
**Solution:** Adaptive timestep based on orbital period
**Implementation:**
```cpp
double calculate_adaptive_timestep(CelestialBody* body, CelestialBody* parent) {
if (parent == NULL || body->semi_major_axis <= 0.0) {
return 60.0; // Default timestep
}
// Calculate orbital period using Kepler's third law
double T = 2.0 * M_PI * sqrt(pow(body->semi_major_axis, 3) / (G * parent->mass));
// Use 1/1000 of orbital period as timestep
double adaptive_dt = T / 1000.0;
// Clamp to reasonable bounds
adaptive_dt = fmax(adaptive_dt, 10.0); // Minimum 10s
adaptive_dt = fmin(adaptive_dt, 600.0); // Maximum 600s
return adaptive_dt;
}
```
**Changes required:**
- Add per-body timesteps to `SimulationState`
- Update `update_simulation()` to use adaptive timesteps
- Add synchronization mechanism for multiple timesteps
**Expected outcome:**
- Better accuracy for fast orbits (moon capture)
- Faster simulation for deep-space phases
- Energy conserved across SOI transitions
**Tests:**
- Verify energy drift with adaptive timesteps
- Verify orbital period accuracy with adaptive timesteps
- Test stability across SOI transitions
### Visualization Features
#### 5. Mission GUI
#### 6. Mission GUI
- Interactive departure window visualization
- Show current phase angle vs. required phase angle
- Countdown to launch window
- Transfer trajectory preview (predicted path)
- Delta-v budget display
#### 6. Multiple Burns Support
#### 7. Multiple Burns Support
- Mid-course corrections
- Gravity assist maneuvers
- Powered flybys
- Multi-stage missions
#### 7. SOI Visualization
#### 8. SOI Visualization
- Render SOI boundaries as wireframe spheres
- Color-coded by mass
- Toggle with keyboard shortcut
@ -393,20 +437,20 @@ Spacecraft may not enter Mars SOI due to:
### Advanced Features
#### 8. Mission Planner
#### 9. Mission Planner
- Complete mission design tool
- Multi-leg missions (Earth→Mars→Phobos)
- Optimization algorithms (minimum Δv, minimum time)
- Launch date search across windows
- Mission timeline visualization
#### 9. Real Ephemeris Integration
#### 10. Real Ephemeris Integration
- Use actual planetary positions (JPL Horizons API)
- Date-based initialization
- Real mission planning with actual ephemeris data
- Compare simulation to historical missions
#### 10. Enhanced Trajectory Analysis
#### 11. Enhanced Trajectory Analysis
- Lambert solver for general transfers
- Not just Hohmann transfers
- Arbitrary departure/arrival positions and times

688
docs/patched_conics_plan.md

@ -1,688 +0,0 @@
# Patched Conics and SOI Transition Implementation Plan
**Date:** January 14, 2026
**Status:** Implementation Ready (Decisions Made)
**Branch:** patched-conics
**Decisions Made:**
1. ✅ Hysteresis: Adaptive approach (Option B)
2. ✅ Integration timing: Current approach (Option A), TODO for future
3. ✅ Test priorities: Create all 3 test cases first
4. ✅ Adaptive timesteps: Deferred to later work (Phase 5)
**Next Step:** Begin Phase 1 - Fix Root Body Transitions
## Overview
This plan implements support for patched conics trajectory simulation, enabling satellites to transition between multiple spheres of influence (SOI) in complex orbital scenarios:
- Planet → Star → Planet transfers
- Star → Planet → Moon rendezvous
- Multi-leg interplanetary missions
## Current State Analysis
### ✅ What's Already Working
1. **SOI Transitions Are Already Implemented**
- Lines 103-121 in `simulation.cpp` show coordinate transformation logic
- Converts local→global using old parent, then global→local using new parent
- This is essentially Phase 3 implementation from hierarchical_frames_plan.md
2. **Local Frame Integration** (Phase 2) ✅
- All bodies integrate in local coordinates
- Global coordinates computed after each timestep
- Improved numerical precision for nested orbits
3. **Parent-First Update Order** (Phase 4) ✅
- Root bodies skipped in loop (fixed at origin)
- Child bodies integrate using parent coordinates
- Hierarchical update order implemented
### 🔴 Critical Issues for Patched Conics
**Issue 1: Cannot Transition to Root Bodies**
```cpp
if (new_parent != body->parent_index && new_parent != -1) {
// ... transition logic
}
```
The `new_parent != -1` condition prevents switching to Sun (parent_index = -1). This breaks the scenario: Planet→Sun→Moon rendezvous is impossible.
**Issue 2: Hysteresis Barrier**
The 0.5x hysteresis factor in `find_dominant_body()` (line 71) creates one-way barriers:
- Planet→Sun: Possible (easy entry)
- Sun→Planet: **Impossible** (can't exit due to hysteresis)
**Issue 3: Integration After Transition**
Transition happens before integration in the same timestep, using coordinates from the end of the previous timestep. This may cause velocity discontinuities.
### ⚠ Potential Issues
**Issue 4: Numerical Precision**
Satellites crossing between star/planet/moon scales will see position magnitude changes of 10⁸ to 10¹¹ meters, potentially losing precision.
**Issue 5: Fixed Timestep**
60s timestep may be too coarse for fast orbital phases (moon capture) and too slow for deep-space phases.
## Implementation Phases
### Phase 1: Fix Root Body Transitions (Critical)
**Goal:** Allow satellites to switch to/from Sun (parent_index = -1)
**Changes:**
1. Remove `new_parent != -1` check in `simulation.cpp` line 104
2. Add special handling for root body transitions:
```cpp
if (new_parent != body->parent_index) {
// Convert local → global using old parent
if (body->parent_index >= 0) {
// old_parent is a real body
CelestialBody* old_parent = &sim->bodies[body->parent_index];
body->position = vec3_add(body->local_position, old_parent->position);
body->velocity = vec3_add(body->local_velocity, old_parent->velocity);
} else {
// old_parent is root (Sun): local = global
body->position = body->local_position;
body->velocity = body->local_velocity;
}
body->parent_index = new_parent;
// Convert global → local using new parent
if (new_parent >= 0) {
// new_parent is a real body
CelestialBody* new_parent_body = &sim->bodies[new_parent];
body->local_position = vec3_sub(body->position, new_parent_body->position);
body->local_velocity = vec3_sub(body->velocity, new_parent_body->velocity);
} else {
// new_parent is root (Sun): global = local
body->local_position = body->position;
body->local_velocity = body->velocity;
}
}
```
3. **Update `find_dominant_body()`** to properly handle -1 returns
**Files to modify:**
- `src/simulation.cpp` (lines 103-121)
- `src/simulation.h` (no changes needed)
**Estimated complexity:** Low
**Risk:** Medium (affects core transition logic)
**Expected outcome:**
- ✅ Satellites can transition to/from Sun
- ✅ Enables Planet→Sun→Planet transfers
- ✅ Enables Star→Planet→Moon rendezvous
**Tests to add:**
- Test satellite transitioning from Earth to Sun
- Test satellite transitioning from Sun to Mars
- Test full round-trip: Earth→Sun→Earth
---
### Phase 2: Adaptive Hysteresis (Critical for Round-Trips)
**Current Problem:**
The 0.5x hysteresis factor prevents oscillation but creates one-way barriers:
```cpp
if (distance < dist_to_current * 0.5) {
dominant = i;
}
```
**Decision:** Adaptive Hysteresis (Option B) - **DECIDED ✅**
- Keep hysteresis but only apply when already in SOI
- Allow free switching when outside current SOI
- **Pros:** Prevents oscillation while enabling round-trips
- **Cons:** More complex logic
**Option B Implementation:**
```cpp
if (can_switch && i != dominant) {
if (dominant == -1) {
dominant = i;
} else {
CelestialBody* current_parent = &sim->bodies[dominant];
double dist_to_current = vec3_distance(body->position, current_parent->position);
if (outside_current_soi) {
// Outside current SOI: switch to closest body (no hysteresis)
if (distance < dist_to_current) {
dominant = i;
}
} else {
// Inside current SOI: apply hysteresis to prevent oscillations
if (distance < dist_to_current * 0.5) {
dominant = i;
}
}
}
}
```
**Files to modify:**
- `src/simulation.cpp` (line 70-75)
**Estimated complexity:** Low-Medium
**Risk:** Medium (may affect transition behavior)
**Expected outcome:**
- ✅ Enables round-trip transitions (Earth→Sun→Earth)
- ✅ Maintains stability by preventing oscillation when inside SOI
- ✅ Allows free switching when outside current SOI
**Tests to add:**
- Validate Satellite→Planet→Satellite round-trip
- Validate Earth→Sun→Mars→Sun→Earth full round-trip
---
### Phase 3: Refactor Transition to Separate Function
**Goal:** Cleaner code, easier to test, better separation of concerns
**Current state:** Transition logic is inline in `update_simulation()` (lines 105-120)
**Proposed refactoring:**
**Add to `simulation.h`:**
```cpp
void transition_to_new_parent(SimulationState* sim, CelestialBody* body,
int old_parent_idx, int new_parent_idx);
```
**Add to `simulation.cpp`:**
```cpp
void transition_to_new_parent(SimulationState* sim, CelestialBody* body,
int old_parent_idx, int new_parent_idx) {
// Current state is in old parent's frame
Vec3 old_local_pos = body->local_position;
Vec3 old_local_vel = body->local_velocity;
// Convert to global coordinates using old parent
if (old_parent_idx >= 0 && old_parent_idx < sim->body_count) {
CelestialBody* old_parent = &sim->bodies[old_parent_idx];
body->position = vec3_add(old_local_pos, old_parent->position);
body->velocity = vec3_add(old_local_vel, old_parent->velocity);
} else {
// old_parent is root (Sun): local = global
body->position = old_local_pos;
body->velocity = old_local_vel;
}
// Update parent index
body->parent_index = new_parent_idx;
// Convert to local coordinates using new parent
if (new_parent_idx >= 0 && new_parent_idx < sim->body_count) {
CelestialBody* new_parent_body = &sim->bodies[new_parent_idx];
body->local_position = vec3_sub(body->position, new_parent_body->position);
body->local_velocity = vec3_sub(body->velocity, new_parent_body->velocity);
} else {
// new_parent is root (Sun): global = local
body->local_position = body->position;
body->local_velocity = body->velocity;
}
}
```
**Update `update_simulation()`:**
```cpp
int new_parent = find_dominant_body(sim, i);
if (new_parent != body->parent_index) {
transition_to_new_parent(sim, body, body->parent_index, new_parent);
}
```
**Files to modify:**
- `src/simulation.h` (add function declaration)
- `src/simulation.cpp` (extract and refactor transition logic)
**Estimated complexity:** Low
**Risk:** Low (pure refactor, no behavior change)
**Expected outcome:**
- ✅ Cleaner code with better separation of concerns
- ✅ Easier to unit test transition logic
- ✅ Follows Phase 3 plan from hierarchical_frames_plan.md
**Tests to add:**
- Unit tests for `transition_to_new_parent()` with all scenarios:
- Body→Body transition
- Body→Root transition
- Root→Body transition
- Root→Root transition (edge case)
---
### Phase 4: Multi-Body Transition Test Configs
**Goal:** Create realistic test scenarios for patched conics
**Decision:** Create all three test cases first, expect failures for unimplemented features - **DECIDED ✅**
**Implementation approach:**
1. Create all three test configurations
2. Run tests to establish baseline failures
3. Tests validate features as they're implemented
4. Comprehensive coverage from the start
#### Test Config 1: Satellite Rendezvous
**File:** `tests/configs/satellite_rendezvous.toml`
```toml
[[bodies]]
name = "Sun"
mass = 1.989e30
radius = 6.96e8
position = { x = 0.0, y = 0.0, z = 0.0 }
parent_index = -1
color = { r = 1.0, g = 1.0, b = 0.0 }
eccentricity = 0.0
semi_major_axis = 0.0
[[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
[[bodies]]
name = "Moon"
mass = 7.342e22
radius = 1.737e6
position = { x = 1.49984e11, y = 0.0, z = 0.0 }
parent_index = 1
color = { r = 0.7, g = 0.7, b = 0.7 }
eccentricity = 0.0
semi_major_axis = 3.844e8
[[bodies]]
name = "Satellite"
mass = 1.0e3
radius = 1.0e1
position = { x = 1.500e11, y = 1.0e8, z = 0.0 }
parent_index = 1
color = { r = 1.0, g = 0.0, b = 1.0 }
eccentricity = 0.2
semi_major_axis = 4.0e8
```
**Scenario:** Satellite launches from Earth, transfers to Moon, returns
#### Test Config 2: Interplanetary Transfer
**File:** `tests/configs/interplanetary_transfer.toml`
```toml
[[bodies]]
name = "Sun"
mass = 1.989e30
radius = 6.96e8
position = { x = 0.0, y = 0.0, z = 0.0 }
parent_index = -1
color = { r = 1.0, g = 1.0, b = 0.0 }
eccentricity = 0.0
semi_major_axis = 0.0
[[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
[[bodies]]
name = "Mars"
mass = 6.39e23
radius = 3.3895e6
position = { x = 2.279e11, y = 0.0, z = 0.0 }
parent_index = 0
color = { r = 0.8, g = 0.3, b = 0.1 }
eccentricity = 0.0
semi_major_axis = 2.279e11
[[bodies]]
name = "Probe"
mass = 1.0e3
radius = 1.0e1
position = { x = 1.496e11, y = 0.0, z = 0.0 }
parent_index = 1
color = { r = 0.0, g = 1.0, b = 0.0 }
eccentricity = 0.5
semi_major_axis = 1.888e11
```
**Scenario:** Probe: Earth→Sun→Mars
#### Test Config 3: Moon Capture
**File:** `tests/configs/moon_capture.toml`
```toml
[[bodies]]
name = "Sun"
mass = 1.989e30
radius = 6.96e8
position = { x = 0.0, y = 0.0, z = 0.0 }
parent_index = -1
color = { r = 1.0, g = 1.0, b = 0.0 }
eccentricity = 0.0
semi_major_axis = 0.0
[[bodies]]
name = "Jupiter"
mass = 1.898e27
radius = 6.9911e7
position = { x = 7.785e11, y = 0.0, z = 0.0 }
parent_index = 0
color = { r = 0.9, g = 0.7, b = 0.5 }
eccentricity = 0.0
semi_major_axis = 7.785e11
[[bodies]]
name = "Ganymede"
mass = 1.48e23
radius = 2.634e6
position = { x = 7.796e11, y = 0.0, z = 0.0 }
parent_index = 1
color = { r = 0.6, g = 0.6, b = 0.5 }
eccentricity = 0.0
semi_major_axis = 1.070e9
[[bodies]]
name = "Comet"
mass = 1.0e14
radius = 5.0e3
position = { x = 1.0e12, y = 0.0, z = 0.0 }
parent_index = 0
color = { r = 0.5, g = 0.8, b = 1.0 }
eccentricity = 2.0
semi_major_axis = -5.0e11
```
**Scenario:** Comet: Sun→Jupiter→Ganymede→Sun
**Files to create:**
- `tests/configs/satellite_rendezvous.toml`
- `tests/configs/interplanetary_transfer.toml`
- `tests/configs/moon_capture.toml`
**Estimated complexity:** Low
**Risk:** Low (configs only, no code changes)
**Expected outcome:**
- ✅ Realistic test scenarios for patched conics
- ✅ Covers multi-leg missions
- ✅ Tests root body transitions
---
### Phase 5: Adaptive Timestepping (Performance + Accuracy)
**Goal:** Different timesteps for different orbital phases
**Decision:** DEFERRED to later work - **DECIDED ✅**
**Problem:** Fixed 60s timestep is:
- Too coarse for fast orbital phases (moon capture)
- Too slow for deep-space phases
**Proposed solution:** Adaptive timestep based on orbital period
**Implementation:**
```cpp
double calculate_adaptive_timestep(CelestialBody* body, CelestialBody* parent) {
if (parent == NULL || body->semi_major_axis <= 0.0) {
return 60.0; // Default timestep
}
// Calculate orbital period using Kepler's third law
double T =2.0 * M_PI * sqrt(pow(body->semi_major_axis, 3) / (G * parent->mass));
// Use 1/1000 of orbital period as timestep
double adaptive_dt = T / 1000.0;
// Clamp to reasonable bounds
adaptive_dt = fmax(adaptive_dt, 10.0); // Minimum 10s
adaptive_dt = fmin(adaptive_dt, 600.0); // Maximum 600s
return adaptive_dt;
}
```
**Changes required:**
1. Add per-body timesteps to `SimulationState`
2. Update `update_simulation()` to use adaptive timesteps
3. Add synchronization mechanism (multiple timesteps)
**Complexity:** High
**Risk:** High (may affect energy conservation, requires careful testing)
**Expected outcome:**
- ✅ Better accuracy for fast orbits (moon capture)
- ✅ Faster simulation for deep-space phases
- ✅ Energy conserved across transitions
**Tests to add:**
- Verify energy drift with adaptive timesteps
- Verify orbital period accuracy with adaptive timesteps
- Test stability across SOI transitions
---
### Phase 6: Enhanced Debugging & Visualization
**Goal:** Better tools for debugging transitions and planning missions
**Features to add:**
#### 6.1 Transition Logging
```cpp
void log_transition(SimulationState* sim, CelestialBody* body,
int old_parent, int new_parent, double time) {
printf("[%.2f days] %s: parent %d → %d\n",
time / 86400.0, body->name, old_parent, new_parent);
}
```
#### 6.2 Visual SOI Boundaries
- Add wireframe spheres in renderer for SOI radii
- Toggle with keyboard key
- Use different colors for different bodies
#### 6.3 Trajectory Prediction
- Predict future trajectory for given time span
- Show predicted SOI crossings
- Assist with mission planning
**Files to modify:**
- `src/simulation.cpp` (logging)
- `src/renderer.cpp` (SOI visualization)
- `src/renderer.cpp` (trajectory prediction - new function)
**Estimated complexity:** Medium
**Risk:** Low (mostly UI/visualization)
**Expected outcome:**
- ✅ Better debugging tools for transitions
- ✅ Visual SOI boundaries
- ✅ Trajectory prediction for mission planning
---
## Decisions Made
### Decision 1: Hysteresis Strategy ✅
**Chosen:** Option B - Adaptive hysteresis approach
**Rationale:**
- Prevents oscillation while enabling round-trips
- Maintains stability during normal operation
- Allows free switching when outside current SOI
- Best balance between stability and flexibility
**Implementation:** Will use adaptive hysteresis in Phase 2 (lines 70-75 in simulation.cpp)
---
### Decision 2: Integration Timing ✅
**Chosen:** Option A - Keep current approach (transition at start of timestep)
**Rationale:**
- Simple, works for most cases
- Start with proven approach
- Defer optimization to future work
**TODO:** Consider half-step transitions (Option B) if velocity discontinuities become problematic
---
### Decision 3: Test Priorities ✅
**Chosen:** Option C - Implement all three test cases first
**Rationale:**
- Create all test configurations upfront
- Expect failures for unimplemented features
- Use tests as validation throughout implementation
- Comprehensive coverage from the start
**Implementation:**
1. Create all three test configs (Phase 4)
2. Run tests to establish baseline failures
3. Implement features to make tests pass
4. Re-run tests after each phase
**Test scenarios:**
- Satellite Rendezvous (Earth→Moon→Earth)
- Interplanetary Transfer (Earth→Sun→Mars)
- Moon Capture (Sun→Jupiter→Ganymede→Sun)
---
### Decision 4: Adaptive Timesteps Priority ✅
**Chosen:** Option B - Defer to later work
**Rationale:**
- Focus on SOI transitions first
- Fixed 60s timestep works adequately for testing
- Optimize performance and accuracy after core features complete
**TODO:** Implement adaptive timesteps in future update (Phase 5)
- Will address: Too coarse for fast orbits, too slow for deep space
- Estimated complexity: High
- Timeline: 2-3 days
---
## Success Criteria
### Phase 1 Success
- [ ] Satellite can transition to/from Sun
- [ ] Tests pass for Earth→Sun→Mars
- [ ] No energy conservation issues during transitions
### Phase 2 Success
- [ ] Round-trip transitions work (Earth→Sun→Earth)
- [ ] No oscillation at SOI boundaries
- [ ] Tests validate stability
### Phase 3 Success
- [ ] Transition logic extracted to separate function
- [ ] Unit tests cover all transition scenarios
- [ ] Code is cleaner and more maintainable
### Phase 4 Success
- [ ] Three test configs created
- [ ] Baseline test failures documented
- [ ] Configs are realistic and well-documented
### Phase 5 Success (Deferred)
- [ ] Adaptive timesteps implemented
- [ ] Energy drift < 1% with adaptive timesteps
- [ ] Performance improved for deep-space phases
### Phase 6 Success (Optional)
- [ ] Transition logging works
- [ ] SOI boundaries visualized
- [ ] Trajectory prediction functional
---
## Timeline Estimate
- **Phase 1:** 1-2 days (fix root body transitions)
- **Phase 2:** 1 day (adaptive hysteresis - decision made ✅)
- **Phase 3:** 0.5 days (refactoring)
- **Phase 4:** 1 day (test configs - create all three first)
- **Phase 5:** 2-3 days (adaptive timesteps - DEFERRED ⏸)
- **Phase 6:** 1-2 days (debugging/visualization - optional)
**Total for core features (Phases 1-4):** 4-5 days
**Total with all features:** 8-10 days (including deferred Phases 5-6)
**Implementation approach:**
1. Create all three test configs (Phase 4)
2. Implement core transition features (Phases 1-3)
3. Validate with tests after each phase
4. Defer Phases 5-6 to future work
---
## Dependencies
### Required
- ✅ Hierarchical coordinate frames (complete)
- ✅ Local frame integration (complete)
- ✅ Parent-first update order (complete)
- ⏸ Root body transitions (Phase 1 - pending)
### Optional
- ⏸ Adaptive timesteps (Phase 5 - optional)
- ⏸ Debugging tools (Phase 6 - optional)
---
## Risks and Mitigations
### High Risk
- **Energy conservation during transitions**
- Mitigation: Careful testing, energy drift checks
- Backup: Keep old code for rollback
- **Numerical precision across scales**
- Mitigation: Use local frames (already implemented)
- Backup: Double precision (already used)
### Medium Risk
- **Oscillation at SOI boundaries**
- Mitigation: Adaptive hysteresis (Phase 2)
- Backup: Increase hysteresis factor if needed
- **Timestep too coarse for fast orbits**
- Mitigation: Adaptive timesteps (Phase 5 - optional)
- Backup: Reduce fixed timestep if needed
### Low Risk
- **Code complexity increases**
- Mitigation: Good unit tests, refactoring (Phase 3)
- Backup: Keep functions small and focused
---
## References
- `docs/hierarchical_frames_plan.md` - Phase 3: SOI Transition with Frame Transform
- `docs/implementation_plan.md` - SOI Transition Mechanics section
- `src/simulation.cpp` - Current SOI transition implementation (lines 103-121)
- `tests/test_soi_transition.cpp` - Current SOI transition tests
Loading…
Cancel
Save