From 7431ab7946064fc6e6add79ee26f7a2158c21310 Mon Sep 17 00:00:00 2001 From: Amatsugu Date: Sun, 19 Apr 2026 21:52:07 -0400 Subject: [PATCH] fixed burn time calculations for multi stage burns --- an.ks | 9 +--- boot/faris3Boot.ks | 6 +++ boot/itsukiBoot.ks | 6 +++ boot/koyukiBoot.ks | 6 +++ boot/testBoot.ks | 6 +++ faris.ks | 5 +- faris3.ks | 39 +++++++++++++++ itsuki.ks | 19 ++++++++ koyuki.ks | 17 +++++++ library/lib_ascent.ks | 58 +++++++++++++++------- library/lib_orbits.ks | 82 ++++--------------------------- library/lib_vessel_utils.ks | 97 +++++++++++++++++-------------------- tests.ks | 26 ++++++++-- 13 files changed, 221 insertions(+), 155 deletions(-) create mode 100644 boot/faris3Boot.ks create mode 100644 boot/itsukiBoot.ks create mode 100644 boot/koyukiBoot.ks create mode 100644 boot/testBoot.ks create mode 100644 faris3.ks create mode 100644 itsuki.ks create mode 100644 koyuki.ks diff --git a/an.ks b/an.ks index 7dd0d5b..ab134f1 100644 --- a/an.ks +++ b/an.ks @@ -1,9 +1,4 @@ -import("library/lib_vessel_utils"). import("library/lib_ascent"). -import("library/lib_orbits"). - - - WaitForEngineStart(). @@ -11,9 +6,9 @@ CORE:PART:GETMODULE("kOSProcessor"):DOEVENT("Open Terminal"). set profile to 1.2. set turn_start to 1000. -set target_orbit to 100000. +set target_orbit to 150000. -Ascent(target_orbit, turn_start, profile). +Ascent(target_orbit, turn_start, profile, 0). print "Orbit Achieved, Releasing Controls". CORE:PART:GETMODULE("kOSProcessor"):DOEVENT("Close Terminal"). diff --git a/boot/faris3Boot.ks b/boot/faris3Boot.ks new file mode 100644 index 0000000..4caa914 --- /dev/null +++ b/boot/faris3Boot.ks @@ -0,0 +1,6 @@ +wait until ship:unpacked. +clearscreen. +copyPath("0:/defaults", ""). +run "defaults". + +import("faris3"). \ No newline at end of file diff --git a/boot/itsukiBoot.ks b/boot/itsukiBoot.ks new file mode 100644 index 0000000..aae5da5 --- /dev/null +++ b/boot/itsukiBoot.ks @@ -0,0 +1,6 @@ +wait until ship:unpacked. +clearscreen. +copyPath("0:/defaults", ""). +run "defaults". + +import("itsuki"). \ No newline at end of file diff --git a/boot/koyukiBoot.ks b/boot/koyukiBoot.ks new file mode 100644 index 0000000..6bd3422 --- /dev/null +++ b/boot/koyukiBoot.ks @@ -0,0 +1,6 @@ +wait until ship:unpacked. +clearscreen. +copyPath("0:/defaults", ""). +run "defaults". + +import("koyuki"). \ No newline at end of file diff --git a/boot/testBoot.ks b/boot/testBoot.ks new file mode 100644 index 0000000..f30cd9e --- /dev/null +++ b/boot/testBoot.ks @@ -0,0 +1,6 @@ +wait until ship:unpacked. +clearscreen. +copyPath("0:/defaults", ""). +run "defaults". + +import("tests"). \ No newline at end of file diff --git a/faris.ks b/faris.ks index ac3e7bc..8396f41 100644 --- a/faris.ks +++ b/faris.ks @@ -1,8 +1,6 @@ -import("library/lib_vessel_utils"). import("library/lib_ascent"). -import("library/lib_orbits"). WaitForEngineStart(). @@ -12,9 +10,8 @@ set profile to 1.2. set turn_start to 1000. set target_orbit to 100000. -Ascent(target_orbit, turn_start, profile). +Ascent(target_orbit, turn_start, profile, 1). print "Orbit Achieved, Releasing Controls". -print "Circ DV" + CalculateCircularizationDV(). CORE:PART:GETMODULE("kOSProcessor"):DOEVENT("Close Terminal"). SHUTDOWN. \ No newline at end of file diff --git a/faris3.ks b/faris3.ks new file mode 100644 index 0000000..9bc7250 --- /dev/null +++ b/faris3.ks @@ -0,0 +1,39 @@ + + +import("library/lib_ascent"). + +WaitForEngineStart(). + +CORE:PART:GETMODULE("kOSProcessor"):DOEVENT("Open Terminal"). + +set profile to 1.2. +set turn_start to 1000. +set target_orbit to 100000. + +Ascent(target_orbit, turn_start, profile, 1). +wait 3. + +lock steering to retrograde. +wait 10. +lock throttle to 1. +wait until ship:deltav:current <= 0. +wait 0.01. +stage. + +set kuniverse:timewarp:rate to 10. +wait until kuniverse:timewarp:rate = 0. + +lock steering to srfRetrograde. + +wait until surfaceSpeed < 1000. + +unlock steering. +set kuniverse:timewarp:rate to 5. + +wait until ship:status = "LANDED" or ship:status = "SPLASHED". + +SET V0 TO GETVOICE(0). +V0:PLAY( NOTE(400, 2.5) ). + +CORE:PART:GETMODULE("kOSProcessor"):DOEVENT("Close Terminal"). +SHUTDOWN. \ No newline at end of file diff --git a/itsuki.ks b/itsuki.ks new file mode 100644 index 0000000..9ff02b0 --- /dev/null +++ b/itsuki.ks @@ -0,0 +1,19 @@ + + +import("library/lib_vessel_utils"). +import("library/lib_ascent"). +import("library/lib_orbits"). + +WaitForEngineStart(). + +CORE:PART:GETMODULE("kOSProcessor"):DOEVENT("Open Terminal"). + +set profile to 1.2. +set turn_start to 1000. +set target_orbit to 120000. + +Ascent(target_orbit, turn_start, profile, 0, 73). + +print "Orbit Achieved, Releasing Controls". +CORE:PART:GETMODULE("kOSProcessor"):DOEVENT("Close Terminal"). +SHUTDOWN. \ No newline at end of file diff --git a/koyuki.ks b/koyuki.ks new file mode 100644 index 0000000..a9c5a18 --- /dev/null +++ b/koyuki.ks @@ -0,0 +1,17 @@ + + +import("library/lib_ascent"). + +WaitForEngineStart(). + +CORE:PART:GETMODULE("kOSProcessor"):DOEVENT("Open Terminal"). + +set profile to 1.2. +set turn_start to 1000. +set target_orbit to 130000. + +Ascent(target_orbit, turn_start, profile, 0). + +print "Orbit Achieved, Releasing Controls". +CORE:PART:GETMODULE("kOSProcessor"):DOEVENT("Close Terminal"). +SHUTDOWN. \ No newline at end of file diff --git a/library/lib_ascent.ks b/library/lib_ascent.ks index ca5bde3..666d44b 100644 --- a/library/lib_ascent.ks +++ b/library/lib_ascent.ks @@ -5,16 +5,23 @@ import("library/lib_orbits"). declare function Ascent{ - parameter targetOrbit is 100. + parameter targetOrbit is 100000. parameter vericalAscent is 1000. parameter ascentProfile is 1.2. + parameter circ is 1. + parameter inc is 0. + + print "Params (" + targetOrbit + ", " + vericalAscent + ", " + ascentProfile + ", " + circ + ", " + inc + ")". print "Vertical Climb to " + vericalAscent. - set tgtPitch to 90. + set tgtPitch to 90. + set isDone to false. lock throttle to 1. - lock steering to heading(90, tgtPitch, 270). + local head to 90 + inc. + + lock steering to heading(head, tgtPitch, 270). local lock asccent_prog to Map(apoapsis, 0, targetOrbit, 0.0, 1.0). @@ -25,17 +32,21 @@ declare function Ascent{ local lock tgtPitch to (1 - ease) * 90. when periapsis < targetOrbit then { - print "P: " + round(asccent_prog, 2) + " T:" + round(ease, 2) + " Pitch: " + round(tgtPitch, 2) + " " at(0, 2). - print "Ap: " + round(apoapsis, 2) + " Pe:" + round(periapsis, 2) + " Alt: " + round(altitude, 2) + " " at(0, 3). + print "P: " + round(asccent_prog, 2) + " T:" + round(ease, 2) + " Pitch: " + round(tgtPitch, 2) + " " at(0, 3). + print "Ap: " + round(apoapsis, 2) + " Pe:" + round(periapsis, 2) + " Alt: " + round(altitude, 2) + " " at(0, 4). wait 0.1. - preserve. + if not isDone{ + preserve. + } } //Auto Staging when periapsis < targetOrbit then{ AutoStage(). wait 0.01. - preserve. + if not isDone{ + preserve. + } } wait until apoapsis >= targetOrbit. @@ -44,44 +55,57 @@ declare function Ascent{ lock tgtPitch to 0. unlock steering. + if circ = 1 { + CircularizeBrute(targetOrbit, head). + }else if circ = 2{ + Circularize(targetOrbit, head). + } - CircularizeBrute(targetOrbit). - - + set isDone to true. unlock steering. unlock throttle. + + wait until throttle = 0. } local function Circularize{ parameter targetOrbit. + parameter head. lock throttle to 0. - lock steering to heading(90, 0, 270). + lock steering to heading(head, 0, 270). local warpTime is eta:apoapsis. - local burnDv is CalculateCircularizationDV(). + local burnDv is CalculateCircularizationDV(targetOrbit, orbit:semimajoraxis). local burnDuration is CalculateMultiStageBurnDuration(burnDv). - print "Warping to Circularization. " + round(burnDv) + "m/s. T: " + round(burnDuration, 2) + "s" at(0, 4). - set warpTime to warpTime - burnDuration. + local remDv is ship:deltav:current - burnDv. + print "Warping to Circularization. " + round(burnDv) + "m/s. T: " + round(burnDuration, 2) + "s" at(0, 5). + print "Final Dv expected: " + remDv + "m/s". + set warpTime to warpTime - burnDuration /2. if warpTime > 0 { wait until throttle = 0. wait 0.01. //Wait for accelleration to stop - warpTo(time:seconds + warpTime). + set warpmode to "physics". + warpTo(time:seconds + warpTime - 3). + wait until eta:apoapsis >= burnDuration /2. } - wait until eta:apoapsis <= burnDuration. lock throttle to 1. + // wait burnDuration. wait until periapsis >= targetOrbit. lock throttle to 0. + + wait 0.01. } local function CircularizeBrute{ parameter targetOrbit. + parameter head. lock throttle to 1. - lock steering to heading(90, 0, 270). + lock steering to heading(head, 0, 270). wait until periapsis >= targetOrbit. lock throttle to 0. } diff --git a/library/lib_orbits.ks b/library/lib_orbits.ks index 826fc23..49c4c7b 100644 --- a/library/lib_orbits.ks +++ b/library/lib_orbits.ks @@ -5,84 +5,22 @@ declare function CreateDeorbit{ parameter offsetX is 0.0. parameter offsetZ is 0.0. - local tol to 100. - - lock steering to retrograde. - local lock align to vDot(ship:facing:vector, retrograde:vector). - wait until align > 0.95. - print align. - - if dv > 0 { - set dv to dv * -1. - } - - local tr to ADDONS:TR. - if not tr:AVAILABLE { - print "Trajectoris is not available". - return. - } - - tr:settarget(target). - - - local deorbit to NODE(time:seconds + 200, 0, 0, dv). - - until not hasNode{ - remove nextNode. - wait 0.001. - } - - add deorbit. - wait until tr:hasimpact. - - local ipos to tr:impactpos. - local lock offset to (ipos:ALTITUDEPOSITION(0) - target:ALTITUDEPOSITION(0)). - local lock xDist to offset:x. - local lock zDist to ipos:lat - target:lat. - local dt is 60. - when xDist < 500000 then{ - set dt to 30. - } - when xDist < 100000 then{ - set dt to 5. - } - when xDist < 10000 then{ - set dt to 1. - } - when xDist < 5000 then{ - set dt to 0.5. - } - until xDist < offsetX + tol { - remove nextNode. - wait 0.001. - set deorbit:eta to deorbit:eta + dt. - add deorbit. - wait until tr:hasimpact. - set ipos to tr:impactpos. - wait 0.001. - } - until abs(zDist) < offsetZ + tol{ - remove nextNode. - wait 0.001. - if zDist > 0 { - set deorbit:normal to deorbit:normal - 0.1. - } else{ - set deorbit:normal to deorbit:normal + 0.1. - } - add deorbit. - wait until tr:hasimpact. - set ipos to tr:impactpos. - } - - unlock steering. } declare function CalculateCircularizationDV{ + parameter ap is 0. + parameter sma is 0. local mu is body:mu. + if ap = 0 { + set ap to apoapsis. + } + if sma = 0 { + set sma to orbit:semimajoraxis. + } - local apR is apoapsis + body:radius. + local apR is ap + body:radius. local circVel is sqrt(mu / apR). - local apVel is sqrt(mu * ((2 / apR) - (1 / orbit:semimajoraxis))). + local apVel is sqrt(mu * ((2 / apR) - (1 / sma))). return circVel - apVel. } diff --git a/library/lib_vessel_utils.ks b/library/lib_vessel_utils.ks index 8781ec3..e18a0a2 100644 --- a/library/lib_vessel_utils.ks +++ b/library/lib_vessel_utils.ks @@ -16,8 +16,8 @@ declare function GetDragDir{ } declare function AnyEngineActive{ - list engines in allEngines. - for eng in allEngines{ + list engines in egs. + for eng in egs{ if eng:ignition { return true. } @@ -26,11 +26,11 @@ declare function AnyEngineActive{ } declare function GetIsp{ - LIST ENGINES IN allEngines. + LIST ENGINES IN egs. declare local totalThrust is ship:maxThrust. local sum is 0. local weights is 0. - for eng in allEngines{ + for eng in egs{ if eng:IGNITION and not eng:flameout{ local w is eng:AVAILABLETHRUST / totalThrust. local ispW is eng:isp * w. @@ -42,15 +42,18 @@ declare function GetIsp{ } declare function GetIspForStage{ - parameter engineState. + parameter engineStage. parameter pressure is 0. - LIST ENGINES IN allEngines. - local totalThrust is GetThrustOfStage(engineState). + LIST ENGINES IN egs. + local totalThrust is GetThrustOfStage(engineStage, pressure). + if totalThrust = 0{ + return 0. + } local sum is 0. local weights is 0. - for eng in allEngines{ - if eng:stage = engineState { - local w is eng:POSSIBLETHRUST / totalThrust. + for eng in egs{ + if eng:stage = engineStage { + local w is eng:POSSIBLETHRUSTAT(pressure) / totalThrust. local ispW is eng:ispat(pressure) * w. set sum to sum + ispW. set weights to weights + w. @@ -60,9 +63,9 @@ declare function GetIspForStage{ } declare function GetMaxMassFlow{ - LIST ENGINES IN allEngines. + LIST ENGINES IN egs. local sum is 0. - for eng in allEngines{ + for eng in egs{ if eng:IGNITION and not eng:flameout{ set sum to sum + eng:maxmassflow. } @@ -70,6 +73,18 @@ declare function GetMaxMassFlow{ return sum. } +declare function GetMaxMassFlowForStage{ + parameter engineStage. + LIST ENGINES IN egs. + local sum is 0. + for eng in egs{ + if eng:stage = engineStage { + set sum to sum + eng:maxmassflow. + } + } + return sum. +} + @@ -86,9 +101,12 @@ declare function CalculateBurnDuration parameter initialMass. parameter massFlow. + if burnIsp = 0 { + return 0. + } set dv to abs(dv). local exp is -dv / (burnIsp * constant:g0). - local massRatio is ApproximateExp(-exp). + local massRatio is constant:e ^ (-exp). local finalMass is initialMass / massRatio. local fuelUsed is initialMass - finalMass. @@ -151,67 +169,43 @@ declare function CalculateTimeToImpact{ function CalculateMultiStageBurnDuration{ parameter dv. - if ship:deltav:current >= dv { - print "one stage" at (0, 5). - return GetBurnTime(dv, ship:maxthrust, ship:mass). + if ship:STAGEDELTAV(ship:stagenum):current >= dv { + return CalculateBurnDuration(dv, GetIsp(), ship:mass, GetMaxMassFlow()). }else{ - print "multi stage" at (0, 5). local burnTime is 0. local remDv is dv. - from {local s is ship:stagenum. } until s = 0 step { set s to s-1.} do { + from {local s is ship:stagenum. } until s = -1 step { set s to s-1.} do { if remDv <= 0 { return burnTime. } local cdv is ship:stagedeltav(s):current. local cmass is GetMassOfStage(s). - local cthrust is GetThrustOfStage(s). + local cflow is GetMaxMassFlowForStage(s). local cisp is GetIspForStage(s). + local sdv is 0. + print cdv. if cdv >= remDv { - set burnTime to burnTime + GetBurnTime(remDv, cmass, cthrust, cisp). + set sdv to remDv. }else{ - set burnTime to burnTime + GetBurnTime(cdv, cmass, cthrust, cisp). + set sdv to cdv. } + set burnTime to burnTime + CalculateBurnDuration(sdv, cisp, cmass, cflow). set remDv to remDv - cdv. } return burnTime. } } -// Burn time from rocket equation -function GetBurnTime { - parameter deltaV. - parameter stagethrust is 0. - parameter stagemass is 0. - parameter isp is 0. - - if deltaV:typename() = "Vector" { - set deltaV to deltaV:mag. - } - if isp = 0 { - set isp to GetIsp(). - } - if stagethrust = 0 { - set stagethrust to ship:thrust. - } - if stagemass = 0 { - set stagemass to ship:mass. - } - - local burnTime is -1. - if stagethrust <> 0 { - set burnTime to stagemass * (1 - CONSTANT:E ^ (-deltaV / isp)) / (stagethrust / isp). - } - return burnTime. -} function GetThrustOfStage { parameter st. + parameter pressure is 0. local totalThrust is 0. - LIST ENGINES IN allEngines. - for eng in allEngines{ + LIST ENGINES IN egs. + for eng in egs{ if eng:stage = st { - set totalThrust to totalThrust + eng:POSSIBLETHRUST. + set totalThrust to totalThrust + eng:POSSIBLETHRUSTAT(pressure). } } return totalThrust. @@ -219,12 +213,11 @@ function GetThrustOfStage { function GetMassOfStage { parameter st. - local total is 0. LIST PARTS IN allP. for p in allP { - if p:stage <= st { + if p:stage <= st and p:DECOUPLEDIN < st { set total to total + p:mass. } } diff --git a/tests.ks b/tests.ks index ea30fa6..a971ce7 100644 --- a/tests.ks +++ b/tests.ks @@ -1,6 +1,26 @@ -run "library/lib_vessel_utils". +import("library/lib_vessel_utils"). CORE:PART:GETMODULE("kOSProcessor"):DOEVENT("Open Terminal"). -print "impact " + CalculateTimeToImpact(300, 500, 9.8). -print "Burn Duration" + CalculateBurnDuration(300, 350, 5000, 3000). \ No newline at end of file +print "Waiting for Engine start". +WaitForEngineStart(). + + +function printStatge { + parameter s is ship:stagenum. + local curDv is ship:STAGEDELTAV(s):current. + local isp is GetIspForStage(s). + local smass is GetMassOfStage(s). + local flow is GetMaxMassFlowForStage(s). + local thrust is GetThrustOfStage(s). + + print "------ Stage: " + s + " ------". + print "Thrust: " + thrust + "kN Mass: " + round(smass, 3) + "t". + print "DV: " + round(curDv, 2) + "m/s ISP: " + round(isp, 2) + "s Flow: " + round(flow, 4) + "Mg/s". + print "Burn Duration: " + round(CalculateBurnDuration(curDv, isp, smass, flow), 2). +} + +// printStatge(ship:stagenum). +// printStatge(ship:stagenum - 1). + +print "Total Burn Time: " + CalculateMultiStageBurnDuration(ship:deltav:current). \ No newline at end of file