The single-stage simulation flew the mission with one monolithic vehicle — physically wrong. Real launch stacks jettison empty fuel tanks as they climb, because every kilogram of dead weight costs propellant. This brief documents the three-stage Artemis II architecture, the new stage maneuver that was added to make autonomous separation possible, and the cinematic propulsive landing that closes the mission.
Artemis II launches on SLS Block 1 — the most powerful rocket currently flying. The full stack is roughly 98 metres tall and 2,600 tonnes at liftoff. It splits into three independent vehicles during the mission, each engineered for its own job.
Liquid hydrogen / liquid oxygen core driving four RS-25 engines, flanked by two five-segment solid rocket boosters.
Single RL10 engine running LH₂ / LOX. Inherited from the Delta IV upper stage; will give way to the Exploration Upper Stage on later Artemis flights.
Crew module with the four-person crew, mated to the European Service Module and its AJ-10 engine for in-space maneuvers, attitude, and re-entry prep.
Why stage at all? Empty fuel tanks are dead weight. To accelerate the upper stages further you'd need to push those tanks too — costing enormous extra propellant. Drop them, and the smaller lighter remainder reaches the Moon with engines a fraction the size. SLS = 39,000 kN. ICPS = 110 kN (354× smaller). Orion = 26 kN (1,500× smaller than SLS).
The simulator had a hidden limitation: stage separation existed only as a manual UI button —
handleStageRocket()
— with no way to script it into an autonomous flight plan. We fixed that.
The physics engine is pure. It runs in a Web Worker and cannot call React state setters like setBodies. So a new maneuver can't simply spawn debris from inside the engine.
Follow the side-effect approach already used by change_simulation_speed — push a SystemEvent onto the physics result; the main thread processes it after the worker returns.
Maneuver.type union; extended SystemEvent with a stage_rocket variant carrying a rocketId.change_simulation_speed. Emits the system event when the maneuver fires, marks complete in one frame — same model as rotate, sas.stage_rocket events to the existing handleStageRocket() — reusing the debris-creation logic the UI button already used. buildManeuverFromModule received a case 'stage'.MANEUVER_TYPE_OPTIONS.execType === 'stage' — no parameters needed; reads as documentation in-app.<option value="stage"> to both maneuver pickers so users can drop it into flight plans by hand.recordGapAndAction type union so manual flight recordings can also capture user-triggered separations.One handler, two entry points. The same handleStageRocket() now serves both the UI button and the maneuver queue. The debris becomes a separate body, the rocket's mass and fuel recalculate from the remaining stages, and the timestamp guard prevents the worker from overwriting the staged state in-flight.
The preset's shipStructure.stages[] array models all three vehicles. Real-world mass proportions
(Core 97% / ICPS 1.5% / Orion 1.5%) would make the upper stages invisible at the sim's scale,
so we flatten to 60/30/10 — the architecture is faithful even where the numbers aren't.
Carries every burn of the launch and LEO insertion. Jettisoned the moment the parking orbit is clean.
Performs the High Earth Orbit checkout loop and the Trans-Lunar Injection. Spent ICPS is dropped on its way out of Earth's gravity well.
Crew home for ten sim-days. Handles the mid-course correction, the free-return coast, and the propulsive landing back on Earth.
A subtlety the single-stage preset hid: when a stage jettisons, the rocket's mass drops drastically. Same thrust, much smaller mass — by Newton's second law, much higher acceleration. Reuse single-stage burn values and the upper-stage engines overshoot wildly.
| Burn | Active stage | Mass at burn | Tuned thrust |
|---|---|---|---|
| Final kick | Stage 1 | 0.001 | 0.002 |
| HEO insertion | Stage 2 | 0.0004 | 0.0006 — was 0.0015 |
| MCC offset | Stage 3 | 0.0001 | 10⁻⁶ — tiny radial nudge |
| Deorbit prep | Stage 3 | 0.0001 | 0.0001 — was 0.002 |
| Landing brakes | Stage 3 | 0.0001 | 0.0003 — deorbit + suicide |
Rule of thumb. Each time a stage separates, divide the next manual burn's thrust by the mass ratio. The autopilot maneuvers (auto_circularize, auto_transfer) self-correct because they compute their own duration from the current mass — only hand-tuned burn maneuvers need adjustment.
Once Orion is alone in flight and the free-return has brought it back to Earth's vicinity, the sequence switches into a multi-act landing — twelve maneuvers across five distinct beats, scored against the trail renderer's animation.
Speed reset to real-time. SAS locks retrograde. The engine fires for 0.8 sim-seconds and the periapsis drops below Earth's surface. Orion is now committed to landing.
SAS flips to radial_out — the rocket points away from Earth's centre and falls "tower up". wait_for_altitude 25:descending watches the altimeter while gravity does the work.
Simulation drops to 0.5×. SAS retrograde (engine pointing down, rocket facing up) and the second burn kills nearly all descent velocity just above the surface — the SpaceX-style propulsive moment.
SAS radial-out re-engages — the rocket squares up against the local horizon. wait_for_altitude 5:descending waits for the vehicle to drift down to almost-ground level.
Simulation drops further to 0.25×. auto_land fires — a closed-loop velocity-null. The rocket free-falls the final few units and contacts the surface. The landing-angle check passes because radial-out attitude already aligns with the surface normal.
Why slow-motion matters. The simulator runs timeStep = 0.008 with adaptive sub-stepping; at 1× the final five seconds of descent take five seconds — easy to miss. The 1× → 0.5× → 0.25× ramp gives the eye time to read the plume, watch the velocity bar drop, see the rocket settle. Identical physics to 1×, only visually generous.
Phase by phase, the simulation maps onto the real Artemis II mission profile. The places it diverges are documented, not hidden.
| Real Artemis II phase | Sim steps | Active stage |
|---|---|---|
| SLS liftoff & gravity turn | 1–11 · ascent, pitch-over, LEO circularize | Core + SRBs |
| Core stage separation | 12 · stage — Stage 1 becomes orange debris |
— |
| HEO checkout loop | 15–21 · HEO burn, apogee coast, re-circularize | ICPS |
| Trans-Lunar Injection | 22–23 · wait_for_transfer + auto_transfer |
ICPS |
| ICPS separation | 24 · stage — Stage 2 becomes silver debris |
— |
| Mid-course correction | 26–27 · radial nudge for free-return offset | Orion |
| 4-day translunar coast · lunar flyby · return | 28–32 · coast, gravity assist, return cruise | Orion |
| Re-entry preparation | 33–40 · deorbit burn, low-orbit recircularization | Orion |
| Propulsive landing (sim only) | 41–52 · deorbit → free-fall → suicide burn → auto_land | Orion |
Where the sim diverges. Three deliberate departures. One: the real Artemis II splashes down under parachutes; the sim has no atmosphere or chutes, so the descent is propulsive. Two: the real TLI bakes the free-return offset into the burn aim point; we model it as an explicit separate MCC. Three: mass proportions are flatter (60/30/10) instead of the real (97/1.5/1.5), so the upper stages stay visually distinguishable.