Browse Source

clean up documentation

main
cinnaboot 6 months ago
parent
commit
8d751cc996
  1. 77
      docs/find_dominant_body_bug.md
  2. 455
      docs/mission_planning.md
  3. 240
      docs/test_plan_invalid_parent_assignment.md

77
docs/find_dominant_body_bug.md

@ -0,0 +1,77 @@
# Find Dominant Body Bug: Mutual SOI Issue
## Overview
This documents the remaining issue with `find_dominant_body()` when two similar-mass bodies are positioned within each other's sphere of influence (SOI).
**Date:** January 20, 2026
**Status:** Failing Test (Test 4 from test_plan_invalid_parent_assignment.md)
**Related:** `docs/test_plan_invalid_parent_assignment.md`
---
## Test Case 4: Mutual SOI - Similar Mass Planets
**Purpose:** Edge case: two Earth-like planets positioned within each other's SOI
**Actual Result:** ❌ **STILL FAILS** (separate issue, not fixed by spacecraft validation)
**Config:** `tests/configs/mutual_soi_close.toml`
**Setup:**
- PlanetA: mass = 5.972e24 kg, position = {1.496e11, 0, 0}
- PlanetB: mass = 5.972e24 kg, position = {1.501e11, 0, 0}
- Separation: 5e8 meters (500 million km)
- Planet SOI: ~9.25e8 meters (925 million km)
- **Both planets within each other's SOI**
**Why This Fails:**
- Both planets start with parent=0 (Sun)
- Both are within each other's SOI
- `find_dominant_body()` logic selects closest body within SOI
- Result: PlanetA selects PlanetB as parent, PlanetB selects PlanetA as parent
- Config validation passes (both are ≥ parent.radius + body.radius from Sun)
**Key Assertions:**
```cpp
// Both should orbit Sun (not each other)
REQUIRE(sim->bodies[PLANET_A_IDX].parent_index == SUN_IDX);
REQUIRE(sim->bodies[PLANET_B_IDX].parent_index == SUN_IDX);
// Planets should never have each other as parents
for (int parent : history.planet_a_parents) {
REQUIRE(parent != PLANET_B_IDX);
}
for (int parent : history.planet_b_parents) {
REQUIRE(parent != PLANET_A_IDX);
}
```
**Expected Behavior (Option A):**
- Both planets should continue orbiting Sun
- Neither should become other's parent
- This requires future fix to `find_dominant_body()` logic (mass hierarchy check)
---
## Future Work
### Current Status
Tests 1-3 from the parent assignment test suite are now passing. Test 4 continues to fail, documenting a separate mutual SOI issue.
### Potential Fixes for Test 4
1. Add mass hierarchy check to `find_dominant_body()`
2. Prevent mutual SOI assignments for similar-mass bodies
3. Detect and reject invalid configs at load time
4. Implement proper N-body interaction or restricted 3-body solution
### Enhanced Detection
- SOI overlap detection at config load time
- Automatic correction of invalid parent assignments
- Validation warnings for edge cases
---
## References
- `src/simulation.cpp:64-107` - `find_dominant_body()` implementation
- `tests/configs/mutual_soi_close.toml` - Test configuration for mutual SOI case
- `tests/test_invalid_parent_assignment.cpp` - Test suite implementation

455
docs/mission_planning.md

@ -1,455 +0,0 @@
# Implementation Plan: Config-Based Spacecraft with Impulse Burn
## Overview
Replace dynamic spacecraft spawning with config-based LEO spacecraft, implement patched conics impulse burn for Hohmann transfer, and add comprehensive test verification.
**Date:** January 18, 2026
**Status:** partially implemented
**Branch:** mission-planning
---
## Phase 1: Update Configuration File
### Step 1.1: Add spacecraft to `tests/configs/earth_mars_simple.toml`
Add Spacecraft body to config with placeholder position/velocity (set at runtime by `initialize_spacecraft_leo()`).
**Implementation:** See `tests/configs/earth_mars_simple.toml` for full config
**Key parameters:**
- mass = 1.0 kg (test particle)
- radius = 1000.0 m
- parent_index = 1 (Earth)
- color = magenta (r=1.0, g=0.0, b=0.5)
- position/velocity: Placeholders (0,0,0)
**TODO**: Future config format should support:
- Earth-relative position: `{ altitude_km = 200.0 }`
- Earth-relative orbit: `{ orbit_type = "circular" }`
- More intuitive spacecraft mission parameters
---
## Phase 2: Mission Planning Module - New Functions
### Step 2.1: Add function declarations to `src/mission_planning.h`
**Implementation:** See `src/mission_planning.h`
**Functions:**
- `initialize_spacecraft_leo()` - Initialize spacecraft in circular LEO around parent body
- `apply_transfer_burn()` - Apply patched conics impulse burn for Hohmann transfer
- `calculate_phase_angle()` - Calculate current phase angle between two bodies (in degrees)
### Step 2.2: Implement `initialize_spacecraft_leo()` in `src/mission_planning.cpp`
**Implementation:** `src/mission_planning.cpp:20-56`
**Algorithm:**
- Calculate orbital radius = parent radius + altitude
- Position spacecraft radially outward from Sun (any angular position acceptable)
- Calculate circular LEO velocity: v = sqrt(G * M_parent / r)
- Set prograde orientation (tangential to Earth-Sun line)
- Set both local and global coordinates correctly
**Key Points:**
- LEO orbit is circular at 200km altitude (~7,788 m/s)
- Spacecraft velocity = Earth velocity + LEO velocity
- Local velocity = LEO velocity only (relative to Earth)
### Step 2.3: Implement `calculate_phase_angle()` in `src/mission_planning.cpp`
**Implementation:** `src/mission_planning.cpp:58-78`
**Algorithm:**
- Calculate angular positions of departure and arrival bodies relative to Sun
- Compute phase difference: θ_arrival - θ_departure
- Normalize to [0°, 360°) range
- Return phase angle in degrees
### Step 2.4: Implement `apply_transfer_burn()` in `src/mission_planning.cpp`
**Implementation:** `src/mission_planning.cpp:80-116`
**Algorithm (Patched Conics Approach):**
- Calculate required heliocentric transfer velocity magnitude from params
- Determine prograde direction (tangential to departure-Sun line)
- Compute delta-v: Δv = v_transfer - v_current (vector subtraction)
- Apply impulse to spacecraft velocity
- Update local velocity relative to departure body
- Print burn information for debugging
**Note:** Simplified single-impulse approximation. True patched conics would:
1. Calculate Δv to reach SOI boundary
2. Calculate velocity at SOI boundary
3. Add transfer Δv at SOI boundary
4. Combine into equivalent single impulse
---
## Phase 3: Comprehensive Test Case
### Step 3.1: Create new test in `tests/test_hohmann_transfer.cpp`
**Implementation:** `tests/test_hohmann_transfer.cpp` - See file for full test
**Test:** "Earth → Mars Hohmann Transfer with LEO Spacecraft"
**Test Structure:**
1. Load config with 4 bodies (Sun, Earth, Mars, Spacecraft)
2. Initialize spacecraft in 200km LEO around Earth
3. Verify LEO orbit stability (parent, position, velocity, energy)
4. Calculate Hohmann transfer parameters
5. Wait for Earth-Mars launch window (within 1° tolerance)
6. Verify phase angle accuracy
7. Apply impulse burn for transfer
8. Verify post-burn energy >= 0 (escape trajectory)
9. Simulate transfer for 110% of expected duration
10. Track SOI transitions (Earth→Sun→Mars)
11. Verify final parent and energy conservation (<5% drift)
12. If Mars SOI entry, verify distance (<2×SOI)
**Key Assertions:**
- Config loading: 4 bodies loaded, spacecraft present
- LEO stability: parent=Earth, position <1km error, velocity <10m/s error, energy <0
- Launch window: opens in ~94 days, phase error <1°
- Transfer: post-burn energy >= 0, Earth→Sun SOI transition, energy conservation
---
## Current Issue Identified
### Problem: Incorrect Delta-V Direction After Multi-Day Wait
**RESOLVED (Jan 20, 2026):**
The FIXME issue below has been addressed by adding config validation in
`src/config_loader.cpp` that prevents bodies from starting too close to their
parent bodies. The spacecraft configuration has been corrected to use proper LEO
altitude (200km) instead of placeholder values.
**Solution Applied:**
- Config validation: distance ≥ parent.radius + body.radius
- Spacecraft position corrected to 1.49606571e11 m (Earth + 6,571 km offset)
- Tests 1-3 in `test_invalid_parent_assignment.cpp` now pass
**FIXME (Original Issue - RESOLVED):**
While running this simulation config graphically, I noticed that a larger
problem is in simulation::find_dominant_body(). Earth's parent gets set to
the satellite's index, which should never happen.
I think the actual fix should be to have non-massive satellites in a different
array than celestial bodies, and treat them differently.
However, we should add more testing for the case that a comet or other massive
celestial body gets close to another body.
We do have tests/test_soi_transition.cpp, and tests/configs/soi_transition.toml
so maybe it's an initialization problem because the new test config starts
with both bodies in each others SOI?
**Symptom:**
- Spacecraft enters LEO orbit correctly with negative energy (bound to Earth)
- Waits 94 days for Earth-Mars launch window
- During wait period, spacecraft completes ~6.3 LEO orbits
- LEO orbit phase changes significantly over 94 days
- After wait, `apply_transfer_burn()` applies delta-v assuming spacecraft is at Earth's current orbital phase
- Result: Delta-v applied in wrong direction, resulting in retrograde burn
- Post-burn energy remains negative (spacecraft still bound to Earth)
**Root Cause Analysis:**
The `apply_transfer_burn()` function calculates:
1. Required heliocentric transfer velocity magnitude: `v_transfer = 32,697 m/s`
2. Prograde direction based on Earth's current position: `transfer_dir = prograde(t_current)`
3. Target velocity: `v_target = v_transfer * transfer_dir`
However, after 94 days:
- Earth has moved to different orbital phase
- Spacecraft in LEO is still orbiting Earth
- Spacecraft's current heliocentric velocity includes Earth's motion + LEO motion
- The calculated transfer direction is based on Earth's instantaneous position, not spacecraft's actual heliocentric velocity vector
- This results in delta-v that doesn't account for spacecraft's phase in LEO
**What Should Happen:**
1. Calculate spacecraft's current heliocentric velocity vector: `v_current`
2. Calculate required heliocentric velocity for transfer orbit: `v_transfer`
3. Apply delta-v: `Δv = v_transfer - v_current` (vector subtraction, not magnitude-based)
**What Currently Happens:**
1. Assumes spacecraft starts at Earth's orbital position (ignores LEO phase)
2. Calculates transfer direction based on Earth's current prograde vector
3. Applies magnitude-based delta-v without considering spacecraft's actual velocity direction
4. Results in incorrect burn direction
### Solution Required (Pending)
NOTE: The immediate bug of Earth becoming a child of spacecraft has been
resolved by config validation. The delta-v calculation issue below remains for
future implementation.
Modify `apply_transfer_burn()` to:
1. **Calculate spacecraft's actual heliocentric velocity:**
```cpp
Vec3 v_current_helio = spacecraft->velocity; // Already in global frame
```
2. **Calculate required heliocentric transfer velocity:**
```cpp
double v_transfer_mag = params->departure_velocity; // ~32,697 m/s
// Direction: prograde to Sun (same as Earth's orbital direction)
Vec3 sun_to_earth = vec3_sub(departure->position, sun->position);
Vec3 sun_to_earth_norm = vec3_normalize(sun_to_earth);
Vec3 transfer_dir = (Vec3){-sun_to_earth_norm.y, sun_to_earth_norm.x, 0.0};
Vec3 v_transfer_helio = vec3_scale(transfer_dir, v_transfer_mag);
```
3. **Calculate delta-v as vector difference:**
```cpp
Vec3 delta_v = vec3_sub(v_transfer_helio, v_current_helio);
```
4. **Apply impulse:**
```cpp
spacecraft->velocity = vec3_add(spacecraft->velocity, delta_v);
spacecraft->local_velocity = vec3_sub(spacecraft->velocity, departure->velocity);
```
**This approach:**
- Accounts for spacecraft's actual heliocentric velocity (includes LEO phase)
- Uses vector subtraction instead of magnitude-based calculation
- Produces correct delta-v direction regardless of LEO phase
- Should result in positive post-burn energy (escape trajectory)
---
## Potential Issues and Mitigation
### Issue 1: LEO Orbit Position Sensitivity
Spacecraft LEO phase may affect optimal launch window timing.
**Mitigation**: Test shows we wait for Earth-Mars phase angle, not spacecraft-LEO phase. This should be acceptable.
### Issue 2: Impulse Burn Accuracy
Single-impulse approximation may not match true patched conics trajectory.
**Mitigation**: Initial test focuses on Earth→Sun transition and energy conservation. If needed, can refine to two-impulse burn in future.
### Issue 3: Mars SOI Entry
Spacecraft may not enter Mars SOI due to:
- Phase angle tolerance (1°)
- Transfer time approximation
- Impulse burn simplifications
**Mitigation**: Test includes explicit INFO messages and requires only Earth→Sun transition, not Mars arrival.
---
## Timeline Estimate
- Phase 0 (Git workflow): 10 minutes
- Phase 1 (Config update): 5 minutes
- Phase 2 (Mission planning): 1-2 hours
- Phase 3 (Comprehensive test): 30 minutes
- Phase 4 (Build and test): 20 minutes
- Phase 5 (Cleanup): 20 minutes
**Total**: 2-3 hours
---
## Test Configuration Reference
### earth_mars_simple.toml
**Implementation:** `tests/configs/earth_mars_simple.toml`
**Bodies:**
- Sun (index 0): Root body, 1.989e30 kg
- Earth (index 1): 5.972e24 kg, 1.496e11 m from Sun
- Mars (index 2): 6.39e23 kg, 2.279e11 m from Sun
- Spacecraft (index 3): 1.0 kg, parent=Earth (position specified in config)
**Spacecraft parameters:**
- mass = 1.0 kg
- radius = 1000.0 m
- parent_index = 1 (Earth)
- color = magenta (r=1.0, g=0.0, b=0.5)
- position: 1.49606571e11 m (Earth position + 6,571,000 m LEO offset)
- velocity: Calculated by `initialize_bodies()` using `semi_major_axis = 6.571e6`
---
## Future Work (Post-Implementation)
### Immediate Next Steps
**TODO: Spacecraft Config Pattern Changes**
Spacecraft now requires full position specification in config files:
- Removed placeholder pattern that expected `initialize_spacecraft_leo()` to set position at runtime
- Position must be: parent position + orbital altitude offset
- Example: Earth LEO at 200km = Earth radius (6.371e6 m) + 200,000 m = 6.571e6 m offset
- Velocity is calculated by `initialize_bodies()` using `semi_major_axis` parameter
**Impact on `initialize_spacecraft_leo()`:**
- Currently sets position relative to parent
- May need to be deprecated or updated to validate/override config-based positions
- Consider keeping function for dynamic scenarios (e.g., multi-burn missions)
#### 1. Config Format Improvements
- Support Earth-relative position specification (e.g., `{ altitude_km = 200.0 }`)
- Support Earth-relative orbit specification (e.g., `{ orbit_type = "circular" }`)
- More intuitive spacecraft mission parameters in TOML config
- Support multiple spacecraft in single config file
#### 2. Improved Patched Conics Implementation
- Calculate Δv to reach SOI boundary (escape trajectory)
- Calculate velocity at SOI boundary
- Add transfer Δv at SOI boundary
- Combine into equivalent single impulse
- Test accuracy of two-impulse vs single-impulse approach
#### 3. Inclination Support
- Extend to 3D transfers
- Need 3D angular position calculations
- Longitude of ascending node, inclination, argument of periapsis
- Phase angle calculations in 3D
- Out-of-plane maneuver calculations
#### 4. Capture Burns
- Simulate retrograde burns for orbital capture at destination
- Calculate Δv needed for circularization
- 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
#### 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
#### 7. Multiple Burns Support
- Mid-course corrections
- Gravity assist maneuvers
- Powered flybys
- Multi-stage missions
#### 8. SOI Visualization
- Render SOI boundaries as wireframe spheres
- Color-coded by mass
- Toggle with keyboard shortcut
- Show SOI transitions in real-time
### Advanced Features
#### 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
#### 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
#### 11. Enhanced Trajectory Analysis
- Lambert solver for general transfers
- Not just Hohmann transfers
- Arbitrary departure/arrival positions and times
- Non-planar transfers
---
## Notes
### Coordinate System
- All calculations assume planar motion (z = 0) for initial implementation
- Angular positions measured in XY plane
- Future work: Extend to 3D with inclination
### Timekeeping
- Simulation time in seconds, conversions to days for display
- Fast-forward uses 1-day steps for efficiency during launch window wait
- Timestep remains 60s during fast-forward
### Mass Strategy
- Spacecraft mass = 1.0 kg (negligible but non-zero)
- Physics engine handles test particles correctly (mass cancels in acceleration)
- No N-body perturbations from spacecraft on planetary bodies
### Validation Strategy
- Compare against NASA reference missions (Viking, Curiosity, Perseverance)
- Energy conservation tracking during transfer
- Transfer time accuracy (±10% tolerance)
- SOI transition verification (Earth→Sun→Mars)
### Testing Approach
- Unit tests for each function (formulas, calculations)
- Integration tests for full missions (LEO initialization, impulse burn, transfer)
- Regression tests against expected Hohmann transfer parameters
### LEO Orbit Considerations
- LEO orbit at 200 km altitude (r = 6.571×10⁶ m)
- LEO velocity: ~7,788 m/s at 200 km
- LEO period: ~88.5 minutes
- Spacecraft LEO phase changes significantly during multi-day wait periods
- Transfer burn must account for spacecraft's actual heliocentric velocity (not just Earth's)
---
## References
- `docs/implementation_plan.md` - Overall system architecture
- NASA Technical Memorandum "Hohmann Transfer Calculations"
- Orbital Mechanics for Engineering Students (Curtis)
- Fundamentals of Astrodynamics (Bate, Mueller, White)

240
docs/test_plan_invalid_parent_assignment.md

@ -1,240 +0,0 @@
# Test Plan: Invalid Parent Assignment Bug
## Overview
Comprehensive test suite to capture and validate parent-child relationship bugs in orbital mechanics simulation.
**Date:** January 20, 2026
**Status:** Complete (Tests 1-3 resolved)
**Related:** `docs/mission_planning.md` FIXME section
---
## Bug Diagnosis
### Root Cause Identified
**The Bug (Fixed):** In `tests/configs/earth_mars_simple.toml`, spacecraft had placeholder values:
- `position = {1.496e11, 0, 0}` (IDENTICAL to Earth)
- `velocity = {0, 0, 0}` (zero velocity)
- `SOI = ~17.3 meters` (calculated from mass=1kg)
**What Happened:**
1. Config loaded with spacecraft at Earth's exact position
2. During `find_dominant_body(1)` for Earth:
- Checks all bodies
- Finds spacecraft at distance = 0
- `0 < 17.3` is TRUE
- Sets Earth's parent to spacecraft!
**Why Test Failed But GUI Failed Worse:**
- Test calls `initialize_spacecraft_leo()` → spacecraft moved to proper LEO orbit (200km from Earth)
- GUI never called this → placeholder values caused immediate bug
### Solution Implemented
**Config Validation in `src/config_loader.cpp`:**
- Added validation loop after parsing bodies, before `initialize_bodies()`
- Validates that distance between body and parent ≥ parent.radius + body.radius
- Provides clear error message with actual and required distances
- Prevents loading invalid configs with bodies too close to their parents
**Config Fix in `tests/configs/earth_mars_simple.toml`:**
- Changed spacecraft position from `1.496e11` (same as Earth) to `1.49606571e11`
- This places spacecraft at proper LEO altitude: Earth position + 6,571,000 m
- 6,571 km = Earth radius (6,371 km) + 200 km altitude
---
## Test Cases
### Test Case 1: Earth→Spacecraft Parent Switch
**Purpose:** Directly detect when Earth's parent becomes spacecraft (the exact bug from FIXME)
**Actual Result:** ✅ **PASSES**
**How It Was Fixed:**
- Config validation now rejects bodies starting at parent's position
- Spacecraft properly positioned at LEO altitude (6,571 km from Earth center)
- `find_dominant_body()` never finds spacecraft at distance=0
- Earth's parent remains Sun throughout simulation
**Config:** `tests/configs/earth_mars_simple.toml`
**Key Assertion:**
```cpp
REQUIRE(sim->bodies[EARTH_IDX].parent_index != SPACECRAFT_IDX);
```
---
### Test Case 2: Mass Hierarchy Validation
**Purpose:** Validate that massive bodies never become children of small bodies
**Actual Result:** ✅ **PASSES**
**How It Was Fixed:**
- Config validation ensures proper parent-child distance
- Mass hierarchy preserved throughout simulation
- Earth never becomes child of spacecraft or other bodies
**Config:** `tests/configs/earth_mars_simple.toml`
**Key Assertions:**
```cpp
// Parent must be more massive
REQUIRE(mass_ratio >= 1.0);
// For planets: parent should be significantly more massive
if (not spacecraft) {
REQUIRE(mass_ratio >= 1000.0);
}
// Massive bodies should never have small bodies as parents
if (child_mass > 1e20) { // Planet-scale
REQUIRE(parent_mass > child_mass);
}
```
---
### Test Case 3: Config Placeholder Validation
**Purpose:** Detect invalid config initialization (bodies starting too close together)
**Actual Result:** ✅ **PASSES**
**How It Was Fixed:**
- Test updated to use radius-based validation (matches config_loader logic)
- Spacecraft now at proper LEO position: 6,571,000 m from Earth center
- Validation: distance (6,571,000 m) ≥ Earth.radius + spacecraft.radius (6,372,000 m)
- Config validation catches any bodies positioned within parent's radius
**Config:** `tests/configs/earth_mars_simple.toml`
**Key Assertion:**
```cpp
double min_distance = sim->bodies[EARTH_IDX].radius + sim->bodies[SPACECRAFT_IDX].radius;
REQUIRE(distance >= min_distance); // parent.radius + body.radius
```
---
### Test Case 4: Mutual SOI - Similar Mass Planets
**Purpose:** Edge case: two Earth-like planets positioned within each other's SOI
**Actual Result:** ❌ **STILL FAILS** (separate issue, not fixed by spacecraft validation)
**Config:** `tests/configs/mutual_soi_close.toml`
**Setup:**
- PlanetA: mass = 5.972e24 kg, position = {1.496e11, 0, 0}
- PlanetB: mass = 5.972e24 kg, position = {1.501e11, 0, 0}
- Separation: 5e8 meters (500 million km)
- Planet SOI: ~9.25e8 meters (925 million km)
- **Both planets within each other's SOI**
**Why This Fails:**
- Both planets start with parent=0 (Sun)
- Both are within each other's SOI
- `find_dominant_body()` logic selects closest body within SOI
- Result: PlanetA selects PlanetB as parent, PlanetB selects PlanetA as parent
- Config validation passes (both are ≥ parent.radius + body.radius from Sun)
**Key Assertions:**
```cpp
// Both should orbit Sun (not each other)
REQUIRE(sim->bodies[PLANET_A_IDX].parent_index == SUN_IDX);
REQUIRE(sim->bodies[PLANET_B_IDX].parent_index == SUN_IDX);
// Planets should never have each other as parents
for (int parent : history.planet_a_parents) {
REQUIRE(parent != PLANET_B_IDX);
}
for (int parent : history.planet_b_parents) {
REQUIRE(parent != PLANET_A_IDX);
}
```
**Expected Behavior (Option A):**
- Both planets should continue orbiting Sun
- Neither should become other's parent
- This requires future fix to `find_dominant_body()` logic (mass hierarchy check)
---
## Test Matrix
| Test Case | Config | Tests | Expected (Before Fix) | **Actual Result** |
|-----------|--------|-------|----------------------|--------------------------------|
| **1. Earth→Spacecraft** | earth_mars_simple.toml | Parent assignment | **FAIL** | **✅ PASS** |
| **2. Mass Hierarchy** | earth_mars_simple.toml | Mass ratios | **FAIL** | **✅ PASS** |
| **3. Config Validation** | earth_mars_simple.toml | Separation distance | **FAIL** | **✅ PASS** |
| **4. Mutual SOI** | mutual_soi_close.toml | Edge case behavior | **FAIL** | **❌ FAIL** (separate issue) |
---
## Implementation
### Test File
`tests/test_invalid_parent_assignment.cpp`
### Test Config Files
- `tests/configs/earth_mars_simple.toml` (existing)
- `tests/configs/mutual_soi_close.toml` (new)
### Build Integration
Add to CMakeLists.txt or Makefile test targets
---
## Implementation Summary
**Solution Applied (Jan 20, 2026):**
1. **Config validation in `src/config_loader.cpp`**:
- Validates parent-child distances before initialization
- Requires distance ≥ parent.radius + body.radius
- Prevents loading invalid configs
2. **Config fix in `tests/configs/earth_mars_simple.toml`**:
- Spacecraft position corrected to proper LEO altitude
- Position: 1.49606571e11 m (Earth position + 6,571,000 m offset)
- Velocity calculated by `initialize_bodies()` using `semi_major_axis = 6.571e6`
3. **Test updates in `tests/test_invalid_parent_assignment.cpp`**:
- Test 3 updated to use radius-based validation
- Matches config_loader validation logic
---
## Future Work
### Current Status
Tests 1-3 are now passing. Test 4 continues to fail, documenting a separate mutual SOI issue.
### Potential Fixes for Test 4
1. Add mass hierarchy check to `find_dominant_body()`
2. Prevent mutual SOI assignments for similar-mass bodies
3. Detect and reject invalid configs at load time
4. Implement proper N-body interaction or restricted 3-body solution
### Enhanced Detection
- SOI overlap detection at config load time
- Automatic correction of invalid parent assignments
- Validation warnings for edge cases
---
## References
- `docs/mission_planning.md:125-135` - FIXME section describing bug (now resolved)
- `src/config_loader.cpp:138-157` - Config validation implementation
- `tests/configs/earth_mars_simple.toml` - Corrected spacecraft position (LEO altitude)
- `src/simulation.cpp:64-107` - `find_dominant_body()` implementation
- `src/simulation.cpp:212-233` - `initialize_bodies()` implementation
- `tests/test_invalid_parent_assignment.cpp` - Test suite implementation
## Commits
- `0239cc1` - Add test suite for invalid parent assignment bugs
- `899fa3b` - Add config validation for parent-child distances
Loading…
Cancel
Save