Last active
December 16, 2018 04:38
-
-
Save JonnyOThan/7e29e9556fb7d2694eb912a793270293 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
parameter desired_roll is 0. | |
parameter desired_heading is 90. | |
parameter target_apoapsis is body:atm:height + 10000. | |
parameter g_turn_target_altitude is target_apoapsis + 20000. // slightly higher than target AP | |
parameter throttle_down_altitude is target_apoapsis - 20000. | |
run once "logging.ks". | |
run once "util.ks". | |
log_message("=== ascent ==="). | |
lock throttle to 1. | |
sas off. | |
function g_turn { | |
parameter target_altitude is g_turn_target_altitude. | |
parameter exponent is 0.5. | |
lock steering to R(0, 0, desired_roll) * heading(desired_heading, max(0, 90*(1-(apoapsis/target_altitude)^exponent))). | |
} | |
g_turn(). | |
local old_thrust to ship:maxthrustat(0). | |
local tanks_by_stage to list(). | |
from { local i to 0. } until i = stage:number+1 step {set i to i+1.} do { | |
tanks_by_stage:add(list()). | |
} | |
local all_parts to list(). | |
list parts in all_parts. | |
for p in all_parts { | |
if (p:stage >= 0) { | |
for r in p:resources { | |
if (r:name = "liquidfuel" and r:enabled) { | |
tanks_by_stage[p:stage]:add(p). | |
break. | |
} | |
} | |
} | |
} | |
log_debug(tanks_by_stage). | |
lock gravity to body:mu/(altitude+body:radius)^2. | |
lock twr to (ship:availablethrust / ship:mass / gravity). | |
when apoapsis > throttle_down_altitude and twr > 1 then lock throttle to 0.5. | |
until apoapsis > target_apoapsis { | |
local should_stage to false. | |
if ship:maxthrustat(0) < old_thrust { | |
set should_stage to true. | |
} | |
if stage:number > 1 and not tanks_by_stage[stage:number-1]:empty { | |
local fuel_in_stage to 0. | |
for t in tanks_by_stage[stage:number-1] { | |
for r in t:resources { | |
if r:name = "liquidfuel" { | |
set fuel_in_stage to fuel_in_stage + r:amount. | |
break. | |
} | |
} | |
} | |
if (fuel_in_stage < 0.001) { | |
log_message("empty fuel tank detected."). | |
set should_stage to true. | |
} | |
} | |
if should_stage { | |
if (body:atm:exists and body:atm:altitudepressure(altitude) > 0.01) { | |
lock steering to srfprograde. | |
log_message("turning prograde for staging"). | |
local start_stage_time to time:seconds. | |
wait until vang(ship:facing:vector, srfprograde:vector) < 1 or time:seconds - start_stage_time > 5. | |
} | |
stage_to_next_engine(). | |
set old_thrust to ship:maxthrustat(0). | |
wait 1. | |
log_message("resuming g-turn"). | |
g_turn(). | |
} | |
wait 0.5. | |
} | |
// TODO: fairings | |
lock throttle to 0. | |
wait 0. | |
wait until altitude > body:atm:height. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
run once "logging.ks". | |
run once "util.ks". | |
run once "orbit_util.ks". | |
log_message("=== finish orbit ==="). | |
local engines to get_active_engines(). | |
list engines in all_engines. | |
if (engines_are_vacuum(engines) or engines:length = all_engines:length) { | |
log_message("finishing orbit with this stage"). | |
run plan_circularize. | |
run execute_node. | |
} else { | |
local booster_separation_pe to get_maximum_periapsis_for_destruction(). | |
local booster_sep_sma to (apoapsis + booster_separation_pe + body:radius*2) / 2. | |
local speed_for_booster_sep to get_orbital_speed_at_altitude(apoapsis, booster_sep_sma). | |
local speed_for_orbit to get_orbital_speed_at_altitude(apoapsis, apoapsis + body:radius). | |
local speed_at_ap to get_orbital_speed_at_altitude(apoapsis). | |
local fuel_mass_in_stage to get_fuel_mass_of_current_stage(). | |
local isp to get_combined_isp(engines). | |
local dv_of_stage to isp * g0 * ln(ship:mass / (ship:mass - fuel_mass_in_stage)). | |
local dv_to_booster_sep to speed_for_booster_sep - speed_at_ap. | |
if (dv_of_stage < dv_to_booster_sep) { | |
log_message("booster will expire before maximum_pe - finishing orbit with one node"). | |
run plan_circularize. | |
run execute_node. | |
} else { | |
local dv_for_sep to min(dv_to_booster_sep, dv_of_stage). | |
local speed_after_sep to speed_at_ap + dv_for_sep. | |
local dv_for_orbit to speed_for_orbit - speed_after_sep. | |
log_debug("speed at ap: " + speed_at_ap). | |
log_debug("speed for sep: " + speed_for_booster_sep). | |
log_debug("speed for orbit: " + speed_for_orbit). | |
log_debug("dv of stage: " + dv_of_stage). | |
log_debug("dv for sep: " + dv_for_sep). | |
log_debug("dv for orbit: " + dv_for_orbit). | |
// magic number: if the dv remaining in the booster could get us | |
// to a significant chunk of a mun transfer, keep the booster around | |
// even though it's going to become space trash | |
local wasted_booster_dv to dv_of_stage - dv_for_sep - dv_for_orbit. | |
if (wasted_booster_dv > 500) { | |
log_message("keeping booster because it has " + round(wasted_booster_dv) + " dv remaining"). | |
run plan_circularize. | |
run execute_node. | |
} else { | |
log_message("dropping booster early - leaving " + round(dv_of_stage - dv_for_sep, 1) + " dV behind"). | |
// TODO: need to figure out the total burn time for both burns, and start the first one earlier | |
local apoapsis_time to time:seconds + eta:apoapsis. | |
local n to node(apoapsis_time, 0, 0, dv_for_sep). | |
add n. | |
run execute_node(0). | |
log_debug("executing second half of circularization"). | |
stage_to_next_engine(). | |
set n to node(apoapsis_time, 0, 0, dv_for_orbit). | |
add n. | |
run execute_node. | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
parameter countdown is 3. | |
run once "logging". | |
run once "util.ks". | |
log_message("=== launch ==="). | |
local v0 is getvoice(0). | |
from {local i is countdown.} until i = 0 step { set i to i-1.} do { | |
log_message(i). | |
v0:play(note("f4", 0.1, 0.5)). | |
wait 1. | |
} | |
log_message("0"). | |
v0:play(note("c5", 0.3, 0.5)). | |
sas on. | |
lock throttle to 1. | |
stage. | |
local clamps to ship:modulesnamed("LaunchClamp"). | |
for clamp in clamps { | |
if clamp:part:stage = stage:number-1 { | |
wait until stage:ready. | |
stage. | |
break. | |
} | |
} | |
wait until velocity:surface:mag > 50. | |
sas off. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
run once "util.ks". | |
run once "orbit_util.ks". | |
set h to apoapsis. | |
if h < 0 { | |
set h to periapsis. | |
set duration_until_node to eta:periapsis. | |
} else { | |
set duration_until_node to eta:apoapsis. | |
} | |
log_message("=== circularizing at " + round(h/1000, 1) + "km ==="). | |
run "remove_all_nodes". | |
set necessary_speed to get_orbital_speed_at_altitude(h, h + body:radius). | |
set current_speed to get_orbital_speed_at_altitude(h). | |
set n to node(time:seconds + duration_until_node, 0, 0, necessary_speed - current_speed). | |
add n. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
run once "logging". | |
set g0 to Kerbin:mu / Kerbin:radius^2. | |
lock normal to vcrs(ship:velocity:orbit, -body:position). | |
lock radialin to vcrs(ship:velocity:orbit, normal). | |
function get_active_engines { | |
list engines in all_engines. | |
set result to list(). | |
for e in all_engines | |
if (e:ignition and not e:flameout) result:add(e). | |
return result. | |
} | |
function get_burn_duration { | |
parameter deltav. | |
local engines to get_active_engines(). | |
local isp to get_combined_isp(engines). | |
local final_mass to ship:mass / (constant:e ^ (deltav / g0 / isp)). | |
local fuel_mass_remaining to get_fuel_mass_of_current_stage(). | |
local burn_duration to (ship:mass - final_mass) / get_mass_flow_rate(engines). | |
log_debug("isp: " + isp). | |
log_debug("current mass: " + round(ship:mass, 2)). | |
log_debug("final mass: " + round(final_mass, 2)). | |
log_debug("delta mass: " + round(ship:mass - final_mass, 2)). | |
log_debug("fuel remaining: " + round(fuel_mass_remaining, 2)). | |
log_debug("mass flow rate: " + get_mass_flow_rate(engines)). | |
log_debug("burn time: " + round(burn_duration, 2)). | |
return burn_duration. | |
} | |
function get_with_default { | |
parameter lex. | |
parameter key. | |
parameter default is 0. | |
set result to default. | |
if lex:haskey(key) set result to lex[key]. | |
return result. | |
} | |
function get_fuel_mass_of_current_stage { | |
// WARNING: stage:resourceslex can be wrong! | |
set liquid_fuel to get_with_default(stage:resourceslex, "liquidfuel", 0):amount. | |
set oxidizer to get_with_default(stage:resourceslex, "oxidizer", 0):amount. | |
set density_t_per_L to 5/1000. | |
return density_t_per_L * (liquid_fuel + oxidizer). | |
} | |
function get_combined_isp { | |
parameter engines. | |
set numerator to 0. | |
for e in engines { | |
set numerator to numerator + e:availablethrust. | |
} | |
set mass_flow_rate to get_mass_flow_rate(engines). | |
if mass_flow_rate > 0 | |
return numerator / mass_flow_rate / g0. | |
return 0. | |
} | |
function engines_are_vacuum { | |
parameter engines. | |
local result to true. | |
for e in engines { | |
if (e:ispat(0) / e:ispat(1) < 2) { | |
set result to false. | |
} | |
} | |
return result. | |
} | |
function get_mass_flow_rate { | |
parameter engines. | |
set result to 0. | |
for e in engines | |
set result to result + e:availablethrustat(0) / (e:ispat(0) * g0). | |
return result. | |
} | |
function warp_and_wait { | |
parameter duration. | |
if duration < 0 return. | |
log_message("waiting for " + format_time(duration)). | |
if duration > 10 { | |
kuniverse:timewarp:cancelwarp(). | |
kuniverse:timewarp:warpto(time:seconds + duration - 5). | |
} | |
wait duration. | |
set warp to 0. | |
} | |
function stage_to_next_engine { | |
stage. | |
until ship:maxthrustat(0) > 0 { | |
wait until stage:ready. | |
stage. | |
} | |
wait 0. | |
} | |
function format_time { | |
parameter t. | |
local h to floor(t/60/60). | |
local m to mod(floor(t/60), 60). | |
local s to mod(t, 60). | |
return h + "h" + m + "m" + round(s, 2). | |
} | |
function get_maximum_periapsis_for_destruction { | |
parameter b is body. | |
if b:atm:exists { | |
local upper_bound to b:atm:height. | |
local lower_bound to 0. | |
until upper_bound - lower_bound < 1000 { | |
local midpoint to (upper_bound + lower_bound) / 2. | |
local pressure to b:atm:altitudepressure(midpoint). | |
if pressure > 0.01 { | |
set lower_bound to midpoint. | |
} else { | |
set upper_bound to midpoint. | |
} | |
} | |
return lower_bound. | |
} else { | |
return 0. | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment