diff --git a/init/rocket.ks b/init/rocket.ks index 1acc9f0..4b8ce10 100644 --- a/init/rocket.ks +++ b/init/rocket.ks @@ -51,6 +51,9 @@ makeButton(row, "NODE", { if HASNODE { set nodeDV:TEXT to NEXTNODE:DELTAV:MAG:ToString. set nodeBT:TEXT to BurnTime(NEXTNODE:DELTAV:MAG):ToString. + } else { + set nodeDV:TEXT to "No Node". + set nodeBT:TEXT to "No Node". } stk:ShowOnly(panes["node"]). }). diff --git a/lib/node.ks b/lib/node.ks index 55aec27..335ad2d 100644 --- a/lib/node.ks +++ b/lib/node.ks @@ -1,8 +1,14 @@ -runoncepath("lib/navigation"). -runoncepath("lib/throttle"). function ExecNode { + if not HASNODE { + print "No node to execute.". + return. + } + SAS off. + + // begin the burn at leadT seconds before the node. + local leadT is BurnTime(NEXTNODE:DELTAV:MAG / 2). local t is BurnTime(NEXTNODE:DELTAV:MAG). print "Adjusting heading". @@ -10,30 +16,91 @@ function ExecNode { wait until VAng(SHIP:FACING:FOREVECTOR, STEERINGMANAGER:TARGET:FOREVECTOR) <= 0.1. print "Warping to node.". - KUNIVERSE:TIMEWARP:WarpTo(NEXTNODE:TIME - (t/2) - 5). - wait until NEXTNODE:ETA <= (t/2). + KUNIVERSE:TIMEWARP:WarpTo(NEXTNODE:TIME - leadT - 5). + wait until NEXTNODE:ETA <= leadT. print "Executing burn.". local dvMin is NEXTNODE:DELTAV:MAG. lock THROTTLE to 1.0. - - // Execute the burn, throttling down by half every time we're - // consuming more than 25% of our dV in one update. - local droppedOnce is false. - until NEXTNODE:DELTAV:MAG <= 0.25 or (dVMin < NEXTNODE:DELTAV:MAG and droppedOnce) { - - if NEXTNODE:DELTAV:MAG > dVMin { - set droppedOnce to true. - } else { - set dvMin to NEXTNODE:DELTAV:MAG. - set droppedOnce to false. - } - - wait 0.01. - } + wait t. + lock THROTTLE to 0.0. unlock THROTTLE. unlock STEERING. SAS on. print "Node execution complete.". } + +// Calculate the time required to burn a given dV. +// Assumes a perfectly spherical Kerbal in a vacuum. +function BurnTime { + parameter totaldV, m is SHIP:MASS, s is STAGE:NUMBER. + local totalT is 0.0. + + until totaldV <= 0 { + local F is stageThrust(). + local Isp is stageISP(). + local dV is min(totaldV, SHIP:StageDeltaV(s):VACUUM). + local t is calcBurnTime(dV, m, Isp, F). + print "DEBUG: " + dV + " m/s^2 in stage " + s + ", in " + t + " seconds.". + set totaldV to totaldV - dV. + set s to s - 1. + set totalT to totalT + t. + } + + return totalT. +} + +// Convenience function to wrap the actual calculation for burn time. +function calcBurnTime { + parameter dV, m, Isp, F. + + if F = 0 { + print "WARNING: Tried to calculate burn time with a thrust of 0. Returning 0. Your calculations are probably wrong.". + return 0. + } + + local g0 is CONSTANT:G0. + return g0 * m * Isp * (1 - CONSTANT():E^(-dV/(g0*Isp))) / F. +} + +// Calculate the ISP for a given stage. +// Defaults to current stage. Assumes your ship is designed so that +// engines are discarded immediately when they flame out. +function stageISP { + parameter s is STAGE:NUMBER. + + local en is list(). + list ENGINES in en. + + local ispSum is 0. + local eCount is 0. + for e in en { + if e:STAGE >= s and e:DECOUPLEDIN < s { + set ispSum to ispSum + e:ISP. + set eCount to eCount + 1. + } + } + if eCount = 0 { return 0. } + + return ispSum / eCount. +} + +// Calculates the total thrust for the given stage, in kN. +// Defaults to current stage. Assumes your ship is designed so that +// engines are discarded immediately when they flame out. +function stageThrust { + parameter s is STAGE:NUMBER. + + local en is list(). + list ENGINES in en. + + local sum is 0. + for e in en { + if e:STAGE >= s and e:DECOUPLEDIN < s { + set sum to sum + e:POSSIBLETHRUST. + } + } + + return sum. +} diff --git a/lib/throttle.ks b/lib/throttle.ks index 3ab0db7..1cf2bf7 100644 --- a/lib/throttle.ks +++ b/lib/throttle.ks @@ -19,101 +19,3 @@ function TWR { local t is THROTTLE * SHIP:AVAILABLETHRUST. return t/(m*G). } - -// Calculate the time required to burn a given dV at a given altitude. -// Must be called while in the same SOI as the burn itself. -// Assumes a perfectly spherical Kerbal in a vacuum. -function BurnTime { - parameter dV, m is SHIP:MASS, s is STAGE:NUMBER. - - local f is stageThrust(). // Engine Thrust (kg * m/s²) - local Isp is stageISP(). // Engine ISP (s) - - local dVs is SHIP:StageDeltaV(s):VACUUM. - if dV > dVs { - // TODO: not 100% this is needed vs using DeltaV:DURATION. - // Docs suggest DeltaV:DURATION is not entirely reliable, however. - // For now we're logging both values for comparison. - local t is burnTimeCalc(dVs, m, Isp, f). - - // debug - print "Computed stage burn time = " + t. - print "KSC-estimated stage burn time = " + SHIP:StageDeltaV(s):DURATION. - // end debug - - local parts is list(). - for part in parts { - if part:DECOUPLEDIN = s - 1 { - set m to m - part:MASS. - } - } - - return t + BurnTime(dV - SHIP:STAGEDELTAV(s):VACUUM, m, s - 1). - } - - // debug - local t is burnTimeCalc(dV, m, Isp, f). - print "Burn time in last utilized stage = " + t. - // end debug - - return t. -} - -// Convenience function to wrap the actual calculation for burn time. -function burnTimeCalc { - parameter dV, m, Isp, f. - - if f = 0 { - print "WARNING: Tried to calculate burn time with a thrust of 0. Returning 0. Your calculations are probably wrong.". - return 0. - } - - // TODO: this formula differs from the following: - // t = ((M0 - Mf) * Isp * G) / f - // which is suggested at https://www.reddit.com/r/Kos/comments/lev9pw/getting_burntime_from_next_stage/gmig0hl/?context=8&depth=9 - // are they equivalent? Is one better than the other? This one doesn't require - // knowing final mass, which is nice. - local g0 is CONSTANT:G0. - return g0 * m * Isp * (1 - CONSTANT():E^(-dV/(g0*Isp))) / f. -} - -// Calculate the ISP for a given stage. -// Defaults to current stage. Assumes your ship is designed so that -// engines are discarded immediately when they flame out. -function stageISP { - parameter s is STAGE:NUMBER. - - local en is list(). - list ENGINES in en. - - local ispSum is 0. - local eCount is 0. - for e in en { - if e:STAGE = s or e:STAGE > s and e:DECOUPLEDIN < s { - set ispSum to ispSum + e:ISP. - set eCount to eCount + 1. - } - } - if eCount = 0 { return 0. } - - return ispSum / eCount. -} - -// Calculates the total thrust for the given stage, in kN. -// Defaults to current stage. Assumes your ship is designed so that -// engines are discarded immediately when they flame out. -function stageThrust { - parameter s is STAGE:NUMBER. - - local en is list(). - list ENGINES in en. - - local sum is 0. - for e in en { - if e:STAGE = s or e:STAGE > s and e:DECOUPLEDIN < s { - set sum to sum + e:POSSIBLETHRUST. - } - } - - return sum. -}