# Orbital Mechanics Simulation - Conceptual Reference ## Overview N-body orbital mechanics simulator using **analytical propagation** for precise Keplerian trajectories. Supports elliptical, parabolic, and hyperbolic orbits with dynamic Sphere of Influence (SOI) transitions, impulsive burns, and 3D visualization via Raylib. ## Architecture Modular C-style C++ (structs/functions, no classes). Module dependencies: ``` Main → Simulation → Orbital Mechanics → Physics → Maneuver → Config Loader ``` Renderer and UI Renderer depend on Config Loader for display data. Test Utilities are standalone. ## Coordinate Frame System **Local Frame**: Position/velocity relative to parent body. Primary system for orbital mechanics calculations. Maintains double-precision accuracy for small orbits (LEO, lunar). **Global Frame**: Position/velocity from simulation origin (Sun at 0,0,0). Computed as `global = parent.global + local`. Used for SOI distance calculations and rendering. **Conversion**: Simple vector addition/subtraction. All bodies and spacecraft store both local and global coordinates. ## Core Data Structures ### Vec3 3D vector (x, y, z). Operations: add, sub, cross, scale, magnitude, distance, normalize, dot. ### Mat3 3x3 row-major matrix. Used for orbital plane rotations (z-x-z Euler angles). ### OrbitalElements Keplerian elements with union for parabolic/hyperbolic distinction: ```cpp struct OrbitalElements { union { double semi_major_axis; // elliptical (e<1), hyperbolic (e>1) double semi_latus_rectum; // parabolic (e≈1) }; double eccentricity; double true_anomaly; double inclination; double longitude_of_ascending_node; double argument_of_periapsis; }; ``` ### CelestialBody Planet/moon with mass, radius, parent_index, color, orbital elements, local/global coordinates, SOI radius. ### Spacecraft Similar to CelestialBody but without radius or SOI. Supports standalone (parent_index = -1) and orbiting spacecraft. ### Maneuver Impulsive burn: name, craft_index, direction, delta_v, trigger_type, trigger_value, scheduled_dt, executed flag, executed_time. ### SimulationState Top-level container: arrays of bodies/spacecraft/maneuvers (with counts and capacities), time, dt, config_name. ## Orbital Propagation Algorithm Analytical propagation solves Kepler's equations exactly (no integration error, perfect energy conservation). **Common Pattern**: 1. Compute mean motion: n = √(μ/|a|³) 2. Convert true anomaly to appropriate anomaly form 3. Advance mean anomaly: M_new = M + n·dt 4. Solve Kepler's equation for new anomaly 5. Convert back to true anomaly 6. Update elements **Elliptical (e < 1)**: Newton-Raphson on E - e·sin(E) = M. Tolerance: 1e-10, max 50 iterations. **Parabolic (|e-1| < PARABOLIC_TOLERANCE)**: Barker's equation D + D³/3 = M with closed-form solution using cubic roots. Mean motion: n = √(μ/p³) where p = semi_latus_rectum. **Hyperbolic (e > 1)**: Newton-Raphson on H - e·sinh(H) = M. Mean motion: n = √(μ/(-a)³) using negative semi-major axis. Initial guess: H = log(2M/e) when e·sinh(M) > M, else H = M. ## Orbital Element Reconstruction Elements are dynamically maintained and reconstructed from Cartesian state when: - **SOI transitions**: Parent changes, local coordinates update - **Burns**: Velocity changes impulsively - **Velocity drift**: |v_local - v_expected| > 1e-6 m/s before propagation Reconstruction uses `cartesian_to_orbital_elements()` which handles edge cases (near-circular e < 1e-10, near-parabolic). ## Coordinate Transformations Orbital plane orientation via z-x-z Euler rotation: ``` R_total = R_z(Ω) · R_x(i) · R_z(ω) ``` Sequence: argument_of_periapsis (ω) → inclination (i) → longitude_of_ascending_node (Ω). **Forward**: `orbital_elements_to_cartesian()` applies rotation. **Reverse**: `cartesian_to_orbital_elements()` computes angles from angular momentum and eccentricity vectors. ## Sphere of Influence Mechanics **SOI Radius**: Hill sphere approximation r_soi = a × (m/M)^(2/5). **SOI Transitions**: 1. `find_dominant_body()` called before each physics update 2. For non-root bodies: stay if distance < parent.soi_radius, else switch to root 3. For root bodies: find closest body where distance < body.soi_radius 4. On parent change: - Compute global position/velocity from old parent - Update parent_index - Compute new local coordinates - Reconstruct orbital elements **SOI in Loop**: Checked for all bodies and spacecraft before physics propagation. ## Maneuver System ### Burn Directions - BURN_PROGRADE: normalized velocity vector - BURN_RETROGRADE: opposite velocity - BURN_NORMAL: normalized (position × velocity) - BURN_ANTINORMAL: opposite normal - BURN_RADIAL_IN: -normalized position - BURN_RADIAL_OUT: normalized position - BURN_CUSTOM: user-specified vector ### Exact Position Execution True anomaly triggers must execute at precise orbital position: 1. `check_maneuver_trigger()` calculates scheduled_dt to target anomaly (triggers when angular distance < 0.01 rad) 2. If scheduled_dt < sim->dt, trigger fires 3. Propagate spacecraft by scheduled_dt to exact position 4. Execute burn (apply delta-v, reconstruct elements) 5. Propagate remaining time (sim->dt - scheduled_dt) 6. Mark spacecraft as handled to skip in update_spacecraft_physics() **Wraparound handling**: When current_nu > 5.0 and future_nu < 1.0, detect 2π→0 crossing at periapsis. ## Simulation Loop **Initialization**: 1. create_simulation() 2. load_system_config() - parse TOML 3. run_all_config_validations() 4. initialize_orbital_objects() - convert elements to Cartesian, compute globals, calculate SOI 5. Main loop begins **Main Loop Order**: 1. update_bodies_physics() - SOI checks, drift detection, propagation 2. compute_global_coordinates() 3. execute_pending_maneuvers() 4. update_spacecraft_physics() 5. compute_spacecraft_globals() 6. time += dt **Body Physics Per-Frame**: - Check SOI via find_dominant_body() - Handle transitions (compute global, update parent, compute local, reconstruct elements) - Check velocity drift (> 1e-6 m/s) and reconstruct if needed - Propagate via propagate_orbital_elements() - Update local position/velocity ## Orbit Types **Elliptical (e < 1)**: ε < 0, bound periodic motion. a = -μ/(2ε) > 0. **Parabolic (|e-1| < tolerance)**: ε ≈ 0, escape trajectory. p = h²/μ. **Hyperbolic (e > 1)**: ε > 0, unbound. a = -μ/(2ε) < 0. All satisfy vis-viva: v² = μ(2/r - 1/a). ## Configuration **TOML Format**: [[bodies]], [[spacecraft]], [[maneuvers]] arrays. **Validation Rules**: - Parent index ordering (parents before children) - Orbital element consistency (e ≥ 0, parabolic p > 0, etc.) - True anomaly ranges for hyperbolic orbits - Mass ratios (MIN_MASS_RATIO = 1000.0 for large-radius bodies) - SOI overlap (siblings must not overlap) - Nested orbits (grandchild semi-major axis ≤ 5× parent SOI) - Initial positions (no overlap with parent) ## Testing Utilities **OrbitalMetrics**: kinetic_energy, potential_energy, total_energy, orbital_radius, velocity_magnitude, angular_position. **OrbitTracker**: Tracks orbit completion via quadrant transitions and total rotation. 3D mode uses orbital elements for inclined orbits. **Energy Functions**: - KE = 0.5 × m × v² - PE = -G × m1 × m2 / r (min distance clamped to 1.0) - Total = ΣKE + ΣPE_pairs ## Visualization **Renderer (Raylib)**: - XY simulation plane → XZ render plane (90° rotation around X) - Scale: 1e-9 (1 unit = 1 billion meters) - Relative rendering when body selected - Orbit paths with appropriate segment counts - Wireframe spheres, child indicators **UI Renderer (raygui)**: - Bottom-left: Sim time, body count, FPS, controls, config - Top-left: Objects list with selection - Top-right: Selected object details - Below info: Maneuver list ## Build System **Targets**: make, make all, make raylib, make run, make test, make test-build, make clean, make rebuild. **Dependencies**: g++ (C++14), raylib (git submodule), raygui (header-only), tomlc17, Catch2 (tests only). **Testing**: ```bash make test # Run all tests ./orbit_test '[config_name]' # Run specific config ./orbit_test -s '[config]' # With debug output ``` Use `WithinAbs(expected, tolerance)` for floating-point comparisons (NOT `Approx()`). ## Hybrid Documentation Strategy This document provides high-level concepts and architecture. Per-module summary files (`src/*.summary.md`) contain detailed function documentation including signatures, parameters, formulas, and edge cases. Use both: this for the big picture, summaries for implementation details.