diff --git a/boot/myboot.ks b/boot/myboot.ks new file mode 100644 index 0000000..27c3001 --- /dev/null +++ b/boot/myboot.ks @@ -0,0 +1,4 @@ +CORE:PART:GETMODULE("kOSProcessor"):DOEVENT("Open Terminal"). +set terminal:width to 80. +set terminal:height to 50. +print "Hello Guido.". diff --git a/burn.ks b/burn.ks new file mode 100644 index 0000000..d8eadec --- /dev/null +++ b/burn.ks @@ -0,0 +1,8 @@ +// burn the next maneuver node +run once libguido. + +myinit(). +set mynode to nextnode. +exec_n(mynode). +myexit(). + diff --git a/dock.ks b/dock.ks new file mode 100644 index 0000000..a0446a1 --- /dev/null +++ b/dock.ks @@ -0,0 +1,85 @@ +// Dock Two Vessels + +run once libguido. + +declare parameter v_max is 1. + +function rcs_ctl { + parameter d. + parameter v. + if d > 0.1 { set tv to -max(min(v_max, d/30),0.1). } + else if d < -0.1 { set tv to max(min(v_max,-d/30),0.1). } + else {set tv to 0.} + if v > tv {return -0.1.} + if v < tv {return 0.1.} + return 0. +} + +myinit(). + +rcs off. + +set tr to target. +set cp to ship:controlpart. + +print "Docking to : "+tr:name. +print "Control from: "+cp:name. +print "Port status : "+cp:state. + +// Adjust direction + +print "adjusting direction.". +lock steering to lookdirup(-tr:portfacing:forevector, tr:portfacing:upvector). + +set da1 to 9. +set da2 to 9. +until da1 < 1 AND da2 < 1 { + set da1 to vang(ship:facing:forevector, -tr:portfacing:forevector). + set da2 to vang(ship:facing:upvector, tr:portfacing:upvector). + print "ang diff:" + round(da1,1) + "/" + round(da2,1). + wait 0.2. +} + +// Align horizontally and vertically. + +rcs on. + +set done to false. + +until cp:state <> "Ready" { + set tr_dis to tr:portfacing:forevector. + set tr_ver to tr:portfacing:upvector. + set tr_hor to tr:portfacing:rightvector. + + set tr_vec to tr:position-cp:position. + set tr_vel to tr:ship:velocity:orbit-ship:velocity:orbit. + + set d_dis to vdot(tr_vec, tr_dis). + set d_ver to vdot(tr_vec, tr_ver). + set d_hor to vdot(tr_vec, tr_hor). + + set v_dis to vdot(tr_vel, tr_dis). + set v_ver to vdot(tr_vel, tr_ver). + set v_hor to vdot(tr_vel, tr_hor). + + print1s("dis/ver/hor: "+round(d_dis,1)+" / "+round(d_ver,1)+" / "+round(d_hor,1)+" "+ + round(v_dis,1)+" / "+round(v_ver,1)+" / "+round(v_hor,1)). + + set ship:control:starboard to rcs_ctl(d_hor,v_hor). + set ship:control:top to -rcs_ctl(d_ver,v_ver). + + if abs(d_hor) > 0.2 or abs(d_ver) > 0.2 { + set ship:control:fore to rcs_ctl(0, v_dis). + } else { + set ship:control:fore to rcs_ctl(d_dis,v_dis). + } + wait 0.1. +} + +set ship:control:neutralize to true. +rcs off. +lock throttle to 0. +unlock steering. +sas on. + +print "done.". diff --git a/go_dres.ks b/go_dres.ks new file mode 100644 index 0000000..be3b3d9 --- /dev/null +++ b/go_dres.ks @@ -0,0 +1,26 @@ +// Launch from Kerbin to Dres +print "Dres 1.0". + +KUniverse:QUICKSAVETO("x0-prelaunch"). +if body = Kerbin { + if ship:altitude < 65000 { + run go_orb(250000). + lock throttle to 0. + wait until KUniverse:CANQUICKSAVE. + KUniverse:QUICKSAVETO("x1-orbit"). + } + if ship:orbit:inclination > 0.01 { + run incl. + } + if ship:apoapsis < 1000000*0.99 { + run reorb(1000000). + wait until KUniverse:CANQUICKSAVE. + KUniverse:QUICKSAVETO("x2-pretransfer"). + } + run tr_pl(Dres). +} else { + // In SOI, but not yet on a stable orbit. + if ship:apoapsis < 0 OR ship:apoapsis > 200000 { run tr_pl(Dres). } +} +print "You arrived at Dres!". + diff --git a/go_dun.ks b/go_dun.ks new file mode 100644 index 0000000..42d119a --- /dev/null +++ b/go_dun.ks @@ -0,0 +1,29 @@ +// Launch from Kerbin to Duna +print "Duna 1.0". + +KUniverse:QUICKSAVETO("x0-prelaunch"). +if body = Kerbin { + if ship:altitude < 65000 { + run go_orb(250000). + lock throttle to 0. + wait until KUniverse:CANQUICKSAVE. + KUniverse:QUICKSAVETO("x1-orbit"). + } + if ship:orbit:inclination > 0.01 { + run incl. + } + if ship:apoapsis < 1000000*0.99 { + run reorb(1000000). + wait until KUniverse:CANQUICKSAVE. + KUniverse:QUICKSAVETO("x2-pretransfer"). + } + run tr_pl(Duna). +} else { + // In SOI, but not yet on a stable orbit. + if ship:apoapsis < 0 OR ship:apoapsis > 200000 { run tr_pl(Duna). } +} + +wait until KUniverse:CANQUICKSAVE. +KUniverse:QUICKSAVETO("x3-dstorbit"). +print "You arrived at Duna!". + diff --git a/go_eve.ks b/go_eve.ks new file mode 100644 index 0000000..819eec7 --- /dev/null +++ b/go_eve.ks @@ -0,0 +1,28 @@ +print "Eve 1.0". + +KUniverse:QUICKSAVETO("x0-prelaunch"). +if body = Kerbin { + if ship:altitude < 65000 { + run go_orb(250000). + lock throttle to 0. + wait until KUniverse:CANQUICKSAVE. + KUniverse:QUICKSAVETO("x1-orbit"). + } + if ship:orbit:inclination > 0.01 { + run incl. + } + if ship:apoapsis < 1000000*0.99 { + run reorb(1000000). + wait until KUniverse:CANQUICKSAVE. + KUniverse:QUICKSAVETO("x2-pretransfer"). + } + run tr_pl(Eve). +} else { + // In SOI, but not yet on a stable orbit. + if ship:apoapsis < 0 OR ship:apoapsis > 200000 { run tr_pl(Eve). } +} + +wait until KUniverse:CANQUICKSAVE. +KUniverse:QUICKSAVETO("x5-dstlow"). +print "You arrived at Eve!". + diff --git a/go_min.ks b/go_min.ks new file mode 100644 index 0000000..0e4bb8d --- /dev/null +++ b/go_min.ks @@ -0,0 +1,33 @@ +// Launch from Kerbin to Minmus +print "Minmus 1.0". + +KUniverse:QUICKSAVETO("x0-prelaunch"). +if body = Kerbin { + if ship:altitude < 65000 { + run go_orb. + } + lock throttle to 0. + wait until KUniverse:CANQUICKSAVE. + KUniverse:QUICKSAVETO("x1-orbit"). + if ship:orbit:inclination < 5 { + run reorb(80000). + run incl. + run incl(6,Minmus:orbit:lan). + + } + run reorb(80000). + wait until KUniverse:CANQUICKSAVE. + KUniverse:QUICKSAVETO("x2-pretransfer"). + run tr_min. +} else { + // In SOI of Minimus, but not yet on a stable orbit. + if ship:apoapsis < 0 OR ship:apoapsis > 100000 { run tr_min. } +} + +if ship:apoapsis > 11000 { run reorb(10000). } +//if ship:orbit:inclination > 0.1 { run incl. } +wait until KUniverse:CANQUICKSAVE. +KUniverse:QUICKSAVETO("x3-dstorbit"). +//run hit(0,6). +print "You arrived on Minmus!". + diff --git a/go_mun.ks b/go_mun.ks new file mode 100644 index 0000000..c6121e8 --- /dev/null +++ b/go_mun.ks @@ -0,0 +1,9 @@ +// Launch from Kerbin to the Mun +print "Mun 1.0". + +run go_orb. +run reorbit2(80000). +run tr_mun. + +print "done.". + diff --git a/go_orb-v1.ks b/go_orb-v1.ks new file mode 100644 index 0000000..11e043f --- /dev/null +++ b/go_orb-v1.ks @@ -0,0 +1,147 @@ +// Orbital Launch Control + +run once libguido. +myinit(). + +set incl to 0. +set apoa to 80000. + +clearscreen. print "Orbital Launch Control v0.1". +print " Orbit: " + apoa + " m, " + incl + " deg". + +set alt_s to 1000. + +// Vessel specific setup +set n to ship:name. +set e_cur to 0. +list engines in e. + +if n = "orbital-1" OR n = "MunOrbiter" OR n = "Mun-1" OR n = "Mun-2" { + set elist to list(e[2],e[1],e[0]). + print "Type: 3-Stage (3 stage, SLL)". +} else if n = "Mun-3-Minimus1" { + set elist to list(e[5],e[4],e[3]). +} else if n:startswith("Mun-3") { + set elist to list(e[3],e[2],e[1],e[0]). + print "Type: 4-Stage (3 stage, SLLL)". +} else if n = "KSS-2" { + set elist to list(e[2]). + print "Type: KSS-2 (single stage L)". +} else if n:startswith("KSS-") { + set elist to list(e[1],e[0]). + print "Type: KSS Launcher (LL).". +} else if n = "Minimus-Lab" { + set elist to list(e[6],e[5],e[4],e[3]). +} else { + print "Unknown vessel. Abort!". +} + +for e in elist { + print " "+e:title. +} + +// Functions -------------------------------------------------- + +function calc_angle { + parameter alt. + + if alt < 500 {return 90.} + if alt < 1000 {return 85.} + if alt < 3000 {return 80.} + if alt < 7000 {return 70.} + if alt < 15000 {return 60.} + if alt < 20000 {return 50.} + if alt < 30000 {return 40.} + if alt < 40000 {return 35.} + return 35. +} + +// Check for flameout and stage if needed +function eng_check { + set ce to elist[e_cur]. + if ce:maxthrust = 0 { + set e_cur to e_cur+1. + print "Fuel for "+ce:title+" exhausted. Staging.". + stage. + wait 0.1. + } +} + +// Main -------------------------------------------------- + +print " ". print "Launching.". +print "3". wait 1. print "2". wait 1. print "1". wait 1. + +// Launch +stage. +lock throttle to 1.0. +lock steering to heading(90,90). + +// Initiate gravity turn +print "climb to grav turn at "+alt_s. +wait until ship:altitude > alt_s. + + +// Raise orbit to 10k below apoapsis, wait until out of the athmosphere, stage if necessary +print "gravity turn.". +print "raising AP to 75% of target: "+floor(apoa*0.75). + +until ship:altitude > 50000 AND eta:apoapsis < 120 { + // Check if ascent stage is done, decouple and start transfer stage + eng_check(). + + set app to ship:apoapsis/apoa. + if app > .75 {lock throttle to 0.0.} + else {lock throttle to 1.0.} + + lock steering to heading(90,calc_angle(ship:altitude)). + wait 0.2. +} + +// Now we are out of the athmosphere and high. Raise orbit to apoapsis, stage if necessary +print "raising AP to 100% of target: "+floor(apoa). + +until eta:apoapsis < 35 { + // Check if ascent stage is done, decouple and start transfer stage + eng_check(). + + set app to ship:apoapsis/apoa. + if app > .999 {lock throttle to 0.0.} + else if app > .99 {lock throttle to 0.1.} + else {lock throttle to 1.0.} + + lock steering to ship:prograde. + wait 0.2. +} + +print "turning for PE raise.". +lock throttle to 0.0. +lock steering to heading (90,0). + +// Raise Periapsis, stage if necessary +set t to eta:apoapsis-30. +print "Waiting "+floor(t)+" seconds for Periapsis raise.". +wait t. + +// burn +until ship:periapsis > apoa { + lock steering to heading (90,0). + set ea to eta:apoapsis. + if ship:periapsis < 0 { + if ea > 25 AND ea < 120 { set thr to 0.1. } + else {set thr to 1.0.} + } else { + if ea > 5 AND ea < 120 { set thr to 0. } + else if ea < 5 { set thr to 0.2.} + else { set thr to 1.} + } + lock throttle to thr. + + eng_check(). + wait 0.2. +} + +lock throttle to 0. + +print "Orbit reached: A/P/T "+floor(ship:apoapsis)+" / "+floor(ship:periapsis)+" / "+apoa. +myexit(). \ No newline at end of file diff --git a/go_orb-v2.ks b/go_orb-v2.ks new file mode 100644 index 0000000..c0e3bde --- /dev/null +++ b/go_orb-v2.ks @@ -0,0 +1,174 @@ +// Orbital Launch Control + +run once libguido. +myinit(). + +declare parameter apoa is 80000. + +set incl to 0. + +clearscreen. print "Orbital Launch Control v0.1". +print " Orbit: " + apoa + " m, " + incl + " deg". + +set alt_s to 1000. + +// Vessel specific setup +set n to ship:name. +set e_cur to 0. +list engines in e. + +if ship:altitude < 1000 { + if n = "orbital-1" OR n = "MunOrbiter" OR n = "Mun-1" OR n = "Mun-2" { + set elist to list(e[2],e[1],e[0]). + print "Type: 3-Stage (3 stage, SLL)". + } else if n:startswith("Mun-3") { + set elist to list(e[3],e[2],e[1],e[0]). + print "Type: 4-Stage (3 stage, SLLL)". + } else if n = "KSS-2" { + set elist to list(e[2]). + print "Type: KSS-2 (single stage L)". + } else if n:startswith("KSS-") { + set elist to list(e[1],e[0]). + print "Type: KSS Launcher (LL).". + } else if n = "Minimus-Lab" { + set elist to list(e[6],e[5],e[4],e[3]). + } else if n = "Duna-1" { + set elist to list(e[4],e[3]). + } else if n = "Duna-2" { + set elist to list(e[4],e[3]). + } else { + print "Unknown vessel. Abort!". + } +} else { + print "Need to improvise.". + set elist to e. +} + +for e in elist { + print " "+e:title. +} + +// Functions -------------------------------------------------- + + + +function calc_angle { + parameter alt. + + if alt < 500 {return 90.} + if alt < 1000 {return 85+ 5*( 1000-alt)/ 500.} + if alt < 3000 {return 80+ 5*( 3000-alt)/ 2000.} + if alt < 7000 {return 70+10*( 7000-alt)/ 4000.} + if alt < 13000 {return 60+10*(15000-alt)/ 6000.} + if alt < 21000 {return 50+10*(21000-alt)/ 8000.} + if alt < 30000 {return 40+10*(30000-alt)/ 9000.} + if alt < 40000 {return 35+ 5*(40000-alt)/10000.} + return 35. +} + +// Check for flameout and stage if needed +function eng_check { + set ce to elist[e_cur]. + if ce:maxthrust = 0 { + set e_cur to e_cur+1. + print "fuel for "+ce:title+" exhausted.". + wait until stage:ready. + print "staging.". + stage. + wait 0.1. + } +} + +// Main -------------------------------------------------- + + + +if ship:altitude < 1000 { + + print " ". print "Launching.". + print "3". wait 1. print "2". wait 1. print "1". wait 1. + mytimer_s(). + + // Launch + stage. + lock throttle to 1.0. + lock steering to heading(90,90). + + // Initiate gravity turn + print mytimer()+"climb to grav turn at "+alt_s. + wait until ship:altitude > alt_s. + + + // Raise orbit to 10k below apoapsis, wait until out of the athmosphere, stage if necessary + print mytimer()+"gravity turn.". + +} + +if ship:altitude < apoa*0.75 { + print mytimer()+"raising AP to 75% of target: "+floor(apoa*0.75). + + until ship:altitude > 45000 { + // Check if ascent stage is done, decouple and start transfer stage + eng_check(). + + set app to ship:apoapsis/apoa. + if app > .75 {lock throttle to 0.0.} + else {lock throttle to 1.0.} + + lock steering to heading(90,calc_angle(ship:altitude)). + wait 0.2. + } +} + +if ship:apoapsis < apoa*0.999 { + // Now we are out of the athmosphere and high. Raise orbit to apoapsis, stage if necessary + print mytimer()+"raising AP to 100% of target: "+floor(apoa). + + lock steering to ship:prograde. + + until ship:apoapsis > apoa*0.999 { + // Check if ascent stage is done, decouple and start transfer stage + eng_check(). + + set app to ship:apoapsis/apoa. + if app > .999 {lock throttle to 0.0.} + else {lock throttle to 1.0.} + wait 0.1. + } + + print mytimer()+"AP rasied to "+ship:apoapsis. + lock throttle to 0. +} + + +// Calculate length of burn at AP. +set max_acc to ship:maxthrust/ship:mass. +set t_ap to eta:apoapsis. +set ap to ship:apoapsis. +set v_ap to vv_alt(ap). +set v_new to vv_circular(ap). +set dt_ap to abs(v_ap-v_new)/max_acc. + +print mytimer()+"burn time: "+round(dt_ap,1)+" s". +lock steering to heading(90,0). +if t_ap-dt_ap/2 > 0 { + print mytimer()+"waiting "+(t_ap-dt_ap/2)+" s". + pwait(t_ap-dt_ap/2). +} + +print "starting burn.". + +until ship:periapsis > apoa*0.999 OR (ship:apoapsis > apoa*1.2 AND ship:periapsis > apoa*0.9) OR ship:periapsis > apoa*2 { + // Check if ascent stage is done, decouple and start transfer stage + eng_check(). + + set app to ship:periapsis/apoa. + if app > .999 {lock throttle to 0.0.} + else if app > .99 {lock throttle to 0.2.} + else {lock throttle to 1.0.} + lock steering to heading(90,0). + wait 0.1. +} + +print "Orbit reached: A/P/T "+floor(ship:apoapsis)+" / "+floor(ship:periapsis)+" / "+apoa. +myexit(). \ No newline at end of file diff --git a/go_orb.ks b/go_orb.ks new file mode 100644 index 0000000..f718c45 --- /dev/null +++ b/go_orb.ks @@ -0,0 +1,167 @@ +// Orbital Launch Control + +run once libguido. +myinit(). + +declare parameter apoa is 80000. + +set incl to 0. + +clearscreen. print "Orbital Launch Control v0.1". +print " Orbit: " + apoa + " m, " + incl + " deg". + +set alt_s to 1000. + +// Vessel specific setup +set n to ship:name. +set e_cur to 0. +list engines in e. + +if ship:altitude < 1000 { + if n = "orbital-1" OR n = "MunOrbiter" OR n = "Mun-1" OR n = "Mun-2" { + set elist to list(e[2],e[1],e[0]). + print "Type: 3-Stage (3 stage, SLL)". + } else if n:startswith("Mun-3") { + set elist to list(e[3],e[2],e[1],e[0]). + print "Type: 4-Stage (3 stage, SLLL)". + } else if n = "KSS-2" { + set elist to list(e[2]). + print "Type: KSS-2 (single stage L)". + } else if n:startswith("KSS-") { + set elist to list(e[1],e[0]). + print "Type: KSS Launcher (LL).". + } else if n = "Minimus-Lab" { + set elist to list(e[6],e[5],e[4],e[3]). + } else if n = "Duna-4" { + set elist to list(e[10],e[9]). + } else if n:startswith("Duna-5") { + // Quad Booster + 8 nuclear + set elist to list(e[9],e[8], e[7]). + } else if n:startswith("Duna-6") { + set elist to list(e[5],e[4], e[3]). + } else if n:startswith("Duna-") { + // Duna Series. Engine cluster + 4x nuclear. + set elist to list(e[4],e[3]). + } else if n = "Eve-Lander3" OR n = "Eve-Lander4" { + set elist to list(e[21],e[17], e[16]). + } else if n:startswith("Eve-Lander") { + set elist to list(e[14],e[10], e[9]). + } else if n:startswith("Sat-1") { + set elist to list(e[5],e[4],e[3]). + } else { + print "Unknown vessel. Abort!". + } +} else { + print "Need to improvise.". + set elist to e. +} + +for e in elist { + print " "+e:title. +} + +// Functions -------------------------------------------------- + + + +function calc_angle { + parameter alt. + + if alt < 500 {return 90.} + if alt < 1000 {return 85+ 5*( 1000-alt)/ 500.} + if alt < 3000 {return 80+ 5*( 3000-alt)/ 2000.} + if alt < 7000 {return 70+10*( 7000-alt)/ 4000.} + if alt < 13000 {return 60+10*(15000-alt)/ 6000.} + if alt < 21000 {return 50+10*(21000-alt)/ 8000.} + if alt < 30000 {return 40+10*(30000-alt)/ 9000.} + if alt < 40000 {return 35+ 5*(40000-alt)/10000.} + return 35. +} + +// Check for flameout and stage if needed +function eng_check { + set ce to elist[e_cur]. + if ce:maxthrust = 0 { + set e_cur to e_cur+1. + print "fuel for "+ce:title+" exhausted.". + safe_stage(). + wait 0.1. + } +} + +// Main -------------------------------------------------- + + + +if ship:altitude < 1000 { + + print " ". print "Launching.". + print "3". wait 1. print "2". wait 1. print "1". wait 1. + mytimer_s(). + + // Launch + safe_stage(). + lock throttle to 1.0. + lock steering to heading(90,90). + + // Initiate gravity turn + print mytimer()+"climb to grav turn at "+alt_s. + wait until ship:altitude > alt_s. + + + // Raise orbit to 10k below apoapsis, wait until out of the athmosphere, stage if necessary + print mytimer()+"gravity turn.". + +} + +if ship:altitude < apoa*0.75 { + print mytimer()+"raising AP to 75% of target: "+floor(apoa*0.75). + + until ship:altitude > 45000 { + // Check if ascent stage is done, decouple and start transfer stage + eng_check(). + + set app to ship:apoapsis/apoa. + if app > .75 {lock throttle to 0.0.} + else {lock throttle to 1.0.} + + lock steering to heading(90,calc_angle(ship:altitude)). + wait 0.2. + } +} + +if ship:apoapsis < apoa*0.999 { + // Now we are out of the athmosphere and high. Raise orbit to apoapsis, stage if necessary + print mytimer()+"raising AP to 100% of target: "+floor(apoa). + + lock steering to ship:prograde. + + until ship:apoapsis > apoa*0.999 { + // Check if ascent stage is done, decouple and start transfer stage + eng_check(). + + set app to ship:apoapsis/apoa. + if app > .999 {lock throttle to 0.0.} + else {lock throttle to 1.0.} + wait 0.1. + } + + print mytimer()+"AP rasied to "+ship:apoapsis. + lock throttle to 0. +} + +// Calculate length of burn at AP. +set max_acc to ship:maxthrust/ship:mass. +set t_ap to eta:apoapsis. +set ap to ship:apoapsis. +set v_ap to vv_alt(ap). +set v_new to vv_circular(ap). +set dv to v_new-v_ap. +set dt_ap to dv/max_acc. + +set mynode to NODE(time:seconds+t_ap,0,0,dv). +ADD mynode. +exec_n(mynode). + +print "Orbit reached: A/P/T "+floor(ship:apoapsis)+" / "+floor(ship:periapsis)+" / "+apoa. +myexit(). \ No newline at end of file diff --git a/go_suborb.ks b/go_suborb.ks new file mode 100644 index 0000000..fbcb0ee --- /dev/null +++ b/go_suborb.ks @@ -0,0 +1,41 @@ +// Suborbital Flight Controls + +CLEARSCREEN. + PRINT "Suborbital Flight Controls v1.0". +FROM {local c is 3.} UNTIL c = 0 STEP {SET c to c - 1.} DO { + PRINT "..." + c. + WAIT 1. // pauses the script here for 1 second. +} + +// [0] is liquid fuel, [1] is solid state +list engines in e. + +// Launch +print "Launching.". +stage. +lock throttle to 1.0. +lock steering to up. + +// Wait until booster is done, decouple and start main engine +wait until ship:altitude > 10000. +print "alt: > 10,000". +wait until e[1]:maxthrust = 0. +print "Solid booster exhausted. Staging.". +stage. + +// Wait until solid fuel is empty and decouple +wait 10. +lock throttle to 0.2. +lock steering to up. +wait until e[0]:maxthrust = 0. +print "Liquid fuel engine exhausted. Decoupling.". +stage. + +// Wait to open Parachute +unlock throttle. +print "waiting for 10,000". +wait until ship:altitude < 10000. +print "alt: < 10,000.". +wait until ship:airspeed < 255. +stage. +print "Control completed.". diff --git a/hit.ks b/hit.ks new file mode 100644 index 0000000..01281ef --- /dev/null +++ b/hit.ks @@ -0,0 +1,195 @@ +// Landing and hit a target. +// +// Assumes: +// - No staging required +// - Ignores athmosphere (for now) +// - Assume latitude is the one of the orbit (within < 0.1 deg). + +parameter target_long is 6. +parameter target_lat is 0. + +run once libguido. +myinit(). +calibrate_geo(). + +// Hover just above landing site. + +function set_up_landing { + + set bd to ship:orbit:body. + set g to bd:mu / bd:radius^2. + + print " ". + print "landing site: "+" "+bd:name+" @ "+target_long+" long / "+target_lat+" lat". + print "approaching site.". + + set da to mod(target_long-longitude+720,360). + set dt to da*ship:orbit:period/360-120. + set g to bd:mu / bd:radius^2. + + print "est. time: "+round(dt)+" s". + rwait(dt). + set da to mod(target_long-longitude+720,360). + set dt to da*ship:orbit:period/360-60. + print "est. time: "+round(dt)+" s". + rwait(dt). + + lock steering to heading(270,0). + pwait(30). + + set da to mod(target_long-longitude+720,360). + print "ready for burn. da: "+round(da,1). + + // Burn to slow down. + + set gv_spot to geo_v(latlng(0,6)). + + set done to false. + set v_est to -999. + + lock steering to retrograde. + + // Slow down to 50 orbital. + + print "slow down to 50 m/s". + set_throttle(50,20). + wait until ship:velocity:orbit:mag < 50. + lock throttle to 0.0. + + print "aiming for landing spot.". + set over to 999. + + until alt:radar < 2000 { + set a_max to maxthrust/mass - g. + set gv_ship to geo_v(ship:geoposition,ship:altitude). + set dx to gv_spot:y-gv_ship:y. + set v to ship:velocity:surface:mag. + set al to alt:radar. + set a_max to maxthrust/mass - g. + set t_left to (-v+(v^2+2*al*g)^0.5)/g. + + if v_est = -999 { + set v_est to 0. + } else { + set v_est to (old_x-dx)/(time:seconds-old_t). + } + set old_t to time:seconds. + set old_x to dx. + set over to t_left*v_est-dx. + + print "spot/ship:"+rn_v(gv_spot)+" "+rn_v(gv_ship). + print "dx: "+dx. + print "est v:"+v_est. + print "est t:"+t_left. + print "over :"+over. + + lock steering to heading(270,0). + if over > 10000 { + lock throttle to 1. + } else if over > 1000 { + lock throttle to 0.1. + } else if over > 100 { + lock throttle to 0.01. + } else { + lock throttle to 0. + } + wait 1. + } + + set warp to 0. + lock throttle to 0. +} + + +// Land from suborbital flight + +function land { + set bd to ship:orbit:body. + set g to bd:mu / bd:radius^2. + set a_max to maxthrust/mass - g. + set v_land to 0. + + print " ". + print "landing on "+bd:name. + print "alt : "+round(alt:radar,2)+" m". + print "a_max: "+round(a_max,1)+" m/s". + + // turn + print "turning retrograde.". + lock steering to srfretrograde. + wait until vang(ship:facing:vector,srfretrograde:vector) < 2 OR alt:radar < 5. + print "turn complete.". + + // Set up math + set v to ship:velocity:surface:mag. + set al to alt:radar. + + set thr to 0. + + until al < 20 AND v < 0.25 { + + // Landing basics + set v to ship:velocity:surface:mag. + set al to alt:radar. + set a_max to maxthrust/mass - g. + set t_left to (-v+(v^2+2*al*g)^0.5)/g. + set t_v0 to abs(v-v_land)/a_max. + + // Targeting logic + // set dst_v to latlng(target_long, target_lat). + // print "dst_v:"+dst_v:position. + + // print1s("lat/lon: "+round(latitude,3)+" / "+round(longitude,3)). + // print "a: "+round(al,1)+" v: "+round(v,1)+" t_left: "+round(t_left,1)+" t_v0: "+round(t_v0,1). + + if al < 20 { gear on. } + + set dt to t_left-t_v0. + + if mod(floor(time:seconds*10),10) = 0 { + if t_left > 5 { + print1s("dt : "+dt+" s"). + } else { + print1s("agl: "+al+" m"). + } + } + + if t_left > 5 { + // Still 5 seconds away, coarse maneuvers... + if dt < 1 and v > 5 { + set thr to 1.0. + } else { + set thr to 0. + } + } else { + // Close to ground fine tune + // calc acceleration that gets us to desired speed in 2 seconds + set v_goal to max((al-20)/5,0). + set dv to max(v-v_goal,0). + set thr to min(1.0,(dv+g-3.0)/(a_max+g)). + //print "thr:"+thr+" dv:"+dv+" goal:"+v_goal. + } + lock throttle to thr. + + wait 0.1. + } + + print "landed lat: "+round(latitude,1)+" lng: "+round(longitude,1). + lock throttle to 0. + sas on. +} + +function test_launch { + stage. + lock steering to heading(270,80). + lock throttle to 1.0. + gear off. + wait 30. + lock throttle to 0. +} + +//test_launch(). +set_up_landing(). +land(). +myexit(). +sas on. \ No newline at end of file diff --git a/hit2.ks b/hit2.ks new file mode 100644 index 0000000..e3345b7 --- /dev/null +++ b/hit2.ks @@ -0,0 +1,170 @@ +// Landing and hit a target. +// +// Assumes: +// - No staging required +// - Ignores athmosphere (for now) +// - Assume latitude is the one of the orbit (within < 0.1 deg). + +parameter target_long is 4. +parameter target_lat is 0. + +run once libguido. +myinit(). + +// Hover just above landing site. + +function set_up_landing { + + set bd to ship:orbit:body. + set g to bd:mu / bd:radius^2. + + print " ". + print "landing site: "+" "+bd:name+" @ "+target_long+" long / "+target_lat+" lat". + print "approaching site.". + + set da to mod(target_long-5-longitude+720,360). + lock steering to ship:retrograde. + + set done to false. + + // Get ready for burn. + until done { + set da to mod(target_long-longitude+720,360). + set dt to da/360*ship:orbit:period. + set a_max to maxthrust/mass - g. + set v_orb to ship:velocity:orbit:mag. + set dt_left to v_orb/a_max. + set mm to 2. + + if dt > dt_left*mm+30 { + // Adjust speed + set_warp_for_t(dt-dt_left*mm+30). + print1s("dang:"+round(da,4)+" dt: "+round(dt,1)+" s dt_left: "+round(dt_left,1)+" s"). + wait max((dt-dt_left*mm/3+30)/2,0.1). + } else if dt > dt_left*mm+1 { + set warp to 0. + pwait(dt-dt_left*mm-1). + } else { + set done to true. + } + } + + // Burn to slow down. + + set v_orb to 999. + + until da < 0.01 and v_orb < 0.1 { + set da to mod(target_long-longitude+720,360). + set dt to da/360*ship:orbit:period. + set a_max to maxthrust/mass - g. + set v_orb to ship:velocity:orbit:mag. + set dt_left to v_orb/a_max. + + set warp to 0. + if dt > dt_left*2 { + // plenty of time, no action + lock throttle to 0. + } else { + set_throttle(v_orb,MAX(dt*2,5)). + } + print1s("ang:"+round(da,3)+" dv: "+round(v_orb,2)+" m/s dt/left: "+round(dt,1)+" / "+round(dt_left,1)). + wait 0.1. + } + + set warp to 0. + lock throttle to 0. +} + + +// Land from suborbital flight + +function land { + set bd to ship:orbit:body. + set g to bd:mu / bd:radius^2. + set a_max to maxthrust/mass - g. + set v_land to 0. + + print " ". + print "landing on "+bd:name. + print "alt : "+round(alt:radar,2)+" m". + print "a_max: "+round(a_max,1)+" m/s". + + // turn + print "turning retrograde.". + wait until vang(ship:facing:vector,srfretrograde:vector) < 2 OR alt:radar < 5. + lock steering to srfretrograde. + print "turn complete.". + + // Set up math + set v to ship:velocity:surface:mag. + set al to alt:radar. + + set thr to 0. + + until al < 20 AND v < 0.25 { + + // Landing basics + set v to ship:velocity:surface:mag. + set al to alt:radar. + set a_max to maxthrust/mass - g. + set t_left to (-v+(v^2+2*al*g)^0.5)/g. + set t_v0 to abs(v-v_land)/a_max. + + // Targeting logic + // set dst_v to latlng(target_long, target_lat). + // print "dst_v:"+dst_v:position. + + print1s("lat/lon: "+round(latitude,3)+" / "+round(longitude,3)). + //print "a: "+round(al,1)+" v: "+round(v,1)+" t_left: "+round(t_left,1)+" t_v0: "+round(t_v0,1). + + if al < 20 { gear on. } + + set dt to t_left-t_v0. + + if mod(floor(time:seconds*10),10) = 0 { + if t_left > 5 { + print "dt : "+dt+" s". + } else { + print "agl: "+al+" m". + } + } + + if t_left > 5 { + // Still 5 seconds away, coarse maneuvers... + if dt < 1 and v > 5 { + set thr to 1.0. + } else { + set thr to 0. + } + } else { + // Close to ground fine tune + // calc acceleration that gets us to desired speed in 2 seconds + set v_goal to max((al-20)/5,0). + set dv to max(v-v_goal,0). + set thr to min(1.0,(dv+g-3.0)/(a_max+g)). + //print "thr:"+thr+" dv:"+dv+" goal:"+v_goal. + } + lock throttle to thr. + + wait 0.1. + } + + print "landed.". + lock throttle to 0. + sas on. +} + +function test_launch { + stage. + lock steering to heading(270,80). + lock throttle to 1.0. + gear off. + wait 30. + lock throttle to 0. +} + +//test_launch(). +set_up_landing(). +land(). +myexit(). +sas on. \ No newline at end of file diff --git a/hov.ks b/hov.ks new file mode 100644 index 0000000..306f475 --- /dev/null +++ b/hov.ks @@ -0,0 +1,269 @@ +// Hover to a location. +// +// Assumes: +// - No staging required + +run once libguido. +myinit(). + +declare parameter thespot is latlng(0,0). + +if floor(thespot:distance-latlng(0,0):distance)<10 { + print "default". + if body = Kerbin { + set thespot_v to ksplaunchpad. + } else if body = Minmus { + set thespot to latlng(0,6). + } +} + +myinit(). + +// Land from suborbital flight + +function retro { + + parameter loc. + + set bd to ship:orbit:body. + set g to bd:mu / bd:radius^2. + set a_max to maxthrust/mass. + set v to 999. + set al to alt:radar. + set alt_tar to 200. + + set t0 to time:seconds. + + print "auto-land at "+loc. + + until al < alt_tar { + set a_max to maxthrust/mass. + set al to alt:radar. + set up_vec to heading(0,90):vector. + + set dx_vec to (loc:position-ship:position). + set v_vec to ship:velocity:surface. + + // Calculate time to impact (0 MSL) + set v to -v_vec*up_vec. + set t_left to (-v+(v^2+2*(max(al-alt_tar,0))*g)^0.5)/g+0.00001. + + // Calculate target velocity that would make us hit the target + set v_target_vec to dx_vec*(1/t_left). + + // Correct by the fact that we want to have v=0 at al=0 + // Split into horizontal and vertical + set hv_target_vec to v_target_vec - (v_target_vec*up_vec)*up_vec. + set vv_target_vec to v_target_vec - hv_target_vec. + // Define velocity goal + set v_goal to t_left*a_max. + + // If vertical speed exceeds target, correct it to target + if vv_target_vec:mag > v_goal { + set vv_target_vec to vv_target_vec:normalized*v_goal. + } + + set v_target_vec to hv_target_vec + vv_target_vec. + + // Burn is the difference between velocities. + set delta_v to v_target_vec-v_vec. + + if delta_v*up_vec < 0 OR v_goal > vv_target_vec:mag { + // Make sure we never steer up and we don't break befor necessary. + print1s("stopping upwards movement."). + set hdelta_v to delta_v - (delta_v*up_vec)*up_vec. + set delta_v to hdelta_v. + } + + // Dampen small corrections + if delta_v:mag > 1 { + set thr_mm to 1.0. + } else { + set thr_mm to 0.1. + } + + lock steering to delta_v:direction. + + if time:seconds-t0 > 5 { + // Set throttle to time it takes to normalize delta_v + lock throttle to thr_mm*max(min(1.0,1*(delta_v:mag)/(a_max-g)),0). + print "v: "+round(v,1)+" thr: "+round(throttle,2)+" al: "+round(al-alt_tar,1)+" dv: "+round(delta_v:mag,1)+" dv_vert: "+round(delta_v*up_vec,1)+" t_left: "+round(t_left,1)+" v_goal: "+round(v_goal,1). + wait 0.1. + } + } + lock throttle to 0.0. + unlock throttle. + print "transition to hover.". +} + + +// Land from suborbital flight + +function tspot { + + parameter loc. + + set bd to ship:orbit:body. + set g to bd:mu / bd:radius^2. + set a_max to maxthrust/mass. + set v_land to 0. + set al to alt:radar-100. + set up_vec to heading(0,90):vector. + + + // Calculate distance in horizontal plane + set dx_vec to (loc:position-ship:position). + set hx_vec to dx_vec - (dx_vec*up_vec)*up_vec. + + // Calculate velocity in horizontal plane. + set dv_vec to ship:velocity:surface. + set hv_vec to dv_vec - (dv_vec*up_vec)*up_vec. + + // Calculate horizontal velocity that gets us to the target. + set v to dv_vec*up_vec. + set t_left to (-v+(v^2+2*al*g)^0.5)/g. + + set dv_target_vec to dx_vec*(1/t_left). + set hv_target_vec to dv_target_vec - (dv_target_vec*up_vec)*up_vec. + + // Burn is the difference between velocities. + set delta_hv to hv_target_vec-hv_vec. + + lock steering to delta_hv:direction. + pwait(10). + + set t to delta_hv:mag/a_max. + lock throttle to 1.0. + wait t. + lock throttle to 0.0. + unlock throttle. +} + +function tland { + parameter loc. + set bd to ship:orbit:body. + set g to bd:mu / bd:radius^2. + set a_max to maxthrust/mass - g. + set v_land to 0. + set alt_tar to 100. + + set up_vec to heading(0,90):vector. + + sas off. + lock steering to heading(0,90). + lock throttle to 0. + + print "hover-land at "+loc. + + // turn + if vang(ship:facing:vector,up_vec) > 10 { + print "waiting to turn sfretro.". + wait until vang(ship:facing:vector,up_vec) < 10. + } + + // Set up math + set v to ship:velocity:surface:mag. + set al to alt:radar. + set thr to 0. + + until al < 10 AND v < 0.25 { + + set v_vec to ship:velocity:surface. + set v to -v_vec*heading(0,90):vector. + set al to alt:radar. + set a_max to maxthrust/mass - g. + set t_left to (-v+(v^2+2*al*g)^0.5)/g. + set t_v0 to abs(v-v_land)/a_max. + + print1s("a: "+round(al,1)+" v: "+round(v,1)+" t_left: "+round(t_left,1)+" t_v0: "+round(t_v0,1)). + + if al < 20 { gear on. } + else { gear off. } + + // Speed + set v_goal to (al-alt_tar)/5. + set dv to v-v_goal. + set thr to max(min(1.0,(dv+g)/(a_max+g)),0). + if al > alt_tar { + set thr to thr-0.01. + } else { + set thr to thr+0.01. + } + //print "thr:"+thr+" dv:"+dv+" goal:"+v_goal. + + // Calculate distance in horizontal plane + set dx_vec to (loc:position-ship:position). + set hx_vec to dx_vec - (dx_vec*up_vec)*up_vec. + + // Calculate velocity in horizontal plane. + set dv_vec to ship:velocity:surface. + set hv_vec to dv_vec - (dv_vec*up_vec)*up_vec. + + // Approximate how long it will take us to break horizontal speed + set ha_max to (maxthrust/mass - g)*0.1*thr. + set ht_left to hx_vec:mag/hv_vec:mag. + + // Calculate a desired velocity towards target + // Goal is to get there in 30 seconds. + // Max horizontal acceleration is about inclination*acceleration*throttle + + // Max speed allowed speed is [time left] x [acceleration] + set h_speed to ht_left*ha_max. + + // Higher precision when close. + if hx_vec:mag > 10 { + set inc_m to 0.2. + } else if hx_vec:mag > 2 { + set inc_m to 0.1. + set h_speed to 0.5. + } else { + set inc_m to 0.02. + set h_speed to 0.1. + } + + set hv_target to hx_vec:normalized*h_speed. + set hv_deltav to hv_vec-hv_target. + + //print "h-dist: "+round(hx_vec:mag,1)+" h-vel: "+round(hv_vec:mag,1)+ " inc: " + inc_m+" hv/tv/dv: " +rn_v(hv_vec) + " " + rn_v(hv_target)+ " " + rn_v(hv_deltav). + //print "h-speed: "+round(h_speed,1)+" ht_left: "+round(ht_left,1)+ " inc: " + inc_m+" hv/tv/dv: " +rn_v(hv_vec) + " " + rn_v(hv_target)+ " " + rn_v(hv_deltav). + print1s("h-speed: "+round(h_speed,1)+" ht_left: "+round(ht_left,1)+ " inc: " + inc_m). + + set str_vec to up_vec-inc_m*hv_deltav:normalized. + lock steering to str_vec:direction. + + lock throttle to thr. + + if hx_vec:mag < 10 AND hv_vec:mag < 1 AND alt_tar > 0 { + set alt_tar to alt_tar-1. + } + + wait 0.1. + } + + print "landed.". + lock throttle to 0. + sas on. +} + +function test_launch { + if alt:radar > 10 { return. } + stage. + lock steering to heading(270,70). + lock throttle to 1.0. + gear off. + wait 15. + lock throttle to 0. + wait(eta:apoapsis-10). +} + +if true { + retro(thespot). + tland(thespot). +} else { + test_launch(). + retro(ksprunwaystart). + tland(ksprunwaystart). +} +lock throttle to 0.0. +wait 1. +myexit(). diff --git a/incl-v1.ks b/incl-v1.ks new file mode 100644 index 0000000..c1e53af --- /dev/null +++ b/incl-v1.ks @@ -0,0 +1,91 @@ +// Set inclination to zero. + +declare parameter incl_new is 0, lan_new is 0. + +run once libguido. +myinit(). + +set firsttime to true. +set done to False. + +// Check if there is anything to do. + +set i to ship:orbit:inclination - incl_new. + +if i > 0 { + wait_turn(heading(180,0)). + lock steering to heading(180,0). +} else { + wait_turn(heading(0,0)). + lock steering to heading(0,0). +} + +until done { + + // calculate angle + if lan_new = 0 { + set an_lat to ship:orbit:lan. + } else { + set an_lat to lan_new. + } + set warpmode to "rails". + + set a to 999. + + until a < 2.0 { + + set t to a/360*ship:orbit:period. + + set_warp_for_t(t). + set ship_lat to mod(longitude+body:rotationangle+720,360). + set a to mod(an_lat-ship_lat+720,360). + wait 0.1. + } + + set warp to 0. + print "AN. lat: "+round(latitude,2)+" incl: "+round(ship:orbit:inclination,3). + print "ship lat: "+round(mod(longitude+body:rotationangle+720,360),2). + print "LAN lat: "+an_lat. + print1s("incl: "+round(ship:orbit:inclination,3)+" ang: "+round(a,2)). + + set i to abs(ship:orbit:inclination - incl_new). + set min_i to 999. + + // Estimate time + + until i < 0 OR mod(a+2,360) > 4 OR abs(i) > (min_i+0.001) { + set old_i to i. + set i to abs(ship:orbit:inclination - incl_new). + set ship_lat to mod(longitude+body:rotationangle+720,360). + set a to mod(an_lat-ship_lat+720,360). + + // How much throttle? + set dv to 2*ship:velocity:orbit:mag*sin(i/2). + set dt to abs(dv)/(ship:maxthrust/ship:mass). + + if dt > 1 { + lock throttle to 1.0. + } else if dt > 0.1 { + lock throttle to 0.1. + } else { + lock throttle to 0.1. + } + print1s("incl: "+round(ship:orbit:inclination,3)+" ang: "+round(a,2)). + wait 0.1. + + if abs(i) < min_i { set min_i to abs(i). }. + } + lock throttle to 0. + + set i to abs(ship:orbit:inclination - incl_new). + if i < 0.1 { + set done to true. + } + + wait 2. + +} + +set i to abs(ship:orbit:inclination - incl_new). +print "done. incl: "+round(i,3). +myexit(). \ No newline at end of file diff --git a/incl.ks b/incl.ks new file mode 100644 index 0000000..7af4c76 --- /dev/null +++ b/incl.ks @@ -0,0 +1,93 @@ +// Set inclination to zero. + +declare parameter incl_new is 0, lan_new is 0. + +run once libguido. +myinit(). + +set firsttime to true. +set done to False. + +// Check if there is anything to do. + +set i to ship:orbit:inclination - incl_new. + +if i > 0 { + wait_turn(heading(180,0)). + //lock steering to heading(180,0). + lock steering to vcrs(ship:velocity:orbit, body:position):direction. +} else { + wait_turn(heading(0,0)). + //lock steering to heading(0,0). + lock steering to vcrs(ship:velocity:orbit, body:position):direction:inverse. +} + +until done { + + // calculate angle + if lan_new = 0 { + set an_lat to ship:orbit:lan. + } else { + set an_lat to lan_new. + } + set warpmode to "rails". + + set a to 999. + + until a < 2.0 { + + set t to a/360*ship:orbit:period. + + set_warp_for_t(t). + set ship_lat to mod(longitude+body:rotationangle+720,360). + set a to mod(an_lat-ship_lat+720,360). + wait 0.1. + } + + set warp to 0. + print "AN. lat: "+round(latitude,2)+" incl: "+round(ship:orbit:inclination,3). + print "ship lat: "+round(mod(longitude+body:rotationangle+720,360),2). + print "LAN lat: "+an_lat. + print1s("incl: "+round(ship:orbit:inclination,3)+" ang: "+round(a,2)). + + set i to abs(ship:orbit:inclination - incl_new). + set min_i to 999. + + // Estimate time + + until i < 0 OR mod(a+2,360) > 4 OR abs(i) > (min_i+0.001) { + set old_i to i. + set i to abs(ship:orbit:inclination - incl_new). + set ship_lat to mod(longitude+body:rotationangle+720,360). + set a to mod(an_lat-ship_lat+720,360). + + // How much throttle? + set dv to 2*ship:velocity:orbit:mag*sin(i/2). + set dt to abs(dv)/(ship:maxthrust/ship:mass). + + if dt > 1 { + lock throttle to 1.0. + } else if dt > 0.1 { + lock throttle to 0.1. + } else { + lock throttle to 0.1. + } + print1s("incl: "+round(ship:orbit:inclination,3)+" ang: "+round(a,2)). + wait 0.1. + + if abs(i) < min_i { set min_i to abs(i). }. + } + lock throttle to 0. + + set i to abs(ship:orbit:inclination - incl_new). + if i < 0.1 { + set done to true. + } + + wait 2. + +} + +set i to abs(ship:orbit:inclination - incl_new). +print "done. incl: "+round(i,3). +myexit(). \ No newline at end of file diff --git a/land.ks b/land.ks new file mode 100644 index 0000000..6944ba9 --- /dev/null +++ b/land.ks @@ -0,0 +1,99 @@ +// Landing function for any planet. +// +// Assumes: +// - No staging required +// - Ignores athmosphere (for now) + + +run once libguido. +myinit(). + +// Land from suborbital flight + +function land { + set bd to ship:orbit:body. + set g to bd:mu / bd:radius^2. + set a_max to maxthrust/mass - g. + set v_land to 0. + + print " ". + print "--- Lander v1.0 ---". + print "landing on "+bd:name. + print "alt : "+round(alt:radar,2)+" m". + print "a_max: "+round(a_max,1)+" m/s". + + sas off. + lock steering to srfretrograde. + lock throttle to 0. + + // turn + print "turning retrograde.". + wait until vang(ship:facing:vector,srfretrograde:vector) < 10 OR alt:radar < 5. + print "turn complete.". + + // Set up math + set v to ship:velocity:surface:mag. + set al to alt:radar. + + set thr to 0. + + until al < 20 AND v < 0.25 { + + set v to ship:velocity:surface:mag. + set al to alt:radar. + set a_max to maxthrust/mass - g. + set t_left to (-v+(v^2+2*al*g)^0.5)/g. + set t_v0 to abs(v-v_land)/a_max. + //print "a: "+round(al,1)+" v: "+round(v,1)+" t_left: "+round(t_left,1)+" t_v0: "+round(t_v0,1). + + if al < 20 { gear on. } + + set dt to t_left-t_v0. + + if mod(floor(time:seconds*10),10) = 0 { + if t_left > 5 { + print "dt : "+dt+" s". + } else { + print "agl: "+al+" m". + } + } + + if t_left > 5 { + // Still 5 seconds away, coarse maneuvers... + if dt < 1 and v > 5 { + set thr to 1.0. + } else { + set thr to 0. + } + } else { + // Close to ground fine tune + // calc acceleration that gets us to desired speed in 2 seconds + set v_goal to max((al-20)/5,0). + set dv to max(v-v_goal,0). + set thr to min(1.0,(dv+g-3.0)/(a_max+g)). + //print "thr:"+thr+" dv:"+dv+" goal:"+v_goal. + } + lock throttle to thr. + + wait 0.1. + } + + print "landed.". + lock throttle to 0. + sas on. +} + +function test_launch { + stage. + lock steering to heading(270,80). + lock throttle to 1.0. + gear off. + wait 30. + lock throttle to 0. +} + +//test_launch(). +land(). +lock throttle to 0.0. +wait 1. +unlock throttle. diff --git a/libcapture.ks b/libcapture.ks new file mode 100644 index 0000000..8f1c688 --- /dev/null +++ b/libcapture.ks @@ -0,0 +1,275 @@ +// Planetary Tranfer Library + +@lazyglobal off. + +run once libguido. +run once libtransfer. + +// Orbit table +// Format is Body, Standard Orbit, Aerocapture Orbit, Departure Orbit + +declare global orbit_table to list( + list(Kerbin, 150, 45, 1000), + list(Duna, 100, 15, 500), + list(Eve, 200, 90, 500 ), + list(Dres, 100, 100, 500) +). + +function get_orbit_data { + parameter dst. + declare local p to 0. + + for p in orbit_table { + if ship:orbit:body = p[0] { + return p. + } + } + print "orbital parameter lookup failed for "+dst. + return list(0,0,0). +} + +// Get into a stable orbit around a planet or moon +// Assumes we are already in the SOI of the planet +// +// Parameters: Destination, target altitude (0 for capture), yes/no flag if we should try to fix inclination. + +function capture_1 { + parameter dst is ship:orbit:body. + parameter dst_alt is -1. + parameter fix_incl is True. + + declare local s to "". + if fix_incl { + set s to ", fix inclination". + } + + // If no altitude was specified, figure it out + + if dst_alt <= 0 { + local p_data is get_orbit_data(dst). + if dst_alt = 0 { + // Aerocapture + set dst_alt to p_data[2]*1000. + set s to ", aerocapture". + } else { + set dst_alt to p_data[1]*1000. + set s to ", standard orbit". + } + } + + print "Capture mode for "+dst:name+" target alt "+km(dst_alt)+s. + + // Error checking that we in the right spot. + + if dst = ship:orbit:body { + print "in SOI of "+body:name+" pe: "+floor(ship:periapsis). + if ship:apoapsis > 0 AND ship:periapsis > dst_alt*0.75 { + print "We are in a stable orbit. Nothing to do.". + return True. + } + } else { + if dst:orbit:body = ship:orbit:body { + print "in SOI of "+body:name+", parent of "+dst:name+" pe: "+floor(ship:periapsis). + panic("Capture to moons not supported yet."). + return False. + } else { + print "Error: destination"+dst:name+" is not in orbit of "+body:name. + panic("Wrong planet?"). + } + } + + + // If there is no maneuver node, create one. + local mynode is NODE(300+time:seconds,0,0,0). + if NOT hasnode { ADD mynode. } + else set mynode to nextnode. + + local old_node to list(mynode:prograde, mynode:normal, mynode:radialout, mynode:eta+time:seconds). + + local n_pro to 0. + local n_nor to 0. + local n_rad to 0. + local step to 20. + local v to 0. + local i to 0. + + local pe to calc_pe(mynode,0). + local original_pe to pe. + local old_pe to 0. + local old_i to 0. + local old_i2 to 0. + + clr_status(). + + // Phase 2 - Fix inclination to the extent possible + + until step < 0.03 OR NOT fix_incl { + set old_i to mynode:orbit:inclination. + set old_i2 to old_i. + // Vary Normal + + vary_node(mynode, old_node, n_pro, n_nor+step, n_rad, 0, 0). + set i to mynode:orbit:inclination. + if i < old_i2 { + set n_nor to n_nor+step. + set old_i2 to i. + } else { + vary_node(mynode, old_node, n_pro, n_nor-step, n_rad, 0, 0). + set i to mynode:orbit:inclination. + if i < old_i2 { + set n_nor to n_nor-step. + set old_i2 to i. + } + } + + set v to vary_node(mynode, old_node, n_pro, n_nor, n_rad+step, 0, 0). + set i to mynode:orbit:inclination. + if i < old_i2 { + set n_rad to n_rad+step. + } else { + vary_node(mynode, old_node, n_pro, n_nor, n_rad-step, 0, 0). + set i to mynode:orbit:inclination. + if i < old_i2 { + set n_rad to n_rad-step. + } + } + vary_node(mynode, old_node, n_pro, n_nor, n_rad, 0, 0). + set i to mynode:orbit:inclination. + + p_status("PE: "+km(pe)+" ("+percent(pe, original_pe)+")",1). + p_status("Incl:"+round(i ,1),2). + p_status("Pro: "+round(n_pro,2),3). + p_status("Nor: "+round(n_nor,2),4). + p_status("Rad: "+round(n_rad,2),5). + p_status("step:"+round(step,2),6). + + if old_i <= i { + set step to step/3. + } + } + + // Phase 3 - increase Periapsis if needed via radial + + set step to 1. + set pe to vary_node(mynode, old_node, n_pro, n_nor, n_rad, 0, 0). + until step < 0.03 OR pe > dst_alt { + set old_pe to pe. + + // Vary Radial + set v to vary_node(mynode, old_node, n_pro, n_nor, n_rad+step, 0, 0). + if v > old_pe { + set n_rad to n_rad+step. + } else { + set v to vary_node(mynode, old_node, n_pro, n_nor, n_rad-step, 0, 0). + if v > old_pe { + set n_rad to n_rad-step. + } + } + set pe to vary_node(mynode, old_node, n_pro, n_nor, n_rad, 0, 0). + + p_status("PE: "+km(pe)+" ("+percent(pe, original_pe)+")",1). + p_status("Incl:"+round(i ,1),2). + p_status("Pro: "+round(n_pro,2),3). + p_status("Nor: "+round(n_nor,2),4). + p_status("Rad: "+round(n_rad,2)+" <--",5). + p_status("step:"+round(step,2),6). + } + + // Phase 4 - Retrograde until we have target periapsis. + + set step to 100. + set pe to vary_node(mynode, old_node, n_pro, n_nor, n_rad, 0, 0). + until step < 0.03 { + set old_pe to pe. + + // Vary Prograde + set v to vary_node(mynode, old_node, n_pro+step, n_nor, n_rad, 0, 0). + if abs(dst_alt-v) < abs(dst_alt-old_pe) AND FALSE { + // This will never happen, for now. + set n_pro to n_pro+step. + } else { + set v to vary_node(mynode, old_node, n_pro-step, n_nor, n_rad, 0, 0). + if abs(dst_alt-v) < abs(dst_alt-old_pe) { + set n_pro to n_pro-step. + } + } + set pe to vary_node(mynode, old_node, n_pro, n_nor, n_rad, 0, 0). + + p_status("PE: "+km(pe)+" ("+percent(pe, original_pe)+")",1). + p_status("Incl:"+round(i ,1),2). + p_status("Pro: "+round(n_pro,2)+" <--",3). + p_status("Nor: "+round(n_nor,2),4). + p_status("Rad: "+round(n_rad,2),5). + p_status("step:"+round(step,2),6). + + if old_pe <= pe { + set step to step/3. + } + } + + print "Maneuver pe: "+km(mynode:orbit:periapsis)+" incl:"+mynode:orbit:inclination.. + exec_n(nextnode). + wait 1. + myquicksave("x6-dstorbit-1"). +} + +function capture_2 { + + parameter dst_alt. + + if ship:apoapsis > 0 AND ship:periapsis > dst_alt*0.75 { + print "Orbit looking good enough. Capture module done.". + return True. + } + + // Now plan the Periapsis burn. + // This time we can simply calculate with VV equations. + + local dv is vv_circular(ship:periapsis)-vv_alt(ship:periapsis). + local mynode is NODE(eta:periapsis+time:seconds,0,0,dv). + ADD mynode. + + print "breaking at PE for "+round(dv,1)+" m/s". + + exec_n(nextnode). + + print "Welcome to "+body:name+" ap/pe: "+km(ship:apoapsis)+" / "+km(ship:periapsis). + myquicksave("x7-dstorbit-2"). +} + +function capture { + parameter dst. + parameter dst_alt is -1. + parameter fix_incl is True. + + if ship:orbit:body <> dst { + print "Wrong planet?". + return False. + } + + // Twice seems to work better for inclination + capture_1(dst, dst_alt, fix_incl). + capture_1(dst, dst_alt, fix_incl). + + capture_2(dst_alt). + +} + + + + + + + + + + + + + + + + + + + diff --git a/libguido.ks b/libguido.ks new file mode 100644 index 0000000..d3caa4b --- /dev/null +++ b/libguido.ks @@ -0,0 +1,559 @@ +// Common Functions + +@lazyglobal off. + +// Constants + +declare global ksplaunchpad to LATLNG(-0.0972077948308072, -74.557676885654786). +declare global ksprunwaystart to LATLNG(-0.048599996665065981,-74.724473624279071). +declare global ksprunwayend to LATLNG(-0.05016922733662988, -74.498071382014942). +declare global ksplandingspot to LATLNG(-0.0,-74.72). + +// Quick function to check for 1%, 2% and 5% deviation + +function prec_01 { + parameter a, b. + if abs(a-b)/max(abs(a),abs(b)) < 0.01 { return True. } + return False. +} + +function prec_02 { + parameter a, b. + if abs(a-b)/max(abs(a),abs(b)) < 0.02 { return True. } + return False. +} + +function prec_05 { + parameter a, b. + if abs(a-b)/max(abs(a),abs(b)) < 0.05 { return True. } + return False. +} + +// Safe staging + +function safe_stage { + print "staging.". + wait until stage:ready. + stage. + wait 0.1. + + // Extend solar panels if we just activated ion engines + declare local elist to 0. + declare local e to 0. + list engines in elist. + for e in elist { + if e:IGNITION AND e:name = "ionEngine" { + panels ON. + print "switching to ion engines, extending solar panels.". + break. + } + + } +} + +// Burn Maneuver Node +// Based on code from KOS documentation + +function exec_n { + parameter n. + + if n:deltav:mag < 1 { + print "Node have dv ov "+n:deltav:mag +" m/s, ignoring.". + REMOVE n. + return True. + } + + if ship:maxthrust = 0 { + print "fuel exhausted. staging.". + safe_stage(). + wait 0.1. + } + + declare local dt to n:deltav:mag/(ship:maxthrust/ship:mass). + + print "executing node in "+round(n:eta,1)+" s with dv: "+round(n:deltav:mag,1). + print "est. time: "+round(dt,1). + + wait_turn(n:deltav:direction). + + if n:eta - dt/2 - 15 > 0 { + print "waiting for burn.". + rwait(n:eta - dt/2 -15). + lock steering to n:deltav. + pwait(15). + } else if n:eta > 0 { + print "too close: "+round(n:eta,1)+" s". + lock steering to n:deltav. + pwait(n:eta). + } + + lock steering to n:deltav. + declare local dv0 to n:deltav. + + until false { + if ship:maxthrust = 0 { + print "fuel exhausted. staging.". + wait until stage:ready. + safe_stage(). + wait 0.1. + } else { + set_throttle(n:deltav:mag,5). + if vdot(dv0, n:deltav) < 0 { break. } + if n:deltav:mag < 0.1 + { + wait until vdot(dv0, n:deltav) < 0.5. + break. + } + } + wait 0.1. + } + lock throttle to 0. + unlock steering. + print "done. dv: "+round(n:deltav:mag,1)+" m/s". + wait 0.1. + remove n. +} + +// Time needed for Hohmann transfer from alt1->alt2 + +function t_hohmann { + parameter alt1. + parameter alt2. + return constant:pi*( (alt1+alt2+2*body:radius)^3/(8*body:mu) )^0.5. +} + +// Velocity at a specific altitude for current orbit. + +function vv_alt { + parameter r. + declare local gm to body:mu. + return (gm*(2/(r+body:radius)-1/ship:orbit:semimajoraxis))^0.5. +} + +// Velocity at a specific altitude for an arbitrary orbit + +function vv_axis { + parameter r. + parameter axis. + declare local gm to body:mu. + return (gm*(2/(r+body:radius)-1/axis))^0.5. +} + +// Velocity for a circular orbit at a given altitude AGL + +function vv_circular { + parameter r. + return vv_axis(r, r+body:radius). +} + +// Horizontal Vector + +function v_hor { + parameter v. + declare local up_vec to 0. + set up_vec to heading(0,90):vector. + return v - (v*up_vec)*up_vec. +} + +// Find closest approach of A to B for the next full orbit of A + +function find_closest { + parameter orbl_a. + parameter orbl_b. + + declare local t to time:seconds. + declare local dt_max to orbl_a:orbit:period. + declare local dt to 0. + declare local a_v to 0. + declare local b_v to 0. + declare local min_d to 999999999999. + declare local old_min_d to 999999999999. + declare local min_t to 0. + + declare local step to 0.01. + + // Check time in steps of 1/100. + until dt > dt_max { + set a_v to positionat(orbl_a,t+dt). + set b_v to positionat(orbl_b, t+dt). + if (a_v-b_v):mag < min_d { + set min_t to t+dt. + set min_d to (a_v-b_v):mag. + } + set dt to dt+0.01*dt_max. + } + + // We have an initial closest approach, now hillclimb + + set step to 0.01. + set dt to min_t-t. + + // Check time in steps of 1/1000. + until step < 0.000001 { + + set old_min_d to min_d. + + // Try dt+step*max + set a_v to positionat(orbl_a, t+dt+step*dt_max). + set b_v to positionat(orbl_b, t+dt+step*dt_max). + if (a_v-b_v):mag < min_d { + set dt to dt+step*dt_max. + set min_d to (a_v-b_v):mag. + } + set a_v to positionat(orbl_a, t+dt-step*dt_max). + set b_v to positionat(orbl_b, t+dt-step*dt_max). + if (a_v-b_v):mag < min_d { + set dt to dt-step*dt_max. + set min_d to (a_v-b_v):mag. + } + //print " dt/min_d/step "+round(dt,1)+" / "+km(min_d)+" / "+step. + if min_d <= old_min_d { + // No improvement, so let's lower granularity + set step to step/4. + } + } + return min_d. +} + +// Geo coordinates for landing + +declare global lat_to_m to 1. +declare global lng_to_m to 1. + +function calibrate_geo { + set lat_to_m to (latlng(0,0):position-latlng(1,0):position):mag. + set lng_to_m to (latlng(0,0):position-latlng(0,1):position):mag. + print "calibration of geo coordinates (equator).". + print "1 deg lat in m: "+lat_to_m. + print "1 deg lat in m: "+lng_to_m. +} + +function geo_v { + parameter geo_pos. + parameter alt is 0. + return V(geo_pos:lat*lat_to_m, geo_pos:lng*lng_to_m, geo_pos:terrainheight+alt). +} + +function rn_v { + parameter v. + return "("+round(v:x,1)+" "+round(v:y,1)+" "+round(v:z,1)+")". +} + +// Burn at max thrust for dt + +function burn { + parameter dt. + parameter thr. + lock throttle to thr. + declare local t0 is time:seconds. + until time:seconds-t0 > dt { + if ship:maxthrust = 0 { + print "fuel exhausted. staging.". + stage. + wait 0.1. + } + wait 0.01. + } + lock throttle to 0.0. +} + +// Set throttle to a 10 second burn or to max + +function set_throttle { + parameter delta_v. + parameter dt. + declare local max_thrust to ship:maxthrust. + + //print max_thrust+" "+delta_v+" "+dt. + if max_thrust > 0 { + lock throttle to max(min(1.0,abs(delta_v/(max_thrust/ship:mass))/dt),0.01). + } else { + lock throttle to 0.01. + } +} + +// timed_turn(direction, time) +// Turns the ship and returns after exactly [time] seconds + +function timed_turn { + parameter v. + parameter t. + lock steering to v. + set warpmode to "physics". + set warp to 3. + wait t. + kuniverse:timewarp:cancelwarp(). +} + +function wait_turn { + parameter v. + lock steering to v. + set warpmode to "physics". + set warp to 3. + until vang(ship:facing:vector,v:vector) < 2 { + //print ship:facing:vector +" "+ v:vector. + wait 0.2. + } + kuniverse:timewarp:cancelwarp(). +} + +function wait_until_in_orbit_of { + parameter dst_body. + + if ship:obt:body <> dst_body { + print "waiting for SOI of "+dst_body:name. + wait 1. + set warpmode to "rails". + set warp to 7. + wait until ship:obt:body = dst_body. + set warp to 0. + } +} + +function smooth_pitch { + parameter mycourse. + parameter old_pitch. + parameter new_pitch. + parameter t is 15. + + declare local s is 0. + + until s > t { + lock steering to heading( mycourse, (old_pitch*(t-s)+new_pitch*s)/t ). + //print heading( mycourse, (old_pitch*(t-s)+new_pitch*s)/t ). + set s to s+0.1. + wait 0.1. + } +} + +function set_warp_for_t { + parameter t. + if t > 110000 { + set warp to 7. + } else if t > 11000 { + set warp to 6. + } else if t > 1100 { + set warp to 5. + } else if t > 110 { + set warp to 4. + } else if t > 55 { + set warp to 3. + } else if t > 11 { + set warp to 2. + } else if t > 6 { + set warp to 1. + } else { + set warp to 0. + } +} + +// rwait() - Wait in rails mode + +function rwait { + parameter dt. + if dt < 0 { + print "warning: rwait time negative. dt = "+round(dt,3). + } + set warpmode to "rails". + declare local t to time:seconds+dt. + until time:seconds > t { + set_warp_for_t(t-time:seconds). + wait 0.2. + } +} + +function pwait { + parameter t. + if t < 0 { + print "warning: pwait time negative. t = "+round(t,3). + } + set warpmode to "physics". + set warp to 3. + wait t. + set warp to 0. +} + +function pfast { + set warpmode to "physics". + set warp to 3. +} + +function pstop { + kuniverse:timewarp:cancelwarp(). +} + +// Engines + +declare function set_engine { + parameter name_str. + parameter on. + + declare local c to 0. + declare local el to 0. + declare local e to 0. + declare local on_str to "". + + list engines in el. + for e in el { + if e:Name:contains(name_str) { + if on { e:ACTIVATE(). } + else { e:SHUTDOWN(). } + } + set c to c+1. + } + if on {set on_str to "on". } + else {set on_str to "off". } + print "switched "+c+" engines of type "+name_str+" to "+on_str. +} + +declare function rapier_air { + declare local c to 0. + declare local el to 0. + declare local e to 0. + + list engines in el. + for e in el { + if e:Name:contains("RAPIER") { + if e:mode = "ClosedCycle" { e:TOGGLEMODE(). } + set c to c+1. + } + } + print "Switched "+c+" x RAPIERs to air-breathing.". +} + +declare function rapier_space { + declare local c to 0. + declare local el to 0. + declare local e to 0. + + list engines in el. + for e in el { + if e:Name:contains("RAPIER") { + if e:mode <> "ClosedCycle" { e:TOGGLEMODE(). } + set c to c+1. + } + } + print "Switched "+c+" x RAPIERs to closed cycle.". +} + + +// Quicksave + +function myquicksave { + parameter name. + wait until KUniverse:CANQUICKSAVE. + KUniverse:QUICKSAVETO(name). + print "saving progress: "+name. +} + +// Printing/Logging + +declare global last_print to 0. + +// Print only if 1s has passed +function print1s { + parameter s. + if time:seconds-last_print > 1 { + print s. + set last_print to time:seconds. + } +} + +// Print status on the right side of the terminal. +function p_status { + parameter s. + parameter l. + set s to " "+s+" ". + print s:substring(0,32) AT(terminal:width-32,l+1). +} + +function clr_status { + p_status("----------- Status -----------",-1). + p_status("",0). + p_status("",1). + p_status("",2). + p_status("",3). + p_status("",4). + p_status("",5). + p_status("",6). + p_status("------------------------------",7). +} + +// Print distance as 10,000km + +function p3d { + parameter v. + set v to floor(v). + if v > 100 { return v. } + if v > 10 { return "0"+v. } + if v > 0 { return "00"+v. } +} + +function km { + parameter d. + if d > 1000000000 { + return floor(d/1000000000)+","+p3d(floor(mod(d,1000000000)/1000000))+","+p3d(floor(mod(d,1000000)/1000))+" km". + } else if d > 1000000 { + return floor(d/1000000)+","+p3d(floor(mod(d,1000000)/1000))+" km". + } else if d > 1000 { + return round(d/1000,1)+" km". + } else if d > 10 { + return round(d,0)+" m". + } else if d > 1 { + return round(d,1)+" m". + } else { + return round(d,2)+" m". + } +} + +// Print percentage of a of b +function percent { + parameter a. + parameter b. + + if b = 0 { return "N/A". } + local p is abs(a/b)*100. + if p > 5 { + return round(p)+"%". + } else { + return round(p,1)+"%". + } +} + +// Print percentage of a of b +function percent_err { + parameter a. + parameter b. + + return percent(a-b,b). +} + +declare global time_zero to 0. + +function mytimer_s { + set time_zero to time:seconds. +} + +function mytimer { + return "["+round(time:seconds-time_zero,1)+" s] ". +} + +function myinit { + sas off. + lock throttle to 0.0. + kuniverse:timewarp:cancelwarp(). + wait 1. +} + +function myexit { + lock throttle to 0.0. + kuniverse:timewarp:cancelwarp(). + wait 0.1. + sas on. +} + +function panic { + parameter s. + print "PANIC: "+s. + KUniverse:PAUSE(). +} \ No newline at end of file diff --git a/libtransfer.ks b/libtransfer.ks new file mode 100644 index 0000000..3dcbdd3 --- /dev/null +++ b/libtransfer.ks @@ -0,0 +1,276 @@ +// Planetary Tranfer Library + +@lazyglobal off. +run once libguido. + +// Pre-calculated transfer table +// Format is Src, Dst, Altitude/km, Phase Angle, Ejection Angle, Ejection Velocity. + +declare global transfer_table to list( + list(Kerbin, Duna, 1000, 44.36, 138.75, 2267.83), + list(Kerbin, Eve, 1000, -54.13, 143.44+180, 2226.01), + list(Kerbin, Dres, 1000, 82.06, 110.16, 2934.47), + list(Duna, Kerbin, 500, -75.19, 110.68+180, 1186.75), + list(Eve, Kerbin, 500, 36.07, 159.13, 3754.75), + list(Dres, Kerbin, 500,-329.68, 90.77+180, 1589.12) +). + +// Helper functions for PE optimization + +function calc_pe { + parameter n. + parameter mode. + + if mode = 0 { + return n:orbit:periapsis. + } else if mode = 1 { + if NOT n:orbit:hasnextpatch { + return 99999999999. + } else { + return n:orbit:nextpatch:periapsis. + } + } else if mode = 2 { + if NOT n:orbit:hasnextpatch or NOT n:orbit:nextpatch:hasnextpatch { + return 99999999999. + } else { + return n:orbit:nextpatch:nextpatch:periapsis. + } + } + panic("wrong mode in calc_pe"). +} + +function print_node { + parameter n. + print "N eta:"+round(n:eta,1)+ + " pro:"+round(n:prograde,1)+ + " rad:"+round(n:radialout,1)+ + " nor:"+round(n:normal,1). +} + + +function vary_node { + parameter p_node. + parameter base_values. + parameter p_pro. + parameter p_nor. + parameter p_rad. + parameter p_eta. + parameter mode. + + set p_node:prograde to base_values[0]+p_pro. + set p_node:normal to base_values[1]+p_nor. + set p_node:radialout to base_values[2]+p_rad. + // set p_node:eta to base_values[3]+p_eta-time:seconds. + + return calc_pe(p_node, mode). + } + + +// Optimize PE +// +// Parameters +// - Min PE, Max PE, Destination Body +// - Auto-detects which mode: +// 1. Current body PE. +// 2. Nextpatch (e.g. interplanetary space for Duna). +// 3. Nextpatch:nextpatch (i.e. still on Kerbin, heading for Duna). +// - Works with existing node or will create one 5 mins out. +// - Returns "best effort" optimization + +function optimize_pe { + + parameter pe_min. + parameter pe_max. + parameter dst. + + local src is ship:orbit:body. + local mynode is NODE(300+time:seconds,0,0,0). + local old_node is 0. + local dst_orb is 0. + local mode is 0. + + // If there is no maneuver node, create one. + if NOT hasnode { ADD mynode. } + else set mynode to nextnode. + + // Which mode are we in? + + + if src = dst { + // Already at the destination, just want to optimize the PE. + print "Optimizing PE. In orbit around "+src:name. + set mode to 0. + } else { + if NOT mynode:orbit:hasnextpatch { panic("Optinize_PE called with no encounter."). return False. } + if mynode:orbit:nextpatch:body = dst { + // Interplanetary, found encounter. + print "Optimizing PE. Interplanetary orbit to "+dst:name. + set mode to 1. + } else { + if NOT mynode:orbit:nextpatch:hasnextpatch OR mynode:orbit:nextpatch:nextpatch:body <> dst { + panic("Optinize_PE called with no encounter."). return False. + } else { + // Interplanetary, found encounter. + print "Optimizing PE. In orbit around "+src:name+" -> "+dst:name. + set mode to 2. + } + } + + + } + + // eta to -1 meaning it is immutable + set old_node to list(mynode:prograde, mynode:normal, mynode:radialout, -1). + + local n_pro to 0. + local n_nor to 0. + local n_rad to 0. + local n_eta to 0. + local step to 20. + local v to 0. + + local pe to calc_pe(mynode,mode). + local old_pe to 0. + local int_pe to 0. + local original_pe is pe. + print "pre-opt pe : "+km(pe). + print "optimizing...". + clr_status(). + + print "starting". + + until pe < pe_max or step < 0.03 { + // remember PE calculated with current values . Copy into a PE for interrim. + set old_pe to vary_node(mynode, old_node, n_pro, n_nor, n_rad, n_eta, mode). + set int_pe to old_pe. + + // Vary Normal + + set v to vary_node(mynode, old_node, n_pro, n_nor+step, n_rad, n_eta, mode). + if v < int_pe AND v > pe_min { + set n_nor to n_nor+step. + set int_pe to calc_pe(mynode,mode). + } else { + set v to vary_node(mynode, old_node, n_pro, n_nor-step, n_rad, n_eta, mode). + if v < int_pe AND v > pe_min { + set n_nor to n_nor-step. + set int_pe to calc_pe(mynode,mode). + } + } + + // Vary Prograde + set v to vary_node(mynode, old_node, n_pro+step/5, n_nor, n_rad, n_eta, mode). + if v < int_pe AND v > pe_min { + set n_pro to n_pro+step/5. + set int_pe to calc_pe(mynode,mode). + } else { + set v to vary_node(mynode, old_node, n_pro-step/5, n_nor, n_rad, n_eta, mode). + if v < int_pe AND v > pe_min { + set n_pro to n_pro-step/5. + set int_pe to calc_pe(mynode,mode). + } + } + + // Vary Radial + set v to vary_node(mynode, old_node, n_pro, n_nor, n_rad+step, n_eta, mode). + if v < int_pe AND v > pe_min { + set n_rad to n_rad+step. + set int_pe to calc_pe(mynode,mode). + } else { + set v to vary_node(mynode, old_node, n_pro, n_nor, n_rad-step, n_eta, mode). + if v < int_pe AND v > pe_min { + set n_rad to n_rad-step. + set int_pe to calc_pe(mynode,mode). + } + } + + set pe to vary_node(mynode, old_node, n_pro, n_nor, n_rad, n_eta, mode). + + p_status("PE: "+km(pe)+" ("+percent(pe, original_pe)+")",1). + p_status("ETA: "+round(n_eta-time:seconds)+" step: "+round(step,2),2). + p_status("Pro: "+round(n_pro,2),3). + p_status("Nor: "+round(n_nor,2),4). + p_status("Rad: "+round(n_rad,2),5). + + if old_pe <= pe { + set step to step/3. + } + } + + print "post-opt pe: "+km(pe)+" ETA/pro/nor/rad : "+round(n_eta)+" / "+round(n_pro,2)+" / "+round(n_nor,2)+" / "+round(n_rad,2). + +} + +// Access table of transfer values + +function get_planet_data { + parameter dst. + declare local p to 0. + + for p in transfer_table { + if ship:orbit:body = p[0] AND dst = p[1] AND prec_01(p[2]*1000,ship:orbit:apoapsis) { return p. } + if ship:orbit:body = Sun AND dst = p[1] { return p. } + } + print "transfer parameter lookup failed for "+ship:orbit:body+" -> "+dst+" alt: "+km(ship:orbit:apoapsis). + return list(0,0,0). +} + +// Calculate and wait for a transfer window between planets. +// This won't return until we are there. + +function calc_phase_angle { + parameter src. + parameter dst. + + declare local as to src:obt:lan + src:obt:argumentofperiapsis + src:obt:trueanomaly. + declare local ad to dst:obt:lan + dst:obt:argumentofperiapsis + dst:obt:trueanomaly. + return mod(ad-as+720,360). +} + + +// Wait for a transfer window. + +function wait_transfer_window { + + declare parameter dst. + + declare local src to ship:orbit:body. + declare local da to calc_phase_angle(src, dst). + declare local da_old to da. + + // Wait for a transfer window to another planets + // Uses precomputed values from transfer calculator + + print "waiting for transfer window.". + declare local tr_data to get_planet_data(dst). + if tr_data[2] = 0 { return False. } + + declare local phase_angle to mod(tr_data[3]+720,360). + print "target phase angle: "+phase_angle. + + if da > phase_angle-2 AND da < phase_angle+2 { + print "At the right phase angle already.". + } else { + + set warpmode to "rails". + clr_status(). + p_status("Waiting for Transfer",0). + p_status("Target:"+round(phase_angle,1),1). + wait 0.1. + + until da > phase_angle-0.5 AND da < phase_angle+0.5 { + set da_old to da. + set da to calc_phase_angle(src, dst). + p_status("Phase : "+round(da,1),2). + p_status("ETA : "+round((phase_angle-da)/(da-da_old)/10)+" s",3). + set warp to 7. + wait 10000. + } + set warp to 0. + } + + // Warping fast, wait until we are done. + wait until kuniverse:timewarp:issettled. + print "Final phase angle: "+round(calc_phase_angle(src, dst),2)+" ("+percent_err(calc_phase_angle(src, dst), phase_angle)+")". + return True. +} \ No newline at end of file diff --git a/lsp.ks b/lsp.ks new file mode 100644 index 0000000..b47049a --- /dev/null +++ b/lsp.ks @@ -0,0 +1,179 @@ +// Spaceplane launch + +run once libguido. +myinit(). + +set runway_g to ksprunwaystart. +set runway_lat to runway_g:lat. +set runway_lng to runway_g:lng. +set landing_spot_alt to runway_g:TERRAINHEIGHT. + +set v_td to 50. +set v_cruise to 300. +set dst_lng to mod(runway_lng-100+720,360). +set p_entry to 45. +set n to ship:name. +set glideslope to 0.15. +set ap_alt_error to 50. + +if n = "Other" { + // Do nothing + print "Other???". +} else { + print "Standard SSTO Space Plane". +} + +print " v_td: "+v_td+" m/s". + +print "Space plane landing started. alt: "+round(ship:altitude). +print "Landing spot altitude: "+round(landing_spot_alt,1)+" m". + +if ship:periapsis > 68000 { + + // Plan re-entry. + + set da to mod(dst_lng-longitude+720,360). + set dt to da*ship:orbit:period/360. + print "wait: "+round(dt)+" s". + rwait(dt). + + wait_turn(ship:retrograde). + lock steering to retrograde. + pwait(10). + print "ready for burn. da: "+round(mod(dst_lng-longitude+720,360),1). + + // Burn to slow down. + print "burn started.". + lock throttle to 1.0. + wait until ship:periapsis < 0. + lock throttle to 0. + + print "re-entry set up complete. pe: "+round(ship:periapsis,1). + + wait 3. + set warpmode to "rails". + set warp to 4. + wait until ship:altitude < 70000. + + print "re-entry into athmosphere.". + lock steering to heading(90,10). + brakes on. + set warpmode to "physics". + set warp to 3. + + wait until ship:altitude < 30000. + print "30,000 feet.". + smooth_pitch(90, 10, 0, 10). + pstop(). + } + +// Descent to 10,000 + +if ship:altitude > 10000 { + brakes on. + set steering to heading(90,0). + print "descending to 10,000 m". + set pitch_high to True. + until ship:altitude < 10000 { + set v to ship:velocity:surface:mag. + if v < 1400 AND pitch_high { + print "speed < 1,400 m/s. pitching down.". + smooth_pitch(90, 0, -20, 10). + set pitch_high to False. + } + wait 0.1. + } +} + +// From now on, we fly actively to the runway. +// Accelerate if needed. Steer to the right latitude. + +if alt:radar > 100 { + // Transitioning to flight + + brakes off. + print "transitioning to flight. a: "+ship:altitude. + + set p_base to 0. + set_engine("nuclear",0). + rapier_air(). + intakes on. + lock throttle to 0. + wait 0.1. + set old_dst to 999999. + + until alt:radar < 50 { + + // distance and velocity is horizontal component only. + set dst to v_hor(ship:position-runway_g:position):mag. + set v to v_hor(ship:velocity:surface):mag. + set a to ship:altitude. + + // -- Throttle + if dst > v_cruise*60 { + set v_target to v_cruise. + } else if dst > v*15 { + set v_target to v_td*1.5. + } else { + set v_target to v_td. + } + + if v < v_target { + set throttle to min(1.0,(v_target-v)/v_target*25). + } else { + set throttle to 0.0. + } + + // -- Pitch + if old_dst < dst { + // past the target + set tar_alt to landing_spot_alt. + } else { + set tar_alt to min(9000,dst*glideslope)+landing_spot_alt-ap_alt_error. + } + set old_dst to dst. + set del_p to max(min((tar_alt-a)/10,5),-20). + set p to p_base+del_p. + + // -- Heading + set d_lat to abs(latitude-runway_lat). + set d_head to min(5,abs(d_lat)*500). + + if latitude < runway_lat { + lock steering to heading(90-d_head,p). + } else { + lock steering to heading(90+d_head,p). + } + + // Gear at 2km distance. + if gear = False and dst < 2000 { + gear on. + } + + print1s( "dst: " +round(dst,1)+ + " d_lat: " +round(d_lat,4)+ + " d_head: "+round(d_head,2)+ + " v: " +round(v,1) + + " a: " +round(a,0) + + " da: " +round(tar_alt-a) + + " p: " +round(p,1) + ). + + wait 0.2. + } +} + +// Land. + +// Flare and land. +lock steering to heading(90.42, 4). +lock throttle to 0.0. +brakes on. + +until v < 0.1. { + wait 0.1. +} + +myexit(). +print "Landed.". + diff --git a/reorb.ks b/reorb.ks new file mode 100644 index 0000000..ced7d06 --- /dev/null +++ b/reorb.ks @@ -0,0 +1,73 @@ +// Change Orbit of Current Ship + +declare parameter alt_new. + +run once libguido. +myinit(). + +// Check if there is anything to do. + +set apo_p to abs( (ship:apoapsis-alt_new)/alt_new). set per_p to abs( (ship:periapsis-alt_new)/alt_new). + +if apo_p < 0.01 AND per_p < 0.01 { + print "nothing to do. reorb done.". +} else { + set done to false. + set firsttime to true. + until done { + set t_pe to eta:periapsis. + set t_ap to eta:apoapsis. + set ap to ship:apoapsis. + set pe to ship:periapsis. + + set max_acc to ship:maxthrust/ship:mass. + set v_new to vv_circular(alt_new). + set v_ap to vv_alt(ship:apoapsis). + set v_pe to vv_alt(ship:periapsis). + set target_v_pe to vv_axis(ship:periapsis,(ship:periapsis+2*body:radius+alt_new)/2). + set target_v_ap to vv_axis(ship:apoapsis,(ship:apoapsis+2*body:radius+alt_new)/2). + set dv_ap to target_v_ap-v_ap. + set dv_pe to target_v_pe-v_pe. + set apo_p to abs( (ship:apoapsis-alt_new)/alt_new). + set per_p to abs( (ship:periapsis-alt_new)/alt_new). + + set thr to 1.0. + + if firsttime { + print "Change to new Circular Orbit v1.0". + print "target altitude: "+alt_new+" vs. "+floor(ship:apoapsis)+" / "+floor(ship:periapsis). + print "difference: "+floor(apo_p*100)+"% / "+floor(per_p*100)+"%". + print "target velocity: "+round(v_new,1)+" m/s". + set firsttime to false. + } + + if t_pe > t_ap and t_ap > 60 { + // Apoapsis maneuver + set mynode to NODE(time:seconds+eta:apoapsis,0,0,dv_ap). + ADD mynode. + exec_n(mynode). + } else if t_pe > 60 { + // Periapsis maneuver + set mynode to NODE(time:seconds+eta:periapsis,0,0,dv_pe). + ADD mynode. + exec_n(mynode). + } else { + print "too close to node, waiting.". + rwait(60). + } + + set apo_p to abs( (ship:apoapsis-alt_new)/alt_new). + set per_p to abs( (ship:periapsis-alt_new)/alt_new). + print "check: "+alt_new+" vs. "+floor(ship:apoapsis)+" / "+floor(ship:periapsis)+" "+floor(apo_p*100)+"% / "+floor(per_p*100)+"%". + + if apo_p < 0.01 AND per_p < 0.01 { + set done to True. + } else { + wait 3. + } + } +} + +// Clean up +myexit(). +print "reorb done.". \ No newline at end of file diff --git a/reorbit1.ks b/reorbit1.ks new file mode 100644 index 0000000..f65e693 --- /dev/null +++ b/reorbit1.ks @@ -0,0 +1,112 @@ +// Change Orbit of Current Ship + +declare parameter alt_new. + +// Target Velocity in new orbit to get a rough idea of scale +set v_target to sqrt(body:MU/(body:Radius + alt_new)). +set max_acc to ship:maxthrust/ship:mass. +set t to abs( (v_target-ship:velocity:orbit:mag)/max_acc). + +set throttle_max to MIN(1.0, MAX(0.1, t/10)). +set maxburn to 60+t/throttle_max/2. + +print "Change to new Circular Orbit v0.1". +print "target altitude: "+alt_new+" vs. "+floor(ship:apoapsis)+" / "+floor(ship:periapsis). +print "target velocity: "+floor(v_target)+" m/s". +print "buffer time : "+maxburn. +print "est. throttle : "+throttle_max. + +sas off. + +set done to False. + +until done = True { + + set ea to eta:apoapsis. + set ep to eta:periapsis. + + if ea < ep { + + // Apoapsis Maneuver + // First check if AE > new altitude, abort if not + + if ship:apoapsis < alt_new*0.99 { + // Can't raise as AP and PE would switch + print "AP: skipping, raise AP before PE.". + wait ea+10. + } else { + // Wait for AP + print "AP: "+floor(ea)+" sec". + wait ea-maxburn. + print "turning.". + + if ship:periapsis < alt_new { + // raising PE + lock steering to ship:prograde. + wait 60. + + until ship:periapsis > alt_new*0.99 { + lock throttle to throttle_max. + wait .1. + } + lock throttle to 0. + } else { + // lower PE + lock steering to ship:retrograde. + wait 60. + + until ship:periapsis < alt_new*1.01 { + lock throttle to throttle_max. + wait .1. + } + lock throttle to 0. + } + } + } else { + + // Periapsis Maneuver + // First check if PE < new altitude, abort if not + + if ship:periapsis > alt_new*1.01 { + // Can't lower AP as AP and PE would switch + print "PE: skipping, lower PE before AP.". + wait ep+10. + } else { + // Wait for PE + print "PE: "+floor(ep)+" sec". + wait ep-maxburn. + print "turning.". + + if ship:apoapsis < alt_new { + // raising AP + lock steering to ship:prograde. + wait 60. + + until ship:apoapsis > alt_new*0.99 { + lock throttle to throttle_max. + wait .1. + } + lock throttle to 0. + } else { + // lower AP + lock steering to ship:retrograde. + wait 60. + + until ship:apoapsis < alt_new*1.01 { + lock throttle to throttle_max. + wait .1. + } + lock throttle to 0. + } + } + } + + set apo_p to abs( (ship:apoapsis-alt_new)/alt_new). + set per_p to abs( (ship:periapsis-alt_new)/alt_new). + print "check: "+alt_new+" vs. "+floor(ship:apoapsis)+" / "+floor(ship:periapsis)+ " "+floor(apo_p*100)+"% / "+floor(per_p*100)+"%". + if apo_p < 0.01 AND per_p < 0.01 { + set done to True. + } else { + wait 20. + } +} \ No newline at end of file diff --git a/reorbit2.ks b/reorbit2.ks new file mode 100644 index 0000000..a24ea49 --- /dev/null +++ b/reorbit2.ks @@ -0,0 +1,140 @@ +// Change Orbit of Current Ship + +declare parameter alt_new. + +// Target Velocity in new orbit to get a rough idea of scale +set v_target to sqrt(body:MU/(body:Radius + alt_new)). +set max_acc to ship:maxthrust/ship:mass. +set t to abs( (v_target-ship:velocity:orbit:mag)/max_acc). + +set throttle_max to MIN(1.0, MAX(0.01, t/30)). +set maxburn to t/throttle_max/2. + +print "Change to new Circular Orbit v0.1". +print "target altitude: "+alt_new+" vs. "+floor(ship:apoapsis)+" / "+floor(ship:periapsis). +print "target velocity: "+floor(v_target)+" m/s". +print "buffer time : "+maxburn. +print "est. throttle : "+throttle_max. + +function timed_turn { + parameter v. + parameter t. + lock steering to v. + set warpmode to "physics". + set warp to 3. + wait t. + kuniverse:timewarp:cancelwarp(). +} + +function rwait { + parameter t. + kuniverse:timewarp:cancelwarp(). + set warpmode to "rails". + warpto(time:seconds+t-0.1). + wait t. + kuniverse:timewarp:cancelwarp(). +} + +function pfast { + set warpmode to "physics". + set warp to 3. +} + +function pstop { + kuniverse:timewarp:cancelwarp(). +} + +sas off. + +set done to False. + +until done = True { + + set ea to eta:apoapsis. + set ep to eta:periapsis. + + if ea < 60 OR ep < 60 { + print "too close to node, waiting.". + rwait(60). + } else if ea < ep { + + // Apoapsis Maneuver + // First check if AE > new altitude, abort if not + + if ship:apoapsis < alt_new*0.999 { + // Can't raise as AP and PE would switch + print "AP: skipping, raise AP before PE.". + rwait(ea+10). + } else { + // Wait for AP + print "AP: "+floor(ea)+" sec". + rwait(ea-maxburn-45). + print "AP: turning.". + + if ship:periapsis < alt_new { + // raising PE + timed_turn(prograde,45). + until ship:periapsis > alt_new*0.999 { + if (eta:apoapsis > maxburn/2 AND eta:apoapsis < 1000) { lock throttle to 0. set maxburn to maxburn-0.1. } + else { lock throttle to throttle_max. } + lock steering to prograde. + wait .1. + } + } else { + // lower PE + timed_turn(retrograde,45). + until ship:periapsis < alt_new*1.001 { + if (eta:apoapsis > maxburn/2 AND eta:apoapsis < 1000) { lock throttle to 0. set maxburn to maxburn-0.1.} + else { lock throttle to throttle_max. } + lock steering to retrograde. + wait .1. + } + } + } + } else { + + // Periapsis Maneuver + // First check if PE < new altitude, abort if not + + if ship:periapsis > alt_new*1.001 { + // Can't lower AP as AP and PE would switch + print "PE: skipping, lower PE before AP.". + rwait(ep+10). + } else { + // Wait for PE + print "PE: "+floor(ep)+" sec". + rwait(ep-maxburn-45). + print "PE: turning.". + + if ship:apoapsis < alt_new { + // raising AP + timed_turn(prograde,45). + until ship:apoapsis > alt_new*0.999 { + if (eta:periapsis > maxburn/2 AND eta:periapsis < 1000) { lock throttle to 0. set maxburn to maxburn-0.1.} + else { lock throttle to throttle_max. } + lock steering to prograde. + wait .1. + } + } else { + // lower AP + timed_turn(retrograde,45). + until ship:apoapsis < alt_new*1.001 { + if (eta:periapsis > maxburn/2 AND eta:periapsis < 1000) { lock throttle to 0. set maxburn to maxburn-0.1.} + else { lock throttle to throttle_max. } + lock steering to retrograde. + wait .1. + } + } + } + } + lock throttle to 0. + + set apo_p to abs( (ship:apoapsis-alt_new)/alt_new). + set per_p to abs( (ship:periapsis-alt_new)/alt_new). + print "check: "+alt_new+" vs. "+floor(ship:apoapsis)+" / "+floor(ship:periapsis)+ " "+floor(apo_p*100)+"% / "+floor(per_p*100)+"%". + if apo_p < 0.01 AND per_p < 0.01 { + set done to True. + } else { + wait 1. + } +} \ No newline at end of file diff --git a/ret_dun.ks b/ret_dun.ks new file mode 100644 index 0000000..83e2ed1 --- /dev/null +++ b/ret_dun.ks @@ -0,0 +1,115 @@ +// Return from Minmus +run once libguido. + +print "Duna Return v0.1". + + +if ship:apoapsis < 20000 and body = Duna { + sas off. + wait until KUniverse:CANQUICKSAVE. + KUniverse:QUICKSAVETO("x4-prereturn"). + + // Let's get into a 60k orbit. + print "taking off.". + lock steering to heading(90,90). + lock throttle to 1.0. + wait 3. + + print "raise ap to 60,000.". + gear off. + lock steering to heading(90,45). + wait until ship:apoapsis > 60000. + lock throttle to 0. + print "ap: "+round(ship:apoapsis,1)+" eta "+round(eta:apoapsis,1). + set warpmode to "rails". + until eta:apoapsis < 30 { set warp to 3. } + rwait(eta:apoapsis-20). + + print "turning.". + wait_turn(heading(90,0)). + print "circualrizing.". + lock throttle to 1.0. + wait until ship:periapsis > 60000 OR ship:apoapsis > 80000. + lock throttle to 0.0. +} + +if ship:apoapsis < 490000 AND ship:orbit:body = Duna { + sas off. + wait until KUniverse:CANQUICKSAVE. + KUniverse:QUICKSAVETO("x5-retloworbit"). + print "adjusting inclination and raising orbit to 500,000 m". + run incl. + run reorb(500000). +} + +if body = Duna { + wait until KUniverse:CANQUICKSAVE. + KUniverse:QUICKSAVETO("x6-pretransfer"). + + // Load transfer library + run tr_pl(Kerbin,True). + my_transfer(Kerbin). +} + +if body = Kerbin { + wait until KUniverse:CANQUICKSAVE. + KUniverse:QUICKSAVETO("x7-kerbin-soi"). + + if ship:periapsis < 40000 { + print "already in capture orbit.". + } else { + wait_turn(retrograde). + print "PE: "+round(ship:periapsis,1). + until ship:periapsis < 40000 { + if ship:periapsis > 100000 { lock throttle to 1. } + else if ship:periapsis > 41000 { lock throttle to 0.1. } + else { lock throttle to 0.01. } + wait 0.1. + } + set throttle to 0. + unlock throttle. + } + + wait until KUniverse:CANQUICKSAVE. + KUniverse:QUICKSAVETO("x8-captureorbit"). + print "capture orbit. PE :"+round(ship:periapsis,0). + + // We are captured, slowly lower the AP+PE + unlock steering. + sas on. + wait 1. + if sasmode <> "retrograde" { + // To avoid annoying bug + set sasmode to "retrograde". + } + + set warp to 0. + wait 1. + set warpmode to "rails". + set warp to 7. + + // Burn rest of fuel to brake once we are low. + wait until eta:periapsis < 60 or ship:altitude < 45000. + lock throttle to 1.0. + wait until maxthrust = 0 OR ship:altitude < 11000. + lock throttle to 0. + wait 1. + safe_stage(). + + print "waiting for 10,000 MSL". + wait until ship:altitude < 10000. + wait until KUniverse:CANQUICKSAVE. + KUniverse:QUICKSAVETO("x9-preland"). + + print "waiting for parachutes to be safe.". + wait until chutessafe = True OR ship:velocity:surface:mag < 250. + print "chutes safe at alt "+round(alt:radar)+" m". + wait 1. + safe_stage(). + chute on. + print "parachutes deployed.". + print "done.". + wait until KUniverse:CANQUICKSAVE. + KUniverse:QUICKSAVETO("x10-landed"). +} + \ No newline at end of file diff --git a/ret_min.ks b/ret_min.ks new file mode 100644 index 0000000..0c92d8a --- /dev/null +++ b/ret_min.ks @@ -0,0 +1,153 @@ +// Return from Minmus +run once libguido. + +print "Minmus Return v0.1". + +sas off. + +if ship:apoapsis < 20000 and body = Minmus { + + // Parked on the Mun, let's get into a 20k-30k orbit. + print "taking off.". + lock steering to heading(90,90). + lock throttle to 1.0. + wait 3. + + print "raise ap to 25,000.". + gear off. + lock steering to heading(90,45). + wait until ship:apoapsis > 25000. + lock throttle to 0. + print "ap: "+round(ship:apoapsis,1)+" eta "+round(eta:apoapsis,1). + set warpmode to "rails". + until eta:apoapsis < 30 { set warp to 3. } + rwait(eta:apoapsis-10). + + print "turning.". + wait_turn(heading(90,0)). + print "circualrizing.". + lock throttle to 1.0. + wait until ship:periapsis > 20000. + lock throttle to 0.0. +} + +wait until KUniverse:CANQUICKSAVE. +KUniverse:QUICKSAVETO("x4-retorbit"). + +if ship:apoapsis > 20000 and body = Minmus { + + print "waiting for ejection point.". + set dst_ang to -22. + set ang to 99. + + until ang < 1 { + set ang to MAX(MOD(-longitude+dst_ang+720,360),0.0001). + // Estimate how long we need to wait + set dt to MAX(ABS(ship:orbit:period/360*ang),1). + print "eta: "+floor(dt)+" s ( "+floor(ang)+" )". + if dt > 60 { + set warpmode to "rails". wait 0.1. + warpto(time:seconds+dt-30). + wait dt-30+1. + pstop(). + } else if dt > 10 { + lock steering to ship:prograde. + set warpmode to "physics". + wait 0.1. + warpto(time:seconds+dt/2). + wait dt/2+1. + pstop(). + } else { + lock steering to ship:prograde. + wait dt/3. + } + } + + print "ejection burn.". + wait_turn(prograde). + set throttle to 1.0. + wait until ship:apoapsis < 0. + wait 0.1. + set throttle to 0. + until body = Kerbin { + set warpmode to "rails". + set warp to 5. + } +} + + +if ship:periapsis < 48000 { + print "already in capture orbit.". +} else { + + // Multiple times... rounding errors + print "warp for AP. 95%". + rwait(eta:apoapsis*0.95). + print "warp for AP. 100%". + rwait(eta:apoapsis). + + until ship:periapsis < 48000 AND ship:periapsis > 43000 { + // Lower PE + print "turning retrograde.". + wait_turn(retrograde). + print "PE: "+ship:periapsis. + until ship:periapsis < 48000 { + if ship:periapsis > 200000 { lock throttle to 1. } + else if ship:periapsis > 60000 { lock throttle to 0.1. } + else { lock throttle to 0.01. } + Wait 0.1. + } + lock throttle to 0. + + // Check in case we need to raise PE + if ship:periapsis < 43000 { + wait_turn(prograde). + lock throttle to 0.01. + wait until ship:periapsis > 43000. + lock throttle to 0. + } + } + + unlock throttle. + +} + +wait until KUniverse:CANQUICKSAVE. +KUniverse:QUICKSAVETO("x5-captureorbit"). + +print "capture orbit. PE :"+round(ship:periapsis,0). + +// We are captured, slowly lower the AP+PE + +unlock steering. +sas on. +wait 1. +set sasmode to "retrograde". + +set warp to 0. +wait 1. +set warpmode to "rails". +set warp to 7. + +wait until eta:periapsis < 60 or ship:altitude < 45000. + +lock throttle to 1.0. + +wait until maxthrust = 0. + +lock throttle to 0. +wait 1. +stage. + +print "waiting for 10,000 MSL". +wait until ship:altitude < 10000. +print "waiting for parachutes to be safe.". +wait until chutessafe = True OR ship:velocity:surface:mag < 250. +print "chutes safe at alt "+alt:radar. +wait 1. +stage. +chute on. + +print "parachutes deployed.". +print "done.". + \ No newline at end of file diff --git a/ret_mun.ks b/ret_mun.ks new file mode 100644 index 0000000..9aafcc5 --- /dev/null +++ b/ret_mun.ks @@ -0,0 +1,146 @@ +// Return from Mun +run once libguido. + +print "Mun Return v0.1". + +sas off. + +if ship:apoapsis < 20000 and body = Mun { + + // Parked on the Mun, let's get into a 20k-30k orbit. + print "taking off.". + lock steering to heading(90,90). + lock throttle to 1.0. + wait 3. + + print "raise ap to 25,000.". + gear off. + lock steering to heading(90,45). + wait until ship:apoapsis > 25000. + lock throttle to 0. + print "ap: "+round(ship:apoapsis,1)+" eta "+round(eta:apoapsis,1). + set warpmode to "rails". + until eta:apoapsis < 30 { set warp to 3. } + rwait(eta:apoapsis-10). + + print "turning.". + wait_turn(heading(90,0)). + print "circualrizing.". + lock throttle to 1.0. + wait until ship:periapsis > 20000. + lock throttle to 0.0. +} + +if ship:apoapsis > 20000 and body = Mun { + + print "waiting for ejection point.". + set dst_ang to -22. + set ang to 99. + + until ang < 1 { + set ang to MAX(MOD(-longitude+dst_ang+720,360),0.0001). + // Estimate how long we need to wait + set dt to MAX(ABS(ship:orbit:period/360*ang),1). + print "eta: "+floor(dt)+" s ( "+floor(ang)+" )". + if dt > 60 { + set warpmode to "rails". wait 0.1. + warpto(time:seconds+dt-30). + wait dt-30+1. + pstop(). + } else if dt > 10 { + lock steering to ship:prograde. + set warpmode to "physics". + wait 0.1. + warpto(time:seconds+dt/2). + wait dt/2+1. + pstop(). + } else { + lock steering to ship:prograde. + wait dt/3. + } + } + + print "ejection burn.". + wait_turn(prograde). + set throttle to 1.0. + wait until ship:apoapsis < 0. + wait 0.1. + set throttle to 0. + until body = Kerbin { + set warpmode to "rails". + set warp to 5. + } +} + +if ship:periapsis < 48000 { + print "already in capture orbit.". +} else { + + // Multiple times... rounding errors + print "warp for AP. 95%". + rwait(eta:apoapsis*0.95). + print "warp for AP. 100%". + rwait(eta:apoapsis). + + until ship:periapsis < 48000 AND ship:periapsis > 43000 { + // Lower PE + print "turning retrograde.". + wait_turn(retrograde). + print "PE: "+ship:periapsis. + until ship:periapsis < 48000 { + if ship:periapsis > 200000 { lock throttle to 1. } + else if ship:periapsis > 60000 { lock throttle to 0.1. } + else { lock throttle to 0.01. } + Wait 0.1. + } + lock throttle to 0. + + // Check in case we need to raise PE + if ship:periapsis < 43000 { + wait_turn(prograde). + lock throttle to 0.01. + wait until ship:periapsis > 43000. + lock throttle to 0. + } + } + + unlock throttle. + +} + +print "capture orbit. PE :"+round(ship:periapsis,0). + +// We are captured, slowly lower the AP+PE + +unlock steering. +sas on. +wait 1. +//set sasmode to "retrograde". + +set warp to 0. +wait 1. +set warpmode to "rails". +set warp to 5. + +wait until eta:periapsis < 60 or ship:altitude < 45000. + +lock throttle to 1.0. + +wait until maxthrust = 0. + +lock throttle to 0. +wait 1. +stage. + +print "waiting for 10,000 MSL". +wait until ship:altitude < 10000. +print "waiting for parachutes to be safe.". +wait until chutessafe = True. +print "chutes safe at alt "+alt:radar. +wait 1. +stage. +chute on. + +print "parachutes deployed.". +print "done.". + \ No newline at end of file diff --git a/rv.ks b/rv.ks new file mode 100644 index 0000000..4dfb0cc --- /dev/null +++ b/rv.ks @@ -0,0 +1,148 @@ +// Rendevous with another craft + +run once libguido. +myinit(). + +declare parameter dst is vessel("KSS"). + +set alt_ship to (ship:apoapsis+ship:periapsis)/2. +set alt_dst to (dst:apoapsis+dst:periapsis)/2. + +if dst:distance > 10000 { + + // Calculate time for Hohmann Transfer + set t_trans to t_hohmann(alt_ship, alt_dst). + + // Calculate how much target will have moved + set a_trans to 180-360/dst:orbit:period*t_trans. + + print "calculating hohmann transfer.". + print "duration: "+round(t_trans,0)+" sec". + print "phase an: "+round(a_trans,1)+" deg". + + set a to 999. + + lock steering to prograde. + + until a-a_trans < 0.1 { + set a to mod(dst:longitude-ship:longitude+720,360). + set da to mod(a-a_trans+720,360). + set dt to da/( 360*(dst:orbit:period-ship:orbit:period) / (ship:orbit:period^2) )*0.9. + print1s("delta:"+round(da,4)+" dt: "+round(dt,1)+" s"). + + // Adjust speed + set_warp_for_t(dt-10). + wait max(dt-55,1). + } + + wait_turn(ship:prograde). + lock steering to ship:prograde. + wait 1. + print "starting burn.". + until ship:apoapsis > alt_dst { + if alt_dst-ship:apoapsis < 1000 { + lock throttle to 0.01. + } else { + lock throttle to 0.1. + } + wait 0.1. + } + + lock throttle to 0. + wait 0.1. + rwait(eta:apoapsis). +} + +set done to false. + +until done { + + // Adjust speed if needed. + set v_rel to dst:velocity:orbit - ship:velocity:orbit. + print "v_rel: "+v_rel:mag+" dist: "+dst:position:mag. + + if v_rel:mag > 1 { + + // Zero out relative speed. + print "reducing relative speed.". + set v_rel to dst:velocity:orbit - ship:velocity:orbit. + wait_turn(v_rel:direction). + + until v_rel:mag < 1 { + set v_rel to dst:velocity:orbit - ship:velocity:orbit. + lock steering to v_rel:direction. + set_throttle(v_rel:mag,2). + wait 0.1. + } + lock throttle to 0. + wait 0.1. + } + + // Move closer if needed + + print "v_rel: "+round(v_rel:mag,1)+" dist: "+round(dst:position:mag). + + if dst:position:mag > 100 { + print "accelerating toward target.". + + wait_turn(dst:position:direction). + wait 1. + set v_rel to dst:velocity:orbit - ship:velocity:orbit. + set speed to max(2,dst:position:mag/120). + print "approaching v: "+speed. + + until v_rel:mag > speed { + set_throttle(10,2). + lock steering to dst:position:direction. + set v_rel to dst:velocity:orbit - ship:velocity:orbit. + wait 0.1. + } + + lock throttle to 0. + + print "in transit, turning to break.". + + set old_dist to 999999. + + until dst:position:mag < 100 OR old_dist < dst:position:mag { + set v_rel to dst:velocity:orbit - ship:velocity:orbit. + lock steering to v_rel:direction. + set dv to v_rel:mag. + set dt to dv/(ship:maxthrust/ship:mass). + set t_left to dst:position:mag/dv. + if t_left < 10 { + set_throttle(dv,10). + } + + set old_dist to dst:position:mag. + wait 0.2. + } + } + + set v_rel to dst:velocity:orbit - ship:velocity:orbit. + if dst:position:mag < 100 AND v_rel:mag < 1 { + set done to True. + } +} + +// Try to get speed down to as low as possible. + +// Zero out relative speed. +print "arrived. attempting to zero speed.". +set v_rel to dst:velocity:orbit - ship:velocity:orbit. +wait_turn(v_rel:direction). +wait 2. + +set v_old to 99999. +until v_rel:mag > v_old { + set v_old to v_rel:mag. + set v_rel to dst:velocity:orbit - ship:velocity:orbit. + lock steering to v_rel:direction. + lock throttle to 0.01. + wait 0.1. + set v_rel to dst:velocity:orbit - ship:velocity:orbit. +} +lock throttle to 0. + +myexit(). +print "done.". diff --git a/sp.ks b/sp.ks new file mode 100644 index 0000000..1cadcf2 --- /dev/null +++ b/sp.ks @@ -0,0 +1,110 @@ +// Spaceplane launch + +run once libguido. +myinit(). + + + +// Speeds +set v_to to 100. +set v_acc to 1000. + +// Pitch +set p_to to 15. +set p_climb to 15. +set p_final to 15. + +// Transition altitudes +set a_acc to 12000. +set a_target to 70000. +set n to ship:name. + +if n = "Other" { + // Do nothing + print "Other???". +} else { + print "Standard SSTO Space Plane". +} + +mytimer_s(). + +if ship:altitude < 0.75*a_acc { + // Assume we are on the ground. + + print " take off at "+v_to+" m/s pitch "+p_to+" deg.". + print " accelerate at "+a_acc+" m to "+v_acc+" m/s". + print " target altitude "+a_target+" m". + + lock throttle to 1.0. + wait 1. + + print mytimer()+"starting engine.". + stage. + + lock steering to heading(90.42, 0). + + wait until ship:velocity:surface:mag > v_to. + + print mytimer()+"takeoff at v: "+round(ship:velocity:surface:mag,1). + smooth_pitch(90, 0, p_to, 1). + + wait until ship:altitude > 100. + print mytimer()+"takeoff complete alt: 100m v: "+round(ship:velocity:surface:mag,1). + gear off. + smooth_pitch(90, p_to, p_climb, 10). + + wait until ship:altitude > a_acc. +} + +if ship:velocity:surface:mag < v_acc { + print mytimer()+"reached a_acc: "+a_acc+" v: "+round(ship:velocity:surface:mag,1). + print mytimer()+"accelerating to "+round(v_acc,1). + lock steering to heading(90, max(0,min(5,(a_acc-ship:altitude)/100))). + + wait until ship:velocity:surface:mag > v_acc. + + print mytimer()+"reached v_acc: "+round(ship:velocity:surface:mag,1). +} + +if ship:apoapsis < a_target { + print mytimer()+"climbing for final burn.". + lock steering to heading(90,p_final). + set_engine("nuclear",1). + + set v_old to ship:velocity:surface:mag. + until ship:velocity:surface:mag < v_old { + set v_old to ship:velocity:surface:mag. + wait 1. + } + + print mytimer()+"losing speed. switching Rapiers at alt: "+ship:altitude. + rapier_space(). + toggle INTAKES. + + wait until ship:apoapsis > a_target. +} + +print mytimer()+"reached ap: "+a_target+" alt: "+ship:altitude+" v: "+round(ship:velocity:surface:mag,1). +smooth_pitch(90,p_final,0,10). + +// Calculate length of burn. + +set max_acc to ship:maxthrust/ship:mass. +set t_ap to eta:apoapsis. +set ap to ship:apoapsis. +set pe to ship:periapsis. +set v_ap to vv_alt(ap). +set v_new to vv_circular(ap). +set target_v_ap to vv_axis(ap,(ap+2*body:radius+ap)/2). +set dt_ap to abs(v_ap-target_v_ap)/max_acc. + +lock throttle to 0. +print "waiting "+(t_ap-dt_ap/2)+" s". +pwait(t_ap-dt_ap/2). + +lock throttle to 1. +wait until ship:periapsis > a_target. +lock throttle to 0. + +print "Orbit reached: A/P/T "+floor(ship:apoapsis)+" / "+floor(ship:periapsis)+" / "+a_target. +myexit(). \ No newline at end of file diff --git a/tr_min.ks b/tr_min.ks new file mode 100644 index 0000000..8011e74 --- /dev/null +++ b/tr_min.ks @@ -0,0 +1,133 @@ +// Transfer from 80,000m Kerbin Orbit with 6 deg inclination to Minmus Orbit +print "Minmus Transfer v1.0". + +run once libguido. +myinit(). + +// Target body and ejection angle +set dst to Minmus. +set dst_ang to 124. +set dst_ap to dst:orbit:apoapsis*0.99. + +set ang to 999. + +// Enable different parts of the program for debugging + +if ship:obt:body = dst { + // At Minmus already... + print "In SOI of Minmus, skipping transfer.". + set phase1 to False. + set phase2 to False. +} else { + set phase1 to True. + set phase2 to True. +} +set phase3 to True. + +function turn { + parameter v. + lock steering to v. + set warpmode to "physics". + set warp to 3. + wait until vang(ship:facing:vector, v:vector) < 5. + set warp to 0. + set warpmode to "rails". +} + +if phase1 { + + print "waiting for transfer window.". + + // Wait for transfer window + + until ang < 1 { + set ang_min to dst:geoposition:LNG. + set ang_ship to ship:geoposition:LNG. + set ang to MAX(MOD(ang_min-ang_ship+720-dst_ang,360),0.0001). + + // Estimate how long we need to wait + set dt to MAX(ABS(ship:orbit:period/360*ang),1). + print "eta: "+floor(dt)+" s ( "+floor(ang)+" )". + if dt > 60 { + set warpmode to "rails". + warpto(time:seconds+dt-60). + wait dt-60. + } else if dt > 10 { + lock steering to ship:prograde. + set warpmode to "physics". + warpto(time:seconds+dt/2). + wait dt/2. + } else { + lock steering to ship:prograde. + wait dt/3. + } + } + + print "starting high velocity burn". + lock steering to ship:prograde. + + until ship:apoapsis > dst_ap*0.985 { + if ship:apoapsis/dst_ap < 0.8 { set thr to 1.0. } + else if ship:apoapsis/dst_ap < 0.95 { set thr to 0.1.} + else {set thr to 0.01.} + lock throttle to thr. + if maxthrust = 0 { + print "Fuel exhausted. Staging.". + stage. + } + wait 0.1. + } + lock throttle to 0. + print "burn complete.". +} + +if phase2 { + // Get us close + print "waiting for SOI. warping.". + wait 3. + set warpmode to "rails". + set warp to 6. + wait until ship:obt:body = dst. + set warp to 0. +} + +if phase3 { + print "entered SOI. Alt: "+floor(ship:altitude)+" PE: "+floor(ship:periapsis). + + // Slow down to capture + turn(ship:retrograde). + print "breaking for capture.". + until (ship:apoapsis > 0 AND ship:periapsis < 100000) OR (ship:periapsis < 50000) { + lock throttle to 1. + if maxthrust = 0 { + print "Fuel exhausted. Staging.". + stage. + } + wait 0.1. + } + lock throttle to 0. + wait 1. + + print "time to PE: "+floor(eta:periapsis). + set warpmode to "rails". + warpto(time:seconds+eta:periapsis-30). + wait eta:periapsis-30. + print "turning for burn.". + turn(ship:retrograde). + print "lowering AP.". + until ship:apoapsis > 0 AND ship:apoapsis < 100000 { + if eta:periapsis > 10 AND eta:periapsis < 200 { + lock throttle to 005. + } else if eta:periapsis > 5 AND eta:periapsis < 200 { + lock throttle to 0.1. + } else { + lock throttle to 1.0. + } + if ship:apoapsis <0 { + lock throttle to 1.0. + } + wait 0.1. + } + print "AP: "+ship.apoapsis. +} +myexit(). diff --git a/tr_mun.ks b/tr_mun.ks new file mode 100644 index 0000000..7a055d5 --- /dev/null +++ b/tr_mun.ks @@ -0,0 +1,131 @@ +// Transfer from 80,000m Kerbin Orbit to Mun Orbit +print "Mun Transfer v0.1". + +// Target body and ejection angle +set dst to Mun. +set dst_ang to 125. +set dst_ap to dst:orbit:apoapsis*0.9. + +set ang to 999. + +// Enable different parts of the program for debugging + +if ship:obt:body = dst { + // At the Moon already... + print "In SOI of Mun, skipping transfer.". + set phase1 to False. + set phase2 to False. +} else { + set phase1 to True. + set phase2 to True. +} +set phase3 to True. + +function turn { + parameter v. + lock steering to v. + set warpmode to "physics". + set warp to 3. + wait until vang(ship:facing:vector, v:vector) < 5. + set warp to 0. + set warpmode to "rails". +} + +if phase1 { + + print "waiting for transfer window.". + + // Wait for transfer window + + until ang < 1 { + set ang_mun to dst:geoposition:LNG. + set ang_ship to ship:geoposition:LNG. + set ang to MAX(MOD(ang_mun-ang_ship+720-dst_ang,360),0.0001). + + // Estimate how long we need to wait + set dt to MAX(ABS(ship:orbit:period/360*ang),1). + print "eta: "+floor(dt)+" s ( "+floor(ang)+" )". + if dt > 60 { + set warpmode to "rails". + warpto(time:seconds+dt-60). + wait dt-60. + } else if dt > 10 { + lock steering to ship:prograde. + set warpmode to "physics". + warpto(time:seconds+dt/2). + wait dt/2. + } else { + lock steering to ship:prograde. + wait dt/3. + } + } + + print "starting high velocity burn". + lock steering to ship:prograde. + + until ship:apoapsis > dst_ap { + + if ship:apoapsis/dst_ap < 0.9 { set thr to 1.0. } + else if ship:apoapsis/dst_ap < 0.98 { set thr to 0.1. } + else {set thr to 0.01.} + + lock throttle to thr. + + if maxthrust = 0 { + print "Fuel exhausted. Staging.". + stage. + } + + wait 0.1. + } + + lock throttle to 0. + + print "burn complete.". +} + +if phase2 { + // Get us close + set warpmode to "rails". + set warp to 5. + wait until ship:obt:body = dst. + set warp to 0. +} + +if phase3 { + print "entered SOI. Alt: "+floor(ship:altitude)+" PE: "+floor(ship:periapsis). + + // Slow down to capture + turn(ship:retrograde). + print "breaking for capture.". + until ship:apoapsis > 0 AND ship:periapsis < 25000 { + lock throttle to 0.1. + if maxthrust = 0 { + print "Fuel exhausted. Staging.". + stage. + } + wait 0.1. + } + lock throttle to 0. + wait 1. + + print "time to PE: "+floor(eta:periapsis). + set warpmode to "rails". + warpto(time:seconds+eta:periapsis-30). + wait eta:periapsis-30. + print "turning for burn.". + turn(ship:retrograde). + print "lowering AP.". + until ship:apoapsis < 100000 { + if eta:periapsis > 10 AND eta:periapsis < 200 { + lock throttle to 0. + } else if eta:periapsis > 5 AND eta:periapsis < 200 { + lock throttle to 0.1. + } else { + lock throttle to 1.0. + } + wait 0.1. + } + print "AP: "+ship.apoapsis. +} + diff --git a/tr_pl-v1.ks b/tr_pl-v1.ks new file mode 100644 index 0000000..955ce03 --- /dev/null +++ b/tr_pl-v1.ks @@ -0,0 +1,346 @@ +// Transfer from 80,000m Kerbin Orbit to Orbit of another planet +print "Planetray Transfer v1.0". + + +run once libguido. +myinit(). + +set phase_angle to 0. + +declare parameter dst_planet is Duna. + +// Departure orbit at 1000 km MSL. + +set enc_step to 0.0001. + +if dst_planet = Duna { + set phase_angle to 44.36. + set ejection_angle to -138.75. + set ejection_v to 2267.83. + set target_pe to 200000. +} else if dst_planet = Kerbin { + if ship:orbit:body = Duna { + set phase_angle to -75.19+360. + set ejection_angle to 180-110.7. + set ejection_v to 1186.75. + set target_pe to 60000. + } else { + print "Unknown departure planet: "+dst_planet. + } +} else { + print "Unknown planet: "+dst_planet. +} + + +function get_pe { + parameter p_node. + parameter p_pro. + parameter p_nor. + parameter p_rad. + parameter p_eta. + + set p_node:prograde to p_pro. + set p_node:radialout to p_rad. + set p_node:normal to p_nor. + set p_node:eta to p_eta-time:seconds. + + if NOT mynode:orbit:nextpatch:hasnextpatch { + return 99999999999. + } else { + return mynode:orbit:nextpatch:nextpatch:periapsis. + } + } + + function get_pe2 { + parameter p_node. + parameter p_pro. + parameter p_nor. + parameter p_rad. + parameter p_eta. + + set p_node:prograde to p_pro. + set p_node:radialout to p_rad. + set p_node:normal to p_nor. + set p_node:eta to p_eta-time:seconds. + + if NOT mynode:orbit:hasnextpatch { + return 99999999999. + } else { + return mynode:orbit:nextpatch:periapsis. + } + } + +function transfer { + parameter dst. + set src to ship:orbit:body. + + print "transfer "+src:name+" -> "+dst:name. + + + if ship:orbit:body = Sun { + print "already interplanetary...". + } else { + print "waiting for transfer window.". + print "target phase angle: "+phase_angle. + set da to 999. + set warpmode to "rails". + + until da > phase_angle-0.5 AND da < phase_angle+0.5 { + set a_src to src:obt:lan + src:obt:argumentofperiapsis + src:obt:trueanomaly. + set a_dst to dst:obt:lan + dst:obt:argumentofperiapsis + dst:obt:trueanomaly. + set da to mod(a_dst-a_src+720,360). + set warp to 7. + //print da. + wait 0.1. + } + set warp to 0. + + print "final phase angle: "+round(da,2). + + // Cross-check + set v1 to Sun:position-src:position. + set v2 to Sun:position-dst:position. + print "cross check angle: "+round(vang(v1,v2),2). + + // Check if we have a maneuver node. If not, create one. + + if hasnode AND ship:orbit:body <> Sun { + set mynode to nextnode. + } else { + // Wait until we are between Kerbin and Sun + set dl to 999. + until dl < 0.1 { + set v_sun to src:position-sun:position. + set v_ship to src:position-ship:position. + set dl to vang(v_sun, v_ship). + set_warp_for_t(ship:orbit:period*dl/360). + wait 0.1. + //print dl. + } + + print "between kerbin and sun. dl: "+round(dl,3). + set dt to ship:orbit:period*MOD(270+ejection_angle+720,360)/360. + + // Add the Node + set n_pro to ejection_v-ship:velocity:orbit:mag. + set n_eta to time:seconds+dt. + set n_t0 to time:seconds. + set mynode to NODE(n_eta,0,0,n_pro). + ADD mynode. + print "maneuver node dv: "+n_pro. + + // Try to get encounter + + set dn_pro to 0. + + // Try increasing dv to get encounter + set orb1 to mynode:orbit:nextpatch. + if NOT orb1:hasnextpatch { + until orb1:hasnextpatch OR dn_pro > n_pro*0.1 { + set dn_pro to dn_pro+n_pro*enc_step. + set mynode:prograde to n_pro+dn_pro. + set orb1 to mynode:orbit:nextpatch. + wait 0.1. + } + } + + // If it didn't work, try decreasing + if NOT orb1:hasnextpatch { + set dn_pro to 0. + until orb1:hasnextpatch OR dn_pro < -n_pro*0.1 { + set dn_pro to dn_pro-n_pro*0.0001. + set mynode:prograde to n_pro+dn_pro. + set orb1 to mynode:orbit:nextpatch. + wait 0.1. + } + } + + if NOT orb1:hasnextpatch { + print "Can't find encounter. Aborting.". + wait 1. + KUniverse:PAUSE(). + return. + } + + // We have an encounter. Hillclimb. + + set old_pe to 99999999999. + set n_pro to n_pro+dn_pro. + set n_nor to 0. + set n_rad to 0. + set pe to mynode:orbit:nextpatch:nextpatch:periapsis. + print "pre-opt pe : "+round(pe/1000)+" km". + print "optimizing...". + + + until old_pe <= pe OR pe < target_pe { + // remember old PE + + set old_pe to mynode:orbit:nextpatch:nextpatch:periapsis. + set old_pe2 to old_pe. + if get_pe(mynode, n_pro, n_nor+0.1, n_rad, n_eta ) < old_pe2 { + set n_nor to n_nor+0.1. + set old_pe2 to mynode:orbit:nextpatch:nextpatch:periapsis. + } else if get_pe(mynode, n_pro, n_nor-0.1, n_rad, n_eta ) < old_pe2 { + set n_nor to n_nor-0.1. + set old_pe2 to mynode:orbit:nextpatch:nextpatch:periapsis. + } + if get_pe(mynode, n_pro+0.01, n_nor, n_rad, n_eta) < old_pe2 { + set n_pro to n_pro+0.01. + set old_pe2 to mynode:orbit:nextpatch:nextpatch:periapsis. + } else if get_pe(mynode, n_pro-0.01, n_nor, n_rad, n_eta) < old_pe2 { + set n_pro to n_pro-0.01. + set old_pe2 to mynode:orbit:nextpatch:nextpatch:periapsis. + } + if get_pe(mynode, n_pro, n_nor, n_rad+0.1, n_eta) < old_pe2 { + set n_rad to n_rad+0.1. + set old_pe2 to mynode:orbit:nextpatch:nextpatch:periapsis. + } else if get_pe(mynode, n_pro, n_nor, n_rad-0.1, n_eta) < old_pe2 { + set n_rad to n_rad-0.1. + set old_pe2 to mynode:orbit:nextpatch:nextpatch:periapsis. + } + set pe to get_pe(mynode, n_pro, n_nor, n_rad, n_eta). + // print1s("pe: "+round(pe)+" ETA/pro/nor/rad : "+round(n_eta-n_t0)+" / "+round(n_pro,2)+" / "+round(n_nor,2)+" / "+round(n_rad,2)). + wait 0.1. + } + + print "post-opt pe: "+round(pe/1000)+" km ETA/pro/nor/rad : "+round(n_eta-n_t0)+" / "+round(n_pro,2)+" / "+round(n_nor,2)+" / "+round(n_rad,2). + print "executing maneuver.". + + exec_n(mynode). + + } + + // Wait until one day after orbit around the Sun. + wait_until_in_orbit_of(Sun). + rwait(24*3600). + } + + // Make sure we have an encounter + if NOT ship:orbit:hasnextpatch { + print "No encounter. Aborting.". + KUniverse:PAUSE(). + return. + } + + + // Now that we are in Sun Orbit, re-tune for precision. + // Add a node in 5 minutes and hillclimb. + set dt to 300. + set n_eta to time:seconds+dt. + set mynode to NODE(n_eta,0,0,0). + ADD mynode. + + // We have an encounter. Hillclimb. + print "orbiting Sun. optimizing trajectory.". + set old_pe to 99999999999. + set n_pro to 0. + set n_nor to 0. + set n_rad to 0. + set pe to mynode:orbit:nextpatch:periapsis. + print "pre-opt pe : "+round(pe/1000)+" km". + + until old_pe <= pe OR pe < target_pe { + // remember old PE + + set old_pe to mynode:orbit:nextpatch:periapsis. + if get_pe(mynode, n_pro, n_nor+0.1, n_rad, n_eta ) < old_pe { + set n_nor to n_nor+0.1. + } else if get_pe2(mynode, n_pro, n_nor-0.1, n_rad, n_eta ) < old_pe { + set n_nor to n_nor-0.1. + } else if get_pe2(mynode, n_pro+0.01, n_nor, n_rad, n_eta) < old_pe { + set n_pro to n_pro+0.01. + } else if get_pe2(mynode, n_pro-0.01, n_nor, n_rad, n_eta) < old_pe { + set n_pro to n_pro-0.01. + } else if get_pe2(mynode, n_pro, n_nor, n_rad+0.1, n_eta) < old_pe { + set n_rad to n_rad+0.1. + } else if get_pe2(mynode, n_pro, n_nor, n_rad-0.1, n_eta) < old_pe { + set n_rad to n_rad-0.1. + } + set pe to get_pe2(mynode, n_pro, n_nor, n_rad, n_eta). + print1s("pe: "+round(pe)+" pro/nor/rad : "+round(n_pro,2)+" / "+round(n_nor,2)+" / "+round(n_rad,2)). + wait 0.1. + } + + print "post-opt pe: "+round(pe/1000)+" km pro/nor/rad : "+round(n_pro,2)+" / "+round(n_nor,2)+" / "+round(n_rad,2). + + if mynode:deltav:mag < 0.001 { + print "no change needed.". + } else { + print "executing maneuver.". + wait 3. + exec_n(mynode). + } + + wait_until_in_orbit_of(dst). + + print "arrived in orbit of "+dst:name. +} + +function capture { + print "in SOI of "+body:name. + print "alt: "+floor(ship:altitude)+" pe: "+floor(ship:periapsis). + + if ship:periapsis < 0 { + print "Preiapses < 0. Don't know how to correct. Aborting.". + KUniverse:PAUSE(). + return. + } + + // Slow down to capture + wait_turn(ship:retrograde). + print "breaking for capture.". + until (ship:apoapsis > 0 AND ship:periapsis < 200000) OR (ship:periapsis < target_pe) { + lock throttle to 1. + + if maxthrust = 0 { + print "Fuel exhausted. Staging.". + stage. + } + wait 0.1. + } + + lock throttle to 0. + wait 1. + run xincl. + + // Wait for PE and break to get us into orbit. + + print "time to PE: "+floor(eta:periapsis). + set warpmode to "rails". + warpto(time:seconds+eta:periapsis-30). + wait eta:periapsis-30. + print "turning for burn.". + wait_turn(ship:retrograde). + print "lowering AP.". + until (ship:apoapsis > 0 AND ship:apoapsis < target_pe*2) OR ship:periapsis < target_pe*0.75 { + if eta:periapsis > 10 AND eta:periapsis < 200 { + lock throttle to 005. + } else if eta:periapsis > 5 AND eta:periapsis < 200 { + lock throttle to 0.1. + } else { + lock throttle to 1.0. + } + + if ship:apoapsis <0 { + lock throttle to 1.0. + } + wait 0.1. + } + print "AP: "+ship.apoapsis. +} + +// Are we in orbit? +if ship:obt:body <> dst_planet { + transfer(dst_planet). + capture(). +} else { + if ship:periapsis <0 OR ship:apoapsis <0 or ship:apoapsis > 200000 { + capture(). + } +} + +myexit(). + + + diff --git a/tr_pl-v2.ks b/tr_pl-v2.ks new file mode 100644 index 0000000..4b09964 --- /dev/null +++ b/tr_pl-v2.ks @@ -0,0 +1,508 @@ +// Transfer from 80,000m Kerbin Orbit to Orbit of another planet +print "Planetray Transfer v1.0". + + +run once libguido. + +declare parameter dst_planet is Duna. +declare parameter lib_mode is False. + +// Departure orbit at 1000 km MSL. + +set enc_step to 0.0001. + +if dst_planet = Duna { + set phase_angle to 44.36. + set ejection_angle to -138.75. + set ejection_v to 2267.83. + set target_pe to 200000. +} else if dst_planet = Eve { + set phase_angle to -54.13+360. + set ejection_angle to 180-143.44. + set ejection_v to 2226.01. + set target_pe to 200000. +} else if dst_planet = Kerbin { + if ship:orbit:body = Duna { + // Duna return orbit 500,000m + set phase_angle to -75.19+360. + set ejection_angle to 180-110.7. + set ejection_v to 1186.75. + set target_pe to 40000. + } else if ship:orbit:body = Eve { + // Eve return orbit 500,000m + set phase_angle to 36.07. + set ejection_angle to -159.13. + set ejection_v to 3754.75. + set target_pe to 40000. + } else { + print "Unknown departure planet: "+dst_planet. + } +} else { + print "Unknown planet: "+dst_planet. +} + + +function get_pe { + parameter p_node. + parameter p_pro. + parameter p_nor. + parameter p_rad. + parameter p_eta. + + set p_node:prograde to p_pro. + set p_node:radialout to p_rad. + set p_node:normal to p_nor. + set p_node:eta to p_eta-time:seconds. + + if NOT mynode:orbit:nextpatch:hasnextpatch { + return 99999999999. + } else { + return mynode:orbit:nextpatch:nextpatch:periapsis. + } + } + +function get_pe2 { + parameter p_node. + parameter p_pro. + parameter p_nor. + parameter p_rad. + parameter p_eta. + + set p_node:prograde to p_pro. + set p_node:radialout to p_rad. + set p_node:normal to p_nor. + set p_node:eta to p_eta-time:seconds. + + if NOT mynode:orbit:hasnextpatch { + return 99999999999. + } else { + return mynode:orbit:nextpatch:periapsis. + } + } + + +function get_d2 { + parameter p_node. + parameter p_pro. + parameter p_nor. + parameter p_rad. + parameter p_eta. + parameter dst_body. + + set p_node:prograde to p_pro. + set p_node:radialout to p_rad. + set p_node:normal to p_nor. + set p_node:eta to p_eta-time:seconds. + + return find_closest(ship, dst_body). + } + +function my_transfer { + parameter dst. + set src to ship:orbit:body. + + print "transfer "+src:name+" -> "+dst:name. + + if ship:orbit:body = Sun { + print "already interplanetary...". + } else { + + print "waiting for transfer window.". + print "target phase angle: "+phase_angle. + + set a_src to src:obt:lan + src:obt:argumentofperiapsis + src:obt:trueanomaly. + set a_dst to dst:obt:lan + dst:obt:argumentofperiapsis + dst:obt:trueanomaly. + set da to mod(a_dst-a_src+720,360). + + if da > phase_angle-2 AND da < phase_angle+2 { + print "at the right phase angle already.". + } else { + set da to 999. + set warpmode to "rails". + + until da > phase_angle-0.5 AND da < phase_angle+0.5 { + set a_src to src:obt:lan + src:obt:argumentofperiapsis + src:obt:trueanomaly. + set a_dst to dst:obt:lan + dst:obt:argumentofperiapsis + dst:obt:trueanomaly. + set da to mod(a_dst-a_src+720,360). + set warp to 7. + //print da. + wait 0.1. + } + set warp to 0. + wait until KUniverse:CANQUICKSAVE. + KUniverse:QUICKSAVETO("x3-transfer-window"). + } + + // Warping fast, wait until we are done. + wait until kuniverse:timewarp:issettled. + + set a_src to src:obt:lan + src:obt:argumentofperiapsis + src:obt:trueanomaly. + set a_dst to dst:obt:lan + dst:obt:argumentofperiapsis + dst:obt:trueanomaly. + set da to mod(a_dst-a_src+720,360). + print "final phase angle: "+round(da,2). + + // Cross-check + set v1 to Sun:position-src:position. + set v2 to Sun:position-dst:position. + print "cross check angle: "+round(vang(v1,v2),2). + + // Check if we have a maneuver node. If not, create one. + + if hasnode AND ship:orbit:body <> Sun { + set mynode to nextnode. + } else { + + // Calculate position vs. body prograde + // dl is zero at prograde, positive in direction of 90 degree rotation + set v_sun to sun:position-src:position. + set v_ship to ship:position-src:position. + set dd to vcrs(v_sun, v_ship)*v(0,1,0). + set a_ship to mod(720-vang(v_sun, v_ship)*dd/abs(dd)+90,360). + set a_eject to mod(ejection_angle+720,360). + set d_a to mod(a_eject-a_ship+720,360). + + print "angles ship/eject/delta: "+round(a_ship,1)+" / "+round(a_eject,1)+" / "+round(d_a,1). + + set dt to ship:orbit:period*d_a/360. + + // Add the Node + set n_pro to ejection_v-ship:velocity:orbit:mag. + set n_eta to time:seconds+dt. + set n_t0 to time:seconds. + print "node dt: "+round(n_eta,1)+" prograde: "+round(n_pro,1). + set mynode to NODE(n_eta,0,0,n_pro). + ADD mynode. + print "maneuver node dv: "+n_pro. + + // Try #1 - Vary ETA + + set dn_eta to -200. + set dn_pro to 0. + set orb1 to mynode:orbit:nextpatch. + print "#1 trying varying ETA.". + if NOT (orb1:hasnextpatch and orb1:nextpatch:body = dst) { + until (orb1:hasnextpatch and orb1:nextpatch:body = dst) OR dn_eta > 200 { + set dn_eta to dn_eta+0.5. + set mynode:eta to n_eta-time:seconds+dn_eta. + set orb1 to mynode:orbit:nextpatch. + } + } + + if orb1:hasnextpatch AND orb1:nextpatch:body = dst{ + set n_eta to n_eta+dn_eta. + } else { + set mynode:eta to n_eta-time:seconds. + } + + // Try #2/#3 - Vary Prograde burn + + if NOT (orb1:hasnextpatch AND orb1:nextpatch:body = dst) { + // Try increasing dv to get encounter + print "#2 trying increasing dv.". + set mynode:eta to n_eta-time:seconds. + until (orb1:hasnextpatch and orb1:nextpatch:body = dst) OR dn_pro > n_pro*0.2 { + set dn_pro to dn_pro+n_pro*enc_step. + set mynode:prograde to n_pro+dn_pro. + set orb1 to mynode:orbit:nextpatch. + } + } + + // If it didn't work, try decreasing + if NOT (orb1:hasnextpatch AND orb1:nextpatch:body = dst) { + print "#3 trying increasing dv.". + set dn_pro to 0. + until (orb1:hasnextpatch and orb1:nextpatch:body = dst) OR dn_pro < -n_pro*0.2 { + set dn_pro to dn_pro-n_pro*0.0001. + set mynode:prograde to n_pro+dn_pro. + set orb1 to mynode:orbit:nextpatch. + } + } + + // We give up. Just burn as prescribed and fix it once we in the SOI of the Sun + + if NOT (orb1:hasnextpatch and orb1:nextpatch:body = dst) { + print "No encounter found. going with default parameters.". + set mynode:prograde to n_pro. + set mynode:eta to n_eta-time:seconds+dn_eta. + } else { + // We have an encounter. Hillclimb. + + set old_pe to 99999999999. + set n_pro to n_pro+dn_pro. + set n_nor to 0. + set n_rad to 0. + set pe to mynode:orbit:nextpatch:nextpatch:periapsis. + print "pre-opt pe : "+round(pe/1000)+" km". + print "optimizing...". + + + until old_pe <= pe OR pe < target_pe { + // remember old PE + + set old_pe to mynode:orbit:nextpatch:nextpatch:periapsis. + set old_pe2 to old_pe. + if get_pe(mynode, n_pro, n_nor+0.1, n_rad, n_eta ) < old_pe2 { + set n_nor to n_nor+0.1. + set old_pe2 to mynode:orbit:nextpatch:nextpatch:periapsis. + } else if get_pe(mynode, n_pro, n_nor-0.1, n_rad, n_eta ) < old_pe2 { + set n_nor to n_nor-0.1. + set old_pe2 to mynode:orbit:nextpatch:nextpatch:periapsis. + } + if get_pe(mynode, n_pro+0.01, n_nor, n_rad, n_eta) < old_pe2 { + set n_pro to n_pro+0.01. + set old_pe2 to mynode:orbit:nextpatch:nextpatch:periapsis. + } else if get_pe(mynode, n_pro-0.01, n_nor, n_rad, n_eta) < old_pe2 { + set n_pro to n_pro-0.01. + set old_pe2 to mynode:orbit:nextpatch:nextpatch:periapsis. + } + if get_pe(mynode, n_pro, n_nor, n_rad+0.1, n_eta) < old_pe2 { + set n_rad to n_rad+0.1. + set old_pe2 to mynode:orbit:nextpatch:nextpatch:periapsis. + } else if get_pe(mynode, n_pro, n_nor, n_rad-0.1, n_eta) < old_pe2 { + set n_rad to n_rad-0.1. + set old_pe2 to mynode:orbit:nextpatch:nextpatch:periapsis. + } + set pe to get_pe(mynode, n_pro, n_nor, n_rad, n_eta). + // print1s("pe: "+round(pe)+" ETA/pro/nor/rad : "+round(n_eta-n_t0)+" / "+round(n_pro,2)+" / "+round(n_nor,2)+" / "+round(n_rad,2)). + wait 0.1. + } + + print "post-opt pe: "+round(pe/1000)+" km ETA/pro/nor/rad : "+round(n_eta-n_t0)+" / "+round(n_pro,2)+" / "+round(n_nor,2)+" / "+round(n_rad,2). + } + + print "executing maneuver.". + exec_n(mynode). + } + + // Wait until one quarter turn after orbit around the Sun. + wait_until_in_orbit_of(Sun). + } + + if NOT ship:orbit:hasnextpatch OR ship:orbit:nextpatch:body <> dst { + // We are in the SOI of the Sun, but no encounter. + if ship:orbit:hasnextpatch { + print "SOI: "+ship:orbit:body:name+" and next patch body is "+ship:orbit:nextpatch:body:name+". trying again for encounter.". + } else { + print "SOI: "+ship:orbit:body:name+" and no next patch. trying again for encounter.". + } + + // How close are we? + set old_pe to find_closest(ship,eve). + print "trying to find encounter.". + print "pre-opt dist: "+km(old_pe). + + set n_pro to 0. + set n_nor to 0. + set n_rad to 0. + set pe to old_pe. + + set n_eta to time:seconds+ship:orbit:period*0.20. + set n_t0 to time:seconds. + set mynode to NODE(n_eta,N_rad,n_nor,n_pro). + ADD mynode. + + // Progressively get more fine grained + set step to 100. + + until step < 0.1 OR (mynode:orbit:hasnextpatch AND mynode:orbit:nextpatch:body = dst) { + // remember old PE + + set old_pe to pe. + set old_pe2 to pe. + if get_d2(mynode, n_pro, n_nor+step, n_rad, n_eta, dst ) < old_pe2 { + set n_nor to n_nor+step. + set old_pe2 to find_closest(ship,dst). + } else if get_d2(mynode, n_pro, n_nor-step, n_rad, n_eta, dst ) < old_pe2 { + set n_nor to n_nor-step. + set old_pe2 to find_closest(ship,dst). + } + if get_d2(mynode, n_pro+step/10, n_nor, n_rad, n_eta, dst ) < old_pe2 { + set n_pro to n_pro+step/10. + set old_pe2 to find_closest(ship,dst). + } else if get_d2(mynode, n_pro-step/10, n_nor, n_rad, n_eta, dst ) < old_pe2 { + set n_pro to n_pro-step/10. + set old_pe2 to find_closest(ship,dst). + } + if get_d2(mynode, n_pro, n_nor, n_rad+step, n_eta, dst ) < old_pe2 { + set n_rad to n_rad+step. + set old_pe2 to find_closest(ship,dst). + } else if get_d2(mynode, n_pro, n_nor, n_rad-step, n_eta, dst ) < old_pe2 { + set n_rad to n_rad-step. + set old_pe2 to find_closest(ship,dst). + } + set pe to get_d2(mynode, n_pro, n_nor, n_rad, n_eta, dst ). + print1s("pe: "+round(pe/1000)+" km pro/nor/rad : "+round(n_pro,2)+" / "+round(n_nor,2)+" / "+round(n_rad,2)+" ["+round(step,2)+"]" ). + print "p: "+mynode:orbit:hasnextpatch. + if old_pe <= pe*1.0001 { + set step to step*0.5. + } + } + + print1s("final pe: "+round(pe/1000)+" km pro/nor/rad : "+round(n_pro,2)+" / "+round(n_nor,2)+" / "+round(n_rad,2)+" ["+round(step,2)+"]" ). + + if mynode:orbit:hasnextpatch AND mynode:orbit:nextpatch:body = dst { + print "we have an encounter. executing maneuver.". + exec_n(mynode). + } + } + + // Make sure we have an encounter + if NOT ship:orbit:hasnextpatch { + print "No encounter. Aborting.". + KUniverse:PAUSE(). + return. + } + + // Now that we are in Sun Orbit, re-tune for precision. + // Add a node in 5 minutes and hillclimb. + set dt to 300. + set n_eta to time:seconds+dt. + set mynode to NODE(n_eta,0,0,0). + ADD mynode. + + // We have an encounter. Hillclimb. + print "orbiting Sun. optimizing trajectory.". + set old_pe to 99999999999. + set n_pro to 0. + set n_nor to 0. + set n_rad to 0. + set pe to mynode:orbit:nextpatch:periapsis. + print "pre-opt pe : "+round(pe/1000)+" km". + + // Progressively get more fine grained + set step to 10. + + until step < 0.1 OR pe < target_pe { + // remember old PE + + set old_pe to mynode:orbit:nextpatch:periapsis. + set old_pe2 to old_pe. + if get_pe2(mynode, n_pro, n_nor+step, n_rad, n_eta ) < old_pe2 { + set n_nor to n_nor+step. + set old_pe2 to mynode:orbit:nextpatch:periapsis. + } else if get_pe2(mynode, n_pro, n_nor-step, n_rad, n_eta ) < old_pe2 { + set n_nor to n_nor-step. + set old_pe2 to mynode:orbit:nextpatch:periapsis. + } else if get_pe2(mynode, n_pro+step/10, n_nor, n_rad, n_eta) < old_pe2 { + set n_pro to n_pro+step/10. + set old_pe2 to mynode:orbit:nextpatch:periapsis. + } else if get_pe2(mynode, n_pro-step/10, n_nor, n_rad, n_eta) < old_pe2 { + set n_pro to n_pro-step/10. + set old_pe2 to mynode:orbit:nextpatch:periapsis. + } else if get_pe2(mynode, n_pro, n_nor, n_rad+step, n_eta) < old_pe2 { + set n_rad to n_rad+step. + set old_pe2 to mynode:orbit:nextpatch:periapsis. + } else if get_pe2(mynode, n_pro, n_nor, n_rad-step, n_eta) < old_pe2 { + set n_rad to n_rad-step. + set old_pe2 to mynode:orbit:nextpatch:periapsis. + } + set pe to get_pe2(mynode, n_pro, n_nor, n_rad, n_eta). + print1s("pe: "+round(pe/1000)+" km pro/nor/rad : "+round(n_pro,2)+" / "+round(n_nor,2)+" / "+round(n_rad,2)+" ["+round(step,2)+"]" ). + if old_pe <= pe { + set step to step*0.5. + } + } + + print "post-opt pe: "+round(pe/1000)+" km pro/nor/rad : "+round(n_pro,2)+" / "+round(n_nor,2)+" / "+round(n_rad,2). + + if mynode:deltav:mag < 0.001 { + print "no change needed.". + } else { + print "executing maneuver.". + wait 3. + exec_n(mynode). + } + + wait_until_in_orbit_of(dst). + + print "arrived in orbit of "+dst:name. + wait until KUniverse:CANQUICKSAVE. + KUniverse:QUICKSAVETO("x4-dstSOI"). +} + +function capture { + print "in SOI of "+body:name. + print "alt: "+floor(ship:altitude)+" pe: "+floor(ship:periapsis). + + if ship:periapsis < 0 { + print "Preiapses < 0. Don't know how to correct. Aborting.". + KUniverse:PAUSE(). + return. + } + + if (ship:apoapsis > 0 or ship:periapsis < 200000) AND (ship:periapsis < target_pe) { + // Slow down to capture + wait_turn(ship:retrograde). + print "breaking for capture.". + until (ship:apoapsis > 0 AND ship:periapsis < 200000) OR (ship:periapsis < target_pe) { + lock throttle to 1. + + if maxthrust = 0 { + print "Fuel exhausted. Staging.". + stage. + } + wait 0.1. + } + wait until KUniverse:CANQUICKSAVE. + KUniverse:QUICKSAVETO("x5-dstorbit-1"). + } + + lock throttle to 0. + wait 1. + + //KUniverse:PAUSE(). + + if ship:orbit:inclination > 1 { + // Try to improve inclination + run xincl. + wait until KUniverse:CANQUICKSAVE. + KUniverse:QUICKSAVETO("x6-dstorbit-2"). + } + + // Wait for PE and break to get us into orbit. + + print "time to PE: "+floor(eta:periapsis). + set warpmode to "rails". + warpto(time:seconds+eta:periapsis-30). + wait eta:periapsis-30. + print "turning for burn.". + wait_turn(ship:retrograde). + print "lowering AP.". + until (ship:apoapsis > 0 AND ship:apoapsis < target_pe*2) OR ship:periapsis < target_pe*0.75 { + if eta:periapsis > 10 AND eta:periapsis < 200 { + lock throttle to 005. + } else if eta:periapsis > 5 AND eta:periapsis < 200 { + lock throttle to 0.1. + } else { + lock throttle to 1.0. + } + + if ship:apoapsis <0 { + lock throttle to 1.0. + } + wait 0.1. + } + wait until KUniverse:CANQUICKSAVE. + KUniverse:QUICKSAVETO("x7-dstorbit-3"). + print "AP: "+ship.apoapsis. +} + + +if NOT lib_mode { + myinit(). + // Are we in orbit? + if ship:obt:body <> dst_planet { + my_transfer(dst_planet). + if ship:obt:body = dst_planet { + capture(). + } + } else { + if ship:periapsis <0 OR ship:apoapsis <0 or ship:apoapsis > 200000 { + capture(). + } + } + + myexit(). +} + + diff --git a/tr_pl.ks b/tr_pl.ks new file mode 100644 index 0000000..7e4756f --- /dev/null +++ b/tr_pl.ks @@ -0,0 +1,251 @@ +// Transfer from 80,000m Kerbin Orbit to Orbit of another planet +print "Planetray Transfer v1.0". + +run once libguido. +run once libtransfer. +run once libcapture. + +parameter dst_planet. +parameter dst_alt is -1. +parameter fix_incl is True. + +set enc_step to 0.0001. + +function get_d2 { + parameter p_node. + parameter p_pro. + parameter p_nor. + parameter p_rad. + parameter p_eta. + parameter dst_body. + + set p_node:prograde to p_pro. + set p_node:radialout to p_rad. + set p_node:normal to p_nor. + set p_node:eta to p_eta-time:seconds. + + return find_closest(ship, dst_body). + } + +function my_transfer { + parameter dst. + set src to ship:orbit:body. + + set dst_min_pe to 100000. + set dst_max_pe to 200000. + + print "planetary transfer "+src:name+" -> "+dst:name. + + set tr_data to get_planet_data(dst). + if tr_data[2] = 0 { panic("Unknown Transfer"). return False. } + set ejection_angle to -tr_data[4]. + set ejection_v to tr_data[5]. + + if ship:orbit:body = Sun { + print "already interplanetary.". + } else { + // Wait for a transfer window between planets + if NOT wait_transfer_window(dst) { + print "wait_transfer_window() failes. Aborting.". + return False. + } + myquicksave("x3-transfer-window"). + + // Check if we have a maneuver node. If not, create one. + + if hasnode AND src <> Sun { + print "found existing maneuver node.". + set mynode to nextnode. + optimize_pe(dst_min_pe,dst_max_pe,dst). + } else { + // Calculate position vs. body prograde + // dl is zero at prograde, positive in direction of 90 degree rotation + set v_sun to sun:position-src:position. + set v_ship to ship:position-src:position. + set dd to vcrs(v_sun, v_ship)*v(0,1,0). + set a_ship to mod(720-vang(v_sun, v_ship)*dd/abs(dd)+90,360). + set a_eject to mod(ejection_angle+720,360). + set d_a to mod(a_eject-a_ship+720,360). + + print "angles ship/eject/delta: "+round(a_ship,1)+" / "+round(a_eject,1)+" / "+round(d_a,1). + + set dt to ship:orbit:period*d_a/360. + + // Add the Node + set n_pro to ejection_v-ship:velocity:orbit:mag. + set n_eta to time:seconds+dt. + set n_t0 to time:seconds. + print "node dt: "+round(n_eta,1)+" prograde: "+round(n_pro,1). + set mynode to NODE(n_eta,0,0,n_pro). + ADD mynode. + print "maneuver node dv: "+n_pro. + + // Try #1 - Vary ETA + + set dn_eta to -200. + set dn_pro to 0. + set orb1 to mynode:orbit:nextpatch. + print "#1 trying varying ETA.". + if NOT (orb1:hasnextpatch and orb1:nextpatch:body = dst) { + until (orb1:hasnextpatch and orb1:nextpatch:body = dst) OR dn_eta > 200 { + set dn_eta to dn_eta+0.5. + set mynode:eta to n_eta-time:seconds+dn_eta. + set orb1 to mynode:orbit:nextpatch. + } + } + + if orb1:hasnextpatch AND orb1:nextpatch:body = dst{ + set n_eta to n_eta+dn_eta. + } else { + set mynode:eta to n_eta-time:seconds. + } + + // Try #2/#3 - Vary Prograde burn + + if NOT (orb1:hasnextpatch AND orb1:nextpatch:body = dst) { + // Try increasing dv to get encounter + print "#2 trying increasing dv.". + set mynode:eta to n_eta-time:seconds. + until (orb1:hasnextpatch and orb1:nextpatch:body = dst) OR dn_pro > n_pro*0.2 { + set dn_pro to dn_pro+n_pro*enc_step. + set mynode:prograde to n_pro+dn_pro. + set orb1 to mynode:orbit:nextpatch. + } + } + + // If it didn't work, try decreasing + if NOT (orb1:hasnextpatch AND orb1:nextpatch:body = dst) { + print "#3 trying increasing dv.". + set dn_pro to 0. + until (orb1:hasnextpatch and orb1:nextpatch:body = dst) OR dn_pro < -n_pro*0.2 { + set dn_pro to dn_pro-n_pro*0.0001. + set mynode:prograde to n_pro+dn_pro. + set orb1 to mynode:orbit:nextpatch. + } + } + + // We give up. Just burn as prescribed and fix it once we in the SOI of the Sun + + if NOT (orb1:hasnextpatch and orb1:nextpatch:body = dst) { + print "No encounter found. going with default parameters.". + set mynode:prograde to n_pro. + set mynode:eta to n_eta-time:seconds+dn_eta. + } else { + // Run the optimizer + optimize_pe(dst_min_pe,dst_max_pe,dst). + } + + + } + + print "executing maneuver.". + exec_n(mynode). + wait_until_in_orbit_of(Sun). + } + + print "In the orbit of "+ship:orbit:body:name. + if ship:orbit:body <> Sun { + panic("I should be in orbit of Sun!?!"). + } + + if ship:orbit:hasnextpatch AND ship:orbit:nextpatch:body <> dst { + print "encounter ok.". + } else if HASNODE { + print "No encounter. Node found. Delete to re-try for encounter.". + } else { + // We are in the SOI of the Sun, but no encounter. + if ship:orbit:hasnextpatch { + print "SOI: "+ship:orbit:body:name+" and next patch body is "+ship:orbit:nextpatch:body:name+". trying again for encounter.". + } else { + print "SOI: "+ship:orbit:body:name+" and no next patch. trying again for encounter.". + } + + // How close are we? + set old_pe to find_closest(ship,eve). + print "trying to find encounter.". + print "pre-opt dist: "+km(old_pe). + set original_pe to old_pe. + clr_status(). + + set n_pro to 0. + set n_nor to 0. + set n_rad to 0. + set pe to old_pe. + + set n_eta to time:seconds+ship:orbit:period*0.20. + set n_t0 to time:seconds. + set mynode to NODE(n_eta,N_rad,n_nor,n_pro). + ADD mynode. + + // Progressively get more fine grained + set step to 100. + + until step < 0.1 OR (mynode:orbit:hasnextpatch AND mynode:orbit:nextpatch:body = dst) { + // remember old PE + + set old_pe to pe. + set old_pe2 to pe. + if get_d2(mynode, n_pro, n_nor+step, n_rad, n_eta, dst ) < old_pe2 { + set n_nor to n_nor+step. + set old_pe2 to find_closest(ship,dst). + } else if get_d2(mynode, n_pro, n_nor-step, n_rad, n_eta, dst ) < old_pe2 { + set n_nor to n_nor-step. + set old_pe2 to find_closest(ship,dst). + } + if get_d2(mynode, n_pro+step/10, n_nor, n_rad, n_eta, dst ) < old_pe2 { + set n_pro to n_pro+step/10. + set old_pe2 to find_closest(ship,dst). + } else if get_d2(mynode, n_pro-step/10, n_nor, n_rad, n_eta, dst ) < old_pe2 { + set n_pro to n_pro-step/10. + set old_pe2 to find_closest(ship,dst). + } + if get_d2(mynode, n_pro, n_nor, n_rad+step, n_eta, dst ) < old_pe2 { + set n_rad to n_rad+step. + set old_pe2 to find_closest(ship,dst). + } else if get_d2(mynode, n_pro, n_nor, n_rad-step, n_eta, dst ) < old_pe2 { + set n_rad to n_rad-step. + set old_pe2 to find_closest(ship,dst). + } + set pe to get_d2(mynode, n_pro, n_nor, n_rad, n_eta, dst ). + p_status("PE: "+km(pe)+" ("+percent(pe, original_pe)+")",1). + p_status("ETA: "+round(n_eta-time:seconds)+" step: "+round(step,2),2). + p_status("Pro: "+round(n_pro,2),3). + p_status("Nor: "+round(n_nor,2),4). + p_status("Rad: "+round(n_rad,2),5). + if old_pe <= pe*1.0001 { + set step to step*0.5. + } + } + + print1s("final pe: "+round(pe/1000)+" km pro/nor/rad : "+round(n_pro,2)+" / "+round(n_nor,2)+" / "+round(n_rad,2)+" ["+round(step,2)+"]" ). + + if mynode:orbit:hasnextpatch AND mynode:orbit:nextpatch:body = dst { + // We have an encounter. + print "Encounter with "+mynode:orbit:nextpatch:body:name. + } else { + panic("No encounter. Aborting."). + return False. + } + } + + // Optimize the encounter, and burn. + optimize_pe(dst_min_pe,dst_max_pe,dst). + myquicksave("x4-encounter"). + exec_n(nextnode). + + wait_until_in_orbit_of(dst). + print "arrived in orbit of "+dst:name. + myquicksave("x5-dstSOI"). +} + + +myinit(). +// Are we in orbit? +if ship:obt:body <> dst_planet { + my_transfer(dst_planet). +} +capture(dst_planet,dst_alt,fix_incl). +myexit(). + + + diff --git a/xincl.ks b/xincl.ks new file mode 100644 index 0000000..f22de9d --- /dev/null +++ b/xincl.ks @@ -0,0 +1,55 @@ +// Set inclination to zero. + +declare parameter incl_new is 0, lan_new is 0. + +run once libguido. +myinit(). + +set firsttime to true. +set done to False. + +// Check if there is anything to do. + +set i to ship:orbit:inclination - incl_new. + +set d to vcrs(ship:velocity:orbit, body:position):direction. +if i > 0 { set d to d:inverse. } +wait_turn(d). + +set i to ship:orbit:inclination - incl_new. +set min_i to 999. + +// Do this until it flips... +until abs(i) > (min_i+0.001) { + set i to ship:orbit:inclination - incl_new. + set d to vcrs(ship:velocity:orbit, body:position):direction. + if i > 0 { set d to d:inverse. } + lock steering to d. + + // How much throttle? Ignore for now... + set dv to 2*ship:velocity:orbit:mag*sin(i/2). + set dt to abs(dv)/(ship:maxthrust/ship:mass). + + if abs(i) > 10 and vang(ship:facing:vector,d:vector) < 2 { + lock throttle to 1.0. + } else if abs(i) > 1 and vang(ship:facing:vector,d:vector) < 5 { + lock throttle to 0.1. + } else if vang(ship:facing:vector,d:vector) < 10{ + lock throttle to 0.01. + } + print1s("incl: "+round(i,3)). + wait 0.1. + + if abs(i) < min_i { set min_i to abs(i). }. + } + lock throttle to 0. + + set i to ship:orbit:inclination - incl_new. + if abs(i) < 1 { + set done to true. +} + + +set i to abs(ship:orbit:inclination - incl_new). +print "done. incl: "+round(i,3). +myexit(). \ No newline at end of file