This guide walks you through running your first launch simulation.
The Problem¶
We want to launch a Falcon 9 rocket to a circular orbit at altitude \(h_{target}\) with payload mass \(m_{payload}\).
The challenge: find the optimal control parameters:
- \(\theta_0\): Pitch-over angle after vertical ascent
- \(t_{coast}\): Coast duration between stages
- \(t_{burn2}\): Second stage burn time
- \(\alpha_2\): Second stage steering angle
Running a Simulation¶
Basic Launch¶
uv run apogee-launch --h-target-km 200 --payload-kg 5000
This outputs:
{
"schema_version": 1,
"inputs": {
"h_target_km": 200.0,
"payload_kg": 5000.0
},
"optimal_numerics": {
"theta0_rad": 0.1547,
"t_coast_s": 5.28,
"t_burn2_s": 351.42,
"alpha2_rad": 0.1132
},
"summary": {
"ecc": 0.000498,
"h_err_m": -1644.6,
"v_err_mps": 1.83,
"gamma_deg": -0.026
}
}
Understanding the Output¶
| Field | Meaning | Good Value |
|---|---|---|
ecc |
Orbital eccentricity | < 0.001 (circular) |
h_err_m |
Altitude error from target | < 2000 m |
v_err_mps |
Velocity error | < 5 m/s |
gamma_deg |
Flight-path angle at insertion | ~0° (horizontal) |
Circular Orbit Achieved
Eccentricity of 0.0005 means the orbit is nearly perfectly circular!
With Trajectory Data¶
To get the full flight path:
uv run apogee-launch --h-target-km 200 --payload-kg 5000 > result.json
The trajectory includes time series for:
t_s: Time [s]h_m: Altitude [m]v_mps: Velocity [m/s]gamma_rad: Flight-path angle [rad]m_kg: Mass [kg]pos_m: 3D position{x, y, z}
Generate Plots¶
uv run apogee-launch --h-target-km 200 --payload-kg 5000 --plot
This creates visualization plots in the plots/ directory:
trajectory.png- 2D trajectory with Earthtime.png- Time series plotscomprehensive.png- 6-panel overview
Python API¶
from apogee_launch import solve_to_circular_orbit
result = solve_to_circular_orbit(
h_target_km=200,
payload_kg=5000,
include_trajectory=True,
)
# Access results
print(f"Eccentricity: {result.summary['ecc']:.6f}")
print(f"Coast time: {result.optimal_numerics['t_coast_s']:.1f} s")
# Plot trajectory
import matplotlib.pyplot as plt
traj = result.trajectory
plt.plot(traj['t_s'], [h/1000 for h in traj['h_m']])
plt.xlabel('Time [s]')
plt.ylabel('Altitude [km]')
plt.show()
Varying Parameters¶
Different Altitudes¶
# Low orbit (ISS altitude)
uv run apogee-launch --h-target-km 400 --payload-kg 5000
# Minimum insertion altitude
uv run apogee-launch --h-target-km 160 --payload-kg 5000
Payload Sweep¶
from apogee_launch import solve_to_circular_orbit
for payload in [0, 2500, 5000, 7500, 10000]:
result = solve_to_circular_orbit(h_target_km=200, payload_kg=payload)
print(f"Payload: {payload} kg, ecc: {result.summary['ecc']:.4f}")
What's Happening Inside?¶
The simulator performs these steps:
- Vertical Ascent - Rocket climbs until pitchover altitude
- Pitchover - Instantaneous tilt by \(\theta_0\) degrees
- Gravity Turn - Stage 1 burns with thrust along velocity
- Stage Separation - Drop stage 1 dry mass
- Coast - Ballistic flight for \(t_{coast}\) seconds
- Stage 2 Burn - Burn at steering angle \(\alpha_2\)
- Orbit Insertion - Achieve target circular orbit
The shooting method iteratively adjusts the control parameters until the orbit is circular.
Next Steps¶
- Theory → State Vector - Mathematical foundations
- Numerical Methods - How the solver works
- Package Reference - API documentation