You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
149 lines
5.5 KiB
149 lines
5.5 KiB
#include <catch2/catch_test_macros.hpp> |
|
#include "../src/physics.h" |
|
#include "../src/mission_planning.h" |
|
#include "../src/simulation.h" |
|
#include "../src/config_loader.h" |
|
#include <cmath> |
|
|
|
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); |
|
}
|
|
|