Compare commits

..

4 Commits

Author SHA1 Message Date
kcjennin dceeddfcf1 feat: overhaul lander suicide burn, add transfer GUI, improve ascent fairing logic
- lander.ks: Replace fixed suicide burn with dynamic throttle control using
  vertical fraction, gateRatio, and finalPhase logic; simplify post-land
  sequence to SAS stabilityassist
- transfer.ks: Replace hardcoded Mun target with GUI popup menu populated
  from body:orbitingchildren
- ascent.ks: Change fairing jettison trigger from dynamic pressure to
  altitude > atm height; guard antenna extension with hasmodule check
- basic.ks: Append stayRunner invocation at end of script
- boot/boot.ks: Remove commented RT connection block; add newline before runPath
- boot/testing.ks: Switch to volume 0 and use relative paths for transfer
  and doManeuver scripts
- boot/heloBoot.ks: Delete unused boot file
2026-06-26 17:44:06 -07:00
kcjennin 36fc515c23 ignorefile changes 2026-06-08 23:35:23 -07:00
kcjennin a936077187 Initial transfer file and some other improvements 2026-06-08 23:28:21 -07:00
kcjennin ef8ae9e9cc Remove RT and tweaked ascent profile 2026-06-07 01:41:03 -07:00
12 changed files with 470 additions and 73 deletions
+1
View File
@@ -1 +1,2 @@
logs
*.code-workspace
+1 -4
View File
@@ -1,6 +1,3 @@
wait until ship:unpacked.
if addons:RT:hasKSCConnection(ship) {
runPath("0:/scripts/basic.ks").
} else {
print "No connection to the KSC".
}
+3
View File
@@ -0,0 +1,3 @@
wait until ship:unpacked.
runPath("0:/scripts/stayRunner.ks").
-2
View File
@@ -1,2 +0,0 @@
wait until ship:unpacked.
runPath("0:/scripts/helo.ks").
+7
View File
@@ -0,0 +1,7 @@
wait until ship:unpacked.
core:part:getmodule("kOSProcessor"):doevent("Open Terminal").
switch to 0.
cd("scripts").
runPath("transfer").
runPath("doManeuver").
+227
View File
@@ -0,0 +1,227 @@
{
"spec_version": "v1.6",
"identifier": "installed-Kerbal-Space-Program",
"name": "installed-Kerbal Space Program",
"abstract": "A list of modules installed on the Kerbal Space Program KSP instance",
"author": "Kyle",
"version": "2026.06.27.12.43.24",
"ksp_version_min": "1.8",
"ksp_version_max": "1.12",
"license": "unknown",
"depends": [
{
"name": "ContractConfigurator",
"suppress_recommendations": true
},
{
"name": "ClickThroughBlocker",
"suppress_recommendations": true
},
{
"name": "ReStock",
"suppress_recommendations": true
},
{
"name": "EnvironmentalVisualEnhancements",
"suppress_recommendations": true
},
{
"name": "Kerbalism",
"suppress_recommendations": true
},
{
"name": "AtmosphereAutopilot",
"suppress_recommendations": true
},
{
"name": "ContractConfigurator-CareerEvolution",
"suppress_recommendations": true
},
{
"name": "Chatterer",
"suppress_recommendations": true
},
{
"name": "ContractConfigurator-CommNetRelays",
"suppress_recommendations": true
},
{
"name": "ConfigurableContainers",
"suppress_recommendations": true
},
{
"name": "ContractConfigurator-AnomalySurveyor",
"suppress_recommendations": true
},
{
"name": "ContractConfigurator-KerbinSpaceStation",
"suppress_recommendations": true
},
{
"name": "ContractConfigurator-CleverSats",
"suppress_recommendations": true
},
{
"name": "ContractConfigurator-ExplorationPlus",
"suppress_recommendations": true
},
{
"name": "ContractConfigurator-FieldResearch",
"suppress_recommendations": true
},
{
"name": "ContractConfigurator-KerbalAcademy",
"suppress_recommendations": true
},
{
"name": "ContractConfigurator-RoverMissionsRedux",
"suppress_recommendations": true
},
{
"name": "ContractConfigurator-Tourism",
"suppress_recommendations": true
},
{
"name": "ContractsWindowPlus",
"suppress_recommendations": true
},
{
"name": "DecouplerShroud",
"suppress_recommendations": true
},
{
"name": "Deferred",
"suppress_recommendations": true
},
{
"name": "EnvironmentalVisualEnhancements-HR",
"suppress_recommendations": true
},
{
"name": "HeatControl",
"suppress_recommendations": true
},
{
"name": "HideEmptyTechNodes",
"suppress_recommendations": true
},
{
"name": "KerbalAlarmClock",
"suppress_recommendations": true
},
{
"name": "KerbalChangelog",
"suppress_recommendations": true
},
{
"name": "KerbalEngineerRedux",
"suppress_recommendations": true
},
{
"name": "KerbalismCompanionCalculator",
"suppress_recommendations": true
},
{
"name": "kOS",
"suppress_recommendations": true
},
{
"name": "KRASH",
"suppress_recommendations": true
},
{
"name": "MinAmbLightUpd",
"suppress_recommendations": true
},
{
"name": "NavballDockAlignIndCE",
"suppress_recommendations": true
},
{
"name": "NearFutureElectrical",
"suppress_recommendations": true
},
{
"name": "OPMAllinOneKSPediaDeltaVMap",
"suppress_recommendations": true
},
{
"name": "ParallaxContinued",
"suppress_recommendations": true
},
{
"name": "PatchManager",
"suppress_recommendations": true
},
{
"name": "PlanetInfoPlus",
"suppress_recommendations": true
},
{
"name": "ProbesBeforeCrew",
"suppress_recommendations": true
},
{
"name": "RCSBuildAid",
"suppress_recommendations": true
},
{
"name": "RestockWaterfallExpansion",
"suppress_recommendations": true
},
{
"name": "ReStockPlus",
"suppress_recommendations": true
},
{
"name": "SCANsat",
"suppress_recommendations": true
},
{
"name": "Scatterer",
"suppress_recommendations": true
},
{
"name": "SmartParts",
"suppress_recommendations": true
},
{
"name": "Strategia",
"suppress_recommendations": true
},
{
"name": "TextureReplacer",
"suppress_recommendations": true
},
{
"name": "JanitorsCloset",
"suppress_recommendations": true
},
{
"name": "Trajectories",
"suppress_recommendations": true
},
{
"name": "TransferWindowPlannerFork",
"suppress_recommendations": true
},
{
"name": "TriggerAu-Flags",
"suppress_recommendations": true
},
{
"name": "TUFX",
"suppress_recommendations": true
},
{
"name": "UtilityWeight",
"suppress_recommendations": true
},
{
"name": "WaypointManager",
"suppress_recommendations": true
}
],
"release_date": "2026-06-27T00:43:24.0386872Z",
"kind": "metapackage"
}
+66 -22
View File
@@ -13,6 +13,47 @@ function signedHeading {
return mod(hdg + 360, 360).
}
function gravityTurn {
parameter targetHeading.
set tarSteer to heading(targetHeading, 90).
lock steering to tarSteer.
until ship:velocity:surface:mag >= 100 {
set tarSteer to heading(targetHeading, 90 - (ship:velocity:surface:mag / 20)).
wait 0.
}
// lock steering to the target heading, but account for drift, and the pitch
// of the surface normal vector
lock calculatedHeading to mod(targetHeading + 2 * (targetHeading - signedHeading()) + 360, 360).
lock steering to heading(
calculatedHeading,
max(5, 90 - vAng(up:vector, ship:srfprograde:vector))
).
print "Locked steering to surface prograde pitch and target heading".
}
// function structuredAscent {
// parameter targetHeading.
// set tarSteer to heading(targetHeading, 90).
// lock steering to tarSteer.
// until ship:velocity:surface:mag >= 100 {
// set tarSteer to heading(targetHeading, 90 - (ship:velocity:surface:mag / 10)).
// wait 0.
// }
// // lock steering to the target heading, but account for drift, and the pitch
// // of the surface normal vector
// lock calculatedHeading to mod(targetHeading + 2 * (targetHeading - signedHeading()) + 360, 360).
// lock steering to heading(
// calculatedHeading,
// max(5, 90 - vAng(up:vector, ship:srfprograde:vector))
// ).
// print "Locked steering to surface prograde pitch and target heading".
// }
function basicAscent {
parameter targetHeading is 90, targetAltitude is 80000.
@@ -40,24 +81,9 @@ function basicAscent {
return true.
}.
// initial pitch-over
set tarSteer to heading(targetHeading, 90).
lock steering to tarSteer.
until ship:velocity:surface:mag >= 100 {
set tarSteer to heading(targetHeading, 90 - (ship:velocity:surface:mag / 10)).
wait 0.
}
gravityTurn(targetHeading).
// lock steering to the target heading, but account for drift, and the pitch
// of the surface normal vector
lock calculatedHeading to mod(targetHeading + 2 * (targetHeading - signedHeading()) + 360, 360).
lock steering to heading(
calculatedHeading,
max(5, 90 - vAng(up:vector, ship:srfprograde:vector))
).
print "Locked steering to surface prograde pitch and target heading".
when ship:q < 0.01 then {
when ship:altitude > body:atm:height then {
for f in fairings {
// get the module and deploy it
set m to f:getmodule("ModuleProceduralFairing").
@@ -66,19 +92,36 @@ function basicAscent {
wait 0.1.
// this isn't always true, figure out a way around
panels on.
radiators on.
for a in antennas {
set m to a:getmodule("ModuleRTAntenna").
if m:hasevent("activate") m:doevent("activate").
if m:getfield("target") = "no-target" m:setfield("target", "Mission Control").
if a:hasmodule("ModuleDeployableAntenna") {
set m to a:getmodule("ModuleDeployableAntenna").
if m:hasevent("extend antenna") m:doevent("extend antenna").
}
}
}
// try to limit the throttle to get a good ascent
set ascentPID to pidLoop(1/30, 0, 0, 0.1, 1).
set ascentPID:setpoint to 60.
set ascentThrottle to 1.
lock throttle to ascentThrottle.
lock pitchAngle to 90 - vAng(up:vector, ship:prograde:vector).
until ship:apoapsis >= targetAltitude or pitchAngle < 10 {
set ascentThrottle to ascentPID:update(time:seconds, eta:apoapsis).
}
// we're pitched down so much we might as well just burn
if ship:apoapsis < targetAltitude {
lock throttle to 1.
wait until ship:apoapsis >= targetAltitude.
}
// coast to apoapsis
wait until ship:apoapsis >= targetAltitude.
unlock calculatedHeading.
unlock pitchAngle.
lock steering to ship:prograde.
lock throttle to 0.
@@ -88,7 +131,8 @@ function basicAscent {
// if we're using a booster to get to orbit drop it before finishing the cirularization
when ship:periapsis > 30000 then {
if ship:stagenum <> 0 and ship:stagedeltav(ship:stagenum - 1):current > 0 {
// use RCS as a condition to not stage the booster
if ship:stagenum <> 0 and ship:stagedeltav(ship:stagenum - 1):current > 0 and not brakes {
print "Dropping booster".
// shutdown engines before dropping them
+3
View File
@@ -55,3 +55,6 @@ if ship:bounds:bottomaltradar > 5 {
// core:part:getmodule("kOSProcessor"):doevent("Close Terminal").
}
// wait for more input
runpath("0:/scripts/stayRunner.ks").
+42 -43
View File
@@ -1,3 +1,5 @@
run once maneuver.
function groundSlope {
parameter xOffset is 0, yOffset is 0.
local east is vCrs(north:vector, up:vector).
@@ -30,58 +32,55 @@ function groundSlope {
return slope.
}
wait until not hasNode.
lock h to ship:bounds:bottomaltradar.
lock velVec to ship:velocity:surface.
lock speed to velVec:mag.
lock vSpeed to ship:verticalspeed.
lock g to body:mu / ((body:radius + ship:altitude)^2).
lock maxA to ship:maxthrust / ship:mass.
lock vertFrac to max(abs(vSpeed) / max(speed, 0.001), 0.05).
set margin to 30. // safety buffer, meters
set gateRatio to 0.9. // start burn when required decel hits this fraction of max
set targetV to -3. // final drift speed, m/s
set burning to false.
set finalPhase to false.
lock maxDecel to max(maxA * vertFrac - g, 0.01).
lock requiredDecel to vSpeed^2 / (2 * max(h - margin, 0.1)).
lock neededA to (requiredDecel / vertFrac) + g.
lock hoverA to g / vertFrac. // accel needed to hold current vertical speed constant
// Suicide burn calcs
set tval to 0.
lock throttle to tval.
lock steering to ship:srfretrograde.
lock steering to srfretrograde.
lock h to ship:bounds:bottomaltradar.
lock v0 to ship:verticalspeed.
lock g to (body:mu / ((body:radius + ship:altitude)^2)).
lock a to ship:maxthrust / ship:mass.
lock d to (v0^2) / (2 * (a - g)).
// wait for burn
until h <= (1.1 * d) {
clearscreen.
print "Altitude AGL : " + round(h) at (4, 0).
print "Vertical Speed : " + round(v0, 1) at (4, 1).
print "Gravity : " + round(g, 2) at (4, 2).
print "Acceleration : " + round(a, 2) at (4, 3).
print "Distance : " + round(d, 2) at (4, 4).
wait 0.
}
unlock d.
unlock a.
set tval to 1.
set steeringLocked to false.
until h < 1 {
if v0 > -4 {
// equalize acceleration to stop downward velocity
set tval to max(0.001, ship:mass * g / ship:maxThrust).
if not burning and requiredDecel >= gateRatio * maxDecel {
set burning to true.
}
else if v0 > -6 and not steeringLocked {
// slow enough that we just want to kill vertical velocity
lock steering to up.
set steeringLocked to true.
if burning and not finalPhase and vSpeed >= targetV {
set finalPhase to true.
}
if finalPhase {
set tval to max(0, min(1, hoverA / maxA)).
} else if burning {
set tval to max(0, min(1, neededA / maxA)).
}
clearscreen.
print "Altitude AGL : " + round(h) at (4, 0).
print "Vertical Speed : " + round(v0, 1) at (4, 1).
print "Gravity : " + round(g, 2) at (4, 2).
print "Throttle : " + 100 * round(tval, 3) at (4, 3).
print "Alt AGL : " + round(h, 1) at (4, 0).
print "VSpeed : " + round(vSpeed, 1) at (4, 1).
print "Burning : " + burning at (4, 2).
print "Final phase : " + finalPhase at (4, 3).
print "Throttle : " + round(tval * 100) at (4, 4).
wait 0.
}
clearscreen.
print "Holding position".
lock steering to groundSlope().
wait until ship:angularvel:mag < 0.1.
wait 5.
print "Stable".
lock throttle to 0.
unlock throttle.
unlock steering.
sas on.
set sasMode to "STABILITYASSIST".
+23
View File
@@ -0,0 +1,23 @@
switch to 0.
cd("scripts").
local g is GUI(300).
set g:x to 100.
set g:y to 100.
local titleLabel is g:addlabel("Scripts").
set titleLabel:style:align to "center".
set titleLabel:style:hstretch to true.
local popup is g:addpopupmenu().
set popup:optionsuffix to "NAME".
list files in localFiles.
for f in localFiles popup:addoption(f).
popup:changed.
g:show().
wait until popup:changed.
g:dispose().
runpath(popup:value).
+6
View File
@@ -0,0 +1,6 @@
on ag10 {
runpath("0:/scripts/runner.ks").
preserve.
}
wait until false.
+89
View File
@@ -0,0 +1,89 @@
function hohmannDeltaV {
parameter r1 is 1, r2 is 1, mu is 1.
local vCirc to sqrt(mu / r1).
local vHohmann to sqrt(mu * (2 / r1 - 2 / (r1 + r2))).
return vHohmann - vCirc.
}
function angleBetween {
parameter posA to V(1, 1, 0), posB to V(1, 1, 0).
local angle to arcTan2(posB:y, posB:x) - arcTan2(posA:y, posA:x).
if angle < 0 set angle to angle + 2 * constant:pi.
return angle.
}
function hohmannTransfer {
// parameter targetPeriapsis is 60000.
parameter tgtBody is Mun.
// get the approximate required deltav for a transfer
local r1 to ship:orbit:semimajoraxis.
local r2 to tgtBody:orbit:semimajoraxis.
local vTransfer to hohmannDeltaV(r1, r2, kerbin:mu).
// compute the transfer time
local transferSMA to (r1 + r2) / 2.
local transferPeriod to 2 * constant:pi * sqrt(transferSMA^3 / kerbin:mu).
local transitTime to transferPeriod / 2.
// get lead angle (how far ahead the tgtBody must be)
local tgtAV to 2 * constant:pi / tgtBody:orbit:period.
local leadAngle to tgtAV * transitTime.
local transferAngle to constant:pi - leadAngle.
// find the next time the phase angle condition is satisfied
local shipAV to 2 * constant:pi / ship:orbit:period.
local relativeAV to tgtAV - shipAV.
// get the phase angle to the target
local bodyToShip to (ship:position - body:position):normalized.
local obtNorm to vCrs(bodyToShip, ship:velocity:orbit:normalized):normalized.
local bodyToTgt to vXcl(obtNorm, (tgtBody:position - body:position):normalized):normalized.
local signVec to vCrs(obtNorm, bodyToShip):normalized.
local phaseSign to vDot(bodyToTgt, signVec).
local currentPhaseAngle to vAng(ship:position - body:position, tgtBody:position - body:position) * (constant:pi / 180).
if phaseSign < 0 set currentPhaseAngle to -1 * currentPhaseAngle + 2 * constant:pi.
// get the time to start the maneuver
local phaseError is transferAngle - currentPhaseAngle.
if phaseError < 0 set phaseError to phaseError + 2 * constant:pi.
local waitTime to phaseError / relativeAV.
if waitTime < 0 set waitTime to waitTime + ship:orbit:period.
set nd to node(time:seconds + waitTime, 0, 0, vTransfer).
add nd.
// print "Transfer DeltaV (m/s) : " + round(vTransfer, 2).
// print "Transit Time (s) : " + round(transitTime*57.3, 0).
// print "Lead Angle (deg) : " + round(transferAngle*57.3, 2).
// print "Relative AV (deg/s) : " + relativeAV*57.3.
// print "Phase Angle (deg) : " + round(currentPhaseAngle*57.3, 2).
// print "Phase Error (deg) : " + round(phaseError*57.3, 2).
// print "Wait Time (s) : " + round(waitTime, 0).
}
local g is GUI(300).
set g:x to 100.
set g:y to 100.
local titleLabel is g:addlabel("Transfer to which body?").
set titleLabel:style:align to "center".
set titleLabel:style:hstretch to true.
local popup is g:addpopupmenu().
set popup:optionsuffix to "NAME".
for localMoon in body:orbitingchildren popup:addoption(localMoon).
popup:changed.
// print popup:options.
// print popup:changed.
g:show().
wait until popup:changed.
// print popup:value.
g:dispose().
hohmannTransfer(popup:value).