diff --git a/old_tests/test_periapsis_burn.cpp b/old_tests/test_periapsis_burn.cpp deleted file mode 100644 index aa3d7d1..0000000 --- a/old_tests/test_periapsis_burn.cpp +++ /dev/null @@ -1,266 +0,0 @@ -#include -#include -#include "../src/physics.h" -#include "../src/simulation.h" -#include "../src/orbital_objects.h" -#include "../src/maneuver.h" -#include "../src/config_loader.h" -#include "../src/orbital_mechanics.h" -#include - -// NOTE: calculate_true_anomaly() was removed from the public API. -// It was redundant with cartesian_to_orbital_elements() which already -// computes true_anomaly as part of OrbitalElements. -// -// Suggested replacement for later refactor: -// OrbitalElements orbit = cartesian_to_orbital_elements(r, v, parent->mass); -// double true_anomaly = orbit.true_anomaly; -// -// Or even simpler — since the sim already calls cartesian_to_orbital_elements() -// each frame, just read craft->orbit.true_anomaly directly. - -// Test prograde burn at periapsis (true anomaly = 0) -// Verifies that the maneuver executes correctly when starting at periapsis -TEST_CASE("Prograde burn at periapsis preserves periapsis distance", "[maneuver][periapsis]") { - const double TIME_STEP = 60.0; - SimulationState* sim = create_simulation(10, 10, 100, TIME_STEP); - - REQUIRE(load_system_config(sim, "tests/test_periapsis_burn.toml")); - - Spacecraft* craft = &sim->spacecraft[0]; - - // Record initial state (at periapsis) - double initial_radius = vec3_magnitude(craft->local_position); - double initial_sma = craft->orbit.semi_major_axis; - double initial_ecc = craft->orbit.eccentricity; - double initial_periapsis = initial_sma * (1.0 - initial_ecc); - double initial_velocity = vec3_magnitude(craft->local_velocity); - - INFO("Initial state:"); - INFO(" Radius: " << initial_radius << " (should equal periapsis: " << initial_periapsis << ")"); - INFO(" True anomaly: " << craft->orbit.true_anomaly); - INFO(" Velocity: " << initial_velocity); - INFO(" Maneuver trigger: true_anomaly = " << sim->maneuvers[0].trigger_value); - - // Execute one step - update_simulation(sim); - - // Check if maneuver executed - INFO("After 1 step:"); - INFO(" Maneuver executed: " << sim->maneuvers[0].executed); - INFO(" Final radius: " << vec3_magnitude(craft->local_position)); - INFO(" Final velocity: " << vec3_magnitude(craft->local_velocity)); - - // The maneuver should have executed since we started at periapsis - // This assertion will fail due to the bug - the trigger check happens - // after physics moves the spacecraft past periapsis - REQUIRE(sim->maneuvers[0].executed); - - // If the maneuver executed, verify the physics: - double final_sma = craft->orbit.semi_major_axis; - double final_ecc = craft->orbit.eccentricity; - double final_periapsis = final_sma * (1.0 - final_ecc); - double final_velocity = vec3_magnitude(craft->local_velocity); - - // Periapsis distance should be preserved - REQUIRE_THAT(final_periapsis, Catch::Matchers::WithinAbs(initial_periapsis, 1.0)); - - // Semi-major axis and velocity should increase - REQUIRE(final_sma > initial_sma); - REQUIRE(final_velocity > initial_velocity); - - destroy_simulation(sim); -} - -TEST_CASE("Two periapsis burns execute at same location", "[maneuver][periapsis][sequential]") { - const double TIME_STEP = 60.0; - const int ORBIT_STEPS = 300; - SimulationState* sim = create_simulation(10, 10, 100, TIME_STEP); - - REQUIRE(load_system_config(sim, "tests/test_periapsis_burn.toml")); - - Spacecraft* craft = &sim->spacecraft[0]; - CelestialBody* parent = &sim->bodies[craft->parent_index]; - - int maneuver_indices[2]; - int maneuver_count_for_craft = 0; - for (int i = 0; i < sim->maneuver_count; i++) { - if (sim->maneuvers[i].craft_index == 0) { - maneuver_indices[maneuver_count_for_craft++] = i; - } - } - REQUIRE(maneuver_count_for_craft == 2); - - double initial_periapsis = craft->orbit.semi_major_axis * (1.0 - craft->orbit.eccentricity); - double initial_apoapsis = craft->orbit.semi_major_axis * (1.0 + craft->orbit.eccentricity); - - INFO("Initial orbit:"); - INFO(" Periapsis: " << initial_periapsis); - INFO(" Apoapsis: " << initial_apoapsis); - INFO(" Eccentricity: " << craft->orbit.eccentricity); - - double burn1_time = -1.0; - double burn1_radius = -1.0; - double burn1_true_anomaly = -10.0; - double burn1_period = -1.0; - double burn2_time = -1.0; - double burn2_radius = -1.0; - double burn2_true_anomaly = -10.0; - - for (int i = 0; i < ORBIT_STEPS; i++) { - update_simulation(sim); - - if (sim->maneuvers[maneuver_indices[0]].executed && burn1_time < 0) { - burn1_time = sim->time; - burn1_radius = vec3_magnitude(craft->local_position); - burn1_period = 2.0 * M_PI * sqrt(pow(craft->orbit.semi_major_axis, 3.0) / (G * parent->mass)); - - Vec3 r = craft->local_position; - Vec3 v = craft->local_velocity; - Vec3 h = vec3_cross(r, v); - Vec3 e_vec = calculate_eccentricity_vector(r, v, h, G * parent->mass); - double e_mag = vec3_magnitude(e_vec); - burn1_true_anomaly = calculate_true_anomaly(r, v, e_vec, e_mag, burn1_radius); - burn1_true_anomaly = normalize_angle(burn1_true_anomaly); - - INFO("First burn executed at step " << i); - INFO(" Time: " << burn1_time); - INFO(" Radius: " << burn1_radius); - INFO(" True anomaly: " << burn1_true_anomaly << " rad (" << burn1_true_anomaly * 180.0 / M_PI << "°)"); - INFO(" Periapsis: " << initial_periapsis); - INFO(" Apoapsis: " << initial_apoapsis); - INFO(" New period: " << burn1_period << " seconds"); - } - - if (sim->maneuvers[maneuver_indices[1]].executed && burn2_time < 0) { - burn2_time = sim->time; - burn2_radius = vec3_magnitude(craft->local_position); - - Vec3 r = craft->local_position; - Vec3 v = craft->local_velocity; - Vec3 h = vec3_cross(r, v); - Vec3 e_vec = calculate_eccentricity_vector(r, v, h, G * parent->mass); - double e_mag = vec3_magnitude(e_vec); - burn2_true_anomaly = calculate_true_anomaly(r, v, e_vec, e_mag, burn2_radius); - burn2_true_anomaly = normalize_angle(burn2_true_anomaly); - - INFO("Second burn executed at step " << i); - INFO(" Time: " << burn2_time); - INFO(" Radius: " << burn2_radius); - INFO(" True anomaly: " << burn2_true_anomaly << " rad (" << burn2_true_anomaly * 180.0 / M_PI << "°)"); - } - } - - REQUIRE(sim->maneuvers[maneuver_indices[0]].executed); - REQUIRE(sim->maneuvers[maneuver_indices[1]].executed); - - INFO("Burn comparison:"); - INFO(" Burn 1: time=" << burn1_time << ", radius=" << burn1_radius << ", true_anomaly=" << burn1_true_anomaly); - INFO(" Burn 2: time=" << burn2_time << ", radius=" << burn2_radius << ", true_anomaly=" << burn2_true_anomaly); - - REQUIRE_THAT(burn1_radius, Catch::Matchers::WithinAbs(initial_periapsis, 10000.0)); - REQUIRE_THAT(burn2_radius, Catch::Matchers::WithinAbs(initial_periapsis, 10000.0)); - - REQUIRE(fabs(burn1_true_anomaly) < 0.5); - REQUIRE(fabs(burn2_true_anomaly) < 0.5); - - INFO("Expected orbital period (after burn 1): " << burn1_period << " seconds"); - INFO("Actual time between burns: " << (burn2_time - burn1_time) << " seconds"); - - REQUIRE_THAT(burn2_time - burn1_time, Catch::Matchers::WithinAbs(burn1_period, TIME_STEP * 2.0)); - - destroy_simulation(sim); -} - -TEST_CASE("Periapsis burn fires when crossing periapsis", "[maneuver][periapsis][crossing]") { - const double TIME_STEP = 60.0; - SimulationState* sim = create_simulation(10, 10, 100, TIME_STEP); - - REQUIRE(load_system_config(sim, "tests/test_periapsis_burn.toml")); - - Spacecraft* craft = &sim->spacecraft[1]; // TestSatelliteCrossing - CelestialBody* parent = &sim->bodies[craft->parent_index]; - - int maneuver_index = -1; - for (int i = 0; i < sim->maneuver_count; i++) { - if (sim->maneuvers[i].craft_index == 1) { - maneuver_index = i; - break; - } - } - REQUIRE(maneuver_index >= 0); - - double initial_periapsis = craft->orbit.semi_major_axis * (1.0 - craft->orbit.eccentricity); - double initial_apoapsis = craft->orbit.semi_major_axis * (1.0 + craft->orbit.eccentricity); - - INFO("Initial orbit:"); - INFO(" Periapsis: " << initial_periapsis); - INFO(" Apoapsis: " << initial_apoapsis); - INFO(" Initial true anomaly: " << craft->orbit.true_anomaly << " rad"); - - double burn_time = -1.0; - double burn_radius = -1.0; - double burn_true_anomaly = -10.0; - - int max_steps = 1000; - for (int i = 0; i < max_steps && !sim->maneuvers[maneuver_index].executed; i++) { - update_simulation(sim); - - if (sim->maneuvers[maneuver_index].executed) { - burn_time = sim->time; - burn_radius = vec3_magnitude(craft->local_position); - - Vec3 r = craft->local_position; - Vec3 v = craft->local_velocity; - Vec3 h = vec3_cross(r, v); - Vec3 e_vec = calculate_eccentricity_vector(r, v, h, G * parent->mass); - double e_mag = vec3_magnitude(e_vec); - burn_true_anomaly = calculate_true_anomaly(r, v, e_vec, e_mag, burn_radius); - burn_true_anomaly = normalize_angle(burn_true_anomaly); - - INFO("Burn executed at step " << i); - INFO(" Time: " << burn_time); - INFO(" Radius: " << burn_radius); - INFO(" True anomaly: " << burn_true_anomaly << " rad (" << burn_true_anomaly * 180.0 / M_PI << "°)"); - INFO(" Periapsis: " << initial_periapsis); - INFO(" Apoapsis: " << initial_apoapsis); - } - } - - REQUIRE(sim->maneuvers[maneuver_index].executed); - - REQUIRE_THAT(burn_radius, Catch::Matchers::WithinAbs(initial_periapsis, 1000.0)); - - REQUIRE(fabs(burn_true_anomaly) < 0.5); - - destroy_simulation(sim); -} - - -TEST_CASE("Burn location equals new periapsis after prograde burn", "[maneuver][periapsis][location]") { - const double TIME_STEP = 60.0; - SimulationState* sim = create_simulation(10, 10, 100, TIME_STEP); - - REQUIRE(load_system_config(sim, "tests/test_periapsis_burn.toml")); - - Spacecraft* craft = &sim->spacecraft[0]; - - double initial_periapsis = craft->orbit.semi_major_axis * (1.0 - craft->orbit.eccentricity); - double initial_radius = vec3_magnitude(craft->local_position); - - update_simulation(sim); - - REQUIRE(sim->maneuvers[0].executed); - - double final_periapsis = craft->orbit.semi_major_axis * (1.0 - craft->orbit.eccentricity); - - INFO("Initial radius: " << initial_radius); - INFO("Initial periapsis: " << initial_periapsis); - INFO("Final periapsis: " << final_periapsis); - - REQUIRE_THAT(initial_radius, Catch::Matchers::WithinAbs(initial_periapsis, 100.0)); - - REQUIRE_THAT(final_periapsis, Catch::Matchers::WithinAbs(initial_periapsis, 100.0)); - - destroy_simulation(sim); -} diff --git a/old_tests/test_periapsis_burn.toml b/old_tests/test_periapsis_burn.toml deleted file mode 100644 index b24f65a..0000000 --- a/old_tests/test_periapsis_burn.toml +++ /dev/null @@ -1,74 +0,0 @@ -# Test Configuration: Prograde Burn at Periapsis -# Tests that periapsis distance is preserved during prograde burn - -[[bodies]] -name = "Sun" -mass = 1.989e30 -radius = 6.96e8 -parent_index = -1 -color = { r = 1.0, g = 1.0, b = 0.0 } -orbit = { - semi_major_axis = 0.0, - eccentricity = 0.0, - true_anomaly = 0.0 -} - -[[bodies]] -name = "Earth" -mass = 5.972e24 -radius = 6.371e6 -parent_index = 0 -color = { r = 0.0, g = 0.5, b = 1.0 } -orbit = { - semi_major_axis = 1.496e11, - eccentricity = 0.0, - true_anomaly = 0.0 -} - -[[spacecraft]] -name = "TestSatellite" -mass = 1000.0 -parent_index = 1 -# Start at periapsis of an elliptical orbit -# a = 10,000 km, e = 0.3 -# periapsis = 7,000 km, apoapsis = 13,000 km -orbit = { - semi_major_axis = 1.0371e7, - eccentricity = 0.3, - true_anomaly = 0.0 -} - -[[spacecraft]] -name = "TestSatelliteCrossing" -mass = 1000.0 -parent_index = 1 -# Start at 90 degrees from periapsis for crossing test -orbit = { - semi_major_axis = 1.0371e7, - eccentricity = 0.3, - true_anomaly = 1.57 # 90 degrees (pi/2) -} - -[[maneuvers]] -name = "periapsis_prograde_burn" -spacecraft_name = "TestSatellite" -trigger_type = "true_anomaly" -trigger_value = 0.0 -direction = "prograde" -delta_v = 500.0 - -[[maneuvers]] -name = "periapsis_prograde_burn_2" -spacecraft_name = "TestSatellite" -trigger_type = "true_anomaly" -trigger_value = 0.0 -direction = "prograde" -delta_v = 500.0 - -[[maneuvers]] -name = "periapsis_prograde_burn_crossing" -spacecraft_name = "TestSatelliteCrossing" -trigger_type = "true_anomaly" -trigger_value = 0.0 -direction = "prograde" -delta_v = 500.0