├── .gitattributes ├── .gitignore ├── Challenge.ks ├── GravityTurn.ks ├── LaunchAirless.ks ├── LaunchMun.ks ├── LaunchTest.ks ├── LaunchTest2.ks ├── LaunchTest3.ks ├── Library ├── lib_ManeuverNodes.ks └── lib_OrbitalManeuvers.ks ├── MatchPeriod.ks ├── OrbitalManeuvers ├── ChangeCirAlt.ks ├── CircularizeAP.ks └── CircularizePE.ks ├── SetPitchOver.ks ├── TEST └── target_rel.ks ├── TrueGravityTurn.ks ├── boot └── boot.ks.txt ├── capture.ks ├── change_orbit.ks ├── docking_helper.ks ├── geneticlaunch.ks ├── horizontal_landing.ks ├── hover.ks ├── hyst_test.ks ├── impact_locator.ks ├── inclinationmatch.ks ├── landing.ks ├── landingFG.ks ├── landing_orbit.ks ├── landing_term_traj.ks ├── launch.ks ├── launch_gamma.ks ├── lib_instaz.ks ├── massout.ks ├── maxq.ks ├── rdz_body.ks ├── rdz_circular.ks ├── rdz_man.ks ├── rdz_man2.ks ├── rdz_target.KS ├── rendezvous.ks ├── spot_land_eq.ks └── vertical_landing.ks /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | test* 2 | -------------------------------------------------------------------------------- /Challenge.ks: -------------------------------------------------------------------------------- 1 | declare parameter OrbitAltKM. 2 | 3 | set OrbitAlt to OrbitAltKM*1000. 4 | set TargetSMA to ship:body:radius + OrbitAlt. 5 | set ship:control:pilotmainthrottle to 0. 6 | clearscreen. 7 | set circstage to 3. 8 | 9 | set flightmode to 0. 10 | set compass to 90. 11 | //set OrbitAlt to 100000. 12 | set starting_alt to altitude. 13 | 14 | lock pitch to sqrt((90^2)*MAX(0,(altitude-2*starting_alt))/50000). 15 | 16 | lock steering to heading(compass,90-pitch). 17 | set thrustset to 1. 18 | lock throttle to thrustset. 19 | 20 | stage. 21 | set starttime to time:seconds. 22 | set startlong to ship:longitude. 23 | wait 1. 24 | set MAX to maxthrust. 25 | set BurnTime to 0. 26 | set DeltaV to 0. 27 | 28 | lock e to ship:orbit:eccentricity. 29 | lock a to ship:orbit:semimajoraxis. 30 | lock u to ship:body:mu. 31 | 32 | when maxthrust < MAX OR availablethrust = 0 then { 33 | stage. 34 | set MAX to maxthrust. 35 | preserve. 36 | } 37 | 38 | lock Q to 1000*ship:dynamicpressure. 39 | set MaxQ to Q. 40 | lock AeroSwitch to Q/MaxQ. 41 | 42 | until e <= .001 OR a >= TargetSMA { 43 | 44 | if MaxQ <= Q { 45 | set MaxQ to Q. 46 | } 47 | 48 | if flightmode = 0 and AeroSwitch < .1 { 49 | lock FPAorbit to VANG(UP:vector,velocity:orbit). 50 | lock pitch to FPAorbit. 51 | set flightmode to 1. 52 | } 53 | 54 | if flightmode = 1 AND pitch >= 80 { 55 | set thrustset to 1. 56 | set flightmode to 2. 57 | } 58 | 59 | if flightmode = 2 AND apoapsis >= .9*OrbitAlt { 60 | lock throttle to MIN(1,((OrbitAlt - apoapsis)^(1/2))/((.1*OrbitAlt)^(1/2))). 61 | wait .5. 62 | set flightmode to 3. 63 | } 64 | 65 | if flightmode <= 3 AND apoapsis >= OrbitAlt AND altitude > 70000 { 66 | lock throttle to 0. 67 | wait .5. 68 | set flightmode to 4. 69 | } 70 | 71 | if flightmode = 4 { 72 | lock Vapo to sqrt(((1-e)*u)/((1+e)*a)). 73 | lock Vcir to sqrt(u/(apoapsis + ship:body:radius)). 74 | lock DeltaV to Vcir - Vapo. 75 | lock BurnTime to .5*DeltaV*(mass/max(.0001,availablethrust)). 76 | lock steering to srfprograde. 77 | set flightmode to 5. 78 | } 79 | 80 | if flightmode = 5 AND altitude >= 70000 { 81 | lock steering to prograde. 82 | wait 5. 83 | warpto(time:seconds + eta:apoapsis - BurnTime - 15). 84 | set flightmode to 6. 85 | } 86 | 87 | if flightmode = 6 { 88 | if .9*BurnTime >= eta:apoapsis OR ship:orbit:trueanomaly >= 180 { 89 | lock throttle to DeltaV*(mass/max(.0001,availablethrust)). 90 | } 91 | if BurnTime < eta:apoapsis AND ship:orbit:trueanomaly < 180 { 92 | lock throttle to 0. 93 | } 94 | } 95 | 96 | 97 | 98 | print "Flight Mode " + flightmode at (0,1). 99 | print "MaxQ " + round(MaxQ,2) at (0,2). 100 | print "Q " + round(Q,2) at (0,3). 101 | print "Pitch " + round(pitch,2) at (0,4). 102 | print "Ship Pitch " + round(VANG(UP:vector,ship:facing:vector),2) at (0,5). 103 | print "Apoapsis " + round(apoapsis,2) at (0,6). 104 | print "Target Apoapsis " + round(OrbitAlt,2) at (0,7). 105 | print "SMA " + round(a,2) at (0,8). 106 | print "Target SMA " + round(TargetSMA,2) at (0,9). 107 | print "Time to Apoapsis " + round(eta:apoapsis,2) at (0,10). 108 | print "BurnTime " + round(BurnTime,2) at (0,11). 109 | print "Throttle " + round(throttle,2) at (0,12). 110 | } 111 | 112 | lock throttle to 0. 113 | unlock all. 114 | set finishtime to time:seconds. 115 | set totaltime to finishtime - starttime. 116 | set finishlong to ship:longitude. 117 | print "Time to Ascent " + round(totaltime,2) at (0,20). 118 | print "Final Longitude " + round(finishlong,2) at (0,21). -------------------------------------------------------------------------------- /GravityTurn.ks: -------------------------------------------------------------------------------- 1 | clearscreen. 2 | set pitchoveralt to 2000. 3 | set pitchangle to 10. 4 | set OrbitAlt to 100000. 5 | 6 | lock g to ship:sensors:grav:mag. 7 | lock a to ship:sensors:acc. 8 | lock p to ship:sensors:pres. 9 | lock VelAcc to VDOT(velocity:surface:direction:vector,a). 10 | set SwitchAlt to 0. 11 | set SwitchAng to 0. 12 | lock FPAsurf to VANG(UP:vector,velocity:surface). 13 | lock FPAorbit to VANG(UP:vector,velocity:orbit). 14 | lock FPAdesired to 0 + pitchangle*altitude/pitchoveralt. 15 | lock steering to Heading(90,90). 16 | 17 | lock error to FPAdesired - FPAsurf. 18 | set Eavg to 0. 19 | set Eint to 0. 20 | set Eder to 0. 21 | set Eder1 to 0. 22 | set Eder2 to 0. 23 | set calcdps to 0. 24 | set calcdps1 to 0. 25 | set calcdps2 to 0. 26 | set Damp to 5. 27 | set Kp to .75. 28 | set Ki to .9. 29 | set Kd to .3. 30 | 31 | set slope to (90-pitchangle)/(OrbitAlt-pitchoveralt). 32 | lock dps to (slope*verticalspeed). 33 | lock realdps to (180/3.1415)*((g*sin(FPAsurf))/velocity:surface:mag). 34 | 35 | wait 5. 36 | set ship:control:pilotmainthrottle to 0. 37 | set p0 to p. 38 | lock throttle to 1. 39 | stage. 40 | print "Launch". 41 | wait 1. 42 | set MAX to maxthrust. 43 | set x to 0. 44 | lock ThrstAcc to availablethrust/mass. 45 | set DeltaV to 0. 46 | set TDeltaV to 0. 47 | 48 | 49 | lock steering to Heading(90,90-(FPAdesired + x*(Kp*Eavg + Ki*Eint - Kd*Eder))). 50 | 51 | until apoapsis >= OrbitAlt OR periapsis > 75000 { 52 | 53 | if MAX > maxthrust { 54 | stage. 55 | wait .00001. 56 | set MAX to maxthrust. 57 | } 58 | 59 | if x = 0 AND altitude >= pitchoveralt { 60 | 61 | lock steering to Heading(90,90-FPAsurf). 62 | lock FPAdesired to pitchangle + slope*(altitude-pitchoveralt). 63 | set Kp to .75. 64 | set Ki to 0. 65 | set Kd to .825. 66 | set Eint to 0. 67 | lock throttle to 1 - Kp*Eavg - Kd*Eder. 68 | set x to 1. 69 | } 70 | 71 | if x = 1 AND p/p0 <= .025 { 72 | 73 | lock steering to Heading(90,90-FPAorbit). 74 | set SwitchAlt to altitude. 75 | set SwitchAng to FPAorbit. 76 | set slope to (90-SwitchAng)/(OrbitAlt-SwitchAlt). 77 | lock FPAdesired to SwitchAng + slope*(altitude-SwitchAlt). 78 | lock error to FPAdesired - FPAorbit. 79 | set Eint to 0. 80 | set x to 2. 81 | } 82 | 83 | set t1 to time:seconds. 84 | set E1 to error. 85 | set FPA1 to FPAsurf. 86 | set TAcc1 to ThrstAcc. 87 | set Acc1 to VelAcc. 88 | wait .00001. 89 | set t2 to time:seconds. 90 | set E2 to error. 91 | set FPA2 to FPAsurf. 92 | set Acc2 to VelAcc. 93 | set TAcc2 to ThrstAcc. 94 | 95 | set Eavg to (E1+E2)/2. 96 | set Accavg to (Acc1+Acc2)/2. 97 | set TAccavg to (TAcc1+TAcc2)/2. 98 | set dt to t2-t1. 99 | set Eint to Eint + x*Eavg*dt. 100 | set Eder1 to (E2-E1)/dt. 101 | set Eder to (Eder1 + Eder2*Damp)/(Damp+1). 102 | set Eder2 to Eder. 103 | set calcdps1 to (FPA2-FPA1)/dt. 104 | set calcdps to (calcdps1 + calcdps2*Damp)/(Damp+1). 105 | set calcdps2 to calcdps. 106 | set DeltaV to DeltaV +Accavg*dt. 107 | set TDeltaV to TDeltaV + TAccavg*dt. 108 | set Loss to TDeltaV - DeltaV. 109 | 110 | 111 | print "Desired " + round(FPAdesired,2) at (0,3). 112 | print "Ship " + round(FPAsurf,2) at (0,4). 113 | print "Error " + round(error,2) + " " at (0,5). 114 | print "SwitchAlt " + round(SwitchAlt,2) at (0,6). 115 | print "SwitchAng " + round(SwitchAng,2) at (0,7). 116 | print "Dps " + round(dps,2) + " " at (0,8). 117 | print "RealDps " + round(realdps,2) + " " at (0,9). 118 | print "CalcDps " + round(calcdps,2) + " " at (0,10). 119 | print "VelAcc " + round(VelAcc,2) + " " at (0,11). 120 | print "ThrstAcc " + round(ThrstAcc,2) + " " at (0,12). 121 | print "DeltaV " + round(DeltaV,2) + " " at (0,13). 122 | print "TDeltaV " + round(TDeltaV,2) + " " at (0,14). 123 | print "Loss " + round(Loss,2) + " " at (0,15). 124 | } 125 | set Vcir to sqrt(ship:body:MU/(OrbitAlt+ship:body:radius)). 126 | set Vap to sqrt(((1-orbit:eccentricity)*body:MU)/((1+orbit:eccentricity)*orbit:semimajoraxis)). 127 | print Vcir - Vap at (0,16). 128 | print TDeltaV + Vcir - Vap at (0,17). -------------------------------------------------------------------------------- /LaunchAirless.ks: -------------------------------------------------------------------------------- 1 | declare parameter SwitchAlt. 2 | SAS off. 3 | lock pitch to min(90,90*altitude^(.5)/SwitchAlt^(.5)). 4 | lock steering to heading(90,90-pitch). 5 | lock throttle to 1. 6 | GEAR OFF. 7 | set R to 100000. 8 | clearscreen. 9 | print "Ascending until apoapsis is " + R + " meters". 10 | wait until apoapsis >= R. 11 | lock throttle to 0. 12 | run CircularizeAP. -------------------------------------------------------------------------------- /LaunchMun.ks: -------------------------------------------------------------------------------- 1 | lock pitch to min(90,90*altitude^(.5)/5000^(.5)). 2 | lock steering to heading(90,90-pitch). 3 | lock throttle to 1. 4 | GEAR OFF. 5 | set R to 100000. 6 | clearscreen. 7 | print "Ascending until apoapsis is " + R + " meters". 8 | wait until apoapsis >= R. 9 | lock throttle to 0. 10 | run CircularizeAP. -------------------------------------------------------------------------------- /LaunchTest.ks: -------------------------------------------------------------------------------- 1 | clearscreen. 2 | set ship:control:pilotmainthrottle to 0. 3 | 4 | set MUKerbin to ship:body:MU. 5 | set RKerbin to ship:body:Radius. 6 | 7 | set DesiredAlt to 75000. 8 | lock AltVar to altitude/DesiredAlt. 9 | //set a to -884.6. 10 | //set b to .02317. 11 | //set c to 885. 12 | //lock DesiredFPA to 90-(a*AltVar^(b) + c). 13 | 14 | set a to 90/((1000/DesiredAlt - 1)^2). 15 | 16 | lock DesiredFPA to 90 - a*(AltVar-1)^2. 17 | 18 | set speed1 to velocity:orbit:mag. 19 | set speed2 to sqrt(MUKerbin/(RKerbin + DesiredAlt)). 20 | set slope to (speed2-speed1)/DesiredAlt. 21 | lock DesiredSpeed to slope*altitude + speed1. 22 | 23 | lock orbitalspeed to velocity:orbit:mag. 24 | lock ErrorSpeed to DesiredSpeed - orbitalspeed. 25 | 26 | lock FPA to VANG(UP:vector,velocity:surface). 27 | lock ErrorFPA to DesiredFPA - FPA. 28 | 29 | set errFPA to 3. 30 | set errSpeed to .5. 31 | 32 | lock Pitch to DesiredFPA + errFPA*ErrorFPA. 33 | lock thrust to 1 + errSpeed*ErrorSpeed. 34 | 35 | set PitchSet to 90. 36 | 37 | lock steering to heading(90,90). 38 | lock throttle to thrust. 39 | 40 | stage. 41 | wait until Pitch > 0. 42 | lock steering to heading(90,90-Pitch). 43 | 44 | until periapsis > 70000 { 45 | 46 | print "DesiredFPA = " + round(DesiredFPA,2) at (0,0). 47 | print "FPA = " + round(FPA,2) at (0,1). 48 | print "DesiredSpeed = " + round(DesiredSpeed,2) at (0,2). 49 | print "OrbitalSpeed = " + round(orbitalspeed,2) at (0,3). 50 | 51 | print round(Pitch,2) at (0,5). 52 | 53 | if stage:liquidfuel = 0 { 54 | stage. 55 | wait .0001. 56 | } 57 | } -------------------------------------------------------------------------------- /LaunchTest2.ks: -------------------------------------------------------------------------------- 1 | clearscreen. 2 | 3 | set ship:control:pilotmainthrottle to 0. 4 | 5 | set MUKerbin to ship:body:MU. 6 | set RKerbin to ship:body:Radius. 7 | 8 | set DesiredAlt to 75000. 9 | lock AltVar to altitude/DesiredAlt. 10 | //set a to -884.6. 11 | //set b to .02317. 12 | //set c to 885. 13 | //lock DesiredFPA to 90-(a*AltVar^(b) + c). 14 | 15 | set a to 90/((1000/DesiredAlt - 1)^2). 16 | 17 | lock DesiredFPA to 90 - a*(AltVar-1)^2. 18 | 19 | set speed1 to velocity:orbit:mag. 20 | set speed2 to sqrt(MUKerbin/(RKerbin + DesiredAlt)). 21 | set speed3 to speed2-speed1. 22 | set a1 to speed3/(.5^2). 23 | lock DesiredSpeed to a1*(AltVar - .5)^3 + speed1 + .5*speed3. 24 | 25 | lock orbitalspeed to velocity:orbit:mag. 26 | lock ErrorSpeed to DesiredSpeed - orbitalspeed. 27 | 28 | lock FPA to VANG(UP:vector,velocity:surface). 29 | lock ErrorFPA to DesiredFPA - FPA. 30 | 31 | set errFPA to 2. 32 | set errSpeed to .5. 33 | 34 | lock Pitch to DesiredFPA + errFPA*ErrorFPA. 35 | lock thrust to 1 + errSpeed*ErrorSpeed. 36 | 37 | lock steering to heading(90,90). 38 | lock throttle to thrust. 39 | 40 | stage. 41 | wait until Pitch > 0. 42 | lock steering to heading(90,90-Pitch). 43 | 44 | until Periapsis > 70000 { 45 | 46 | print "DesiredFPA = " + round(DesiredFPA,2) at (0,0). 47 | print "FPA = " + round(FPA,2) at (0,1). 48 | print "DesiredSpeed = " + round(DesiredSpeed,2) at (0,2). 49 | print "OrbitalSpeed = " + round(orbitalspeed,2) at (0,3). 50 | 51 | print round(Pitch,2) at (0,5). 52 | 53 | if stage:liquidfuel = 0 { 54 | stage. 55 | wait .0001. 56 | } 57 | } -------------------------------------------------------------------------------- /LaunchTest3.ks: -------------------------------------------------------------------------------- 1 | clearscreen. 2 | 3 | set ship:control:pilotmainthrottle to 0. 4 | 5 | set MUKerbin to ship:body:MU. 6 | set RKerbin to ship:body:Radius. 7 | 8 | set DesiredAlt to 75000. 9 | lock AltVar to altitude/DesiredAlt. 10 | set speed1 to velocity:orbit:mag. 11 | set speed2 to sqrt(MUKerbin/(RKerbin + DesiredAlt)). 12 | set speed3 to speed2-speed1. 13 | set a1 to speed3/(.5^2). 14 | lock DesiredSpeed to a1*(AltVar - .5)^3 + speed1 + .5*speed3. 15 | 16 | set p1 to -8.676*10^04. 17 | set p2 to 4.212*10^05. 18 | set p3 to -8.703*10^05. 19 | set p4 to 9.983*10^05. 20 | set p5 to -6.952*10^05. 21 | set p6 to 3.022*10^05. 22 | set p7 to -8.155*10^04. 23 | set p8 to 1.332*10^04. 24 | set p9 to -1269. 25 | set p10 to 90. 26 | 27 | lock DesiredFPA to p1*AltVar^9 + p2*AltVar^8 + p3*AltVar^7 + p4*AltVar^6 + p5*AltVar^5 + p6*AltVar^4 + p7*AltVar^3 + p8*AltVar^2 + p9*AltVar + p10. 28 | 29 | lock orbitalspeed to velocity:orbit:mag. 30 | lock ErrorSpeed to DesiredSpeed - orbitalspeed. 31 | 32 | lock FPA to 90-VANG(UP:vector,velocity:surface). 33 | lock ErrorFPA to DesiredFPA - FPA. 34 | 35 | set errFPA to 3. 36 | set errSpeed to .5. 37 | 38 | lock Pitch to DesiredFPA + errFPA*ErrorFPA. 39 | lock thrust to 1 + errSpeed*ErrorSpeed. 40 | 41 | lock steering to heading(90,90). 42 | lock throttle to thrust. 43 | 44 | stage. 45 | wait 3. 46 | lock steering to heading(90,Pitch). 47 | 48 | until periapsis > 70000 { 49 | 50 | print "DesiredFPA = " + round(DesiredFPA,2) at (0,0). 51 | print "FPA = " + round(FPA,2) at (0,1). 52 | print "DesiredSpeed = " + round(DesiredSpeed,2) at (0,2). 53 | print "OrbitalSpeed = " + round(orbitalspeed,2) at (0,3). 54 | 55 | print round(Pitch,2) at (0,5). 56 | 57 | if stage:liquidfuel = 0 { 58 | stage. 59 | wait .0001. 60 | } 61 | 62 | wait .0001. 63 | } -------------------------------------------------------------------------------- /Library/lib_ManeuverNodes.ks: -------------------------------------------------------------------------------- 1 | @lazyGlobal OFF. 2 | 3 | global manNodeLib to ({ 4 | local function ExecuteNode { 5 | clearscreen. 6 | lock throttle to 0. 7 | SAS off. 8 | local Delta_V to nextnode:deltav:mag. 9 | local BurnTime to Delta_V*mass/availablethrust. 10 | lock steering to lookdirup(nextnode:burnvector,ship:facing:upvector). 11 | print "Aligning with Maneuver Node". 12 | until VANG(ship:facing:vector,nextnode:burnvector) < 1 { 13 | print "Direction Angle Error = " + round(VANG(ship:facing:vector,nextnode:burnvector),1) + " "at(0,1). 14 | } 15 | clearscreen. 16 | print "Alignment Complete". 17 | print "Warping to Burn Point". 18 | print "Burn Starts at T-minus " + round(BurnTime,2) + "secs ". 19 | warpto(time:seconds + nextnode:eta - BurnTime/2 - 10). 20 | wait until warp <= 0. 21 | 22 | clearscreen. 23 | local prev_dv to Delta_V. 24 | local diff_dv to -1. 25 | local stop_burn to false. 26 | local thr_var to 0. 27 | lock throttle to thr_var. 28 | 29 | until Delta_V <= .05 { 30 | set Delta_V to nextnode:deltav:mag. 31 | if nextnode:eta > BurnTime/2 { 32 | print "Burn Starts at T-minus " + round(nextnode:eta - BurnTime/2,2) + "secs " at(0,1). 33 | } else { 34 | set thr_var to 1*Delta_V*mass/availablethrust. 35 | print "Initiate Burn " at(0,1). 36 | } 37 | print "Delta V = " + round(Delta_V,2) + " " at(0,2). 38 | print "Throttle = " + MIN(100,round(throttle*100)) + "% " at(0,3). 39 | print "diff_dv = " + round(diff_dv,2) + " " at(0,4). 40 | wait 0. 41 | set diff_dv to Delta_V - prev_dv. 42 | if diff_dv > 0 { 43 | set stop_burn to true. 44 | } else { 45 | set prev_dv to Delta_V. 46 | } 47 | } 48 | lock throttle to 0. 49 | unlock all. 50 | remove nextnode. 51 | clearscreen. 52 | print "Node Executed". 53 | print "Delta V Error: " + round(Delta_V,3) + "m/s". 54 | wait 2. 55 | } 56 | 57 | return lexicon( 58 | "ExecuteNode", ExecuteNode@ 59 | ). 60 | 61 | }):call(). -------------------------------------------------------------------------------- /Library/lib_OrbitalManeuvers.ks: -------------------------------------------------------------------------------- 1 | @lazyGlobal OFF. 2 | 3 | global orbitManLib to ({ 4 | local function Circularize_AP { 5 | local u to ship:body:MU. 6 | local e to ship:orbit:eccentricity. 7 | local a to ship:orbit:semimajoraxis. 8 | local Rp to ship:body:radius + apoapsis. 9 | local V_ap to sqrt(((1-e)*u)/((1+e)*a)). 10 | 11 | local Vcir_pe to sqrt(u/(Rp)). 12 | local DeltaV to Vcir_pe- V_ap. 13 | local circ_pe_node to NODE(time:seconds + eta:apoapsis,0,0,DeltaV). 14 | add circ_pe_node. 15 | } 16 | 17 | local function Circularize_PE { 18 | local u to ship:body:MU. 19 | local e to ship:orbit:eccentricity. 20 | local a to ship:orbit:semimajoraxis. 21 | local Rp to ship:body:radius + periapsis. 22 | 23 | local V_pe to 0. 24 | 25 | if e >= 1 { 26 | set V_pe to sqrt(u*((2/(Rp))-(1/a))). 27 | } 28 | if e < 1 { 29 | set V_pe to sqrt(((1+e)*u)/((1-e)*a)). 30 | } 31 | 32 | local Vcir_pe to sqrt(u/(Rp)). 33 | local DeltaV to Vcir_pe- V_pe. 34 | local circ_pe_node to NODE(time:seconds + eta:periapsis,0,0,DeltaV). 35 | add circ_pe_node. 36 | } 37 | 38 | return lexicon( 39 | "Circularize_AP", Circularize_AP@, 40 | "Circularize_PE", Circularize_PE@ 41 | ). 42 | 43 | }):call(). -------------------------------------------------------------------------------- /MatchPeriod.ks: -------------------------------------------------------------------------------- 1 | parameter TP_target is ship:orbit:period. 2 | 3 | local R1 to ship:body:radius + periapsis. 4 | local body_mu to ship:body:mu. 5 | for n in allnodes { remove n.} 6 | 7 | function vis_via_speed { 8 | parameter R, a is ship:orbit:semimajoraxis. 9 | local R_val to ship:body:radius + R. 10 | return sqrt(ship:body:mu*(2/R_val - 1/a)). 11 | } 12 | 13 | function OrbitalPeriodMatch { 14 | parameter target_period is ship:orbit:period. 15 | print target_period. 16 | local SMA_new to ((body_mu*(target_period^2))/(4*(constant:pi()^2)))^(1/3). 17 | print SMA_new. 18 | local R2 to 2*SMA_new - R1. 19 | print R2. 20 | local V_per_current to vis_via_speed(periapsis). 21 | print V_per_current. 22 | local V_per_new to vis_via_speed(periapsis,SMA_new). 23 | local Delta_V to V_per_new - V_per_current. 24 | local PER_node to node(time:seconds + eta:periapsis,0,0,Delta_V). 25 | add PER_node. 26 | ExecuteNode. 27 | clearscreen. 28 | print "Executed Orbital Period Match to within 0.01 m/s". 29 | print "Orbital Periods are different by " + round(abs(ship:orbit:period - target_period),3) + " sec". 30 | wait 2. 31 | return. 32 | } 33 | 34 | function ExecuteNode { 35 | clearscreen. 36 | lock throttle to 0. 37 | SAS off. 38 | lock DeltaV to nextnode:deltav:mag. 39 | local BurnTime to .5*DeltaV*mass/availablethrust. 40 | lock steering to LOOKDIRUP(nextnode:burnvector,facing:topvector). 41 | print "Aligning with Maneuver Node". 42 | until VANG(ship:facing:vector,nextnode:burnvector) < 1 { 43 | print "Direction Angle Error = " + round(VANG(ship:facing:vector,nextnode:burnvector),1) + " "at(0,1). 44 | } 45 | clearscreen. 46 | print "Warping to Node". 47 | print "Burn Starts at T-minus " + round(BurnTime,2) + "secs ". 48 | warpto(time:seconds + nextnode:eta - BurnTime - 10). 49 | wait until BurnTime >= nextnode:eta. 50 | 51 | clearscreen. 52 | lock throttle to DeltaV*mass/availablethrust. 53 | print "Executing Node". 54 | local runmode is 1. 55 | 56 | until DeltaV <= .01 { 57 | print "Delta V = " + round(DeltaV,2) + " " at(0,1). 58 | print "Throttle = " + MIN(100,round(throttle*100)) + "% " at(0,2). 59 | if runmode = 1 AND DeltaV < 0.5 { 60 | lock throttle to DeltaV*mass/(2*availablethrust). 61 | set runmode to 2. 62 | } 63 | wait 0. 64 | } 65 | lock throttle to 0. 66 | unlock all. 67 | remove nextnode. 68 | clearscreen. 69 | print "Node Executed". 70 | return. 71 | } 72 | 73 | if TP_target:istype("Vessel") { 74 | // Match Target Vessel Orbital Period 75 | clearscreen. 76 | print "Matching Orbital Period to " + TP_target:name. 77 | wait 2. 78 | clearscreen. 79 | set target_period to TP_target:orbit:period. 80 | print target_period. 81 | OrbitalPeriodMatch(target_period). 82 | } else if TP_target:istype("Scalar") { 83 | // Match ship's orbital period to the target orbital period 84 | print "Setting Orbital Period to " + TP_target + " sec". 85 | wait 2. 86 | set target_period to TP_target. 87 | OrbitalPeriodMatch(target_period). 88 | } else { 89 | 90 | clearscreen. 91 | print "Incorrect target format. Please enter a valid target (either a target ship or target period)". 92 | } -------------------------------------------------------------------------------- /OrbitalManeuvers/ChangeCirAlt.ks: -------------------------------------------------------------------------------- 1 | declare parameter R_new. 2 | 3 | declare function vis_via_speed { 4 | parameter R, a is ship:orbit:semimajoraxis. 5 | local R_val to ship:body:radius + R. 6 | return sqrt(ship:body:mu*(2/R_val - 1/a)). 7 | } 8 | 9 | declare function circ_speed { 10 | parameter R. 11 | local R_val to ship:body:radius + R. 12 | return sqrt(ship:body:mu/R_val). 13 | } 14 | 15 | declare function ExecuteNode { 16 | clearscreen. 17 | lock throttle to 0. 18 | SAS off. 19 | lock Delta_V to nextnode:deltav:mag. 20 | local BurnTime to .5*Delta_V*mass/availablethrust. 21 | lock steering to nextnode. 22 | print "Aligning with Maneuver Node". 23 | until VANG(ship:facing:vector,nextnode:burnvector) < 1 { 24 | print "Direction Angle Error = " + round(VANG(ship:facing:vector,nextnode:burnvector),1) + " "at(0,1). 25 | } 26 | clearscreen. 27 | print "Warping to Node". 28 | print "Burn Starts at T-minus " + round(BurnTime,2) + "secs ". 29 | warpto(time:seconds + nextnode:eta - BurnTime - 10). 30 | wait until BurnTime >= nextnode:eta. 31 | 32 | clearscreen. 33 | lock throttle to Delta_V*mass/availablethrust. 34 | print "Executing Node". 35 | 36 | until Delta_V <= .1 { 37 | print "Delta V = " + round(Delta_V,1) + " " at(0,1). 38 | print "Throttle = " + MIN(100,round(throttle*100)) + "% " at(0,2). 39 | } 40 | lock throttle to 0. 41 | unlock all. 42 | remove nextnode. 43 | clearscreen. 44 | print "Node Executed". 45 | } 46 | 47 | declare function Circularize_apo_Node{ 48 | local Vapo_cir to circ_speed(apoapsis). 49 | local Delta_V to Vapo_cir - vis_via_speed(apoapsis). 50 | local CirPer to NODE(TIME:seconds + eta:apoapsis, 0, 0, Delta_V). 51 | ADD CirPer. 52 | ExecuteNode(). 53 | } 54 | 55 | declare function Circularize_per_Node{ 56 | local Vper_cir to circ_speed(periapsis). 57 | local Delta_V to Vper_cir - vis_via_speed(periapsis). 58 | local CirPer to NODE(TIME:seconds + eta:periapsis, 0, 0, Delta_V). 59 | ADD CirPer. 60 | ExecuteNode(). 61 | } 62 | 63 | declare function HohmannTransfer { 64 | parameter R. 65 | local R_planet to ship:body:radius. 66 | local R_val to R_planet + R. 67 | local R_p to periapsis + R_planet. 68 | local R_a to apoapsis + R_planet. 69 | local a to ship:orbit:semimajoraxis. 70 | 71 | local a_new to (R_p + R_val)/2. 72 | local V_trans to vis_via_speed(periapsis,a_new). 73 | print round(V_trans,2). 74 | local V_per to vis_via_speed(periapsis). 75 | print round(V_per,2). 76 | set Delta_V to V_trans - V_per. 77 | set HomTran to NODE(TIME:seconds + eta:periapsis, 0, 0, Delta_V). 78 | ADD HomTran. 79 | ExecuteNode(). 80 | } 81 | 82 | 83 | // Main Body 84 | set No_Nodes to false. 85 | until No_Nodes { 86 | if hasnode { 87 | remove nextnode. 88 | wait 0. 89 | } else { 90 | set No_Nodes to true. 91 | } 92 | } 93 | 94 | if ship:body:atm:exists { 95 | 96 | set a to ship:orbit:semimajoraxis. 97 | 98 | if R_new < ship:body:atm:height { 99 | clearscreen. 100 | print "Cannot Reach Altitude, Atmosphere Present At Desired Height. Must be above " + round(ship:body:atm:height,0) + " meters". 101 | } else { 102 | clearscreen. 103 | print "Creating New Circular Orbit at " + round(R_new,0) + " meters". 104 | wait 2. 105 | HohmannTransfer(R_new). 106 | clearscreen. 107 | print "Circularizing at new altitude " + round(R_new,0) + " meters". 108 | wait 2. 109 | if altitude > a { 110 | Circularize_per_Node. 111 | } else { 112 | Circularize_apo_Node. 113 | } 114 | } 115 | } else { 116 | clearscreen. 117 | print "Creating New Circular Orbit at " + round(R_new,0) + " meters". 118 | HohmannTransfer(R_new). 119 | } -------------------------------------------------------------------------------- /OrbitalManeuvers/CircularizeAP.ks: -------------------------------------------------------------------------------- 1 | clearscreen. 2 | lock Vper to VCRS(UP:vector,velocity:orbit/velocity:orbit:mag). 3 | set u to ship:body:MU. 4 | set e to ship:orbit:eccentricity. 5 | set a to ship:orbit:semimajoraxis. 6 | set Ra to ship:body:radius + apoapsis. 7 | 8 | lock Vcir to sqrt(ship:body:MU/ship:body:position:mag)*VCRS(Vper,UP:vector). 9 | set Vperp to VELOCITYAT(ship,time:seconds + eta:periapsis):orbit:mag. 10 | set Vcir_pe to sqrt(u/(Ra)). 11 | lock DeltaV to Vcir - velocity:orbit. 12 | set DeltaV_time to abs(Vcir_pe - Vperp). 13 | lock BurnTime to .5*DeltaV:mag*(mass/max(.0001,availablethrust)). 14 | set BurnTimeWarp to .5*DeltaV_time/(availablethrust/mass). 15 | lock steering to DeltaV:direction. 16 | print "Aligning with Circularization Burn Vector". 17 | wait 5. 18 | print "Warping to Apoapsis". 19 | print "Burn Starts at T-minus " + round(BurnTime,2) + "secs ". 20 | set flightmode to 0. 21 | warpto(time:seconds + eta:apoapsis - BurnTimeWarp - 10). 22 | 23 | until DeltaV:mag < .1 AND flightmode = 1 { 24 | print "Burn Time = " + round(BurnTime,2) + "secs " at(0,2). 25 | if flightmode = 0 AND BurnTime*.5 >= eta:apoapsis { 26 | lock throttle to DeltaV:mag*(mass/max(.0001,availablethrust)). 27 | set flightmode to 1. 28 | } 29 | } 30 | lock throttle to 0. 31 | clearscreen. 32 | print "Finished Circularization". 33 | wait 1. -------------------------------------------------------------------------------- /OrbitalManeuvers/CircularizePE.ks: -------------------------------------------------------------------------------- 1 | 2 | lock Vper to VCRS(UP:vector,velocity:orbit/velocity:orbit:mag). 3 | set u to ship:body:MU. 4 | set e to ship:orbit:eccentricity. 5 | set a to ship:orbit:semimajoraxis. 6 | set Rp to ship:body:radius + periapsis. 7 | 8 | if e >= 1 { 9 | set Vperp to sqrt(u*((2/(Rp))-(1/a))). 10 | } 11 | if e < 1 { 12 | set Vperp to sqrt(((1+e)*u)/((1-e)*a)). 13 | } 14 | 15 | set Vcir_pe to sqrt(u/(Rp)). 16 | set DeltaV to Vcir_pe- Vperp. 17 | set circ_pe_node to NODE(time:seconds + eta:periapsis,0,0,DeltaV). 18 | add circ_pe_node. -------------------------------------------------------------------------------- /SetPitchOver.ks: -------------------------------------------------------------------------------- 1 | clearscreen. 2 | set thrust to 0. 3 | lock throttle to 0. 4 | 5 | lock Vcir_mag to sqrt(ship:body:MU/(altitude+ship:body:RADIUS)). 6 | lock Vcir to Vcir*heading(90,0):vector. 7 | 8 | lock DeltaV to Vcir-velocity:orbit. 9 | lock DeltaV_dir to DeltaV:direction. 10 | lock steering to DeltaV_dir. 11 | lock thrust to DeltaV:mag*mass/maxthrust. 12 | lock HalfBurnTime to .5*mass*(DeltaV:mag)/maxthrust. 13 | 14 | until DeltaV:mag < 1 { 15 | 16 | 17 | print "DeltaV = " + round(DeltaV:mag,2) at (0,0). 18 | print "Apoapsis = " + round(apoapsis,2) at (0,2). 19 | print "HalfBurnTime = " + round(HalfBurnTime,2) at (0,4). 20 | print "ETA to Apoapsis = " + round(eta:apoapsis,2) at (0,6). 21 | 22 | if flightmode = 2 AND HalfBurnTime > eta:apoapsis { 23 | 24 | lock throttle to thrust. 25 | set flightmode to 3. 26 | } 27 | 28 | wait .0001. 29 | 30 | } -------------------------------------------------------------------------------- /TEST/target_rel.ks: -------------------------------------------------------------------------------- 1 | until false { 2 | lock relvelocity to target:velocity:orbit - ship:velocity:orbit. 3 | lock targetdirection to target:position:normalized. 4 | lock SideSlip to VCRS(VCRS(targetdirection,ship:velocity:orbit),targetdirection):normalized. 5 | lock SideSlipSpeed to VDOT(SideSlip,relvelocity). 6 | lock steering to (relvelocity+SideSlip*SideSlipSpeed):direction. 7 | lock DeltaV to relvelocity:mag. 8 | set TargetPos to VECDRAW(V(0,0,0),target:position,GREEN,"Target Position",1.0,TRUE,.5). 9 | set RelativeVel to VECDRAW(V(0,0,0),relvelocity,RED,"RelativeVel",1.0,TRUE,.5). 10 | set SideSlipVec to VECDRAW(relvelocity,SideSlip*SideSlipSpeed,Blue,"SideSlip",1.0,TRUE,.5). 11 | } -------------------------------------------------------------------------------- /TrueGravityTurn.ks: -------------------------------------------------------------------------------- 1 | clearscreen. 2 | set pitchoveralt to 2000. 3 | set pitchangle to 25. 4 | set OrbitAlt to 100000. 5 | 6 | lock g to ship:sensors:grav:mag. 7 | lock a to ship:sensors:acc. 8 | lock p to ship:sensors:pres. 9 | lock VelAccO to VDOT(velocity:orbit:direction:vector,a). 10 | lock VelAccS to VDOT(velocity:orbit:direction:vector,a). 11 | set SwitchAlt to 0. 12 | set SwitchAng to 0. 13 | lock FPAsurf to VANG(UP:vector,velocity:surface). 14 | lock FPAorbit to VANG(UP:vector,velocity:orbit). 15 | lock FPAdesired to 0 + pitchangle*altitude/pitchoveralt. 16 | lock steering to Heading(90,90). 17 | 18 | lock error to FPAdesired - FPAsurf. 19 | set Eavg to 0. 20 | set Eint to 0. 21 | set Eder to 0. 22 | set Eder1 to 0. 23 | set Eder2 to 0. 24 | set calcdps to 0. 25 | set calcdps1 to 0. 26 | set calcdps2 to 0. 27 | set Damp to 5. 28 | set Kp to .75. 29 | set Ki to .9. 30 | set Kd to .3. 31 | 32 | set slope to (90-pitchangle)/(OrbitAlt-pitchoveralt). 33 | lock dps to (slope*verticalspeed). 34 | lock realdps to (180/3.1415)*((g*sin(FPAsurf))/velocity:surface:mag). 35 | 36 | wait 5. 37 | set ship:control:pilotmainthrottle to 0. 38 | set p0 to p. 39 | lock throttle to 1. 40 | stage. 41 | print "Launch". 42 | wait 1. 43 | set MAX to maxthrust. 44 | set x to 0. 45 | lock ThrstAcc to availablethrust/mass. 46 | set DeltaV to 0. 47 | set TDeltaV to 0. 48 | 49 | lock steering to Heading(90,90-(FPAdesired + x*(Kp*Eavg + Ki*Eint - Kd*Eder))). 50 | 51 | until apoapsis >= OrbitAlt OR periapsis > 75000 { 52 | 53 | if MAX > maxthrust { 54 | stage. 55 | wait .00001. 56 | set MAX to maxthrust. 57 | } 58 | 59 | if x = 0 AND altitude >= pitchoveralt { 60 | 61 | lock steering to Heading(90,90-FPAsurf). 62 | set x to 1. 63 | 64 | } 65 | 66 | if x = 1 AND p/p0 <= .025 { 67 | 68 | lock steering to Heading(90,90-FPAorbit). 69 | set x to 2. 70 | } 71 | 72 | set t1 to time:seconds. 73 | set E1 to error. 74 | set FPA1 to FPAsurf. 75 | set TAcc1 to ThrstAcc. 76 | set Acc1 to VelAcc. 77 | wait .00001. 78 | set t2 to time:seconds. 79 | set E2 to error. 80 | set FPA2 to FPAsurf. 81 | set Acc2 to VelAcc. 82 | set TAcc2 to ThrstAcc. 83 | 84 | set Eavg to (E1+E2)/2. 85 | set Accavg to (Acc1+Acc2)/2. 86 | set TAccavg to (TAcc1+TAcc2)/2. 87 | set dt to t2-t1. 88 | set Eint to Eint + x*Eavg*dt. 89 | set Eder1 to (E2-E1)/dt. 90 | set Eder to (Eder1 + Eder2*Damp)/(Damp+1). 91 | set Eder2 to Eder. 92 | set calcdps1 to (FPA2-FPA1)/dt. 93 | set calcdps to (calcdps1 + calcdps2*Damp)/(Damp+1). 94 | set calcdps2 to calcdps. 95 | set DeltaV to DeltaV +Accavg*dt. 96 | set TDeltaV to TDeltaV + TAccavg*dt. 97 | set Loss to TDeltaV - DeltaV. 98 | 99 | 100 | print "Desired " + round(FPAdesired,2) at (0,3). 101 | print "Ship " + round(FPAsurf,2) at (0,4). 102 | print "Error " + round(error,2) + " " at (0,5). 103 | print "SwitchAlt " + round(SwitchAlt,2) at (0,6). 104 | print "SwitchAng " + round(SwitchAng,2) at (0,7). 105 | print "Dps " + round(dps,2) + " " at (0,8). 106 | print "RealDps " + round(realdps,2) + " " at (0,9). 107 | print "CalcDps " + round(calcdps,2) + " " at (0,10). 108 | print "VelAcc " + round(VelAcc,2) + " " at (0,11). 109 | print "ThrstAcc " + round(ThrstAcc,2) + " " at (0,12). 110 | print "DeltaV " + round(DeltaV,2) + " " at (0,13). 111 | print "TDeltaV " + round(TDeltaV,2) + " " at (0,14). 112 | print "Loss " + round(Loss,2) + " " at (0,15). 113 | } 114 | 115 | set Vcir to sqrt(ship:body:MU/(OrbitAlt+ship:body:radius)). 116 | set Vap to sqrt(((1-orbit:eccentricity)*body:MU)/((1+orbit:eccentricity)*orbit:semimajoraxis)). 117 | print Vcir - Vap at (0,16). 118 | print TDeltaV + Vcir - Vap at (0,17). -------------------------------------------------------------------------------- /boot/boot.ks.txt: -------------------------------------------------------------------------------- 1 | core:part:getmodule("kOSProcessor"):doevent("Open Terminal"). 2 | -------------------------------------------------------------------------------- /capture.ks: -------------------------------------------------------------------------------- 1 | clearscreen. 2 | set R2 to ship:body:radius + 100000. 3 | lock R1 to ship:body:position:mag. 4 | lock a_cap to (R1+R2)/2. 5 | lock ecc_cap to abs(R1-R2)/(R1+R2). 6 | lock Va_cap to sqrt(ship:body:MU*(2/R1 - 1/a_cap)). 7 | 8 | lock vec1 to VCRS(ship:body:position,ship:body:body:position):normalized. 9 | lock vec2 to VCRS(vec1,ship:body:position):normalized. 10 | lock Delta_V to Va_cap*vec2 - ship:velocity:orbit. 11 | set arrow to VECDRAW(ship:position,Delta_V:normalized*10,RGB(1,1,1),"Delta V",1,TRUE,.5). 12 | lock steering to Delta_V:direction. 13 | print "Aligning to Delta V vector". 14 | until VANG(ship:facing:vector,Delta_V) < 1 { 15 | print "Direction Angle Error = " + round(VANG(ship:facing:vector,Delta_V),1) + " "at(0,1). 16 | } 17 | clearscreen. 18 | print "Burning for Capture". 19 | 20 | until Delta_V:mag < 1 { 21 | lock throttle to Delta_V:mag*mass/maxthrust. 22 | print "Delta V = " + round(Delta_V:mag,1) at(0,2). 23 | } 24 | clearscreen. 25 | print "Captured on " + ship:body:name. 26 | clearvecdraws(). -------------------------------------------------------------------------------- /change_orbit.ks: -------------------------------------------------------------------------------- 1 | function Change_LAN_Inc { 2 | 3 | parameter DesiredOrbit. 4 | local body_pos to ship:body:position. 5 | local INC_ship to ship:orbit:inclination. 6 | local R to -body_pos. 7 | local SMA_ship to ship:orbit:semimajoraxis. 8 | local LAN_des to DesiredOrbit["LAN"]. 9 | local LAN_VEC to solarprimevector*(SMA_ship)*R(0,-LAN_des,0). 10 | local Inc_Rotate to ANGLEAXIS(-1*DesiredOrbit["INC"],LAN_VEC). 11 | local Inc_Normal to Inc_Rotate*(V(0,-1,0):direction). 12 | local Inc_Normal to SMA_ship*Inc_Normal:vector. 13 | 14 | local AngVel_ship to SMA_ship*VCRS(R,ship:velocity:orbit):normalized. 15 | 16 | local LAN_relative_vec to SMA_ship*VCRS(AngVel_ship,Inc_Normal):normalized. 17 | 18 | local LAN_relative_theta to FindTheta_Vec(LAN_relative_vec). 19 | local LAN_eta to ETA_to_theta(LAN_relative_theta). 20 | //local LAN_node to NODE( time:seconds + LAN_eta,0,0,0). 21 | //add LAN_node. 22 | 23 | local delta_inc to VANG(AngVel_ship,Inc_Normal). 24 | local Vel_at_LAN to velocityat(ship,time:seconds + LAN_eta):orbit. 25 | local temp_dir to Vel_at_LAN:direction. 26 | local rotate_dir to ANGLEAXIS(delta_inc,LAN_relative_vec). 27 | local vel_rotated to rotate_dir*temp_dir. 28 | local New_Vel_at_LAN to (Vel_at_LAN:mag)*vel_rotated:vector. 29 | 30 | local LAN_node to SetNode_BurnVector(time:seconds + LAN_eta,New_Vel_at_LAN). 31 | add LAN_node. 32 | 33 | 34 | 35 | // Debugging Vecdraws 36 | set LAN_VEC_Draw to vecdraw(). 37 | set LAN_VEC_Draw:startupdater to { return ship:body:position. }. 38 | set LAN_VEC_Draw:vecupdater to { return LAN_VEC. }. 39 | set LAN_VEC_Draw:show to true. 40 | set LAN_VEC_Draw:color to RGB(255,0,0). 41 | 42 | set INC_VEC_Draw to vecdraw(). 43 | set INC_VEC_Draw:startupdater to { return ship:body:position. }. 44 | set INC_VEC_Draw:vecupdater to { return Inc_Normal. }. 45 | set INC_VEC_Draw:show to true. 46 | set INC_VEC_Draw:color to RGB(0,255,0). 47 | 48 | set ANG_VEC_Draw to vecdraw(). 49 | set ANG_VEC_Draw:startupdater to { return ship:body:position. }. 50 | set ANG_VEC_Draw:vecupdater to { return AngVel_ship. }. 51 | set ANG_VEC_Draw:show to true. 52 | set ANG_VEC_Draw:color to RGB(0,0,255). 53 | 54 | set Rel_LAN_VEC_Draw to vecdraw(). 55 | set Rel_LAN_VEC_Draw:startupdater to { return ship:body:position. }. 56 | set Rel_LAN_VEC_Draw:vecupdater to { return LAN_relative_vec. }. 57 | set Rel_LAN_VEC_Draw:show to true. 58 | set Rel_LAN_VEC_Draw:color to RGB(255,255,0). 59 | 60 | set LAN_VEL_VEC_Draw to vecdraw(). 61 | set LAN_VEL_VEC_Draw:startupdater to { return V(0,0,0). }. 62 | set LAN_VEL_VEC_Draw:vecupdater to { return Vel_at_LAN/50. }. 63 | set LAN_VEL_VEC_Draw:show to true. 64 | set LAN_VEL_VEC_Draw:color to RGB(255,0,0). 65 | 66 | set LAN_VEL_VEC_Draw2 to vecdraw(). 67 | set LAN_VEL_VEC_Draw2:startupdater to { return V(0,0,0). }. 68 | set LAN_VEL_VEC_Draw2:vecupdater to { return New_Vel_at_LAN/50. }. 69 | set LAN_VEL_VEC_Draw2:show to true. 70 | set LAN_VEL_VEC_Draw2:color to RGB(0,255,0). 71 | 72 | wait 1. 73 | 74 | ExecuteNode(). 75 | 76 | return true. 77 | } 78 | 79 | function Change_AoP_PerApo { 80 | 81 | parameter DesiredOrbit. 82 | local body_pos to ship:body:position. 83 | local INC_ship to ship:orbit:inclination. 84 | local R to -body_pos. 85 | local SMA_ship to ship:orbit:semimajoraxis. 86 | local LAN_ship to ship:orbit:LAN. 87 | local LAN_VEC to solarprimevector*(SMA_ship)*R(0,-LAN_ship,0). 88 | local AngVel_ship to SMA_ship*VCRS(R,ship:velocity:orbit):normalized. 89 | local AOP_ship to ship:orbit:argumentofperiapsis. 90 | local AoP_Rotate to ANGLEAXIS(DesiredOrbit["AOP"],AngVel_ship). 91 | //local AoP_Rotate to ANGLEAXIS(AOP_ship,AngVel_ship). // Used for debugging 92 | local AoP_VEC to AoP_Rotate*(LAN_VEC:direction). 93 | local AoP_VEC to SMA_ship*AoP_VEC:vector. 94 | 95 | local AoP_theta to FindTheta_Vec(AoP_VEC). 96 | local AoP_eta to ETA_to_theta(AoP_theta). 97 | local AoP_timeat to time:seconds + AoP_eta. 98 | 99 | Apoapsis_Set_TimeAt(AoP_timeat,DesiredOrbit). 100 | local New_Apo_time to time:seconds + eta:apoapsis. 101 | Periapsis_Set_TimeAt(New_Apo_time,DesiredOrbit). 102 | // Debugging Vecdraws 103 | //set LAN_VEC_Draw to vecdraw(). 104 | //set LAN_VEC_Draw:startupdater to { return ship:body:position. }. 105 | //set LAN_VEC_Draw:vecupdater to { return LAN_VEC. }. 106 | //set LAN_VEC_Draw:show to true. 107 | //set LAN_VEC_Draw:color to RGB(255,0,0). 108 | // 109 | //set AoP_VEC_Draw to vecdraw(). 110 | //set AoP_VEC_Draw:startupdater to { return ship:body:position. }. 111 | //set AoP_VEC_Draw:vecupdater to { return AoP_VEC. }. 112 | //set AoP_VEC_Draw:show to true. 113 | //set AoP_VEC_Draw:color to RGB(0,255,0). 114 | 115 | wait 1. 116 | } 117 | 118 | function FindTheta_Vec { 119 | 120 | parameter test_vector is -ship:body:position. 121 | 122 | local body_pos to ship:body:position. 123 | local R to -body_pos. 124 | local AngVel_ship to VCRS(R,ship:velocity:orbit):normalized. 125 | local theta_test to VANG(test_vector,R). 126 | local cross_test to VCRS(R,test_vector):normalized. 127 | 128 | local check_vec to cross_test + AngVel_ship. 129 | local theta_ship is ship:orbit:trueanomaly. 130 | local theta is theta_ship. 131 | 132 | if check_vec:mag > 1 { 133 | set theta to theta_ship + theta_test. 134 | } else { 135 | set theta to theta_ship - theta_test. 136 | } 137 | 138 | if theta < 0 { 139 | set theta to 360 + theta. 140 | } 141 | 142 | if theta > 360 { 143 | set theta to theta - 360. 144 | } 145 | 146 | clearscreen. 147 | // print "Ship Theta is " + round(theta_ship,2). 148 | // print "Theta is " + round(theta,2). 149 | // wait 3. 150 | return theta. 151 | } 152 | 153 | function ETA_to_theta { 154 | 155 | parameter theta_test. 156 | 157 | local T_orbit to ship:orbit:period. 158 | local theta_ship to ship:orbit:trueanomaly. 159 | local e to ship:orbit:eccentricity. 160 | local GM to ship:body:mu. 161 | local a to ship:orbit:semimajoraxis. 162 | clearscreen. 163 | 164 | local EA_ship to 2*ARCTAN((TAN(theta_ship/2))/sqrt((1+e)/(1-e))). 165 | local MA_ship to EA_ship*constant:pi/180 - e*SIN(EA_ship). 166 | local EA_test to 2*ARCTAN((TAN(theta_test/2))/sqrt((1+e)/(1-e))). 167 | local MA_test to EA_test*constant:pi/180 - e*SIN(EA_test). 168 | local n to sqrt(GM/(a)^3). 169 | local eta_to_testpoint to (MA_test - MA_ship)/n. 170 | if eta_to_testpoint < 0 { 171 | set eta_to_testpoint to T_orbit + eta_to_testpoint. 172 | } 173 | 174 | // print "ETA to " + round(theta_test,2) + " degrees True Anomaly is " + round(eta_to_testpoint,2) + " seconds". 175 | // wait 2. 176 | return eta_to_testpoint. 177 | } 178 | 179 | function Apoapsis_Set_TimeAt { 180 | parameter AoP_timeat, DesiredOrbit. 181 | 182 | local body_pos to ship:body:position. 183 | local body_radius to ship:body:radius. 184 | local R to -body_pos. 185 | local SMA_ship to ship:orbit:semimajoraxis. 186 | local AngVel_ship to SMA_ship*VCRS(R,ship:velocity:orbit):normalized. 187 | local R_ap to body_radius + DesiredOrbit["APO"]. 188 | local R_aop_vec to positionat(ship,AoP_timeat) - body_pos. 189 | local R_aop to R_aop_vec:mag. 190 | local R_ap_vec to -1*R_ap*R_aop_vec:normalized. 191 | 192 | local SMA_new to (R_ap + R_aop)/2. 193 | local V_aop_speed to vis_via_speed(R_aop-body_radius,SMA_new). 194 | local temp_vec to VCRS(AngVel_ship,R_aop_vec):normalized. 195 | local V_aop_new_vec to V_aop_speed*temp_vec. 196 | 197 | local APO_node to SetNode_BurnVector(AoP_timeat,V_aop_new_vec). 198 | add APO_node. 199 | 200 | local delta_v_current to APO_node:burnvector:mag. 201 | local max_acc to availablethrust/mass. 202 | local burn_time to delta_v_current/max_acc. 203 | 204 | 205 | 206 | ExecuteNode(). 207 | // Debugging Vecdraws 208 | //set R_VEC_Draw to vecdraw(). 209 | //set R_VEC_Draw:startupdater to { return ship:body:position. }. 210 | //set R_VEC_Draw:vecupdater to { return R_ap_vec. }. 211 | //set R_VEC_Draw:show to true. 212 | //set R_VEC_Draw:color to RGB(0,0,255). 213 | 214 | wait 1. 215 | } 216 | 217 | function Periapsis_Set_TimeAt { 218 | parameter New_Apo_time, DesiredOrbit. 219 | 220 | local body_pos to ship:body:position. 221 | local R to -body_pos. 222 | local body_radius to ship:body:radius. 223 | local R_per_new to DesiredOrbit["PER"] + body_radius. 224 | local R_ap_new to positionat(ship,New_Apo_time) + R. 225 | local SMA_new to (R_ap_new:mag + R_per_new)/2. 226 | local V_ap_new_speed to vis_via_speed(R_ap_new:mag-body_radius,SMA_new). 227 | local V_ap_current_speed to velocityat(ship,New_Apo_time):orbit:mag. 228 | 229 | local delta_v_node to V_ap_new_speed - V_ap_current_speed. 230 | local PER_node to node(New_Apo_time,0,0,delta_v_node). 231 | add PER_node. 232 | 233 | ExecuteNode(). 234 | 235 | } 236 | 237 | function vis_via_speed { 238 | parameter R, a is ship:orbit:semimajoraxis. 239 | local R_val to ship:body:radius + R. 240 | return sqrt(ship:body:mu*(2/R_val - 1/a)). 241 | } 242 | 243 | function ExecuteNode { 244 | clearscreen. 245 | lock throttle to 0. 246 | SAS off. 247 | local Delta_V to nextnode:deltav:mag. 248 | local BurnTime to .5*Delta_V*mass/availablethrust. 249 | lock steering to nextnode. 250 | print "Aligning with Maneuver Node". 251 | until VANG(ship:facing:vector,nextnode:burnvector) < 1 { 252 | print "Direction Angle Error = " + round(VANG(ship:facing:vector,nextnode:burnvector),1) + " "at(0,1). 253 | } 254 | clearscreen. 255 | print "Alignment Complete". 256 | print "Warping to Burn Point". 257 | print "Burn Starts at T-minus " + round(BurnTime,2) + "secs ". 258 | warpto(time:seconds + nextnode:eta - BurnTime - 10). 259 | wait until warp <= 0. 260 | 261 | clearscreen. 262 | 263 | 264 | until Delta_V <= .01 { 265 | if nextnode:eta > BurnTime/2 { 266 | print "Burn Starts at T-minus " + round(nextnode:eta - BurnTime/2,2) + "secs " at(0,1). 267 | print "Delta V = " + round(Delta_V,1) + " " at(0,2). 268 | print "Throttle = " + MIN(100,round(throttle*100)) + "% " at(0,3). 269 | } else { 270 | set Delta_V to nextnode:deltav:mag. 271 | lock throttle to .5*Delta_V*mass/availablethrust. 272 | print "Initiate Burn " at(0,1). 273 | print "Delta V = " + round(Delta_V,2) + " " at(0,2). 274 | print "Throttle = " + MIN(100,round(throttle*100)) + "% " at(0,3). 275 | } 276 | } 277 | lock throttle to 0. 278 | unlock all. 279 | remove nextnode. 280 | clearscreen. 281 | print "Node Executed". 282 | wait 2. 283 | } 284 | 285 | function SetNode_BurnVector { 286 | parameter timeat,V_New. 287 | 288 | local V_timeat to velocityat(ship,timeat):orbit. 289 | 290 | local node_normal_vec to vcrs(ship:body:position,ship:velocity:orbit):normalized. 291 | local node_prograde_vec to V_timeat:normalized. 292 | local node_radial_vec to VCRS(node_normal_vec,node_prograde_vec). 293 | 294 | local burn_vector to (V_New - V_timeat). 295 | local burn_prograde to VDOT(node_prograde_vec,burn_vector). 296 | local burn_normal to VDOT(node_normal_vec,burn_vector). 297 | local burn_radial to VDOT(node_radial_vec,burn_vector). 298 | 299 | return NODE(timeat,burn_radial,burn_normal,burn_prograde). 300 | } 301 | 302 | local LAN_ship to ship:orbit:LAN. 303 | local INC_ship to ship:orbit:inclination. 304 | local AOP_ship to ship:orbit:argumentofperiapsis. 305 | local PER_ship to ship:orbit:periapsis. 306 | local APO_ship to ship:orbit:apoapsis. 307 | local default_DesiredOrbit to lexicon("LAN",LAN_ship,"INC",INC_ship,"AOP",AOP_ship,"PER",PER_ship,"APO",APO_ship). 308 | 309 | parameter DesiredOrbit is lexicon("LAN",LAN_ship,"INC",INC_ship,"AOP",AOP_ship,"PER",PER_ship,"APO",APO_ship). 310 | 311 | for key in default_DesiredOrbit:keys { 312 | if not DesiredOrbit:haskey(key) { set DesiredOrbit[key] to default_DesiredOrbit[key]. } 313 | } 314 | clearscreen. 315 | print DesiredOrbit. 316 | wait 2. 317 | 318 | clearscreen. 319 | clearvecdraws(). 320 | for n in allnodes { remove n.} 321 | local tolerance_angle to 0.01. 322 | local LAN_diff to abs(DesiredOrbit["LAN"] - LAN_ship). 323 | local INC_diff to abs(DesiredOrbit["INC"] - INC_ship). 324 | 325 | if LAN_diff < tolerance_angle AND INC_diff < tolerance_angle { 326 | 327 | print "No Change to Inclination or LAN". 328 | wait 2. 329 | 330 | } else { 331 | 332 | if LAN_diff > tolerance_angle { 333 | print "LAN is above tolerance with a difference of " + round(LAN_diff,3) + " degrees". 334 | } 335 | if INC_diff > tolerance_angle { 336 | print "INC is above tolerance with a difference of " + round(INC_diff,3) + " degrees". 337 | } 338 | print "Running Change_LAN_Inc". 339 | for n in allnodes { remove n.} 340 | wait 5. 341 | Change_LAN_Inc(DesiredOrbit). 342 | wait 1. 343 | for n in allnodes { remove n.} 344 | } 345 | local AOP_ship to ship:orbit:argumentofperiapsis. 346 | local PER_ship to ship:orbit:periapsis. 347 | local APO_ship to ship:orbit:apoapsis. 348 | 349 | local AOP_diff to abs(AOP_ship - DesiredOrbit["AOP"]). 350 | local APO_diff to abs(APO_ship - DesiredOrbit["APO"]). 351 | local PER_diff to abs(PER_ship - DesiredOrbit["PER"]). 352 | 353 | local AOP_diff_percent to 100*(1 - AOP_diff/DesiredOrbit["AOP"]). 354 | local APO_diff_percent to 100*(APO_diff/DesiredOrbit["APO"]). 355 | local PER_diff_percent to 100*(PER_diff/DesiredOrbit["PER"]). 356 | 357 | local tolerance_percent to 0.05. 358 | 359 | if AOP_diff_percent < tolerance_percent AND APO_diff_percent < tolerance_percent AND PER_diff_percent < tolerance_percent { 360 | 361 | print "No Change to Argument of Periapsis, Apoapsis, or Periapsis". 362 | wait 2. 363 | 364 | } else { 365 | 366 | if AOP_diff_percent > tolerance_percent { 367 | print "AoP is above tolerance with a difference of " + round(AOP_diff,3) + "%". 368 | } 369 | if APO_diff_percent > tolerance_percent { 370 | print "Apoapsis is above tolerance with a difference of " + round(APO_diff_percent,3) + "%". 371 | } 372 | if PER_diff_percent > tolerance_percent { 373 | print "Periapsis is above tolerance with a difference of " + round(PER_diff_percent,3) + "%". 374 | } 375 | 376 | print "Running Change_AoP_PerApo". 377 | wait 5. 378 | for n in allnodes { remove n.} 379 | Change_AoP_PerApo(DesiredOrbit). 380 | wait 1. 381 | for n in allnodes { remove n.} 382 | 383 | } 384 | clearvecdraws(). -------------------------------------------------------------------------------- /docking_helper.ks: -------------------------------------------------------------------------------- 1 | SAS OFF. 2 | RCS ON. 3 | lock steering to (-1*target:facing:vector):direction. 4 | until VANG(ship:facing:vector,(-1*target:facing:vector)) < 1 { 5 | print "Direction Angle Error = " + round(VANG(ship:facing:vector,(-1*target:facing:vector)),1) + " "at(0,1). 6 | } 7 | list parts in p_list. 8 | for part in p_list { 9 | if part:tag = "MainDockingPort" { 10 | set DP_part to part. 11 | } 12 | } 13 | 14 | set Kp_star to 1. 15 | set Ki_star to 0. 16 | set Kd_star to 10. 17 | clearscreen. 18 | clearvecdraws(). 19 | 20 | set PID_star to PIDloop(Kp_star,Ki_star,Kd_star,-1.0,1.0). 21 | set PID_top to PIDloop(Kp_star,Ki_star,Kd_star,-1.0,1.0). 22 | set PID_fore to PIDloop(Kp_star,Ki_star,Kd_star,-1.0,1.0). 23 | 24 | set PID_star:setpoint to 0. 25 | set PID_top:setpoint to 0. 26 | set PID_fore:setpoint to 0. 27 | 28 | set fore_dist to 25. 29 | 30 | lock star_error to -1*VDOT(DP_part:facing:starvector,vector5). 31 | lock top_error to -1*VDOT(DP_part:facing:topvector,vector5). 32 | lock fore_error to fore_dist - VDOT(DP_part:facing:vector,vector5). 33 | 34 | set vec1 to VECDRAW(V(0,0,0),V(0,0,0),red,"FRONT",1.0,TRUE,0.2). 35 | set vec2 to VECDRAW(V(0,0,0),V(0,0,0),green,"FRONT",1.0,FALSE,0.2). 36 | set vec3 to VECDRAW(V(0,0,0),V(0,0,0),blue,"TOP",1.0,TRUE,0.2). 37 | set vec4 to VECDRAW(V(0,0,0),V(0,0,0),green,"STAR",1.0,TRUE,0.2). 38 | set vec5 to VECDRAW(V(0,0,0),V(0,0,0),white,"TARGET",1.0,TRUE,0.2). 39 | 40 | set Phase to 1. 41 | set dockingmode to 0. 42 | until false { 43 | set vector1 to (target:position:mag)*DP_part:facing:vector. 44 | set vector2 to target:facing:vector. 45 | set vector3 to (target:position:mag)*DP_part:facing:topvector. 46 | set vector4 to (target:position:mag)*DP_part:facing:starvector. 47 | set vector5 to target:position - DP_part:position. 48 | 49 | set vec1:start to DP_part:position. 50 | set vec2:start to target:position. 51 | set vec3:start to DP_part:position. 52 | set vec4:start to DP_part:position. 53 | set vec5:start to DP_part:position. 54 | 55 | set vec1:vec to vector1. 56 | set vec2:vec to vector2. 57 | set vec3:vec to vector3. 58 | set vec4:vec to vector4. 59 | set vec5:vec to vector5. 60 | 61 | if target:istype("Part") { 62 | set relvelocity to ship:velocity:orbit - target:ship:velocity:orbit. 63 | } else { 64 | set relvelocity to ship:velocity:orbit - target:velocity:orbit. 65 | } 66 | 67 | set star_speed to VDOT(DP_part:facing:starvector,relvelocity). 68 | set top_speed to VDOT(DP_part:facing:topvector,relvelocity). 69 | set fore_speed to VDOT(DP_part:facing:vector,relvelocity). 70 | if Phase = 1 { 71 | set ship:control:top to 0. 72 | set ship:control:starboard to 0. 73 | set ship:control:fore to PID_fore:update(time:seconds,fore_error). 74 | if abs(fore_speed) < .1 AND abs(fore_error) < 1 { 75 | set Phase to 2. 76 | set dockingmode to 1. 77 | } 78 | } 79 | 80 | 81 | if Phase = 2 { 82 | if dockingmode = 1 { 83 | set ship:control:starboard to PID_star:update(time:seconds,star_error). 84 | set ship:control:top to 0. 85 | set ship:control:fore to 0. 86 | 87 | if ABS(star_speed) < .1 AND ABS(star_error) < .1 { 88 | set dockingmode to 2. 89 | } 90 | } 91 | 92 | if dockingmode = 2 { 93 | set ship:control:top to PID_top:update(time:seconds,top_error). 94 | set ship:control:starboard to PID_star:update(time:seconds,star_error). 95 | set ship:control:fore to 0. 96 | 97 | if ABS(top_speed) < .1 AND ABS(top_error) < .1 { 98 | set dockingmode to 3. 99 | } 100 | } 101 | 102 | if dockingmode = 3 { 103 | set ship:control:top to PID_top:update(time:seconds,top_error). 104 | set ship:control:starboard to PID_star:update(time:seconds,star_error). 105 | set ship:control:fore to PID_fore:update(time:seconds,fore_error). 106 | if abs(fore_speed) < .1 AND abs(fore_error) < 1 { 107 | set dockingmode to 4. 108 | } 109 | } 110 | if dockingmode = 4 { 111 | set ship:control:top to PID_top:update(time:seconds,top_error). 112 | set ship:control:starboard to PID_star:update(time:seconds,star_error). 113 | set ship:control:fore to PID_fore:update(time:seconds,fore_error). 114 | set fore_dist to .5*vector5:mag. 115 | } 116 | } 117 | print "Docking Mode " + dockingmode + " Phase " + Phase at (0,0). 118 | print "top_error = " + round(top_error,2) + " "at (0,1). 119 | print "top_control = " + round(100*ship:control:top,2) + "% " at (0,2). 120 | print "star_error = " + round(star_error,2) + " "at (0,3). 121 | print "star_control = " + round(100*ship:control:starboard,2) + "% " at (0,4). 122 | print "fore_error = " + round(fore_error,2) + " "at (0,5). 123 | print "fore_control = " + round(100*ship:control:fore,2) + "% " at (0,6). 124 | 125 | wait 0. 126 | } -------------------------------------------------------------------------------- /geneticlaunch.ks: -------------------------------------------------------------------------------- 1 | clearscreen. 2 | set ship:control:pilotmainthrottle to 0. 3 | print "First Phase". 4 | 5 | set a1 to 9.743. 6 | set b1 to -233.1. 7 | set c1 to 1292. 8 | set a2 to 132.3. 9 | set b2 to -30060. 10 | set c2 to 32720. 11 | set a3 to 50.25. 12 | set b3 to 19350. 13 | set c3 to 22290. 14 | set a4 to 31.61. 15 | set b4 to 39210. 16 | set c4 to 14840. 17 | 18 | set thrust to 0.422652479755061. 19 | set alt1 to 29516.50. 20 | set qswitch to 0.301224691747042. 21 | set etaSSing to 255.057279755142. 22 | // lock pitch to a1*(constant:e)^(-((altitude-b1)/c1)^2) + a2*(constant:e)^(-((altitude-b2)/c2)^2) + a3*(constant:e)^(-((altitude-b3)/c3)^2) + a4*(constant:e)^(-((altitude-b4)/c4)^2). 23 | //lock pitch to a1*(constant:e)^(-((altitude-b1)/c1)^2) + a2*(constant:e)^(-((altitude-b2)/c2)^2) + a3*(constant:e)^(-((altitude-b3)/c3)^2) + a4*(constant:e)^(-((altitude-b4)/c4)^2). 24 | lock steering to heading(90,min(90,max(0,pitch))). 25 | lock throttle to thrust. 26 | stage. 27 | WHEN (ship:maxthrust < 1) AND (eta:apoapsis < etaSSing) THEN { 28 | stage. 29 | wait .1. 30 | lock throttle to 1. 31 | preserve. 32 | } 33 | wait until altitude >= alt1. 34 | 35 | set a1 to 44.41. 36 | set b1 to 2.5040. 37 | set c1 to 8820. 38 | set a2 to 35.4. 39 | set b2 to 36760. 40 | set c2 to 9304. 41 | set a3 to -255.8. 42 | set b3 to 51720. 43 | set c3 to 9093. 44 | set a4 to -0.252. 45 | set b4 to 39150. 46 | set c4 to 503.9. 47 | set a5 to 279.8. 48 | set b5 to 51630. 49 | set c5 to 9372. 50 | 51 | lock pitch to a1*(constant:e)^(-((altitude-b1)/c1)^2) + a2*(constant:e)^(-((altitude-b2)/c2)^2) + a3*(constant:e)^(-((altitude-b3)/c3)^2) + a4*(constant:e)^(-((altitude-b4)/c4)^2) + a5*(constant:e)^(-((altitude-b5)/c5)^2). 52 | 53 | print "surface prograde". 54 | set qper to 1. 55 | set MaxQ to 0. 56 | until qper < qswitch { 57 | if ship:q > MaxQ { set MaxQ to ship:q. } 58 | set qper to ship:q/MaxQ. 59 | } 60 | print "switch to orbital prograde". 61 | wait until apoapsis > 100000. 62 | lock throttle to 0. 63 | unlock all. 64 | -------------------------------------------------------------------------------- /horizontal_landing.ks: -------------------------------------------------------------------------------- 1 | //WARNING COMPATIBILITY CHECK 2 | //-This script is only ment to work on non-atmosphere bodies, have not tested or run this on atmosphere bodies. 3 | //-Only works if the ship does not have to stage in the middle of the landing burn. Otherwise all calculations might be thrown off 4 | //-Only works if the ship is at near 0 starting inclination and very circular 5 | 6 | // Execute Node Function that I use for maneuver nodes 7 | declare function ExecuteNode { 8 | clearscreen. 9 | lock throttle to 0. 10 | SAS off. 11 | lock DeltaV to nextnode:deltav:mag. 12 | set BurnTime to .5*DeltaV*mass/availablethrust. 13 | lock steering to nextnode. 14 | print "Aligning with Maneuver Node". 15 | until VANG(ship:facing:vector,nextnode:burnvector) < 1 { 16 | print "Direction Angle Error = " + round(VANG(ship:facing:vector,nextnode:burnvector),1) + " "at(0,1). 17 | } 18 | clearscreen. 19 | print "Warping to Node". 20 | print "Burn Starts at T-minus " + round(BurnTime,2) + "secs ". 21 | warpto(time:seconds + nextnode:eta - BurnTime - 10). 22 | wait until BurnTime >= nextnode:eta. 23 | 24 | clearscreen. 25 | lock throttle to DeltaV*mass/availablethrust. 26 | print "Executing Node". 27 | 28 | until DeltaV <= .1 { 29 | print "Delta V = " + round(DeltaV,1) + " " at(0,1). 30 | print "Throttle = " + MIN(100,round(throttle*100)) + "% " at(0,2). 31 | } 32 | lock throttle to 0. 33 | unlock all. 34 | remove nextnode. 35 | clearscreen. 36 | print "Node Executed". 37 | } 38 | 39 | // Landing position 40 | CLEARVECDRAWS(). 41 | SAS OFF. 42 | //lock steering to srfretrograde. 43 | set landing_pos to LATLNG(0,120).// Where you want to land, currently can only be at 0 lattitude 44 | set g0 to ship:body:mu/(ship:body:radius)^2. 45 | set TWR to availablethrust/(mass*g0). 46 | set Fuel_Factor to 1.25. 47 | set landing_per_buffer to 2000. // How high above the landing postion do you want the periapsis of the transfer orbit to be. 48 | // NOTE: If this is too low your ship might crash because it starts to drop as it looses horizontal speed. 49 | // 500m worked very well for my test ship which had a starting Mun TWR of 5.91 50 | if ship:body:name = "Mun" { 51 | set landing_per_buffer to (50290*(TWR*Fuel_Factor)^(-2.232) + 222.1)*(0.955)^(landing_pos:terrainheight/2500). 52 | clearscreen. 53 | print landing_per_buffer. 54 | wait 1. 55 | } 56 | if ship:body:name = "Kerbin" { 57 | set landing_per_buffer to 40000. 58 | } 59 | if ship:body:name = "Duna" { 60 | set landing_per_buffer to 20000. 61 | } 62 | //if ship:body = Mars { 63 | // set landing_per_buffer to 15000. 64 | // } 65 | 66 | 67 | lock R_ship to ship:body:position. 68 | lock angle_diff_h to VANG(-R_ship, landing_pos:position - R_ship). 69 | lock dist_diff_h to (angle_diff_h/360)*2*(constant:pi)*R_ship:mag. // Converstion of the difference in angle to a distance 70 | lock Velocity_h_norm to VCRS(VCRS(R_ship,ship:velocity:orbit),R_ship):normalized. 71 | lock Speed_h to VDOT(Velocity_h_norm,ship:velocity:orbit). 72 | lock position_speed_h to landing_pos:altitudevelocity(altitude):orbit:mag. 73 | lock speed_diff_h to Speed_h-position_speed_h. // Converstion of the difference in angular speed to a speed difference 74 | clearscreen. 75 | 76 | // Calculte and set the maneuver node. The periapsis will be the preset landing periapsis buffer altitude above the ground at the landing point. 77 | if ship:body:name = "Mun" { 78 | set R_per_landing to ship:body:radius + max(4500*(ship:body:radius/200000),landing_pos:terrainheight + landing_per_buffer). 79 | } else { 80 | set R_per_landing to ship:body:radius + landing_per_buffer. 81 | } 82 | 83 | set SMA_landing to (R_ship:mag + R_per_landing)/2. 84 | set ecc_landing to (R_ship:mag - R_per_landing)/(R_ship:mag + R_per_landing). 85 | set V_apo to sqrt(((1-ecc_landing)*ship:body:MU)/((1+ecc_landing)*SMA_landing)). 86 | 87 | set TimePeriod_landing to 2*(constant:pi)*sqrt((SMA_landing^3)/(ship:body:mu)). 88 | 89 | set prev_dist_h to dist_diff_h. 90 | wait .1. 91 | set curr_dist_h to dist_diff_h. 92 | set delta_dist_h to curr_dist_h - prev_dist_h. // Check to see if you are infront of behind the desired maneuver node burn point 93 | 94 | if delta_dist_h > 0 { 95 | set eta_node to (TimePeriod_landing/2*position_speed_h)/speed_diff_h + ((constant:pi)*R_ship:mag-dist_diff_h)/speed_diff_h. 96 | if eta_node < 60 { 97 | set eta_node to (TimePeriod_landing/2*position_speed_h)/speed_diff_h + ((constant:pi)*R_ship:mag-dist_diff_h+(constant:pi)*R_ship:mag)/speed_diff_h. 98 | } 99 | } else { 100 | set eta_node to (TimePeriod_landing/2*position_speed_h)/speed_diff_h + ((constant:pi)*R_ship:mag+dist_diff_h)/speed_diff_h. 101 | } 102 | 103 | set deltaV_landing to V_apo - velocityat(ship,time:seconds + eta_node):orbit:mag. 104 | 105 | for node in allnodes {remove node.} 106 | set landing_node to NODE(TIME:seconds + eta_node, 0, 0, deltaV_landing). 107 | ADD landing_node. 108 | 109 | ExecuteNode(). 110 | // I have no idea why I have to retype all the variables I defined earlier but if I don't it gives me some strange errors that the variables aren't defined. 111 | // If anyone would like to help, you can comment from the next line to the "End of the commenting section" and try and run it. I hope you get the same error, and know how to fix it! 112 | lock steering to srfretrograde. 113 | set landing_pos to LATLNG(0,120). 114 | 115 | set buffer_speed_h to 0. 116 | set cutoffspeed_h to 25. 117 | //set landing_eta_buffer to 100. 118 | set CutOffThrottle to 0. // In percent 119 | set MaxCount to 5. 120 | 121 | lock R_ship to ship:body:position. 122 | lock angle_diff_h to VANG(-R_ship, landing_pos:position - R_ship). 123 | lock dist_diff_h to (angle_diff_h/360)*2*(constant:pi)*R_ship:mag. 124 | lock Velocity_h_norm to VCRS(VCRS(R_ship,ship:velocity:orbit),R_ship):normalized. 125 | lock Speed_h to VDOT(Velocity_h_norm,ship:velocity:orbit). 126 | lock speed_diff_h to Speed_h-landing_pos:altitudevelocity(altitude):orbit:mag. 127 | lock long_diff_dir to VCRS(landing_pos:position,R_ship):normalized. 128 | lock long_diff_h to VDOT(long_diff_dir,ship:velocity:surface). 129 | lock Velocity_diff_direction to (-1*(ship:velocity:orbit - landing_pos:altitudevelocity(altitude):orbit + long_diff_h*long_diff_dir)):direction. 130 | clearscreen. 131 | // End of error commenting section. 132 | // This is the heart of the function. The max horizontal acceleration is calculated as if the rocket is always in surface retrograde. 133 | // Maintaining surface retrograde maximizes efficiency when landing 134 | // Vmax_h is the maximum speed a ship can be traveling at its current distance to the target such that at full thrust it will reach the target with 0 velocity (aka suicide burn) 135 | // Vmax_h assumes the thrust is constant but updates it to the current max horizontal acceleration and uses a PD loop to deal with the changing TWR 136 | lock MaxThrustAccHor to -1*VDOT(Velocity_h_norm,availablethrust/mass*srfretrograde:vector). 137 | lock truealt to altitude - landing_pos:terrainheight. 138 | lock touchdown_time to (-verticalspeed - sqrt(verticalspeed^2 - 4*(-0.5*g0)*truealt))/(-1*g0). 139 | lock cutoffdist_h to speed_diff_h*touchdown_time. 140 | //set buffer_dist to 93.75. 141 | set buffer_dist to 0. 142 | lock Vmax_h to sqrt(MAX(0,2*(dist_diff_h - buffer_dist)*MaxThrustAccHor)). 143 | // Standard PD loop parameters 144 | lock error_h to Vmax_h - speed_diff_h. 145 | set errorP_h to 0. 146 | set Kp_h to 0.04. 147 | set errorD_h to 0. 148 | set Kd_h to 0.04. 149 | set ThrustSet to 0. 150 | set GravityTurnCorrection to 1.5/100. 151 | lock throttle to ThrustSet. 152 | set time0 to time:seconds. 153 | lock time1 to time:seconds - time0. 154 | set count to 1. 155 | set flightmode to 1. 156 | // Just a nice helping orientation so that your ship is already close to ready to go when it is done warping to the periapsis 157 | set align_vector to -1*landing_pos:altitudevelocity(altitude):orbit. 158 | lock steering to align_vector. 159 | print "Aligning with Surface Retrograde Preemptively". 160 | until VANG(ship:facing:vector,align_vector) < 1 { 161 | print "Direction Angle Error = " + round(VANG(ship:facing:vector,align_vector),1) + " "at(0,1). 162 | } 163 | clearscreen. 164 | set landing_eta_buffer to velocityat(ship,time:seconds + eta:periapsis):orbit:mag/(TWR*g0). 165 | print "Warping to " + round(landing_eta_buffer,0) + "sec before Periapsis". 166 | warpto(time:seconds + eta:periapsis - 1.075*landing_eta_buffer). 167 | 168 | set follow_mode to 1. 169 | lock steering to srfretrograde. 170 | clearscreen. 171 | until flightmode = 2 { 172 | if follow_mode = 1 { 173 | if ship:body:atm:exists { 174 | if ThrustSet > 0 { 175 | lock steering to Velocity_diff_direction. 176 | set follow_mode to 2. 177 | } 178 | } else { 179 | lock steering to Velocity_diff_direction. 180 | set follow_mode to 2. 181 | } 182 | } 183 | // A visual aid to show where the ship is supposed to land. 184 | set LandingVector to VECDRAW(landing_pos:position,(altitude-landing_pos:terrainheight+25)*(landing_pos:position-R_ship):normalized,GREEN,"Landing Position",1.0,TRUE,.5). 185 | set SideslipVector to VECDRAW(V(0,0,0),10*long_diff_h*long_diff_dir,GREEN,"Sideslip Component",1.0,TRUE,.5). 186 | if flightmode = 1 { 187 | // Main PD loop for the thrust control 188 | set error1_h to error_h. 189 | set dist1 to dist_diff_h. 190 | set t1 to time1. 191 | wait .00001. 192 | set error2_h to error_h. 193 | set dist2 to dist_diff_h. 194 | set t2 to time1. 195 | set dt to t2-t1. 196 | // I like to take an average error so its not going crazy due to discrete calculations. 197 | set errorP_h to .5*(error1_h+error2_h). 198 | set errorD_h_test to (error2_h-error1_h)/dt. 199 | //This next part is used as a running average, the Derivative term was behaving eratically thus this damps out the spikes. 200 | if count < MaxCount { 201 | if count < 2 { 202 | set errorD_h to errorD_h_test. 203 | } 204 | if count >= 2 { 205 | set errorD_h to (errorD_h*(count-1)+errorD_h_test)/count. 206 | } 207 | set count to count + 1. 208 | } 209 | if count >= MaxCount { 210 | 211 | set errorD_h to (errorD_h*(MaxCount-1)+errorD_h_test)/MaxCount. 212 | } 213 | 214 | set ThrustSet to 1 - Kp_h*errorP_h - Kd_h*errorD_h + GravityTurnCorrection. 215 | 216 | if ThrustSet > 1 { 217 | set ThrustSet to 1. 218 | } 219 | if dist2 > dist1 AND ship:obt:trueanomaly < 90 { 220 | set ThrustSet to 1. 221 | } 222 | // The Cut Off Thrust is used to help maximize efficiency. At 0 it is a nice smooth ramp up but if you make the fuel cut off higher it only turns on when its above this value and thus increases efficiency 223 | // since the ship will be burning at a higher throttle on average (100% throttle is the most efficient but that requires some more calculations). 224 | if ThrustSet < CutOffThrottle/100 { 225 | set ThrustSet to 0. 226 | } 227 | if errorP_h < 0 { 228 | set ThrustSet to 1. // This is very important. If the error ever drops below 0, it means it might crash since the 229 | // equation is calculated based on full thrust. 230 | } 231 | // Cut off conditions to switch to vertical landing portion of the controller 232 | if speed_diff_h < 0.1 { 233 | set ThrustSet to 0. 234 | set flightmode to 2. 235 | } 236 | if (dist_diff_h > (cutoffdist_h)) AND speed_diff_h < cutoffspeed_h { 237 | set ThrustSet to 0. 238 | set flightmode to 2. 239 | } 240 | } 241 | 242 | print "Horizontal Distance to Landing Site = " + round(dist_diff_h,2) + " "at(0,0). 243 | print "Speed relative to Landing Site = " + round(speed_diff_h,2) at(0,1). 244 | print "MaxThrustAccHor = " + round(MaxThrustAccHor,2) at(0,2). 245 | print "Vmax_h = " + round(Vmax_h,2) at(0,3). 246 | print "errorP_h = " + round(errorP_h,2) + " " at(0,4). 247 | print "errorD_h = " + round(errorD_h,2) + " " at(0,5). 248 | print "ThrustSet = " + round(ThrustSet*100,2) + "% " at(0,7). 249 | print "Flightmode = " + flightmode at(0,8). 250 | print "cutoffdist_h = " + round(cutoffdist_h,2) + " " at(0,9). 251 | print "Distance to target cutoff = " + round(cutoffdist_h - dist_diff_h,2) + " " at(0,10). 252 | print "follow_mode = " + follow_mode at(0,11). 253 | print "long_diff_h = " + round(long_diff_h,2) + " " at(0,12). 254 | } 255 | run vertical_landing(landing_pos,TRUE). -------------------------------------------------------------------------------- /hover.ks: -------------------------------------------------------------------------------- 1 | set kp to .001. 2 | set ki to .0001. 3 | set kd to 0. 4 | 5 | set ship:control:pilotmainthrottle to 0. 6 | stage. 7 | SAS on. 8 | clearscreen. 9 | 10 | set PID to PIDloop(kp,ki,kd). 11 | lock g to ship:body:mu/(ship:body:position:mag)^2. 12 | lock TWR to (availablethrust/mass)/g. 13 | set thrust to 0. 14 | lock throttle to thrust. 15 | set PID:setpoint to 100. 16 | until false { 17 | 18 | set thrust to g*mass/availablethrust + PID:update(time:seconds,altitude). 19 | 20 | print round(PID:error,2) at (0,1). 21 | print round(PID:output,2) at (0,2). 22 | print round(g,2) at (0,3). 23 | print round(PID:Pterm,2) at (0,4). 24 | print round(PID:Iterm,2) at (0,5). 25 | print round(PID:Dterm,2) at (0,6). 26 | 27 | } -------------------------------------------------------------------------------- /hyst_test.ks: -------------------------------------------------------------------------------- 1 | lock steering to up. 2 | 3 | declare function Hysteresis { 4 | declare parameter input,prev_output, right_hand_limit, left_hand_limit,right_hand_output is true. 5 | set output to prev_output. 6 | if prev_output = right_hand_output { 7 | if input <= left_hand_limit { 8 | set output to not(right_hand_output). 9 | } 10 | } else { 11 | if input >= right_hand_limit { 12 | set output to right_hand_output. 13 | } 14 | } 15 | return output. 16 | } 17 | //Hyst Test 18 | //set test_out to Hysteresis(75,false,100,50,true). 19 | //print test_out. 20 | //set test_out to Hysteresis(101,test_out,100,50,true). 21 | //print test_out. 22 | //set test_out to Hysteresis(75,test_out,100,50,true). 23 | //print test_out. 24 | //set test_out to Hysteresis(25,test_out,100,50,true). 25 | //print test_out. 26 | 27 | lock default_throttle to mass*9.81/availablethrust. 28 | set throttle_check to true. 29 | set right_hand_limit to 100. 30 | set left_hand_limit to 90. 31 | clearscreen. 32 | until false { 33 | 34 | set throttle_check to Hysteresis(altitude,throttle_check,right_hand_limit,left_hand_limit,false). 35 | if throttle_check { 36 | lock throttle to default_throttle*1.1. 37 | } else { 38 | lock throttle to default_throttle*0.9. 39 | } 40 | 41 | print throttle_check at(0,0). 42 | print round(altitude,0) at(0,1). 43 | print round(100*throttle,0) at(0,2). 44 | } 45 | 46 | -------------------------------------------------------------------------------- /impact_locator.ks: -------------------------------------------------------------------------------- 1 | // Function used to determine the first point of impact of a rocket on a ballistic/suborbital trajectory 2 | local drawvec_check to true. 3 | local Body_Ang_speed to 360/ship:body:rotationperiod. 4 | 5 | function Height_At_Position { 6 | parameter test_position. 7 | local body_pos to ship:body:position. 8 | local body_R to ship:body:radius. 9 | local body_test_position to test_position - body_pos. 10 | local H to body_test_position:mag - body_R. 11 | return H. 12 | } 13 | function Impact_locator { 14 | local Ttest_ltln is LATLNG(0,0). 15 | if periapsis > 0 { 16 | clearscreen. 17 | print "No impact detected". 18 | } else { 19 | 20 | local T0 is time:seconds. 21 | 22 | local Tp is eta:periapsis. 23 | 24 | local Ttest is Tp/2. 25 | 26 | local T1 is 0. 27 | local T2 is Tp. 28 | 29 | if drawvec_check { 30 | set Ttest_vec_Draw to vecdraw(). 31 | set Ttest_vec_Draw:startupdater to { return V(0,0,0). }. 32 | set Ttest_vec_Draw:vecupdater to { return positionat(ship,T0 + Ttest). }. 33 | set Ttest_vec_Draw:show to true. 34 | set Ttest_vec_Draw:color to RGB(255,0,0). 35 | } 36 | clearscreen. 37 | set impact_found to false. 38 | local count to 0. 39 | local iprint to 3. 40 | until impact_found { 41 | local time_offset to time:seconds - T0. 42 | local eta_impact to Ttest - time_offset. 43 | local long_offset to eta_impact*Body_Ang_speed. // For the future this needs to be checked for prograde or retrograde 44 | local Ttest_vec to positionat(ship,T0 + Ttest). 45 | set Ttest_ltln to ship:body:geopositionof(Ttest_vec). 46 | set Ttest_ltln to LATLNG(Ttest_ltln:LAT,Ttest_ltln:LNG - long_offset). 47 | 48 | local Ttest_H to Height_At_Position(Ttest_vec). 49 | local error to Ttest_H - Ttest_ltln:terrainheight. 50 | 51 | set iprint to 3. 52 | print "Error " + round(error,2) + " " at(0,iprint). 53 | set iprint to iprint + 1. 54 | print "Ttest_ltln:LAT " + round(Ttest_ltln:LAT,3) + " " at(0,iprint). 55 | set iprint to iprint + 1. 56 | print "Ttest_ltln:LNG " + round(Ttest_ltln:LNG,3) + " " at(0,iprint). 57 | set iprint to iprint + 1. 58 | print "count " + count + " " at(0,iprint). 59 | set iprint to iprint + 1. 60 | print "eta_impact " + round(eta_impact,2) + " " at(0,iprint). 61 | 62 | // wait 1. 63 | set count to count + 1. 64 | 65 | if abs(error) < 0.1 { 66 | set impact_found to true. 67 | } 68 | 69 | if error > 0 { 70 | set T1 to Ttest. 71 | set Ttest to (T1 + T2)/2. 72 | } else { 73 | set T2 to Ttest. 74 | set Ttest to (T1 + T2)/2. 75 | } 76 | } 77 | //until false { 78 | // local time_offset to time:seconds - T0. 79 | // local eta_impact to Ttest - time_offset. 80 | // print "eta_impact " + round(eta_impact,2) + " " at(0,iprint). 81 | //} 82 | } 83 | 84 | return Ttest_ltln. 85 | } 86 | 87 | -------------------------------------------------------------------------------- /inclinationmatch.ks: -------------------------------------------------------------------------------- 1 | // This script is for matching inclination of a target around the same body 2 | 3 | clearscreen. 4 | 5 | set DV_tol to 0.1. 6 | set DA_tol to .01. 7 | if hasnode { 8 | for node in allnodes {remove node.} 9 | } 10 | lock Ship_angvel to VCRS(ship:velocity:orbit,(ship:position-ship:body:position)). 11 | lock Target_angvel to VCRS(target:velocity:orbit,(target:position-ship:body:position)). 12 | set asc_node_vec to VCRS(Ship_angvel,Target_angvel). 13 | lock Ship_ecc to ship:orbit:eccentricity. 14 | lock Ship_TA to ship:orbit:trueanomaly. 15 | set vec1 to VCRS((-1*ship:body:position),asc_node_vec):normalized+Ship_angvel:normalized. 16 | set ang to VANG(asc_node_vec,(-1*ship:body:position)). 17 | if vec1:mag > 1 { 18 | set asc_node_TA to Ship_TA - ang. 19 | if asc_node_TA < 0 { 20 | set asc_node_TA to 360 + asc_node_TA. 21 | } 22 | if asc_node_TA > 360 { 23 | set asc_node_TA to asc_node_TA - 360. 24 | } 25 | } else { 26 | set asc_node_TA to Ship_TA + ang. 27 | if asc_node_TA < 0 { 28 | set asc_node_TA to 360 + asc_node_TA. 29 | } 30 | if asc_node_TA > 360 { 31 | set asc_node_TA to asc_node_TA - 360. 32 | } 33 | } 34 | 35 | 36 | set Ship_EA to 2*ARCTAN((TAN(Ship_TA/2))/sqrt((1+Ship_ecc)/(1-Ship_ecc))). 37 | set Ship_MA to Ship_EA*constant:pi/180 - Ship_ecc*SIN(Ship_EA). 38 | set asc_node_EA to 2*ARCTAN((TAN(asc_node_TA/2))/sqrt((1+Ship_ecc)/(1-Ship_ecc))). 39 | set asc_node_MA to asc_node_EA*constant:pi/180 - Ship_ecc*SIN(asc_node_EA). 40 | set n to sqrt(ship:body:mu/(ship:orbit:semimajoraxis)^3). 41 | set asc_node_eta to (asc_node_MA-Ship_MA)/n. 42 | 43 | if asc_node_eta < 0 { 44 | set asc_node_eta to ship:orbit:period + asc_node_eta. 45 | } 46 | 47 | set mynode to NODE(TIME:seconds + asc_node_eta, 0, 0, 0). 48 | ADD mynode. 49 | 50 | lock delta_ang to VANG(Ship_angvel,Target_angvel). 51 | set delta_v_check to 2*(VELOCITYAT(ship,time:seconds + asc_node_eta):orbit:mag)*sin(delta_ang/2). 52 | lock Burn_dir to (-1*Ship_angvel):direction. 53 | lock steering to Burn_dir. 54 | print "Aligning to Burn Vector". 55 | until VANG(ship:facing:vector,Burn_dir:vector) < 1 { 56 | print "Direction Alignment Error = " + round(VANG(ship:facing:vector,Burn_dir:vector),1) + " "at(0,1). 57 | } 58 | lock acc to maxthrust/mass. 59 | lock Burn_time to delta_v_check/acc. 60 | warpto(time:seconds + mynode:eta - Burn_time/2 - 15). 61 | 62 | print "True Anomaly of Ascending Node = " + round(asc_node_TA). 63 | print "ETA to Ascending Node = " + round(asc_node_eta). 64 | print "EA of Ascending Node = " + round(asc_node_EA). 65 | print "MA of Ascending Node = " + round(asc_node_MA). 66 | print "EA of Ship = " + round(Ship_EA). 67 | print "MA of Ship = " + round(Ship_MA). 68 | print " ". 69 | print "Delta V = " + round(delta_v_check). 70 | print "Burn Time = " + round(Burn_time/2). 71 | print "Warp to Time = T-" + round(Burn_time/2 + 15). 72 | lock delta_v_check to 2*(ship:velocity:orbit:mag)*sin(delta_ang/2). 73 | set delta_ang_der to -1. 74 | set delta_ang_der_check to 0. 75 | until delta_v_check < DV_tol { 76 | 77 | if delta_ang_der_check > 0 { 78 | break. 79 | } 80 | if mynode:eta > Burn_time/2 { 81 | lock throttle to 0. 82 | } 83 | else { 84 | if delta_v_check*mass/maxthrust > 1 { 85 | lock throttle to 1. 86 | } 87 | else { 88 | lock throttle to delta_v_check*mass/maxthrust. 89 | } 90 | set delta_ang_1 to delta_ang. 91 | wait .1. 92 | set delta_ang_2 to delta_ang. 93 | set delta_ang_der to delta_ang_2-delta_ang_1. 94 | if delta_ang_der > 0 { 95 | set delta_ang_der_check to 1. 96 | lock throttle to 0. 97 | } 98 | } 99 | print "Delta V Left = " + round(delta_v_check,1) + " " at(0,10). 100 | print "Throttle = " + round(throttle*100) + "% " at(0,11). 101 | print "Delta Angle = " + round(delta_ang,2) + " " at(0,12). 102 | print "Angle Derivative = " + round(delta_ang_der_check) at(0,13). 103 | set Arrow1 to VECDRAW(ship:position,(Ship_angvel:normalized)*20,RGB(1,0,0),"Ship AngVel",1,TRUE,.5). 104 | set Arrow2 to VECDRAW(ship:position,(Target_angvel:normalized)*20,RGB(0,1,0),"Target AngVel",1,TRUE,.5). 105 | } 106 | lock throttle to 0. 107 | 108 | if delta_v_check < DV_tol { 109 | print "Delta V less than " + round(DV_tol,2) + "m/s" at(0,20). 110 | } else if delta_ang_der > 0 { 111 | print "Broke because of increasing angle" at(0,20). 112 | } 113 | clearvecdraws(). 114 | for node in allnodes{remove node.} 115 | wait 3. -------------------------------------------------------------------------------- /landing.ks: -------------------------------------------------------------------------------- 1 | declare parameter LandingPeriapsis is 10000,CutOffSpeed is 25,CutOffThrottle is 0. 2 | clearscreen. 3 | // This sets some pre launch parameters such as determining what the true altiude is of the base of the rocket. 4 | set ship:control:pilotmainthrottle to 0. 5 | set TouchDownSpeed to 5. // This is set by the user, I set it to 5 since the landing legs break at 6. 6 | set MaxCount to 3. // Used to average the derivative term since it can get pretty eratic 7 | set buffer_alt to 20. // Its not perfect, so a little wiggle room is good to retract the legs. 8 | lock true_alt to altitude - ship:geoposition:terrainheight.// - start_alt. // Again measured from the bottom of the craft. 9 | // This script is meant to be used from a flat surface to launch and return. It can be adapted for landing from any situation. 10 | SAS off. 11 | GEAR OFF. 12 | lock steering to retrograde. 13 | print "Aligning with Orbit Retrograde". 14 | wait 15. 15 | print "Burning to Drop Periapsis to " + round(LandingPeriapsis,2). 16 | lock throttle to 1 - (.9*LandingPeriapsis)/periapsis. 17 | wait until periapsis <= LandingPeriapsis. 18 | lock throttle to 0. 19 | wait 1. 20 | print "Warping to Periapsis". 21 | warpto(time:seconds + eta:periapsis - 30). 22 | lock V to ship:velocity:orbit. 23 | lock R to ship:body:position. 24 | lock Vper to VDOT(VCRS(R,VCRS(V,R)):direction:vector,V). 25 | lock AccelCent to (Vper^2)/R:mag. 26 | // After it goes up high the rocket will wait to fall back down. 27 | // I manually select the retrograde selection on the SAS. I would do it with the cooked steering but its current 28 | // iteration was not working well with the test ship. 29 | lock MaxThrustAccUp to VDOT(UP:vector,availablethrust/mass*srfretrograde:vector). 30 | // This assumes the ship is pointed exactly retrograde. Meaning this can be used as a gravity turn for landing as well. 31 | lock GravUp to (-1)*(ship:body:mu)/((R:mag)^2). 32 | 33 | lock MaxAccUp to MaxThrustAccUp + GravUp + AccelCent. // I opted out of adding drag since its finiky, this adds some safety margin though 34 | // log "1" to landingdata.csv. 35 | // delete landingdata.csv. 36 | // log "Time,Vmax,Vvert,Altitude,Error,ThrustSet,MaxAccUp" to landingdata.csv. 37 | // Log various variables to view. This can be changed to your liking or commented out if you don't need it. 38 | //wait until verticalspeed < -20. // Just to make sure there are no weird transition errors. 39 | 40 | lock FPAsurf to 90 - VANG(UP:vector,ship:velocity:surface). 41 | 42 | clearscreen. 43 | lock Vmax to sqrt(MAX(0,2*(true_alt-buffer_alt)*MaxAccUp + TouchDownSpeed^2)). 44 | // The magic of the script. This equation is derived assuming an ascent starting at the touchdown speed and accelerating 45 | // at full throttle. It auto adjusts based on the altitude and the Max Acceleration as it changes with mass loss. 46 | // Basic PD loop. I want essentially no overshoot and very little error at the end. The Kp_v and Kd_v gains are tuned so at the finish 47 | // of the script the error > 0 and absolutely no overshoot. Tune to your liking however (fair warning, you have VERY little margin 48 | // when you are landing. The burn times I have seen are very short. That depends on the ship's TWR however. 49 | lock error_v to Vmax + verticalspeed. 50 | set errorP_v to 0. 51 | set Kp_v to .04. 52 | set errorD_v to 0. 53 | set Kd_v to 0.04. 54 | set ThrustSet to 0. 55 | lock throttle to ThrustSet. 56 | set time0 to time:seconds. 57 | lock time1 to time:seconds - time0. 58 | set count to 1. 59 | set flightmode to 1. 60 | lock steering to srfretrograde. 61 | until flightmode = 2 AND ship:status = "LANDED" { 62 | 63 | if verticalspeed > 0 OR ship:orbit:trueanomaly <= 180 { 64 | set ThrustSet to 1. 65 | wait until ship:velocity:surface:mag <= CutOffSpeed. 66 | set ThrustSet to 0. 67 | GEAR on. 68 | } 69 | 70 | if flightmode = 1 AND true_alt < 100 AND ship:velocity:surface:mag < TouchDownSpeed AND GroundSpeed < 1 { 71 | lock steering to up. 72 | lock throttle to .99*mass*-1*GravUp/availablethrust. 73 | set flightmode to 2. 74 | } 75 | 76 | if flightmode = 1 { 77 | 78 | set error1 to error_v. 79 | set t1 to time1. 80 | wait .00001. 81 | set error2 to error_v. 82 | set t2 to time1. 83 | set dt to t2-t1. 84 | // I like to take an average error so its not going crazy due to discrete calculations. 85 | set errorP_v to .5*(error1+error2). 86 | set errorD_v_test to (error2-error1)/dt. 87 | //This next part is used as a running average, the Derivative term was behaving eratically thus this damps out the spikes. 88 | if count < MaxCount { 89 | if count < 2 { 90 | set errorD_v to errorD_v_test. 91 | } 92 | if count >= 2 { 93 | set errorD_v to (errorD_v*(count-1)+errorD_v_test)/count. 94 | } 95 | set count to count + 1. 96 | } 97 | if count >= MaxCount { 98 | 99 | set errorD_v to (errorD_v*(MaxCount-1)+errorD_v_test)/MaxCount. 100 | } 101 | 102 | set ThrustSet to 1 - Kp_v*errorP_v - Kd_v*errorD_v. 103 | 104 | if ThrustSet > 1 { 105 | set ThrustSet to 1. 106 | } 107 | if ThrustSet < CutOffThrottle { 108 | set ThrustSet to 0. 109 | } 110 | if error_v < 0 { 111 | set ThrustSet to 1. // This is very important. If the error ever drops below 0, it means it might crash since the 112 | // equation is calculated based on full thrust. 113 | } 114 | } 115 | // Some data readouts. Pay attention to the Error term, make sure it doesn't drop below 0. 116 | 117 | print "Vmax = " + round(-1*Vmax,2) + " "at(0,0). 118 | print "VertSpeed = " + round(verticalspeed,2) + " " at (0,2). 119 | print "Radar Alt = " + round(true_alt,2) + " " at(0,4). 120 | print "Error Vert = " + round(error_v,2) + " " at(0,6). 121 | print "ThrustSet = " + round(ThrustSet,2) + " " at(0,8). 122 | print "GravUp = " + round(GravUp,2) + " " at(0,10). 123 | print "AccelCent = " + round(AccelCent,2) + " " at(0,12). 124 | print "MaxThrustAccUp = " + round(MaxThrustAccUp,2) + " " at(0,14). 125 | print "MaxAccUp = " + round(MaxAccUp,2) + " " at (0,16). 126 | print "FlightMode = " + flightmode + " " at (0,18). 127 | print "GroundSpeed= " + round(GroundSpeed,2) + " " at (0,20). 128 | //log round(time1,3) +","+ round(Vmax,2) +","+ -1*round(verticalspeed,2) +","+ round(true_alt,2) +","+ round(error_v,2) +","+ 100*round(ThrustSet,2) +","+ round(MaxAccUp,2) to landingdata.csv. 129 | 130 | } 131 | 132 | // Lastly a very crude landing script. The reason for the .99 multiplication is because its not perfect. So the velocity will start to decrease even though there should be no acceleration. 133 | // One could make a simple Proportional controller to assure touchdown speed is met buuut this works fine for low buffer_alt values. 134 | lock throttle to 0. 135 | SAS on. 136 | unlock steering. 137 | wait 10. 138 | clearscreen. 139 | if ship:status = "LANDED" { 140 | 141 | set M0 to 24.92998. 142 | set M1 to mass. 143 | set ISP to 350. 144 | set g0 to 9.80665. 145 | 146 | set DeltaV_used to g0*ISP*ln(M0/M1). 147 | 148 | set Rf to ship:body:radius + altitude. 149 | set Rcir to ship:body:radius + 100000. 150 | set u to ship:body:MU. 151 | set a to (Rf + Rcir)/2. 152 | set e to (Rcir - Rf)/(Rf + Rcir). 153 | set Vgrnd to 2*Rf*(constant():pi)/138984.38. 154 | set Vcir to sqrt(u/Rcir). 155 | set Vap to sqrt(((1 - e)*u)/((1 + e)*a)). 156 | set Vper to sqrt(((1 + e)*u)/((1 - e)*a)). 157 | set DeltaV_opt to (Vcir - Vap) + (Vper-Vgrnd). 158 | set Deviation to DeltaV_used - DeltaV_opt. 159 | 160 | print "You used " + round(Deviation,2) + "m/s more than the optimal" at(0,20). 161 | 162 | } -------------------------------------------------------------------------------- /landingFG.ks: -------------------------------------------------------------------------------- 1 | // WARNING: THIS WILL NOT WORK WITHOUT THE GRAVITY METER AND ACCELEROMETER. 2 | 3 | 4 | clearscreen. 5 | // This sets some pre launch parameters such as determining what the true altiude is of the base of the rocket. 6 | set ship:control:pilotmainthrottle to 0. 7 | set TouchDownSpeed to 5. // This is set by the user, I set it to 5 since the landing legs break at 6. 8 | set TestAlt to 1000. // How high you want the 9 | set MaxCount to 3. // Used to average the derivative term since it can get pretty eratic 10 | set buffer_alt to 10. // Its not perfect, so a little wiggle room is good to retract the legs. 11 | //set start_alt to alt:radar. // Determines where the control core is. The Radar Alt measures from there so if 12 | // the ship is on the ground it won't be 0. For this script, small errors matter. 13 | lock true_alt to ship:geoposition:terrainheight.// - start_alt. // Again measured from the bottom of the craft. 14 | // This script is meant to be used from a flat surface to launch and return. It can be adapted for landing from any situation. 15 | //SAS on. 16 | //lock throttle to 1. 17 | //stage. 18 | GEAR OFF. 19 | wait until altitude > TestAlt. 20 | lock throttle to 0. 21 | lock steering to srfretrograde. 22 | // After it goes up high the rocket will wait to fall back down. 23 | // I manually select the retrograde selection on the SAS. I would do it with the cooked steering but its current 24 | // iteration was not working well with the test ship. 25 | lock AccelUP to VDOT(UP:vector,ship:sensors:acc). 26 | lock MaxThrustAccUp to VDOT(UP:vector,availablethrust/mass*srfretrograde:vector). 27 | // This assumes the ship is pointed exactly retrograde. Meaning this can be used as a gravity turn for landing as well. 28 | lock GravUp to VDOT(UP:vector,ship:sensors:grav). 29 | lock DragUp to AccelUP - GravUp - MaxThrustAccUp*throttle. 30 | 31 | // WARNING: THIS WILL NOT WORK WITHOUT THE GRAVITY METER AND ACCELEROMETER. 32 | 33 | lock MaxAccUp to MaxThrustAccUp + GravUp. // I opted out of adding drag since its finiky, this adds some safety margin though 34 | log "1" to landingdata.csv. 35 | delete landingdata.csv. 36 | log "Time,Vmax,Vvert,Altitude,Error,ThrustSet,MaxAccUp" to landingdata.csv. 37 | // Log various variables to view. This can be changed to your liking or commented out if you don't need it. 38 | wait until verticalspeed < -20. // Just to make sure there are no weird transition errors. 39 | 40 | clearscreen. 41 | lock g to ship:sensors:grav:mag. 42 | lock Vmax to sqrt(2*(alt:radar-buffer_alt)*abs(MaxAccUp) + TouchDownSpeed^2). 43 | // The magic of the script. This equation is derived assuming an ascent starting at the touchdown speed and accelerating 44 | // at full throttle. It auto adjusts based on the altitude and the Max Acceleration as it changes with mass loss. 45 | // Basic PD loop. I want essentially no overshoot and very little error at the end. The Kp and Kd gains are tuned so at the finish 46 | // of the script the error > 0 and absolutely no overshoot. Tune to your liking however (fair warning, you have VERY little margin 47 | // when you are landing. The burn times I have seen are very short. That depends on the ship's TWR however. 48 | lock error to verticalspeed + Vmax. 49 | set errorP to 0. 50 | set Kp to .02. 51 | set errorD to 0. 52 | set Kd to 0.01. 53 | set ThrustSet to 0. 54 | lock throttle to ThrustSet. 55 | set time0 to time:seconds. 56 | lock time1 to time:seconds - time0. 57 | set count to 1. 58 | lock steering to srfretrograde. 59 | 60 | until verticalspeed > -1*TouchDownSpeed { 61 | 62 | set error1 to error. 63 | set t1 to time1. 64 | wait .00001. 65 | set error2 to error. 66 | set t2 to time1. 67 | set dt to t2-t1. 68 | // I like to take an average error so its not going crazy due to discrete calculations. 69 | set errorP to .5*(error1+error2). 70 | set errorD_test to (error2-error1)/dt. 71 | //This next part is used as a running average, the Derivative term was behaving eratically thus this damps out the spikes. 72 | if count < MaxCount { 73 | if count < 2 { 74 | set errorD to errorD_test. 75 | } 76 | if count >= 2 { 77 | set errorD to (errorD*(count-1)+errorD_test)/count. 78 | } 79 | set count to count + 1. 80 | } 81 | if count >= MaxCount { 82 | 83 | set errorD to (errorD*(MaxCount-1)+errorD_test)/MaxCount. 84 | } 85 | 86 | set ThrustSet to 1 - Kp*errorP- Kd*errorD. 87 | 88 | if ThrustSet > 1 { 89 | set ThrustSet to 1. 90 | } 91 | if ThrustSet < 0 { 92 | set ThrustSet to 0. 93 | } 94 | if error < 0 { 95 | set ThrustSet to 1. // This is very important. If the error ever drops below 0, it means it might crash since the 96 | // equation is calculated based on full thrust. 97 | } 98 | 99 | // Some data readouts. Pay attention to the Error term, make sure it doesn't drop below 0. 100 | 101 | print "Vmax = " + round(Vmax,2) at(0,0). 102 | print "VertSpeed = " + round(verticalspeed,2) at (0,2). 103 | print "Radar Alt = " + round(alt:radar,2) at(0,4). 104 | print "Error = " + round(error,2) at(0,6). 105 | print "ThrustSet = " + round(ThrustSet,2) at(0,8). 106 | print "GravUp = " + round(GravUp,2) at(0,10). 107 | print "AccelUP = " + round(AccelUP,2) at(0,12). 108 | print "DragUp = " + round(DragUp,2) at(0,14). 109 | print "MaxThrustAccUp = " + round(MaxThrustAccUp,2) at(0,16). 110 | print "MaxAccUp = " + round(MaxAccUp,2) at (0,18). 111 | 112 | log round(time1,3) +","+ round(Vmax,2) +","+ -1*round(verticalspeed,2) +","+ round(alt:radar,2) +","+ round(error,2) +","+ 100*round(ThrustSet,2) +","+ round(MaxAccUp,2) to landingdata.csv. 113 | 114 | } 115 | 116 | // Lastly a very crude landing script. The reason for the .99 multiplication is because its not perfect. So the velocity will start to decrease even though there should be no acceleration. 117 | // One could make a simple Proportional controller to assure touchdown speed is met buuut this works fine for low buffer_alt values. 118 | GEAR ON. 119 | until ship:status = "LANDED" { 120 | 121 | lock throttle to .99*mass*g/availablethrust. 122 | 123 | } -------------------------------------------------------------------------------- /landing_orbit.ks: -------------------------------------------------------------------------------- 1 | // ASSUME EQUATORIAL CIRCULAR ORBIT 2 | parameter target_ltlng is LATLNG(5,120), landing_peri is 20000. 3 | clearscreen. 4 | for n in ALLNODES { remove n.} 5 | clearvecdraws(). 6 | set show_vecdraws to true. 7 | 8 | function ETA_to_theta { 9 | 10 | parameter theta_test. 11 | 12 | local orbit_test to ship:orbit. 13 | local mnv_time to 0. 14 | 15 | if HASNODE { 16 | set orbit_test to nextnode:orbit. 17 | set mnv_time to nextnode:eta. 18 | } 19 | 20 | local T_orbit to orbit_test:period. 21 | local theta_ship to orbit_test:trueanomaly. 22 | local e to orbit_test:eccentricity. 23 | local GM to ship:body:mu. 24 | local a to orbit_test:semimajoraxis. 25 | //clearscreen. 26 | 27 | local EA_ship to 2*ARCTAN((TAN(theta_ship/2))/sqrt((1+e)/(1-e))). 28 | local MA_ship to EA_ship*constant:pi/180 - e*SIN(EA_ship). 29 | local EA_test to 2*ARCTAN((TAN(theta_test/2))/sqrt((1+e)/(1-e))). 30 | local MA_test to EA_test*constant:pi/180 - e*SIN(EA_test). 31 | local n to sqrt(GM/(a)^3). 32 | local eta_to_testpoint to (MA_test - MA_ship)/n. 33 | if eta_to_testpoint < 0 { 34 | set eta_to_testpoint to T_orbit + eta_to_testpoint. 35 | } 36 | 37 | // print "ETA to " + round(theta_test,2) + " degrees True Anomaly is " + round(eta_to_testpoint,2) + " seconds". 38 | // wait 2. 39 | return eta_to_testpoint. 40 | } 41 | 42 | function Vec_To_Node { 43 | parameter des_vec, mnv_time. 44 | 45 | local vel_vec to velocityat(ship,time:seconds + mnv_time):orbit. 46 | 47 | local norm_vec to vcrs(ship:body:position,ship:velocity:orbit):normalized. 48 | local prog_vec to vel_vec:normalized. 49 | local radi_vec to VCRS(norm_vec,prog_vec). 50 | 51 | local burn_vec to des_vec - vel_vec. 52 | 53 | local norm_comp to VDOT(norm_vec,burn_vec). 54 | local prog_comp to VDOT(prog_vec,burn_vec). 55 | local radi_comp to VDOT(radi_vec,burn_vec). 56 | 57 | local mynode to NODE(time:seconds + mnv_time,radi_comp,norm_comp,prog_comp). 58 | add mynode. 59 | } 60 | 61 | function Des_Peri_RadialBurn { 62 | parameter des_peri. 63 | 64 | local a to ship:orbit:Semimajoraxis. 65 | local u to ship:body:mu. 66 | local V0 to ship:velocity:orbit:mag. 67 | local R to ship:body:position:mag. 68 | local Rp to des_peri + ship:body:radius. 69 | local Ra to 2*a - Rp. 70 | local e to (Ra - Rp)/(Ra + Rp). 71 | local A to sqrt(a*u*(1-e^2)). 72 | local B to V0*R. 73 | local rad_des to ARCCOS(A/B). 74 | 75 | return rad_des. 76 | } 77 | 78 | function Set_Landing_Orbit_vec { 79 | parameter des_inc, des_peri, mnv_time. 80 | 81 | local vel_vec to velocityat(ship,time:seconds + mnv_time):orbit. 82 | local pos_vec to positionat(ship,time:seconds + mnv_time). 83 | local body_vec to pos_vec - ship:body:position. 84 | 85 | local angle_rotate_inc to ANGLEAXIS(des_inc,-body_vec). 86 | local new_vel_vec to vel_vec*angle_rotate_inc. 87 | local new_norm to VCRS(body_vec,new_vel_vec). 88 | local rad_des to Des_Peri_RadialBurn(landing_peri). 89 | 90 | local angle_rotate_rad to ANGLEAXIS(rad_des,new_norm). 91 | local new_vel_vec to new_vel_vec*angle_rotate_rad. 92 | 93 | return new_vel_vec. 94 | } 95 | 96 | // Main 97 | local time_test to 30. 98 | local landing_vec to Set_Landing_Orbit_vec(target_ltlng:LAT,landing_peri,time_test). 99 | 100 | Vec_To_Node(landing_vec,time_test). 101 | 102 | local peri_time to ETA_to_theta(0). 103 | local peri_pos to positionat(ship,time:seconds + peri_time). 104 | local long_offset to 360*(peri_time)/ship:body:rotationperiod. 105 | local peri_ltlng_pre to ship:body:GEOPOSITIONOF(peri_pos). 106 | local peri_ltlng to LATLNG(peri_ltlng_pre:LAT, peri_ltlng_pre:LNG + long_offset). 107 | local long_diff to target_ltlng:LNG - peri_ltlng:LNG. 108 | 109 | local period_diff to 1/ship:orbit:period - 1/ship:body:rotationperiod. 110 | print long_diff. 111 | 112 | local long_fix to(long_diff/360)/period_diff. 113 | print long_fix. 114 | local time_test to time_test + long_fix. 115 | remove nextnode. 116 | local landing_vec to Set_Landing_Orbit_vec(target_ltlng:LAT,landing_peri,time_test). 117 | Vec_To_Node(landing_vec,time_test). 118 | 119 | if show_vecdraws { 120 | set target_ltlng_draw to vecdraw(). 121 | set target_ltlng_draw:startupdater to { return target_ltlng:position. }. 122 | set target_ltlng_draw:vecupdater to { return target_ltlng:position - ship:body:position. }. 123 | set target_ltlng_draw:show to true. 124 | set target_ltlng_draw:color to RGB(255,255,255). 125 | } 126 | 127 | wait until false. 128 | // Determine the angle ALPHA to rotate a circular orbit velocity vector in order to achieve a desired periapsis. 129 | // 130 | // *************** Known *************** 131 | // 132 | // mew = Gravitational Parameter of Body 133 | // 134 | // h = Angular Momentum of Ship 135 | // 136 | // p = h^2/mew 137 | // 138 | // h = V_perpendicular*R 139 | // 140 | // V0 = Circular Orbit Speed 141 | // 142 | // V_perpendicular = V0*cos(ALPHA) 143 | // 144 | // a = Semi Major Axis of Orbit (constant) 145 | // 146 | // e = Eccentricty of Desired Orbit 147 | // 148 | // Rc = Radius of Circular Orbit 149 | // 150 | // Rp = Periapsis Radius (Input) 151 | // 152 | // Ra = Apoapsis Radius 153 | // 154 | // *************** Starting Equation *************** 155 | // 156 | // a = P/(1 - e^2) 157 | // 158 | // *************** Derivation *************** 159 | // 160 | // Ra = 2*a - Rp 161 | // 162 | // e = (Ra - Rp)/(Ra + Rp) 163 | // 164 | // a*(1 - e^2) = P 165 | // 166 | // a*(1 - e^2) = h^2/mew 167 | // 168 | // flip sides 169 | // 170 | // h^2 = (a*(1 - e^2))/mew 171 | // 172 | // V_perpendicular*Rc = (V0*cos(ALPHA)*Rc)^2 = (a*(1 - e^2))/mew 173 | // 174 | // cos(ALPHA) = sqrt((a*(1 - e^2))/mew)/(V0*Rc) 175 | // 176 | // ALPHA = cos(sqrt((a*(1 - e^2))/mew)/(V0*Rc))^-1 -------------------------------------------------------------------------------- /landing_term_traj.ks: -------------------------------------------------------------------------------- 1 | clearscreen. 2 | clearvecdraws(). 3 | for n in allnodes { remove n.} 4 | 5 | parameter target_ltln is LATLNG(5,120). 6 | 7 | if true { 8 | set Target_Vecdraw to vecdraw(). 9 | set Target_Vecdraw:startupdater to { return target_ltln:position. }. 10 | set Target_Vecdraw:vecupdater to { return 50000*((target_ltln:position-ship:body:position):normalized). }. 11 | set Target_Vecdraw:show to true. 12 | set Target_Vecdraw:color to RGB(255,255,255). 13 | } 14 | 15 | 16 | function Height_At_Position { 17 | parameter test_position. 18 | local body_pos to ship:body:position. 19 | local body_R to ship:body:radius. 20 | local body_test_position to test_position - body_pos. 21 | local H to body_test_position:mag - body_R. 22 | return H. 23 | } 24 | 25 | function ETA_to_theta { 26 | 27 | parameter theta_test. 28 | 29 | local orbit_test to ship:orbit. 30 | local mnv_time to 0. 31 | 32 | if HASNODE { 33 | set orbit_test to nextnode:orbit. 34 | set mnv_time to nextnode:eta. 35 | } 36 | 37 | local T_orbit to orbit_test:period. 38 | local theta_ship to orbit_test:trueanomaly. 39 | local e to orbit_test:eccentricity. 40 | local GM to ship:body:mu. 41 | local a to orbit_test:semimajoraxis. 42 | //clearscreen. 43 | 44 | local EA_ship to 2*ARCTAN((TAN(theta_ship/2))/sqrt((1+e)/(1-e))). 45 | local MA_ship to EA_ship*constant:pi/180 - e*SIN(EA_ship). 46 | local EA_test to 2*ARCTAN((TAN(theta_test/2))/sqrt((1+e)/(1-e))). 47 | local MA_test to EA_test*constant:pi/180 - e*SIN(EA_test). 48 | local n to sqrt(GM/(a)^3). 49 | local eta_to_testpoint to (MA_test - MA_ship)/n. 50 | if eta_to_testpoint < 0 { 51 | set eta_to_testpoint to T_orbit + eta_to_testpoint. 52 | } 53 | 54 | // print "ETA to " + round(theta_test,2) + " degrees True Anomaly is " + round(eta_to_testpoint,2) + " seconds". 55 | // wait 2. 56 | return eta_to_testpoint. 57 | } 58 | 59 | function Impact_locator { 60 | parameter height_above to 2000. 61 | 62 | local Ttest_ltln is LATLNG(0,0). 63 | local per_test to periapsis. 64 | local Body_Ang_speed to 360/ship:body:rotationperiod. 65 | 66 | local drawvec_check is true. 67 | local T0 is time:seconds. 68 | 69 | local Tp is nextnode:eta + ETA_to_theta(0). 70 | 71 | local Ttest is Tp/2. 72 | 73 | if HASNODE { 74 | set per_test to nextnode:orbit:periapsis. 75 | } 76 | if per_test > 0 { 77 | clearscreen. 78 | print "No impact detected". 79 | } else { 80 | local T1 is 0. 81 | local T2 is Tp. 82 | 83 | if drawvec_check { 84 | set Ttest_vec_Draw to vecdraw(). 85 | set Ttest_vec_Draw:startupdater to { return V(0,0,0). }. 86 | set Ttest_vec_Draw:vecupdater to { return positionat(ship,T0 + Ttest). }. 87 | set Ttest_vec_Draw:show to true. 88 | set Ttest_vec_Draw:color to RGB(255,0,0). 89 | } 90 | local impact_found to false. 91 | local count to 0. 92 | local iprint to 3. 93 | until impact_found { 94 | local time_offset to time:seconds - T0. 95 | local eta_impact to Ttest - time_offset. 96 | local long_offset to eta_impact*Body_Ang_speed. // For the future this needs to be checked for prograde or retrograde 97 | local Ttest_vec to positionat(ship,T0 + Ttest). 98 | set Ttest_ltln to ship:body:geopositionof(Ttest_vec). 99 | set Ttest_ltln to LATLNG(Ttest_ltln:LAT,Ttest_ltln:LNG - long_offset). 100 | 101 | local Ttest_H to Height_At_Position(Ttest_vec). 102 | local error to Ttest_H - (Ttest_ltln:terrainheight + height_above). 103 | 104 | set iprint to 3. 105 | print "Error " + round(error,2) + " " at(0,iprint). 106 | set iprint to iprint + 1. 107 | print "Ttest_ltln:LAT " + round(Ttest_ltln:LAT,3) + " " at(0,iprint). 108 | set iprint to iprint + 1. 109 | print "Ttest_ltln:LNG " + round(Ttest_ltln:LNG,3) + " " at(0,iprint). 110 | set iprint to iprint + 1. 111 | print "count " + count + " " at(0,iprint). 112 | set iprint to iprint + 1. 113 | print "eta_impact " + round(eta_impact,2) + " " at(0,iprint). 114 | 115 | wait 0.001. 116 | set count to count + 1. 117 | if count > 50 { 118 | break. 119 | } 120 | if abs(error) < 0.1 { 121 | set impact_found to true. 122 | } 123 | 124 | if error > 0 { 125 | set T1 to Ttest. 126 | set Ttest to (T1 + T2)/2. 127 | } else { 128 | set T2 to Ttest. 129 | set Ttest to (T1 + T2)/2. 130 | } 131 | } 132 | //until false { 133 | // local time_offset to time:seconds - T0. 134 | // local eta_impact to Ttest - time_offset. 135 | // print "eta_impact " + round(eta_impact,2) + " " at(0,iprint). 136 | //} 137 | } 138 | 139 | return LIST(Ttest_ltln,T0 + Ttest). 140 | } 141 | 142 | function GPS_score_func { 143 | parameter target_ltln, term_traj_ltln. 144 | 145 | local LAT_diff is abs(target_ltln:LAT - term_traj_ltln:LAT). 146 | if LAT_diff > 180 { 147 | set LAT_diff to 360 - LAT_diff. 148 | } 149 | 150 | local LNG_diff is abs(target_ltln:LNG - term_traj_ltln:LNG). 151 | if LNG_diff > 180 { 152 | set LNG_diff to 360 - LNG_diff. 153 | } 154 | 155 | local GPS_score is sqrt(LAT_diff^2 + LNG_diff^2). 156 | } 157 | 158 | function Impact_score { 159 | parameter term_traj_node, IMP_output, target_ltln. 160 | local drawvec_check is false. 161 | local term_traj_ltln is IMP_output[0]. 162 | // GPS Score is based on the angular difference between the Lattitudes and Longitudes of the 163 | // target landing spot and the current impact location 164 | 165 | 166 | // DeltaV Score is the percentage of the starting speed at the node. 167 | local speed_at_node is velocityat(ship,time:seconds + nextnode:eta - 0.1):orbit:mag. 168 | local Dv is nextnode:deltav:mag. 169 | local DeltaV_score is 1 - Dv/speed_at_node. 170 | 171 | // Verticality Score is how close to 90 degrees is the final impact velocity. 172 | local vel_at_imp is velocityat(ship,IMP_output[1]):surface. 173 | local pos_at_imp is positionat(ship,IMP_output[1]). 174 | local body_vec is ship:body:position. 175 | local UP_at_imp is (pos_at_imp - body_vec):normalized. 176 | local Vert_diff is VANG(vel_at_imp,UP_at_imp) - 90. 177 | local Vert_score is Vert_diff/90. 178 | 179 | if drawvec_check { 180 | set Ttest_vec_Draw to vecdraw(). 181 | set Ttest_vec_Draw:startupdater to { return V(0,0,0). }. 182 | set Ttest_vec_Draw:vecupdater to { return vel_at_imp. }. 183 | set Ttest_vec_Draw:show to true. 184 | set Ttest_vec_Draw:color to RGB(255,0,0). 185 | wait 2. 186 | print round(LAT_diff,3). 187 | print round(LNG_diff,3). 188 | print round(Vert_diff,2). 189 | print round(GPS_score,3). 190 | print round(DeltaV_score,3). 191 | print round(Vert_score,3). 192 | } 193 | 194 | local Total_score to 10*GPS_score + 0.25*DeltaV_score + Vert_score. 195 | 196 | return Total_score. 197 | } 198 | 199 | function Impact_Score_Func { 200 | parameter Inputs. 201 | for n in allnodes { remove n.} 202 | //local term_traj_node to NODE(Inputs[0],Inputs[1],Inputs[2],Inputs[3]). 203 | local term_traj_node to NODE(Inputs[0],0,0,Inputs[1]). 204 | add term_traj_node. 205 | 206 | local IMP_output is Impact_locator(). 207 | local term_traj_ltln is IMP_output[0]. 208 | 209 | local Score is Impact_score(term_traj_node, IMP_output, target_ltln). 210 | 211 | return Score. 212 | } 213 | 214 | function Slope { 215 | parameter p1, p2, p3, delta. 216 | 217 | local der1 is (p2 - p1)/delta. 218 | local der2 is (p3 - p1)/(-1*delta). 219 | local der is (der1 + der2)/2. 220 | 221 | return der. 222 | } 223 | 224 | function Optimize_Score { 225 | parameter Inputs, Score_Func, method is 1. 226 | 227 | local Inputs_inc to Inputs. 228 | local Inputs_base to Inputs. 229 | local Inputs_deltas to LIST(). 230 | local iInput to 0. 231 | for i in Inputs { 232 | Inputs_deltas:ADD(0). 233 | } 234 | 235 | local iCount to 0. 236 | local Score_0 to Score_Func(Inputs_inc). 237 | local Score_1 to 0. 238 | local delta is 10. 239 | local gamma is 0.001. 240 | clearscreen. 241 | until iCount > 50 { 242 | local iInput to 0. 243 | for Input in Inputs { 244 | 245 | set Inputs_base[iInput] to Inputs_inc[iInput]. 246 | set Inputs_inc[iInput] to Inputs_base[iInput] + delta. 247 | local Score_p to Score_Func(Inputs_inc). 248 | set Inputs_inc[iInput] to Inputs_base[iInput] - delta. 249 | local Score_n to Score_Func(Inputs_inc). 250 | if method = 1 { // Newton Rapson Method 251 | local der is Slope(Score_0, Score_p, Score_n, delta). 252 | print der. 253 | set Inputs_deltas[iInput] to gamma*Score_0/der. 254 | } 255 | if method = 2 { // Hillclimb Method 256 | if Score_p > Score_0 AND Score_p > Score_n { 257 | set Inputs_deltas[iInput] to delta. 258 | } else if Score_n > Score_0 AND Score_n > Score_p { 259 | set Inputs_deltas[iInput] to -1*delta. 260 | } else { 261 | set Inputs_deltas[iInput] to 0. 262 | } 263 | } 264 | set iInput to iInput + 1. 265 | } 266 | clearscreen. 267 | print Inputs_deltas at(0,20). 268 | wait 1. 269 | local iInput to 0. 270 | for i in Inputs_inc { 271 | set Inputs_inc[iInput] to Inputs_inc[iInput] + Inputs_deltas[iInput]. 272 | set iInput to iInput + 1. 273 | } 274 | set Score_1 to Score_Func(Inputs_inc). 275 | if Score_1 < Score_0 { 276 | clearscreen. 277 | print "Best Score Found". 278 | set Inputs to Inputs_inc. 279 | break. 280 | } 281 | 282 | set iCount to iCount + 1. 283 | print iCount at(0,0). 284 | } 285 | return Inputs. 286 | } 287 | 288 | local T0 is time:seconds. // Time that the script started 289 | local Tf is time:seconds + eta:periapsis. 290 | 291 | local Ttest is (eta:periapsis)/2. 292 | local term_traj_time to time:seconds + Ttest. 293 | local radi_init to 0. 294 | local norm_init to 0. 295 | local prog_init to -0.5*velocityat(ship,term_traj_time):orbit:mag. 296 | 297 | //local Inputs to LIST(term_traj_time,radi_init,norm_init,prog_init). 298 | local Inputs to LIST(term_traj_time,prog_init). 299 | 300 | print Impact_Score_Func(Inputs). 301 | 302 | Optimize_Score(Inputs,Impact_Score_Func@). -------------------------------------------------------------------------------- /launch.ks: -------------------------------------------------------------------------------- 1 | declare parameter OrbitAlt is 100000. 2 | set ship:control:pilotmainthrottle to 0. 3 | clearscreen. 4 | set circstage to 3. 5 | declare function ExecuteNode { 6 | clearscreen. 7 | lock throttle to 0. 8 | SAS off. 9 | lock DeltaV to nextnode:deltav:mag. 10 | set BurnTime to .5*DeltaV*mass/availablethrust. 11 | lock steering to nextnode. 12 | print "Aligning with Maneuver Node". 13 | until VANG(ship:facing:vector,nextnode:burnvector) < 1 { 14 | print "Direction Angle Error = " + round(VANG(ship:facing:vector,nextnode:burnvector),1) + " "at(0,1). 15 | } 16 | clearscreen. 17 | print "Warping to Node". 18 | print "Burn Starts at T-minus " + round(BurnTime,2) + "secs ". 19 | warpto(time:seconds + nextnode:eta - BurnTime - 10). 20 | wait until BurnTime >= nextnode:eta. 21 | 22 | clearscreen. 23 | lock throttle to DeltaV*mass/availablethrust. 24 | print "Executing Node". 25 | 26 | until DeltaV <= .1 { 27 | print "Delta V = " + round(DeltaV,1) + " " at(0,1). 28 | print "Throttle = " + MIN(100,round(throttle*100)) + "% " at(0,2). 29 | } 30 | lock throttle to 0. 31 | unlock all. 32 | remove nextnode. 33 | clearscreen. 34 | print "Node Executed". 35 | } 36 | 37 | declare function Circularize_apo_Node{ 38 | set Vapo_cir to sqrt(ship:body:mu/(ship:body:radius + apoapsis)). 39 | set DeltaV to Vapo_cir - VELOCITYAT(ship,time:seconds + eta:apoapsis):orbit:mag. 40 | set CirPer to NODE(TIME:seconds + eta:apoapsis, 0, 0, DeltaV). 41 | ADD CirPer. 42 | ExecuteNode(). 43 | } 44 | 45 | declare function Circularize_apo_Vector { 46 | set Vapo_cir to sqrt(ship:body:mu/(ship:body:radius + apoapsis)). 47 | set DeltaV to Vapo_cir - VELOCITYAT(ship,time:seconds + eta:apoapsis):orbit:mag. 48 | set BurnTime to .4*DeltaV*mass/availablethrust. 49 | set BurnDir to velocityat(ship,time:seconds + eta:apoapsis):orbit:direction. 50 | lock steering to BurnDir. 51 | 52 | lock V_cir to sqrt(ship:body:mu/(ship:body:radius + altitude)). 53 | lock V_cir_vec to VCRS(VCRS(ship:body:position,ship:velocity:orbit),ship:body:position):normalized. 54 | 55 | lock DeltaV_vec to V_cir*V_cir_vec - ship:velocity:orbit. 56 | 57 | clearscreen. 58 | print "Aligning to Burn Vector". 59 | until VANG(ship:facing:vector,BurnDir:vector) < 1 { 60 | print "Direction Angle Error = " + round(VANG(ship:facing:vector,BurnDir:vector),1) + " "at(0,1). 61 | } 62 | print "Warping to Apoapsis". 63 | print "Burn Starts at T-minus " + round(BurnTime,2) + "secs ". 64 | lock steering to DeltaV_vec:direction. 65 | 66 | warpto(time:seconds + eta:apoapsis - BurnTime - 10). 67 | wait until BurnTime >= eta:apoapsis. 68 | 69 | clearscreen. 70 | lock throttle to DeltaV_vec:mag*mass/availablethrust. 71 | print "Executing Circularization". 72 | 73 | until DeltaV_vec:mag <= .1 { 74 | print "Delta V = " + round(DeltaV_vec:mag,1) + " " at(0,1). 75 | print "Throttle = " + MIN(100,round(throttle*100)) + "% " at(0,2). 76 | } 77 | lock throttle to 0. 78 | unlock all. 79 | clearscreen. 80 | print "Circularization Executed". 81 | } 82 | 83 | declare function pitch{ 84 | declare parameter flightmode,starting_alt is 0. 85 | if flightmode = 0 { 86 | set pitch_ang to sqrt((90^2)*max(0,(altitude-starting_alt)/70000)). 87 | } else if flightmode = 1 { 88 | set pitch_ang to VANG(UP:vector,velocity:orbit). 89 | } else if flightmode = -1 { 90 | set pitch_ang to 0. 91 | } else { 92 | set pitch_ang to 90. 93 | } 94 | 95 | return pitch_ang. 96 | } 97 | 98 | set flightmode to -1. 99 | set VS_switch to 50. 100 | set compass to 90. 101 | set starting_alt to altitude. 102 | //set OrbitAlt to 100000. 103 | 104 | //lock pitch to sqrt((90^2)*altitude/70000). 105 | 106 | //lock steering to heading(compass,90-pitch(flightmode,starting_alt)). 107 | lock steering to heading(compass,90-pitch(flightmode,starting_alt)). 108 | 109 | lock throttle to 1. 110 | stage. 111 | set starttime to time:seconds. 112 | wait 1. 113 | set MAX to maxthrust. 114 | set BurnTime to 0. 115 | set DeltaV to 0. 116 | 117 | when maxthrust < MAX OR availablethrust = 0 then { 118 | lock throttle to 0. 119 | stage. 120 | lock throttle to 1. 121 | set MAX to maxthrust. 122 | preserve. 123 | } 124 | 125 | lock Q to 1000*ship:dynamicpressure. 126 | set MaxQ to Q. 127 | lock AeroSwitch to Q/MaxQ. 128 | //lock FPAorbit to VANG(UP:vector,velocity:orbit). 129 | 130 | until flightmode = 3 { 131 | 132 | print "Flight Mode " + flightmode + " " at (0,1). 133 | print "MaxQ " + round(MaxQ,2) at (0,2). 134 | print "Q " + round(Q,2) at (0,3). 135 | print "Pitch " + round(pitch(flightmode,starting_alt),2) at (0,4). 136 | print "Ship Pitch " + round(VANG(UP:vector,ship:facing:vector),2) at (0,5). 137 | print "Apoapsis " + round(apoapsis,2) at (0,6). 138 | print "Target Apoapsis " + round(OrbitAlt,2) at (0,7). 139 | print "Time to Apoapsis " + round(eta:apoapsis,2) at (0,8). 140 | print "BurnTime " + round(BurnTime,2) at (0,9). 141 | print "Throttle " + round(throttle,2) at (0,10). 142 | 143 | if MaxQ <= Q { 144 | set MaxQ to Q. 145 | } 146 | if flightmode = -1 { 147 | set FPAorbit to VANG(UP:vector,velocity:orbit). 148 | if verticalspeed >= VS_switch { 149 | set starting_alt to altitude. 150 | set flightmode to 0. 151 | } 152 | } 153 | 154 | if flightmode = 0 { 155 | set FPAorbit to VANG(UP:vector,velocity:orbit). 156 | } 157 | 158 | if flightmode = 0 and AeroSwitch < .1 or FPAorbit < pitch(flightmode,starting_alt){ 159 | //lock pitch to FPAorbit. 160 | set flightmode to 1. 161 | } 162 | 163 | if flightmode = 1 AND apoapsis >= .9*OrbitAlt { 164 | lock throttle to max(0,(OrbitAlt - apoapsis+100)/(.05*OrbitAlt)). 165 | wait .5. 166 | set flightmode to 2. 167 | } 168 | 169 | if flightmode <= 2 AND apoapsis >= OrbitAlt { 170 | //lock throttle to 0. 171 | lock steering to srfprograde. 172 | wait .5. 173 | set flightmode to 3. 174 | } 175 | 176 | } 177 | clearscreen. 178 | lock throttle to 0. 179 | print "Coasting until out of Atmosphere". 180 | wait until altitude > 70000. 181 | 182 | if Career():canmakenodes { 183 | Circularize_apo_Node(). 184 | //Circularize_apo_Vector(). 185 | set finishtime to time:seconds. 186 | set totaltime to finishtime - starttime. 187 | print "Time to Ascent " + round(totaltime,2) at (0,20). 188 | } else { 189 | clearscreen. 190 | } 191 | 192 | print "Program finished". 193 | 194 | -------------------------------------------------------------------------------- /launch_gamma.ks: -------------------------------------------------------------------------------- 1 | declare parameter OrbitAlt is 100000. 2 | set ship:control:pilotmainthrottle to 0. 3 | clearscreen. 4 | set circstage to 3. 5 | 6 | run lib_instaz. 7 | 8 | declare function ExecuteNode { 9 | clearscreen. 10 | lock throttle to 0. 11 | SAS off. 12 | lock DeltaV to nextnode:deltav:mag. 13 | set BurnTime to .5*DeltaV*mass/max(0.0001,availablethrust). 14 | lock steering to nextnode. 15 | print "Aligning with Maneuver Node". 16 | until VANG(ship:facing:vector,nextnode:burnvector) < 1 { 17 | print "Direction Angle Error = " + round(VANG(ship:facing:vector,nextnode:burnvector),1) + " "at(0,1). 18 | } 19 | clearscreen. 20 | print "Warping to Node". 21 | print "Burn Starts at T-minus " + round(BurnTime,2) + "secs ". 22 | warpto(time:seconds + nextnode:eta - BurnTime - 10). 23 | wait until BurnTime >= nextnode:eta. 24 | 25 | clearscreen. 26 | lock throttle to DeltaV*mass/max(0.0001,availablethrust). 27 | print "Executing Node". 28 | 29 | until DeltaV <= .1 { 30 | print "Delta V = " + round(DeltaV,1) + " " at(0,1). 31 | print "Throttle = " + MIN(100,round(throttle*100)) + "% " at(0,2). 32 | } 33 | lock throttle to 0. 34 | unlock all. 35 | remove nextnode. 36 | clearscreen. 37 | print "Node Executed". 38 | } 39 | 40 | declare function Circularize_apo_Node{ 41 | set Vapo_cir to sqrt(ship:body:mu/(ship:body:radius + apoapsis)). 42 | set DeltaV to Vapo_cir - VELOCITYAT(ship,time:seconds + eta:apoapsis):orbit:mag. 43 | set CirPer to NODE(TIME:seconds + eta:apoapsis, 0, 0, DeltaV). 44 | ADD CirPer. 45 | ExecuteNode(). 46 | } 47 | 48 | declare function Circularize_apo_Vector { 49 | set Vapo_cir to sqrt(ship:body:mu/(ship:body:radius + apoapsis)). 50 | set DeltaV to Vapo_cir - VELOCITYAT(ship,time:seconds + eta:apoapsis):orbit:mag. 51 | set BurnTime to .4*DeltaV*mass/max(0.0001,availablethrust). 52 | set BurnDir to velocityat(ship,time:seconds + eta:apoapsis):orbit:direction. 53 | lock steering to BurnDir. 54 | 55 | lock V_cir to sqrt(ship:body:mu/(ship:body:radius + altitude)). 56 | lock V_cir_vec to VCRS(VCRS(ship:body:position,ship:velocity:orbit),ship:body:position):normalized. 57 | 58 | lock DeltaV_vec to V_cir*V_cir_vec - ship:velocity:orbit. 59 | 60 | clearscreen. 61 | print "Aligning to Burn Vector". 62 | until VANG(ship:facing:vector,BurnDir:vector) < 1 { 63 | print "Direction Angle Error = " + round(VANG(ship:facing:vector,BurnDir:vector),1) + " "at(0,1). 64 | } 65 | print "Warping to Apoapsis". 66 | print "Burn Starts at T-minus " + round(BurnTime,2) + "secs ". 67 | lock steering to DeltaV_vec:direction. 68 | 69 | warpto(time:seconds + eta:apoapsis - BurnTime - 10). 70 | wait until BurnTime >= eta:apoapsis. 71 | 72 | clearscreen. 73 | lock throttle to DeltaV_vec:mag*mass/max(0.0001,availablethrust). 74 | print "Executing Circularization". 75 | 76 | until DeltaV_vec:mag <= .1 { 77 | print "Delta V = " + round(DeltaV_vec:mag,1) + " " at(0,1). 78 | print "Throttle = " + MIN(100,round(throttle*100)) + "% " at(0,2). 79 | } 80 | lock throttle to 0. 81 | unlock all. 82 | clearscreen. 83 | print "Circularization Executed". 84 | } 85 | 86 | declare function pitch{ 87 | declare parameter flightmode,starting_alt is 0. 88 | if flightmode = 0 { 89 | set pitch_ang to sqrt((90^2)*max(0,(altitude-starting_alt)/70000)). 90 | } else if flightmode = 1 { 91 | set pitch_ang to VANG(UP:vector,velocity:orbit). 92 | } else if flightmode = -1 { 93 | set pitch_ang to 0. 94 | } else { 95 | set pitch_ang to 90. 96 | } 97 | 98 | return pitch_ang. 99 | } 100 | 101 | set flightmode to -1. 102 | set VS_switch to 30. 103 | set Alt_gamma to (.75)*ship:body:atm:height. 104 | set inc to 25. 105 | set compass to inst_az(inc). 106 | set starting_alt to altitude. 107 | set pitch_des to 0. 108 | //set OrbitAlt to 100000. 109 | 110 | //lock pitch to sqrt((90^2)*altitude/70000). 111 | 112 | //lock steering to heading(compass,90-pitch(flightmode,starting_alt)). 113 | //lock steering to heading(compass,90-pitch(flightmode,starting_alt)). 114 | lock steering to lookdirup(heading(compass,90-pitch_des):vector,ship:facing:upvector). 115 | 116 | lock throttle to 1. 117 | set MAX to maxthrust. 118 | set starting_TWR to 0. 119 | 120 | when maxthrust < MAX OR availablethrust = 0 then { 121 | stage. 122 | set MAX to maxthrust. 123 | if MAX > 0 { 124 | set g to body:mu/(body:radius^2). 125 | set starting_TWR to availablethrust/(mass*9.81).. 126 | } 127 | preserve. 128 | } 129 | 130 | set starttime to time:seconds. 131 | wait 1. 132 | 133 | set Alt_gamma to max(2/3,(1-(starting_TWR - 1.1)/(2.0 - 1.1)/3))*ship:body:atm:height. 134 | set BurnTime to 0. 135 | set DeltaV to 0. 136 | 137 | set gamma_des to 0. 138 | set time_to_alt to 0. 139 | set time_to_alt1 to 0. 140 | set time_to_alt2 to 0. 141 | set gamma_rate to 0. 142 | set dt to 0. 143 | set verticalspeed1 to 0. 144 | set verticalspeed2 to 0. 145 | set accel_vs to 0. 146 | 147 | lock Q to 1000*ship:dynamicpressure. 148 | set MaxQ to Q. 149 | lock AeroSwitch to Q/MaxQ. 150 | //lock FPAorbit to VANG(UP:vector,velocity:orbit). 151 | 152 | until flightmode = 3 { 153 | 154 | set compass to inst_az(inc). 155 | set time1 to time:seconds. 156 | set verticalspeed1 to verticalspeed. 157 | wait 0. 158 | 159 | print "Flight Mode " + flightmode + " " at (0,1). 160 | print "MaxQ " + round(MaxQ,2) at (0,2). 161 | print "Q " + round(Q,2) at (0,3). 162 | //print "Pitch " + round(pitch(flightmode,starting_alt),2) at (0,4). 163 | print "Pitch " + round(pitch_des,2) at (0,4). 164 | print "Ship Pitch " + round(VANG(UP:vector,ship:facing:vector),2) at (0,5). 165 | print "Apoapsis " + round(apoapsis,2) at (0,6). 166 | print "Target Apoapsis " + round(OrbitAlt,2) at (0,7). 167 | print "Time to Apoapsis " + round(eta:apoapsis,2) at (0,8). 168 | print "BurnTime " + round(BurnTime,2) at (0,9). 169 | print "Throttle " + round(throttle,2) at (0,10). 170 | print "Gamma_des " + round(gamma_des,2) at (0,11). 171 | print "time_to_alt " + round(time_to_alt,2) at (0,12). 172 | print "gamma_rate " + round(gamma_rate,4) at (0,13). 173 | print "dt " + round(dt,4) at (0,14). 174 | print "Alt_gamma " + round(Alt_gamma,2) at (0,15). 175 | print "accel_vs " + round(accel_vs,2) at (0,16). 176 | print "time_to_alt1 " + round(time_to_alt1,2) at (0,17). 177 | print "time_to_alt2 " + round(time_to_alt2,2) at (0,18). 178 | print "starting_TWR " + round(starting_TWR,2) at (0,19). 179 | print "compass " + round(compass,2) at (0,20). 180 | 181 | 182 | if MaxQ <= Q { 183 | set MaxQ to Q. 184 | } 185 | if flightmode = -1 { 186 | set FPAorbit to VANG(UP:vector,velocity:orbit). 187 | if verticalspeed >= VS_switch { 188 | set starting_alt to altitude. 189 | set flightmode to 0. 190 | } 191 | } 192 | 193 | if flightmode <= 2 { 194 | set FPAorbit to VANG(UP:vector,velocity:orbit). 195 | set pitch_des to gamma_des. 196 | } 197 | 198 | if flightmode = 0 AND AeroSwitch < .1 AND FPAorbit < pitch_des{ 199 | lock steering to lookdirup(heading(compass,90-FPAorbit):vector,ship:facing:upvector). 200 | set flightmode to 1. 201 | } 202 | 203 | if flightmode = 1 AND apoapsis >= .9*OrbitAlt { 204 | lock throttle to max(0,(OrbitAlt - apoapsis+100)/(.05*OrbitAlt)). 205 | wait 0. 206 | set flightmode to 2. 207 | } 208 | 209 | if flightmode <= 2 AND apoapsis >= OrbitAlt { 210 | //lock throttle to 0. 211 | lock steering to srfprograde. 212 | wait .5. 213 | set flightmode to 3. 214 | } 215 | 216 | set time2 to time:seconds. 217 | set verticalspeed2 to verticalspeed. 218 | set dt to time2 - time1. 219 | set accel_vs to (verticalspeed2 - verticalspeed1)/dt. 220 | set alt_diff to Alt_gamma - altitude. 221 | 222 | set a to .5*accel_vs. 223 | set b to verticalspeed. 224 | set c to -alt_diff. 225 | 226 | //set time_to_alt1 to ((-b) - sqrt(b^2 - 4*a*c))/(2*a). 227 | set time_to_alt2 to ((-b) + sqrt(max(0,b^2 - 4*a*c)))/(2*a). 228 | 229 | set time_to_alt to max(0.0001,(alt_diff)/verticalspeed). 230 | //set gamma_rate to (90 - gamma_des)/time_to_alt. 231 | set gamma_rate to max(0,(90 - gamma_des)/time_to_alt2). 232 | if flightmode = -1 { 233 | set gamma_rate to 0. 234 | } 235 | 236 | 237 | set gamma_des to min(90,max(0,gamma_des + dt*gamma_rate)). 238 | 239 | } 240 | clearscreen. 241 | lock throttle to 0. 242 | print "Coasting until out of Atmosphere". 243 | wait until altitude > 70000. 244 | LIGHTS on. 245 | 246 | if Career():canmakenodes { 247 | Circularize_apo_Node(). 248 | //Circularize_apo_Vector(). 249 | set finishtime to time:seconds. 250 | set totaltime to finishtime - starttime. 251 | print "Time to Ascent " + round(totaltime,2) at (0,20). 252 | } else { 253 | clearscreen. 254 | } 255 | 256 | print "Program finished". 257 | 258 | -------------------------------------------------------------------------------- /lib_instaz.ks: -------------------------------------------------------------------------------- 1 | // This function calculates the direction a ship must travel to achieve the target inclination given the current ship's latitude and orbital velocity. 2 | 3 | //@LAZYGLOBAL off. 4 | 5 | function inst_az { 6 | parameter 7 | inc. // target inclination 8 | 9 | // find orbital velocity for a circular orbit at the current altitude. 10 | //local V_orb is sqrt( body:mu / ( ship:altitude + body:radius)). 11 | local V_orb is ship:velocity:orbit:mag. 12 | 13 | // project desired orbit onto surface heading 14 | local az_orb is arcsin ( cos(inc) / cos(ship:latitude)). 15 | if (inc < 0) { 16 | set az_orb to 180 - az_orb. 17 | } 18 | 19 | // create desired orbit velocity vector 20 | local V_star is heading(az_orb, 0)*v(0, 0, V_orb). 21 | 22 | // find horizontal component of current orbital velocity vector 23 | local V_ship_h is ship:velocity:orbit - vdot(ship:velocity:orbit, up:vector:normalized)*up:vector:normalized. 24 | 25 | // calculate difference between desired orbital vector and current (this is the direction we go) 26 | local V_corr is V_star - V_ship_h. 27 | 28 | // project the velocity correction vector onto north and east directions 29 | local vel_n is vdot(V_corr, ship:north:vector). 30 | local vel_e is vdot(V_corr, heading(90,0):vector). 31 | 32 | // calculate compass heading 33 | local az_corr is arctan2(vel_e, vel_n). 34 | return az_corr. 35 | } -------------------------------------------------------------------------------- /massout.ks: -------------------------------------------------------------------------------- 1 | clearscreen. 2 | until 1 < 0 { 3 | 4 | set mass1 to mass. 5 | set t1 to time:seconds. 6 | wait .1. 7 | set mass2 to mass. 8 | set t2 to time:seconds. 9 | 10 | set dt to t2-t1. 11 | set mout to (mass1-mass2)/dt. 12 | 13 | print round(mout,3) + " " at (0,0). 14 | 15 | } -------------------------------------------------------------------------------- /maxq.ks: -------------------------------------------------------------------------------- 1 | clearscreen. 2 | lock Q to ship:dynamicpressure. 3 | set MaxQ to 0. 4 | until false { 5 | 6 | if MaxQ <= Q { 7 | set MaxQ to Q. 8 | } 9 | 10 | print "MaxQ " + round(MaxQ,2) + " " at (0,1). 11 | print "Q " + round(Q,2) + " " at (0,2). 12 | print "Q/MaxQ " + round(100*Q/MaxQ,2) + "% " at (0,3). 13 | 14 | } -------------------------------------------------------------------------------- /rdz_body.ks: -------------------------------------------------------------------------------- 1 | // This script calculates a Maneuver Node to intercept a target body. It is assumed both target and ship are in near circular orbits 2 | declare parameter target_periapsis is 100000. 3 | 4 | clearscreen. 5 | for node in allnodes {remove node.} 6 | 7 | set R1 to ship:orbit:semimajoraxis. 8 | set R2 to target:orbit:semimajoraxis. 9 | if R1 < R2 { 10 | set Warp_P_or_A to "Apoapsis". 11 | } else { 12 | set Warp_P_or_A to "Periapsis". 13 | } 14 | 15 | set a_trans to (R1+R2)/2. 16 | set ecc_trans to abs(R2-R1)/(R1+R2). 17 | lock T_ship to ship:orbit:period. 18 | lock T_target to target:orbit:period. 19 | set T_trans to 2*constant:pi*sqrt((a_trans^3)/ship:body:MU). 20 | set Phase_burn to (T_trans/T_target)*180. 21 | set Phase_ang_tol to 20. 22 | lock Ship_TA to ship:orbit:trueanomaly. 23 | lock Ship_ecc to ship:orbit:eccentricity. 24 | 25 | lock Ship_angvel to VCRS(ship:velocity:orbit,(ship:position-ship:body:position)):normalized. 26 | set Phase_ang to VANG(-1*ship:body:position,target:position-ship:body:position). 27 | lock vec_check to VCRS(-1*ship:body:position,target:position-ship:body:position):normalized + Ship_angvel. 28 | 29 | if vec_check:mag > 1 { 30 | set Phase_ang to 360-Phase_ang. 31 | } 32 | 33 | set Burn_TA to Ship_TA + (Phase_ang - (180-Phase_burn)). 34 | 35 | if Burn_TA > 360 { 36 | set Burn_TA to Burn_TA - 360. 37 | } 38 | if Burn_TA < 0 { 39 | set Burn_TA to Burn_TA + 360. 40 | } 41 | 42 | set Ship_EA to 2*ARCTAN((TAN(Ship_TA/2))/sqrt((1+Ship_ecc)/(1-Ship_ecc))). 43 | set Ship_MA to Ship_EA*constant:pi/180 - Ship_ecc*SIN(Ship_EA). 44 | set Burn_EA to 2*ARCTAN((TAN(Burn_TA/2))/sqrt((1+Ship_ecc)/(1-Ship_ecc))). 45 | set Burn_MA to Burn_EA*constant:pi/180 - Ship_ecc*SIN(Burn_EA). 46 | set n to sqrt(ship:body:mu/(ship:orbit:semimajoraxis)^3). 47 | set Burn_eta_A to (Burn_MA-Ship_MA)/n. 48 | 49 | if Burn_eta_A < 0 { 50 | set Burn_eta_A to ship:orbit:period + Burn_eta_A. 51 | } 52 | 53 | set Delta_V to sqrt(ship:body:mu*(2/R1 - 1/a_trans))-sqrt(ship:body:mu/ship:orbit:semimajoraxis). 54 | 55 | set Phase_burn_test to 180-Phase_burn. 56 | set Phase_dot to -1*360/T_ship + 360/T_target. 57 | set T_burn to (Phase_burn_test - Phase_ang)/Phase_dot. 58 | if T_burn < 0{ 59 | if Phase_dot < 0{ 60 | set T_burn to T_burn + T_ship. 61 | } 62 | else { 63 | set T_burn to (Phase_burn_test - Phase_ang + 360)/Phase_dot. 64 | } 65 | } 66 | 67 | lock Target_angvel to VCRS(target:velocity:orbit,(target:position-Kerbin:position)):normalized. 68 | 69 | set PlaneAngDiff to VANG(Ship_angvel,Target_angvel). 70 | if PlaneAngDiff < 0.01 { 71 | set mynode to NODE(TIME:seconds + T_burn, 0, 0, Delta_V). 72 | ADD mynode. 73 | //clearscreen. 74 | print "Maneuver Node Added". 75 | print "Moving to Periapsis Solver". 76 | wait 3. 77 | } else { 78 | clearscreen. 79 | print "WARNING: Inclination Difference greater than 0.01 degrees!". 80 | wait 3. 81 | } 82 | lock orbit_check to nextnode:orbit:nextpatch. 83 | set good_man to false. 84 | if nextnode:orbit:hasnextpatch AND orbit_check:body = target { 85 | set test_periapsis to orbit_check:periapsis. 86 | set good_man to true. 87 | } 88 | set i to 1. 89 | set delta to 2. 90 | set delta_dir to -1. 91 | set tollerance to .1. 92 | 93 | until i >= 100 { 94 | 95 | set diff1 to abs(test_periapsis - target_periapsis). 96 | set Delta_V to Delta_V + delta*delta_dir. 97 | set nextnode:prograde to Delta_V. 98 | set test_periapsis to orbit_check:periapsis. 99 | set diff2 to abs(test_periapsis - target_periapsis). 100 | 101 | if diff2 > diff1 { 102 | set delta to delta/2. 103 | set delta_dir to -1*delta_dir. 104 | } 105 | 106 | if diff2 < tollerance { 107 | set bad_intercept to false. 108 | break. 109 | } 110 | 111 | set i to i+1. 112 | if i = 100 { 113 | if diff2 > 10*tollerance { 114 | set bad_intercept to true. 115 | } else { 116 | set bad_intercept to false. 117 | } 118 | } 119 | print "Iteration = " + i at(0,3). 120 | print "delta = " + delta at (0,4). 121 | print "delta_dir = " + delta_dir at (0,5). 122 | print "test_periapsis = " + round(test_periapsis,2) at (0,6). 123 | print "target_periapsis = " + target_periapsis at (0,7). 124 | 125 | } 126 | clearscreen. print "Solver finished". 127 | if bad_intercept { 128 | print "Bad Intercept". 129 | } else { 130 | print "Successful Intercept". 131 | print "Iterations " + i. 132 | print "Periapsis within " + round(diff2,4) + " meters". 133 | } 134 | wait 3. 135 | -------------------------------------------------------------------------------- /rdz_circular.ks: -------------------------------------------------------------------------------- 1 | // This script calculates a Maneuver Node to intercept a target vessel. It is assumed both target and ship are in near circular orbits 2 | clearscreen. 3 | for node in allnodes {remove node.} 4 | 5 | declare function ExecuteNode { 6 | clearscreen. 7 | lock throttle to 0. 8 | SAS off. 9 | lock DeltaV to nextnode:deltav:mag. 10 | set BurnTime to .5*DeltaV*mass/availablethrust. 11 | lock steering to nextnode. 12 | print "Aligning with Maneuver Node". 13 | until VANG(ship:facing:vector,nextnode:burnvector) < 1 { 14 | print "Direction Angle Error = " + round(VANG(ship:facing:vector,nextnode:burnvector),1) + " "at(0,1). 15 | } 16 | clearscreen. 17 | print "Warping to Node". 18 | print "Burn Starts at T-minus " + round(BurnTime,2) + "secs ". 19 | warpto(time:seconds + nextnode:eta - BurnTime - 10). 20 | wait until BurnTime >= nextnode:eta. 21 | 22 | clearscreen. 23 | lock throttle to DeltaV*mass/availablethrust. 24 | print "Executing Node". 25 | 26 | until DeltaV <= .1 { 27 | print "Delta V = " + round(DeltaV,1) + " " at(0,1). 28 | print "Throttle = " + MIN(100,round(throttle*100)) + "% " at(0,2). 29 | } 30 | lock throttle to 0. 31 | unlock all. 32 | remove nextnode. 33 | clearscreen. 34 | print "Node Executed". 35 | } 36 | 37 | declare function Circularize_per{ 38 | set Vper_cir to sqrt(ship:body:mu/(ship:body:radius + periapsis)). 39 | set DeltaV to Vper_cir - VELOCITYAT(ship,time:seconds + eta:periapsis):orbit:mag. 40 | set CirPer to NODE(TIME:seconds + eta:periapsis, 0, 0, DeltaV). 41 | ADD CirPer. 42 | wait 1. 43 | ExecuteNode(). 44 | } 45 | declare function Circularize_apo{ 46 | set Vapo_cir to sqrt(ship:body:mu/(ship:body:radius + apoapsis)). 47 | set DeltaV to Vapo_cir - VELOCITYAT(ship,time:seconds + eta:apoapsis):orbit:mag. 48 | set CirPer to NODE(TIME:seconds + eta:apoapsis, 0, 0, DeltaV). 49 | ADD CirPer. 50 | wait 1. 51 | ExecuteNode(). 52 | } 53 | set R1 to ship:orbit:semimajoraxis. 54 | set R2 to target:orbit:semimajoraxis. 55 | if R1 < R2 { 56 | set Warp_P_or_A to "Apoapsis". 57 | } else { 58 | set Warp_P_or_A to "Periapsis". 59 | } 60 | if (min(R1,R2)/(max(R1,R2))) > 0.99 { // When the target and ship have very close orbits, we will go ahead and try and match the orbits as close as we can 61 | // Match as close as you can to the target's circular orbit height. 62 | print "Orbits are Close Enough To Phase without Transfer". 63 | print "Burning to match intercept altitude more closely". 64 | set R_planet to ship:body:radius. 65 | set Rp to periapsis + R_planet. 66 | if Rp < R2 { // Decide whether we need to increase or decrease the periapsis 67 | set ecc_fix to (R2 - Rp)/(Rp + R2). 68 | set SMA_fix to (R2 + Rp)/2. 69 | set V_per_fix to sqrt(((1+ecc_fix)*ship:body:mu)/((1-ecc_fix)*SMA_fix)). 70 | set Delta_V_fix to V_per_fix - VELOCITYAT(ship,time:seconds + eta:periapsis):orbit:mag. 71 | } else { 72 | set ecc_fix to (Rp - R2)/(Rp + R2). 73 | set SMA_fix to (R2 + Rp)/2. 74 | set V_apo_fix to sqrt(((1-ecc_fix)*ship:body:mu)/((1+ecc_fix)*SMA_fix)). 75 | set Delta_V_fix to V_apo_fix - VELOCITYAT(ship,time:seconds + eta:periapsis):orbit:mag. 76 | } 77 | if Delta_V_fix > 0.1 { 78 | set fixnode to NODE(TIME:seconds + eta:periapsis, 0, 0, Delta_V_fix). 79 | ADD fixnode. 80 | wait 5. 81 | ExecuteNode(). 82 | if (R2-periapsis-R_planet) < (R2 - apoapsis - R_planet) { 83 | Circularize_per(). 84 | } else { 85 | Circularize_apo(). 86 | } 87 | } 88 | clearscreen. 89 | } 90 | set a_trans to (R1+R2)/2. 91 | set ecc_trans to abs(R2-R1)/(R1+R2). 92 | lock T_ship to ship:orbit:period. 93 | lock T_target to target:orbit:period. 94 | set T_trans to 2*constant:pi*sqrt((a_trans^3)/ship:body:MU). 95 | set Phase_burn to (T_trans/T_target)*180. 96 | set Phase_ang_tol to 20. 97 | lock Ship_TA to ship:orbit:trueanomaly. 98 | lock Ship_ecc to ship:orbit:eccentricity. 99 | 100 | lock Ship_angvel to VCRS(ship:velocity:orbit,(ship:position-ship:body:position)):normalized. 101 | set Phase_ang to VANG(-1*ship:body:position,target:position-ship:body:position). 102 | lock vec_check to VCRS(-1*ship:body:position,target:position-ship:body:position):normalized + Ship_angvel. 103 | 104 | if vec_check:mag > 1 { 105 | set Phase_ang to 360-Phase_ang. 106 | } 107 | 108 | set Burn_TA to Ship_TA + (Phase_ang - (180-Phase_burn)). 109 | 110 | if Burn_TA > 360 { 111 | set Burn_TA to Burn_TA - 360. 112 | } 113 | if Burn_TA < 0 { 114 | set Burn_TA to Burn_TA + 360. 115 | } 116 | 117 | set Ship_EA to 2*ARCTAN((TAN(Ship_TA/2))/sqrt((1+Ship_ecc)/(1-Ship_ecc))). 118 | set Ship_MA to Ship_EA*constant:pi/180 - Ship_ecc*SIN(Ship_EA). 119 | set Burn_EA to 2*ARCTAN((TAN(Burn_TA/2))/sqrt((1+Ship_ecc)/(1-Ship_ecc))). 120 | set Burn_MA to Burn_EA*constant:pi/180 - Ship_ecc*SIN(Burn_EA). 121 | set n to sqrt(ship:body:mu/(ship:orbit:semimajoraxis)^3). 122 | set Burn_eta_A to (Burn_MA-Ship_MA)/n. 123 | 124 | if Burn_eta_A < 0 { 125 | set Burn_eta_A to ship:orbit:period + Burn_eta_A. 126 | } 127 | 128 | set Delta_V_trans to sqrt(ship:body:mu*(2/R1 - 1/a_trans))-sqrt(ship:body:mu/ship:orbit:semimajoraxis). 129 | 130 | set Phase_burn_test to 180-Phase_burn. 131 | set Phase_dot to -1*360/T_ship + 360/T_target. 132 | set T_burn to (Phase_burn_test - Phase_ang)/Phase_dot. 133 | if T_burn < 0{ 134 | if Phase_dot < 0{ 135 | set T_burn to T_burn + T_ship. 136 | } 137 | else { 138 | set T_burn to (Phase_burn_test - Phase_ang + 360)/Phase_dot. 139 | } 140 | } 141 | 142 | // Solution B is to increase the time period 143 | // Solution C is to decrease the time period 144 | if (min(R1,R2)/(max(R1,R2))) > 0.99 { //For when the ships are in almost the same exact orbit. 145 | // Match as close as you can to the target's circular orbit height. 146 | set Phase_Time_B to ((360-Phase_ang)/360)*T_target. 147 | set Phase_Time_C to (Phase_ang/360)*T_target. 148 | set N_B to 1. 149 | set N_C to 1. 150 | set solution_B to 0. 151 | set solution_C to 0. 152 | set solution to 0. 153 | until solution >= 2 { 154 | if solution_B <= 0 { 155 | set RdzTime_B to T_target + Phase_Time_B/N_C. 156 | set SMA_B to ((((RdzTime_B)/(2*(constant:pi)))^2)*ship:body:mu)^(1/3). 157 | set New_apo_B to SMA_B*2 - (periapsis + R_planet). 158 | set solution_B to 1. 159 | set WaitTime_B to RdzTime_B*N_B. 160 | } 161 | if solution_C <=0 { 162 | set RdzTime_C to T_target - Phase_Time_C/N_C. 163 | set SMA_C to ((((RdzTime_C)/(2*(constant:pi)))^2)*ship:body:mu)^(1/3). 164 | set New_per_C to SMA_C*2 - (periapsis + R_planet). 165 | set TEST to New_per_C - (R_planet + ship:body:atm:height). 166 | if New_per_C < 0 OR TEST < 0{ 167 | set N_C to N_C + 1. 168 | } else { 169 | set solution_C to 1. 170 | } 171 | set WaitTime_C to RdzTime_C*N_C. 172 | } 173 | set solution to solution_B + solution_C. 174 | } 175 | if WaitTime_B < WaitTime_C { 176 | set ecc_B to ( New_apo_B - R1)/(New_apo_B + R1). 177 | set V_per to sqrt(((1+ecc_B)*ship:body:mu)/((1-ecc_B)*SMA_B)). 178 | set Delta_V_alt to V_per - sqrt(ship:body:mu/R1). 179 | set Warp_P_or_A to "Periapsis". 180 | } else { 181 | set ecc_C to (R1 - New_per_C)/(New_per_C + R1). 182 | set V_apo to sqrt(((1-ecc_C)*ship:body:mu)/((1+ecc_C)*SMA_C)). 183 | set Delta_V_alt to V_apo - sqrt(ship:body:mu/R1). 184 | set Warp_P_or_A to "Apoapsis". 185 | } 186 | } else { 187 | set WaitTime_B to (T_burn+T_trans/2)*2. 188 | set WaitTime_C to (T_burn+T_trans/2)*2. 189 | } 190 | 191 | if (T_burn+T_trans/2) < min(WaitTime_B,WaitTime_C) { 192 | set node_eta_sel to T_burn. 193 | set Delta_V to Delta_V_trans. 194 | } else { 195 | set node_eta_sel to eta:periapsis. 196 | set Delta_V to Delta_V_alt. 197 | } 198 | //print "Phase_burn_test = " + round(Phase_burn_test). 199 | lock Target_angvel to VCRS(target:velocity:orbit,(target:position-Kerbin:position)):normalized. 200 | 201 | set PlaneAngDiff to VANG(Ship_angvel,Target_angvel). 202 | if PlaneAngDiff < 0.01 { 203 | set mynode to NODE(TIME:seconds + node_eta_sel, 0, 0, Delta_V). 204 | ADD mynode. 205 | //clearscreen. 206 | print "Maneuver Node Added". 207 | print "Executing Burn". 208 | wait 3. 209 | } else { 210 | clearscreen. 211 | print "WARNING: Inclination Difference greater than 0.01 degrees!". 212 | wait 3. 213 | } 214 | ExecuteNode(). 215 | clearscreen. 216 | print "Setting Up Maneuver Node at Intercept Point". 217 | wait 3. 218 | if Warp_P_or_A = "Periapsis" { 219 | Circularize_per(). 220 | } else { 221 | Circularize_apo(). 222 | } 223 | clearscreen. 224 | print "Rendezvous Maneuver Complete". 225 | wait 3. -------------------------------------------------------------------------------- /rdz_man.ks: -------------------------------------------------------------------------------- 1 | clearscreen. 2 | lock relvelocity to target:velocity:orbit - ship:velocity:orbit. 3 | lock targetdirection to target:position:normalized. 4 | lock SideSlip to VCRS(VCRS(targetdirection,ship:velocity:orbit),targetdirection):normalized. 5 | set SideSlipCoef to 4. 6 | lock SideSlipSpeed to VDOT(SideSlip,relvelocity)/SideSlipCoef. 7 | //lock PointVector to relvelocity+SideSlip*SideSlipSpeed. 8 | lock PointVector to relvelocity. 9 | lock steering to PointVector:direction. 10 | lock DeltaV to relvelocity:mag. 11 | lock throttle to 0. 12 | lock amax to availablethrust/mass. 13 | lock alignang to VANG(ship:facing:vector,PointVector). 14 | print "Aligning to Retrograde Burn". 15 | set TargetPos to VECDRAW(V(0,0,0),target:position,GREEN,"Target Position",1.0,TRUE,.5). 16 | set RelativeVel to VECDRAW(V(0,0,0),relvelocity,RED,"RelativeVel",1.0,TRUE,.5). 17 | until alignang < 1 { 18 | print "Direction Angle Error = " + round(alignang,1) + " "at(0,2). 19 | } 20 | clearscreen. 21 | print "Zeroing out speed to target". 22 | wait 3. 23 | until DeltaV <= .1 { 24 | set TargetPos to VECDRAW(V(0,0,0),target:position,GREEN,"Target Position",1.0,TRUE,.5). 25 | set RelativeVel to VECDRAW(V(0,0,0),relvelocity,RED,"RelativeVel",1.0,TRUE,.5). 26 | set SideSlipVec to VECDRAW(relvelocity,(1/SideSlipCoef)*SideSlip*SideSlipSpeed,Blue,"SideSlip",1.0,TRUE,.5). 27 | set PointDrawVec to VECDRAW(V(0,0,0),PointVector,Blue," ",1.0,TRUE,.5). 28 | 29 | lock throttle to DeltaV/amax. 30 | } 31 | lock throttle to 0. 32 | clearscreen. 33 | print "Rendezvous Phase 1 Complete, Phase 2 Begin". 34 | set bufferdist to 50. 35 | lock stopcheck to (target:position:mag - bufferdist) - 2*(VDOT(target:position:normalized,relvelocity))^2/amax. 36 | lock PointVector to target:position - SideSlip*SideSlipSpeed. 37 | print "Aligning to Prograde Burn". 38 | until alignang < 1 { 39 | print "Direction Angle Error = " + round(alignang,1) + " "at(0,2). 40 | } 41 | clearscreen. 42 | print "Accelerating to Target". 43 | wait 3. 44 | set throttlecheck to stopcheck. 45 | until stopcheck < 0 { 46 | lock throttle to sqrt(max(0,stopcheck/throttlecheck)). 47 | print "amax = " + round(amax,2) at (0,2). 48 | print "stopcheck = " + round(stopcheck,2) at(0,3). 49 | } 50 | lock throttle to 0. 51 | lock PointVector to relvelocity+SideSlip*SideSlipSpeed. 52 | set startretro to .25*target:position:mag+bufferdist. 53 | set SideSlipCoef to 1. 54 | until DeltaV <= .1 { 55 | set TargetPos to VECDRAW(V(0,0,0),target:position,GREEN,"Target Position",1.0,TRUE,.5). 56 | set RelativeVel to VECDRAW(V(0,0,0),relvelocity,RED,"RelativeVel",1.0,TRUE,.5). 57 | set SideSlipVec to VECDRAW(relvelocity,2*SideSlip*SideSlipSpeed,Blue,"SideSlip",1.0,TRUE,.5). 58 | set PointDrawVec to VECDRAW(V(0,0,0),PointVector,WHITE," ",1.0,TRUE,.5). 59 | set Alt_ship1 to altitude. 60 | set Alt_target1 to target:altitude. 61 | set Diff1 to abs(Alt_ship1 - Alt_target1). 62 | wait .0001. 63 | set Alt_ship2 to altitude. 64 | set Alt_target2 to target:altitude. 65 | set Diff2 to abs(Alt_ship2 - Alt_target2). 66 | set diff to Diff2-Diff1. 67 | if startretro > target:position:mag { 68 | lock throttle to DeltaV/amax. 69 | } 70 | print "amax = " + round(amax,2) at (0,2). 71 | print "stopcheck = " + round(stopcheck,2) at(0,3). 72 | print "Target Dist = " + round(target:position:mag,2) at(0,4). 73 | print "startretro = " + round(startretro,2) at(0,5). 74 | } 75 | lock throttle to 0. 76 | CLEARVECDRAWS(). -------------------------------------------------------------------------------- /rdz_man2.ks: -------------------------------------------------------------------------------- 1 | clearscreen. 2 | lock relvelocity to ship:velocity:orbit - target:velocity:orbit. 3 | lock targetdirection to target:position:normalized. 4 | lock SideSlip_vec to VCRS(VCRS(targetdirection,ship:velocity:orbit),targetdirection):normalized. 5 | set SideSlipCoef to 4. 6 | lock SideSlipSpeed to VDOT(SideSlip_vec,relvelocity)/SideSlipCoef. 7 | lock max_acc_tar to VDOT(targetdirection,availablethrust*ship:facing:vector)/mass. 8 | lock target_dist to target:position:mag. 9 | lock speed_to_target to VDOT(relvelocity,targetdirection). 10 | 11 | //lock PointVector to relvelocity+SideSlip_vec*SideSlipSpeed. 12 | lock PointVector to relvelocity. 13 | lock steering to PointVector:direction. 14 | lock DeltaV to relvelocity:mag. 15 | lock throttle to 0. 16 | lock amax to availablethrust/mass. 17 | lock alignang to VANG(ship:facing:vector,PointVector). 18 | print "Aligning to Retrograde Burn". 19 | set TargetPos to VECDRAW(V(0,0,0),target:position,GREEN,"Target Position",1.0,TRUE,.5). 20 | set RelativeVel to VECDRAW(V(0,0,0),relvelocity,RED,"RelativeVel",1.0,TRUE,.5). 21 | until alignang < 1 { 22 | print "Direction Angle Error = " + round(alignang,1) + " "at(0,2). 23 | } 24 | 25 | until DeltaV <= .1 { 26 | set TargetPos to VECDRAW(V(0,0,0),target:position,GREEN,"Target Position",1.0,TRUE,.5). 27 | set RelativeVel to VECDRAW(V(0,0,0),relvelocity,RED,"RelativeVel",1.0,TRUE,.5). 28 | set SideSlipVec to VECDRAW(relvelocity,(1/SideSlipCoef)*SideSlip_vec*SideSlipSpeed,Blue,"SideSlip_vec",1.0,TRUE,.5). 29 | set PointDrawVec to VECDRAW(V(0,0,0),PointVector,Blue," ",1.0,TRUE,.5). 30 | set Alt_ship1 to altitude. 31 | set Alt_target1 to target:altitude. 32 | set Diff1 to abs(Alt_ship1 - Alt_target1). 33 | wait .0001. 34 | set Alt_ship2 to altitude. 35 | set Alt_target2 to target:altitude. 36 | set Diff2 to abs(Alt_ship2 - Alt_target2). 37 | set diff to Diff2-Diff1. 38 | if diff >= 0 { 39 | lock throttle to DeltaV/amax. 40 | } 41 | } 42 | lock throttle to 0. 43 | clearscreen. 44 | print "Rendezvous Phase 1 Complete, Phase 2 Begin". 45 | set bufferdist to 50. 46 | lock stopcheck to (target:position:mag - bufferdist) - 2*(VDOT(target:position:normalized,relvelocity))^2/amax. 47 | lock PointVector to target:position. 48 | print "Aligning to Prograde Burn". 49 | until alignang < 1 { 50 | print "Direction Angle Error = " + round(alignang,1) + " "at(0,2). 51 | } 52 | clearscreen. 53 | set throttlecheck to stopcheck. 54 | until stopcheck < 0 { 55 | lock throttle to sqrt(max(0,stopcheck/throttlecheck)). 56 | print "amax = " + round(amax,2) at (0,2). 57 | print "stopcheck = " + round(stopcheck,2) at(0,3). 58 | } 59 | lock throttle to 0. 60 | lock PointVector to relvelocity+SideSlip_vec*SideSlipSpeed. 61 | set startretro to .25*target:position:mag+bufferdist. 62 | set SideSlipCoef to 1. 63 | until DeltaV <= .1 { 64 | set TargetPos to VECDRAW(V(0,0,0),target:position,GREEN,"Target Position",1.0,TRUE,.5). 65 | set RelativeVel to VECDRAW(V(0,0,0),relvelocity,RED,"RelativeVel",1.0,TRUE,.5). 66 | set SideSlipVec to VECDRAW(relvelocity,2*SideSlip_vec*SideSlipSpeed,Blue,"SideSlip_vec",1.0,TRUE,.5). 67 | set PointDrawVec to VECDRAW(V(0,0,0),PointVector,WHITE," ",1.0,TRUE,.5). 68 | set Alt_ship1 to altitude. 69 | set Alt_target1 to target:altitude. 70 | set Diff1 to abs(Alt_ship1 - Alt_target1). 71 | wait .0001. 72 | set Alt_ship2 to altitude. 73 | set Alt_target2 to target:altitude. 74 | set Diff2 to abs(Alt_ship2 - Alt_target2). 75 | set diff to Diff2-Diff1. 76 | if startretro > target:position:mag { 77 | lock throttle to DeltaV/amax. 78 | } 79 | print "amax = " + round(amax,2) at (0,2). 80 | print "stopcheck = " + round(stopcheck,2) at(0,3). 81 | print "Target Dist = " + round(target:position:mag,2) at(0,4). 82 | print "startretro = " + round(startretro,2) at(0,5). 83 | } 84 | lock throttle to 0. 85 | CLEARVECDRAWS(). -------------------------------------------------------------------------------- /rdz_target.KS: -------------------------------------------------------------------------------- 1 | clearscreen. 2 | 3 | lock Ship_angvel to VCRS(ship:velocity:orbit,(ship:position-ship:body:position)). 4 | lock Target_angvel to VCRS(target:velocity:orbit,(target:position-ship:body:position)). 5 | 6 | lock PlaneAngDiff to VANG(Ship_angvel,Target_angvel). 7 | set i to 1. 8 | set max_iter to 5. 9 | until PlaneAngDiff < 0.01 OR i >= max_iter{ 10 | clearscreen. 11 | print "Matching Inclination". 12 | print "Inclination Match Iteration: " + i. 13 | wait 3. 14 | run inclinationmatch. 15 | set i to i+1. 16 | } 17 | 18 | clearscreen. 19 | print "Inclination Match Complete". 20 | wait 3. 21 | if target:istype("Body") { 22 | run rdz_body. 23 | } else { 24 | run rdz_circular. 25 | } 26 | //run rdz_man. -------------------------------------------------------------------------------- /rendezvous.ks: -------------------------------------------------------------------------------- 1 | clearscreen. 2 | lock relvelocity to target:velocity:orbit - ship:velocity:orbit. 3 | lock targetdirection to target:position:normalized. 4 | lock SideSlip to VCRS(VCRS(targetdirection,ship:velocity:orbit),targetdirection):normalized. 5 | lock SideSlipSpeed to VDOT(SideSlip,relvelocity). 6 | lock steering to (relvelocity+SideSlip*SideSlipSpeed):direction. 7 | lock DeltaV to relvelocity:mag. 8 | 9 | until DeltaV <= .1 { 10 | set TargetPos to VECDRAW(V(0,0,0),target:position,GREEN,"Target Position",1.0,TRUE,.5). 11 | set RelativeVel to VECDRAW(V(0,0,0),relvelocity,RED,"RelativeVel",1.0,TRUE,.5). 12 | set SideSlipVec to VECDRAW(relvelocity,SideSlip*SideSlipSpeed,Blue,"SideSlip",1.0,TRUE,.5). 13 | set Alt_ship1 to altitude. 14 | set Alt_target1 to target:altitude. 15 | set Diff1 to abs(Alt_ship1 - Alt_target1). 16 | wait .0001. 17 | set Alt_ship2 to altitude. 18 | set Alt_target2 to target:altitude. 19 | set Diff2 to abs(Alt_ship2 - Alt_target2). 20 | set diff to Diff2-Diff1. 21 | if diff <= 0 { 22 | lock throttle to DeltaV*mass/availablethrust. 23 | break. 24 | } 25 | } -------------------------------------------------------------------------------- /spot_land_eq.ks: -------------------------------------------------------------------------------- 1 | // Script to do a spot landing on equatorial trajectory. 2 | set landing_pos to LATLNG(5,120). 3 | //set landing_pos to LATLNG(-0.09720767,-74.557677). 4 | 5 | clearscreen. 6 | clearvecdraws(). 7 | 8 | SAS OFF. 9 | if HASNODE { 10 | run executenode. 11 | } 12 | wait 0.001. 13 | set max_acc to maxthrust/mass. 14 | set peri_v to velocityat(ship,time:seconds + eta:periapsis):orbit:mag. 15 | set delta_time to peri_v/max_acc. 16 | 17 | 18 | //warpto(time:seconds + eta:periapsis - 2*delta_time). 19 | function Hysteresis { 20 | declare parameter input,prev_output, right_hand_limit, left_hand_limit,right_hand_output is true. 21 | set output to prev_output. 22 | if prev_output = right_hand_output { 23 | if input <= left_hand_limit { 24 | set output to not(right_hand_output). 25 | } 26 | } else { 27 | if input >= right_hand_limit { 28 | set output to right_hand_output. 29 | } 30 | } 31 | return output. 32 | } 33 | 34 | function Vmax_v { 35 | declare parameter buffer_terrain is 0, TouchDownSpeed is 5. 36 | local true_alt to altitude - ship:geoposition:terrainheight. 37 | local V to ship:velocity:orbit. 38 | local R to ship:body:position. 39 | local Vper to VDOT(VCRS(R,VCRS(V,R)):normalized,V). 40 | local AccelCent to (Vper^2)/R:mag. 41 | local MaxThrustAccUp to availablethrust/mass. 42 | local GravUp to (-1)*(ship:body:mu)/((R:mag)^2). 43 | local MaxAccUp to MaxThrustAccUp + GravUp + AccelCent. 44 | local FPAsurf to 90 - VANG(UP:vector,ship:velocity:surface). 45 | local Vmax to sqrt(MAX(0,2*(true_alt - buffer_terrain)*MaxAccUp - TouchDownSpeed^2)). 46 | return Vmax. 47 | } 48 | 49 | function Vmax_h { 50 | declare parameter buffer_dist is 0. 51 | local R to ship:body:position. 52 | local V to ship:velocity:orbit. 53 | local MaxThrustAccHor to availablethrust/mass. 54 | local angle_diff_h to VANG(-R, landing_pos:position - R). 55 | local dist_diff_h to (angle_diff_h/360)*2*(constant:pi)*R:mag. 56 | local Vmax to sqrt(MAX(0.001,2*(dist_diff_h - buffer_dist)*MaxThrustAccHor)). 57 | 58 | local dir_check_vel to VCRS(V,R). 59 | local dir_check_pos to VCRS(-R,landing_pos:position-R). 60 | local dir_check to 1. 61 | if VDOT(dir_check_vel,dir_check_pos) > 0 { 62 | set dir_check to 1. 63 | } else { 64 | set dir_check to -1. 65 | } 66 | 67 | return dir_check*Vmax. 68 | } 69 | 70 | function Follow_throttle_func { 71 | local R to ship:body:position. 72 | local V to ship:velocity:surface. 73 | local V_ref to (V:mag)*(landing_pos:position:normalized). 74 | local h to altitude - landing_pos:terrainheight. // used to adjust the V_ref later 75 | local V_diff to V_ref - V. 76 | local throttle_sel to (V_diff*mass)/availablethrust. 77 | 78 | return throttle_sel. 79 | } 80 | 81 | function S_throttle_func { 82 | declare parameter t_0 is 1. 83 | local R to ship:body:position. 84 | local V to ship:velocity:surface. 85 | local S to V:mag. 86 | local V_side to VCRS(V,R):normalized. 87 | local V_per to VCRS(R,V_side):normalized. 88 | local T_vec to VCRS(R,VCRS(landing_pos:position,R)):normalized. 89 | local delta_v to -1*VDOT(V_side,(T_vec*S - V_per*S)). 90 | 91 | return delta_v. 92 | } 93 | 94 | lock R to ship:body:position. 95 | lock V_surf to ship:velocity:surface. 96 | lock g to ship:body:mu/(R:mag^2). 97 | lock Velocity_h_norm to VCRS(VCRS(R,landing_pos:position),R):normalized. 98 | lock Speed_h to VDOT(Velocity_h_norm,ship:velocity:surface). 99 | lock speed_diff_h to Speed_h-landing_pos:altitudevelocity(altitude):orbit:mag. 100 | lock true_alt to altitude - ship:geoposition:terrainheight. 101 | 102 | lock V_vec to UP:vector. 103 | lock H_vec to VCRS(R,VCRS(V_surf,R)):normalized. 104 | lock S_vec to -1*VCRS(V_surf,R):normalized. 105 | 106 | set KP_V to .01. 107 | set KD_V to 0.005. 108 | set V_throttle_PID to PIDLOOP(KP_V,0,KD_V,0,1). 109 | set V_throttle_PID:setpoint to Vmax_v(). 110 | 111 | set KP_H to .01. 112 | set KD_H to 0.002.//0.02. 113 | set H_throttle_PID to PIDLOOP(KP_H,0,KD_H,-1,1). 114 | set H_throttle_PID:setpoint to Vmax_h(). 115 | 116 | set KS to 1/5. // Time constant 117 | set S_throttle to S_throttle_func(2). 118 | 119 | set throttle_vec to V_vec*V_throttle_PID:update(time:seconds,-1*verticalspeed) + H_vec*H_throttle_PID:update(time:seconds,Speed_h) + S_vec*S_throttle. 120 | 121 | lock steering to throttle_vec:direction. 122 | 123 | lock land_surf to VANG(landing_pos:position,ship:velocity:surface). 124 | 125 | clearscreen. 126 | 127 | set touchdown_speed to -5. 128 | set alt_cutoff to 100. 129 | 130 | set throttle_hyst to false. 131 | set throttle_hyst_UL to 50. 132 | set throttle_hyst_LL to 1. 133 | 134 | set ang_hyst to false. 135 | set ang_hyst_UL to 50. 136 | set ang_hyst_LL to 10. 137 | 138 | set left_over_flag to false. 139 | set Follow_Mode to false. 140 | set TouchDown_Mode to false. 141 | 142 | set LandingVector to VECDRAW((alt:radar)*(landing_pos:position - R):normalized,landing_pos:position,GREEN,"Landing Position",1.0,TRUE,.5). 143 | set LandingVector:vectorupdater to { return (altitude-landing_pos:terrainheight)*(landing_pos:position - R):normalized.}. 144 | set LandingVector:startupdater to { return landing_pos:position.}. 145 | 146 | set LandingPositionVector to VECDRAW(V(0,0,0),landing_pos:position,RED,"Landing Vector",1.0,TRUE,.5). 147 | set LandingPositionVector:vectorupdater to { return landing_pos:position.}. 148 | set LandingPositionVector:startupdater to { return V(0,0,0).}. 149 | 150 | set SurfaceVelocity to VECDRAW(V(0,0,0),ship:velocity:surface,BLUE,"Surface Velocity",1.0,TRUE,.5). 151 | set SurfaceVelocity:vectorupdater to { return ship:velocity:surface.}. 152 | set SurfaceVelocity:startupdater to { return V(0,0,0).}. 153 | 154 | until ship:status = "LANDED" { 155 | 156 | 157 | set V_throttle_PID:setpoint to Vmax_v(). 158 | set H_throttle_PID:setpoint to Vmax_h(). 159 | if verticalspeed > touchdown_speed AND true_alt < alt_cutoff AND not(TouchDown_Mode){ 160 | set TouchDown_Mode to True. 161 | } 162 | 163 | if TouchDown_Mode{ 164 | set V_throttle to (1-(touchdown_speed-verticalspeed)/touchdown_speed)*mass*g/availablethrust. 165 | GEAR ON. 166 | } else { 167 | set V_throttle to MIN(1,1-V_throttle_PID:update(time:seconds,-1*verticalspeed)). 168 | GEAR OFF. 169 | } 170 | 171 | set H_throttle_test to MIN(1,1-H_throttle_PID:update(time:seconds,Speed_h)). 172 | //set H_throttle_test to H_throttle_func(). 173 | 174 | set S_deltaV to S_throttle_func(2). 175 | set S_throttle_enable to true. 176 | set S_throttle_test to (S_deltaV*mass)/(availablethrust*1). 177 | //if throttle_hyst { 178 | // set S_throttle_enable to true. 179 | // set S_throttle_test to (S_deltaV*mass)/(availablethrust*1). 180 | //} else { 181 | // set S_throttle_enable to false. 182 | // set S_throttle_test to 0. 183 | //} 184 | 185 | if sqrt(V_throttle^2 + H_throttle_test^2 + S_throttle_test^2) > 1 { 186 | set left_over_flag to True. 187 | set left_over to 1- V_throttle^2. 188 | if H_throttle_test > sqrt(left_over) { 189 | set H_throttle to MAX(0,MIN(H_throttle_test,sqrt(left_over))). 190 | set S_throttle to 0. 191 | } else { 192 | set H_throttle to H_throttle_test. 193 | set S_throttle to MAX(0,MIN(S_throttle_test,sqrt(left_over - H_throttle_test^2))). 194 | } 195 | } else { 196 | set left_over_flag to False. 197 | set S_throttle to S_throttle_test. 198 | set H_throttle to H_throttle_test. 199 | } 200 | set Follow_Mode_Ang to VANG(landing_pos:position,ship:velocity:surface). 201 | set Follow_Mode_Dist to VXCL(UP:vector,landing_pos:position):mag/true_alt. 202 | if Follow_Mode_Ang < 15 AND Follow_Mode_Dist < 0.1{ 203 | set Follow_Mode to True. 204 | } 205 | if groundspeed < 10 AND not(Follow_Mode) { 206 | set Follow_Mode to True. 207 | } 208 | 209 | if Follow_Mode { 210 | set throttle_vec to V_vec*V_throttle + Follow_throttle_func(). 211 | } else { 212 | set throttle_vec to V_vec*V_throttle - H_vec*H_throttle + S_vec*S_throttle. 213 | } 214 | 215 | set throttle_hyst_test to throttle_vec:mag. 216 | set ang_diff to VANG(throttle_vec,ship:facing:vector). 217 | set throttle_hyst to Hysteresis(100*throttle_hyst_test,throttle_hyst, throttle_hyst_UL, throttle_hyst_LL). 218 | set ang_hyst to Hysteresis(ang_diff,ang_hyst,ang_hyst_UL,ang_hyst_LL,False). 219 | 220 | if throttle_hyst { 221 | if ang_hyst { 222 | lock throttle to throttle_vec:mag. 223 | lock steering to LOOKDIRUP(throttle_vec,facing:topvector). 224 | } else { 225 | lock throttle to 0. 226 | lock steering to LOOKDIRUP(throttle_vec,facing:topvector). 227 | } 228 | } else { 229 | lock throttle to 0. 230 | lock steering to LOOKDIRUP(srfretrograde:vector,facing:topvector). 231 | } 232 | 233 | print "V_throttle = " + round(100*(VDOT(V_vec,throttle_vec)),1) + "% "at(0,0). 234 | print "H_throttle = " +round(100*(VDOT(H_vec,throttle_vec)),1) + "% " at(0,1). 235 | print "S_throttle = " +round(100*(VDOT(S_vec,throttle_vec)),1) + "% " at(0,2). 236 | print "Vmax_v = " +round(Vmax_v,2) at(0,3). 237 | print "Vspeed = " +round(verticalspeed,2) at(0,4). 238 | print "Vmax_h = " +round(Vmax_h,2) at(0,5). 239 | print "Vspeed_h = " +round(Speed_h,2) at(0,6). 240 | print "Longitude = " +round(ship:geoposition:lng,2) at(0,7). 241 | print "Throttle = " + round(100*throttle_vec:mag,0) + "% " at(0,8). 242 | print "throttle_hyst = " + throttle_hyst + " " at(0,9). 243 | print "left_over_flag = " + left_over_flag + " " at(0,10). 244 | print "ang_diff = " + round(ang_diff,1) + " " at(0,11). 245 | print "ang_hyst = " + ang_hyst + " " at(0,12). 246 | print "S_deltaV = " + round(S_deltaV,2) + " " at(0,13). 247 | print "groundspeed = " + round(groundspeed,2) + " " at(0,14). 248 | print "land_surf = " + round(land_surf,2) + " " at(0,15). 249 | print "Follow_Mode = " + Follow_Mode + " " at(0,16). 250 | print "TouchDown_Mode = " + TouchDown_Mode + " " at(0,17). 251 | print "S_throttle_enable = " + S_throttle_enable + " " at(0,18). 252 | print "S_throttle_test = " + round(S_throttle_test,2) + " " at(0,19). 253 | print "throttle_hyst_test = " + round(throttle_hyst_test,2) + " " at(0,20). 254 | 255 | 256 | wait 0. 257 | } 258 | lock throttle to 0. 259 | SAS ON. 260 | wait 5. -------------------------------------------------------------------------------- /vertical_landing.ks: -------------------------------------------------------------------------------- 1 | // This script is essentially the same principle as the horizontal landing however it 2 | declare parameter LandingPosition is latlng(0,0), SpotLanding is FALSE. 3 | // This script can funcion on its own and thus doesn't need the LandingPosition to be displayed 4 | // SpotLanding is used for when using horizontal_landing 5 | clearscreen. 6 | 7 | declare function Hysteresis { 8 | declare parameter input,prev_output, right_hand_limit, left_hand_limit,right_hand_output is true. 9 | set output to prev_output. 10 | if prev_output = right_hand_output { 11 | if input <= left_hand_limit { 12 | set output to not(right_hand_output). 13 | } 14 | } else { 15 | if input >= right_hand_limit { 16 | set output to right_hand_output. 17 | } 18 | } 19 | return output. 20 | } 21 | 22 | // This sets some landing parameters such as determining what the true altiude is of the base of the rocket. 23 | set ship:control:pilotmainthrottle to 0. 24 | set TouchDownSpeed to 1. // This is set by the user, I set it to 5 since the landing legs break at 6. 25 | set MaxCount to 3. // Used to average the derivative term since it can get pretty eratic 26 | set buffer_alt to 20. // Its not perfect, so a little wiggle room is good to retract the legs. 27 | lock true_alt to altitude - ship:geoposition:terrainheight.// - start_alt. // Again measured from the bottom of the craft. 28 | // This script is meant to be used from a flat surface to launch and return. It can be adapted for landing from any situation. 29 | SAS off. 30 | GEAR ON. 31 | set Throttle_RHL to 60. 32 | set Throttle_LHL to 10. 33 | 34 | if ship:body = "Mun" { 35 | set buffer_terrain to 0. 36 | } 37 | if ship:body = "Duna" { 38 | set buffer_terrain to 10. 39 | } 40 | if ship:body = "Mars" { 41 | set buffer_terrain to 10. 42 | } 43 | set buffer_terrain to 10. 44 | lock V to ship:velocity:orbit. 45 | lock R to ship:body:position. 46 | lock Vper to VDOT(VCRS(R,VCRS(V,R)):direction:vector,V). 47 | lock AccelCent to (Vper^2)/R:mag. 48 | // After it goes up high the rocket will wait to fall back down. 49 | // I manually select the retrograde selection on the SAS. I would do it with the cooked steering but its current 50 | // iteration was not working well with the test ship. 51 | lock MaxThrustAccUp to VDOT(UP:vector,availablethrust/mass*srfretrograde:vector). 52 | // This assumes the ship is pointed exactly retrograde. Meaning this can be used as a gravity turn for landing as well. 53 | lock GravUp to (-1)*(ship:body:mu)/((R:mag)^2). 54 | lock MaxAccUp to MaxThrustAccUp + GravUp + AccelCent. // I opted out of adding drag since its finiky, this adds some safety margin though 55 | lock FPAsurf to 90 - VANG(UP:vector,ship:velocity:surface). 56 | 57 | clearscreen. 58 | lock Vmax to sqrt(MAX(0,2*(true_alt - buffer_terrain)*MaxAccUp + TouchDownSpeed^2)). 59 | // The magic of the script. This equation is derived assuming an ascent starting at the touchdown speed and accelerating 60 | // at full throttle. It auto adjusts based on the altitude and the Max Acceleration as it changes with mass loss. 61 | // Basic PD loop. I want essentially no overshoot and very little error at the end. The Kp_v and Kd_v gains are tuned so at the finish 62 | // of the script the error > 0 and absolutely no overshoot. Tune to your liking however (fair warning, you have VERY little margin 63 | // when you are landing. The burn times I have seen are very short. That depends on the ship's TWR however. 64 | lock error_v to Vmax + verticalspeed. 65 | set errorP_v to 0. 66 | set Kp_v to .04. 67 | set errorD_v to 0. 68 | set Kd_v to 0.04. 69 | set ThrustSet to 0. 70 | lock throttle to ThrustSet. 71 | set time0 to time:seconds. 72 | lock time1 to time:seconds - time0. 73 | set count to 1. 74 | set flightmode to 1. 75 | lock steering to srfretrograde. 76 | set Thrust_Hyst_En to false. 77 | 78 | until flightmode = 2 AND ship:status = "LANDED" { 79 | // If you are using this in tandem with Horizontal Landing then this will display where you are landing. 80 | if SpotLanding { 81 | set LandingVector to VECDRAW(LandingPosition:position,(altitude-LandingPosition:terrainheight+25)*(LandingPosition:position-R):normalized,GREEN,"Landing Position",1.0,TRUE,.5). 82 | } 83 | 84 | if flightmode = 1 { 85 | if verticalspeed > 0 AND (AccelCent+GravUp) > 0 { 86 | set ThrustSet to 1. 87 | clearscreen. 88 | print "Burning to Kill Speed, Centrifugal Acceleration too high". 89 | wait until verticalspeed < 0. 90 | clearscreen. 91 | } 92 | set error1 to error_v. 93 | set t1 to time1. 94 | wait .00001. 95 | set error2 to error_v. 96 | set t2 to time1. 97 | set dt to t2-t1. 98 | // I like to take an average error so its not going crazy due to discrete calculations. 99 | set errorP_v to .5*(error1+error2). 100 | set errorD_v_test to (error2-error1)/dt. 101 | //This next part is used as a running average, the Derivative term was behaving eratically thus this damps out the spikes. 102 | if count < MaxCount { 103 | if count < 2 { 104 | set errorD_v to errorD_v_test. 105 | } 106 | if count >= 2 { 107 | set errorD_v to (errorD_v*(count-1)+errorD_v_test)/count. 108 | } 109 | set count to count + 1. 110 | } 111 | if count >= MaxCount { 112 | 113 | set errorD_v to (errorD_v*(MaxCount-1)+errorD_v_test)/MaxCount. 114 | } 115 | 116 | set ThrustDemand to 1 - Kp_v*errorP_v - Kd_v*errorD_v. 117 | if ThrustDemand > 1 { set ThrustDemand to 1. } 118 | set Thrust_Hyst_En to Hysteresis(ThrustDemand,Thrust_Hyst_En,Throttle_RHL/100,Throttle_LHL/100). 119 | 120 | if Thrust_Hyst_En { 121 | set ThrustSet to ThrustDemand. 122 | } else { 123 | set ThrustSet to 0. 124 | } 125 | 126 | if error_v < 0 { 127 | set ThrustSet to 1. // This is very important. If the error ever drops below 0, it means it might crash since the 128 | // equation is calculated based on full thrust. 129 | } 130 | 131 | } 132 | // Cut off conditions for exiting the vertical landing 133 | if flightmode = 1 AND true_alt < buffer_alt AND verticalspeed > -1*TouchDownSpeed AND GroundSpeed < 1 { 134 | GEAR on. 135 | lock steering to up. 136 | lock throttle to .99*mass*-1*GravUp/availablethrust. 137 | set flightmode to 2. 138 | } 139 | if flightmode = 1 AND verticalspeed > -1*TouchDownSpeed AND GroundSpeed < 1 { 140 | GEAR on. 141 | lock steering to up. 142 | lock throttle to .99*mass*-1*GravUp/availablethrust. 143 | set flightmode to 2. 144 | } 145 | // Some data readouts. Pay attention to the Error term, make sure it doesn't drop below 0. 146 | 147 | print "Vmax = " + round(-1*Vmax,2) + " "at(0,0). 148 | print "VertSpeed = " + round(verticalspeed,2) + " " at (0,1). 149 | print "Radar Alt = " + round(true_alt,2) + " " at(0,2). 150 | print "Error Vert = " + round(error_v,2) + " " at(0,3). 151 | print "ThrustSet = " + round(ThrustSet*100,2) + "% " at(0,4). 152 | print "GravUp = " + round(GravUp,2) + " " at(0,5). 153 | print "AccelCent = " + round(AccelCent,2) + " " at(0,6). 154 | print "MaxThrustAccUp = " + round(MaxThrustAccUp,2) + " " at(0,7). 155 | print "MaxAccUp = " + round(MaxAccUp,2) + " " at (0,8). 156 | print "FlightMode = " + flightmode + " " at (0,9). 157 | print "GroundSpeed= " + round(GroundSpeed,2) + " " at (0,10). 158 | print "Thrust_Hyst_En = " + Thrust_Hyst_En + " " at(0,11). 159 | print "ThrustDemand = " + round(ThrustDemand*100,1) +"% " at(0,12). 160 | 161 | } 162 | 163 | // Lastly a very crude landing script. The reason for the .99 multiplication is because its not perfect. So the velocity will start to decrease even though there should be no acceleration. 164 | // One could make a simple Proportional controller to assure touchdown speed is met buuut this works fine for low buffer_alt values. 165 | lock throttle to 0. 166 | SAS on. 167 | unlock steering. 168 | wait 10. 169 | clearscreen. --------------------------------------------------------------------------------