7. Space Travel#

It may seem odd to place this chapter at the end of the first part of this book, considering that we’re talking about space infrastructure. However, it speaks to the framing I wanted to achieve: orbital ring systems make life here on Earth better in substantial ways that would be difficult or impossible to achieve by other means. The fact that we – as you’ll see – get extremely cheap space travel is a nice side-effect, not the goal.

7.1. Why Is Space Expensive Now?#

Let’s say you want to launch a Crew Dragon – SpaceX’s astronaut and cargo delivery vehicle – to the International Space Station, in a circular orbit around 400km. Fully laden, that weighs somewhere between 12 and 13 tonnes; let’s go with 12 tonnes to keep our estimates on the low side.

Crew Dragon is currently launched on the Falcon 9 rocket, which consists of two stages. The first stage lifts the spacecraft and the second stage up to an altitude of 75-80km and a velocity of around 1700 m/s. The first stage then shuts itself down, separates from the rest of the craft, and lands itself for reuse. The second stage takes over, getting up to an altitude of about 200km and approximately 7500 m/s before shutting down and separating, to burn up in the atmosphere. Finally, the Crew Dragon coasts up to the final altititude and does a few small burns using its onboard engines to align its orbit with the ISS and dock.

To return, it jettisons dead weight, performs a small burn to set itself up for reentry, then uses a heavy-duty heat shield to slow itself down (aerobraking) and protect itself from the massive heat generated.

Assuming the first stage is successfully recovered – something SpaceX has gotten very good at – and has minimal cost to refurbish for reuse, there are two expendable components: the second stage and fuel. While recovering the second stage (assuming it didn’t cost you too much fuel, which is why they currently don’t do so) would be advantageous for costs, the fuel is the dominating factor in all of this, and the reason why space is expensive: you need to lift your fuel.

For that 12 tonne craft, how much fuel do we need? 10 tonnes? 100? 200? 475 tonnes! With average prices for the RP-1 (high-grade kerosene) and LOX (liquid oxygen) used by the Falcon 9 rocket, this comes to almost exactly $400,000. That is the absolute minimum cost, ignoring that we’re discarding the second stage, ignoring the fuel used by the spacecraft itself, and ignoring the cost for facilities, refurbishment, labor, etc.

Every kilogram we add to the payload, we need more fuel, which needs more fuel to lift that. This is captured in the Tsiolkovsky rocket equation:

\[\Delta v = v_e \ln \frac{m_i}{m_f} = I_{sp} \cdot g_0 \cdot \ln \frac{m_i}{m_f}\]

I won’t break this down in detail, but there are four very important pieces here:

  • \(I_{sp}\): The specific impulse of the engines (a measure of their efficiency)

  • \({m_i}\): The initial mass of the vehicle, including fuel – aka wet mass

  • \({m_f}\): The final mass of the vehicle after fuel is expended – aka dry mass

  • \(\Delta v\): The resulting change in velocity

As the \(\Delta v\) or dry mass of the vehicle go up, the more fuel you need – exponentially. It takes roughly 9500-10000 m/s of \(\Delta v\) to get to ISS; that factor only really changes depending on your exact flight profile. So the factor you can control is your dry mass: keeping the craft as light as possible to minimize the fuel usage.

7.2. How Do Orbital Rings Help?#

Instead of using a rocket, we can run a maglev (magnetic levitation) track around the circumference of our ring. Crafts would be held by a “train” and accelerate around the planet until they reach their desired release speed. Because the turning radius is so large – larger than the radius of Earth – such craft would experience low G forces and could be released at any point along the ring, in order to achieve the correct trajectory.

Such craft would – unless hitting very specific target orbits – need to carry their own propellant and engines for final maneuvers; however, this is minimal compared to that of launching from the ground.

In this interactive widget, you can see just how much savings could be achieved. Bear in mind that the calculations for dry mass are highly approximate, particularly when it comes to the structural elements.

Hide code cell source
from IPython.display import display, HTML
display(HTML('''
<style>
.hidden {
    display: none;
}
</style>
<div>
    Target: <select id="target-orbit">
        <option value="earth" selected>Earth</option>
        <option value="moon">Moon</option>
        <option value="mars-best">Mars (Best Case)</option>
        <!--<option value="mars-worst">Mars (Worst Case)</option>-->
    </select><br>
    Engine: <select id="engine">
        <option value="merlin" selected>Merlin 1D Vacuum (Falcon)</option>
        <option value="raptor">Raptor Vacuum (Starship)</option>
    </select><br>
    Orbital altitude: <input type="range" min="100" max="50000" step="1" value="400" id="altitude"> <span id="altitude-label"></span> km<br>
    Payload mass: <input type="range" min="1" max="500" step="1" value="12" id="payload"> <span id="payload-label"></span> tonnes<br>
    Structural mass / fuel+payload radio: <input type="range" min="0" max="100" step="1" value="12" id="structure-percentage"> <span id="structure-label"></span>%<br>
    <hr>
    &Delta;v required from the ground: <span id="earth-dv"></span> m/s<br>
    <div id="ground-unavailable" class="hidden"><b>Payload to orbit too high for existing rockets!</b></div>
    Velocity leaving ring: <span id="velocity-label"></span> m/s<br>
    Max G force experienced: <span id="g-label"> g</span><br>
    Dry mass: <span id="dry-label"></span> tonnes<br>
    Wet mass: <span id="wet-label"></span> tonnes<br>
    Fuel mass: <span id="fuel-label"></span> tonnes<br>
    Fuel cost: $<span id="cost-label"></span><br>
    &Delta;v: <span id="ring-dv"></span> m/s<br>
    <b>&Delta;v savings: <span id="delta-dv"></span> m/s</b><br>
</div>
<script type="module">
const targetElem = document.getElementById('target-orbit')
const engineElem = document.getElementById('engine')
const altitudeElem = document.getElementById('altitude')
const altitudeLabel = document.getElementById('altitude-label')
const payloadElem = document.getElementById('payload')
const payloadLabel = document.getElementById('payload-label')
const structureElem = document.getElementById('structure-percentage')
const structureLabel = document.getElementById('structure-label')
const groundUnavailableElem = document.getElementById('ground-unavailable')
const earthDVLabel = document.getElementById('earth-dv')
const velocityLabel = document.getElementById('velocity-label')
const gLabel = document.getElementById('g-label')
const dryLabel = document.getElementById('dry-label')
const wetLabel = document.getElementById('wet-label')
const fuelLabel = document.getElementById('fuel-label')
const costLabel = document.getElementById('cost-label')
const ringDVLabel = document.getElementById('ring-dv')
const deltaDVLabel = document.getElementById('delta-dv')

const setGroundAvailable = x => {
    if(x)
        groundUnavailableElem.classList.remove('hidden')
    else
        groundUnavailableElem.classList.add('hidden')
}

// Isp in seconds, mass in kg, fuel cost $/kg, rocket name, stages as [[Isp, fuel mass, dry mass], ...]
const engines = {
    merlin: [348, 470, 0.8402252631578947, "Falcon 9", [ [282, 395_700, 22_200], [348, 92_670, 4_000] ]],
    raptor: [380, 1200, 0.16, "Starship", [ [330, 3_400_000, 200_000], [380, 1_200_000, 100_000] ]],
}

const G = 6.674e-11 // gravitational constant in m^3 kg^-1 s^-2
const earthRadius = 6378.14 // in m
const earthMass = 5.972e24 // in kg
const earthOrbit = 149.6e9 // in m
const moonRadius = 1737.4 // in m
const moonMass = 7.3e22 // in kg
const marsRadius = 3389.5 // in m
const marsMass = 6.39e23 // in kg
const marsOrbit = 227.9e9 // in m
const sunMass = 1.989e30 // in kg
const update = () => {
    const target = targetElem.value
    const engine = engineElem.value
    const [isp, engineMass, costPerKg, rocketName, stages] = engines[engine]
    const altitude = parseFloat(altitudeElem.value)
    const payload = parseInt(payloadElem.value) * 1000
    const structurePercent = parseInt(structureElem.value) / 100
    payloadLabel.innerText = payload / 1000
    altitudeLabel.innerText = altitude
    structureLabel.innerText = Math.round(structurePercent * 100)

    const g0 = 9.81
    const rocketMaxDeltaV = (() => {
        let totalDV = 0
        for(let i = 0; i < stages.length; ++i) {
            let currentMass = payload
            for(let j = i; j < stages.length; ++j)
                currentMass += stages[j][1] + stages[j][2]
            const finalMass = currentMass - stages[i][1]
            totalDV += stages[i][0] * g0 * Math.log(currentMass / finalMass)
        }
        return totalDV
    })()

    // km to m/s^2
    const GravityAtAltitude = (bodyRadius, bodyMass, altitude) => G * bodyMass * ((bodyRadius + altitude) * 2) ** 2
    // km to m
    const AltitudeToRadius = (bodyRadius, altitude) => (bodyRadius + altitude) * 1_000
    // km to m/s
    const OrbitalVelocity = (bodyRadius, bodyMass, altitude) => Math.sqrt(G * bodyMass / AltitudeToRadius(bodyRadius, altitude))
    const SemiMajorAxis = (bodyRadius, perigee, apogee) => (AltitudeToRadius(bodyRadius, perigee) + AltitudeToRadius(bodyRadius, apogee)) / 2
    // km to m/s
    const SpeedAtPerigee = (bodyRadius, bodyMass, perigee, apogee) => Math.sqrt(G * bodyMass * (2 / AltitudeToRadius(bodyRadius, perigee) - 1 / SemiMajorAxis(bodyRadius, perigee, apogee)))
    // km to m/s
    const SpeedAtApogee = (bodyRadius, bodyMass, perigee, apogee) => Math.sqrt(G * bodyMass * (2 / AltitudeToRadius(bodyRadius, apogee) - 1 / SemiMajorAxis(bodyRadius, perigee, apogee)))
    const Eccentricity = (bodyRadius, perigee, apogee) => (AltitudeToRadius(bodyRadius, apogee) - AltitudeToRadius(bodyRadius, perigee)) / (AltitudeToRadius(bodyRadius, apogee) + AltitudeToRadius(bodyRadius, perigee))
    const OrbitalPeriod = (bodyRadius, bodyMass, perigee, apogee) => Math.PI * 2 * Math.sqrt(SemiMajorAxis(bodyRadius, perigee, apogee) ** 3 / (G * bodyMass))
    const DeltaVForHohmannTransfer = (bodyRadius, bodyMass, starting, final) => {
        const apogeeSpeed = SpeedAtApogee(bodyRadius, bodyMass, starting, final)
        const circularSpeed = OrbitalVelocity(bodyRadius, bodyMass, final)
        return Math.abs(circularSpeed - apogeeSpeed)
    }
    const DeltaVForBiEllipticTransfer = (bodyRadius, bodyMass, starting, higher, final) => {
        const perigeeSpeed = SpeedAtPerigee(bodyRadius, bodyMass, final, higher)
        const apogeeSpeed1 = SpeedAtApogee(bodyRadius, bodyMass, starting, higher)
        const apogeeSpeed2 = SpeedAtApogee(bodyRadius, bodyMass, final, higher)
        const circularSpeed = OrbitalVelocity(bodyRadius, bodyMass, final)
        return Math.abs(circularSpeed - perigeeSpeed) + Math.abs(apogeeSpeed2 - apogeeSpeed1)
    }
    const DeltaVForInclinationChange = (bodyRadius, bodyMass, perigee, apogee, degrees) => {
        const apogeeSpeed = SpeedAtApogee(bodyRadius, bodyMass, perigee, apogee)
        const di = degrees * Math.PI / 180
        return 2 * apogeeSpeed * Math.sin(di / 2)
    }

    let deltaVFromGround, deltaVFromRing, velocityFromRing;
    switch(target) {
        case 'earth': {
            if(altitude > 2500)
                deltaVFromGround = 2000 + OrbitalVelocity(earthRadius, earthMass, 2500) + DeltaVForHohmannTransfer(earthRadius, earthMass, 0, 2500) + DeltaVForHohmannTransfer(earthRadius, earthMass, 2500, altitude)
            else
                deltaVFromGround = (2000 - 1500) * ((altitude - 100) / 2400) + 1500 + OrbitalVelocity(earthRadius, earthMass, altitude)
            velocityFromRing = SpeedAtPerigee(earthRadius, earthMass, 150, altitude)
            deltaVFromRing = DeltaVForHohmannTransfer(earthRadius, earthMass, 150, altitude)
            break
        }
        case 'moon': {
            const moonDistance = 384400 // km
            const moonInsertion = moonDistance + moonRadius / 1000 + altitude
            velocityFromRing = SpeedAtPerigee(earthRadius, earthMass, 150, moonInsertion)
            const apogeeSpeed = SpeedAtApogee(earthRadius, earthMass, 150, moonInsertion)
            const moonSpeedRelative = 1022 // m/s -- moon's speed around Earth
            const insertionVelocity = Math.sqrt(apogeeSpeed ** 2 + moonSpeedRelative ** 2)
            const targetVelocity = OrbitalVelocity(moonRadius, moonMass, altitude)
            deltaVFromRing = Math.abs(insertionVelocity - targetVelocity)
            // This is really circularizing at 150km and then boosting up
            deltaVFromGround = 2000 + velocityFromRing + deltaVFromRing
            break
        }
        case 'mars-best': { // Hohmann transfer
            const earthOrbitalVelocity = OrbitalVelocity(0, sunMass, earthOrbit / 1000)
            velocityFromRing = OrbitalVelocity(earthRadius, earthMass, 150) + Math.abs(Math.sqrt(G * sunMass / earthOrbit) * Math.sqrt(2 * marsOrbit / (earthOrbit + marsOrbit)) - earthOrbitalVelocity)
            const marsOrbitalVelocity = OrbitalVelocity(0, sunMass, marsOrbit / 1000)
            const marsTransV = Math.abs(Math.sqrt(G * sunMass / marsOrbit) * Math.sqrt(2 * earthOrbit / (earthOrbit + marsOrbit)) - marsOrbitalVelocity)
            const circ = OrbitalVelocity(marsRadius, marsMass, altitude)
            deltaVFromRing = Math.abs(circ - marsTransV)
            deltaVFromGround = 2000 + velocityFromRing + deltaVFromRing
            break
        }
    }

    const [dryMass, propellantMass] = ((deltaV) => {
        const massRatio = Math.exp(deltaV / (isp * g0))
    
        let dryMass = engineMass + payload
        let propellantMass
        let structuralMass
    
        for(let i = 0; i < 200; i++) {
            propellantMass = dryMass * (massRatio - 1)
            structuralMass = (propellantMass + dryMass) * structurePercent
            dryMass = engineMass + payload + structuralMass
        }
        
        return [dryMass, propellantMass]
    })(deltaVFromRing)
    
    setGroundAvailable(rocketMaxDeltaV < deltaVFromGround)
    earthDVLabel.innerText = Math.round(deltaVFromGround)
    velocityLabel.innerText = Math.round(velocityFromRing)
    ringDVLabel.innerText = Math.round(deltaVFromRing)
    deltaDVLabel.innerText = Math.round(deltaVFromGround - deltaVFromRing)
    gLabel.innerText = Math.round(velocityFromRing ** 2 / AltitudeToRadius(earthRadius, 150) / 9.81 * 10) / 10
    dryLabel.innerText = Math.round(dryMass / 1000 * 10) / 10
    wetLabel.innerText = Math.round((dryMass + propellantMass) / 1000 * 10) / 10
    fuelLabel.innerText = Math.round(propellantMass / 1000 * 10) / 10
    costLabel.innerText = Math.round(propellantMass * costPerKg)
}
update()
targetElem.addEventListener('input', update)
engineElem.addEventListener('input', update)
altitudeElem.addEventListener('input', update)
payloadElem.addEventListener('input', update)
structureElem.addEventListener('input', update)
</script>
'''))
Target:
Engine:
Orbital altitude: km
Payload mass: tonnes
Structural mass / fuel+payload radio: %

Δv required from the ground: m/s
Velocity leaving ring: m/s
Max G force experienced: g
Dry mass: tonnes
Wet mass: tonnes
Fuel mass: tonnes
Fuel cost: $
Δv: m/s
Δv savings: m/s

As you can see here, we don’t need 475 tonnes of fuel anymore. We don’t need 100, we don’t need 10, we don’t even need 1. We need 300 kg. That’s because we can race around the ring building up that speed we need, let go of the ring, and then expend a tiny amount of fuel to circularize our orbit.

The difference is even more staggering for the Moon. If we use the Raptor engines and want to put 100 tonnes into a 100km lunar orbit, we need all of 17.7 tonnes of fuel; this is not even possible with any rocket launched from the ground today. (Although there is a caveat: you might be able to accomplish this with in-orbit refueling of the Starship, if you’re willing to launch 6-8 refueling tankers.)

7.3. Spacecraft Assumptions#

These calculations make the assumption that we’re going to use complex engines and structures that are built to the rigors of atmospheric flight, but it’s a lot more likely that we’ll end up building dumb, cheap spacecraft that are less efficient, but cost virtually nothing to produce and are highly reliable. We don’t even need to make them aerodynamic, because they’ll barely touch any atmosphere.

Once we factor in the cost of assembly – assuming we can’t reuse them (we’ll touch on that in a moment) – the relatively inefficient engines would require a bit more fuel, but that cost would be more than cancelled out, especially considering that even a 10x fuel budget for that last moon launch we discussed would cost less than $30k.

7.4. Capture#

Orbital rings aren’t just good for launches, though; they can also help us recover spacecraft. The same “train” that pushes our craft up to speed could instead speed itself up to match an incoming craft, attach to it via a harpoon system or other mechanism, then slow it down. If we were to build orbital rings around the Moon, Mars, and other bodies, it would be possible to launch from one planetary body to another using nothing but ring capture – no rockets at all.