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.
 
 
 
 
 

7.2 KiB

Hohmann Transfer Rendezvous - Burn Timing Quantization Analysis

Session Date

2026-04-19

Problem Statement

The Hohmann transfer rendezvous simulation was failing with ~1.3 km separation despite correct phasing calculations. Investigation revealed two issues:

  1. Burn timing quantization: Time-triggered burns execute at step boundaries, not exact trigger times
  2. cartesian_to_orbital_elements bug: Coplanar orbit omega calculation was incorrect

Root Cause Analysis

1. Burn Timing Quantization

How it works:

  • check_maneuver_trigger() for TRIGGER_TIME uses simple comparison: sim->time >= maneuver->trigger_value
  • Burns execute at the first step where sim->time >= trigger_value
  • No sub-step interpolation for time triggers

Verified behavior (from test_maneuver_timing.cpp):

Trigger Time Step Boundary Actual Execution Delay
t=305.0 t=310.0 t=310.0 5.0s
t=300.0 t=300.0 t=300.0 0.0s
t=62807.0 t=62810.0 t=62810.0 3.0s

Impact on Hohmann transfer:

  • Arrival trigger: t=62804.47 (calculated precisely)
  • Step boundaries: ..., 62800, 62810, ...
  • Actual execution: t=62810 (5.53s late)
  • Position drift: ~5.53s × ~7672 m/s ≈ 42 km of orbital travel

2. cartesian_to_orbital_elements Bug

Location: src/orbital_mechanics.cpp, lines 300-320

Bug: For coplanar orbits (inclination < 0.01 rad), the function was setting omega = 0.0 instead of computing the longitude of periapsis.

Fix:

} else if (e > 1e-10) {
    // Coplanar or near-circular: use longitude of periapsis
    omega = atan2(e_vec.y, e_vec.x);
    if (omega < 0.0) {
        omega += 2.0 * M_PI;
    }
} else {
    omega = 0.0;
}

Impact: Without this fix, Hohmann separation goes from 8.75m → 3.22 million meters.

DT Reduction Results

TIME_STEP Separation Test Result
10.0 s 1,324 m Failed (>100m)
1.0 s 55 m Passed
0.1 s 8.75 m Passed

Key insight: DT reduction dramatically improves accuracy:

  • 24x improvement from 10s→1s
  • 6x more from 1s→0.1s

Test Results Summary

Test Category Before Fix After Fix Status
rendezvous_hohmann (8 cases) 87 passed 107 passed All pass
maneuver_timing (3 cases) N/A 14 passed All pass
omega (2 cases) 1 failed 6 passed All pass
rendezvous (10 cases) 3 failed 3 failed Pre-existing
Total 156/160 pass 157/160 pass +1 fixed

Suggested Fixes for Burn Timing Quantization

Approach: When a burn trigger is detected between steps, propagate to the exact trigger time before executing.

Changes needed:

  1. In check_maneuver_trigger() for TRIGGER_TIME:

    • When sim->time >= trigger_value, calculate dt_to_burn = trigger_value - (sim->time - sim->dt)
    • Set maneuver->scheduled_dt = dt_to_burn
    • Return true
  2. In execute_pending_maneuvers():

    • When dt_to_burn > 0, propagate the spacecraft to the exact burn time
    • Execute the burn
    • Propagate the remaining sim->dt - dt_to_burn

Pros: Exact timing, no analytical drift Cons: More complex, requires careful handling of edge cases

Option B: Snap Trigger Times to Step Boundaries

Approach: In calculate_next_hohmann_wait_time(), snap the calculated wait time to the nearest step boundary.

Changes needed:

  1. In calculate_next_hohmann_wait_time():
    • After calculating wait time, snap to step boundary: wait_time = ceil(wait_time / DT) * DT
    • This ensures the trigger aligns with a simulation step

Pros: Simple, minimal code changes Cons: Introduces systematic timing error, may affect phasing accuracy

Option C: Accept Quantization Error

Approach: Keep current behavior but set realistic thresholds based on DT.

Changes needed:

  1. Calculate expected quantization error: max_error = DT
  2. Set rendezvous threshold proportional to DT: threshold = 100 * DT (meters)
  3. Document the limitation

Pros: Simplest, no code changes Cons: Less accurate, threshold depends on DT choice

Strategy for Testing with Larger Time Steps

Goal

Understand the accuracy limitations of the simulation at realistic DT values (10s, 30s) to set appropriate rendezvous thresholds.

Test Plan

Phase 1: Baseline at Current DT (0.1s)

  • Already done: 8.75m separation at DT=0.1s

Phase 2: Systematic DT Sweep

Run the same Hohmann transfer test at increasing DT values:

DT Expected Steps Expected Separation
0.1s ~628,000 ~8.75 m
0.5s ~125,600 ~40 m (estimate)
1.0s ~62,800 ~55 m
2.0s ~31,400 ~100-200 m (estimate)
5.0s ~12,560 ~500 m (estimate)
10.0s ~6,280 ~1,324 m
30.0s ~2,093 ~4,000 m (estimate)

Method:

  1. Create a new test file tests/test_hohmann_dt_sweep.cpp
  2. Run the same Hohmann transfer scenario at each DT value
  3. Record: final separation, radius error, relative velocity
  4. Plot separation vs DT to determine the relationship

Phase 3: Quantization Impact Analysis

Test the effect of burn timing quantization specifically:

Scenario Trigger Offset Expected Delay
Exact boundary 0s 0s
5s after boundary 5s 5s
9s after boundary 9s 1s

Method:

  1. For each DT, run the Hohmann transfer multiple times with different trigger offsets
  2. Measure the variation in final separation
  3. Determine if quantization error dominates over integration error

Phase 4: Threshold Recommendation

Based on Phase 2 & 3 results, recommend:

  • Maximum DT for rendezvous operations
  • Separation threshold as a function of DT
  • Whether sub-step interpolation is necessary

Implementation Notes

  • Use calculate_next_hohmann_wait_time() with min_wait_time to control trigger timing
  • Keep all other parameters constant (initial conditions, maneuver DVs, etc.)
  • Use WithinAbs() with increasing margins to find the threshold that passes at each DT

Next Session Context

Files Modified

  • src/orbital_mechanics.cpp - Fixed coplanar orbit omega calculation
  • src/rendezvous_hohmann.cpp - Added 3 new functions (validate, relative period, next wait time)
  • src/rendezvous_hohmann.h - Added function declarations
  • src/test_utilities.cpp - Added dump_simulation_state() helper
  • src/test_utilities.h - Added function declaration
  • tests/test_rendezvous_hohmann.cpp - Updated integration test with DT=0.1
  • tests/test_rendezvous_hohmann.toml - Reverted to original values
  • tests/test_omega_debug.cpp - Updated to accept new coplanar omega behavior
  • tests/test_maneuver_timing.cpp - New test file (to be merged into test_maneuver_planning.cpp)

Pre-existing Issues

  • 3 rendezvous test cases failing (CW guidance related) - not related to this fix

Remaining Work

  1. Merge test_maneuver_timing.cpp into test_maneuver_planning.cpp
  2. Implement burn timing quantization fix (Option A recommended)
  3. Run DT sweep tests to understand accuracy limits
  4. Update rendezvous thresholds based on DT analysis