diff --git a/execnode.ks b/execnode.ks index dd5f0fa..db3bed3 100644 --- a/execnode.ks +++ b/execnode.ks @@ -15,18 +15,25 @@ wait until NEXTNODE:ETA <= (t/2). // todo: pid loop here or nah? overshoot would be tricky to deal with... print "Executing burn.". +local dvMin is NEXTNODE:DELTAV:MAG. local throt is 1.0. lock THROTTLE to throt. -local dvLast is NEXTNODE:DELTAV:MAG. + +// debug +print "dVMin = " + dvMin. +print "dV = " + NEXTNODE:DELTAV:MAG. // Execute the burn, throttling down by half every time we're // consuming more than 25% of our dV in one update. -until NEXTNODE:DELTAV:MAG <= 0.25 { - local dvRem is NEXTNODE:DELTAV:MAG. - if dvRem < dvLast * 0.75 { - set throt to throt / 2. +until NEXTNODE:DELTAV:MAG <= 0.25 or dVMin < NEXTNODE:DELTAV:MAG { + // debug + print "dVMin = " + dvMin. + print "dV = " + NEXTNODE:DELTAV:MAG. + + if NEXTNODE:DELTAV:MAG < dVMin { + set dvMin to NEXTNODE:DELTAV:MAG. } - set dvLast to dvRem. + wait 0.001. } @@ -34,3 +41,8 @@ unlock THROTTLE. unlock STEERING. SAS on. print "Node execution complete.". + +// debug +print "Final dVMin = " + dvMin. +print "Final dV = " + NEXTNODE:DELTAV:MAG. + diff --git a/launch.ks b/launch.ks index 6cc02e5..09ce17d 100644 --- a/launch.ks +++ b/launch.ks @@ -45,11 +45,13 @@ wait until vectorangle( STEERINGMANAGER:TARGET:FOREVECTOR) < 0.5. -// then wait until Prograde catches up. -wait until vectorangle( - SHIP:SRFPROGRADE:FOREVECTOR, - STEERINGMANAGER:TARGET:FOREVECTOR) - < 0.5. +// then wait until Prograde catches up (or passes us). +local targetPitch is GetPitch(STEERINGMANAGER:TARGET:FOREVECTOR). +wait until GetPitch(SHIP:SRFPROGRADE:FOREVECTOR) <= targetPitch. +// wait until vectorangle( +// SHIP:SRFPROGRADE:FOREVECTOR, +// STEERINGMANAGER:TARGET:FOREVECTOR) +// < 0.5. print "Locking to prograde, letting gravity do the hard work.". lock STEERING to GetAscentVector(MINIMUM_PITCH). diff --git a/lib/throttle.ks b/lib/throttle.ks index 70e19a9..a60720e 100644 --- a/lib/throttle.ks +++ b/lib/throttle.ks @@ -1,7 +1,8 @@ // Functions for calculating thrust values. @lazyglobal off. -local G is 9.81. +// point gravity for TWR calculations. +local G is 0. lock G to SHIP:BODY:MU / ((SHIP:BODY:RADIUS+SHIP:ALTITUDE)^2). // Returns the throttle value you should use to achieve the @@ -22,25 +23,21 @@ function TWR { // 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, a, m is SHIP:MASS, s is STAGE:NUMBER. + parameter dV, m is SHIP:MASS, s is STAGE:NUMBER. - local Gb is SHIP:BODY:MU / ((SHIP:BODY:RADIUS+a)^2). local f is stageThrust(). // Engine Thrust (kg * m/s²) local Isp is stageISP(). // Engine ISP (s) - // debug - print "Calculating burn time.". - print "dV = " + dV. - print "f = " + f. - print "m = " + m. - print "e = " + e. - print "Isp = " + Isp. - print "Gb = " + Gb. - // end debug - - if dV > SHIP:STAGEDELTAV(s) { - local t is burnTimeCalc(SHIP:STAGEDELTAV(s), m, Gb, Isp, f). + 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). + print "Computed stage burn time = " + t. + print "KSC-estimated stage burn time = " + SHIP:StageDeltaV(s):DURATION. local parts is list(). for part in parts { @@ -49,15 +46,15 @@ function BurnTime { } } - return t + BurnTime(dV - SHIP:STAGEDELTAV(s), a, m, s - 1). + return t + BurnTime(dV - SHIP:STAGEDELTAV(s):VACUUM, m, s - 1). } - return burnTimeCalc(dV, m, Gb, Isp, f). + return burnTimeCalc(dV, m, Isp, f). } // Convenience function to wrap the actual calculation for burn time. function burnTimeCalc { - parameter dV, m, Gb, Isp, f. + 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.". @@ -69,7 +66,8 @@ function burnTimeCalc { // 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. - return Gb * m * Isp * (1 - CONSTANT():E^(-dV/(Gb*Isp))) / f. + local g0 is CONSTANT:G0. + return g0 * m * Isp * (1 - CONSTANT():E^(-dV/(g0*Isp))) / f. } // Calculate the ISP for a given stage. diff --git a/ui/rocket.ks b/ui/rocket.ks index 0f6b588..d16df54 100644 --- a/ui/rocket.ks +++ b/ui/rocket.ks @@ -1,4 +1,13 @@ +runoncepath("/lib/navigation"). + function launchButtonPressed { + // adjust torque settings here... + local oldEpsilon is STEERINGMANAGER:TORQUEEPSILONMAX. + set STEERINGMANAGER:TORQUEEPSILONMAX to maxEpsilon:TEXT:ToNumber(). + + local oldStopTime is STEERINGMANAGER:MAXSTOPPINGTIME. + set STEERINGMANAGER:MAXSTOPPINGTIME to maxStopTime:TEXT:ToNumber(). + run "launch"( targetApo:TEXT:ToNumber(), gravTurnStart:TEXT:ToNumber(), @@ -6,67 +15,99 @@ function launchButtonPressed { initialPitch:TEXT:ToNumber(), minimumPitch:TEXT:ToNumber() ). + + set STEERINGMANAGER:TORQUEEPSILONMAX to oldEpsilon. + set STEERINGMANAGER:MAXSTOPPINGTIME to oldStopTime.. } -function nodeButtonPressed { +function executeNode { run "execnode". } -local termOn is false. -function terminalButtonPressed { - if termOn { - CORE:PART:GETMODULE("kOSProcessor"):DOEVENT("Close Terminal"). - set termOn to false. - } else { - CORE:PART:GETMODULE("kOSProcessor"):DOEVENT("Open Terminal"). - set termOn to true. - } +function showLaunchMenu { + stk:ShowOnly(launchMenu). } // Main UI. -local interface is gui(200). +local interface is gui(250, 300). set interface:X to 200. -set interface:Y to 800. +set interface:Y to 700. -// Launch button -local hBox is interface:AddHBox(). -hBox:AddLabel("Initial Pitch"). -local initialPitch is hBox:AddTextField("85"). +// Main menu elements in here. +local box is interface:AddVBox(). -local hBox is interface:AddHBox(). -hBox:AddLabel("Minimum Pitch"). -local minimumPitch is hBox:AddTextField("5"). +local btn is box:AddButton("TERM"). +set btn:TOGGLE to true. +set btn:ONTOGGLE to { + parameter activate. -local hBox is interface:AddHBox(). -hBox:AddLabel("Gravity Turn @"). -local gravTurnStart is hBox:AddTextField("8000"). + if activate { + CORE:PART:GETMODULE("kOSProcessor"):DOEVENT("Open Terminal"). + } else { + CORE:PART:GETMODULE("kOSProcessor"):DOEVENT("Close Terminal"). + } +}. -local hBox is interface:AddHBox(). -hBox:AddLabel("Gravity Pitch"). -local gravPitch is hBox:AddTextField("75"). +set btn to box:AddButton("LAUNCH"). +set btn:onClick to showLaunchMenu@. -local hBox is interface:AddHBox(). -hBox:AddLabel("Target Apoapsis"). -local targetApo is hBox:AddTextField("80000"). +set btn to box:AddButton("CIRC"). +set btn:onClick to { add CreateCircularizationNode(). }. -local launchButton is interface:AddButton("Launch"). -set launchButton:onClick to launchButtonPressed@. +set btn to box:AddButton("EXECNODE"). +set btn:onClick to executeNode@. -local nodeButton is interface:AddButton("Execute Node"). -set nodeButton:onClick to nodeButtonPressed@. +local stk is interface:AddStack(). -local termButton is interface:AddButton("Terminal"). -set termButton:onClick to terminalButtonPressed@. +// Launch menu +local launchMenu is stk:AddVLayout(). -// debug -function circButtonPressed { - runpath("/lib/navigation"). - add CreateCircularizationNode(). -} -local cButton is interface:AddButton("Circularize"). -set cButton:onClick to circButtonPressed@. -// end debug +set btn to launchMenu:AddButton("Execute"). +set btn:onClick to launchButtonPressed@. + +local launchConfig is box:AddScrollBox(). +// set launchConfig:STYLE:WIDTH to 300. +// set launchConfig:STYLE:HEIGHT to 800. + +set sbox to launchConfig:AddHBox(). +sbox:AddLabel("Target Apoapsis"). +local targetApo is sbox:AddTextField("80000"). + +set sbox to launchConfig:AddHBox(). +sbox:AddLabel("Atmo TWR"). +local targetTWR is sbox:AddTextField("1.6"). + +set sbox to launchConfig:AddHBox(). +sbox:AddLabel("Initial Pitch"). +local initialPitch is sBox:AddTextField("85"). + +set sbox to launchConfig:AddHBox(). +sbox:AddLabel("Minimum Pitch"). +local minimumPitch is sbox:AddTextField("5"). + +set sbox to launchConfig:AddHBox(). +sbox:AddLabel("Gravity Turn Alt"). +local gravTurnStart is sbox:AddTextField("8000"). + +set sbox to launchConfig:AddHBox(). +sbox:AddLabel("Gravity Turn Pitch"). +local gravPitch is sbox:AddTextField("75"). + +launchConfig:AddSpacing(5). + +set sbox to launchConfig:AddHBox(). +sbox:AddLabel("Torque Epsilon Max"). +local maxEpsilon is sbox:AddTextField("0.001"). + +set sbox to launchConfig:AddHBox(). +sbox:AddLabel("Max Stopping Time"). +local maxStopTime is sbox:AddTextField("2.0"). + +// End Launch Menu interface:show(). + + + wait until false.