|
|
|
|
@ -1,844 +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:** Ready to implement |
|
|
|
|
**Branch:** mission-planning |
|
|
|
|
|
|
|
|
|
--- |
|
|
|
|
|
|
|
|
|
## Phase 0: Git Workflow Preparation |
|
|
|
|
|
|
|
|
|
### Step 0.1: Stash debug changes on main |
|
|
|
|
```bash |
|
|
|
|
git stash push -m "Debug printf statements for spacecraft parent switch investigation" |
|
|
|
|
``` |
|
|
|
|
|
|
|
|
|
### Step 0.2: Checkout and update mission-planning branch |
|
|
|
|
```bash |
|
|
|
|
git checkout mission-planning |
|
|
|
|
git rebase main # Or git merge main if cleaner |
|
|
|
|
``` |
|
|
|
|
|
|
|
|
|
### Step 0.3: Apply debug changes to mission-planning branch |
|
|
|
|
```bash |
|
|
|
|
git stash list # Verify stash exists |
|
|
|
|
git stash pop # Apply debug changes |
|
|
|
|
``` |
|
|
|
|
|
|
|
|
|
**Verification**: Confirm debug printf statements are in `src/simulation.cpp` after applying stash |
|
|
|
|
|
|
|
|
|
--- |
|
|
|
|
|
|
|
|
|
## Phase 1: Update Configuration File |
|
|
|
|
|
|
|
|
|
### Step 1.1: Add spacecraft to `tests/configs/earth_mars_simple.toml` |
|
|
|
|
|
|
|
|
|
Append to config file: |
|
|
|
|
```toml |
|
|
|
|
[[bodies]] |
|
|
|
|
name = "Spacecraft" |
|
|
|
|
mass = 1.0 |
|
|
|
|
radius = 1000.0 |
|
|
|
|
# Position and velocity will be initialized at runtime for LEO orbit |
|
|
|
|
position = { x = 0.0, y = 0.0, z = 0.0 } |
|
|
|
|
velocity = { x = 0.0, y = 0.0, z = 0.0 } |
|
|
|
|
parent_index = 1 # Earth |
|
|
|
|
color = { r = 1.0, g = 0.0, b = 0.5 } |
|
|
|
|
eccentricity = 0.0 |
|
|
|
|
# Semi-major axis will be: Earth radius + 200km |
|
|
|
|
semi_major_axis = 6.571e6 # Placeholder, will be set during initialization |
|
|
|
|
``` |
|
|
|
|
|
|
|
|
|
**Note**: Position/velocity are placeholders; will be calculated by `initialize_spacecraft_leo()` at runtime. |
|
|
|
|
|
|
|
|
|
**TODO**: Future config file format should support: |
|
|
|
|
- Earth-relative position (e.g., `{ altitude_km = 200.0 }`) |
|
|
|
|
- Earth-relative velocity (e.g., `{ 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` |
|
|
|
|
|
|
|
|
|
```cpp |
|
|
|
|
// Initialize spacecraft in circular LEO around parent body |
|
|
|
|
void initialize_spacecraft_leo(CelestialBody* spacecraft, CelestialBody* parent, |
|
|
|
|
double altitude_m); |
|
|
|
|
|
|
|
|
|
// Apply patched conics impulse burn for Hohmann transfer |
|
|
|
|
void apply_transfer_burn(SimulationState* sim, int spacecraft_idx, |
|
|
|
|
int departure_idx, TransferParameters* params); |
|
|
|
|
|
|
|
|
|
// Helper: Calculate current phase angle between two bodies (in degrees) |
|
|
|
|
double calculate_phase_angle(SimulationState* sim, int departure_idx, int arrival_idx); |
|
|
|
|
``` |
|
|
|
|
|
|
|
|
|
### Step 2.2: Implement `initialize_spacecraft_leo()` in `src/mission_planning.cpp` |
|
|
|
|
|
|
|
|
|
**Algorithm**: |
|
|
|
|
```cpp |
|
|
|
|
void initialize_spacecraft_leo(CelestialBody* spacecraft, CelestialBody* parent, |
|
|
|
|
double altitude_m) { |
|
|
|
|
// Calculate orbital radius (distance from Earth center) |
|
|
|
|
double orbital_radius = parent->radius + altitude_m; |
|
|
|
|
|
|
|
|
|
// Position spacecraft radially outward from Earth-Sun line |
|
|
|
|
// Get vector from Sun to Earth |
|
|
|
|
Vec3 sun_to_earth = vec3_sub(parent->position, |
|
|
|
|
(Vec3){0.0, 0.0, 0.0}); // Sun at origin |
|
|
|
|
Vec3 direction = vec3_normalize(sun_to_earth); |
|
|
|
|
|
|
|
|
|
// Position: Earth position + offset radially outward |
|
|
|
|
Vec3 offset = vec3_scale(direction, orbital_radius); |
|
|
|
|
spacecraft->position = vec3_add(parent->position, offset); |
|
|
|
|
|
|
|
|
|
// Initialize local coordinates (relative to parent) |
|
|
|
|
spacecraft->local_position = offset; |
|
|
|
|
spacecraft->local_velocity = (Vec3){0.0, 0.0, 0.0}; // Will be set below |
|
|
|
|
|
|
|
|
|
// Calculate circular LEO velocity magnitude |
|
|
|
|
double v_leo = sqrt(G * parent->mass / orbital_radius); |
|
|
|
|
|
|
|
|
|
// Direction: tangential to Earth-Sun line (prograde) |
|
|
|
|
// If sun_to_earth = (x, y, 0), then tangent = (-y, x, 0) |
|
|
|
|
Vec3 leo_tangent = (Vec3){-direction.y, direction.x, 0.0}; |
|
|
|
|
Vec3 leo_velocity = vec3_scale(leo_tangent, v_leo); |
|
|
|
|
|
|
|
|
|
// Spacecraft velocity = Earth velocity + LEO velocity |
|
|
|
|
spacecraft->velocity = vec3_add(parent->velocity, leo_velocity); |
|
|
|
|
|
|
|
|
|
// Local velocity relative to Earth = LEO velocity only |
|
|
|
|
spacecraft->local_velocity = leo_velocity; |
|
|
|
|
|
|
|
|
|
// Update semi-major axis for reference |
|
|
|
|
spacecraft->semi_major_axis = orbital_radius; |
|
|
|
|
|
|
|
|
|
// SOI will be calculated by config loader |
|
|
|
|
} |
|
|
|
|
``` |
|
|
|
|
|
|
|
|
|
**Key Points**: |
|
|
|
|
- Spacecraft positioned radially outward from Sun (any position is acceptable) |
|
|
|
|
- LEO orbit is circular at 200km altitude |
|
|
|
|
- Prograde orientation (same direction as Earth's orbital velocity) |
|
|
|
|
- Both local and global coordinates set correctly |
|
|
|
|
|
|
|
|
|
### Step 2.3: Implement `calculate_phase_angle()` in `src/mission_planning.cpp` |
|
|
|
|
|
|
|
|
|
**Algorithm**: |
|
|
|
|
```cpp |
|
|
|
|
double calculate_phase_angle(SimulationState* sim, int departure_idx, int arrival_idx) { |
|
|
|
|
CelestialBody* departure = &sim->bodies[departure_idx]; |
|
|
|
|
CelestialBody* arrival = &sim->bodies[arrival_idx]; |
|
|
|
|
CelestialBody* sun = &sim->bodies[0]; // Assume Sun at index 0 |
|
|
|
|
|
|
|
|
|
// Calculate angular positions relative to Sun |
|
|
|
|
double theta_depart = calculate_angular_position(departure, sun); |
|
|
|
|
double theta_arrival = calculate_angular_position(arrival, sun); |
|
|
|
|
|
|
|
|
|
// Calculate phase difference |
|
|
|
|
double phase_rad = theta_arrival - theta_depart; |
|
|
|
|
|
|
|
|
|
// Normalize to [0, 2π) |
|
|
|
|
while (phase_rad < 0.0) { |
|
|
|
|
phase_rad += 2.0 * M_PI; |
|
|
|
|
} |
|
|
|
|
while (phase_rad >= 2.0 * M_PI) { |
|
|
|
|
phase_rad -= 2.0 * M_PI; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Convert to degrees |
|
|
|
|
return phase_rad * 180.0 / M_PI; |
|
|
|
|
} |
|
|
|
|
``` |
|
|
|
|
|
|
|
|
|
### Step 2.4: Implement `apply_transfer_burn()` in `src/mission_planning.cpp` |
|
|
|
|
|
|
|
|
|
**Algorithm (Patched Conics Approach)**: |
|
|
|
|
```cpp |
|
|
|
|
void apply_transfer_burn(SimulationState* sim, int spacecraft_idx, |
|
|
|
|
int departure_idx, TransferParameters* params) { |
|
|
|
|
CelestialBody* spacecraft = &sim->bodies[spacecraft_idx]; |
|
|
|
|
CelestialBody* departure = &sim->bodies[departure_idx]; |
|
|
|
|
CelestialBody* sun = &sim->bodies[0]; // Assume Sun at index 0 |
|
|
|
|
|
|
|
|
|
// Calculate required heliocentric transfer velocity |
|
|
|
|
// v_transfer = params->departure_velocity |
|
|
|
|
// Direction: prograde (tangential to Earth-Sun line) |
|
|
|
|
Vec3 sun_to_earth = vec3_sub(departure->position, sun->position); |
|
|
|
|
Vec3 sun_to_earth_norm = vec3_normalize(sun_to_earth); |
|
|
|
|
|
|
|
|
|
// Tangent direction (prograde): (-y, x, 0) |
|
|
|
|
Vec3 transfer_dir = (Vec3){-sun_to_earth_norm.y, sun_to_earth_norm.x, 0.0}; |
|
|
|
|
Vec3 v_transfer_helio = vec3_scale(transfer_dir, params->departure_velocity); |
|
|
|
|
|
|
|
|
|
// Current heliocentric velocity |
|
|
|
|
Vec3 current_helio = spacecraft->velocity; |
|
|
|
|
|
|
|
|
|
// Calculate total Δv to apply |
|
|
|
|
Vec3 delta_v = vec3_sub(v_transfer_helio, current_helio); |
|
|
|
|
|
|
|
|
|
// Apply impulse burn |
|
|
|
|
spacecraft->velocity = vec3_add(spacecraft->velocity, delta_v); |
|
|
|
|
|
|
|
|
|
// Update local velocity |
|
|
|
|
spacecraft->local_velocity = vec3_sub(spacecraft->velocity, departure->velocity); |
|
|
|
|
|
|
|
|
|
// Print burn information |
|
|
|
|
printf("Transfer burn applied:\n"); |
|
|
|
|
printf(" Current heliocentric velocity: (%.2f, %.2f, %.2f) m/s\n", |
|
|
|
|
current_helio.x, current_helio.y, current_helio.z); |
|
|
|
|
printf(" Target heliocentric velocity: (%.2f, %.2f, %.2f) m/s\n", |
|
|
|
|
v_transfer_helio.x, v_transfer_helio.y, v_transfer_helio.z); |
|
|
|
|
printf(" Delta-v: (%.2f, %.2f, %.2f) m/s\n", |
|
|
|
|
delta_v.x, delta_v.y, delta_v.z); |
|
|
|
|
printf(" Delta-v magnitude: %.2f m/s (%.3f km/s)\n", |
|
|
|
|
vec3_magnitude(delta_v), vec3_magnitude(delta_v) / 1000.0); |
|
|
|
|
} |
|
|
|
|
``` |
|
|
|
|
|
|
|
|
|
**Note**: This is a simplified single-impulse approach. A true patched conics calculation would: |
|
|
|
|
1. Calculate Δv to reach SOI boundary (escape trajectory) |
|
|
|
|
2. Calculate velocity at SOI boundary |
|
|
|
|
3. Add transfer Δv at SOI boundary |
|
|
|
|
4. Combine into equivalent single impulse |
|
|
|
|
|
|
|
|
|
For initial implementation, we'll use single impulse as approximation. |
|
|
|
|
|
|
|
|
|
--- |
|
|
|
|
|
|
|
|
|
## Phase 3: Comprehensive Test Case |
|
|
|
|
|
|
|
|
|
### Step 3.1: Create new test in `tests/test_hohmann_transfer.cpp` |
|
|
|
|
|
|
|
|
|
```cpp |
|
|
|
|
TEST_CASE("Earth → Mars Hohmann Transfer with LEO Spacecraft", "[mission][hohmann][config][integration]") { |
|
|
|
|
const double TIME_STEP = 60.0; |
|
|
|
|
const double SECONDS_PER_DAY = 86400.0; |
|
|
|
|
const double LEO_ALTITUDE_M = 200000.0; // 200 km |
|
|
|
|
|
|
|
|
|
// 1. Load config with LEO spacecraft |
|
|
|
|
SimulationState* sim = create_simulation(4, TIME_STEP); |
|
|
|
|
REQUIRE(load_system_config(sim, "tests/configs/earth_mars_simple.toml")); |
|
|
|
|
|
|
|
|
|
const int SUN_IDX = 0; |
|
|
|
|
const int EARTH_IDX = 1; |
|
|
|
|
const int MARS_IDX = 2; |
|
|
|
|
const int CRAFT_IDX = 3; |
|
|
|
|
|
|
|
|
|
// Verify spacecraft loaded |
|
|
|
|
REQUIRE(sim->body_count == 4); |
|
|
|
|
REQUIRE(strcmp(sim->bodies[CRAFT_IDX].name, "Spacecraft") == 0); |
|
|
|
|
|
|
|
|
|
// 2. Initialize spacecraft LEO orbit |
|
|
|
|
initialize_spacecraft_leo(&sim->bodies[CRAFT_IDX], &sim->bodies[EARTH_IDX], |
|
|
|
|
LEO_ALTITUDE_M); |
|
|
|
|
|
|
|
|
|
INFO("Spacecraft initialized at %.2f km altitude", LEO_ALTITUDE_M / 1000.0); |
|
|
|
|
INFO("Spacecraft parent: %d (Earth)", sim->bodies[CRAFT_IDX].parent_index); |
|
|
|
|
|
|
|
|
|
// 3. Verify initial LEO orbit is stable |
|
|
|
|
REQUIRE(sim->bodies[CRAFT_IDX].parent_index == EARTH_IDX); |
|
|
|
|
|
|
|
|
|
double dist_to_earth = vec3_distance(sim->bodies[CRAFT_IDX].position, |
|
|
|
|
sim->bodies[EARTH_IDX].position); |
|
|
|
|
double expected_radius = sim->bodies[EARTH_IDX].radius + LEO_ALTITUDE_M; |
|
|
|
|
REQUIRE(fabs(dist_to_earth - expected_radius) < 1000.0); // Within 1 km |
|
|
|
|
|
|
|
|
|
// Verify LEO velocity magnitude |
|
|
|
|
double leo_velocity_mag = sqrt(G * sim->bodies[EARTH_IDX].mass / dist_to_earth); |
|
|
|
|
double v_leo_relative = vec3_magnitude(sim->bodies[CRAFT_IDX].local_velocity); |
|
|
|
|
INFO("Expected LEO velocity: %.2f m/s", leo_velocity_mag); |
|
|
|
|
INFO("Actual LEO velocity: %.2f m/s", v_leo_relative); |
|
|
|
|
REQUIRE(fabs(v_leo_relative - leo_velocity_mag) < 10.0); // Within 10 m/s |
|
|
|
|
|
|
|
|
|
// Verify negative total energy (bound to Earth) |
|
|
|
|
OrbitalMetrics leo_metrics = calculate_orbital_metrics(&sim->bodies[CRAFT_IDX], |
|
|
|
|
&sim->bodies[EARTH_IDX]); |
|
|
|
|
INFO("LEO total energy: %.2e J", leo_metrics.total_energy); |
|
|
|
|
REQUIRE(leo_metrics.total_energy < 0.0); |
|
|
|
|
|
|
|
|
|
// 4. Calculate Hohmann transfer parameters |
|
|
|
|
double r_earth = vec3_distance(sim->bodies[EARTH_IDX].position, |
|
|
|
|
sim->bodies[SUN_IDX].position); |
|
|
|
|
double r_mars = vec3_distance(sim->bodies[MARS_IDX].position, |
|
|
|
|
sim->bodies[SUN_IDX].position); |
|
|
|
|
TransferParameters params = calculate_hohmann_transfer(r_earth, r_mars, |
|
|
|
|
sim->bodies[SUN_IDX].mass); |
|
|
|
|
|
|
|
|
|
INFO("Transfer time: %.2f days", params.transfer_time / SECONDS_PER_DAY); |
|
|
|
|
INFO("Required phase angle: %.3f degrees", params.phase_angle_deg); |
|
|
|
|
INFO("Delta-v injection: %.3f km/s", params.delta_v_injection / 1000.0); |
|
|
|
|
|
|
|
|
|
// 5. Wait for Earth-Mars launch window |
|
|
|
|
double wait_start_time = sim->time; |
|
|
|
|
wait_for_launch_window(sim, EARTH_IDX, MARS_IDX, params.phase_angle_deg, 1.0); |
|
|
|
|
double wait_duration = sim->time - wait_start_time; |
|
|
|
|
|
|
|
|
|
INFO("Launch window opened after %.2f days", wait_duration / SECONDS_PER_DAY); |
|
|
|
|
|
|
|
|
|
// 6. Verify launch window accuracy (within 1°) |
|
|
|
|
double current_phase = calculate_phase_angle(sim, EARTH_IDX, MARS_IDX); |
|
|
|
|
double phase_error = fabs(current_phase - params.phase_angle_deg); |
|
|
|
|
if (phase_error > 180.0) phase_error = fabs(phase_error - 360.0); |
|
|
|
|
|
|
|
|
|
INFO("Current phase angle: %.3f degrees", current_phase); |
|
|
|
|
INFO("Required phase angle: %.3f degrees", params.phase_angle_deg); |
|
|
|
|
INFO("Phase angle error: %.3f degrees", phase_error); |
|
|
|
|
REQUIRE(phase_error < 1.0); |
|
|
|
|
|
|
|
|
|
// 7. Apply impulse burn for transfer |
|
|
|
|
double pre_burn_time = sim->time; |
|
|
|
|
OrbitalMetrics pre_burn_metrics = calculate_orbital_metrics(&sim->bodies[CRAFT_IDX], |
|
|
|
|
&sim->bodies[SUN_IDX]); |
|
|
|
|
|
|
|
|
|
apply_transfer_burn(sim, CRAFT_IDX, EARTH_IDX, ¶ms); |
|
|
|
|
|
|
|
|
|
OrbitalMetrics post_burn_metrics = calculate_orbital_metrics(&sim->bodies[CRAFT_IDX], |
|
|
|
|
&sim->bodies[SUN_IDX]); |
|
|
|
|
|
|
|
|
|
INFO("Pre-burn heliocentric energy: %.2e J", pre_burn_metrics.total_energy); |
|
|
|
|
INFO("Post-burn heliocentric energy: %.2e J", post_burn_metrics.total_energy); |
|
|
|
|
INFO("Energy added: %.2e J", |
|
|
|
|
post_burn_metrics.total_energy - pre_burn_metrics.total_energy); |
|
|
|
|
|
|
|
|
|
// Verify spacecraft is now in escape trajectory (positive or zero energy) |
|
|
|
|
REQUIRE(post_burn_metrics.total_energy >= 0.0); |
|
|
|
|
|
|
|
|
|
// 8. Track SOI transitions during transfer |
|
|
|
|
int earth_soi_exit_step = 0; |
|
|
|
|
int sun_soi_enter_step = 0; |
|
|
|
|
int mars_soi_enter_step = 0; |
|
|
|
|
double transfer_duration = params.transfer_time * 1.1; |
|
|
|
|
int max_steps = (int)(transfer_duration / sim->dt); |
|
|
|
|
|
|
|
|
|
INFO("Simulating for %.2f days (%d steps)", |
|
|
|
|
transfer_duration / SECONDS_PER_DAY, max_steps); |
|
|
|
|
|
|
|
|
|
for (int step = 0; step < max_steps; step++) { |
|
|
|
|
update_simulation(sim); |
|
|
|
|
|
|
|
|
|
// Track Earth SOI exit |
|
|
|
|
if (earth_soi_exit_step == 0 && |
|
|
|
|
sim->bodies[CRAFT_IDX].parent_index != EARTH_IDX) { |
|
|
|
|
earth_soi_exit_step = step; |
|
|
|
|
INFO("Earth SOI exit at step %d (t = %.2f days)", |
|
|
|
|
step, sim->time / SECONDS_PER_DAY); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Track Sun SOI entry (after leaving Earth) |
|
|
|
|
if (earth_soi_exit_step > 0 && sun_soi_enter_step == 0 && |
|
|
|
|
sim->bodies[CRAFT_IDX].parent_index == SUN_IDX) { |
|
|
|
|
sun_soi_enter_step = step; |
|
|
|
|
INFO("Sun SOI entry at step %d (t = %.2f days)", |
|
|
|
|
step, sim->time / SECONDS_PER_DAY); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Track Mars SOI entry |
|
|
|
|
if (mars_soi_enter_step == 0 && |
|
|
|
|
sim->bodies[CRAFT_IDX].parent_index == MARS_IDX) { |
|
|
|
|
mars_soi_enter_step = step; |
|
|
|
|
INFO("Mars SOI entry at step %d (t = %.2f days)", |
|
|
|
|
step, sim->time / SECONDS_PER_DAY); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 9. Verify Earth → Sun transition occurred |
|
|
|
|
INFO("Earth SOI exit step: %d", earth_soi_exit_step); |
|
|
|
|
INFO("Sun SOI entry step: %d", sun_soi_enter_step); |
|
|
|
|
|
|
|
|
|
REQUIRE(earth_soi_exit_step > 0); |
|
|
|
|
REQUIRE(sun_soi_enter_step > 0); |
|
|
|
|
|
|
|
|
|
// Final parent should be Sun or Mars |
|
|
|
|
int final_parent = sim->bodies[CRAFT_IDX].parent_index; |
|
|
|
|
REQUIRE(final_parent == SUN_IDX || final_parent == MARS_IDX); |
|
|
|
|
INFO("Final parent: %d (%s)", final_parent, |
|
|
|
|
final_parent == SUN_IDX ? "Sun" : "Mars"); |
|
|
|
|
|
|
|
|
|
// 10. Verify spacecraft followed transfer orbit (energy conservation) |
|
|
|
|
OrbitalMetrics final_metrics = calculate_orbital_metrics(&sim->bodies[CRAFT_IDX], |
|
|
|
|
&sim->bodies[SUN_IDX]); |
|
|
|
|
|
|
|
|
|
double energy_drift = fabs(final_metrics.total_energy - post_burn_metrics.total_energy); |
|
|
|
|
if (post_burn_metrics.total_energy != 0.0) { |
|
|
|
|
energy_drift /= fabs(post_burn_metrics.total_energy); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
INFO("Final orbital radius: %.2f AU", |
|
|
|
|
final_metrics.orbital_radius / 1.496e11); |
|
|
|
|
INFO("Final energy: %.2e J", final_metrics.total_energy); |
|
|
|
|
INFO("Expected energy: %.2e J", post_burn_metrics.total_energy); |
|
|
|
|
INFO("Energy drift: %.2f%%", energy_drift * 100.0); |
|
|
|
|
|
|
|
|
|
REQUIRE(energy_drift < 0.05); // < 5% energy conservation |
|
|
|
|
|
|
|
|
|
// 11. If Mars SOI entry occurred, verify distance |
|
|
|
|
if (mars_soi_enter_step > 0) { |
|
|
|
|
double dist_to_mars = vec3_distance(sim->bodies[CRAFT_IDX].position, |
|
|
|
|
sim->bodies[MARS_IDX].position); |
|
|
|
|
INFO("Distance to Mars: %.2f km", dist_to_mars / 1000.0); |
|
|
|
|
INFO("Mars SOI radius: %.2f km", sim->bodies[MARS_IDX].soi_radius / 1000.0); |
|
|
|
|
REQUIRE(dist_to_mars < 2.0 * sim->bodies[MARS_IDX].soi_radius); |
|
|
|
|
} else { |
|
|
|
|
INFO("Spacecraft did not enter Mars SOI within simulation time"); |
|
|
|
|
INFO("This may be due to phase angle or timing inaccuracies"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
destroy_simulation(sim); |
|
|
|
|
} |
|
|
|
|
``` |
|
|
|
|
|
|
|
|
|
--- |
|
|
|
|
|
|
|
|
|
## Phase 4: Build and Test |
|
|
|
|
|
|
|
|
|
### Step 4.1: Update Makefile (if needed) |
|
|
|
|
|
|
|
|
|
Verify `mission_planning.o` is in OBJECTS list and build rule exists. |
|
|
|
|
|
|
|
|
|
### Step 4.2: Build test executable |
|
|
|
|
```bash |
|
|
|
|
make clean |
|
|
|
|
make test-build |
|
|
|
|
``` |
|
|
|
|
|
|
|
|
|
### Step 4.3: Run comprehensive test |
|
|
|
|
```bash |
|
|
|
|
./orbit_test -s 'Earth → Mars Hohmann Transfer with LEO Spacecraft' |
|
|
|
|
``` |
|
|
|
|
|
|
|
|
|
### Step 4.4: Verify all tests still pass |
|
|
|
|
```bash |
|
|
|
|
make test |
|
|
|
|
``` |
|
|
|
|
|
|
|
|
|
--- |
|
|
|
|
|
|
|
|
|
## Phase 5: Cleanup and Documentation |
|
|
|
|
|
|
|
|
|
### Step 5.1: Remove deprecated function |
|
|
|
|
Remove `spawn_spacecraft_on_transfer()` from: |
|
|
|
|
- `src/mission_planning.h` |
|
|
|
|
- `src/mission_planning.cpp` |
|
|
|
|
|
|
|
|
|
### Step 5.2: Update mission planning documentation |
|
|
|
|
|
|
|
|
|
Update `docs/mission_planning.md`: |
|
|
|
|
- Mark Phase 4 as complete |
|
|
|
|
- Note config-based approach implemented |
|
|
|
|
- Document patched conics impulse burn |
|
|
|
|
- Remove spawn_spacecraft_on_transfer references |
|
|
|
|
|
|
|
|
|
### Step 5.3: Add TODO comment for config format |
|
|
|
|
|
|
|
|
|
Add in `docs/mission_planning.md`: |
|
|
|
|
``` |
|
|
|
|
TODO: Future config file 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 |
|
|
|
|
``` |
|
|
|
|
|
|
|
|
|
--- |
|
|
|
|
|
|
|
|
|
## Summary of Changes |
|
|
|
|
|
|
|
|
|
### New Files/Functions Added |
|
|
|
|
- `initialize_spacecraft_leo()` - Initialize spacecraft in LEO |
|
|
|
|
- `apply_transfer_burn()` - Apply patched conics impulse burn |
|
|
|
|
- `calculate_phase_angle()` - Calculate phase angle between bodies |
|
|
|
|
- Comprehensive test case with SOI transition tracking |
|
|
|
|
|
|
|
|
|
### Files Modified |
|
|
|
|
- `tests/configs/earth_mars_simple.toml` - Add spacecraft body |
|
|
|
|
- `src/mission_planning.h` - Add function declarations |
|
|
|
|
- `src/mission_planning.cpp` - Implement new functions |
|
|
|
|
- `tests/test_hohmann_transfer.cpp` - Add comprehensive test |
|
|
|
|
|
|
|
|
|
### Functions Removed |
|
|
|
|
- `spawn_spacecraft_on_transfer()` - Still present in code but no longer used |
|
|
|
|
|
|
|
|
|
--- |
|
|
|
|
|
|
|
|
|
## Implementation Session Summary |
|
|
|
|
|
|
|
|
|
### Date: January 18, 2026 |
|
|
|
|
### Branch: mission-planning |
|
|
|
|
### Duration: ~2 hours |
|
|
|
|
|
|
|
|
|
### Completed Work |
|
|
|
|
|
|
|
|
|
#### Phase 0: Git Workflow ✅ |
|
|
|
|
- Stashed debug changes on main branch |
|
|
|
|
- Switched to mission-planning branch |
|
|
|
|
- Applied debug printf statements to mission-planning branch |
|
|
|
|
- All debug output from spacecraft parent investigation preserved |
|
|
|
|
|
|
|
|
|
#### Phase 1: Configuration File ✅ |
|
|
|
|
- Added Spacecraft body to `tests/configs/earth_mars_simple.toml` |
|
|
|
|
- Configured with placeholder position/velocity (set at runtime) |
|
|
|
|
- Parent set to Earth (index 1) |
|
|
|
|
- Initial semi-major axis placeholder: 6.571e6 m (Earth radius + 200km) |
|
|
|
|
|
|
|
|
|
#### Phase 2: Mission Planning Module ✅ |
|
|
|
|
|
|
|
|
|
**Function Declarations Added:** |
|
|
|
|
```cpp |
|
|
|
|
void initialize_spacecraft_leo(CelestialBody* spacecraft, CelestialBody* parent, |
|
|
|
|
double altitude_m); |
|
|
|
|
void apply_transfer_burn(SimulationState* sim, int spacecraft_idx, |
|
|
|
|
int departure_idx, TransferParameters* params); |
|
|
|
|
double calculate_phase_angle(SimulationState* sim, int departure_idx, int arrival_idx); |
|
|
|
|
``` |
|
|
|
|
|
|
|
|
|
**Function Implementations:** |
|
|
|
|
|
|
|
|
|
1. **`initialize_spacecraft_leo()`** - Sets circular LEO orbit at specified altitude |
|
|
|
|
- Calculates orbital radius = Earth radius + altitude |
|
|
|
|
- Positions spacecraft radially outward from Sun |
|
|
|
|
- Calculates LEO velocity: v = sqrt(G * M_earth / r) |
|
|
|
|
- Sets prograde orientation (tangential to Earth-Sun line) |
|
|
|
|
- Verified to produce correct LEO velocity (~7788 m/s at 200km altitude) |
|
|
|
|
|
|
|
|
|
2. **`calculate_phase_angle()`** - Computes phase angle between two bodies |
|
|
|
|
- Calculates angular positions relative to Sun |
|
|
|
|
- Returns phase difference normalized to [0°, 360°) |
|
|
|
|
- Used for launch window verification |
|
|
|
|
|
|
|
|
|
3. **`apply_transfer_burn()`** - Applies impulse burn for Hohmann transfer |
|
|
|
|
- Calculates required heliocentric velocity magnitude from transfer parameters |
|
|
|
|
- Calculates prograde direction (tangential to Earth-Sun line) |
|
|
|
|
- Computes delta-v vector: Δv = v_target - v_current |
|
|
|
|
- Applies impulse to spacecraft velocity |
|
|
|
|
- Updates local velocity relative to departure body |
|
|
|
|
|
|
|
|
|
#### Phase 3: Comprehensive Test Case ✅ |
|
|
|
|
|
|
|
|
|
**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°) |
|
|
|
|
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 |
|
|
|
|
12. If Mars SOI entry, verify distance |
|
|
|
|
``` |
|
|
|
|
|
|
|
|
|
**Test Results (Current Status):** |
|
|
|
|
|
|
|
|
|
✅ PASSED (8 assertions): |
|
|
|
|
- Config loading (4 bodies loaded) |
|
|
|
|
- Spacecraft loaded correctly |
|
|
|
|
- Spacecraft parent = Earth (index 1) |
|
|
|
|
- LEO position within expected radius (<1km error) |
|
|
|
|
- LEO velocity matches expected (<10 m/s error) |
|
|
|
|
- LEO total energy negative (bound to Earth) |
|
|
|
|
- Launch window opened after ~94 days |
|
|
|
|
- Phase angle error < 1° |
|
|
|
|
|
|
|
|
|
❌ FAILED (1 assertion): |
|
|
|
|
- Post-burn heliocentric energy >= 0.0 (expected) |
|
|
|
|
- Actual: -3.5e8 J (negative, still bound) |
|
|
|
|
- Expected: ≥ 0 J (positive, escape trajectory) |
|
|
|
|
|
|
|
|
|
#### Phase 4: Build System ✅ |
|
|
|
|
- Makefile already configured for mission_planning.o |
|
|
|
|
- Test executable builds successfully |
|
|
|
|
- All warnings noted (unused variables, harmless) |
|
|
|
|
|
|
|
|
|
#### Phase 5: Cleanup ⏸️ |
|
|
|
|
- Not yet started (waiting on test fix) |
|
|
|
|
|
|
|
|
|
--- |
|
|
|
|
|
|
|
|
|
## Current Issue Identified |
|
|
|
|
|
|
|
|
|
### Problem: Incorrect Delta-V Direction After Multi-Day Wait |
|
|
|
|
|
|
|
|
|
**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 |
|
|
|
|
|
|
|
|
|
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 |
|
|
|
|
```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 = "Spacecraft" |
|
|
|
|
mass = 1.0 |
|
|
|
|
radius = 1000.0 |
|
|
|
|
# Position and velocity will be initialized at runtime for LEO orbit |
|
|
|
|
position = { x = 0.0, y = 0.0, z = 0.0 } |
|
|
|
|
velocity = { x = 0.0, y = 0.0, z = 0.0 } |
|
|
|
|
parent_index = 1 # Earth |
|
|
|
|
color = { r = 1.0, g = 0.0, b = 0.5 } |
|
|
|
|
eccentricity = 0.0 |
|
|
|
|
# Semi-major axis will be: Earth radius + 200km |
|
|
|
|
semi_major_axis = 6.571e6 # Placeholder, will be set during initialization |
|
|
|
|
``` |
|
|
|
|
|
|
|
|
|
--- |
|
|
|
|
|
|
|
|
|
## Future Work (Post-Implementation) |
|
|
|
|
|
|
|
|
|
### Immediate Next Steps |
|
|
|
|
|
|
|
|
|
#### 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) |
|
|
|
|
|
|
|
|
|
### Visualization Features |
|
|
|
|
|
|
|
|
|
#### 5. 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 |
|
|
|
|
- Mid-course corrections |
|
|
|
|
- Gravity assist maneuvers |
|
|
|
|
- Powered flybys |
|
|
|
|
- Multi-stage missions |
|
|
|
|
|
|
|
|
|
#### 7. SOI Visualization |
|
|
|
|
- Render SOI boundaries as wireframe spheres |
|
|
|
|
- Color-coded by mass |
|
|
|
|
- Toggle with keyboard shortcut |
|
|
|
|
- Show SOI transitions in real-time |
|
|
|
|
|
|
|
|
|
### Advanced Features |
|
|
|
|
|
|
|
|
|
#### 8. 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 |
|
|
|
|
- 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 |
|
|
|
|
- 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) |