Compare commits
8 Commits
413b118847
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
| dceeddfcf1 | |||
| 36fc515c23 | |||
| a936077187 | |||
| ef8ae9e9cc | |||
| a314cdaa62 | |||
| 6822923238 | |||
| 6dd14708bc | |||
| 8aec6aa8a4 |
@@ -0,0 +1,2 @@
|
|||||||
|
logs
|
||||||
|
*.code-workspace
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
wait until ship:unpacked.
|
||||||
|
|
||||||
|
runPath("0:/scripts/basic.ks").
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
wait until ship:unpacked.
|
||||||
|
|
||||||
|
runPath("0:/scripts/stayRunner.ks").
|
||||||
@@ -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
@@ -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"
|
||||||
|
}
|
||||||
@@ -0,0 +1,149 @@
|
|||||||
|
// Inital gravity turn
|
||||||
|
// #include staging
|
||||||
|
run once staging.
|
||||||
|
// #include maneuver
|
||||||
|
run once maneuver.
|
||||||
|
|
||||||
|
function signedHeading {
|
||||||
|
local fwd is ship:srfprograde:vector.
|
||||||
|
local n is north:vector.
|
||||||
|
local e is vCrs(up:vector, north:vector).
|
||||||
|
|
||||||
|
local hdg is arcTan2(vdot(fwd, e), vdot(fwd, n)).
|
||||||
|
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.
|
||||||
|
|
||||||
|
if ship:altitude > body:atm:height return.
|
||||||
|
|
||||||
|
// get parts of interest
|
||||||
|
set fairings to ship:partstitledpattern("^AE-FF.*").
|
||||||
|
set antennas to ship:partstitledpattern("^(CommTech|Communotron|HG-|RA-|Reflectron).*").
|
||||||
|
|
||||||
|
lock throttle to 1.
|
||||||
|
|
||||||
|
print "Counting down:".
|
||||||
|
from {local countdown is 5.} until countdown = 0 step {set countdown to countdown - 1.} do {
|
||||||
|
print "..." + countdown.
|
||||||
|
wait 1.
|
||||||
|
}
|
||||||
|
|
||||||
|
// initial stage to takeoff
|
||||||
|
stage.
|
||||||
|
|
||||||
|
// stage everytime thrust drops to zero
|
||||||
|
when ship:maxThrust = 0 then {
|
||||||
|
print "Staging".
|
||||||
|
stage.
|
||||||
|
return true.
|
||||||
|
}.
|
||||||
|
|
||||||
|
gravityTurn(targetHeading).
|
||||||
|
|
||||||
|
when ship:altitude > body:atm:height then {
|
||||||
|
for f in fairings {
|
||||||
|
// get the module and deploy it
|
||||||
|
set m to f:getmodule("ModuleProceduralFairing").
|
||||||
|
if m:hasevent("deploy") m:doevent("deploy").
|
||||||
|
}
|
||||||
|
|
||||||
|
wait 0.1.
|
||||||
|
|
||||||
|
// this isn't always true, figure out a way around
|
||||||
|
panels on.
|
||||||
|
radiators on.
|
||||||
|
for a in antennas {
|
||||||
|
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
|
||||||
|
unlock calculatedHeading.
|
||||||
|
unlock pitchAngle.
|
||||||
|
lock steering to ship:prograde.
|
||||||
|
lock throttle to 0.
|
||||||
|
|
||||||
|
// don't do futher calcs until out of the atmosphere or very close to apoapsis
|
||||||
|
until ship:altitude >= body:atm:height or eta:apoapsis < 60.
|
||||||
|
|
||||||
|
|
||||||
|
// if we're using a booster to get to orbit drop it before finishing the cirularization
|
||||||
|
when ship:periapsis > 30000 then {
|
||||||
|
// 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
|
||||||
|
for e in ship:engines {
|
||||||
|
if e:ignition e:shutdown().
|
||||||
|
}
|
||||||
|
|
||||||
|
stage.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
executeNode(createCircularizationNodeAp()).
|
||||||
|
|
||||||
|
print "Circularized".
|
||||||
|
}
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
// core:part:getmodule("kOSProcessor"):doevent("Open Terminal").
|
||||||
|
|
||||||
|
if ship:bounds:bottomaltradar > 5 {
|
||||||
|
print "Script shouldn't start off the ground".
|
||||||
|
} else {
|
||||||
|
set MODULES to list(
|
||||||
|
"ascent.ks",
|
||||||
|
"maneuver.ks",
|
||||||
|
"staging.ks",
|
||||||
|
"logger.ks"
|
||||||
|
).
|
||||||
|
|
||||||
|
for mod in MODULES {
|
||||||
|
copyPath("0:/scripts/" + mod, "1:/" + mod).
|
||||||
|
}
|
||||||
|
|
||||||
|
// #include ascent
|
||||||
|
run once ascent.
|
||||||
|
|
||||||
|
// --- GUI ---
|
||||||
|
local targetAlt is 80000.
|
||||||
|
local targetHdg is 90.
|
||||||
|
local guiConfirmed is false.
|
||||||
|
|
||||||
|
local g is GUI(300).
|
||||||
|
set g:x to 100.
|
||||||
|
set g:y to 100.
|
||||||
|
|
||||||
|
local titleLabel is g:addlabel("Ascent Parameters").
|
||||||
|
set titleLabel:style:align to "center".
|
||||||
|
set titleLabel:style:hstretch to true.
|
||||||
|
|
||||||
|
g:addlabel("Target Altitude (m):").
|
||||||
|
local altBox is g:addtextfield(targetAlt:tostring).
|
||||||
|
set altBox:style:hstretch to true.
|
||||||
|
|
||||||
|
g:addlabel("Heading (degrees):").
|
||||||
|
local hdgBox is g:addtextfield(targetHdg:tostring).
|
||||||
|
set hdgBox:style:hstretch to true.
|
||||||
|
|
||||||
|
local confirmBtn is g:addbutton("Launch").
|
||||||
|
set confirmBtn:onclick to {
|
||||||
|
set targetAlt to altBox:text:tonumber(targetAlt).
|
||||||
|
set targetHdg to hdgBox:text:tonumber(targetHdg).
|
||||||
|
set guiConfirmed to true.
|
||||||
|
g:hide().
|
||||||
|
}.
|
||||||
|
|
||||||
|
g:show().
|
||||||
|
wait until guiConfirmed.
|
||||||
|
g:dispose().
|
||||||
|
// --- END GUI ---
|
||||||
|
|
||||||
|
basicAscent(targetHdg, targetAlt).
|
||||||
|
|
||||||
|
// core:part:getmodule("kOSProcessor"):doevent("Close Terminal").
|
||||||
|
}
|
||||||
|
|
||||||
|
// wait for more input
|
||||||
|
runpath("0:/scripts/stayRunner.ks").
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
// #include maneuver
|
||||||
|
run once maneuver.
|
||||||
|
|
||||||
|
createCircularizationNodeAp().
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
// #include maneuver
|
||||||
|
run once maneuver.
|
||||||
|
|
||||||
|
createCircularizationNodePe().
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
// #include maneuver
|
||||||
|
run once maneuver.
|
||||||
|
|
||||||
|
if hasNode executeNode(nextNode).
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
core:part:getmodule("kOSProcessor"):doevent("Open Terminal").
|
||||||
|
|
||||||
|
set tr to ship:partstagged("tailRotor")[0].
|
||||||
|
set rm to tr:getModule("ModuleRoboticServoRotor").
|
||||||
|
set rpmMax to 410.
|
||||||
|
|
||||||
|
set pid to pidLoop(0.0025, 0, 0, rpmMax, rpmMax).
|
||||||
|
set pid:setpoint to 0.
|
||||||
|
|
||||||
|
until false {
|
||||||
|
set L_z to ship:angularMomentum:z.
|
||||||
|
set rpmLimit to pid:update(time:seconds, L_z).
|
||||||
|
rm:setfield("rpm limit", rpmLimit).
|
||||||
|
|
||||||
|
clearscreen.
|
||||||
|
print "Lz : " + round(L_z, 2) at (5, 5).
|
||||||
|
print "RPM Limit : " + round(rpmLimit, 2) at (5, 6).
|
||||||
|
wait 0.
|
||||||
|
}
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
run once maneuver.
|
||||||
|
|
||||||
|
function groundSlope {
|
||||||
|
parameter xOffset is 0, yOffset is 0.
|
||||||
|
local east is vCrs(north:vector, up:vector).
|
||||||
|
|
||||||
|
local center is (
|
||||||
|
ship:position +
|
||||||
|
(yOffset * north:vector) +
|
||||||
|
(xOffset * east)
|
||||||
|
).
|
||||||
|
|
||||||
|
local a is body:geopositionof(center + 5 * north:vector).
|
||||||
|
local b is body:geopositionof(center - 3 * north:vector + 4 * east).
|
||||||
|
local c is body:geopositionof(center - 3 * north:vector - 4 * east).
|
||||||
|
|
||||||
|
local aVec is a:altitudeposition(a:terrainheight).
|
||||||
|
local bVec is b:altitudeposition(b:terrainheight).
|
||||||
|
local cVec is c:altitudeposition(c:terrainheight).
|
||||||
|
|
||||||
|
local slope is vCrs(cVec - aVec, bVec - aVec):normalized.
|
||||||
|
// local centerPos is body:geopositionof(center).
|
||||||
|
// set slopeDraw to vecDraw(
|
||||||
|
// centerPos:altitudeposition(centerPos:terrainheight),
|
||||||
|
// slope,
|
||||||
|
// green,
|
||||||
|
// "",
|
||||||
|
// 10,
|
||||||
|
// true
|
||||||
|
// ).
|
||||||
|
|
||||||
|
return slope.
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
set tval to 0.
|
||||||
|
lock throttle to tval.
|
||||||
|
lock steering to srfretrograde.
|
||||||
|
|
||||||
|
until h < 1 {
|
||||||
|
if not burning and requiredDecel >= gateRatio * maxDecel {
|
||||||
|
set burning 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 "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.
|
||||||
|
}
|
||||||
|
|
||||||
|
lock throttle to 0.
|
||||||
|
unlock throttle.
|
||||||
|
unlock steering.
|
||||||
|
sas on.
|
||||||
|
set sasMode to "STABILITYASSIST".
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
// ═══════════════════════════════════════════════════════════
|
||||||
|
// logger.ks
|
||||||
|
// CSV logger with buffered writes.
|
||||||
|
//
|
||||||
|
// Usage:
|
||||||
|
// local LOGGER to loggerCreate("0:/logs/flight.csv", list("time", "altitude", "apoapsis")).
|
||||||
|
// loggerUpdate(LOGGER, list(time:seconds, altitude, apoapsis)).
|
||||||
|
// loggerFlush(LOGGER). // call at end of script to flush remaining buffer
|
||||||
|
// ═══════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
// ── Creates a logger and writes the CSV header.
|
||||||
|
// Parameters:
|
||||||
|
// filePath : string — destination path, e.g. "logs/flight.csv"
|
||||||
|
// columns : list — ordered list of column name strings
|
||||||
|
// flushPeriod : scalar — seconds between buffer flushes (default 1.0)
|
||||||
|
// Returns a logger lexicon to be passed to loggerUpdate / loggerFlush.
|
||||||
|
function loggerCreate {
|
||||||
|
parameter filePath.
|
||||||
|
parameter columns.
|
||||||
|
parameter flushPeriod is 1.0.
|
||||||
|
|
||||||
|
// Create or overwrite the file and write the header row
|
||||||
|
if not archive:exists(filePath) archive:create(filePath).
|
||||||
|
local f to archive:open(filePath).
|
||||||
|
f:clear().
|
||||||
|
f:writeln(_loggerFormatRow(columns)).
|
||||||
|
|
||||||
|
local l to lexicon(
|
||||||
|
"file", f,
|
||||||
|
"columns", columns,
|
||||||
|
"buffer", list(),
|
||||||
|
"flushPeriod", flushPeriod,
|
||||||
|
"lastFlush", time:seconds
|
||||||
|
).
|
||||||
|
|
||||||
|
return l.
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Appends a data row to the buffer.
|
||||||
|
// Values must be in the same order as the columns list passed to loggerCreate.
|
||||||
|
// Flushes the buffer to disk if the flush period has elapsed.
|
||||||
|
function loggerUpdate {
|
||||||
|
parameter l.
|
||||||
|
parameter values.
|
||||||
|
|
||||||
|
l["buffer"]:add(_loggerFormatRow(values)).
|
||||||
|
|
||||||
|
if time:seconds - l["lastFlush"] >= l["flushPeriod"] {
|
||||||
|
loggerFlush(l).
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Flushes all buffered rows to disk immediately.
|
||||||
|
// Call at the end of a script to ensure no data is lost.
|
||||||
|
function loggerFlush {
|
||||||
|
parameter l.
|
||||||
|
|
||||||
|
local f to l["file"].
|
||||||
|
local buf to l["buffer"].
|
||||||
|
|
||||||
|
local i to 0.
|
||||||
|
until i >= buf:length {
|
||||||
|
f:writeln(buf[i]).
|
||||||
|
set i to i + 1.
|
||||||
|
}
|
||||||
|
|
||||||
|
buf:clear().
|
||||||
|
set l["lastFlush"] to time:seconds.
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Formats a list of values as a CSV row string.
|
||||||
|
function _loggerFormatRow {
|
||||||
|
parameter values.
|
||||||
|
|
||||||
|
local row to "".
|
||||||
|
local i to 0.
|
||||||
|
|
||||||
|
until i >= values:length {
|
||||||
|
if i > 0 { set row to row + ",". }
|
||||||
|
set row to row + values[i].
|
||||||
|
set i to i + 1.
|
||||||
|
}
|
||||||
|
|
||||||
|
return row.
|
||||||
|
}
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
// ═══════════════════════════════════════════════════════════
|
||||||
|
// maneuver.ks
|
||||||
|
// Utility functions related to maneuvers.
|
||||||
|
//
|
||||||
|
// Usage:
|
||||||
|
// executeNode(nd: node)
|
||||||
|
// ═══════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
// #include staging
|
||||||
|
run once staging.
|
||||||
|
|
||||||
|
function executeNode {
|
||||||
|
parameter nd is node(0, 0, 0, 0).
|
||||||
|
print "boof".
|
||||||
|
|
||||||
|
if nd:deltav:mag = 0 {
|
||||||
|
print "Empty node".
|
||||||
|
return.
|
||||||
|
}
|
||||||
|
|
||||||
|
local burnTime to calcBurnTime(nd:deltav:mag).
|
||||||
|
print "Node in: " + round(nd:eta) + "s, dV: " + round(nd:deltav:mag, 1) + " m/s, burn time: " + round(burnTime, 1) + "s".
|
||||||
|
|
||||||
|
// wait for node to be close then align to vector
|
||||||
|
wait until nd:eta <= burnTime / 2 + 60.
|
||||||
|
local np to nd:deltav.
|
||||||
|
lock steering to np.
|
||||||
|
wait until vang(ship:facing:vector, nd:deltav) < 1.
|
||||||
|
print "Maneuver vector lined up".
|
||||||
|
|
||||||
|
// wait until burn
|
||||||
|
wait until nd:eta <= burnTime / 2.
|
||||||
|
print "Burn time".
|
||||||
|
|
||||||
|
// ── Snapshot initial dV for overburn detection
|
||||||
|
local dv0 to nd:deltav.
|
||||||
|
|
||||||
|
local throttleSet to 0.
|
||||||
|
lock throttle to throttleSet.
|
||||||
|
|
||||||
|
// ag1 off.
|
||||||
|
// until ag1 {
|
||||||
|
until False {
|
||||||
|
local maxAcc to ship:maxThrust / ship:mass.
|
||||||
|
set throttleSet to min(nd:deltav:mag / maxAcc, 1).
|
||||||
|
set np to nd:deltav.
|
||||||
|
|
||||||
|
// ── Overburn detection
|
||||||
|
if vdot(dv0, nd:deltav) < 0 {
|
||||||
|
print "Overburn detected. Cutting throttle.".
|
||||||
|
lock throttle to 0.
|
||||||
|
break.
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Residual dV negligible
|
||||||
|
if nd:deltav:mag < 0.1 {
|
||||||
|
wait until vdot(dv0, nd:deltav) < 0.5.
|
||||||
|
lock throttle to 0.
|
||||||
|
break.
|
||||||
|
}
|
||||||
|
|
||||||
|
wait 0.
|
||||||
|
}
|
||||||
|
|
||||||
|
lock throttle to 0.
|
||||||
|
unlock throttle.
|
||||||
|
unlock steering.
|
||||||
|
remove nd.
|
||||||
|
}
|
||||||
|
|
||||||
|
function createCircularizationNodeAp {
|
||||||
|
local rBurn to body:radius + apoapsis.
|
||||||
|
local vTarget to sqrt(body:mu / rBurn).
|
||||||
|
local dvEst to vTarget - velocityat(ship, time:seconds + eta:apoapsis):orbit:mag.
|
||||||
|
|
||||||
|
local nd to node(time:seconds + eta:apoapsis, 0, 0, dvEst).
|
||||||
|
add nd.
|
||||||
|
return nd.
|
||||||
|
}
|
||||||
|
|
||||||
|
function createCircularizationNodePe {
|
||||||
|
local rBurn to body:radius + periapsis.
|
||||||
|
local vTarget to sqrt(body:mu / rBurn).
|
||||||
|
local dvEst to vTarget - velocityat(ship, time:seconds + eta:periapsis):orbit:mag.
|
||||||
|
|
||||||
|
local nd to node(time:seconds + eta:periapsis, 0, 0, dvEst).
|
||||||
|
add nd.
|
||||||
|
return nd.
|
||||||
|
}
|
||||||
@@ -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).
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
// ═══════════════════════════════════════════════════════════
|
||||||
|
// staging.ks
|
||||||
|
// Utility functions related to staging and the effects of changing stages
|
||||||
|
//
|
||||||
|
// Usage:
|
||||||
|
// basicStaging()
|
||||||
|
// calcBurnTime(dvNeeded: scalar)
|
||||||
|
// ═══════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
|
||||||
|
function calcBurnTime {
|
||||||
|
parameter dvNeeded.
|
||||||
|
|
||||||
|
local totalTime to 0.
|
||||||
|
local dvRemaining to dvNeeded.
|
||||||
|
local stageNum to ship:stagenum.
|
||||||
|
|
||||||
|
until dvRemaining <= 0 or stageNum < 0 {
|
||||||
|
local stageDv to ship:stagedeltav(stageNum):current.
|
||||||
|
local stageTime to ship:stagedeltav(stageNum):duration.
|
||||||
|
|
||||||
|
print "Stage: " + stageNum.
|
||||||
|
if stageDv <= 0 {
|
||||||
|
set stageNum to stageNum - 1.
|
||||||
|
} else if stageDv >= dvRemaining {
|
||||||
|
set totalTime to totalTime + stageTime * (dvRemaining / stageDv).
|
||||||
|
set dvRemaining to 0.
|
||||||
|
} else {
|
||||||
|
set totalTime to totalTime + stageTime.
|
||||||
|
set dvRemaining to dvRemaining - stageDv.
|
||||||
|
set stageNum to stageNum - 1.
|
||||||
|
}
|
||||||
|
|
||||||
|
print " - time: " + totalTime.
|
||||||
|
print " - dv : " + dvRemaining.
|
||||||
|
}
|
||||||
|
|
||||||
|
if dvRemaining > 0 {
|
||||||
|
print "WARNING: Insufficient dV. Short by " + round(dvRemaining, 1) + " m/s.".
|
||||||
|
}
|
||||||
|
|
||||||
|
return totalTime.
|
||||||
|
}
|
||||||
|
|
||||||
|
function deployables {
|
||||||
|
ag1 on.
|
||||||
|
wait 0.5.
|
||||||
|
panels on.
|
||||||
|
radiators on.
|
||||||
|
ag2 on.
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
on ag10 {
|
||||||
|
runpath("0:/scripts/runner.ks").
|
||||||
|
preserve.
|
||||||
|
}
|
||||||
|
|
||||||
|
wait until false.
|
||||||
@@ -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).
|
||||||
Reference in New Issue
Block a user