#!/usr/bin/env python3 """ Precalculate expected values for test_extreme_eccentricity.cpp. Usage: python3 scripts/precalc_extreme_eccentricity.py Outputs C++-style comments with precalculated values for embedding in the test. """ import sys, math sys.path.insert(0, 'scripts') from sim_engine import orbital_to_cartesian, cartesian_to_orbital_elements, vmag, OrbitalElements, G # ============================================================================= # Spacecraft 0: Highly_Elliptical (e=0.99, a=6.5e8) # ============================================================================= mu = G * 5.972e24 a0 = 6.5e8 e0 = 0.99 nu0 = 0.0 elements0 = OrbitalElements(a=a0, e=e0, nu=nu0, inc=0.0, Omega=0.0, omega=0.0) pos0, vel0 = orbital_to_cartesian(elements0, 5.972e24) r0 = vmag(pos0) v0 = vmag(vel0) expected_r_peri0 = a0 * (1.0 - e0) expected_r_apo0 = a0 * (1.0 + e0) # Round-trip elements0_rt = cartesian_to_orbital_elements(pos0, vel0, 5.972e24) print("# Spacecraft 0: Highly_Elliptical (e=0.99, a=6.5e8)") print(f"# r_peri = {expected_r_peri0:.6f} m") print(f"# r_apo = {expected_r_apo0:.6f} m") print(f"# r = {r0:.6f} m") print(f"# v = {v0:.6f} m/s") print(f"# dr = {abs(r0 - expected_r_peri0):.2e} m") print(f"# dr_apo = {abs(r0 - expected_r_apo0):.2e} m") print(f"# e_rt = {elements0_rt.e:.15f} (error: {abs(elements0_rt.e - e0):.2e})") print(f"# a_rt = {elements0_rt.a:.6f} m") print() # Nu = pi (apoapsis) elements0_pi = OrbitalElements(a=a0, e=e0, nu=math.pi, inc=0.0, Omega=0.0, omega=0.0) pos0_pi, vel0_pi = orbital_to_cartesian(elements0_pi, 5.972e24) r0_pi = vmag(pos0_pi) v0_pi = vmag(vel0_pi) print(f"# At apoapsis (nu=pi):") print(f"# r = {r0_pi:.6f} m (expected: {expected_r_apo0:.6f} m)") print(f"# v = {v0_pi:.6f} m/s") print(f"# dr = {abs(r0_pi - expected_r_apo0):.2e} m") print() # ============================================================================= # Spacecraft 1: Near_Parabolic (e=0.99, a=7.0e8) # ============================================================================= a1 = 7.0e8 e1 = 0.99 nu1 = 0.0 elements1 = OrbitalElements(a=a1, e=e1, nu=nu1, inc=0.0, Omega=0.0, omega=0.0) pos1, vel1 = orbital_to_cartesian(elements1, 5.972e24) r1 = vmag(pos1) v1 = vmag(vel1) expected_r_peri1 = a1 * (1.0 - e1) expected_r_apo1 = a1 * (1.0 + e1) # Apoapsis elements1_pi = OrbitalElements(a=a1, e=e1, nu=math.pi, inc=0.0, Omega=0.0, omega=0.0) pos1_pi, vel1_pi = orbital_to_cartesian(elements1_pi, 5.972e24) r1_pi = vmag(pos1_pi) v1_pi = vmag(vel1_pi) print("# Spacecraft 1: Near_Parabolic (e=0.99, a=7.0e8)") print(f"# r_peri = {expected_r_peri1:.6f} m") print(f"# r_apo = {expected_r_apo1:.6f} m") print(f"# r_peri_actual = {r1:.6f} m") print(f"# v_peri = {v1:.6f} m/s") print(f"# r_apo_actual = {r1_pi:.6f} m") print(f"# v_apo = {v1_pi:.6f} m/s") print(f"# dr_peri = {abs(r1 - expected_r_peri1):.2e} m") print(f"# dr_apo = {abs(r1_pi - expected_r_apo1):.2e} m") print(f"# v_peri > v_apo: {v1 > v1_pi}") print() # ============================================================================= # Spacecraft 2: Slightly_Hyperbolic (e=1.05, a=-1.3e8) # ============================================================================= a2 = -1.3e8 e2 = 1.05 nu2 = 0.0 elements2 = OrbitalElements(a=a2, e=e2, nu=nu2, inc=0.0, Omega=0.0, omega=0.0) pos2, vel2 = orbital_to_cartesian(elements2, 5.972e24) r2 = vmag(pos2) v2 = vmag(vel2) escape_vel = math.sqrt(2.0 * mu / r2) circular_vel = math.sqrt(mu / r2) expected_v_sq = mu * (2.0 / r2 - 1.0 / a2) expected_v = math.sqrt(expected_v_sq) print("# Spacecraft 2: Slightly_Hyperbolic (e=1.05, a=-1.3e8)") print(f"# r = {r2:.6f} m") print(f"# v = {v2:.6f} m/s") print(f"# v_exp = {expected_v:.6f} m/s") print(f"# v_err = {abs(v2 - expected_v):.2e} m/s") print(f"# rel_err = {abs(v2 - expected_v) / expected_v:.2e}") print(f"# escape_vel = {escape_vel:.6f} m/s") print(f"# circular_vel = {circular_vel:.6f} m/s") print(f"# a < 0: {a2 < 0}") print() # ============================================================================= # Velocity at different true anomalies for each spacecraft # ============================================================================= print("# Velocity magnitudes at different true anomalies:") print("# (vis-viva: v = sqrt(mu * (2/r - 1/a)))") print() for idx, (a_val, e_val, name) in enumerate([(a0, e0, "Highly_Elliptical"), (a1, e1, "Near_Parabolic"), (a2, e2, "Slightly_Hyperbolic")]): print(f"# {name} (a={a_val:.2e}, e={e_val:.2f}):") for nu in [0.0, math.pi/2.0, math.pi, 3.0*math.pi/2.0]: if e_val > 1.0: max_nu = math.acos(-1.0 / e_val) if abs(nu) >= max_nu: print(f"# nu={nu:.4f} rad: SKIPPED (hyperbolic limit +/- {max_nu:.4f})") continue elem = OrbitalElements(a=a_val, e=e_val, nu=nu, inc=0.0, Omega=0.0, omega=0.0) p, v = orbital_to_cartesian(elem, 5.972e24) r = vmag(p) v_mag = vmag(v) v_exp = math.sqrt(mu * (2.0/r - 1.0/a_val)) rel_err = abs(v_mag - v_exp) / v_exp print(f"# nu={nu:.4f} rad: v={v_mag:.6f} m/s, v_exp={v_exp:.6f} m/s, rel_err={rel_err:.2e}") print()