Initial import

This commit is contained in:
2025-10-29 15:39:36 -07:00
commit af3c3ecdd3
38 changed files with 2308 additions and 0 deletions

5
.idea/.gitignore generated vendored Normal file
View File

@@ -0,0 +1,5 @@
# Default ignored files
/shelf/
/workspace.xml
# Environment-dependent path to Maven home directory
/mavenHomeManager.xml

10
.idea/Script.iml generated Normal file
View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$USER_HOME$/Documents/papers/guidance" />
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

6
.idea/misc.xml generated Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" languageLevel="JDK_24" default="true" project-jdk-name="24" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

8
.idea/modules.xml generated Normal file
View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/Script.iml" filepath="$PROJECT_DIR$/.idea/Script.iml" />
</modules>
</component>
</project>

6
.idea/vcs.xml generated Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

27
boot/bumper.ks Normal file
View File

@@ -0,0 +1,27 @@
@lazyglobal off.
wait until ship:unpacked.
runoncepath("0:/lib/stage/v2.ks").
runoncepath("0:/lib/common.ks").
local target_azimuth is 90.
local target_pitch is 10.
rcs off.
v2:launch(target_azimuth, target_pitch).
rcs on.
local hdg is lookdirup(ship:srfprograde:forevector, ship:up:forevector).
lock throttle to 1.0.
lock steering to hdg.
wait 1.
wait until steering_locked().
stage.
wait 3.
stage.
wait until stage:ready.
stage.
wait until ship:thrust = 0.

14
boot/cherenkov.ks Normal file
View File

@@ -0,0 +1,14 @@
@lazyglobal off.
wait until ship:unpacked.
rcs off.
runoncepath("0:/lib/common.ks").
runoncepath("0:/lib/stage/thor.ks").
runoncepath("0:/lib/stage/able.ks").
local hdg is 90.
thor:launch(hdg, 250_000, 7).
stage.
able:orbit(hdg, true).
stage.

30
boot/gravimetric.ks Normal file
View File

@@ -0,0 +1,30 @@
@lazyglobal off.
wait until ship:unpacked.
rcs off.
runoncepath("0:/lib/common.ks").
runoncepath("0:/lib/stage/thor.ks").
runoncepath("0:/lib/stage/able.ks").
local target_inclination is 55.
local target_alt is 1_050_000.
local target_ecc is 0.0029.
local hdg is launch_azimuth(target_inclination, target_alt).
thor:launch(hdg, target_alt, 5).
stage.
able:yeet(hdg, target_alt).
able:power_down().
wait 1.
set warpmode to "rails".
set warp to 2.
wait until eta:apoapsis < 180.
set warp to 1.
wait until eta:apoapsis < 150.
set warp to 0.
wait 1.
wait until kuniverse:timewarp:issettled.
able:power_up().
able:circularize(target_ecc).
wait 1.
stage.

View File

@@ -0,0 +1,26 @@
@lazyglobal off.
wait until ship:unpacked.
rcs off.
runoncepath("0:/lib/common.ks").
runoncepath("0:/lib/stage/thor.ks").
runoncepath("0:/lib/stage/able.ks").
local target_inclination is ship:latitude.
local target_alt is 300_000.
local hdg is launch_azimuth(target_inclination, target_alt).
thor:launch(hdg, target_alt).
stage.
able:burn(hdg).
rcs on.
lock steering to heading(hdg, 0, -hdg).
wait until steering_locked().
stage.
wait 1.
set warpmode to "physics".
set warp to 3.
wait until ship:thrust = 0.
set warp to 0.

19
boot/ir-radiometry.ks Normal file
View File

@@ -0,0 +1,19 @@
@lazyglobal off.
wait until ship:unpacked.
rcs off.
runoncepath("0:/lib/common.ks").
runoncepath("0:/lib/stage/thor.ks").
runoncepath("0:/lib/stage/able.ks").
local target_inclination is 80.
local target_alt is 600_000.
local hdg is launch_azimuth(target_inclination, target_alt).
thor:launch(hdg, target_alt, 6).
stage.
able:orbit(hdg).
wait 1. // Ensure engine shuts down?
stage.

37
boot/jupiter.ks Normal file
View File

@@ -0,0 +1,37 @@
@lazyglobal off.
wait until ship:unpacked.
runoncepath("0:/lib/stage/v2.ks").
runoncepath("0:/lib/common.ks").
local target_azimuth is 90.
// 6Mm with A-6
//local target_pitch is 10.
// 7.5Mm with A-6H
local target_pitch is 7.
rcs off.
v2:launch(target_azimuth, target_pitch).
// Release upper stage and align.
rcs on.
stage.
local hdg is lookdirup(ship:srfprograde:forevector, ship:up:forevector).
lock throttle to 1.0.
lock steering to hdg.
wait 1.
// spin up solids
wait until steering_locked(0.001).
unlock steering.
set ship:control:roll to 1.0.
wait 20.
// Sequence solid motors
stage.
wait 8.
stage.
wait 8.
stage.

60
boot/kh-1.ks Normal file
View File

@@ -0,0 +1,60 @@
@lazyglobal off.
wait until ship:unpacked.
rcs off.
runoncepath("0:/lib/common.ks").
runoncepath("0:/lib/stage/thor.ks").
runoncepath("0:/lib/stage/agena.ks").
local target_inclination is 90.
local target_alt is 150_000.
local hdg is launch_azimuth(target_inclination, target_alt).
thor:launch(hdg, target_alt, 9.3).
stage.
agena:orbit(hdg).
agena:power_down().
print "Waiting for film or batteries to run out".
wait 1.
set warpmode to "rails".
set warp to 4.
local cam is ship:partsdubbed("RO-BasicFilmCamera")[0]:getmodule("Experiment").
until false {
if agena:low_power() {
break.
}
local done is false.
for evt in cam:allevents {
if evt:contains("depleted") {
set done to true.
}
}
if done {
break.
}
wait 1.
}
set warp to 0.
wait until kuniverse:timewarp:issettled.
print "Transferring data to return capsule".
wait until ship:rootpart:getmodule("HardDrive"):hasevent("transfer data here").
ship:rootpart:getmodule("HardDrive"):doevent("Transfer data here").
print "Aligning for return".
agena:power_up().
rcs on.
lock steering to ship:retrograde.
wait 20.
wait until steering_locked(0.001).
print "Deorbit!".
stage.
// Stage parachute
wait until ship:altitude < 25000.
print "Parachute deploy".
stage.

53
boot/kh-4.ks Normal file
View File

@@ -0,0 +1,53 @@
@lazyglobal off.
wait until ship:unpacked.
rcs off.
runoncepath("0:/lib/common.ks").
runoncepath("0:/lib/stage/thor.ks").
runoncepath("0:/lib/stage/agena.ks").
local target_inclination is 90.
local target_alt is 200_000.
local hdg is launch_azimuth(target_inclination, target_alt).
thor:launch(hdg, target_alt, 8).
stage.
agena:orbit(hdg).
agena:power_down().
print "Waiting for film or batteries to run out".
wait 1.
set warpmode to "rails".
set warp to 4.
local cam is ship:partsdubbed("RO-ImprovedFilmCamera")[0]:getmodule("Experiment").
until false {
if agena:low_power() {
break.
}
if cam:depleted {
break.
}
wait 1.
}
set warp to 0.
wait until kuniverse:timewarp:issettled.
print "Transferring data to return capsule".
ship:rootpart:getmodule("HardDrive"):transferHere.
print "Aligning for return".
agena:power_up().
rcs on.
lock steering to ship:retrograde.
wait 20.
wait until steering_locked(0.1).
print "Deorbit!".
stage.
// Stage parachute
wait until ship:altitude < 25000.
print "Parachute deploy".
stage.

32
boot/magnetometry.ks Normal file
View File

@@ -0,0 +1,32 @@
@lazyglobal off.
wait until ship:unpacked.
rcs off.
runoncepath("0:/lib/common.ks").
runoncepath("0:/lib/stage/thor.ks").
runoncepath("0:/lib/stage/able.ks").
local hdg is 90.
thor:launch(hdg, 250_000, 8).
stage.
able:yeet(hdg, 3_050_000).
rcs off.
able:power_down().
wait 1.
set warpmode to "rails".
set warp to 2.
wait until eta:apoapsis < 120.
set warp to 1.
wait until eta:apoapsis < 45.
set warp to 0.
wait 1.
wait until kuniverse:timewarp:issettled.
able:power_up().
lock steering to ship:prograde.
rcs on.
wait 1.
wait until steering_locked(0.05).
wait until eta:apoapsis < 20.
stage.

61
boot/mercury-orbit.ks Normal file
View File

@@ -0,0 +1,61 @@
@lazyglobal off.
wait until ship:unpacked.
rcs off.
lock throttle to 0.
runoncepath("0:/lib/common.ks").
runoncepath("0:/lib/moonmath.ks").
runoncepath("0:/lib/stage/atlas.ks").
on abort {
unlock steering.
sas on.
wait 5.
stage.
wait until stage:ready.
stage.
rcs on.
set sasmode to "retrograde".
ship:rootpart:getmodule("kOSProcessor"):deactivate.
}
// Any automatic abort triggers go where
when false then {
abort on.
}
local orbit_time is 26*60*60.
local target_alt is 225_000.
atlas:launch(90, target_alt, 7.5).
stage.
panels on.
wait 1.
rcs on.
local dir is sun:direction.
lock steering to dir.
wait 1.
wait until steering_locked().
set warpmode to "rails".
set warp to 1.
// Human can time-warp faster here if they want
wait orbit_time.
set warp to 0.
wait 1.
wait until kuniverse:timewarp:issettled.
local retro is ship:retrograde.
lock steering to retro.
wait 1.
wait until steering_locked().
stage.
wait 20.
stage.
set warpmode to "rails".
set warp to 2.
wait until ship:altitude < 140_000.
lock steering to ship:retrograde.
wait until ship:altitude < 35_000.
stage.

39
boot/mercury-return.ks Normal file
View File

@@ -0,0 +1,39 @@
@lazyglobal off.
wait until ship:unpacked.
rcs off.
lock throttle to 0.
runoncepath("0:/lib/common.ks").
runoncepath("0:/lib/moonmath.ks").
runoncepath("0:/lib/stage/atlas.ks").
local orbit_time is 24*60*60.
stage.
rcs on.
local dir is ship:prograde.
lock steering to dir.
wait 1.
wait until steering_locked().
set warpmode to "rails".
set warp to 1.
// Human can time-warp faster here if they want
wait orbit_time.
set warp to 0.
wait 1.
wait until kuniverse:timewarp:issettled.
local retro is ship:retrograde.
lock steering to retro.
wait 1.
wait until steering_locked().
stage.
wait 20.
stage.
set warpmode to "rails".
set warp to 2.
wait until ship:altitude < 140_000.
lock steering to ship:retrograde.
wait until ship:altitude < 35_000.
stage.

177
boot/moon-impactor.ks Normal file
View File

@@ -0,0 +1,177 @@
@lazyglobal off.
wait until ship:unpacked.
rcs off.
lock throttle to 0.
runoncepath("0:/lib/common.ks").
runoncepath("0:/lib/moonmath.ks").
runoncepath("0:/lib/stage/atlas.ks").
runoncepath("0:/lib/stage/agena.ks").
local state is lex().
local function ship_volume {
return ship:rootpart:getmodule("kosprocessor"):volume.
}
local function phase {
switch to ship_volume().
if not ship_volume():exists("state.json") {
set_phase("prelaunch").
}
set state to readjson("state.json").
return state["phase"].
}
local function set_phase {
parameter new_phase.
switch to ship_volume().
set state["phase"] to new_phase.
writejson(state, "state.json").
kuniverse:quicksaveto("moon-impactor-"+new_phase).
}
if phase() = "prelaunch" {
local target_inclination is max(moon:obt:inclination,ship:latitude).
local target_alt is 500_000.
set state["azimuth"] to launch_azimuth(target_inclination, target_alt).
local launch_params is moonmath:calculate_launch(target_inclination, state["azimuth"], target_alt).
local launch_time is launch_params:launch_time.
set state["moon_altitude"] to launch_params:moon_altitude.
set state["burn_longitude"] to launch_params:burn_longitude.
print "Burning for moon at " + state["burn_longitude"] + " right ascension".
wait 2.
until launch_time - time:seconds < 10 {
print "Not ready to launch yet, warping...".
warpto(launch_time-9).
wait 0.
wait until warp = 0.
wait until kuniverse:timewarp:issettled.
print "Maybe done warping?".
}
wait until time:seconds > launch_time.
atlas:launch(state["azimuth"], target_alt, 4).
stage.
set_phase("circularize").
}
if phase() = "circularize" {
agena:orbit(state["azimuth"]).
agena:power_down().
wait 1.
set_phase("parkingorbit").
}
local function ship_longitude {
return mod(ship:longitude + ship:body:rotationangle + 360, 360).
}
local function transfer_lead_angle {
parameter moon_alt.
local moon_range is moon:apoapsis - moon:periapsis.
local moon_frac is (moon_alt - moon:periapsis) / moon_range.
local lead_angle_frac is 1.0 - moon_frac.
return 1.1 + 0.65 * lead_angle_frac.
}
if phase() = "parkingorbit" {
// Just in case our burn point is RIGHT HERE, we want to go around at least once.
set warpmode to "physics".
set warp to 3.
wait until abs(ship_longitude() - state["burn_longitude"]) > 10.
set warp to 0.
wait until kuniverse:timewarp:issettled.
wait 1.
// Rails warp until we're nearish to the burn point
print "Warping to dLongitude < 15".
set warpmode to "rails".
set warp to 2.
wait until abs(ship_longitude() - state["burn_longitude"]) < 15.
set warp to 0.
wait until kuniverse:timewarp:issettled.
wait 1.
// Physics warp until we're nearish-er
print "Warping to dLongitude < 7".
set warpmode to "physics".
set warp to 3.
wait until abs(ship_longitude() - state["burn_longitude"]) < 4.
set warp to 0.
wait until kuniverse:timewarp:issettled.
wait 1.
agena:power_up().
rcs on.
lock steering to ship:prograde.
local lead_angle is transfer_lead_angle(state["moon_altitude"]).
wait until abs(ship_longitude() - state["burn_longitude"]) < lead_angle. // Hand-picked rather than computing burn time & time to target longitude
local transfer_vel is circular_vel() + hohmann_transfer_dv(earth, ship:altitude, state["moon_altitude"]).
print "Moon altitude is: " + state["moon_altitude"].
print "Transfer DV is: " + (transfer_vel - ship:velocity:orbit:mag).
print "Burn lead angle is: " + lead_angle.
agena:transfer_burn(transfer_vel).
wait 1.
stage.
set_phase("adjust").
}
if phase() = "adjust" {
panels on.
rcs on.
lock throttle to 0.0.
lock steering to lookdirup(ship:prograde:forevector, ship:up:forevector).
local adjustment is 8_000_000. // 1.5%..2.0%?
print "Alt Adjustment is " + adjustment.
local target_alt is state["moon_altitude"] + adjustment.
local max_alt_delta is 1_000_000.
local threshold is 0.1.
until false {
local p is threshold / max_alt_delta.
local da is target_alt - ship:orbit:apoapsis.
local horz_factor is da * p.
if abs(horz_factor) < threshold {
set ship:control:fore to 0.
break.
}
set ship:control:fore to horz_factor.
wait 0.
}
set_phase("pretransfer").
}
if phase() = "pretransfer" {
rcs on.
lock steering to sun:direction.
wait 1.
wait until steering_locked().
wait 1.
local avi_mod is ship:rootpart:getmodule("ModuleProceduralAvionics").
avi_mod:doaction("shutdown avionics", true).
wait 1.
set_phase("transfer").
}
if phase() = "transfer" {
set warpmode to "rails".
warpto(eta:transition + time:seconds).
wait until ship:obt:body = moon.
wait until kuniverse:timewarp:issettled.
set_phase("done").
}
if phase() <> "done" {
print "Phase logic failed, expected to be in phase '" + phase() + "'".
}
print "Done".

170
boot/moon-orbiter.ks Normal file
View File

@@ -0,0 +1,170 @@
@lazyglobal off.
wait until ship:unpacked.
rcs off.
lock throttle to 0.
runoncepath("0:/lib/common.ks").
runoncepath("0:/lib/moonmath.ks").
runoncepath("0:/lib/stage/atlas.ks").
runoncepath("0:/lib/stage/centaur.ks").
runoncepath("0:/lib/stage/probe.ks").
local state is lex().
local function ship_volume {
return ship:rootpart:getmodule("kosprocessor"):volume.
}
local function phase {
switch to ship_volume().
if not ship_volume():exists("state.json") {
set_phase("prelaunch").
}
set state to readjson("state.json").
return state["phase"].
}
local function set_phase {
parameter new_phase.
switch to ship_volume().
set state["phase"] to new_phase.
writejson(state, "state.json").
kuniverse:quicksaveto("moon-impactor-"+new_phase).
}
if phase() = "prelaunch" {
local target_inclination is max(moon:obt:inclination,ship:latitude).
local target_alt is 500_000.
set state["azimuth"] to launch_azimuth(target_inclination, target_alt).
local launch_params is moonmath:calculate_launch(target_inclination, state["azimuth"], target_alt).
local launch_time is launch_params:launch_time.
set state["moon_altitude"] to launch_params:moon_altitude.
set state["departure_ra"] to launch_params:burn_longitude.
print "Departing for moon at " + state["departure_ra"] + " right ascension".
wait 2.
until launch_time - time:seconds < 10 {
print "Not ready to launch yet, warping...".
warpto(launch_time-9).
wait 0.
wait until warp = 0.
wait until kuniverse:timewarp:issettled.
print "Maybe done warping?".
}
wait until time:seconds > launch_time.
atlas:launch(state["azimuth"], target_alt, 4).
stage.
set_phase("circularize").
}
if phase() = "circularize" {
centaur:orbit(state["azimuth"]).
centaur:power_down().
wait 1.
set_phase("parkingorbit").
}
local function ship_ra {
return mod(ship:longitude + ship:body:rotationangle + 360, 360).
}
if phase() = "parkingorbit" {
local transfer_dv is hohmann_transfer_dv(earth, ship:altitude, state["moon_altitude"]).
local burn_time is centaur:burn_time(transfer_dv / 2).
local burn_angle is (burn_time / ship:obt:period) * 360.
local burn_ra is mod(state["departure_ra"] - burn_angle + 360, 360).
// Just in case our departure point is RIGHT HERE, we want to go around at least once.
set warpmode to "physics".
set warp to 3.
wait until abs(ship_ra() - burn_ra) > 16.
set warp to 0.
wait until kuniverse:timewarp:issettled.
wait 1.
// Rails warp until we're nearish to the burn point
print "Warping to dLongitude < 15".
set warpmode to "rails".
set warp to 2.
wait until abs(ship_ra() - burn_ra) < 15.
set warp to 0.
wait until kuniverse:timewarp:issettled.
wait 1.
// Physics warp until we're nearish-er
print "Warping to dLongitude < 4".
set warpmode to "physics".
set warp to 3.
wait until abs(ship_ra() - burn_ra) < 4.
set warp to 0.
wait until kuniverse:timewarp:issettled.
wait 1.
centaur:power_up().
rcs on.
lock steering to ship:prograde.
wait until ship_ra() >= burn_ra.
print "Moon altitude is: " + state["moon_altitude"].
print "Transfer DV is: " + transfer_dv.
centaur:transfer_burn(state["moon_altitude"]).
wait 1.
set_phase("pretransfer").
}
if phase() = "pretransfer" {
rcs on.
panels on.
stage.
wait 1.
probe:power_up().
lock steering to sun:direction.
wait 1.
wait until steering_locked().
wait 1.
rcs off.
probe:power_down().
wait 1.
set_phase("transfer").
}
if phase() = "transfer" {
set warpmode to "rails".
warpto(eta:transition + time:seconds).
wait until ship:obt:body = moon.
wait until kuniverse:timewarp:issettled.
set_phase("lunar_arrival").
}
if phase() = "lunar_arrival" {
stage.
probe:capture_burn().
set_phase("lunar_deploy").
}
if phase() = "lunar_deploy" {
probe:power_up().
lock steering to sun:direction.
wait 1.
wait until steering_locked().
wait 1.
rcs off.
probe:power_down().
set_phase("done").
}
if phase() <> "done" {
print "Phase logic failed, expected to be in phase '" + phase() + "'".
}
print "Done".

28
boot/navsat-1.ks Normal file
View File

@@ -0,0 +1,28 @@
@lazyglobal off.
wait until ship:unpacked.
rcs off.
runoncepath("0:/lib/common.ks").
runoncepath("0:/lib/stage/thor.ks").
runoncepath("0:/lib/stage/able.ks").
local target_alt is 500_000.
local target_ecc is 0.01.
local hdg is 30.
thor:launch(hdg, target_alt, 1.4).
stage.
able:yeet(hdg, target_alt).
able:power_down().
wait 1.
set warpmode to "rails".
set warp to 2.
wait until eta:apoapsis < 180.
set warp to 1.
wait until eta:apoapsis < 150.
set warp to 0.
wait 1.
wait until kuniverse:timewarp:issettled.
able:power_up().
able:circularize(target_ecc).
wait 1.

30
boot/navsat-2.ks Normal file
View File

@@ -0,0 +1,30 @@
@lazyglobal off.
wait until ship:unpacked.
rcs off.
runoncepath("0:/lib/common.ks").
runoncepath("0:/lib/stage/thor.ks").
runoncepath("0:/lib/stage/able.ks").
local target_alt is 800_000.
local target_ecc is 0.0025.
local hdg is launch_azimuth(89, target_alt).
thor:launch(hdg, target_alt, 5, 300).
stage.
able:yeet(hdg, target_alt).
able:power_down().
wait 1.
set warpmode to "rails".
set warp to 2.
wait until eta:apoapsis < 180.
set warp to 1.
wait until eta:apoapsis < 150.
set warp to 0.
wait 1.
wait until kuniverse:timewarp:issettled.
able:power_up().
able:circularize(target_ecc).
wait 1.
stage.

73
boot/orbit-return.ks Normal file
View File

@@ -0,0 +1,73 @@
@lazyglobal off.
wait until ship:unpacked.
rcs off.
runoncepath("0:/lib/common.ks").
runoncepath("0:/lib/stage/thor.ks").
runoncepath("0:/lib/stage/able.ks").
local target_inclination is ship:latitude.
local target_alt is 600_000.
local hdg is launch_azimuth(target_inclination, target_alt).
thor:launch(hdg, target_alt).
stage.
able:launch(hdg, target_alt).
set warpmode to "rails".
warpto(time:seconds + (eta:apoapsis - 20)).
wait until eta:apoapsis < 20.
// Kick stage.
rcs on.
lock steering to ship:prograde.
wait until eta:apoapsis < 10.
stage.
// Burn out kick stage
wait until ship:thrust = 0.
stage.
rcs off.
unlock steering.
unlock throttle.
wait 0.
// Skip a day for science collection
warpto(time:seconds + 24 * 60 * 60).
wait 24 * 60 * 60 + 1.
wait until kuniverse:timewarp:issettled.
print "Transferring data to return capsule".
wait until ship:rootpart:getmodule("HardDrive"):hasevent("transfer data here").
ship:rootpart:getmodule("HardDrive"):doevent("Transfer data here").
if eta:apoapsis < 35 {
print "Skipping this orbit".
wait until eta:apoapsis > eta:periapsis.
}
print "Warping to AP for deorbit".
wait 1.
warpto(time:seconds + eta:apoapsis - 120).
wait until eta:apoapsis < 120.
wait until kuniverse:timewarp:issettled.
print "Aligning for return".
rcs on.
lock steering to ship:retrograde.
set warpmode to "physics".
set warp to 3.
wait until eta:apoapsis < 5.
set warp to 0.
wait until eta:apoapsis < 1.
print "Deorbit!".
stage.
// Stage parachute
wait until ship:altitude < 35000.
print "Parachute deploy".
stage.

42
boot/orbiter.ks Normal file
View File

@@ -0,0 +1,42 @@
@lazyglobal off.
wait until ship:unpacked.
runoncepath("0:/lib/stage/v2.ks").
runoncepath("0:/lib/common.ks").
// First polar and first solar
//local target_azimuth is 355.
//local target_pitch is 5.
// First orbit and first scientific
local target_azimuth is 90.
local target_pitch is 6.5.
//local target_pitch is 2.0.
// First atmospheric analysis
// local target_azimuth is 60.
// local target_pitch is 5.
rcs off.
v2:launch(target_azimuth, target_pitch).
wait until eta:apoapsis < 30.
// Release upper stage and track prograde.
rcs on.
stage.
lock steering to prograde.
wait 1.
// Stabilize
wait until eta:apoapsis < 10.
local hdg is ship:prograde.
lock steering to hdg.
wait until steering_locked(0.001).
// Sequence solid motors
stage.
wait 8.
stage.
wait 8.
stage.

24
boot/sun-synchronous.ks Normal file
View File

@@ -0,0 +1,24 @@
@lazyglobal off.
wait until ship:unpacked.
rcs off.
runoncepath("0:/lib/common.ks").
runoncepath("0:/lib/stage/thor.ks").
runoncepath("0:/lib/stage/able.ks").
local target_inclination is 97.
local target_alt is 350_000.
local hdg is launch_azimuth(target_inclination, target_alt).
thor:launch(hdg, target_alt).
stage.
able:launch(hdg, target_alt).
warpto(time:seconds + (eta:apoapsis - 30)).
wait until eta:apoapsis < 30.
rcs on.
lock steering to ship:prograde.
wait until eta:apoapsis < 10.
stage.

37
boot/tv.ks Normal file
View File

@@ -0,0 +1,37 @@
@lazyglobal off.
wait until ship:unpacked.
rcs off.
runoncepath("0:/lib/common.ks").
runoncepath("0:/lib/stage/thor.ks").
runoncepath("0:/lib/stage/able.ks").
local target_alt is 1_200_000.
local target_ecc is 0.0025.
local hdg is launch_azimuth(89, target_alt).
set steeringmanager:pitchts to 3.
set steeringmanager:yawts to 3.
thor:launch(hdg, target_alt, 5, 300).
stage.
able:yeet(hdg, target_alt).
able:power_down().
wait 1.
set warpmode to "rails".
set warp to 2.
wait until eta:apoapsis < 180.
set warp to 1.
wait until eta:apoapsis < 150.
set warp to 0.
wait 1.
wait until kuniverse:timewarp:issettled.
able:power_up().
able:circularize(target_ecc).
wait 1.
rcs on.
panels on.
lock steering to sun:direction.
wait 1.
wait until steering_locked().
stage.

15
boot/v2_camera.ks Normal file
View File

@@ -0,0 +1,15 @@
@lazyglobal off.
wait until ship:unpacked.
runoncepath("0:/lib/stage/v2.ks").
local target_azimuth is 90.
v2:launch(target_azimuth).
wait until ship:verticalspeed < 0 and ship:altitude < 140000.
stage.
wait until stage:ready.
wait until ship:altitude < 75000.
stage.

17
boot/wac.ks Normal file
View File

@@ -0,0 +1,17 @@
@lazyglobal off.
wait until ship:unpacked.
lock throttle to 1.0.
local sustainer is ship:partsdubbed("ROE-Aerobee")[0].
//local tim is ship:partsdubbed("TinyTim").
local ks18 is ship:partsdubbed("ROE-25KS18000").
local nike is ship:partsdubbed("ROE-NikeM5E1").
local booster is choose nike[0] if ks18:empty else ks18[0].
stage.
wait until stage:ready.
wait until sustainer:thrust > booster:thrust.
stage.
wait until ship:verticalspeed < 0 and ship:altitude < 75000.
stage.

103
lib/common.ks Normal file
View File

@@ -0,0 +1,103 @@
@lazyglobal off.
global function steering_locked {
parameter epsilon is 0.1.
local rate_epsilon is epsilon * 0.1.
local angle_good is abs(steeringmanager:pitcherror) < epsilon and abs(steeringmanager:yawerror) < epsilon.
local rate_good is abs(ship:angularvel:x) < rate_epsilon and abs(ship:angularvel:y) < rate_epsilon.
return rate_good and angle_good.
}
global function launch_azimuth {
// from https://www.orbiterwiki.org/wiki/Launch_Azimuth
parameter target_inclination, target_alt.
local inertial_hdg is arcsin(cos(target_inclination) / cos(ship:latitude)).
local orbit_vel is sqrt(ship:body:mu / (target_alt + ship:body:radius)).
local body_vel is 2 * constant:pi * ship:body:radius / ship:body:rotationperiod.
local vxrot is orbit_vel * sin(inertial_hdg) - body_vel * cos(ship:latitude).
local vyrot is orbit_vel * cos(inertial_hdg).
return arctan(vxrot / vyrot).
}
global function ap_prograde {
local nd is node(time:seconds + eta:apoapsis, 0, 0, 1).
add(nd).
local target_hdg is rotatefromto(ship:prograde:forevector, nd:burnvector) * ship:prograde.
remove(nd).
return target_hdg.
}
global function obt_altitude {
if eta:apoapsis > eta:periapsis {
local since_ap is ship:obt:period - eta:apoapsis.
if since_ap < eta:periapsis {
return ship:obt:periapsis.
} else {
return ship:obt:apoapsis.
}
} else {
local since_pe is ship:obt:period - eta:periapsis.
if since_pe < eta:apoapsis {
ship:obt:apoapsis.
} else {
ship:obt:periapsis.
}
}
}
global function target_lan {
parameter target_lan, epsilon is 0.1.
local current_lan is mod(earth:rotationangle - ship:longitude - 90 + 360, 360).
local lan_diff is mod(current_lan - target_lan + 360, 360).
local target is time:now - 60 * (lan_diff / 4).
warpto(target - 10).
wait until time:now > target.
}
global function circular_vel {
parameter obt_alt is ship:altitude.
return sqrt(ship:body:mu / (obt_alt + ship:body:radius)).
}
global function orbital_vel {
parameter obt_alt.
return sqrt(ship:body:mu * (2 / (obt_alt + ship:body:radius) - 1 / ship:obt:semimajoraxis)).
}
global function circularization_dv {
return circular_vel(ship:obt:apoapsis) - orbital_vel(ship:obt:apoapsis).
}
global function burn_time {
parameter dv, engine.
local thrust is engine:possiblethrust.
local exhaust_vel is thrust / engine:maxmassflow.
local initial_mass is ship:mass.
return initial_mass * exhaust_vel * (1 - CONSTANT:E ^ (0 - dv / exhaust_vel)) / thrust.
}
global function hohmann_transfer_time {
parameter b, pe, ap.
local r1 is pe + b:radius.
local r2 is ap + b:radius.
return constant:pi * sqrt((r1+r2)*(r1+r2)*(r1+r2)/(8*b:mu)).
}
global function hohmann_transfer_dv {
parameter b, pe, ap.
local r1 is pe + b:radius.
local r2 is ap + b:radius.
return sqrt(b:mu/r1)*(sqrt(2*r2/(r1 + r2)) - 1).
}
global function predicted_ap {
local vel is ship:velocity:orbit:mag.
local rp is ship:altitude + ship:obt:body:radius.
local a is rp / 2 - ship:obt:body:mu/(vel*vel).
return (2*a - rp) - ship:obt:body:radius.
}

110
lib/moonmath.ks Normal file
View File

@@ -0,0 +1,110 @@
@lazyglobal off.
global moonmath is lex(
"calculate_launch", calculate_launch@,
"position", moon_position_at_time@
).
local function calculate_launch {
parameter target_inclination, azimuth, target_alt.
local time_fudge is 0.
local wait_time is 0.
local orbit_time is 0.
local burn_ra is 0.
local tt is hohmann_transfer_time(earth, target_alt, moon:obt:semimajoraxis).
print "Initial moon distance: " + moon:obt:semimajoraxis.
print "Initial travel time: " + tt.
local moon_vec is moon_position_at_time(time:seconds + tt + time_fudge).
local iterations is 0.
until iterations > 10 {
local next_tt is hohmann_transfer_time(earth, target_alt, moon_vec:mag - earth:radius).
print "Updated moon distance: " + (moon_vec:mag - earth:radius).
print "Updated travel time: " + next_tt.
local next_moon_vec is moon_position_at_time(time:seconds + next_tt + wait_time + orbit_time+time_fudge).
local err is abs((next_moon_vec - moon_vec):mag).
print "Position Error " + iterations + ": " + err.
set moon_vec to next_moon_vec.
set tt to next_tt.
set iterations to iterations + 1.
local rm is moon_vec:normalized.
local rt is(-1) * rm.
set burn_ra to mod(arctan2(rt:y,rt:x) + 360, 360).
// `w` is the unit vector normal to the launch orbital plane
local w_z is cos(target_inclination).
local w_y_1 is (0 - w_z*rm:y*rm:z + rm:x*sqrt(1 - rm:z*rm:z - w_z*w_z)) / (rm:x*rm:x + rm:y*rm:y).
local w_y_2 is (0 - w_z*rm:y*rm:z - rm:x*sqrt(1 - rm:z*rm:z - w_z*w_z)) / (rm:x*rm:x + rm:y*rm:y).
local w_x_1 is (0 - w_y_1*rm:y - w_z*rm:z)/rm:x.
local w_x_2 is (0 - w_y_2*rm:y - w_z*rm:z)/rm:x.
local launch_ra_1_cos is (w_z*w_x_1*sin(ship:latitude) + w_y_1*cos(ship:latitude)*cos(azimuth)) / (w_z*w_z-1)*cos(ship:latitude).
local launch_ra_2_cos is (w_z*w_x_2*sin(ship:latitude) + w_y_2*cos(ship:latitude)*cos(azimuth)) / (w_z*w_z-1)*cos(ship:latitude).
local launch_ra_1_sin is (w_z*w_y_1*sin(ship:latitude) - w_x_1*cos(ship:latitude)*cos(azimuth)) / (w_z*w_z-1)*cos(ship:latitude).
local launch_ra_2_sin is (w_z*w_y_2*sin(ship:latitude) - w_x_1*cos(ship:latitude)*cos(azimuth)) / (w_z*w_z-1)*cos(ship:latitude).
local launch_right_ascension_1 is arctan2(launch_ra_1_sin, launch_ra_1_cos).
local launch_right_ascension_2 is arctan2(launch_ra_2_sin, launch_ra_2_cos).
local current_right_ascension is earth:rotationangle + ship:longitude.
local wait_angle_1 is mod(360 + launch_right_ascension_1 - current_right_ascension, 360).
local wait_angle_2 is mod(360 + launch_right_ascension_2 - current_right_ascension, 360).
print "Need to rotate " + wait_angle_1 + " or " + wait_angle_2 + " degrees.".
local wait_angle is min(wait_angle_1, wait_angle_2).
print "Choosing " + wait_angle.
set wait_time to body:rotationperiod * wait_angle / 360.
print "That will take " + wait_time + " seconds.".
local launch_ra is wait_angle + earth:rotationangle + ship:longitude.
local orbit_angle is mod(burn_ra - launch_ra + 360, 360).
local orbit_frac is orbit_angle / 360.
set orbit_time to orbit_frac * 90 * 60.
if err < (moon:radius / 100) {
break.
}
}
return lex(
"launch_time", time:seconds + wait_time,
"moon_altitude", moon_vec:mag - earth:radius,
"burn_longitude", burn_ra
).
}
local function moon_position_at_time {
parameter t.
return position_at_time(moon, t).
}
global function position_at_time {
parameter bod, t.
local bod_orbit is bod:obt.
local delta_t is t - bod_orbit:epoch.
local revolutions is delta_t / bod_orbit:period.
local mean_anomaly is mod(revolutions * 360 + bod_orbit:meananomalyatepoch, 360).
local e is bod_orbit:eccentricity.
local e2 is e*e.
local e3 is e2*e.
local true_anomaly is mean_anomaly + (2*e - e3/4)*sin(mean_anomaly) + 5/4*e2*sin(2*mean_anomaly)+13/12*e3*sin(3*mean_anomaly).
local radius is bod_orbit:semimajoraxis * (1 - e2) / (1 + e*cos(true_anomaly)).
local sin_lan is sin(bod_orbit:longitudeofascendingnode).
local cos_lan is cos(bod_orbit:longitudeofascendingnode).
local sin_inc is sin(bod_orbit:inclination).
local cos_inc is cos(bod_orbit:inclination).
local sin_anom is sin(bod_orbit:argumentofperiapsis + true_anomaly).
local cos_anom is cos(bod_orbit:argumentofperiapsis + true_anomaly).
local x is radius * (cos_lan*cos_anom - sin_lan*sin_anom*cos_inc).
local y is radius * (sin_lan*cos_anom + cos_lan*sin_anom*cos_inc).
local z is radius * sin_inc * sin_anom.
return V(x, y, z).
}

208
lib/stage/able.ks Normal file
View File

@@ -0,0 +1,208 @@
@lazyglobal off.
global able is lex(
"launch", launch@,
"burn", burn@,
"orbit", do_orbit@,
"circularize", circularize@,
"yeet", yeet@,
"power_down", power_down@,
"power_up", power_up@
).
local function engine {
local early is ship:partsdubbed("ROE-AJ10Early").
local mid is ship:partsdubbed("ROE-AJ10Mid").
for eng in early {
return eng.
}
for eng in mid {
return eng.
}
}
local function ignite {
rcs on.
lock throttle to 1.0.
wait 3.
stage.
}
local function is_ablestar {
return not ship:partsdubbed("ROE-AJ10Mid"):empty.
}
local function yeet {
parameter hdg, tgt_alt.
power_down().
set warpmode to "physics".
set warp to 3.
if is_ablestar() {
wait until eta:apoapsis < 180.
} else {
wait until eta:apoapsis < 100.
}
set warp to 0.
wait until kuniverse:timewarp:issettled.
power_up().
rcs on.
local target is heading(hdg, ship:obt:trueanomaly - 180, -hdg).
lock steering to target.
if is_ablestar() {
wait until eta:apoapsis < 150.
} else {
wait until eta:apoapsis < 80.
}
lock throttle to 1.0.
wait 3.
stage.
wait until ship:obt:apoapsis > tgt_alt.
rcs off.
lock throttle to 0.0.
unlock steering.
wait 0.
}
local function do_orbit {
parameter hdg, burnout is false.
// power_down().
set warpmode to "physics".
set warp to 3.
wait until eta:apoapsis < 100.
set warp to 0.
wait until kuniverse:timewarp:issettled.
// power_up().
rcs on.
local target is heading(hdg, ship:obt:trueanomaly - 180, -hdg).
lock steering to target.
wait until eta:apoapsis < 80.
lock throttle to 1.0.
wait 3.
stage.
if burnout {
wait until engine():flameout.
} else {
wait until ship:velocity:orbit:mag > circular_vel().
}
// Fine-tune orbital speed w/ RCS fore/aft?
rcs off.
lock throttle to 0.0.
unlock steering.
wait 0.
}
local function circularize {
parameter target_ecc, max_vel_delta is 0.1.
power_down().
set warpmode to "physics".
set warp to 3.
wait until eta:apoapsis < 100.
set warp to 0.
wait until kuniverse:timewarp:issettled.
power_up().
rcs on.
lock steering to ship:prograde.
wait until eta:apoapsis < 80.
local second_burn is engine:ignition.
engine():shutdown().
lock throttle to 1.0.
wait 3.
engine():activate().
wait until ship:velocity:orbit:mag > circular_vel().
lock throttle to 0.0.
lock steering to lookdirup(ship:prograde:forevector, ship:up:forevector).
until false {
local threshold is 0.1.
local p is threshold / max_vel_delta.
local dv is circular_vel() - ship:velocity:orbit:mag.
local vert_vel is ship:verticalspeed * ship:up:forevector.
local vert_vel_d is 0.0 - vert_vel:mag.
local horz_vel_d is circular_vel() - (ship:velocity:orbit - vert_vel):mag.
local horz_factor is horz_vel_d * p.
local vert_factor is vert_vel_d * p.
if ship:obt:eccentricity < target_ecc or (abs(horz_factor) < threshold and abs(vert_factor) < threshold) {
set ship:control:fore to 0.
set ship:control:top to 0.
break.
}
set ship:control:fore to horz_factor.
set ship:control:top to vert_factor.
wait 0.
}
unlock steering.
rcs off.
wait 0.
}
local function burn {
lock steering to heading(hdg, 0, -hdg).
parameter hdg.
ignite().
wait 1.
rcs off.
set warpmode to "physics".
set warp to 3.
wait until ship:thrust = 0.
unlock steering.
unlock throttle.
set warp to 0.
wait until kuniverse:timewarp:issettled.
}
local function launch {
parameter hdg, target_alt.
local pitch_pid is pidloop(0.001, 0, 0, -90, 90, 1).
set pitch_pid:setpoint to target_alt.
local wanted_hdg is ship:facing.
lock steering to wanted_hdg.
ignite().
wait 1.
set warpmode to "physics".
set warp to 3.
until ship:thrust = 0 or ship:obt:periapsis > target_alt or eta:periapsis < eta:apoapsis {
local wanted_pitch is pitch_pid:update(time:seconds, ship:obt:apoapsis).
local neutral_pitch is ship:obt:trueanomaly / 2 - 90.
set wanted_hdg to heading(hdg, wanted_pitch, -hdg).
wait 0.
}
if ship:thrust <> 0 {
lock steering to ship:prograde.
wait until ship:thrust = 0.
}
unlock steering.
unlock throttle.
rcs off.
set warp to 0.
wait until kuniverse:timewarp:issettled.
}
local function power_down {
local avionics is ship:partsdubbed("able-avionics")[0].
local avi_mod is avionics:getmodule("ModuleProceduralAvionics").
avi_mod:doaction("shutdown avionics", true).
}
local function power_up {
local avionics is ship:partsdubbed("able-avionics")[0].
local avi_mod is avionics:getmodule("ModuleProceduralAvionics").
avi_mod:doaction("activate avionics", true).
}

85
lib/stage/agena.ks Normal file
View File

@@ -0,0 +1,85 @@
@lazyglobal off.
runoncepath("0:/lib/common.ks").
global agena is lex(
"orbit", do_orbit@,
"power_down", power_down@,
"power_up", power_up@,
"low_power", low_power@,
"separate", separate@,
"transfer_burn", transfer_burn@
).
local function do_orbit {
parameter hdg.
print "Agena startup".
print "Warping to burn".
set warpmode to "physics".
set warp to 3.
wait until eta:apoapsis < 140.
set warp to 0.
wait until kuniverse:timewarp:issettled.
print "RCS On. Locking heading".
rcs on.
local target is heading(hdg, ship:obt:trueanomaly - 180, -hdg).
lock steering to target.
wait until eta:apoapsis < 120.
print "Throttle up".
lock throttle to 1.0.
wait 3.
stage.
print "GO GO GO".
wait until ship:velocity:orbit:mag > circular_vel() and ship:obt:periapsis > 140000.
rcs off.
lock throttle to 0.0.
unlock steering.
wait 0.
print "Agena done".
}
local function power_down {
local avionics is ship:partsdubbed("agena-avionics")[0].
local avi_mod is avionics:getmodule("ModuleProceduralAvionics").
avi_mod:doaction("shutdown avionics", true).
}
local function power_up {
local avionics is ship:partsdubbed("agena-avionics")[0].
local avi_mod is avionics:getmodule("ModuleProceduralAvionics").
avi_mod:doaction("activate avionics", true).
}
local function low_power {
local avionics is ship:partsdubbed("agena-avionics")[0].
local power is avionics:resources[0].
return power:amount / power:capacity < 0.1.
}
local function separate {
rcs on.
lock steering to prograde.
lock throttle to 1.0.
wait 5.
lock throttle to 0.0.
unlock steering.
rcs off.
}
local function transfer_burn {
parameter target_vel.
// Shutdown engine for ullage
local engine is ship:partsdubbed("ROE-Agena")[0].
engine:shutdown().
lock throttle to 1.0.
wait 3.
// Engine on
engine:activate().
wait until ship:velocity:orbit:mag >= target_vel.
lock throttle to 0.0.
wait 0.
}

102
lib/stage/atlas.ks Normal file
View File

@@ -0,0 +1,102 @@
@lazyglobal off.
runoncepath("0:/lib/common.ks").
global atlas is lex(
"launch", launch@
).
local function launch {
parameter hdg, target_ap, target_pitch is 6.
lock throttle to 1.0.
local engine is ship:partsdubbed("ROE-LR89.2")[0].
stage.
wait until stage:ready.
wait until engine:thrust > (engine:maxthrust * 0.9).
stage.
local booster_drop is time:seconds + 160.
local target_vel is 150.
lock steering to heading(hdg, 90 - min(target_pitch, target_pitch * (ship:velocity:surface:mag / target_vel)), -hdg).
wait until ship:velocity:surface:mag > target_vel.
print "Heading stable, switching to gravity turn".
set warpmode to "physics".
set warp to 3.
lock steering to lookdirup(ship:srfprograde:forevector, ship:up:forevector).
wait until time:seconds > booster_drop.
set warp to 0.
wait until kuniverse:timewarp:issettled.
stage.
wait 2.
set warp to 3.
wait until ship:altitude > 100000.
print "Dropping Fairings".
if not ship:partsdubbed("SSTUHollowRing"):empty {
set warp to 0.
wait until kuniverse:timewarp:issettled.
print "Dropping Fairings".
stage.
wait 2.
set warp to 3.
}
print "Switching to target PE mode".
lock steering to insert_orbit_pe(hdg, target_ap).
wait until ship:thrust = 0.
unlock steering.
lock throttle to 0.0.
set warp to 0.
wait until kuniverse:timewarp:issettled.
}
local function drawvec {
parameter vec, color, desc.
local origin is ship:position.
return vecdraw(origin, origin + vec:normalized, color, desc, 5.0, TRUE, 0.2, TRUE, FALSE).
}
local function insert_orbit_pe {
parameter azimuth, target_ap.
//clearvecdraws().
local ap_hdg is ap_prograde().
local origin is ship:position.
//drawvec(ship:facing:forevector, RGB(0, 1, 0), "Ship Facing").
//drawvec(ap_hdg:forevector, RGB(1, 1, 0), "AP Prograde").
local ap_delta is ship:orbit:apoapsis - target_ap.
local cur_burn_angle is mod(vang(vxcl(ship:facing:forevector, ap_hdg:starvector), ap_hdg:forevector) + 360, 360).
local ap_burn_ang is symmetric_clamp(ap_delta/3000, 90).
local target_burn_hdg is angleaxis(ap_burn_ang, ap_hdg:starvector) * ap_hdg.
//drawvec(target_burn_hdg:forevector, RGB(1, 0, 0), "Non-azimuth-corrected burn vector").
// Vector pointing exactly towards our azimuth, flat with our orbital position
local azimuth_vector is heading(azimuth, 0, 0):forevector.
//drawvec(azimuth_vector, RGB(0, 1, 1), "Azimuth").
// Vector pointing exactly towards AP, flat with our orbital position
local steering_vector is vxcl(ship:up:forevector, target_burn_hdg:forevector).
//drawvec(steering_vector, RGB(1, 0, 1), "AP Steering Vector").
// Angle to rotate to bring our AP vector to our azimuth
local azimuth_ang is vang(steering_vector, azimuth_vector).
local azimuth_adjustment is angleaxis(-azimuth_ang, ship:up:forevector).
local azimuth_burn_hdg is azimuth_adjustment * target_burn_hdg.
//drawvec(azimuth_burn_hdg:forevector, RGB(0, 1, 0), "Azimuth-corrected burn vector").
local steering_ang is symmetric_clamp(vang(ship:facing:forevector, azimuth_burn_hdg:forevector), 10).
local steering_hdg is angleaxis(steering_ang, vcrs(ship:facing:forevector, azimuth_burn_hdg:forevector)) * ship:facing.
return steering_hdg.
}
local function symmetric_clamp {
parameter val, limit.
return min(max(val, -limit), limit).
}

172
lib/stage/centaur.ks Normal file
View File

@@ -0,0 +1,172 @@
@lazyglobal off.
runoncepath("0:/lib/common.ks").
global centaur is lex(
"orbit", do_orbit@,
"power_down", power_down@,
"power_up", power_up@,
"low_power", low_power@,
"separate", separate@,
"transfer_burn", transfer_burn@,
"burn_time", centaur_burn_time@,
"capture_burn", capture_burn@
).
local function do_orbit {
parameter hdg, target_ecc is 0.002, max_vel_delta is 0.1.
print "Centaur startup".
local dv is circularization_dv().
local circularization_time is centaur_burn_time(dv).
local half_circularization_time is centaur_burn_time(dv / 2).
print "Circularization is " + dv + "m/s over " + circularization_time + "s".
print "Will burn " + half_circularization_time + "s before AP".
local ignition_time is half_circularization_time.
local ullage_time is ignition_time + 3.
local steering_time is ullage_time + 20.
print "Warping to burn".
set warpmode to "physics".
set warp to 3.
wait until eta:apoapsis < steering_time.
set warp to 0.
wait 1.
wait until kuniverse:timewarp:issettled.
print "RCS On. Locking heading".
rcs on.
local target is heading(hdg, ship:obt:trueanomaly - 180, -hdg).
lock steering to target.
wait until eta:apoapsis < ullage_time.
print "Throttle up".
lock throttle to 1.0.
wait until eta:apoapsis < ignition_time.
stage.
print "GO GO GO".
wait until ship:velocity:orbit:mag > circular_vel() and ship:obt:periapsis > 140000.
lock throttle to 0.0.
lock steering to lookdirup(ship:prograde:forevector, ship:up:forevector).
until false {
local threshold is 0.1.
local p is threshold / max_vel_delta.
local dv is circular_vel() - ship:velocity:orbit:mag.
local vert_vel is ship:verticalspeed * ship:up:forevector.
local vert_vel_d is 0.0 - vert_vel:mag.
local horz_vel_d is circular_vel() - (ship:velocity:orbit - vert_vel):mag.
local horz_factor is horz_vel_d * p.
local vert_factor is vert_vel_d * p.
if ship:obt:eccentricity < target_ecc or (abs(horz_factor) < threshold and abs(vert_factor) < threshold) {
set ship:control:fore to 0.
set ship:control:top to 0.
break.
}
set ship:control:fore to horz_factor.
set ship:control:top to vert_factor.
wait 0.
}
rcs off.
unlock steering.
wait 0.
print "Centaur done".
}
local function power_down {
local avionics is ship:partsdubbed("centaur-avionics")[0].
local avi_mod is avionics:getmodule("ModuleProceduralAvionics").
avi_mod:doaction("shutdown avionics", true).
}
local function power_up {
local avionics is ship:partsdubbed("centaur-avionics")[0].
local avi_mod is avionics:getmodule("ModuleProceduralAvionics").
avi_mod:doaction("activate avionics", true).
}
local function low_power {
local avionics is ship:partsdubbed("centaur-avionics")[0].
local power is avionics:resources[0].
return power:amount / power:capacity < 0.1.
}
local function separate {
rcs on.
lock steering to prograde.
lock throttle to 1.0.
wait 5.
lock throttle to 0.0.
unlock steering.
rcs off.
}
local function transfer_burn {
parameter target_ap.
// Shutdown engine for ullage
local engine is ship:partsdubbed("ROE-RL10Fixed")[0].
engine:shutdown().
lock throttle to 1.0.
wait 3.
// Engine on
engine:activate().
wait until ship:obt:apoapsis > target_ap.
lock throttle to 0.0.
wait 0.
}
local function centaur_burn_time {
parameter dv.
local engine is ship:partsdubbed("ROE-RL10Fixed")[0].
return burn_time(dv, engine).
}
local function capture_burn {
parameter threshold is 250_000.
local engine is ship:partsdubbed("ROE-RL10Fixed")[0].
engine:shutdown().
local initial_pe is ship:obt:periapsis.
wait 1.
warpto(eta:periapsis + time:seconds - 30).
wait 1.
wait until kuniverse:timewarp:warp = 0.
wait until kuniverse:timewarp:issettled.
power_up().
rcs on.
lock steering to ship:retrograde.
wait 1.
wait until steering_locked().
lock throttle to 1.
wait 3.
engine:activate().
if initial_pe > threshold {
wait until ship:obt:periapsis < (threshold/2).
lock throttle to 0.
engine:shutdown().
power_down().
unlock steering.
wait 1.
warpto(eta:periapsis + time:seconds - 30).
wait 1.
wait until kuniverse:timewarp:warp = 0.
wait until kuniverse:timewarp:issettled.
wait 1.
power_up().
lock steering to ship:retrograde.
wait 1.
wait until steering_locked().
lock throttle to 1.
wait 3.
engine:activate().
wait until ship:obt:apoapsis < (threshold*2).
} else {
wait until ship:obt:eccentricity < 1 and ship:obt:apoapsis < threshold*2.
}
engine:shutdown().
lock throttle to 0.
power_down().
wait 1.
}

72
lib/stage/probe.ks Normal file
View File

@@ -0,0 +1,72 @@
@lazyglobal off.
runoncepath("0:/lib/common.ks").
global probe is lex(
"power_down", power_down@,
"power_up", power_up@,
"capture_burn", capture_burn@
).
local function capture_burn {
parameter threshold is 250_000.
local engine is ship:partsdubbed("ROE-generic-quarter")[0].
engine:shutdown().
local initial_pe is ship:obt:periapsis.
wait 1.
warpto(eta:periapsis + time:seconds - 30).
wait 1.
wait until kuniverse:timewarp:warp = 0.
wait until kuniverse:timewarp:issettled.
power_up().
rcs on.
lock steering to ship:retrograde.
wait 1.
wait until steering_locked().
lock throttle to 1.
engine:activate().
if initial_pe > threshold {
wait until ship:obt:periapsis < (threshold/2).
lock throttle to 0.
engine:shutdown().
lock steering to sun:direction.
wait 1.
wait until steering_locked().
power_down().
unlock steering.
wait 1.
set warpmode to "rails".
warpto(eta:periapsis + time:seconds - 30).
wait 1.
wait until kuniverse:timewarp:warp = 0.
wait until kuniverse:timewarp:issettled.
wait 1.
power_up().
lock steering to ship:retrograde.
wait 1.
wait until steering_locked().
lock throttle to 1.
engine:activate().
wait until ship:obt:apoapsis < (threshold*2).
} else {
wait until ship:obt:eccentricity < 1 and ship:obt:apoapsis < threshold*2.
}
engine:shutdown().
lock throttle to 0.
power_down().
wait 1.
}
local function power_down {
local avionics is ship:rootpart.
local avi_mod is avionics:getmodule("ModuleProceduralAvionics").
avi_mod:doaction("shutdown avionics", true).
}
local function power_up {
local avionics is ship:rootpart.
local avi_mod is avionics:getmodule("ModuleProceduralAvionics").
avi_mod:doaction("activate avionics", true).
}

63
lib/stage/thor.ks Normal file
View File

@@ -0,0 +1,63 @@
@lazyglobal off.
global thor is lex(
"launch", launch@
).
local function launch {
parameter hdg, target_alt, target_pitch is 6, target_vel is 150.
lock throttle to 1.0.
local engine is ship:partsdubbed("ROE-LR79")[0].
local boosters is ship:partsdubbed("ROE-Castor1").
stage.
wait until stage:ready.
wait until engine:thrust > (engine:maxthrust * 0.9).
stage.
if boosters:length > 0 {
when boosters[0]:thrust < 1 then {
print "Dropping boosters".
stage.
}
}
lock steering to heading(hdg, 90 - min(target_pitch, target_pitch * (ship:velocity:surface:mag / target_vel)), -hdg).
wait until ship:velocity:surface:mag > target_vel.
// wait until steering_locked().
print "Heading stable, switching to gravity turn".
set warp to 3.
lock steering to lookdirup(ship:srfprograde:forevector, ship:up:forevector).
wait until ship:altitude > 100000.
if not ship:partsdubbed("SSTUHollowRing"):empty {
set warp to 0.
wait until kuniverse:timewarp:issettled.
print "Dropping Fairings".
stage.
wait 2.
set warp to 3.
}
// print "Switching to target AP mode".
// local pitch_pid is pidloop(0.0003, 0, 0, -90, 90, 1).
// set pitch_pid:setpoint to target_alt.
// local wanted_hdg is ship:srfprograde.
// lock steering to wanted_hdg.
//
// until ship:thrust = 0 {
// local wanted_pitch is pitch_pid:update(time:seconds, ship:obt:apoapsis).
// local neutral_pitch is ship:obt:trueanomaly / 2 - 90.
// set wanted_hdg to heading(hdg, wanted_pitch, -hdg).
// }
wait until ship:thrust = 0.
unlock steering.
lock throttle to 0.0.
set warp to 0.
wait until kuniverse:timewarp:issettled.
}

37
lib/stage/v2.ks Normal file
View File

@@ -0,0 +1,37 @@
@lazyglobal off.
runoncepath("0:/lib/common.ks").
global v2 is lex(
"launch", launch@
).
local function launch {
parameter hdg, target_pitch is 10.
lock throttle to 1.0.
local engine is 0.
// local a4 is ship:partsdubbed("ROE-A4").
local xlr41 is ship:partsdubbed("ROE-XLR41").
local naa75 is ship:partsdubbed("ROE-A7").
local engine is choose naa75[0] if xlr41:empty else xlr41[0].
stage.
wait until stage:ready.
wait until engine:thrust > (engine:maxthrust * 0.9).
stage.
print "Beginning initial pitchover".
local target_vel is 150.
lock steering to heading(hdg, 90 - min(target_pitch, target_pitch * (ship:velocity:surface:mag / target_vel)), -hdg).
wait until ship:velocity:surface:mag > target_vel.
//wait until steering_locked().
print "Heading stable, switching to gravity turn".
lock steering to lookdirup(ship:srfprograde:forevector, ship:up:forevector).
wait until ship:thrust = 0.
unlock throttle.
unlock steering.
}

259
lib/switch.ks Normal file
View File

@@ -0,0 +1,259 @@
local function iterate {
parameter maneuver.
// `maneuver` is a lexicon of:
// "mass" - vehicle mass at start of maneuver
// "mu" - gravitational constant
// "hmax" - maximum step size
// "itmax" - maximum number of iterations
// "r0" - initial position
// "v0" - initial velocity
// "u0" - initial heading
// "du0" - initial change in heading
// "burns" - list of lexicon
// "start" - burn start time
// "end" - burn end time
// "initial_coast" - either start time of coast, or `false` if none
// "stages" - list of lexicon
// "thrust" - engine thrust
// "massflow" - fuel consumption of engine
// "fuel" - total amount of fuel in the stage
// "boiloff_rate" - how quickly fuel evaporates when not being used
// "dry_mass" - mass lost when vehicle stages
// "c" - target orbit parameters (TODO)
local num_legs is burns:length * 2.
if initial_coast = false {
set num_legs to num_legs - 1.
}
for iter in RANGE(itmax) {
local q0 is list(u0:x, u0:y, y0:z, du0:x, du0:y, du0:z).
local x0 is list(r0:x, r0:y, r0:z, v0:x, v0:y, v0:z).
local xf is list(0.0, 0.0, 0.0, 0.0, 0.0, 0.0).
local qf is list(0.0, 0.0, 0.0, 0.0, 0.0, 0.0).
// Initialization of matrix of partials
// z(i,j) partial of state and costate with respect to initial costate and switching times
// e(i,j) partial of right end variables and switching conditions with respect to initial costate and switching times
local z is list().
local e is list().
for i in RANGE(12) {
z:add(list()).
e:add(list()).
for j in RANGE(6 + num_legs) {
z[i]:add(0.0).
e[i]:add(0.0).
}
e[i]:add(0.0).
}
local leg is 0.
local leg5 is 5.
local leg6 is 6.
local leg7 is 7.
local l7 is num_legs+6.
local ump is 0.0.
local uk is maneuver:mu.
local prev_burn is false.
for burn in maneuver:burns {
if (leg <> 0) or (initial_coast <> false) {
local phi is list().
local dphi is list().
for i in range(6) {
phi:add(list()).
dphi:add(list()).
for j in range(6) {
phi[i]:add(0.0).
dphi[i]:add(0.0).
}
}
local start is false.
if prev_burn <> false {
set start to prev_burn:end.
} else {
set start to maneuver:initial_coast.
}
local end is burn:start.
local t is end - start.
// phi(i,j) partial of state at end of coast with respect to state at start of coast
// dphi(i,j) partial of costate at end of coast with respect to state at start of coast
coast (x0, q0, xf, qf, phi, dphi, uk, t, no).
local dz is list().
for i in range(12) {
dz:add(list()).
for j in RANGE(leg6) {
dz[i]:add(0.0).
}
}
for i in range(6) {
local i6 is i + 6.
for j in range(leg6) {
for k in range(6) {
set dz[i][j] to dz[i][j] + phi[i][k] * z[k][j].
set dz[i6][j] to dz[i6][j] + phi[i][k] * z[k+6][j] + dphi[i][k] * z[k][j].
}
}
}
// Update matrix of partials Z
for i in range(12) {
for j in range(leg6) {
set z[i][j] to dz[i][j].
}
}
local um is sqrt(qf[0]*qf[0]+qf[1]*qf[1]+qf[2]*qf[2]).
local cbmu is burn:thrust / (mass*um).
for i in range(3) {
set z[i+3][leg6] to -cbmu * qf[i].
}
if leg <> 0 {
// Calculation of switching condition and corresponding partial
set e[leg5][l7] to ump - um.
for j in range(leg5+1) {
set e[leg5][j] to -e[leg5][j].
for k in range(3) {
set e[leg5][j] to e[leg5][j] + (qf[k]/um)*z[k+6][j].
}
}
}
set leg to leg + 1.
set leg5 to leg + 5.
set leg6 to leg + 6.
set leg7 to leg + 7.
// Calculation of transversality condition and corresponding partial with respect to initial costate and switching times
local r2 is xf[0]*xf[0] + xf[1]*xf[1] + xf[2]*xf[2].
local rs is xf[0]*qf[0] + xf[1]*qf[1] + xf[2]*qf[2].
local c3 is -uk / (r2 * sqrt(r2)).
local c4 is -3.0 * c3 * rs / r2.
set e[leg5][l7] to xf[3]*qf[3]+xf[4]*qf[4]+xf[5]*qf[5] - c3*rs - e[leg5][l7].
set dummy to list(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0).
for i in range(3) {
set dummy[i] to -c3*qf[i]-c4*xf[i].
set dummy[i+3] to qf[i+3].
set dummy[i+6] to - c3 * xf[i].
set dummy[i+9] to xf[i+3].
}
for j in range(leg7) {
for k in range(12) {
set e[leg5][j] to -dummy[k]*z[k][j] + e[leg5][j].
}
}
for j in range(leg7) {
set e[leg5][j] to -e[leg5][j].
}
set e[leg5][leg5] to 0.0.
set x0 to xf.
set q0 to qf.
set xf to list(0.0, 0.0, 0.0, 0.0, 0.0, 0.0).
set qf to list(0.0, 0.0, 0.0, 0.0, 0.0, 0.0).
}
// burn
set leg to leg + 1.
set leg5 to leg + 5.
set leg6 to leg + 6.
set leg7 to leg + 7.
set prev_burn to burn.
}
// When we have convergeence, break
}
}
local function coast {
parameter x0, q0, xf, qf, phi, dphi, uk, t, no.
local jump is false.
local rm0 is sqrt(x0[0]*x0[0] + x0[1]*x0[1] + x0[2]*x0[2]).
local drm0 is (x0[0]*q0[0] + x0[1]*q0[1] + x0[2]*q0[2])/rm0.
local sig0 is x0[0]*x0[3] + x0[1]*x0[4] + x0[2]*q0[5].
local dsig0 is x0[3]*q0[0] + x0[4]*q0[1] + x0[5]*q0[2] + x0[0]*q0[3] + x0[1]*q0[4] + x0[2]*q0[5].
local alpha is x0[3]*x0[3] + x0[4]*x0[4] + x0[5]*x0[5] - 2.0 * uk / rm0.
local h0 is list(
x0[1]*x0[5] - x0[2]*x0[4],
x0[2]*x0[3] - x0[0]*x0[5],
x0[0]*x0[4] - x0[1]*x0[3]
).
local p0 is (h0[0]*h0[0] + h0[1]*h0[1] + h0[2]*h0[2])/uk.
local psy is t/p0.
local alpsq is sqrt(-alpha). // This probably blows up for non-eliptical orbits?
local s0 is 0.0.
local s1 is 0.0.
local s2 is 0.0.
local s3 is 0.0.
local ft is t.
local rm is rm0.
until false {
local alpsy is psy * alpsq.
set s0 to cos(alpsy*CONSTANT:RadTodeg).
set s1 to sin(alpsy*CONSTANT:RadToDeg)/alpsq.
set s2 to (s0 - 1.0) / alpha.
set s3 to (s1 - psy) / alpha.
set ft to rm0 * s1 + sig0 * s2 + uk * s3.
set rm to rm0*s0 + sig0*s1 + uk*s2.
if jump {
break.
}
set psy to psy + (t-ft) / rm.
if abs(t-ft) < abs(t) * 0.00001 {
set jump to true.
}
}
print psy.
print alpha.
print ft.
local fm1 is -uk * s2 / rm0.
local f is 1.0 + fm1.
local fd is -uk * s1 / (rm * rm0).
local g is ft - uk * s3.
local gdm1 is -uk * s2 / rm.
local gd is 1.0 + gdm1.
local ukr3 is uk / (rm * rm * rm).
local ukr03 is uk / (rm0 * rm0 * rm0).
local dalph is 2.0 * (x0[3]*q0[3] + x0[4]*q0[4] + x0[5]*q0[5] + ukr03 * (x0[0]*q0[0] + x0[1]*q0[1] + x0[2]*q0[2])).
local dapa is dalph/alpha.
local dapa2 is dapa/alpha.
local dpsy is -(drm0*s1 + dsig0*s2 + rm0*(psy*s0-s1)*dapa*0.5 + sig0*(psy*s1*0.5 - s2)*dapa + uk*(psy - 1.5*s1 + psy*s0*0.5)*dapa2)/rm.
local ds0 is (alpha*dpsy + 0.5*psy*dalph)*s1.
local ds1 is s0*dpsy + (psy*s0 - s1)*dapa*0.5.
local ds2 is s1*dpsy + (0.5*psy*s1 - s2)*dapa.
local ds3 is s2*dpsy + (psy - 1.5*s1 + 0.5*psy*s0)*dapa2.
local s4 is (s2 - psy*psy*0.5)/alpha.
local ds4 is s3*dpsy + (psy*psy*0.5 - 2.0*s2 + 0.5*psy*s1)*dapa2.
local s5 is (s3 - psy*psy*psy/6.0)/alpha.
local ds5 is s4*dpsy+(psy*psy*psy/6.0 + (2.0*psy - 2.5*s1 + 0.5*psy*20)/alpha)*dapa2.
local u is s2*ft + uk*(psy*s4 - 3.0*s5).
local du is ds2*ft + uk*(dpsy*s4 + psy*ds4 - 3.0*ds5).
local drm is 20*drm0 + ds0*rm0 + s1*dsig0 + ds1*sig0 + uk*ds2.
local df is (-uk*ds2 - fm1*drm0)/rm0.
local dg is -uk*ds3.
local dgd is (-uk*ds2 - gdm1*drm)/rm.
local r01 is rm0*rm.
local dr01 is rm*drm0 + drm*rm0.
local dfd is (-uk*ds1 - fd*dr01)/r01.
for i in range(3) {
set xf[i] to x0[i]*f + x0[i+3]*g.
set xf[i+3] to x0[i]*fd + x0[i+3]*gd.
set qf[i] to x0[i]*df + x0[i+3]*dg + q0[i]*f + q0[i+3]*g.
set qf[i+3] to x0[i]*dfd + x0[i+3]*dgd + q0[i]*fd + q0[i+3]*gd..
}
if no = false {
return.
}
// calculation of partials
}
local function test_coast {
local x0 is list(4551.3085900, 4719.8398400, 25.0576324, 5.5990610, -5.4170895, -0.0118389).
local q0 is list(0.4601788, -0.8868545, 0.0415273, -0.0004394, -0.0010504, -0.0004081).
local uk is 398601.5.
local xf is list(0.0, 0.0, 0.0, 0.0, 0.0, 0.0).
local qf is list(0.0, 0.0, 0.0, 0.0, 0.0, 0.0).
local t is 2047.6868 - 934.
coast(x0, q0, xf, qf, list(), list(), uk, t, false).
print xf.
print qf.
}
test_coast().

35
notes.md Normal file
View File

@@ -0,0 +1,35 @@
Altitude | dV | Lead Angle | Offset | Status
-----------------------------------------------------------
Day 0:
391037637 | 3068.9 | 1.50 | 7000000 | Miss
391037637 | 3068.9 | 1.33 | 7000000 | Glancing impact
391037637 | 3068.9 | 1.33 | 6500000 | Glancing impact
391037637 | 3068.9 | 1.25 | 7000000 | Overcorrected impact
391037637 | 3068.9 | 1.25 | 7500000 | Glancing, but better
391037637 | 3068.9 | 1.10 | 7500000 | Overcorrected impact
391037637 | 3068.9 | 1.10 | 8000000 | Clean impact, slightly overcorrected
Day 4:
399817493 | 3065.4 | 1.10 | 8000000 | Clean impact, slightly overcorrected
Day 8:
393926503 | 3065.3 | 1.10 | 8000000 | Glancing, maybe burned too early?
Day 12:
373127715 | 3045.4 | 1.10 | 8000000 | Glancing, maybe burned too early?
Day 16:
354660048 | 3041.3 | 1.10 | 8000000 | Miss
| 1.50 | 8000000 | Glancing impact
| 1.75 | 8000000 | Clean impact
Day 20:
361419747 | 3048.6 | 1.10 | 8000000 | Clean impact
Day 24:
Day 28:
LUNAR_AP -> LUNAR_PE
1.10 -> 1.75

16
todo.md Normal file
View File

@@ -0,0 +1,16 @@
# Next Session
* Write new ascent guidance program for Gemini & future
* Design and fly a seat-of-our-pants lunar lander
# Overall Plan
* Lunar lander
* First lunar orbiter/mapper once science unlocks
* Get as much moon science as possible
* Also lots of science in earth orbit here?
* Gemini
# Optional science stuff
* Get an orbital perturbation probe up just so we have it
* Maybe another lunar probe with orbital perturbation as well?
* Bio capsule in space high
* New experiments when they unlock?