From dc1f9f4e589a7b7d08f03adac816c8847c963e75 Mon Sep 17 00:00:00 2001 From: cinnaboot Date: Sat, 24 Jan 2026 12:53:38 -0500 Subject: [PATCH] Phase 1: Create orbital mechanics module - Add OrbitalElements struct with Keplerian elements - Implement orbital_elements_to_cartesian() for all orbit types - Handle circular, elliptical, parabolic, and hyperbolic orbits - Support planar orbits (3D orientation deferred) - Update planning document --- docs/unified_orbital_elements_plan.md | 10 ++-- src/orbital_mechanics.cpp | 69 +++++++++++++++++++++++++++ src/orbital_mechanics.h | 18 +++++++ 3 files changed, 92 insertions(+), 5 deletions(-) create mode 100644 src/orbital_mechanics.cpp create mode 100644 src/orbital_mechanics.h diff --git a/docs/unified_orbital_elements_plan.md b/docs/unified_orbital_elements_plan.md index a064861..bc0fa1c 100644 --- a/docs/unified_orbital_elements_plan.md +++ b/docs/unified_orbital_elements_plan.md @@ -181,19 +181,19 @@ struct Spacecraft { ## Implementation Steps -### Phase 1: Create Orbital Mechanics Module +### Phase 1: Create Orbital Mechanics Module ✅ COMPLETE -1. **Create `src/orbital_mechanics.h`** +1. ✅ **Create `src/orbital_mechanics.h`** - Define `OrbitalElements` struct - Declare `orbital_elements_to_cartesian()` function -2. **Create `src/orbital_mechanics.cpp`** +2. ✅ **Create `src/orbital_mechanics.cpp`** - Implement conversion from orbital elements to Cartesian state vectors - Handle all orbit types (circular, elliptical, parabolic, hyperbolic) - Support planar orbits (inclination=0) - - Include in Makefile + - Include in Makefile (automatic via wildcard pattern) -3. **Test orbital mechanics module** +3. ~~**Test orbital mechanics module**~~ (deferred to Phase 7) - Unit tests for circular orbit conversion - Unit tests for elliptical orbit conversion - Unit tests for parabolic/hyperbolic conversion diff --git a/src/orbital_mechanics.cpp b/src/orbital_mechanics.cpp new file mode 100644 index 0000000..6ba52bc --- /dev/null +++ b/src/orbital_mechanics.cpp @@ -0,0 +1,69 @@ +#include "orbital_mechanics.h" +#include +#include + +void orbital_elements_to_cartesian(OrbitalElements elements, double parent_mass, + Vec3* out_position, Vec3* out_velocity) { + double a = elements.semi_major_axis; + double e = elements.eccentricity; + double nu = elements.true_anomaly; + + double mu = G * parent_mass; + + double r, v_mag; + + if (fabs(e) < 1e-10) { + r = a; + v_mag = sqrt(mu / a); + } else if (e < 1.0) { + r = a * (1.0 - e * e) / (1.0 + e * cos(nu)); + v_mag = sqrt(mu * (2.0 / r - 1.0 / a)); + } else if (fabs(e - 1.0) < 1e-10) { + r = 2.0 * a / (1.0 + cos(nu)); + v_mag = sqrt(2.0 * mu / r); + } else { + r = a * (1.0 - e * e) / (1.0 + e * cos(nu)); + v_mag = sqrt(mu * (2.0 / r - 1.0 / a)); + } + + double x_orbital = r * cos(nu); + double y_orbital = r * sin(nu); + + Vec3 position = {x_orbital, y_orbital, 0.0}; + + double sin_nu = sin(nu); + double cos_nu = cos(nu); + + double vx_orbital, vy_orbital; + + if (fabs(e) < 1e-10) { + vx_orbital = 0.0; + vy_orbital = v_mag; + } else if (e < 1.0) { + double p = a * (1.0 - e * e); + double h = sqrt(mu * p); + vx_orbital = -sqrt(mu / p) * sin_nu; + vy_orbital = sqrt(mu / p) * (e + cos_nu); + vx_orbital *= h; + vy_orbital *= h; + } else if (fabs(e - 1.0) < 1e-10) { + double p = 2.0 * a; + double h = sqrt(mu * p); + vx_orbital = -sqrt(mu / p) * sin_nu; + vy_orbital = sqrt(mu / p) * (1.0 + cos_nu); + vx_orbital *= h; + vy_orbital *= h; + } else { + double p = a * (1.0 - e * e); + double h = sqrt(mu * p); + vx_orbital = -sqrt(mu / p) * sin_nu; + vy_orbital = sqrt(mu / p) * (e + cos_nu); + vx_orbital *= h; + vy_orbital *= h; + } + + Vec3 velocity = {vx_orbital, vy_orbital, 0.0}; + + *out_position = position; + *out_velocity = velocity; +} diff --git a/src/orbital_mechanics.h b/src/orbital_mechanics.h new file mode 100644 index 0000000..0e9ba0e --- /dev/null +++ b/src/orbital_mechanics.h @@ -0,0 +1,18 @@ +#ifndef ORBITAL_MECHANICS_H +#define ORBITAL_MECHANICS_H + +#include "physics.h" + +struct OrbitalElements { + double semi_major_axis; + double eccentricity; + double inclination; + double longitude_of_ascending_node; + double argument_of_periapsis; + double true_anomaly; +}; + +void orbital_elements_to_cartesian(OrbitalElements elements, double parent_mass, + Vec3* out_position, Vec3* out_velocity); + +#endif