From d51e94830e116de617f0d9f98482ff29da822f77 Mon Sep 17 00:00:00 2001 From: cinnaboot Date: Mon, 26 Jan 2026 13:37:51 -0500 Subject: [PATCH] add test case to verify spacecraft state vectors --- tests/test_maneuvers.cpp | 71 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/tests/test_maneuvers.cpp b/tests/test_maneuvers.cpp index a812e23..1dda1d9 100644 --- a/tests/test_maneuvers.cpp +++ b/tests/test_maneuvers.cpp @@ -159,3 +159,74 @@ TEST_CASE("Spacecraft propagation maintains stability", "[spacecraft][propagatio destroy_simulation(sim); } + +TEST_CASE("Spacecraft state vectors at orbital quarters", "[spacecraft][state_vectors]") { + const double TIME_STEP = 60.0; + + SimulationState* sim = create_simulation(10, 10, 0, TIME_STEP); + + REQUIRE(load_system_config(sim, "tests/test_maneuvers.toml")); + + Spacecraft* craft = &sim->spacecraft[0]; + CelestialBody* earth = &sim->bodies[1]; + + double orbit_radius = vec3_magnitude(craft->local_position); + double earth_mass = earth->mass; + + double orbital_period = 2.0 * M_PI * sqrt(pow(orbit_radius, 3.0) / (G * earth_mass)); + double quarter_orbit_time = orbital_period / 4.0; + int steps_per_quarter = (int)(quarter_orbit_time / TIME_STEP); + + INFO("Orbital radius: " << orbit_radius << " m"); + INFO("Expected orbital period: " << orbital_period << " s (" << orbital_period / 3600.0 << " hours)"); + INFO("Steps per quarter: " << steps_per_quarter); + + double previous_angle = atan2(craft->local_position.y, craft->local_position.x); + + for (int quarter = 0; quarter <= 4; quarter++) { + INFO(""); + INFO("=== Point " << quarter << "/4 (" << (quarter * 90) << "°) ==="); + INFO("Local position: (" << craft->local_position.x << ", " << craft->local_position.y << ", " << craft->local_position.z << ") m"); + INFO("Local velocity: (" << craft->local_velocity.x << ", " << craft->local_velocity.y << ", " << craft->local_velocity.z << ") m/s"); + + double current_radius = vec3_magnitude(craft->local_position); + double current_velocity = vec3_magnitude(craft->local_velocity); + double current_angle = atan2(craft->local_position.y, craft->local_position.x); + + INFO("Radius: " << current_radius << " m"); + INFO("Velocity magnitude: " << current_velocity << " m/s"); + INFO("Angular position: " << current_angle << " rad (" << (current_angle * 180.0 / M_PI) << "°)"); + + if (quarter > 0) { + double angle_change = current_angle - previous_angle; + if (angle_change < 0) angle_change += 2.0 * M_PI; + INFO("Angle change from previous: " << angle_change << " rad (" << (angle_change * 180.0 / M_PI) << "°)"); + REQUIRE(fabs(angle_change - M_PI / 2.0) < 0.1); + } + + if (quarter < 4) { + for (int step = 0; step < steps_per_quarter; step++) { + update_simulation(sim); + } + } + + previous_angle = current_angle; + } + + INFO(""); + INFO("=== Final Summary ==="); + double final_radius = vec3_magnitude(craft->local_position); + double final_velocity = vec3_magnitude(craft->local_velocity); + double final_angle = atan2(craft->local_position.y, craft->local_position.x); + double total_rotation = final_angle; + + if (total_rotation < 0) total_rotation += 2.0 * M_PI; + + INFO("Total rotation: " << total_rotation << " rad (" << (total_rotation * 180.0 / M_PI) << "°)"); + INFO("Radius change: " << ((final_radius - orbit_radius) / orbit_radius * 100.0) << "%"); + INFO("Velocity change: " << ((final_velocity - vec3_magnitude(craft->local_velocity)) / vec3_magnitude(craft->local_velocity) * 100.0) << "%"); + + REQUIRE(fabs(total_rotation - 2.0 * M_PI) < 0.1); + + destroy_simulation(sim); +}