1. Apply impulsive burn to `craft->local_velocity`
@ -437,6 +438,23 @@ Energy calculations and orbit tracking for testing.
- If exceeded: reconstruct elements from current state
- This catches numerical drift and ensures consistency
### Exact Position Burn Execution
**Purpose:** True anomaly triggers must execute burns at the exact orbital position, not at the current position when crossing is detected.
**Mechanism:**
1. `check_maneuver_trigger()` calculates `scheduled_dt` (time to reach target anomaly)
2. If crossing will occur within current frame (`scheduled_dt <sim->dt`), trigger fires
3. `execute_pending_maneuvers()` propagates spacecraft by `scheduled_dt` to exact position
4. Burn executes at precise orbital location
5. Remaining frame time (`sim->dt - scheduled_dt`) is propagated after burn
6. Spacecraft marked as handled to skip redundant propagation in `update_spacecraft_physics()`
**Wraparound Handling:**
- Special case for 2π→0 crossing at periapsis
- When current_nu > 5.0 and future_nu <1.0,wraparoundcrossingisdetected
- Prevents false "moving away" rejection near angle boundaries
### 3D Orbital Orientation
**Rotation:** z-x-z Euler angles via `mat3_rotation_orbital(omega, i, Omega)`
@ -492,7 +510,7 @@ Energy calculations and orbit tracking for testing.
The simulation initializes in this sequence: create_simulation() is called first, then load_system_config() parses the TOML file and loads bodies, spacecraft, and maneuvers. Next, run_all_config_validations() performs system-level validation. Then initialize_orbital_objects() converts orbital elements to local position/velocity for all bodies and spacecraft, computes global coordinates, and calculates SOI radii. Finally, the main simulation loop begins.
### Main Simulation Loop
The main simulation loop executes in this order: update_bodies_physics(), compute_global_coordinates(), update_spacecraft_physics(), execute_pending_maneuvers(), compute_spacecraft_globals(), then increments simulation time. Within update_bodies_physics(), for each body: check SOI via find_dominant_body, handle transitions by computing global coordinates from old parent, updating parent_index, computing new local coordinates, and reconstructing orbital elements. Then check velocity deviation with 1e-6 tolerance and reconstruct elements if needed. Propagate elements via propagate_orbital_elements() and update local position/velocity. compute_global_coordinates() updates all body global positions from parent.global + local. update_spacecraft_physics() performs the same velocity deviation check and propagation for spacecraft. execute_pending_maneuvers() checks each unexecuted maneuver for time or true anomaly triggers; if triggered, applies burn to local_velocity, reconstructs orbital elements, and marks executed. compute_spacecraft_globals() updates all spacecraft global positions.
The main simulation loop executes in this order: update_bodies_physics(), compute_global_coordinates(), execute_pending_maneuvers(), update_spacecraft_physics(), compute_spacecraft_globals(), then increments simulation time. Within update_bodies_physics(), for each body: check SOI via find_dominant_body, handle transitions by computing global coordinates from old parent, updating parent_index, computing new local coordinates, and reconstructing orbital elements. Then check velocity deviation with 1e-6 tolerance and reconstruct elements if needed. Propagate elements via propagate_orbital_elements() and update local position/velocity. compute_global_coordinates() updates all body global positions from parent.global + local. execute_pending_maneuvers() checks each unexecuted maneuver for time or true anomaly triggers. For true anomaly triggers: if crossing detected, sets scheduled_dt to time needed to reach target. When triggered, propagates spacecraft by scheduled_dt to exact position, executes burn, propagates remaining frame time, and marks spacecraft as handled to skip in update_spacecraft_physics(). update_spacecraft_physics() propagates spacecraft not already handled this frame. compute_spacecraft_globals() updates all spacecraft global positions.
### SOI Mechanics
SOI transitions are detected by calling find_dominant_body() before each physics update. If the parent changes, the body's global coordinates are computed in the old frame, the parent_index is updated, new local coordinates are computed, and orbital elements are reconstructed. Propagation then uses the new local frame.
@ -514,7 +532,7 @@ SOI transitions are detected by calling find_dominant_body() before each physics