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.
135 lines
4.6 KiB
135 lines
4.6 KiB
#!/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()
|
|
|