#include #include "../src/physics.h" #include "../src/mission_planning.h" #include "../src/simulation.h" #include "../src/config_loader.h" #include const double AU = 1.496e11; const double M_SUN = 1.989e30; const double M_EARTH = 5.972e24; const double M_MARS = 6.39e23; const double R_EARTH = 1.496e11; const double R_MARS = 2.279e11; const double SECONDS_PER_DAY = 86400.0; TEST_CASE("Hohmann transfer - Earth to Mars", "[mission][hohmann]") { TransferParameters params = calculate_hohmann_transfer(R_EARTH, R_MARS, M_SUN); INFO("Semi-major axis: " << params.semi_major_axis / AU << " AU"); INFO("Eccentricity: " << params.eccentricity); INFO("Transfer time: " << params.transfer_time / SECONDS_PER_DAY << " days"); INFO("Departure velocity: " << params.departure_velocity / 1000.0 << " km/s"); INFO("Arrival velocity: " << params.arrival_velocity / 1000.0 << " km/s"); INFO("Phase angle: " << params.phase_angle_deg << " degrees"); INFO("Delta-v injection: " << params.delta_v_injection / 1000.0 << " km/s"); double expected_transfer_time = 259.0 * SECONDS_PER_DAY; double transfer_time_error = fabs(params.transfer_time - expected_transfer_time) / expected_transfer_time; REQUIRE(transfer_time_error < 0.05); double expected_phase_angle = 44.3; double phase_angle_error = fabs(params.phase_angle_deg - expected_phase_angle); REQUIRE(phase_angle_error < 1.0); double expected_delta_v = 2940.0; double delta_v_error = fabs(params.delta_v_injection - expected_delta_v) / expected_delta_v; REQUIRE(delta_v_error < 0.05); } TEST_CASE("Hohmann transfer - Mars to Earth", "[mission][hohmann][reverse]") { TransferParameters params = calculate_hohmann_transfer(R_MARS, R_EARTH, M_SUN); INFO("Transfer time (return): " << params.transfer_time / SECONDS_PER_DAY << " days"); INFO("Phase angle (return): " << params.phase_angle_deg << " degrees"); INFO("Delta-v injection (return): " << params.delta_v_injection / 1000.0 << " km/s"); REQUIRE(params.transfer_time > 0); double expected_sma = (R_EARTH + R_MARS) / 2.0; double sma_error = fabs(params.semi_major_axis - expected_sma) / expected_sma; REQUIRE(sma_error < 0.01); } TEST_CASE("Angular position - circular orbit", "[mission][angular]") { SimulationState* sim = create_simulation(10, 60.0); REQUIRE(load_system_config(sim, "tests/configs/earth_circular.toml")); CelestialBody* earth = &sim->bodies[1]; CelestialBody* sun = &sim->bodies[0]; double angle = calculate_angular_position(earth, sun); INFO("Earth angular position: " << angle << " rad (" << angle * 180.0 / M_PI << " deg)"); REQUIRE(angle >= 0.0); REQUIRE(angle < 2.0 * M_PI); update_simulation(sim); double angle_after = calculate_angular_position(earth, sun); INFO("Earth angular position after update: " << angle_after << " rad (" << angle_after * 180.0 / M_PI << " deg)"); REQUIRE(angle_after >= 0.0); REQUIRE(angle_after < 2.0 * M_PI); destroy_simulation(sim); } TEST_CASE("Phase angle calculation", "[mission][phase]") { double earth_period = 365.25 * SECONDS_PER_DAY; double mars_period = 687.0 * SECONDS_PER_DAY; double transfer_time = 259.0 * SECONDS_PER_DAY; double phase_angle = calculate_required_phase_angle(transfer_time, mars_period); INFO("Required phase angle: " << phase_angle << " degrees"); REQUIRE(phase_angle >= 0.0); REQUIRE(phase_angle < 360.0); double expected_phase_angle = 44.3; double phase_error = fabs(phase_angle - expected_phase_angle); REQUIRE(phase_error < 1.0); } TEST_CASE("Launch window detection", "[mission][window]") { const double TIME_STEP = 60.0; SimulationState* sim = create_simulation(10, TIME_STEP); REQUIRE(load_system_config(sim, "tests/configs/earth_mars_simple.toml")); const int EARTH_IDX = 1; const int MARS_IDX = 2; double r_earth = vec3_distance(sim->bodies[EARTH_IDX].position, sim->bodies[0].position); double r_mars = vec3_distance(sim->bodies[MARS_IDX].position, sim->bodies[0].position); TransferParameters params = calculate_hohmann_transfer(r_earth, r_mars, sim->bodies[0].mass); bool window_open = check_launch_window(sim, EARTH_IDX, MARS_IDX, params.phase_angle_deg, 5.0); INFO("Phase angle required: " << params.phase_angle_deg << " degrees"); INFO("Launch window open: " << (window_open ? "YES" : "NO")); REQUIRE(!window_open); destroy_simulation(sim); } TEST_CASE("Wait for launch window", "[mission][wait]") { const double TIME_STEP = 60.0; SimulationState* sim = create_simulation(10, TIME_STEP); REQUIRE(load_system_config(sim, "tests/configs/earth_mars_simple.toml")); const int EARTH_IDX = 1; const int MARS_IDX = 2; double r_earth = vec3_distance(sim->bodies[EARTH_IDX].position, sim->bodies[0].position); double r_mars = vec3_distance(sim->bodies[MARS_IDX].position, sim->bodies[0].position); TransferParameters params = calculate_hohmann_transfer(r_earth, r_mars, sim->bodies[0].mass); double start_time = sim->time; wait_for_launch_window(sim, EARTH_IDX, MARS_IDX, params.phase_angle_deg, 1.0); double end_time = sim->time; double wait_time = (end_time - start_time) / SECONDS_PER_DAY; INFO("Waited " << wait_time << " days for launch window"); bool window_open = check_launch_window(sim, EARTH_IDX, MARS_IDX, params.phase_angle_deg, 1.0); REQUIRE(window_open); destroy_simulation(sim); }