In [1]:
import numpy as np
from matplotlib import pyplot
import copy

In [2]:
g_asl = dict(
    sun        = 1.74625,
    moho       = 0.275,
    eve        = 1.7,
        gilly  = 0.005,
    kerbin     = 1.0,
        mun    = 0.166,
        minmus = 0.05,
    duna       = 0.3,
        ike    = 0.112,
    jool       = 0.8,
        laythe = 0.8,
        vall   = 0.235,
        tylo   = 0.8,
        bop    = 0.06,
        pol    = 0.038,
    eeloo      = 0.172,
    )

for p in g_asl:
    g_asl[p] *= 9.81

In [3]:
def list2str(l):
    luniq = list(set(l))
    for i in range(len(luniq)):
        c = l.count(luniq[i])
        if c > 1:
            luniq[i] = '{0}x{1}'.format(c,luniq[i])
    return ', '.join(luniq)

def total_mass(*items):
    if len(items) == 1 and (not isinstance(items[0],str)):
        items = items[0]
    return sum([catalog[i]['m'] for i in items])

def total_tmax(*items):
    if len(items) == 1 and (not isinstance(items[0],str)):
        items = items[0]
    return sum([catalog[i]['tmax'] for i in items])

def total_Isp(*items):
    if len(items) == 1 and (not isinstance(items[0],str)):
        items = items[0]
    a = total_tmax(*items)
    b = sum([catalog[i]['tmax']/catalog[i]['Isp'] for i in items])
    return a/b

def total_mfuel(*items):
    if len(items) == 1 and (not isinstance(items[0],str)):
        items = items[0]
    return sum([catalog[i]['mfuel'] for i in items])

In [4]:
'''
A stage consists of one or more engine/tank configurations
and one or more booster sets

engine/tank configurations can be one of:
    isolated
    central-fed
    asparagus-fed

booster sets can be thought of as isolated engine/tank configurations

It will be assumed that maximum thrust is used for each maneuver
which is justified by the fact that the TWR at maximum weight is
expected to be in the range of 1.5 - 3.0 for each stage

all ejectable objects will have an assoicated "payload" mass
that will include the decoupler, struts and any fins or 
stability modules

rocket = [payload, stage0, stage1...]
stagei = [ (detachable_payload, engines, tanks), (detachable_payload, boosters)... ]

'''

def delta_velocity(mfull,mempty,Isp):
    return np.log(mfull / mempty) * Isp * g_asl['kerbin']

def thrust_to_weight_ratio(thrust,mass,g=g_asl['kerbin']):
    return thrust / (mass * g)

def data_boosters(payload, boosters):
    Isp = total_Isp(*boosters)
    mfull = payload + total_mass(*boosters)
    mempty = mfull - total_mfuel(*boosters)
    tmax = total_tmax(*boosters)
    dt = tmax / Isp
    return mfull,mempty,Isp,tmax,dt

def data_engines(payload, engines, tanks):
    Isp = total_Isp(*engines)
    mfull = payload + total_mass(*engines) + total_mass(*tanks)
    mempty = mfull - total_mfuel(*tanks)
    tmax = total_tmax(*engines)
    dt = tmax / Isp
    return mfull,mempty,Isp,tmax,dt

def data_substage(payload, engines, tanks, boosters):
    if False:
        print 'data_substage:'
        print '    engines:',engines
        print '    tanks:',tanks
        print '    boosters:',boosters
    if len(engines) > 0:
        if len(boosters) > 0:
            # engines and boosters
            edata = data_engines(payload,engines,tanks)
            bdata = data_boosters(payload,boosters)
            
            mfull1 = edata[0] + bdata[0]
            tmax1 = edata[3] + bdata[3]
            Isp1 = tmax1 / (edata[3]/edata[2] + bdata[3]/bdata[2])
            
            # ratio of dt
            r = bdata[4] / edata[4]
            
            if r < 1:
                # boosters cut-off before engines
                dt1 = bdata[4]
                dt0 = edata[4] - dt1
                m_used = (dt1 / (dt1+dt0)) * (edata[0] - edata[1])
                
                mempty1 = edata[0] - m_used + bdata[1]
                
                mfull0 = edata[0] - m_used
                mempty0 = edata[1]
                Isp0 = edata[2]
                tmax0 = edata[3]
                
            else:
                # engines cut-off before boosters
                dt1 = edata[4]
                dt0 = bdata[4] - dt1
                m_used = (dt1 / (dt1+dt0)) * (bdata[0] - bdata[1])
                
                mempty1 = bdata[0] - m_used + edata[1]
                
                mfull0 = bdata[0] - m_used
                mempty0 = bdata[1]
                Isp0 = bdata[2]
                tmax0 = bdata[3]
                
                
            return [(mfull0,mempty0,Isp0,tmax0,dt0),
                    (mfull1,mempty1,Isp1,tmax1,dt1)]
        else:
            # engines only
            return (data_engines(payload, engines, tanks),)
    else:
        # boosters only
        return (data_boosters(payload, boosters),)

def data_stage(*substages):
    '''
    A "stage" assumes all engines are operating at full thrust
    for the duration of the stage. Engines may drop off between
    the substages.
    
    The substages must be ordered by dt. Since this is hard to 
    anticipate with booster/engine combinations, an exception
    is thrown if this contract is not satisfied.
    
    [(dpayload0,engines0,tanks0),(dpayload1,boosters1)...] = substages
    '''
    if False:
        print '''\
data_stage()
    substages: {0}'''.format(substages)
    
    data = []
    
    skip = False
    for i in range(len(substages)):
        if skip:
            skip = False
        else:
            upper_stages = copy.deepcopy(substages[:i])
            this_stage = copy.deepcopy(substages[i])
    
            payload = this_stage[0]
            if len(this_stage) == 4:
                # engine/tank and boosters
                engines = this_stage[1]
                tanks = this_stage[2]
                boosters = this_stage[3]
            elif len(this_stage) == 3:
                # engine/tank
                engines = this_stage[1]
                tanks = this_stage[2]
                boosters = []
                if (i+1) < len(substages):
                    if len(substages[i+1]) == 2:
                        # engine/tank and boosters
                        payload += substages[i+1][0]
                        boosters = substages[i+1][1]
                        skip = True
            else:
                # boosters
                engines = []
                tanks = []
                boosters = this_stage[1]
    
            for s in upper_stages:
                payload += s[0]
                if len(s) == 3:
                    # engine/tank
                    payload += total_mass(*s[2])
                    engines += s[1]
                else:
                    # boosters
                    boosters += s[1]

            #print '    ',payload,engines,tanks,boosters
            for d in data_substage(payload,engines,tanks,boosters):
                data.append(d)
        
    return data

def data_rocket(planet,payload,*stages):
    '''
    mfull,mempty,Isp,tmax,dt == data
    '''
    if False:
        print '''\
data_rocket()
    planet:  {0}
    payload: {1}
    stages:  {2}'''.format(planet,payload,stages)
    
    data_rocket = []
    data_stages = [data_stage(*s) for s in stages]
    for stage in range(len(stages)):
        this_stage = copy.deepcopy(data_stages[stage])
        upper_stages = copy.deepcopy(data_stages[:stage])
        
        upper_stages_mass = 0.
        for s in upper_stages:
            for ss in s:
                upper_stages_mass += ss[0]
        
        for substage in range(len(this_stage)):
            this_substage = this_stage[substage]
            mfull = payload + this_substage[0] + upper_stages_mass
            mempty = payload + this_substage[1] + upper_stages_mass
            Isp,tmax,dt = this_substage[2:]
            
            dv = delta_velocity(mfull,mempty,Isp)
            twr = thrust_to_weight_ratio(tmax,mfull,g_asl[planet])
            
            data_rocket += [(stage,substage,mfull,mempty,Isp,tmax,dt,dv,twr)]
        
    return data_rocket
        
def info(*data,**kwargs):
    verbose = kwargs.get('verbose',False)
    if verbose:
        template = '''\
Stage {stage}-{substage}
    M: {mfull:.1f} -> {mempty:.1f}
    dt: {dt:.3f}
    dV: {dv:.0f}
    TWR: {twr:.2f}
'''
    else:
        template = 'Stage {stage}-{substage}, M: {mfull:.1f}, dV: {dv:.0f}, TWR: {twr:.2f}\n'
        
    msg = ''
    for (stage,substage,mfull,mempty,Isp,tmax,dt,dv,twr) in data[::-1]:
        msg += template.format(**dict(
            stage=stage,
            substage=substage,
            mfull=mfull,
            mempty=mempty,
            Isp=Isp,
            tmax=tmax,
            dt=dt,
            dv=dv,
            twr=twr))
    totdv = sum([d[7] for d in data])
    msg += 'Total dV = {0:.0f}\n'.format(totdv)
    return msg

def plot_rocket_info(planet,minpayload,maxpayload,*stages):
    sample_data = data_rocket(planet,1,*stages)
    nsubstages = len(sample_data)
    
    npoints = 200
    payloads = np.linspace(minpayload,maxpayload,npoints)
    dv = np.empty(shape=(npoints,))
    twr0 = np.empty(shape=(nsubstages,npoints))
    
    for i,payload in enumerate(payloads):
        data = data_rocket(planet,payload,*stages)
        dv[i] = sum(d[-2] for d in data)
        for j in range(nsubstages):
            twr0[j,i] = data[j][-1]
    
    fig = pyplot.figure(figsize=(6,4))
    ax = fig.add_subplot(1,1,1)
    axr = ax.twinx()
    ax.grid(True)
    axr.set_color_cycle('b g r c m y'.split())
    
    pt = ax.plot(payloads,dv,lw=3,color='black')
    for tl in axr.get_yticklabels():
        tl.set_color('blue')
    
    twr_pts = []
    for i in range(nsubstages-1,-1,-1):
        twr_pts += axr.plot(payloads,twr0[i,:],lw=3)
    
    lx = ax.set_xlabel('payload (T)')
    ly = ax.set_ylabel('$\Delta v$')
    lyr = axr.set_ylabel('Initial TWR', color='blue')
    ax.legend(twr_pts,['stage {0}'.format(i) for i in range(nsubstages-1,-1,-1)])
    
    return ax,axr

In [5]:
catalog = {
# tanks
    # Extra Large
    'S3-14400' : dict(m = 82.,  mfuel = 72.),
    'S3-7200'  : dict(m = 41.,  mfuel = 36.),
    'S3-3600'  : dict(m = 20.5, mfuel = 18.),
    
    # Large
    'Jumbo-64' : dict(m = 36.,  mfuel = 32.),
    'X200-32'  : dict(m = 18.,  mfuel = 16.),
    'X200-16'  : dict(m = 9.,   mfuel = 8.),
    'X200-8'   : dict(m = 4.5,  mfuel = 4.),
    
    # Small
    'FL-T800'  : dict(m = 4.5,    mfuel = 4.0),
    'FL-T400'  : dict(m = 2.25,   mfuel = 2.0),
    'FL-T200'  : dict(m = 1.125,  mfuel = 1.0),
    'FL-T100'  : dict(m = 0.5625, mfuel = 0.49),
    
    # Tiny
    'ROUND-8'  : dict(m = 0.136,  mfuel = 0.11),
    'Oscar-B'  : dict(m = 0.0787, mfuel = 0.06),
    'PB-X150'  : dict(m = 0.12,   mfuel = 0.07),
    
    # monopropellant
    'FL-R1'    : dict(m = 3.4,    mfuel = 3.),
    'FL-R25'   : dict(m = 0.55,   mfuel = 0.4),
    'FL-R10'   : dict(m = 0.25,   mfuel = 0.2),
    'Stratus-V Cylindrified' : dict(m = 0.75,  mfuel = 0.6),
    'Stratus-V Roundified'   : dict(m = 0.235, mfuel = 0.16),
    'PB-X50R'  : dict(m = 0.07,   mfuel = 0.04),

# engines
    # Extra Large
    'KS-25x4'  : dict(m = 9.75, tmax =  3200., Isp =  360., Isp_asl =  320.),
    'KR-2L'    : dict(m = 6.5,  tmax =  2500., Isp =  380., Isp_asl =  280.),
    
    # Large
    'Mainsail' : dict(m = 6.0,  tmax =  1500., Isp =  360., Isp_asl =  320.),
    'Skipper'  : dict(m = 3.0,  tmax =   650., Isp =  370., Isp_asl =  320.),
    'Poodle'   : dict(m = 2.0,  tmax =   220., Isp =  390., Isp_asl =  270.),
    
    # Small
    'LV-N'     : dict(m = 2.25, tmax =    60., Isp =  800., Isp_asl =  220.),
    'LV-T45'   : dict(m = 1.5 , tmax =   200., Isp =  370., Isp_asl =  320.),
    'LV-T30'   : dict(m = 1.25, tmax =   215., Isp =  370., Isp_asl =  320.),
    'LV-909'   : dict(m = 0.5 , tmax =    50., Isp =  390., Isp_asl =  300.),
    
    # Tiny
    '48-7S'    : dict(m = 0.1 , tmax =    30., Isp =  350., Isp_asl =  300.),
    'LV-1'     : dict(m = 0.03, tmax =     4., Isp =  290., Isp_asl =  220.),
    'PB-ION'   : dict(m = 0.25, tmax =     2., Isp = 4200., Isp_asl = 4200.),
    
    # Radially-Mounted
    'Mark 55'  : dict(m = 0.9 , tmax =   120., Isp =  320., Isp_asl =  290.),
    '24-77'    : dict(m = 0.09, tmax =    20., Isp =  300., Isp_asl =  250.),
    'LV-1R'    : dict(m = 0.03, tmax =     4., Isp =  290., Isp_asl =  220.),
    
    # monopropellant
    'O-10'     : dict(m = 0.09, tmax =    20., Isp =  290., Isp_asl =  220.),
    'RV-105'   : dict(m = 0.05, tmax =     1., Isp =  260., Isp_asl =  100.),
    '7 Linear' : dict(m = 0.05, tmax =     1., Isp =  260., Isp_asl =  100.),

# boosters
    # Large
    'KR-1x2'    : dict(m = 42.0,   tmax = 2000.0, Isp = 340., Isp_asl = 290,  mfuel = 32.0),
    
    # Small
    'SRB-KD25K' : dict(m = 21.75,  tmax = 650.,   Isp = 250., Isp_asl = 230., mfuel = 18.75),
    'BACC'      : dict(m = 7.875,  tmax = 315.,   Isp = 250., Isp_asl = 230., mfuel = 6.37),
    'RT-10'     : dict(m = 3.7475, tmax = 250.,   Isp = 240., Isp_asl = 225., mfuel = 3.25),
    
    # Tiny
    'Sepratron I' : dict(m=0.0725),

# equipment
    # command modules
        'Command Pod Mk1' : dict(m=0.84), # Small
        'Mk1-2 Command Pod' : dict(m=4.12), # Large
        'Mk2 Lander-can' : dict(m=2.66), # Large
    # Probe Cores
        'OKTO2' : dict(m=0.04), # Tiny, Flat
    # Stability Enhancers
        'Inline Reaction Wheel' : dict(m=0.12), # Small
        'ASAS' : dict(m=0.2), # Large
    # (De)couplers
        # Extra Large
        
        # Large
        'TR-XL' : dict(m=0.45), # 2-sided
        'Rockomax Decoupler' : dict(m=0.4), # 1-sided
        # Small
        'TR-18D' : dict(m=0.075), # 2-sided
        'TR-18A' : dict(m=0.05), # 1-sided decoupler
        'TVR-200' : dict(m=0.1), # Bi-coupler
        # Radial
        'HDM' : dict(m=0.4), # Large
    # Fuel Line
        'FTX-2' : dict(m=0.05),
    # Struts
        'EAS-4' : dict(m=0.05), # basic strut
        'LT-2' : dict(m=0.1), # landing leg (Large)
        'LT-1' : dict(m=0.05), # landing leg (Small)
        'LT-5' : dict(m=0.015), # landing leg (Tiny)
        'Rockomax Adapter' : dict(m=0.1), # Large/Small (long)
        'Rockomax Adapter 2' : dict(m=0.08), # Large/Small (short)
        'M-1x1' : dict(m=0.075), # 1x1 panel
    # Parachutes and Recovery
        'Launch Escape' : dict(m=1.1125),
        'Mk16' : dict(m=0.1), # Tiny
        'Mk16-XL' : dict(m=0.3), # Large
        'Mk2-R' : dict(m=0.15), # radial
    # Communications
        'Communotron 16' : dict(m=0.005),
    # Solar Panels and batteries
        'OX-STAT' : dict(m=0.005), # single panel
        'SP-L 1x6' : dict(m=0.025),
        'Z-400' : dict(m=0.02),
        'Z-200' : dict(m=0.01),
    # Docking
        'Clamp-O-Tron' : dict(m=0.05),
        'Clamp-O-Tron Jr' : dict(m=0.02),
    # Lighting
        'Illuminator Mk1' : dict(m=0.015),
        'Illuminator Mk2' : dict(m=0.015),
    # Mobility
        'Telus-LV' : dict(m = 0.005),
    # Science!
        'Mystery Goo' : dict(m=0.15),
        'Science Jr' : dict(m=0.2),
        'Double-C' : dict(m=0.005),
        'PresMat' : dict(m=0.005),
        '2HOT' : dict(m=0.005),
        'GRAVMAX' : dict(m=0.005),
        'Sensor Array' : dict(m=0.08),
            
}

In [28]:
planet = 'kerbin'
payload = 4

stage1 = (0.5,
    ['LV-N']*3,
    ['FL-T400']*3)# + ['FL-T100']*3)

stage2a = (0.5,
    ['Mainsail'],
    ['Jumbo-64'])
stage2b = (0.5,
    ['Skipper']*2,
    ['Jumbo-64']*2)
stages = [[stage1],[stage2a,stage2b]]

data = data_rocket(planet,payload,*stages)
print info(*data)

ax,axr = plot_rocket_info(planet,0,5,*stages)
l=ax.axvline(payload,color='blue',zorder=-1,ls='--')


Stage 1-1, M: 139.0, dV: 2207, TWR: 2.05
Stage 1-0, M: 60.5, dV: 2658, TWR: 2.53
Stage 0-0, M: 18.0, dV: 3182, TWR: 1.02
Total dV = 8047


In [39]:
_='''
ED-50K (Elrond II)

50T to LKO
'''

print '12x6 EAS-4 mass:',total_mass(['EAS-4']*(12*4))
print '12x12 M-1x1 mass:',total_mass(['M-1x1']*(12*4))

planet = 'kerbin'
payload = total_mass(['Command Pod Mk1','Mk16-XL','OKTO2','Z-200'] \
                     + ['TR-18A']*2 + ['OX-STAT']*2 + ['FL-T400','LV-909'] \
                     + ['Jumbo-64']+['Clamp-O-Tron']*4 +['Clamp-O-Tron Jr']*2 +['Rockomax Adapter 2','FL-R1']*2 \
                     + ['EAS-4']*24)
print 'payload:',payload

stage1 = (1,
    ['KR-2L'],
    ['S3-14400','S3-3600'])
stage2 = (1,
    ['KS-25x4'],
    ['S3-14400','S3-7200'],
    ['KR-1x2']*2)
stages = [[stage1],[stage2]]

data = data_rocket(planet,payload,*stages)
print info(*data)

ax,axr = plot_rocket_info(planet,0,100,*stages)
l=ax.axvline(payload,color='blue',zorder=-1,ls='--')


12x6 EAS-4 mass: 2.4
12x12 M-1x1 mass: 3.6
payload: 48.45
Stage 1-1, M: 377.2, dV: 1831, TWR: 1.95
Stage 1-0, M: 195.1, dV: 279, TWR: 2.09
Stage 0-0, M: 158.4, dV: 3129, TWR: 1.61
Total dV = 5238


In [6]:
_='''
ED-10K (Elrond I)

10T to LKO
'''

planet = 'kerbin'
payload = 10
stage0 = (1,
    ['Skipper'],
    ['Jumbo-64'])
stage1 = (1,
    ['Mainsail'],
    ['Jumbo-64'],
    [])
stages = [[stage0],[stage1]]
data = data_rocket(planet,payload,*stages)
print info(*data)

ax,axr = plot_rocket_info(planet,0,20,*stages)
l=ax.axvline(payload,color='blue',zorder=-1,ls='--')


Stage 1-0, M: 93.0, dV: 1489, TWR: 1.64
Stage 0-0, M: 50.0, dV: 3708, TWR: 1.33
Total dV = 5198


In [88]:
_='''
Silmaril Mechanics SM-ST6 Space Tug (Ori)

6.5k dv in a compact and very maneuverable package
with all the docking ports you might need.
Can move 50T from LKO to the Mun and back!
All this delivered to 100km orbit for less than 200k in funds!
Kerbed or unkerbed, your choice!
'''

planet = 'kerbin'
payload = 0
stage0 = (1+total_mass(['FL-R1','Rockomax Adapter']+['Clamp-O-Tron']*5+['OKTO2']+['LV-909']*2),
    ['LV-N']*2,
    ['X200-32'],
    [])
data = data_rocket(planet,payload,[stage0])
print info(*data)

ax,axr = plot_rocket_info(planet,0,100,[stage0])
l=ax.axvline(50,color='blue',zorder=-1,ls='--')


Stage 0-0, M: 28.3, dV: 6543, TWR: 0.43
Total dV = 6543


In [89]:
_='''
Eru Dynamics ED-30KMI D (Arwen D)

4th version using Extra Large Components
Heavy Lifter by ED. 30T to LKO (100km) to Mun Intercept

Tested and works great!

target dV = 4550 + 860 = 5410
'''

planet = 'kerbin'
payload = total_mass(['Launch Escape', 'TR-18A','TR-XL','Rockomax Adapter 2','TR-18D']+['EAS-4']*6)
payload += 27.8
print 'payload:',payload

stage0 = (total_mass(['Rockomax Decoupler','ASAS']),
          ['Mainsail'],
          ['X200-32'])
stage1 = (2,
           ['KR-2L'],
           ['S3-14400'])
stage2 = (2,
           ['KS-25x4'] + ['Mark 55']*8,
           ['S3-14400']*2)

stages = [[stage0],[stage1],[stage2]]

data = data_rocket(planet,payload,*stages)
print info(*data)
ax,axr = plot_rocket_info(planet,0,40,*stages)
l=ax.axvline(payload,color='blue',zorder=-1,ls='--')


payload: 29.8675
Stage 2-0, M: 327.9, dV: 1985, TWR: 1.29
Stage 1-0, M: 145.0, dV: 2559, TWR: 1.76
Stage 0-0, M: 54.5, dV: 1228, TWR: 2.81
Total dV = 5772


In [90]:
_='''
Eru Dynamics ED-30KMI-C (Arwen C)

3rd version using Extra Large Components
Heavy Lifter by ED. 30T to LKO (100km) to Mun Intercept

Untested. Mostly because the engineers can't figure out how to make a cluster of five mainsails.
Not to mention using a KS-25x4 as an upper stage engine.

target dV = 4550 + 860 = 5410
'''

planet = 'kerbin'
payload = total_mass(['Launch Escape', 'TR-18A','TR-XL','Rockomax Adapter 2','TR-18D']+['EAS-4']*6)
payload += 27.8
print 'payload:',payload

stage0 = (total_mass(['Rockomax Decoupler','ASAS']),
          ['Mainsail'],
          ['X200-32']+['X200-16'])
stage1 = (2,
           ['KS-25x4'],
           ['S3-7200'] + ['S3-3600'])
stage2 = (2,
          ['Mainsail']*5,
          ['S3-14400']*2 + ['S3-3600'])

stages = [[stage0],[stage1],[stage2]]

data = data_rocket(planet,payload,*stages)
print info(*data)
ax,axr = plot_rocket_info(planet,0,40,*stages)
l=ax.axvline(payload,color='blue',zorder=-1,ls='--')


payload: 29.8675
Stage 2-0, M: 353.2, dV: 2167, TWR: 2.16
Stage 1-0, M: 136.7, dV: 1775, TWR: 2.39
Stage 0-0, M: 63.5, dV: 1678, TWR: 2.41
Total dV = 5620


In [91]:
_='''
Eru Dynamics ED-30KMI-B (Arwen B)

2nd version using Extra Large Components
Heavy Lifter by ED. 30T to LKO (100km) to Mun Intercept

Works, but is more expensive in the end than the Arwen
despite having fewer parts.

target dV = 4550 + 860 = 5410
'''

planet = 'kerbin'
payload = total_mass(['Launch Escape', 'TR-18A','TR-XL','Rockomax Adapter 2','TR-18D']+['EAS-4']*6)
payload += 27.8
print 'payload:',payload

stage0 = (total_mass(['Rockomax Decoupler','ASAS']),
          ['Mainsail'],
           ['X200-32'])

stage1A = (total_mass(['Rockomax Decoupler']),
           ['KS-25x4'],
           ['S3-14400']*2 + ['Jumbo-64']*2)
stage1B = (total_mass(['HDM']*2 + ['Rockomax Adapter']*2 + ['Mk16-XL']*2 + ['Sepratron I']*4 + ['EAS-4']*2 + ['FTX-2']*2),
           ['KR-1x2'])

stages = [[stage0],[stage1A,stage1B]]

data = data_rocket(planet,payload,*stages)
print info(*data)
ax,axr = plot_rocket_info(planet,0,40,*stages)
l=ax.axvline(payload,color='blue',zorder=-1,ls='--')


payload: 29.8675
Stage 1-1, M: 347.2, dV: 2316, TWR: 1.53
Stage 1-0, M: 165.1, dV: 1962, TWR: 1.98
Stage 0-0, M: 54.5, dV: 1228, TWR: 2.81
Total dV = 5506


In [92]:
_='''
Eru Dynamics ED-30KMI (Arwen)

Heavy Lifter by ED. 30T to LKO (100km) to Mun Intercept

target dV = 4550 + 860 = 5410
'''

planet = 'kerbin'
payload = total_mass(['Launch Escape', 'TR-18A','TR-XL','Rockomax Adapter 2','TR-18D']+['EAS-4']*6)
payload += 27.8
print 'payload:',payload

stage1A = (total_mass(['Rockomax Decoupler','ASAS']),
           ['Mainsail'] + ['Mark 55']*4,
           ['Jumbo-64','X200-16','X200-8'])
stage1B = (total_mass(['HDM']*2 + ['Rockomax Adapter']*2 + ['Mk16-XL']*2 + ['Sepratron I']*4 + ['EAS-4']*2 + ['FTX-2']*2),
           ['Mainsail']*2,
           ['Jumbo-64']*4)
stage1C = (total_mass(['HDM']*2 + ['Rockomax Adapter']*2 + ['Mk16-XL']*2 + ['Sepratron I']*4 + ['EAS-4']*2 + ['FTX-2']*2),
           ['Mainsail']*2,
           ['Jumbo-64']*2)

stages = [[stage1A,stage1B,stage1C]]

data = data_rocket(planet,payload,*stages)
print info(*data)
ax,axr = plot_rocket_info(planet,0,40,*stages)
l=ax.axvline(payload,color='blue',zorder=-1,ls='--')


payload: 29.8675
Stage 0-2, M: 333.7, dV: 746, TWR: 2.44
Stage 0-1, M: 247.7, dV: 2538, TWR: 2.05
Stage 0-0, M: 89.6, dV: 2316, TWR: 2.25
Total dV = 5601


In [93]:
_='''
Silmaril Mechanics SM-O3-20 (Elendil)

3-Kerbin, 20T Orbiter with standard Clamp-O-Tron

LKO - > Mun Intercept:       860 (with full lander: 9.4)
Mun Intercept -> Mun Orbit:  210 (with full lander: 9.4)
--------------------------------
Total:                      1070
Mun Orbit -> Kerbin Int:     210 (with empty lander: 5.4)
--------------------------------
Total:                      1280
Kerbin Int -> Orbit:         860
Total:                      2120 (use X200-32 instead of the X200-16)

Enough fuel to circularize in Munar Orbit and back to LKO (vD = 1300)
'''

planet = 'kerbin'
equipment = ['Clamp-O-Tron','Mk1-2 Command Pod'] + ['Mk2-R']*2 \
    + ['RV-105']*4 + ['Rockomax Decoupler'] + ['Stratus-V Roundified']*2 \
    + ['SP-L 1x6']*2 + ['Z-400']*2 \
    + ['Communotron 16'] + ['EAS-4']*4
equipment_mass = total_mass(equipment)

# lander mass
payload = 10.

stage0 = (
    equipment_mass,
    ['Skipper'],
    ['X200-16'] )

stages = [[stage0]]
data = data_rocket(planet,payload,*stages)
print info(*data)
ax,axr = plot_rocket_info(planet,0,20,*stages)
l=ax.axvline(payload,color='blue',zorder=-1,ls='--')


Stage 0-0, M: 27.8, dV: 1230, TWR: 2.38
Total dV = 1230


In [94]:
_='''
Silmaril Mechanics SM-ML2-10 (Took)

2-Kerbin Mun Lander
'''

planet = 'mun'
equipment = ['Clamp-O-Tron','Mk2 Lander-can', 'Science Jr', 'Communotron 16', 'Double-C', 'PresMat', '2HOT'] \
    + ['Mystery Goo','GRAVMAX'] + ['Illuminator Mk2']*3 + ['LT-2']*3 + ['Telus-LV'] + ['RV-105']*4 \
    + ['Stratus-V Roundified']*2 + ['EAS-4']*8
payload = total_mass(equipment)

stage0 = (
    0,
    ['24-77']*4,
    ['X200-8'] )
stages = [[stage0]]
data = data_rocket(planet,payload,*stages)
print info(*data,verbose=True)
ax,axr = plot_rocket_info(planet,0,10,*stages)
l=ax.axvline(payload,color='blue',zorder=-1,ls='--')


Stage 0-0
    M: 9.4 -> 5.4
    dt: 0.267
    dV: 1639
    TWR: 5.25
Total dV = 1639


In [95]:
_='''
Eru Dynamics ED-3K-2 (Feanor III)

3 ton payload
two stage kerbin launch to orbit at 100km.

Smooth gravity turn at 200 m/s, Circularize at 72km, Hohmann to 100km.
'''

    
planet = 'kerbin'

equipment =['Command Pod Mk1','OKTO2','Mk16','Communotron 16'] + ['OX-STAT']*2 \
    + ['TR-18A']*2 \
    + ['RV-105']*4 + ['FL-R25']
engines = ['LV-909']
tanks = ['FL-T100']
payload = total_mass(equipment + engines + tanks)


stage0 = (
    total_mass(['TR-18A'] + ['Sepratron I']*3),
    ['LV-T30'],
    ['FL-T800']*2 )
stage1 = (
    total_mass(['TVR-200'] + ['TR-18A'] + ['EAS-4']*2 \
    + ['Inline Reaction Wheel']),
    ['LV-T30']*2,
    ['FL-T800']*2  + ['FL-T400']*2)
stage2 = (
    0.2,
    ['BACC']*4)

planet = 'kerbin'
stages = [[stage0],[stage1],[stage2]]
data = data_rocket(planet,payload,*stages)
print info(*data)
ax,axr = plot_rocket_info(planet,0,5,*stages)
l=ax.axvline(payload,color='blue',zorder=-1,ls='--')


Stage 2-0, M: 61.5, dV: 1312, TWR: 2.09
Stage 1-0, M: 29.8, dV: 1871, TWR: 1.47
Stage 0-0, M: 13.4, dV: 3289, TWR: 1.63
Total dV = 6472


In [96]:
_='''
Eru Dynamics ED-1K-2 (Feanor II)

1 ton payload
two stage kerbin launch to orbit.
fuel lines from the side tanks to the center are required

Fuel requirement is much less than half the single-stage version!
'''

stage0 = [
    # upper substage
    (0.1, ['LV-T30'], ['FL-T800']),
    # lower substage
    (0.1, ['LV-909']*2, ['FL-T400']*2  + ['FL-T200']*2),
]

planet = 'kerbin'
payload = 0.8
data = data_rocket(planet,payload,stage0)
print info(*data)
ax,axr = plot_rocket_info(planet,0,5,stage0)
l=ax.axvline(payload,color='blue',zorder=-1,ls='--')


Stage 0-1, M: 14.5, dV: 1971, TWR: 2.21
Stage 0-0, M: 6.6, dV: 3340, TWR: 3.30
Total dV = 5310


In [97]:
_='''
Eru Dynamics ED-1K-B (Feanor IB)

1 ton payload
single stage kerbin launch to orbit.
fins are probably needed.
TWR > 2.2 means this should work but
it requires a lot of fuel

JUST enough to get to 71km and deorbit!
had to route fuel TO the outer engines.
'''

stage0 = [
    (0.2, ['LV-T30']*3, ['FL-T800']*3 + ['FL-T800']*2)
]

planet = 'kerbin'
payload = 0.8
data = data_rocket(planet,payload,stage0)
print info(*data)
ax,axr = plot_rocket_info(planet,0,5,stage0)
l=ax.axvline(payload,color='blue',zorder=-1,ls='--')


Stage 0-0, M: 27.2, dV: 4806, TWR: 2.41
Total dV = 4806


In [98]:
_='''
Eru Dynamics ED-1K (Feanor I)

1 ton payload
single stage kerbin launch to orbit.
requires fins for steering
low TWR, but enough to make it to 75km and to deorbit.
looks like no room for sloppy piloting.
'''

stage0 = [
    (0.2, ['LV-T30'], ['FL-T800']*2 + ['FL-T400'])
]

planet = 'kerbin'
payload = 0.8
data = data_rocket(planet,payload,stage0)
print info(*data)
ax,axr = plot_rocket_info(planet,0,5,stage0)
l=ax.axvline(payload,color='blue',zorder=-1,ls='--')


Stage 0-0, M: 13.5, dV: 4900, TWR: 1.62
Total dV = 4900