workshop private

← all creations

Rendezvous

mechanics · created 2026-09-15

Catch a station in the same orbit as you, with the one control you have — a throttle that is not a speed control but a clock. Burning toward the target reports 86.6% of your impulse as closing speed and then makes you 10.8° later every lap, and the fix everyone quotes ("to catch up, slow down") has a ceiling at 126.17° and stops being the cheap answer at 105.62°.

physicssimulationgame-feelcanvas

You are on a circular orbit. The station is on the same circular orbit, 60° ahead of you, going the same speed, and it has been exactly 60° ahead since before you woke up. You have one control: an engine that points along your velocity, forward or back.

The obvious move is wrong, and — this is the part worth building — the instrument agrees with you while you make it.

The throttle is a clock

Everything here comes out of two lines. Vis-viva,

v² = μ(2/r − 1/a)

and Kepler’s third law, T = 2π√(a³/μ). Differentiate the second: dT/T = (3/2)(da/a). Differentiate the first at fixed r, because an impulse changes your speed where you are and not where you are:

2v dv = μ da/a²        ⇒   da/a = 2 v a dv / μ

On a circular orbit a = r and v² = μ/r, so a/μ = 1/v², and the whole thing collapses:

da/a = 2 dv/v                    dT/T = 3 dv/v

A burn of one percent of circular speed makes your orbit three percent longer. Not faster. Longer. And the period is the only thing that decides whether you arrive: after one of your laps the station has gone round T′/T of a lap, so the gap you close per lap is

Δθ = 2π(1 − T′/T) = −6π·(Δv/v_c)   radians per lap

which is −10.8° per lap for a 1% prograde burn, forever, in the direction you did not want. The exact version — no small-angle anything, just vis-viva rearranged — is in periodRatio:

T′/T = (2 − (1+f)²)^(−3/2),        f = Δv/v_c

and it runs away from the linear one fast, because a blows up at f = √2 − 1 = 0.41421, where the period is infinite and you have left.

Δv / v_cT′/T closed formT′/T measured1 + 3fdrift/lap−6πfother apsis
+0.0051.015231.015231.01500−5.48°−5.40°1.0203
+0.0101.030931.030931.03000−11.13°−10.80°1.0410
+0.0201.063811.063811.06000−22.97°−21.60°1.0842
+0.0501.176111.176111.15000−63.40°−54.00°1.2284
+0.1001.424161.424161.30000−152.70°−108.00°1.5316
−0.0100.970880.970880.97000+10.48°+10.80°0.9610
−0.0500.869750.869750.85000+46.89°+54.00°0.8223
−0.1000.770330.770330.70000+82.68°+108.00°0.6807
−0.2000.630510.630510.40000+133.02°+216.00°0.4706

“Measured” is the period recovered by integrating the orbit and bisecting on the position angle coming back round, so the second column is the algebra and the third is the solar system.

Note the last two columns diverging in opposite directions, because 1 + 3f is an underestimate going up and an overestimate going down. That asymmetry is not a rounding detail — it is the reason for half of the rest of this page.

The instrument, and exactly how convincing it is

Burn toward the station and the range starts falling. It does this for a real reason and the number is exact.

Both of you were on one circular orbit, so the separation was constant and d(range)/dt was exactly zero. All the reading you get afterwards is your own impulse. With the target θ ahead:

Δr = r(1 − cos θ, −sin θ)          Δv⃗ = v(sin θ, 1 − cos θ) + Δv(0, 1)
Δr · Δv⃗ = −r·Δv·sin θ              the v terms cancel, exactly
|Δr|     = 2r sin(θ/2)

range rate = −Δv·sin θ / (2 sin(θ/2)) = −Δv·cos(θ/2)

The range rate reports cos(θ/2) of your burn as closing speed. Nearly all of it for a near target; none of it only at 180°. The instrument is most convincing exactly when the station is closest — which is exactly when you are most tempted to chase it.

leadmeasured range rate−Δv·cos(θ/2)fraction of the burnbelievable for (laps)
10°−0.02989−0.029890.99620.102
30°−0.02898−0.028980.96590.094
60°−0.02598−0.025980.86600.076
90°−0.02121−0.021210.70710.059
120°−0.01500−0.015000.50000.040
150°−0.00776−0.007760.25880.021
179°−0.00026−0.000260.00870.001

The last column is the honest one. A tenth of a lap. The drift it bought you is −6π·Δv/v_c per lap regardless of θ, so the ratio of what the instrument says to what the manoeuvre costs is fixed, and it is terrible.

The same 60° lead, the same 0.03 of Δv, twice, differing only in sign:

burnrange rate at t=0flips atclosest rangeatlead after 1 lapafter 2after 3
prograde +0.03 (toward it)−0.02600.076 laps0.99290.07695.6°131.2°166.7°
retrograde −0.03 (away)+0.02600.783 laps0.00311.78830.3°0.6°−29.1°

The burn that reads as closing never gets within 0.993 of a station it started 1.000 from — it moves the range by seven parts in a thousand and then spends three laps putting the station on the far side of the planet. The burn that reads as opening passes within 0.003 without a second impulse. One number in that table is what the HUD shows; the rest is what happened.

So “to catch up, slow down” — and where it expires

That is the folklore, it is right, and like every good folklore rule it is right over a band and nobody tells you where the band ends. There are two edges, and they are at different places.

Edge one: the ground. The retrograde burn that shortens your period lowers the other side of the orbit. Burning at radius r makes that point your apoapsis, so

r_p = 2a′ − r = r(2(T′/T)^(2/3) − 1)

and to close a lead θ in n revolutions you need T′/T = 1 − θ/(2πn). Setting r_p ≥ R_planet gives a closed form for how impatient you are allowed to be:

θ_max = 2πn·(1 − ((1 + R/r)/2)^(3/2))

With the planet at half the station’s orbital radius, that is 126.17° in one revolution, and the demo’s measured ceiling — bisecting on the periapsis actually dipping under the surface — agrees to two decimals:

revolutions nceiling, closed formmeasuredΔv thereperiapsis there
1126.17°126.17°0.36640.5005
2252.35°252.35°0.36640.5005
3378.5° — past a lapevery lead0.33860.5268
4504.7° — past a lapevery lead0.22360.6513

Past 126°, in one lap, there is no such manoeuvre. Not an expensive one. None.

Edge two, which arrives first: the price. The map from Δv to period ratio is violently asymmetric, and the reason is that a is unbounded above and bounded below. You can make your period infinite for Δv = +0.414 v_c; you would need Δv = −1.000 v_c — your entire orbital velocity — to make it zero. So the same impulse always moves the clock further forward than back: +0.1 buys T′/T = 1.424, −0.1 buys 0.770, and in log terms that is 1.36× more clock for the same fuel.

Which means going the long way round — raising your orbit and letting the station lap you — is often cheaper than chasing it:

leadΔv chasingΔv going highratiocheaper
30°0.06060.32545.37chase
60°0.13370.30862.31chase
90°0.22400.29031.30chase
105.6°0.28010.28021.00
120°0.33910.27030.80go high
150°into the planet (r_p 0.396)0.2484go high
180°into the planet (r_p 0.260)0.2243go high
300°no such orbit0.0954go high

105.62°, not 180°. Twenty degrees before the ground rules chasing out, the price already has. Nobody chose that number either.

And it is not a constant — it is a fact about being in a hurry. Give yourself more revolutions and the crossover walks outward toward the halfway point you expected in the first place:

revolutions ncrossoverΔv either waywait chasingwait high
1105.62°0.28010.71 laps1.71 laps
2137.55°0.15811.622.62
3150.80°0.10842.583.58
4157.85°0.08223.564.56

Patience is the fuel tank

The other thing the closed form says out loud. To close a 90° lead:

revolutions nT′/TΔv each burnΔv totalperiapsistime (target laps)
10.75000−0.11200.22400.65100.75
20.87500−0.04770.09540.82971.75
30.91667−0.03030.06060.88732.75
40.93750−0.02220.04450.91583.75
80.96875−0.01080.02150.95817.75
120.97917−0.00710.01420.972111.75

Sixteen times the fuel to arrive eleven laps sooner. That is the only knob this mechanic has, and it is why the demo’s solver is capped at six revolutions: with unlimited patience the answer to every scenario is “wait longer” and the trade disappears.

Two burns, and the second one is not optional

The whole manoeuvre is: burn once to put your period off by exactly the fraction of a lap you owe, coast n of them, and burn the mirror image at the same point in space. Both burns happen in the same place — that is why the cost is exactly twice one of them, and why the demo draws one ring and labels it “and again in 6 laps.”

Computed up front and flown open-loop through the integrator, with no correction of any kind:

leaddirectionnΔv eachΔv totalrange at arrivalrelative speed
30°down8−0.00350.00702.00e−122.02e−12
75°down8−0.00890.01781.89e−131.57e−13
90°down8−0.01080.02151.23e−121.20e−12
150°down8−0.01830.03664.08e−124.16e−12
210°up8+0.01650.03303.24e−123.22e−12
300°up8+0.00680.01367.88e−137.65e−13

Twelve decimal places, which is the integrator’s noise floor and not the manoeuvre’s. The plan is exact; there is nothing to steer.

The second burn is the one people skip, and the first version of this piece let them. The docking gate was a relative speed of 0.02, and a patient phasing orbit arrives with its relative speed equal to the impulse that set it up — 0.0095 for a six-lap plan — so the craft sailed through the gate still on its transfer ellipse and the demo called it a dock. Correct-looking, and it deleted half the idea. The gate is 0.006 now, and arriving in the right place at the right time with the wrong velocity is the failure it should always have been.

Four beliefs about the throttle

The game layer is thin on purpose: get inside 0.02 of the station at under 0.006 of relative speed, on a Δv budget. Nothing in it knows any of the above. So scripts/measure.mjs flies 17 leads, 20° to 340°, under four autopilots that share one control loop — brake when close, thrust while the gap is open, null the drift when it isn’t — and differ in one line: which way to point.

pilotdockedcrashesmean closest approachmean Δv spentmean laps
“burn toward it”0.0%171.1040.3574.8
“follow the range rate”0.0%01.2840.4508.7
“burn away from it”0.0%80.0990.4084.9
“the phasing solution”100.0%00.0010.0218.0

A twentieth of the fuel and it is the only one that ever arrives.

Three things in that table are worth more than the headline. “Burn toward it” crashes every single time, which looks like a strawman and isn’t: it chases a gap that runs away from it, the gap wraps past 180°, the pilot dutifully reverses, and now it is dumping retrograde into a lower and lower periapsis. The failure mode of the wrong sign is not “arrives late”, it is “flies into the planet while doing exactly what it meant to.”

“Follow the range rate” never crashes and never gets anywhere, burning its entire budget over 8.7 laps. It is the most defensible of the three — it is optimising a real measured quantity, in the direction that quantity says to go — and it is the one that spends everything for nothing.

And “burn away from it” gets the sign right and still docks 0%, at a mean closest approach of 0.099 — five times closer than the others and not once inside 0.02. Knowing which way to point buys you the neighbourhood. It does not buy you the arrival, because closing the phase gap and matching the orbit are two manoeuvres, and folklore only ever contained the first.

What is physics here and what isn’t

Reuse

src/rendezvous.mjs is framework-free with no canvas in it.

The demo is demo/index.html with its own copy of the module (ADR-0002): and (or W/S, or holding the on-screen buttons, or tapping the upper and lower half of the orbit view) to burn, space for warp, H for the closed-form solution, P to swap the phase tape for the cost curve, N for the next setup, R to reset. It sizes itself to its viewport, so the site’s full-screen button just works.

The phase tape is the part that earns its space. It plots lead angle against time, with the station as the zero line and the dashed projection showing where the current orbit is taking you. The trace wobbles — angular velocity varies around an ellipse — and the wobble is precisely why the instantaneous range rate is worthless: the straight dashed line under it is the per-lap drift, which is the only thing that decides anything.

node scripts/measure.mjs regenerates every table above. node scripts/screenshot-demo.mjs regenerates the thumb and media and is the smoke test: 20 assertions, any page error fails the run, and it checks the live demo’s own readouts against the closed forms — that a +0.03 burn at a 60° lead reports exactly −0.025981 as closing speed, that the same burn has moved the lead to 95.58° one lap later, and that the plan the demo offers, flown open-loop through the demo, docks for the Δv the algebra said.