vibe coding an orbital mechanics simulation to try out claude code
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.
 
 
 
 
 

89 lines
3.2 KiB

#include <catch2/catch_test_macros.hpp>
#include <catch2/matchers/catch_matchers_floating_point.hpp>
#include "../src/physics.h"
#include "../src/orbital_mechanics.h"
#include "../src/simulation.h"
#include "../src/config_loader.h"
#include <cmath>
using Catch::Matchers::WithinAbs;
SCENARIO("Cartesian ↔ orbital elements round-trip conversion",
"[cartesian][elements][roundtrip]") {
const double TIME_STEP = 60.0;
const double parent_mass = 5.972e24;
const double A_TOL = 1e-6;
const double E_TOL = 1e-12;
const double ANG_TOL = 1e-12;
const double R_TOL = 1e-6;
const double V_TOL = 1e-6;
SimulationState* sim = create_simulation(10, 1, 0, TIME_STEP);
REQUIRE(load_system_config(sim, "tests/test_cartesian_to_elements_basic.toml"));
Spacecraft* craft = &sim->spacecraft[0];
const OrbitalElements& orig = craft->orbit;
// Convert elements → state vectors
Vec3 pos, vel;
orbital_elements_to_cartesian(orig, parent_mass, &pos, &vel);
const double expected_r = vec3_magnitude(pos); // 7500000.0
const double expected_v = vec3_magnitude(vel); // 8928.484709...
// Round-trip: state vectors → elements
const OrbitalElements recovered = cartesian_to_orbital_elements(pos, vel, parent_mass);
// Re-convert recovered elements → state vectors
Vec3 pos2, vel2;
orbital_elements_to_cartesian(recovered, parent_mass, &pos2, &vel2);
const double recovered_r = vec3_magnitude(pos2);
const double recovered_v = vec3_magnitude(vel2);
SECTION("elements round-trip: semi-major axis") {
const double da = fabs(recovered.semi_major_axis - orig.semi_major_axis);
INFO("Original a: " << orig.semi_major_axis);
INFO("Recovered a: " << recovered.semi_major_axis);
INFO("Error: " << da << " m");
REQUIRE_THAT(da, WithinAbs(0.0, A_TOL));
}
SECTION("elements round-trip: eccentricity") {
const double de = fabs(recovered.eccentricity - orig.eccentricity);
INFO("Original e: " << orig.eccentricity);
INFO("Recovered e: " << recovered.eccentricity);
INFO("Error: " << de);
REQUIRE_THAT(de, WithinAbs(0.0, E_TOL));
}
SECTION("elements round-trip: true anomaly") {
const double dnu = fabs(recovered.true_anomaly - orig.true_anomaly);
INFO("Original nu: " << orig.true_anomaly);
INFO("Recovered nu: " << recovered.true_anomaly);
INFO("Error: " << dnu);
REQUIRE_THAT(dnu, WithinAbs(0.0, ANG_TOL));
}
SECTION("elements round-trip: inclination") {
const double dinc = fabs(recovered.inclination - orig.inclination);
INFO("Original inc: " << orig.inclination);
INFO("Recovered inc: " << recovered.inclination);
INFO("Error: " << dinc);
REQUIRE_THAT(dinc, WithinAbs(0.0, ANG_TOL));
}
SECTION("radius preservation") {
INFO("Original r: " << expected_r);
INFO("Recovered r: " << recovered_r);
REQUIRE_THAT(recovered_r, WithinAbs(expected_r, R_TOL));
}
SECTION("velocity magnitude preservation") {
INFO("Original v: " << expected_v);
INFO("Recovered v: " << recovered_v);
REQUIRE_THAT(recovered_v, WithinAbs(expected_v, V_TOL));
}
destroy_simulation(sim);
}