#include #include "../src/physics.h" #include "../src/mission_planning.h" #include "../src/simulation.h" #include "../src/config_loader.h" #include "../src/test_utilities.h" #include TEST_CASE("Earth → Mars Hohmann Transfer - Basic", "[mission][hohmann][integration]") { const double TIME_STEP = 60.0; const double SECONDS_PER_DAY = 86400.0; SimulationState* sim = create_simulation(10, 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; CelestialBody* earth = &sim->bodies[EARTH_IDX]; CelestialBody* mars = &sim->bodies[MARS_IDX]; CelestialBody* sun = &sim->bodies[SUN_IDX]; double r_earth = vec3_distance(earth->position, sun->position); double r_mars = vec3_distance(mars->position, sun->position); TransferParameters params = calculate_hohmann_transfer(r_earth, r_mars, sun->mass); INFO("Transfer time: " << params.transfer_time / SECONDS_PER_DAY << " days"); INFO("Required phase angle: " << params.phase_angle_deg << " degrees"); INFO("Delta-v injection: " << params.delta_v_injection / 1000.0 << " km/s"); wait_for_launch_window(sim, EARTH_IDX, MARS_IDX, params.phase_angle_deg, 1.0); double departure_time = sim->time; int probe_idx = spawn_spacecraft_on_transfer(sim, EARTH_IDX, ¶ms); REQUIRE(probe_idx >= 0); CelestialBody* probe = &sim->bodies[probe_idx]; REQUIRE(probe->parent_index == SUN_IDX); REQUIRE(vec3_distance(probe->position, earth->position) < 1e6); OrbitalMetrics initial_metrics = calculate_orbital_metrics(probe, sun); INFO("Initial orbital energy: " << initial_metrics.total_energy); double simulation_duration = params.transfer_time * 1.1; while (sim->time < departure_time + simulation_duration) { update_simulation(sim); } OrbitalMetrics final_metrics = calculate_orbital_metrics(probe, sun); INFO("Final orbital radius: " << final_metrics.orbital_radius / 1.496e11 << " AU"); INFO("Final orbital energy: " << final_metrics.total_energy); double energy_drift = fabs(final_metrics.total_energy - initial_metrics.total_energy); if (initial_metrics.total_energy != 0.0) { energy_drift /= fabs(initial_metrics.total_energy); } INFO("Energy drift: " << (energy_drift * 100.0) << "%"); REQUIRE(energy_drift < 0.05); destroy_simulation(sim); }