vibe coding an orbital mechanics simulation to try out claude code
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.
 
 
 
 
 

5.1 KiB

Parabolic Orbit Union Implementation Plan

Overview

Add support for parabolic orbits (e≈1.0) using semi-latus rectum parameter p instead of the current hacky semi_major_axis = 1.0e30 infinity approximation.

Problem

Current implementation uses semi_major_axis = 1.0e30 to approximate infinity for parabolic orbits, causing:

  1. Numerical precision issues with extremely large distances (~6.68e18 AU)
  2. Velocities approaching zero (1.6e-08 km/s instead of ~42 km/s escape velocity)
  3. Test failures due to floating-point equality (final_distance ≈ initial_distance)

Solution

Use a union in OrbitalElements struct to support both semi_major_axis (for elliptical/hyperbolic) and semi_latus_rectum (for parabolic).

Mathematical Background

For parabolic orbits (e=1.0), the semi-major axis is theoretically infinity. Using semi-latus rectum p is mathematically correct:

Position: r = p / (1 + cos(ν)) Velocity: v = √(2μ / r)

Where:

  • p = semi-latus rectum
  • ν = true anomaly
  • μ = GM (gravitational parameter)

For parabolic orbits: p = 2q where q is perihelion distance

Implementation Steps

Phase 1: Update OrbitalElements Struct

File: src/orbital_mechanics.h

struct OrbitalElements {
    union {
        double semi_major_axis;       // for elliptical (e<1) and hyperbolic (e>1)
        double semi_latus_rectum;     // for parabolic (e≈1)
    };
    double eccentricity;
    double true_anomaly;
    double inclination;
    double longitude_of_ascending_node;
    double argument_of_periapsis;
};

Phase 2: Update Config Loader

File: src/config_loader.cpp

Add to parse_toml_body() and parse_toml_spacecraft():

  1. Parse both semi_major_axis and semi_latus_rectum from orbit table
  2. Initialize union field based on which is specified
  3. Validate exactly one is present per eccentricity range

Validation Logic:

bool has_semi_major = (semi_major.type == TOML_FP64);
bool has_semi_latus = (semi_latus.type == TOML_FP64);

if (fabs(elements.eccentricity - 1.0) < 0.005) {
    // Parabolic orbit - requires semi_latus_rectum
    if (!has_semi_latus) {
        printf("Error: Parabolic orbit requires 'semi_latus_rectum'\n");
        return false;
    }
    if (has_semi_major) {
        printf("Error: Parabolic orbit cannot have 'semi_major_axis'\n");
        return false;
    }
    elements.semi_latus_rectum = semi_latus.u.fp64;
} else {
    // Elliptical or hyperbolic - requires semi_major_axis
    if (!has_semi_major) {
        printf("Error: Elliptical/hyperbolic orbit requires 'semi_major_axis'\n");
        return false;
    }
    if (has_semi_latus) {
        printf("Error: Elliptical/hyperbolic orbit cannot have 'semi_latus_rectum'\n");
        return false;
    }
    elements.semi_major_axis = semi_major.u.fp64;
}

Phase 3: Update orbital_mechanics.cpp

File: src/orbital_mechanics.cpp

Update parabolic case (line 21-23):

} else if (fabs(e - 1.0) < 0.005) {
    double p = elements.semi_latus_rectum;
    r = p / (1.0 + cos(nu));
    v_mag = sqrt(2.0 * mu / r);
}

Remove the 2.0 * a approximation that requires a=1.0e30.

Phase 4: Update Test Configs

File: tests/configs/parabolic_comet.toml

Replace semi_major_axis = 1.0e30 with semi_latus_rectum = 1.496e11 (p = 1 AU):

[[bodies]]
name = "ParabolicComet"
mass = 1.0e14
radius = 5.0e3
parent_index = 0
color = { r = 0.7, g = 0.8, b = 0.9 }
orbit = {
    semi_latus_rectum = 1.496e11,
    eccentricity = 1.0,
    true_anomaly = 0.0
}

Phase 5: Update Documentation

File: docs/technical_reference.md

  1. Update OrbitalElements struct documentation to show union
  2. Add note about semi_latus_rectum being required for parabolic orbits (e≈1.0)
  3. Document semi_latus_rectum in config format section

File: docs/unified_orbital_elements_plan.md

Mark union implementation as complete in Phase 7 status.

Validation Steps

  1. Build: make clean && make
  2. Run parabolic test: ./orbit_test '[parabolic]'
  3. Verify velocity is correct: should be ~42,127 m/s escape velocity at 1 AU
  4. Verify energy is ~0 (parabolic orbits have total energy = 0)

Decisions Made

Default Behavior

No backward compatibility for semi_major_axis on parabolic orbits - require explicit semi_latus_rectum for all parabolic configs. This is cleaner than trying to auto-convert p = 2*a.

Spacecraft Altitude Parameter

Spacecraft altitude parameter is not supported for parabolic orbits in this implementation. If user specifies altitude with eccentricity ≈ 1.0, the config loader will require semi_latus_rectum instead and reject altitude or semi_major_axis. Added to future todos for Phase 8+.

Parabolic Detection Tolerance

Using |e - 1.0| < 0.005 as threshold for detecting parabolic orbits. This matches tolerance used elsewhere in the codebase.

Future Enhancements (TODO)

  • Spacecraft altitude parameter for parabolic orbits: parse altitude and convert to semi_latus_rectum = parent_radius + altitude when eccentricity is parabolic
  • Consider adding explicit perihelion parameter to config file, then derive semi_latus_rectum = 2 * perihelion for parabolic orbits