Earth-Moon Free-Return Trajectory¶
In this example we'll design and fly an Earth-Moon free-return trajectory: a path that departs a low Earth parking orbit, coasts out to the Moon, swings around its far side, and lets lunar gravity bend it back onto an Earth-return leg without any dedicated return burn. This is the trajectory class that gave the early Apollo missions their abort safety margin - if the service propulsion system had failed on the way out, the spacecraft would still have looped around the Moon and returned to a survivable re-entry. Apollo 13's abort after its oxygen tank ruptured depended on exactly this property. Artemis I did not fly a strict free return; Artemis II, the first crewed Artemis flight, does.
We'll use the NumericalOrbitPropagator integrated about the Earth-Moon barycenter (the EMBI frame) with a 5x5 Earth spherical-harmonic field plus Moon and Sun third-body perturbations, target the translunar injection (TLI) delta-v with a bisection search, and apply the burn with a TimeEvent callback. A terminal ValueEvent on geodetic altitude stops the flight at the atmospheric entry interface on the way home. Finally we'll visualize the result in the Earth-Moon Rotating (EMR) frame, where the trajectory traces its characteristic figure-8.
What "Free Return" Means¶
A free-return trajectory is a solution of the Earth-Moon-spacecraft three-body problem whose outbound leg is aimed so that the lunar flyby rotates the velocity vector back toward Earth. No propulsion is needed after the initial injection: the Moon's gravity does the work of turning the spacecraft around. The defining property is passive safety - once on the trajectory, the spacecraft returns to Earth's vicinity on its own.
Geometry¶
The departure geometry fixes everything about the transfer except its energy. We depart a 400 km (ISS-like) circular parking orbit from a point near the antipode of the Moon's position at the expected arrival time, burning prograde in the Moon's instantaneous orbital plane so the transfer apogee reaches toward the Moon roughly half an orbit later.
A real mission targets a two-dimensional B-plane at the Moon (a miss distance and an approach angle). Here AIM_OFFSET_DEG is a simplified stand-in for that second dimension: rotating the departure point ahead of the pure antipode about the orbit normal sets up a flyby that swings around the far side of the Moon rather than passing in front of it. We use spk_state to query the Moon's Earth-relative state from the DE440s ephemeris and build an orthonormal departure frame from it. Because the mission is integrated about the Earth-Moon barycenter, the departure state is translated from ECI into the EMBI frame with state_eci_to_emb.
With the standard preamble in place, the next step sets up the departure geometry.
Force Model¶
A free return is shaped by three bodies. We integrate about the Earth-Moon barycenter, so the central gravity term is zero - the barycenter has no mass of its own. Earth carries a 5x5 spherical-harmonic field as an attributed third body (evaluated at the spacecraft's Earth-relative position), and the Moon and Sun are point-mass perturbers from the DE440s ephemeris. This is the EMB-centered force-model pattern used for cislunar propagation: the integration state stays barycentric while Earth-fidelity gravity still acts near perigee. The lunar term is what bends the trajectory home; the Sun is a smaller but non-negligible perturbation accumulated over the multi-day flight.
Targeting the TLI Delta-V¶
This example's purpose is showing the Earth-Moon rotating frame, so we take some shortcuts to generate the trajectory - a fixed departure geometry and a one-dimensional bisection on the TLI delta-v - which in practice should not be done. Real mission design uses Lambert solvers and B-plane targeting.
With the departure geometry fixed, the only free parameter is the TLI delta-v, which sets the transfer's energy. The miss distance at the Moon is a V-shaped function of that delta-v: too little energy and the transfer apogee never reaches lunar distance, too much and the spacecraft races out ahead of the Moon. The free-return solutions live on the ascending branch of the V, where the perilune radius grows with delta-v. We run a coarse scan to reveal the V and locate its minimum, then bracket the target perilune on the ascending branch and refine the delta-v with a bisection.
The same builder that scores a candidate during targeting flies the final mission, so the trajectory the search converges on is exactly the one flown.
Why a coarse scan first?
A naive bisection on delta-v cannot converge here: the miss distance is not monotonic, so a bracket chosen blindly may straddle the bottom of the V, and the descending branch reaches the same perilune values without ever returning to Earth. The coarse scan finds the V's minimum so the bisection can be restricted to the ascending branch, where perilune increases monotonically with delta-v and the free-return solution for this geometry lives. The final propagation, terminated by the entry event, is what actually confirms the Earth return.
Flying the Mission¶
We fly the tuned design as it would be flown. The propagator starts in the parking orbit, coasts one short arc, and applies the TLI impulsively through a TimeEvent callback. Because the integration state is barycentric, the burn is applied along the spacecraft's Earth-relative velocity - the state is translated to ECI, the delta-v is added, and it is translated back. The flight is stopped by a terminal ValueEvent on geodetic altitude, triggered on decreasing altitude at 120 km - the atmospheric entry interface where a real capsule would begin re-entry. A plain AltitudeEvent would measure altitude above the barycenter rather than the Earth, so the custom value function translates the barycentric state to ECI before computing altitude. The flight time to that point falls out of the propagation rather than being prescribed.
Event geometry follows the integration center, not Earth
Because the state is integrated about the Earth-Moon barycenter, any detector or maneuver that assumes an Earth-centered state is wrong by the Earth-barycenter offset (thousands of kilometers). A plain AltitudeEvent measures altitude above the barycenter, and an impulsive burn added to the raw integration velocity would be along the barycentric velocity - so both must translate to ECI first. This example's terminal entry cutoff uses a custom ValueEvent that re-centers on Earth before computing geodetic altitude.
Distance History¶
Sampling the recorded trajectory gives the distance from Earth and from the Moon over the whole flight. The Earth distance climbs to nearly lunar distance and returns to the entry interface; the Moon distance dips sharply at the flyby. The final epoch is appended to the sample times so the re-entry point itself is captured.
The Moon-distance curve reaches its minimum - the perilune - a little over three days after departure, and the Earth-distance curve turns over shortly after, marking the moment the lunar flyby has bent the trajectory back toward home. The spacecraft reaches the entry interface after about six and a half days.
Figure-8 in the Rotating Frame¶
In an inertial frame the free-return path is an unremarkable elongated loop. Its structure only becomes visible in the Earth-Moon Rotating (EMR) frame, which co-rotates with the Earth-Moon line so the Moon sits fixed on one axis. In that frame the outbound leg, the far-side lunar swing-by, and the return leg trace the characteristic figure-8 that is the signature of a free-return trajectory - the outbound and return legs cross near Earth. We build two views: a 3D view around the textured Earth and Moon, and a top-down (X-Y) view with the bodies drawn to scale. The top-down view carries direction-of-travel arrows along the path, and the fixed body spheres are placed at the perilune epoch so the swing-by aligns with the Moon.
The top-down view makes the figure-8 unmistakable: the outbound leg swings around the far side of the Moon and the return leg crosses it near Earth, closing the loop.
Body textures: Solar System Scope, CC BY 4.0.
Full Code Example¶
Full Code
| earth_moon_free_return.py | |
|---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 | |
See Also¶
- LRO Lunar Orbit - Propagating a Moon-centered orbit with the lunar force model
- Numerical Orbit Propagation - Propagator fundamentals
- Event Detection - Time, altitude, and value event detectors
- Force Models - Configuring third-body perturbations
- Synodic Frame Plots - Visualizing trajectories in rotating frames