If a rocket can take 1,000 kg to SSO at 500 km, is that enough information to determine what its capacity to, say, GTO or GSO would be?
If so, how would one calculate it?
If a rocket can take 1,000 kg to SSO at 500 km, is that enough information to determine what its capacity to, say, GTO or GSO would be?
If so, how would one calculate it?
No, such a calculation is not possible. The performance to different orbits is determined by the specific parameters of each launcher, e.g. specific impulse of each stage engines, fuel ratio, time of staging, flight profile...
Have a look at this plot, taken from https://elvperf.ksc.nasa.gov
As you can see the two launchers have the same performance to a 600km orbit, but Falcon 9 drops of much more rapidly for larger heights. That is (mainly) caused by the fact that Falcon 9 uses a low-performance second stage based on RP-1/LOX while Atlas uses a LH/LOX mixture with a higher specific impulse.
You might also notice the step in Atlas V performance at 500km altitude - that's due to different flight profiles. For low orbits they do only one long burn of the second stage, while for higher orbits they split it into a more efficient two-burn plan. There are likely technical reasons they can't do that for lower orbits, e.g. the cool-down phase between the two burns might be too short.
The actual information can usually be found in the User's Guide of the different launchers, e.g. the Atlas V User's Guide has 90 pages of plots and tables showing the performance figures to various kinds of orbits.
A first-order method I used before is to exploit the total impulse capability of the launch vehicle. This is specified for nearly every variety of booster, whether space launcher or short-range ballistic missile. Knowing the velocity change required to establish a trajectory in orbit (nearly independent of payload mass), one divides this into the total impulse to find the delivered mass limit. (Yes, it can depend somewhat on shape and method of ascent to orbit.)
It's only first order but an effective guide to eliminating bad ideas for payloads. Everything else that follows should be regarded as refining the first answer's value and validity. Validity, as I think of that term, depends on the type and manner of trajectory insertion as noted by @asdfex.
The other answers that there are no formulae are of course correct.
We could of course make some rules of thumb based on data.
@FreddieR's answer to What are the longest current rocket payload fairings, capable of carrying long space station sections? contains the following graphic. It's attributed to Ken Kirtland and I found a copy in DBS Larssson's tweeted graphic of LEO, GTO and TLI payload capabilities for heavy haul launch vehicles:
If we plot them, we can see that GTO payload mass can be as good as 0.3 to 0.5 of that for LEO, and TLI a bit lower. But for some vehicle configurations and specific operating choices the ratios are much lower. Those are not necessarily limits, it's just that it's impossible to do everything in one table.
import numpy as np
import matplotlib.pyplot as plt
info = (('Vulcan Centaur Heavy \n Expended', 27.2, 14.4, 13, 2775454),
('New Glenn \n 1st Stage Reuse', 45, 13, 8.5, 4454545),
('Falcon Heavy \n Expended', 63.8, 26.7, 18, 2754545),
('Starship \n Full Reuse No Refuel', 100, 21, 0, 9090909),
('SLS Block 1a \n Expended', 95, 41.5, 27, 4454545),
('SLS Block 1b - USA \n Expended, Co-Manifest w/ Orion', 63.5, 16.2, 4.5, 2609090),
('SLS Block 1b \n Expended', 97.2, 49.6, 42, 9981818),
('SLS BLock 2 \n Expended', 130, 70.8, 46, 12000000))
data = np.array([line[1:-1] for line in info])
names = [''] + [line[0] for line in info]
nicknames = '', 'VCH', 'NG', 'FH', 'STR', 'SLS1a', 'SLS1bco', 'SLS1b', 'SLS2'
labels = 'LEO', 'GTO', 'TLI'
LEO, GTO, TLI = data.T
TLI_to_LEO = TLI/LEO
GTO_to_LEO = GTO/LEO
if True:
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=[7, 10])
for thing, label in zip(data.T, labels):
ax1.plot(thing, label=label)
ax1.legend()
ax1.set_xticklabels(nicknames)
ax1.set_ylabel('metric tons', fontsize=10)
ax2.plot(GTO_to_LEO, label='GTO/LEO')
ax2.plot(TLI_to_LEO, label='TLI/LEO')
ax2.set_xticklabels(names, rotation = 90, fontsize=8)
ax2.legend(loc='best')
plt.subplots_adjust(left=None, bottom=0.35, right=None, top=0.98,
wspace=None, hspace=None)
plt.show()