From 9d979341759e7df8cb32b0b56cec97d3690d559d Mon Sep 17 00:00:00 2001 From: cinnaboot Date: Sat, 31 Jan 2026 10:38:11 -0500 Subject: [PATCH] Fix true anomaly calculation in cartesian_to_orbital_elements() Bug: r_dot_e was incorrectly divided by mu instead of r_mag*e_mag, causing cos_nu values of ~7.5e6 (far outside [-1,1]) which made acos() return NaN. Fix: Calculate cos_nu correctly as r_dot_e/(r_mag*e_mag) and clamp to [-1, 1] to handle floating-point precision errors. This fixes all cartesian <-> orbital elements round-trip conversion tests. --- src/orbital_mechanics.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/orbital_mechanics.cpp b/src/orbital_mechanics.cpp index 6f25bd9..10798ad 100644 --- a/src/orbital_mechanics.cpp +++ b/src/orbital_mechanics.cpp @@ -119,13 +119,17 @@ OrbitalElements cartesian_to_orbital_elements(Vec3 position, Vec3 velocity, doub a = mu / (2.0 * specific_energy); } - double r_dot_e = vec3_dot(r_vec, e_vec) / mu; + double r_mag = vec3_magnitude(r_vec); + double e_mag = vec3_magnitude(e_vec); + double r_dot_e = vec3_dot(r_vec, e_vec); double true_anomaly; - if (e < 1e-10) { + if (e < 1e-10 || e_mag < 1e-10) { true_anomaly = 0.0; } else { - true_anomaly = acos(r_dot_e / e); + double cos_nu = r_dot_e / (r_mag * e_mag); + cos_nu = fmax(-1.0, fmin(1.0, cos_nu)); + true_anomaly = acos(cos_nu); if (vec3_dot(r_vec, v_vec) < 0.0) { true_anomaly = 2.0 * M_PI - true_anomaly; }