Skip to content

Commit

Permalink
Add ability to limit when solid fuel boosters can fire
Browse files Browse the repository at this point in the history
  • Loading branch information
popiel committed Oct 27, 2017
1 parent 4db41d0 commit 9bc1299
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 14 deletions.
21 changes: 16 additions & 5 deletions kspalculator/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ def positive_float(string):
raise ArgumentTypeError("%r is not positive" % string)
return fl

def to_boolean(string):
if string.lower() not in ['t', 'true', '1', 'y', 'yes', 'f', 'false', '0', 'n', 'no', '']:
raise ArgumentTypeError("%r is not a boolean (true/false)" % string)
return string.lower() in ['t', 'true', '1', 'y', 'yes']

def dvtuple(string):
spl = string.split(':')
positive_float(spl[0])
Expand All @@ -28,6 +33,8 @@ def dvtuple(string):
if len(spl) > 2:
nonnegative_float(spl[2])
if len(spl) > 3:
to_boolean(spl[3])
if len(spl) > 4:
raise ArgumentTypeError("%r contains too many ':'" % string)
return string

Expand All @@ -39,10 +46,12 @@ def main():

parser = ArgumentParser(description=summary, epilog=epilog)
parser.add_argument('payload', type=nonnegative_float, help='Payload in kg')
parser.add_argument('dvtuples', type=dvtuple, metavar='deltav[:min_acceleration[:pressure]]', nargs='+',
help='Tuples of required delta v (in m/s), minimum acceleration (in m/s²) and environment '
'pressure (0.0 = vacuum, 1.0 = ATM) at each flight phase. Default for minimum acceleration '
'is 0 m/s², default for pressure is vacuum.')
parser.add_argument('dvtuples', type=dvtuple,
metavar='deltav[:min_acceleration[:pressure[:sfb_allowed]]]', nargs='+',
help='Tuples of required delta v (in m/s), minimum acceleration (in m/s²), environment '
'pressure (0.0 = vacuum, 1.0 = ATM), and whether solid fuel boosters are allowed (t/f) '
'at each flight phase. Default for minimum acceleration is 0 m/s², default for pressure '
'is vacuum, and default for sfb allowed is true.')
parser.add_argument('-V', '--version', action='version',
version=('kspalculator version %s, for KSP version %s.' % (get_version(), kspversion)))
parser.add_argument('-q', '--quiet', action='store_true', help='Do not print prologue')
Expand Down Expand Up @@ -82,13 +91,15 @@ def main():
dv = []
ac = []
pr = []
sa = []
for st in args.dvtuples:
s = st.split(':')
dv.append(float(s[0]))
ac.append(0.0 if len(s) < 2 else float(s[1]))
pr.append(0.0 if len(s) < 3 else float(s[2]))
sa.append(True if len(s) < 4 else s[3].lower() in ['t', 'true', '1', 'y', 'yes'])

finder = Finder(args.payload, preferred_size, dv, ac, pr, args.gimbal, args.boosters,
finder = Finder(args.payload, preferred_size, dv, ac, pr, sa, args.gimbal, args.boosters,
args.electricity, args.length, args.monopropellant)
D = finder.find(not args.show_all_solutions, args.cheapest)

Expand Down
28 changes: 20 additions & 8 deletions kspalculator/design.py
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,16 @@ def has_enough_acceleration(self, min_acceleration):
return False
return True

def sfb_burning_when_allowed(self, sfb_allowed):
if self.performance is None:
return False
# pylint: disable=unused-variable
dv, p, a_s, a_t, m_s, m_t, solid, op = self.performance
for i in range(len(solid)):
if solid[i] and not sfb_allowed[op[i]]:
return False
return True

def __str__(self):
rstr = ''
f_yes = ' ✔ '
Expand Down Expand Up @@ -398,7 +408,7 @@ def create_monopropellant_design(payload, pressure, dv, acc, tank, count):
size=tank.size, count=count, fueltype=parts.FuelTypes.Monopropellant, tank=tank)


def create_sfb_design(payload, pressure, dv, acc, eng, eng_F_percentage, size, count, sfb, sfbcount):
def create_sfb_design(payload, pressure, dv, acc, sfb_allowed, eng, eng_F_percentage, size, count, sfb, sfbcount):
"""Create LiquidFuel + SFB design with given parameters"""
design = Design(payload, eng, count, size, parts.FuelTypes.LiquidFuel)
design.add_sfb(sfb, sfbcount)
Expand All @@ -417,20 +427,22 @@ def create_sfb_design(payload, pressure, dv, acc, eng, eng_F_percentage, size, c
design.calculate_performance(dv, pressure)
if not design.has_enough_acceleration(acc):
return None
if not design.sfb_burning_when_allowed(sfb_allowed):
return None
if sfbcount != 1:
design.notes.append("Set liquid fuel engine thrust to {:.0%} while SFB are burning".format(eng_F_percentage))
return design


def create_single_lfe_sfb_design(payload, pressure, dv, acc, eng, eng_F_percentage, sfb, sfbcount):
return create_sfb_design(payload, pressure, dv, acc, eng, eng_F_percentage, eng.size, 1, sfb, sfbcount)
def create_single_lfe_sfb_design(payload, pressure, dv, acc, sfb_allowed, eng, eng_F_percentage, sfb, sfbcount):
return create_sfb_design(payload, pressure, dv, acc, sfb_allowed, eng, eng_F_percentage, eng.size, 1, sfb, sfbcount)


def create_radial_lfe_sfb_design(payload, pressure, dv, acc, eng, eng_F_percentage, size, count, sfb, sfbcount):
return create_sfb_design(payload, pressure, dv, acc, eng, eng_F_percentage, size, count, sfb, sfbcount)
def create_radial_lfe_sfb_design(payload, pressure, dv, acc, sfb_allowed, eng, eng_F_percentage, size, count, sfb, sfbcount):
return create_sfb_design(payload, pressure, dv, acc, sfb_allowed, eng, eng_F_percentage, size, count, sfb, sfbcount)


def find_designs(payload, pressure, dv, min_acceleration,
def find_designs(payload, pressure, dv, min_acceleration, sfb_allowed,
preferredsize = None, bestgimbal = 0, sfballowed = False, prefergenerators = False,
prefershortengines = False, prefermonopropellant = True):
# pressure: 0 = vacuum, 1 = kerbin
Expand Down Expand Up @@ -467,7 +479,7 @@ def find_designs(payload, pressure, dv, min_acceleration,
continue
for sfb in parts.SolidFuelBoosters:
for limit in [0, 1/3, 1/2, 2/3, 1]:
d = create_radial_lfe_sfb_design(payload, pressure, dv, min_acceleration,
d = create_radial_lfe_sfb_design(payload, pressure, dv, min_acceleration, sfb_allowed,
eng, limit, size, count, sfb, sfbcount)
if d is not None:
designs.append(d)
Expand All @@ -484,7 +496,7 @@ def find_designs(payload, pressure, dv, min_acceleration,
continue
for sfb in parts.SolidFuelBoosters:
for limit in [0, 1/3, 1/2, 2/3, 1]:
d = create_single_lfe_sfb_design(payload, pressure, dv, min_acceleration,
d = create_single_lfe_sfb_design(payload, pressure, dv, min_acceleration, sfb_allowed,
eng, limit, sfb, sfbcount)
if d is not None:
designs.append(d)
Expand Down
10 changes: 9 additions & 1 deletion kspalculator/finder.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@


class Finder(object):
def __init__(self, payload, preferred_radial_size, delta_vs, accelerations, pressures, gimbal,
def __init__(self, payload, preferred_radial_size, delta_vs, accelerations, pressures, sfb_allowed, gimbal,
boosters, electricity, length, monopropellant):
"""Initializes this finder.
Expand All @@ -14,6 +14,7 @@ def __init__(self, payload, preferred_radial_size, delta_vs, accelerations, pres
delta_vs ([float]) - Array of delta-V requirements.
accelerations ([float]) - Array of acceleration requirements.
pressures ([float]) - Array of pressure requirements.
sfb_allowed ([boolean]) - Array of whether SFB are allowed in this flight phase.
gimbal (boolean) - Whether or not to prefer thrust vectoring engines.
boosters (boolean) - Whether or not to include solid boosters.
electricity (boolean) - Whether or not to prefer engines that generate power.
Expand All @@ -31,6 +32,7 @@ def __init__(self, payload, preferred_radial_size, delta_vs, accelerations, pres
self.delta_vs = delta_vs
self.accelerations = accelerations
self.pressures = pressures
self.sfb_allowed = sfb_allowed
self.gimbal = gimbal
self.boosters = boosters
self.electricity = electricity
Expand Down Expand Up @@ -69,13 +71,19 @@ def lint(self):
warnings.append("To launch from Kerbin, your minimum acceleration should be actually "
"higher than the surface gravity.")

sfb_dv_allowed = sum(self.delta_vs[x] for x in range(len(self.delta_vs)) if self.sfb_allowed[x])
if kerbin_launcher and sfb_dv_allowed > 1700:
warnings.append("Solid fuel boosters cannot be shut off for coasting mid-flight during "
"launch. Consider restricting which flight phases they can be used in.")

return warnings

def find(self, best_only=True, order_by_cost=False):
all_designs = find_designs(self.payload,
self.pressures,
self.delta_vs,
self.accelerations,
self.sfb_allowed,
self.preferred_radial_size,
self.gimbal,
self.boosters,
Expand Down

0 comments on commit 9bc1299

Please sign in to comment.