Skip to content

Instantly share code, notes, and snippets.

@kuzetsa
Forked from KK4TEE/first.ks
Last active December 3, 2015 16:48
Show Gist options
  • Save kuzetsa/2d837f1fadb5a5e39eea to your computer and use it in GitHub Desktop.
Save kuzetsa/2d837f1fadb5a5e39eea to your computer and use it in GitHub Desktop.
Orbital Injection for K-OS mod (kerbal space program)
// injection.ks
// Orbital Injection for K-OS mod (kerbal space program)
DECLARE altitudeMinimum is (70000 * 1.001). // make sure we stay out of atmosphere
DECLARE targetAltitude is 80000. // Target circular-ish orbit (try really hard)
DECLARE limitQ is 0.14. // threshold where we start to throttle back due to drag (Q)
DECLARE stillBreathing is (68955 / 1.001). // effects of the atmosphere (Q) exists
DECLARE hundus is 0.0001. // hundred us (microseconds)
DECLARE ASL is 600000. // sea level is not actually zero
DECLARE ASLHalf is (ASL / 2). //
DECLARE targetSMA is targetAltitude + ASL. // used for orbital velocity calculation
DECLARE grav is 9.807. // gravity at sea level
DECLARE mu is (grav * (ASL ^ 2)). // Standard gravitational parameter for kerbin
DECLARE targetOVel is sqrt(mu / targetSMA). // circular orbit should be this speed
// Set the ship to a known configuration
SAS off. // this would cause an issue anyway.
lock throttle to 0. // Throttle is a decimal from 0.0 to 1.0
set TVAL to 0. // initialize now with a safe value. "because for reasons" [tm]
set CleanWarp to 0. // when a warp is about to start, can't be "under acceleration"
clearscreen.
set runmode to 2. // Safety in case we start mid-flight
if (ALT:RADAR < 50) { // Guess if we are waiting for take off
set runmode to 1.
}
until runmode = 0 { // Orbital injection flight control loop continues until runmode 0
set curvey to (min(((max((ln(150000 - min(altitudeMinimum, SHIP:ALTITUDE)) - 11), 0) ^ 6.31) * 163), 95)-5).
set failgrade to arctan((SHIP:VERTICALSPEED / max(SHIP:GROUNDSPEED, 0.0001))). // PROGRADE is reserved word
if (SHIP:ALTITUDE < stillBreathing) { // optimization: evaluating once per physics update is sufficient.
set cutieQ to SHIP:Q. // Value used per-pass doesn't change anyway.
set TVAL to min((limitQ / cutieQ), 1). // Drag limiting, apply this throttle can be done LATER
if (SHIP:APOAPSIS > 256) { // compute targetPitch for gravity turn
set tmp1 to min(sqrt(cutieQ), 0.09). // Reduced AoA at MaxQ, but Lower Q allows more turn
set tmp2 to min((1 / tmp1), 11). // up to 11
set tmp3 to min((tmp2 / 3), 3). // up to 3, hits limit faster
set tmp4 to (failgrade - tmp2).
set tmp5 to (curvey - tmp3).
set tmp6 to max(tmp4, tmp5).
set targetPitch to max(tmp6, (0 - 5)). // 5 degrees below horizon is low enough
}
else {
// Pitch over VERY gradually, but start gravity turn much early after only 200 meters
set targetPitch to (min(((max((ln(150000 - min(altitudeMinimum, SHIP:ALTITUDE)) - 11), 0) ^ 6.31) * 163), 95)-15).
}
}
else {
set cutieQ to (0 - 999). // there is no Q in space
set targetPitch to (0 - 1).
}
if (runmode = 1) { // Ship is on the launchpad
lock steering to UP. // Point the rocket straight up
set TVAL to 1. // Throttle up to 100% (AFTER validation / logical sanity checks)
stage. // Same thing as pressing Space-bar
set runmode to 2. // Go to the next runmode
}
else if (runmode = 2) {
lock steering to UP. // VETO: do not gravity turn during the first few meters
if (SHIP:APOAPSIS > 128) {
// Once apoapsis is higher than 128 meters, go to Gravity Turn mode
set runmode to 3.
}
else {
wait hundus.
}
} // Make sure you always close out your if statements.
else if (runmode = 3) { // Gravity turn
if (targetPitch >= (0 - 2)) {
lock steering to heading(90, targetPitch).
}
if (SHIP:APOAPSIS > targetAltitude) {
lock throttle to 0. // Engines off. NOW!!!
set TVAL to 0. // make sure the engines don't come back on later.
set CleanWarp to (0 - 999). // request warp
set runmode to 4. // warp code is in the next runmode
}
else {
wait hundus.
}
}
else if (runmode = 4) { // Coast to edge of atmosphere, warp to Apoapsis
if (SHIP:ALTITUDE <= stillBreathing) { // continue to follow the gravity turn curve
if (targetPitch >= (0 - 7)) {
lock steering to heading(90, targetPitch).
}
else {
lock throttle to 0. // Engines off. NOW!!!
set TVAL to 0. // make sure the engines don't come back on later.
wait hundus.
lock steering to heading(90, (0 - 1)).
}
wait hundus.
}
else if (SHIP:ALTITUDE > altitudeMinimum) { // warping in the atmosphere could've ... NOPE!!!
lock throttle to 0. // Engines off. NOW!!!
set TVAL to 0. // make sure the engines don't come back on later.
if (ETA:APOAPSIS >= 135) {
wait hundus.
if ((CleanWarp + 995) < 0) {
lock steering to heading(90, (0 - 1)).
wait hundus.
set CleanWarp to (0 - 42). /// request the actual warp
}
}
}
// STOP ACCELERATING!!!
if (((CleanWarp + 40) < 0) and ((CleanWarp + 45) > 0)) {
SET WARP to 0. // just in case we were already warping.
lock steering to heading(90, (0 - 1)).
lock throttle to 0. // Engines off. NOW!!!
wait 0.25. // 250 milliseconds
SET WARP to 0. // just in case we were already warping.
lock throttle to 0. // Engines off. NOW!!!
wait 0.25. // 250 milliseconds
SET WARP to 0. // just in case we were already warping.
lock throttle to 0. // Engines off. NOW!!!
set TVAL to 0. // make sure the engines don't come back on later.
wait 2. // 2 full seconds (total up to this point should be 2 and a half seconds)
set CleanWarp to 3. // request up to 50x warp
}
if ((ETA:APOAPSIS >= 270) and (CleanWarp >= 3)) { // 50x is good for gravity turn --> circularization warp
wait 1.
SET WARP to 3.
set CleanWarp to 3. // lock out all the higher warp levels
}
else if ((ETA:APOAPSIS < 270) and (ETA:APOAPSIS >= 175) and (CleanWarp >= 2)) {
wait 0.5.
SET WARP to 2.
set CleanWarp to 2. // lock out all the higher warp levels
}
else if ((ETA:APOAPSIS < 175) and (ETA:APOAPSIS >= 120) and (CleanWarp >= 1)) {
wait 0.2.
SET WARP to 1.
set CleanWarp to 1. // lock out all the higher warp levels
}
else if (ETA:APOAPSIS < 90) { // DISABLE warp here
wait hundus.
SET WARP to 0.
set CleanWarp to 0. // we're done here
lock steering to heading(90, (0 - 1)).
wait 0.25.
lock steering to heading(90, (0 - 1)).
wait 0.25.
lock steering to heading(90, (0 - 1)).
wait 0.25.
lock steering to heading(90, (0 - 1)).
wait 0.25.
lock steering to heading(90, (0 - 1)).
set runmode to 5.
}
else { // "all other cases" means something unplanned has happened???
wait hundus.
}
}
else if (runmode = 5) { // Burn to raise Periapsis above atmosphere
if ((ETA:APOAPSIS >= 0) and (ETA:APOAPSIS < 30) and (ETA:PERIAPSIS > ETA:APOAPSIS)) {
lock steering to heading(90, (0 - 1)). // attempt to prevent apoapsis from rising
wait hundus.
set sanitize1 to min((ETA:APOAPSIS), 300). // try to keep the apoapsis from increasing
set sanitize2 to max((sanitize1 - 0.0001), 0).
set sanitize3 to max((sanitize2 / 37), 0.0001).
set sanitize4 to min(sqrt((2/11)), 0.43).
set sanitize5 to max((sanitize3 ^ sanitize4), 0.0001).
set sanitize6 to min((1 - sanitize5), 1.0).
set sanitize7 to max(sanitize6, 0.1).
set TVAL to sanitize7. // The kraken likes to divide by zero
lock throttle to TVAL. // ASAP: For better burn accuracy / timing optimization
}
else if ((ETA:APOAPSIS > ETA:PERIAPSIS) and ((SHIP:ORBIT:PERIOD - ETA:APOAPSIS) < 45)) {
lock steering to heading(90, 5). // we're falling back to kerbin, so point nose up
wait hundus.
set sanitize1 to max((SHIP:PERIAPSIS), 1). // gently burn to increase periapsis.
set sanitize2 to max((altitudeMinimum - sanitize1), 1).
set sanitize3 to max((altitudeMinimum - stillBreathing), 1).
set sanitize4 to max((sanitize2 / sanitize3), 0.1).
set sanitize5 to max(sqrt(2.0), 1.4).
set sanitize6 to max((sanitize4 ^ sanitize5), 0.1).
set sanitize7 to min(sanitize6, 1.0).
set TVAL to sanitize7. // The kraken likes to divide by zero
lock throttle to TVAL. // ASAP: For better burn accuracy / timing optimization
}
else { // the engine should probably be off?
set TVAL to 0.
lock throttle to TVAL.
if ((ETA:APOAPSIS > ETA:PERIAPSIS) and (SHIP:PERIAPSIS < altitudeMinimum)) {
set runmode to 9037. // Notify the pilot or operator from control
}
wait hundus.
}
if (SHIP:PERIAPSIS > altitudeMinimum) { // check for non-decaying orbit
if (SHIP:PERIAPSIS > targetAltitude) { // check exit condition
lock throttle to 0. // ASAP!!! (prevent overshoot)
set TVAL to 0.
set runmode to 10.
}
else if (SHIP:PERIAPSIS > altitudeMinimum) { // double check, we're about to WARP THERE!!!
lock throttle to 0. // ASAP!!! (prevent overshoot)
set TVAL to 0.
set CleanWarp to (0 - 999). // request warp
set runmode to 6.
}
else {
wait hundus.
}
}
}
else if (runmode = 6) { // Warp to current Periapsis
if (SHIP:PERIAPSIS <= altitudeMinimum) { // This orbit is no good.
set CleanWarp to 0. // don't bother warping
set runmode to 9037. // Notify the pilot or operator from control
}
else if (SHIP:PERIAPSIS > altitudeMinimum) {
if (ETA:PERIAPSIS >= 135) {
wait hundus.
if ((CleanWarp + 995) < 0) {
set CleanWarp to (0 - 42). /// request the actual warp
}
}
}
// STOP ACCELERATING!!!
if (((CleanWarp + 40) < 0) and ((CleanWarp + 45) > 0)) {
SET WARP to 0. // just in case we were already warping.
lock steering to heading(90, 0). // point ship at the horizon
lock throttle to 0. // Engines off. NOW!!!
wait 0.25. // 250 milliseconds
SET WARP to 0. // just in case we were already warping.
lock throttle to 0. // Engines off. NOW!!!
wait 0.25. // 250 milliseconds
SET WARP to 0. // just in case we were already warping.
lock throttle to 0. // Engines off. NOW!!!
set TVAL to 0. // make sure the engines don't come back on later.
wait 2. // 2 full seconds (total up to this point should be 2 and a half seconds)
set CleanWarp to 3. // request up to 50x warp
}
if ((ETA:PERIAPSIS >= 270) and (CleanWarp >= 3)) { // 50x is good for gravity turn --> circularization warp
wait 1.
SET WARP to 3.
set CleanWarp to 3. // lock out all the higher warp levels
}
else if ((ETA:PERIAPSIS < 270) and (ETA:PERIAPSIS >= 175) and (CleanWarp >= 2)) {
wait 0.5.
SET WARP to 2.
set CleanWarp to 2. // lock out all the higher warp levels
}
else if ((ETA:PERIAPSIS < 175) and (ETA:PERIAPSIS >= 120) and (CleanWarp >= 1)) {
wait 0.2.
SET WARP to 1.
set CleanWarp to 1. // lock out all the higher warp levels
}
else if (ETA:PERIAPSIS < 50) { // DISABLE warp here
wait hundus.
SET WARP to 0.
set CleanWarp to 0. // we're done here
lock steering to heading(90, 0).
wait 0.25.
lock steering to heading(90, 0).
wait 0.25.
lock steering to heading(90, 0).
wait 0.25.
lock steering to heading(90, 0).
wait 0.25.
lock steering to heading(90, 0).
set runmode to 7.
}
else { // "all other cases" could mean something unplanned [entering runmode: 9037] probably?
wait hundus.
}
}
else if (runmode = 7) { // Burn to raise Apoapsis to at least targetAltitude
lock steering to heading(90, 0).
if ((ETA:PERIAPSIS < 5) or ((ETA:PERIAPSIS > ETA:APOAPSIS) and ((2 + (SHIP:ORBIT:PERIOD - ETA:PERIAPSIS)) < 1))) {
wait hundus.
set sanitize1 to max((SHIP:APOAPSIS), 1). // gently burn to increase apoapsis.
set sanitize2 to max((targetAltitude - sanitize1), 1).
set sanitize3 to max((altitudeMinimum - stillBreathing), 1).
set sanitize4 to max((sanitize2 / sanitize3), 0.1).
set sanitize5 to max(sqrt(2.0), 1.4).
set sanitize6 to max((sanitize4 ^ sanitize5), 0.1).
set sanitize7 to min(sanitize6, 1.0).
set TVAL to sanitize7. // The kraken likes to divide by zero
lock throttle to TVAL. // ASAP: For better burn accuracy / timing optimization
}
if ((SHIP:PERIAPSIS > altitudeMinimum) and (SHIP:APOAPSIS > targetAltitude)) {
if (SHIP:PERIAPSIS > targetAltitude) { // check exit condition
lock throttle to 0. // ASAP!!! (prevent overshoot)
set TVAL to 0.
set runmode to 10.
}
else if (SHIP:APOAPSIS > targetAltitude) {
lock throttle to 0. // ASAP!!! (prevent overshoot)
set TVAL to 0.
set CleanWarp to (0 - 999). // request warp
set runmode to 8.
}
else {
wait hundus.
}
}
}
else if (runmode = 8) { // Warp to the current Apoapsis
if (SHIP:PERIAPSIS <= altitudeMinimum) { // This orbit is no good.
set CleanWarp to 0. // don't bother warping
set runmode to 9037. // Notify the pilot or operator from control
}
else if (SHIP:PERIAPSIS > altitudeMinimum) {
if (ETA:APOAPSIS >= 135) {
wait hundus.
if ((CleanWarp + 995) < 0) {
set CleanWarp to (0 - 42). /// request the actual warp
}
}
}
// STOP ACCELERATING!!!
if (((CleanWarp + 40) < 0) and ((CleanWarp + 45) > 0)) {
SET WARP to 0. // just in case we were already warping.
lock steering to heading(90, 0). // point ship at the horizon
lock throttle to 0. // Engines off. NOW!!!
wait 0.25. // 250 milliseconds
SET WARP to 0. // just in case we were already warping.
lock throttle to 0. // Engines off. NOW!!!
wait 0.25. // 250 milliseconds
SET WARP to 0. // just in case we were already warping.
lock throttle to 0. // Engines off. NOW!!!
set TVAL to 0. // make sure the engines don't come back on later.
wait 2. // 2 full seconds (total up to this point should be 2 and a half seconds)
set CleanWarp to 3. // request up to 50x warp
}
if ((ETA:APOAPSIS >= 270) and (CleanWarp >= 3)) { // 50x is good for gravity turn --> circularization warp
wait 1.
SET WARP to 3.
set CleanWarp to 3. // lock out all the higher warp levels
}
else if ((ETA:APOAPSIS < 270) and (ETA:APOAPSIS >= 175) and (CleanWarp >= 2)) {
wait 0.5.
SET WARP to 2.
set CleanWarp to 2. // lock out all the higher warp levels
}
else if ((ETA:APOAPSIS < 175) and (ETA:APOAPSIS >= 120) and (CleanWarp >= 1)) {
wait 0.2.
SET WARP to 1.
set CleanWarp to 1. // lock out all the higher warp levels
}
else if (ETA:APOAPSIS < 90) { // DISABLE warp here
wait hundus.
SET WARP to 0.
set CleanWarp to 0. // we're done here
lock steering to heading(90, 0).
wait 0.25.
lock steering to heading(90, 0).
wait 0.25.
lock steering to heading(90, 0).
wait 0.25.
lock steering to heading(90, 0).
wait 0.25.
lock steering to heading(90, 0).
set runmode to 9.
}
else { // "all other cases" could mean something unplanned [entering runmode: 9037] probably?
wait hundus.
}
}
else if (runmode = 9) { // Burn to raise Periapsis to at least targetAltitude
lock steering to heading(90, 0).
if ((ETA:APOAPSIS < 0.1) or ((ETA:APOAPSIS > ETA:PERIAPSIS) and ((SHIP:ORBIT:PERIOD - ETA:APOAPSIS) < 1))) {
wait hundus.
set sanitize1 to max((SHIP:PERIAPSIS), 1). // gently burn to increase periapsis.
set sanitize2 to max((targetAltitude - sanitize1), 1).
set sanitize3 to max((targetAltitude - stillBreathing), 1).
set sanitize4 to max((sanitize2 / sanitize3), 0.1).
set sanitize5 to max(sqrt(2.0), 1.4).
set sanitize6 to max((sanitize4 ^ sanitize5), 0.1).
set sanitize7 to min(sanitize6, 1.0).
set TVAL to sanitize7. // The kraken likes to divide by zero
lock throttle to TVAL. // ASAP: For better burn accuracy / timing optimization
}
else if ((ETA:APOAPSIS >= 0.1) and (ETA:APOAPSIS < 1) and (ETA:PERIAPSIS > ETA:APOAPSIS)) {
wait hundus.
set sanitize1 to min((ETA:APOAPSIS), 300). // try to keep the apoapsis from increasing
set sanitize2 to max((sanitize1 - 0.0001), 0).
set sanitize3 to max((sanitize2 / 15), 0.0001).
set sanitize4 to min(sqrt((3/19)), 0.42).
set sanitize5 to max((sanitize3 ^ sanitize4), 0.0001).
set sanitize6 to min((1 - sanitize5), 1.0).
set sanitize7 to max(sanitize6, 0.1).
set TVAL to sanitize7. // The kraken likes to divide by zero
lock throttle to TVAL. // ASAP: For better burn accuracy / timing optimization
}
if (SHIP:PERIAPSIS > altitudeMinimum) {
if (SHIP:PERIAPSIS > targetAltitude) { // exit condition hopefully met by this point?
lock throttle to 0. // ASAP!!! (prevent overshoot)
set TVAL to 0.
set runmode to 10.
}
else if (SHIP:APOAPSIS < targetAltitude) { // Easy to spell banana; how do you STOP spelling bana{na}+
lock throttle to 0. // ASAP!!! (prevent overshoot)
set TVAL to 0.
set runmode to 6.
}
else {
wait hundus.
}
}
}
else if (runmode = 10) { // Final touches
set TVAL to 0. // Shutdown engine.
lock throttle to 0. // like actually do that IMMEDIATELY (just in case it wasn't already off)
panels on. // Deploy solar panels
unlock steering.
print "SHIP SHOULD NOW BE IN SPACE!".
set runmode to 0.
}
else if (runmode = 9037) { // ABORT!!!
set TVAL to 0. // Shutdown engine.
lock throttle to 0. // like actually do that IMMEDIATELY (just in case it wasn't already off)
unlock steering.
print "DECAYING ORBIT DETECTED!".
set runmode to 0.
}
// Housekeeping
if ((stage:Liquidfuel < 0.0618) and (stage:Solidfuel < 0.0618)) { // Stage if the stage is out of fuel
lock throttle to 0.
wait 2.
stage.
wait 3.
lock throttle to TVAL.
}
if (runmode = 9037) { // ERROR!!!
lock throttle to 0.
}
else if (runmode = 1) {
lock throttle to 1. // Enforce the initial boost 100% of the time.
}
else if (runmode = 4) {
if (SHIP:ALTITUDE < stillBreathing) {
if (SHIP:APOAPSIS < targetAltitude) {
lock throttle to 0.1. // tiny boosts to compensate for drag
set TVAL to 0.1. //
}
else {
lock throttle to 0. // Engines off. NOW!!!
}
}
else if (SHIP:ALTITUDE >= stillBreathing) {
lock throttle to 0. // Engines off. NOW!!!
}
}
else if (runmode = 6) or (runmode = 8) {
lock throttle to 0. // Can't warp under acceleration.
}
else { // Unless there was a VETO, keep using TVAL as per normal operation
lock throttle to TVAL. // [re]apply the throttle value to the actual physical throttle
}
// Print data to screen.
print "SCRIPT RUNMODE: " + runmode + " " at (5,3).
print "Orbital Period: " + round(SHIP:ORBIT:PERIOD) + " " at (5,5).
print "ALTITUDE: " + round(SHIP:ALTITUDE) + " " at (5,7).
print "Target Pitch: " + round(targetPitch, 2) + " " at (5,8).
print "Prograde angle: " + round(failgrade, 2) + " " at (5,9).
print "Q: " + round(cutieQ, 3) + " " at (5,10).
print "APOAPSIS: " + round(SHIP:APOAPSIS) + " " at (5,12).
print "ETA to AP: " + round(ETA:APOAPSIS) + " " at (5,13).
print "PERIAPSIS: " + round(SHIP:PERIAPSIS) + " " at (5,15).
print "ETA to PE: " + round(ETA:PERIAPSIS) + " " at (5,16).
}
@kuzetsa
Copy link
Author

kuzetsa commented Nov 27, 2015

Orbital injection script << video

Updated this script a little:

  1. Don't start the gravity turn at 10km
  2. Locking throttle to 100% is naive and wastes fuel for atmospheric flight.
    The game engine already exposes how much pressure the ship is experiencing from drag, etc. etc. etc.
  3. Circularization burn needed to be refined somewhat.

@kuzetsa
Copy link
Author

kuzetsa commented Dec 2, 2015

horizon pitch correction for circularization burns

orbital_velocity = sqrt ( mu * ( ( 2 / altitude ) - ( 1 / SMA ) ) )

where:

  1. mu is the standard gravitational parameter for kerbin
  2. altitude is relative to the center of kerbin, not sea level

TODO:

This speed (along with the ETA for a burn node) can be used to estimate the length of a base of a triangle. Current altitude VS altitude at node being the other two sides...

Triangles only have three sides, and only needing trig ratios will be less hassle.

Known sides:

  1. current altitude
  2. altitude of the intended burn (apoapsis, periapsis, etc.)

MUCH easier / less math O_O

This:

theta = arcsin(now_altitude / burn_altitude)

where:

Altitude is relative to the center of kerbin, not sea level

@kuzetsa
Copy link
Author

kuzetsa commented Dec 2, 2015

realtime estimated dV needed to reach target orbit

target_orbital_velocity = sqrt ( mu * ( 1 / (targetAltitude + 600000) ) )
current_orbital_velocity = sqrt ( mu * ( 1 / (ArithmeticMean(periapsis, apoapsis) + 600000) ) )

where:

  1. mu is the standard gravitational parameter for kerbin
  2. the constant 600000 is the distance from the center of kerbin to offset elevation above sea level

estimated time to complete a burn

  1. Determine dV requirement for intended burn using SMA method from above
  2. burnTime = (burn_req_dV * SHIP:MASS) / (SHIP:MAXTHRUST * 9.81)
    needs tested!!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment