├── Dockee ├── Readme.txt ├── Dockee-boot.ks ├── satprogram.ks └── launch-incl.ks ├── KOT ├── D │ ├── Readme.txt │ ├── Docker-autodock-boot.ks │ ├── dockprogram.ks │ └── launch-inclan.ks ├── Readme.txt ├── KOT-boot.ks ├── flightprogram.ks ├── orbprog.ks └── launch.ks ├── Mapsat ├── README ├── MapSat-boot.ks ├── satprogram-inclan.ks └── launch-inclan.ks ├── liborbital ├── annorm.ks ├── orbdir.ks ├── aponode.ks ├── perinode.ks ├── circularize.ks ├── trimperiod.ks ├── etaNodes.ks ├── altNodes.ks ├── exenode.ks └── dock.ks ├── Kommsat-incl ├── README ├── transfernode.ks ├── KommSat2-incl-boot.ks ├── KommSat-incl-boot.ks ├── fltper.ks ├── mode2.ks ├── satprogram.ks ├── sat2.ks ├── launch.ks └── launch2.ks ├── Moona ├── 1 │ ├── mode1.ks │ ├── sat.ks │ └── launch.ks ├── 2 │ ├── wait.ks │ ├── mode1.ks │ ├── launch.ks │ └── sat.ks ├── 6 │ ├── README │ ├── wait.ks │ ├── mode1.ks │ ├── sat.ks │ ├── launch.ks │ └── landing1.ks ├── boot │ ├── Moona1-boot.ks │ ├── Moona2-boot.ks │ ├── MoonaPol-boot.ks │ └── Moona6-boot.ks └── Pol │ ├── wait.ks │ ├── mode1.ks │ ├── polorb.ks │ ├── sat.ks │ └── launch.ks ├── libvessel ├── thrustisp.ks └── vesselsize.ks ├── L3project ├── mode1.ks ├── flttraj.ks ├── boot │ ├── capsule.ks │ └── lander.ks ├── wait.ks ├── lander │ ├── launch.ks │ ├── program.ks │ └── landing1.ks ├── launch.ks └── capsule │ └── flight.ks ├── libmath ├── frame.ks ├── math.ks ├── ridders.ks ├── cse.ks ├── lambert.ks └── brent.ks ├── libwarp ├── warpheight.ks └── warpfor.ks ├── LICENSE ├── libinput └── require.ks └── README.md /Dockee/Readme.txt: -------------------------------------------------------------------------------- 1 | Docking test vehicle (Unmanned part) 2 | -------------------------------------------------------------------------------- /KOT/D/Readme.txt: -------------------------------------------------------------------------------- 1 | Docking test vehicle (Manned part) 2 | -------------------------------------------------------------------------------- /KOT/Readme.txt: -------------------------------------------------------------------------------- 1 | Simple manned craft and launch script. 2 | Launch vehicle unified with KommSat. 3 | Optimized for FAR. 4 | -------------------------------------------------------------------------------- /Mapsat/README: -------------------------------------------------------------------------------- 1 | Resource scanning satellite. 2 | Example of orbital plane targeting in stock. 3 | Craft optimized for FAR. 4 | -------------------------------------------------------------------------------- /liborbital/annorm.ks: -------------------------------------------------------------------------------- 1 | function ANNorm { 2 | //returns direction with vector=AN vector, up=normal 3 | parameter lan, incl, SPV to SolarPrimeVector. 4 | return lookdirup(SPV, V(0,1,0))*R(0,-lan,-incl). 5 | } 6 | -------------------------------------------------------------------------------- /liborbital/orbdir.ks: -------------------------------------------------------------------------------- 1 | function orbdir { 2 | //returns direction with vector=AN vector, up=normal 3 | local normvec to vcrs(body:position-orbit:position,velocity:orbit). 4 | local anvec to vcrs(normvec,V(0,1,0)). 5 | return lookdirup(anvec,normvec). 6 | } 7 | -------------------------------------------------------------------------------- /Kommsat-incl/README: -------------------------------------------------------------------------------- 1 | Scripts to launch communication satellites from non-equatorial site. 2 | Craft files require RemoteTech, kOS, Kerbalism (Geiger counter) and Ven's Stock Part Revamp (solar panels). 3 | Demonstration of work: https://www.youtube.com/watch?v=6L3PcNf1Af4 4 | -------------------------------------------------------------------------------- /Moona/6/README: -------------------------------------------------------------------------------- 1 | Moona 6 - a fully automated mission from launch to the Mun landing. 2 | Gameplay Mods: 3 | KSCSwitcher to launch from Inland Space Center (20°39'N, 146°25'W) 4 | RemoteTech 5 | FAR 6 | Part mods: 7 | kOS 8 | Kerbalism (adds Geiger counter) 9 | DMagic Orbital Science (scientific instruments) 10 | Ven's Stock Parts Revamp 11 | -------------------------------------------------------------------------------- /libvessel/thrustisp.ks: -------------------------------------------------------------------------------- 1 | function ThrustIsp { 2 | list engines in el. 3 | local vex to 1. 4 | local ff to 0. 5 | local tt to 0. 6 | for e in el { 7 | set ff to ff + e:availablethrust/max(e:visp,0.01). 8 | set tt to tt + e:availablethrust*vdot(facing:vector,e:facing:vector). 9 | } 10 | if tt<>0 set vex to 9.80665*tt/ff. 11 | return list(tt,vex). 12 | } 13 | -------------------------------------------------------------------------------- /libvessel/vesselsize.ks: -------------------------------------------------------------------------------- 1 | function vesselsize { 2 | parameter v. 3 | 4 | local vparts to v:parts. 5 | local vcenter to V(0,0,0). 6 | 7 | for p in vparts { set vcenter to vcenter+v:position. } 8 | set vcenter to vcenter/vparts:length. 9 | 10 | set dmax to 0. 11 | for p in vparts { 12 | set dmax to max(dmax, (p:position - vcenter):sqrmagnitude). 13 | } 14 | 15 | return sqrt(dmax)*4+1. 16 | } 17 | -------------------------------------------------------------------------------- /L3project/mode1.ks: -------------------------------------------------------------------------------- 1 | require("liborbital","etaNodes.ks"). 2 | 3 | clearscreen. 4 | 5 | local ttr to time:seconds+etaAN()+19.066/360*orbit:period. 6 | local a1 to (1.15*Mun:orbit:semimajoraxis + orbit:semimajoraxis)/2. 7 | local Vpe to sqrt( body:mu*(2/orbit:semimajoraxis - 1/a1) ). 8 | local deltav to Vpe - velocity:orbit:mag. 9 | print "Transfer burn: " + round(velocity:orbit:mag) + " -> " + round(Vpe) + "m/s". 10 | local nd to node(ttr, 0, 0, deltav). 11 | add nd. 12 | -------------------------------------------------------------------------------- /Kommsat-incl/transfernode.ks: -------------------------------------------------------------------------------- 1 | function transfernode { 2 | parameter newperiod is 3600. 3 | parameter ndeta is 30. 4 | 5 | local newsma to (newperiod/(2*constant:pi)*body:mu^0.5)^(2.0/3.0). 6 | local r0 to orbit:semimajoraxis. 7 | local v0 to velocity:orbit:mag. 8 | local a1 to (newsma+r0)/2. 9 | local Vpe to sqrt( body:mu*(2/r0 - 1/a1) ). 10 | set deltav to Vpe - v0. 11 | print "Transfer burn: " + round(v0) + " -> " + round(Vpe) + "m/s". 12 | set nd to node(time:seconds + ndeta, 0, 0, deltav). 13 | add nd. 14 | } 15 | -------------------------------------------------------------------------------- /L3project/flttraj.ks: -------------------------------------------------------------------------------- 1 | require("liborbital","etaNodes.ks"). 2 | { 3 | local nt to time:seconds + min(etaDN(), etaAN()). 4 | wait 0. 5 | local pn to positionat(ship, nt) - body:position. 6 | local vn to velocityat(ship,nt):orbit. 7 | local nrm to orbdir():upvector. 8 | local refvec to V(0, nrm:y, 0):normalized. 9 | local rad to vcrs(nrm, vn):normalized. 10 | local vh to vdot(vn, vcrs(pn:normalized, nrm)). 11 | local dv to vh*(vcrs(pn:normalized, refvec) - vcrs(pn:normalized,nrm)). 12 | local nd to node(nt, vdot(dv, rad), vdot(dv, nrm), vdot(dv, vn:normalized)). 13 | add nd. 14 | } 15 | -------------------------------------------------------------------------------- /KOT/KOT-boot.ks: -------------------------------------------------------------------------------- 1 | function require { 2 | parameter lib, fn is "". 3 | if fn = "" { 4 | if not exists(lib) { 5 | cd("0:/" + lib). 6 | list files in fl. 7 | for f in fl { copypath(f:name,"1:/" + lib + "/" + f:name). } 8 | } 9 | cd("1:/" + lib). 10 | list files in fl. 11 | for f in fl { runpath(f:name). } 12 | } 13 | else { 14 | if not exists(fn) { 15 | local fstr to "0:/". 16 | if lib = "" { set fstr to fstr + fn. } 17 | else { set fstr to fstr + lib + "/" + fn. } 18 | copypath(fstr, fn). 19 | } 20 | runpath(fn). 21 | } 22 | } 23 | require("KOT","flightprogram.ks"). 24 | -------------------------------------------------------------------------------- /Moona/boot/Moona1-boot.ks: -------------------------------------------------------------------------------- 1 | function require { 2 | parameter lib, fn is "". 3 | if fn = "" { 4 | if not exists(lib) { 5 | cd("0:/" + lib). 6 | list files in fl. 7 | for f in fl { copypath(f:name,"1:/" + lib + "/" + f:name). } 8 | } 9 | cd("1:/" + lib). 10 | list files in fl. 11 | for f in fl { runpath(f:name). } 12 | } 13 | else { 14 | if not exists(fn) { 15 | local fstr to "0:/". 16 | if lib = "" { set fstr to fstr + fn. } 17 | else { set fstr to fstr + lib + "/" + fn. } 18 | copypath(fstr, fn). 19 | } 20 | runpath(fn). 21 | } 22 | } 23 | require("Moona/1","sat.ks"). 24 | -------------------------------------------------------------------------------- /Moona/boot/Moona2-boot.ks: -------------------------------------------------------------------------------- 1 | function require { 2 | parameter lib, fn is "". 3 | if fn = "" { 4 | if not exists(lib) { 5 | cd("0:/" + lib). 6 | list files in fl. 7 | for f in fl { copypath(f:name,"1:/" + lib + "/" + f:name). } 8 | } 9 | cd("1:/" + lib). 10 | list files in fl. 11 | for f in fl { runpath(f:name). } 12 | } 13 | else { 14 | if not exists(fn) { 15 | local fstr to "0:/". 16 | if lib = "" { set fstr to fstr + fn. } 17 | else { set fstr to fstr + lib + "/" + fn. } 18 | copypath(fstr, fn). 19 | } 20 | runpath(fn). 21 | } 22 | } 23 | require("Moona/2","sat.ks"). 24 | -------------------------------------------------------------------------------- /Moona/boot/MoonaPol-boot.ks: -------------------------------------------------------------------------------- 1 | function require { 2 | parameter lib, fn is "". 3 | if fn = "" { 4 | if not exists(lib) { 5 | cd("0:/" + lib). 6 | list files in fl. 7 | for f in fl { copypath(f:name,"1:/" + lib + "/" + f:name). } 8 | } 9 | cd("1:/" + lib). 10 | list files in fl. 11 | for f in fl { runpath(f:name). } 12 | } 13 | else { 14 | if not exists(fn) { 15 | local fstr to "0:/". 16 | if lib = "" { set fstr to fstr + fn. } 17 | else { set fstr to fstr + lib + "/" + fn. } 18 | copypath(fstr, fn). 19 | } 20 | runpath(fn). 21 | } 22 | } 23 | require("Moona/Pol","sat.ks"). 24 | -------------------------------------------------------------------------------- /Mapsat/MapSat-boot.ks: -------------------------------------------------------------------------------- 1 | function require { 2 | parameter lib, fn is "". 3 | if fn = "" { 4 | if not exists(lib) { 5 | cd("0:/" + lib). 6 | list files in fl. 7 | for f in fl { copypath(f:name,"1:/" + lib + "/" + f:name). } 8 | } 9 | cd("1:/" + lib). 10 | list files in fl. 11 | for f in fl { runpath(f:name). } 12 | } 13 | else { 14 | if not exists(fn) { 15 | local fstr to "0:/". 16 | if lib = "" { set fstr to fstr + fn. } 17 | else { set fstr to fstr + lib + "/" + fn. } 18 | copypath(fstr, fn). 19 | } 20 | runpath(fn). 21 | } 22 | } 23 | require("Mapsat","satprogram-inclan.ks"). 24 | -------------------------------------------------------------------------------- /Kommsat-incl/KommSat2-incl-boot.ks: -------------------------------------------------------------------------------- 1 | function require { 2 | parameter lib, fn is "". 3 | if fn = "" { 4 | if not exists(lib) { 5 | cd("0:/" + lib). 6 | list files in fl. 7 | for f in fl { copypath(f:name,"1:/" + lib + "/" + f:name). } 8 | } 9 | cd("1:/" + lib). 10 | list files in fl. 11 | for f in fl { runpath(f:name). } 12 | } 13 | else { 14 | if not exists(fn) { 15 | local fstr to "0:/". 16 | if lib = "" { set fstr to fstr + fn. } 17 | else { set fstr to fstr + lib + "/" + fn. } 18 | copypath(fstr, fn). 19 | } 20 | runpath(fn). 21 | } 22 | } 23 | require("Kommsat-incl","sat2.ks"). 24 | -------------------------------------------------------------------------------- /Kommsat-incl/KommSat-incl-boot.ks: -------------------------------------------------------------------------------- 1 | function require { 2 | parameter lib, fn is "". 3 | if fn = "" { 4 | if not exists(lib) { 5 | cd("0:/" + lib). 6 | list files in fl. 7 | for f in fl { copypath(f:name,"1:/" + lib + "/" + f:name). } 8 | } 9 | cd("1:/" + lib). 10 | list files in fl. 11 | for f in fl { runpath(f:name). } 12 | } 13 | else { 14 | if not exists(fn) { 15 | local fstr to "0:/". 16 | if lib = "" { set fstr to fstr + fn. } 17 | else { set fstr to fstr + lib + "/" + fn. } 18 | copypath(fstr, fn). 19 | } 20 | runpath(fn). 21 | } 22 | } 23 | require("Kommsat-incl","satprogram.ks"). 24 | -------------------------------------------------------------------------------- /Moona/2/wait.ks: -------------------------------------------------------------------------------- 1 | function waitwindow { 2 | parameter Horb. 3 | 4 | local lngdiff to ship:longitude + 90 - Mun:longitude. 5 | 6 | local a1 to (Mun:apoapsis + Horb)/2 + body:radius. 7 | local t12 to constant:pi*sqrt(a1^3/body:mu). 8 | 9 | local phitrans to 180*(2*t12/Mun:orbit:period - 1). 10 | local omegaeff to 360*(1/body:rotationperiod - 1/Mun:orbit:period). 11 | local etatrans to (phitrans - lngdiff)/omegaeff - constant:pi/2*sqrt((body:radius + Horb)^3/body:mu) - 900. 12 | if etatrans < 0 set etatrans to etatrans + 360/omegaeff. 13 | 14 | wait until kuniverse:timewarp:issettled. 15 | set kuniverse:timewarp:mode to "rails". 16 | warpfor(etatrans). 17 | } 18 | -------------------------------------------------------------------------------- /Dockee/Dockee-boot.ks: -------------------------------------------------------------------------------- 1 | set volume(1):name to "Target". 2 | function require { 3 | parameter lib, fn is "". 4 | if fn = "" { 5 | if not exists(lib) { 6 | cd("0:/" + lib). 7 | list files in fl. 8 | for f in fl { copypath(f:name,"1:/" + lib + "/" + f:name). } 9 | } 10 | cd("1:/" + lib). 11 | list files in fl. 12 | for f in fl { runpath(f:name). } 13 | } 14 | else { 15 | if not exists(fn) { 16 | local fstr to "0:/". 17 | if lib = "" { set fstr to fstr + fn. } 18 | else { set fstr to fstr + lib + "/" + fn. } 19 | copypath(fstr, fn). 20 | } 21 | runpath(fn). 22 | } 23 | } 24 | require("Dockee","satprogram.ks"). 25 | -------------------------------------------------------------------------------- /Moona/boot/Moona6-boot.ks: -------------------------------------------------------------------------------- 1 | function require { 2 | parameter lib, fn is "". 3 | if fn = "" { 4 | if not exists(lib) { 5 | cd("0:/" + lib). 6 | list files in fl. 7 | for f in fl { copypath(f:name,"1:/" + lib + "/" + f:name). } 8 | } 9 | cd("1:/" + lib). 10 | list files in fl. 11 | for f in fl { runpath(f:name). } 12 | } 13 | else { 14 | if not exists(fn) { 15 | local fstr to "0:/". 16 | if lib = "" { set fstr to fstr + fn. } 17 | else { set fstr to fstr + lib + "/" + fn. } 18 | copypath(fstr, fn). 19 | } 20 | runpath(fn). 21 | } 22 | } 23 | local landsite to Mun:geopositionlatlng(4.3,76.3). 24 | require("Moona/5","sat.ks"). 25 | -------------------------------------------------------------------------------- /L3project/boot/capsule.ks: -------------------------------------------------------------------------------- 1 | set volume(1):name to "podCPU". 2 | set core:part:tag to "podCPU". 3 | function require { 4 | parameter lib, fn is "". 5 | local prefix to "1:/" + lib + "/". 6 | if fn = "" { 7 | if not exists(lib) { 8 | cd("0:/" + lib). 9 | list files in fl. 10 | for f in fl { copypath(f:name, prefix + f:name). } 11 | } 12 | cd("1:/" + lib). 13 | list files in fl. 14 | for f in fl { runpath(f:name). } 15 | cd("1:/"). 16 | } 17 | else { 18 | set lfn to prefix + fn. 19 | if not exists(lfn) { 20 | set fn to "0:/" + lib + "/" + fn. 21 | copypath(fn, lfn). 22 | } 23 | runpath(lfn). 24 | } 25 | } 26 | require("L3/capsule","flight.ks"). 27 | -------------------------------------------------------------------------------- /L3project/boot/lander.ks: -------------------------------------------------------------------------------- 1 | set volume(1):name to "landerCPU". 2 | set core:part:tag to "landerCPU". 3 | function require { 4 | parameter lib, fn is "". 5 | local prefix to "1:/" + lib + "/". 6 | if fn = "" { 7 | if not exists(lib) { 8 | cd("0:/" + lib). 9 | list files in fl. 10 | for f in fl { copypath(f:name, prefix + f:name). } 11 | } 12 | cd("1:/" + lib). 13 | list files in fl. 14 | for f in fl { runpath(f:name). } 15 | cd("1:/"). 16 | } 17 | else { 18 | set lfn to prefix + fn. 19 | if not exists(lfn) { 20 | set fn to "0:/" + lib + "/" + fn. 21 | copypath(fn, lfn). 22 | } 23 | runpath(lfn). 24 | } 25 | } 26 | require("L3/lander","program.ks"). 27 | -------------------------------------------------------------------------------- /Moona/6/wait.ks: -------------------------------------------------------------------------------- 1 | require("libwarp","warpfor.ks"). 2 | 3 | function waitwindow { 4 | parameter Horb. 5 | 6 | local lngdiff to ship:longitude + 90 - Mun:longitude. 7 | 8 | local a1 to (Mun:apoapsis + Horb)/2 + body:radius. 9 | local t12 to constant:pi*sqrt(a1^3/body:mu). 10 | 11 | local phitrans to 180*(2*t12/Mun:orbit:period - 1). 12 | local omegaeff to 360*(1/body:rotationperiod - 1/Mun:orbit:period). 13 | local etatrans to (phitrans - lngdiff)/omegaeff - constant:pi/2*sqrt((body:radius + Horb)^3/body:mu) - 600. 14 | if etatrans < 0 set etatrans to etatrans + 360/omegaeff. 15 | 16 | wait until kuniverse:timewarp:issettled. 17 | set kuniverse:timewarp:mode to "rails". 18 | warpfor(etatrans). 19 | } 20 | -------------------------------------------------------------------------------- /Moona/Pol/wait.ks: -------------------------------------------------------------------------------- 1 | require("libwarp","warpfor.ks"). 2 | 3 | function waitwindow { 4 | parameter Horb. 5 | 6 | local lngdiff to ship:longitude + 90 - Mun:longitude. 7 | 8 | local a1 to (Mun:apoapsis + Horb)/2 + body:radius. 9 | local t12 to constant:pi*sqrt(a1^3/body:mu). 10 | 11 | local phitrans to 180*(2*t12/Mun:orbit:period - 1). 12 | local omegaeff to 360*(1/body:rotationperiod - 1/Mun:orbit:period). 13 | local etatrans to (phitrans - lngdiff)/omegaeff - constant:pi/2*sqrt((body:radius + Horb)^3/body:mu) - 630. 14 | if etatrans < 0 set etatrans to etatrans + 360/omegaeff. 15 | 16 | wait until kuniverse:timewarp:issettled. 17 | set kuniverse:timewarp:mode to "rails". 18 | warpfor(etatrans). 19 | } 20 | -------------------------------------------------------------------------------- /Moona/1/mode1.ks: -------------------------------------------------------------------------------- 1 | require("liborbital","orbdir.ks"). 2 | 3 | function dneta { 4 | local vecs to orbdir(). 5 | local dnangle to arctan2( vdot(vcrs(vecs:vector,body:position), vecs:upvector), vdot(vecs:vector, body:position)). 6 | if dnangle < 0 { set dnangle to 360 + dnangle. } 7 | return dnangle / 360 * orbit:period. 8 | } 9 | 10 | clearscreen. 11 | 12 | local ttr to time:seconds+dneta. 13 | local a1 to (Mun:orbit:semimajoraxis + orbit:semimajoraxis)/2. 14 | local Vpe to sqrt( body:mu*(2/orbit:semimajoraxis - 1/a1) ). 15 | local deltav to Vpe - velocity:orbit:mag. 16 | print "Transfer burn: " + round(velocity:orbit:mag) + " -> " + round(Vpe) + "m/s". 17 | local nd to node(ttr, 0, 0, deltav). 18 | add nd. 19 | deletepath("orbdir.ks"). 20 | -------------------------------------------------------------------------------- /Moona/2/mode1.ks: -------------------------------------------------------------------------------- 1 | require("liborbital","orbdir.ks"). 2 | 3 | function dneta { 4 | local vecs to orbdir(). 5 | local dnangle to arctan2( vdot(vcrs(vecs:vector,body:position), vecs:upvector), vdot(vecs:vector, body:position)). 6 | if dnangle < 0 { set dnangle to 360 + dnangle. } 7 | return dnangle / 360 * orbit:period. 8 | } 9 | 10 | clearscreen. 11 | 12 | local ttr to time:seconds+dneta+30. 13 | local a1 to (1.15*Mun:orbit:semimajoraxis + orbit:semimajoraxis)/2. 14 | local Vpe to sqrt( body:mu*(2/orbit:semimajoraxis - 1/a1) ). 15 | local deltav to Vpe - velocity:orbit:mag. 16 | print "Transfer burn: " + round(velocity:orbit:mag) + " -> " + round(Vpe) + "m/s". 17 | local nd to node(ttr, 0, 0, deltav). 18 | add nd. 19 | deletepath("orbdir.ks"). 20 | -------------------------------------------------------------------------------- /Moona/Pol/mode1.ks: -------------------------------------------------------------------------------- 1 | require("liborbital","orbdir.ks"). 2 | 3 | function dneta { 4 | local vecs to orbdir(). 5 | local dnangle to arctan2( vdot(vcrs(vecs:vector,body:position), vecs:upvector), vdot(vecs:vector, body:position)). 6 | if dnangle < 0 { set dnangle to 360 + dnangle. } 7 | return dnangle / 360 * orbit:period. 8 | } 9 | 10 | clearscreen. 11 | 12 | local ttr to time:seconds+dneta + 40. 13 | local a1 to (Mun:orbit:semimajoraxis + orbit:semimajoraxis)/2. 14 | local Vpe to sqrt( body:mu*(2/orbit:semimajoraxis - 1/a1) ). 15 | local deltav to Vpe - velocity:orbit:mag - 2. 16 | print "Transfer burn: " + round(velocity:orbit:mag) + " -> " + round(Vpe) + "m/s". 17 | local nd to node(ttr, 0, 0, deltav). 18 | add nd. 19 | deletepath("orbdir.ks"). 20 | -------------------------------------------------------------------------------- /Kommsat-incl/fltper.ks: -------------------------------------------------------------------------------- 1 | function fltper { 2 | parameter newperiod. 3 | local atodn to orbit:argumentofperiapsis. 4 | local Ra to apoapsis + body:radius. 5 | local Va to sqrt( body:mu * (2/Ra - 1/orbit:semimajoraxis) ). 6 | local tm to time:seconds + eta:apoapsis - sin(atodn)*Ra/Va. 7 | if tm < time:seconds set tm to time:seconds + eta:apoapsis. 8 | local a1 to (newperiod/(2*constant:pi)*body:mu^0.5)^(2.0/3.0). 9 | local v1 to sqrt(body:mu*(2/Ra-1/a1)). 10 | local Vc to sqrt(body:mu/Ra). 11 | local i to orbit:inclination. 12 | local dVy to Vc*sin(i). 13 | local dVx to Vc*cos(i)-Va. 14 | local sqdV to dvx^2+dvy^2. 15 | local alpha to (sqrt((Va*dVx)^2+sqdV*(v1^2-Va^2))-Va*dVx)/sqdV. 16 | if alpha>0.99 set alpha to 1. 17 | local nd to node(tm,0,alpha*dVy,alpha*dVx). 18 | add nd. 19 | } 20 | -------------------------------------------------------------------------------- /KOT/D/Docker-autodock-boot.ks: -------------------------------------------------------------------------------- 1 | set volume(1):name to "KOT". 2 | function require { 3 | parameter lib, fn is "". 4 | if fn = "" { 5 | if not exists(lib) { 6 | cd("0:/" + lib). 7 | list files in fl. 8 | for f in fl { copypath(f:name,"1:/" + lib + "/" + f:name). } 9 | } 10 | cd("1:/" + lib). 11 | list files in fl. 12 | for f in fl { runpath(f:name). } 13 | } 14 | else { 15 | if not exists(fn) { 16 | local fstr to "0:/". 17 | if lib = "" { set fstr to fstr + fn. } 18 | else { set fstr to fstr + lib + "/" + fn. } 19 | copypath(fstr, fn). 20 | } 21 | runpath(fn). 22 | } 23 | } 24 | print "Number of kOS processors: " + ship:modulesnamed("kOSProcessor"):length. 25 | wait until hastarget or status <> "prelaunch". 26 | require("KOT/D","dockprogram.ks"). 27 | -------------------------------------------------------------------------------- /libmath/frame.ks: -------------------------------------------------------------------------------- 1 | function chFrame { 2 | parameter oldVec, oldSP, newSP to SolarPrimeVector. 3 | return vdot(oldVec, oldSP)*newSP + (oldVec:z * oldSP:x - oldVec:x * oldSP:z)*V(-newSP:z, 0, newSP:x) + V(0, oldVec:y, 0). 4 | } 5 | 6 | function toIRF { 7 | // changes to inertial right-handed coordinate system where ix = SPV, iy = vcrs(SPV, V(0, 1, 0)), iz = V(0, 1, 0) 8 | parameter oldVec, SPV to SolarPrimeVector. 9 | return V( oldVec:x * SPV:x + oldVec:z * SPV:z, oldVec:z * SPV:x - oldVec:x * SPV:z, oldVec:y). 10 | } 11 | 12 | function fromIRF { 13 | // changes from inertial right-handed coordinate system where ix = SPV, iy = vcrs(SPV, V(0, 1, 0)), iz = V(0, 1, 0) 14 | parameter irfVec, SPV to SolarPrimeVector. 15 | return V( irfVec:x * SPV:x - irfVec:y * SPV:z, irfVec:z, irfVec:x * SPV:z + irfVec:y * SPV:x ). 16 | } 17 | -------------------------------------------------------------------------------- /liborbital/aponode.ks: -------------------------------------------------------------------------------- 1 | function aponode { 2 | parameter newapsis is apoapsis. 3 | 4 | print "T+" + round(missiontime) + " Maneuver at Ap. Changing orbit around " + body:name + ":". 5 | print round(apoapsis/1000,1) + "x" + round(periapsis/1000,1) + " km -> " + round(apoapsis/1000,1) + "x" + round(newapsis/1000,1) + " km ". 6 | 7 | local a0 to orbit:semimajoraxis. 8 | local Ra to body:radius + apoapsis. 9 | local Va to sqrt( body:mu * (2/Ra - 1/a0) ). 10 | 11 | local a1 to (newapsis + apoapsis)/2 + body:radius. // target orbit SMA 12 | local v1 to sqrt( body:mu * (2/Ra - 1/a1) ). 13 | set deltav to v1 - Va. 14 | 15 | print "Burn at Ap: " + round(Va) + " -> " + round(v1) + "m/s". 16 | 17 | add node(time:seconds + eta:apoapsis, 0, 0, deltav). 18 | print "T+" + round(missiontime) + " Node created.". 19 | } 20 | -------------------------------------------------------------------------------- /liborbital/perinode.ks: -------------------------------------------------------------------------------- 1 | function aponode { 2 | parameter newapsis is periapsis. 3 | 4 | print "T+" + round(missiontime) + " Maneuver at Pe. Changing orbit around ". + body:name + ":". 5 | print round(periapsis/1000,1) + "x" + round(apoapsis/1000,1) + " km -> " + round(periapsis/1000,1) + "x" + round(newapsis/1000,1) + " km ". 6 | 7 | local a0 to orbit:semimajoraxis. 8 | local Rp to body:radius + periapsis. 9 | local Vp to sqrt( body:mu * (2/Rp - 1/a0) ). 10 | 11 | local a1 to (newapsis + periapsis)/2 + body:radius. // target orbit SMA 12 | local v1 to sqrt( body:mu * (2/Rp - 1/a1) ). 13 | set deltav to v1 - Vp. 14 | 15 | print "Burn at Pe: " + round(Vp) + " -> " + round(v1) + "m/s". 16 | 17 | add node(time:seconds + eta:periapsis, 0, 0, deltav). 18 | print "T+" + round(missiontime) + " Node created.". 19 | } 20 | -------------------------------------------------------------------------------- /KOT/flightprogram.ks: -------------------------------------------------------------------------------- 1 | function AlignToSun { 2 | lock steering to lookdirup(-velocity:orbit,Sun:position) + R(0,0,225). 3 | } 4 | 5 | function nextmode { 6 | parameter newmode is satmode+1. 7 | set satmode to newmode. 8 | log "set satmode to " + newmode + "." to "mode.ks". 9 | AlignToSun(). 10 | } 11 | 12 | function length { 13 | parameter lst. 14 | local n to 0. 15 | for i in lst set n to n+1. 16 | return n. 17 | } 18 | 19 | function satprogram { 20 | if satmode = 0 { 21 | require("KOT","launch.ks"). 22 | gettoorbit(80000,100). 23 | deletepath("launch.ks"). 24 | startnextstage(). 25 | deletepath("circularize.ks"). 26 | wait 20. 27 | nextmode(). 28 | } 29 | require("KOT","orbprog.ks"). 30 | } 31 | 32 | local satmode to 0. 33 | if exists("mode.ks") { runpath("mode.ks"). } 34 | else nextmode(0). 35 | satprogram(). 36 | -------------------------------------------------------------------------------- /liborbital/circularize.ks: -------------------------------------------------------------------------------- 1 | function circularize { 2 | local a0 is 2. // aoa limit 3 | local kt is 2. // gain factor 4 | local hz is 10. // controller rate 5 | 6 | local st is facing. 7 | local th is 0. 8 | lock steering to st. 9 | lock throttle to th. 10 | 11 | until false { 12 | local sc is sqrt(body:mu/(body:radius+altitude)). //circular speed 13 | local hv is vxcl(up:vector,velocity:orbit):normalized. //horizontal velocity 14 | local ev to hv*sc-velocity:orbit. 15 | if ev:mag < 0.05 break. 16 | local ad is 1-vang(facing:vector,ev)/a0. 17 | set st to lookdirup(ev,facing:topvector). 18 | set th to min(ad*kt*ev:mag*mass/max(1,maxthrust),1). 19 | if ship:availablethrust = 0 { set th to max(th,0.05). } 20 | wait 1/hz. 21 | } 22 | set th to 0. 23 | wait 1. 24 | unlock steering. 25 | set ship:control:pilotmainthrottle to 0. 26 | unlock throttle. 27 | } 28 | -------------------------------------------------------------------------------- /Moona/Pol/polorb.ks: -------------------------------------------------------------------------------- 1 | function polorb { 2 | parameter dtnode is 150. 3 | local nodet is time:seconds + dtnode. 4 | 5 | local vatnode is velocityat(ship,nodet):orbit. 6 | local upnode is (positionat(ship,nodet)-body:position):normalized. 7 | local northax is vxcl(upnode,V(0,1,0)):normalized. 8 | 9 | local prg is vatnode:normalized. 10 | local nrm is vcrs(prg,upnode):normalized. 11 | local rad is vcrs(nrm,prg). 12 | 13 | local vnorth is vdot(northax, vatnode). 14 | local vh is vxcl(upnode,vatnode). 15 | local vv is vatnode - vh. 16 | local vhmag is vh:mag. 17 | local newv is velocity:orbit. 18 | if vnorth > 0 { set newv to vv + vhmag*northax. } 19 | else { set newv to vv - vhmag*northax. } 20 | 21 | print vang(newv,vv). 22 | print vang(vatnode,vv). 23 | local dv is newv - vatnode. 24 | local dvprg is vdot(dv,prg). 25 | local dvrad is vdot(dv,rad). 26 | local dvnrm is vdot(dv,nrm). 27 | 28 | local nd is node(nodet,dvrad,dvnrm,dvprg). 29 | add nd. 30 | } 31 | -------------------------------------------------------------------------------- /L3project/wait.ks: -------------------------------------------------------------------------------- 1 | function waitwindow { 2 | parameter Horb. 3 | 4 | local lngdiff to ship:longitude + 270 - Mun:longitude. 5 | 6 | local a1 to (1.15*Mun:orbit:semimajoraxis + Horb + body:radius)/2. 7 | local ecc to (1.15*Mun:orbit:semimajoraxis - Horb - body:radius)/(2*a1). 8 | local tamun to arccos( (((1 - ecc^2)*a1/Mun:orbit:semimajoraxis) - 1) / ecc ). 9 | local ef to sqrt( (1-ecc) / (1+ecc) ). 10 | local eanew to 2*arctan( ef * tan(tamun / 2) ). 11 | local t12 to sqrt(a1^3/body:mu) * (eanew*constant:degtorad - ecc * sin(eanew)). 12 | 13 | local phitrans to 180*(2*t12/Mun:orbit:period - 1). 14 | local omegaeff to 360*(1/body:rotationperiod - 1/Mun:orbit:period). 15 | local etatrans to (phitrans - lngdiff)/omegaeff - constant:pi*1.5*sqrt((body:radius + Horb)^3/body:mu) + 800. 16 | until etatrans > 0 set etatrans to etatrans + 360/omegaeff. 17 | 18 | wait until kuniverse:timewarp:issettled. 19 | set kuniverse:timewarp:mode to "rails". 20 | warpfor(etatrans). 21 | } 22 | -------------------------------------------------------------------------------- /libmath/math.ks: -------------------------------------------------------------------------------- 1 | global m_pi to constant:pi. 2 | global m_e to constant:e. 3 | global m_rtd to constant:radtodeg. 4 | global m_dtr to constant:degtorad. 5 | 6 | function sinh { 7 | parameter x. 8 | return 0.5 * (m_e^x - m_e^(-x)). 9 | } 10 | 11 | function cosh { 12 | parameter x. 13 | return 0.5 * (m_e^x + m_e^(-x)). 14 | } 15 | 16 | function tanh { 17 | parameter x. 18 | local y to m_e^(2*x) 19 | return (y - 1) / (y + 1). 20 | } 21 | 22 | function sign { 23 | parameter x. 24 | if x > 0 { return 1. } 25 | if x < 0 { return -1. } 26 | return 0. 27 | } 28 | 29 | function bnd { 30 | parameter x, b1, b2. 31 | local xmin to min(b1, b2). 32 | local xmax to max(b1, b2). 33 | 34 | if x < xmin { return xmin. } 35 | if x > xmax { return xmax. } 36 | return x. 37 | } 38 | 39 | function arsinh { 40 | parameter x. 41 | return ln(x + sqrt(x * x + 1)). 42 | } 43 | 44 | function arcosh { 45 | parameter x. 46 | return ln(x + sqrt(x * x - 1)). 47 | } 48 | 49 | function artanh { 50 | parameter x. 51 | return 0.5 * ln((1 + x) / (1 - x)). 52 | } 53 | -------------------------------------------------------------------------------- /liborbital/trimperiod.ks: -------------------------------------------------------------------------------- 1 | function TrimPeriod { 2 | parameter WantedPeriod. 3 | parameter epsilon is 5e-8. 4 | 5 | local dt to WantedPeriod - orbit:period. 6 | lock steering to velocity:orbit*dt. 7 | list engines in elist. 8 | local thrustlim to list(). 9 | // set thrustlimit to max 0.05 m/s^2 acceleration 10 | from { local i to 0. } until i=elist:length step { set i to i+1. } do { 11 | thrustlim:add(elist[i]:thrustlimit). 12 | set elist[i]:thrustlimit to 5*ship:mass/ship:maxthrust. 13 | } 14 | wait until vang(facing:vector,velocity:orbit*dt) < 1. 15 | until abs( (orbit:period - WantedPeriod) / WantedPeriod ) < epsilon { 16 | lock throttle to min( max( abs( orbit:period - WantedPeriod ), 0.05 ), 1 ). 17 | wait 0. 18 | } 19 | lock throttle to 0. 20 | // restore thrustlimits 21 | from { local i to 0. } until i=elist:length step { set i to i+1. } do { 22 | set elist[i]:thrustlimit to thrustlim[i]. 23 | } 24 | print "Target period: " + round(WantedPeriod,1) + "s, Delta: " + (orbit:period - WantedPeriod) + " s ". 25 | set ship:control:pilotmainthrottle to 0. 26 | unlock throttle. 27 | } 28 | -------------------------------------------------------------------------------- /Moona/6/mode1.ks: -------------------------------------------------------------------------------- 1 | require("liborbital","orbdir.ks"). 2 | 3 | function dneta { 4 | local vecs to orbdir(). 5 | local dnangle to arctan2( vdot(vcrs(vecs:vector,body:position), vecs:upvector), vdot(vecs:vector, body:position)). 6 | if dnangle < 0 { set dnangle to 360 + dnangle. } 7 | return dnangle / 360 * orbit:period. 8 | } 9 | 10 | clearscreen. 11 | 12 | local ttr to time:seconds+dneta + 10. 13 | local a1 to (Mun:orbit:semimajoraxis + orbit:semimajoraxis)/2. 14 | local Vpe to sqrt( body:mu*(2/orbit:semimajoraxis - 1/a1) ). 15 | local deltav to Vpe - velocity:orbit:mag - 2. 16 | print "Transfer burn: " + round(velocity:orbit:mag) + " -> " + round(Vpe) + "m/s". 17 | local nd to node(ttr, 0, 0, deltav). 18 | add nd. 19 | local pe0 to nd:orbit:nextpatch:periapsis. 20 | set nd:prograde to nd:prograde + 0.001. 21 | local pe1 to nd:orbit:nextpatch:periapsis. 22 | local dpedv to (pe1 - pe0)/0.001. 23 | until pe1 > 50000 { 24 | set pe0 to pe1. 25 | local dv to 0.1*(50000 - pe0)/dpedv. 26 | set nd:prograde to nd:prograde + dv. 27 | set pe1 to nd:orbit:nextpatch:periapsis. 28 | set dpedv to (pe1-pe0)/dv. 29 | } 30 | deletepath("orbdir.ks"). 31 | -------------------------------------------------------------------------------- /liborbital/etaNodes.ks: -------------------------------------------------------------------------------- 1 | require("liborbital","orbdir.ks"). 2 | 3 | function etaToTA { 4 | parameter ta, orbit_in to ship:orbit. 5 | 6 | local tanow to orbit_in:trueanomaly. 7 | local ecc to orbit_in:eccentricity. 8 | local ef to sqrt( (1-ecc) / (1+ecc) ). 9 | local eanow to 2*arctan( ef * tan(tanow / 2) ). 10 | local eanew to 2*arctan( ef * tan(ta / 2) ). 11 | 12 | local dt to sqrt( orbit_in:semimajoraxis^3 / orbit_in:body:mu ) * ((eanew - eanow)*constant:degtorad - ecc * (sin(eanew) - sin(eanow))). 13 | until dt > 0 { set dt to dt + orbit_in:period. } 14 | return dt. 15 | } 16 | 17 | function etaAN { 18 | parameter refNRM to V(0,1,0). 19 | 20 | local AN_NRM to orbdir(refNRM). 21 | local ANvec to AN_NRM:vector. 22 | local taAN to arctan2( vdot(AN_NRM:upvector, vcrs(body:position, ANvec)), -vdot(body:position, ANvec) ) + orbit:trueanomaly. 23 | return etaToTA(taAN). 24 | } 25 | 26 | function etaDN { 27 | parameter refNRM to V(0,1,0). 28 | 29 | local DN_NRM to orbdir(refNRM). 30 | local DNvec to -DN_NRM:vector. 31 | local taDN to arctan2( vdot(DN_NRM:upvector, vcrs(body:position, DNvec)), -vdot(body:position, DNvec) ) + orbit:trueanomaly. 32 | return etaToTA(taDN). 33 | } 34 | -------------------------------------------------------------------------------- /libwarp/warpheight.ks: -------------------------------------------------------------------------------- 1 | function bnd { 2 | parameter val, minval, maxval. 3 | return min(maxval, max(minval, val)). 4 | } 5 | 6 | function warpheight { 7 | parameter h. 8 | local wp to 0. 9 | 10 | if (h < periapsis) { 11 | print "ERROR: target altitude is lower than periapsis.". 12 | } 13 | else if (apoapsis > 0) and (h > apoapsis) { 14 | print "ERROR: target altitude is higher than apoapsis.". 15 | } 16 | else { 17 | local tw to kuniverse:timewarp. 18 | local flag to ship:altitude > h. 19 | local wp to tw:warp. 20 | local oldwp to wp. 21 | local rt to 0. 22 | until (ship:altitude > h) <> flag { 23 | set rt to abs(ship:altitude - h)/max(0.01,abs(verticalspeed)). 24 | set oldwp to tw:warp. 25 | set wp to bnd(round(log10(min((rt*0.356)^2,rt*100))),0,6). 26 | if wp <> oldwp { 27 | if not tw:issettled wait tw:ratelist[min(oldwp,wp)]*0.1. 28 | set wp to bnd(wp, oldwp-1, oldwp+1). 29 | set tw:warp to wp. 30 | } 31 | if tw:mode <> "rails" and altitude > body:atm:height { 32 | tw:cancelwarp(). 33 | wait until tw:issettled. 34 | set tw:mode to "rails". 35 | } 36 | wait 0. 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /KOT/orbprog.ks: -------------------------------------------------------------------------------- 1 | if satmode = 1 { 2 | print "Aligning for optimal solar panel performance.". 3 | nextmode(). 4 | } 5 | if satmode = 2 { 6 | if length(ship:crew())=0 nextmode(). 7 | until length(ship:crew())=0 { 8 | hudtext("Waiting for crew EVA",1,2,18,YELLOW,True). 9 | wait 2. 10 | } 11 | nextmode(). 12 | } 13 | if satmode = 3 { 14 | wait until length(ship:crew())>0. 15 | nextmode(). 16 | } 17 | if satmode = 4 { 18 | require("libwarp","warpfor.ks"). 19 | nextmode(). 20 | } 21 | if satmode = 5 { 22 | wait 10. 23 | warpfor(orbit:period*2/3 - missiontime). 24 | nextmode(). 25 | } 26 | if satmode = 6 { 27 | wait until vang(ship:facing:vector,retrograde:vector)<0.1. 28 | lock throttle to 1. 29 | nextmode(). 30 | } 31 | if satmode = 7 { 32 | wait until ship:availablethrust=0. 33 | lock throttle to 0. 34 | wait 5. 35 | stage. 36 | nextmode(). 37 | } 38 | lock steering to lookdirup(-velocity:surface,Sun:position) + R(0,0,225). 39 | wait until alt:radar < 5000. 40 | stage. 41 | unlock steering. 42 | wait until ship:status = "LANDED" or ship:status = "SPLASHED". 43 | 44 | Hudtext(ship:status,20,2,18,YELLOW,True). 45 | -------------------------------------------------------------------------------- /libwarp/warpfor.ks: -------------------------------------------------------------------------------- 1 | function bnd { 2 | parameter val, minval, maxval. 3 | return min(maxval, max(minval, val)). 4 | } 5 | 6 | function warpfor { 7 | parameter dt. 8 | // warp (0:1) (1:5) (2:10) (3:50) (4:100) (5:1000) (6:10000) (7:100000) 9 | set t1 to time:seconds+dt. 10 | if dt < 0 { 11 | print "WARNING: wait time " + round(dt) + " is in the past.". 12 | return. 13 | } 14 | local tw to kuniverse:timewarp. 15 | local wp to tw:warp. 16 | local oldwp to wp. 17 | local rt to t1 - time:seconds. 18 | until rt <= 0 { 19 | set wp to bnd(round(log10(min((rt*0.356)^2,rt*50))),0,7). 20 | if wp <> oldwp or wp <> tw:warp { 21 | if not tw:issettled wait tw:ratelist[min(oldwp,wp)]*0.1. 22 | set wp to bnd(wp, oldwp-1, oldwp+1). 23 | set tw:warp to wp. 24 | if wp <> oldwp print "Warp " + tw:ratelist[wp] + "x; remaining time " + round(rt) + "/" + round(dt). 25 | set oldwp to wp. 26 | } 27 | if tw:mode <> "rails" and (altitude > body:atm:height or status = "prelaunch") { 28 | tw:cancelwarp. 29 | wait until tw:issettled. 30 | set tw:mode to "rails". 31 | wait 0. 32 | } 33 | wait 0. 34 | set rt to t1 - time:seconds. 35 | } 36 | tw:cancelwarp. 37 | } 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /Mapsat/satprogram-inclan.ks: -------------------------------------------------------------------------------- 1 | require("liborbital","circularize.ks"). 2 | 3 | function AlignToSun { 4 | lock steering to lookdirup(-Sun:position,Kerbin:position). 5 | } 6 | 7 | function nextmode { 8 | parameter newmode is satmode+1. 9 | set satmode to newmode. 10 | log "set satmode to " + newmode + "." to "mode.ks". 11 | AlignToSun(). 12 | } 13 | 14 | function satprogram { 15 | local ti to 51.6. 16 | local tlan to 12. 17 | 18 | clearscreen. 19 | print "Desired inclination: " + round(ti,2). 20 | print "Desired LAN: " + round(tlan,2). 21 | if satmode = 0 { 22 | require("Mapsat-K","launch-inclan.ks"). 23 | local Hsat to 80000. 24 | LVprogram(Hsat,ti,tlan,80,57500,575). 25 | nextmode(). 26 | } 27 | if satmode = 1 { 28 | startnextstage(). 29 | panels on. 30 | wait 5. 31 | circularize(). 32 | nextmode(). 33 | } 34 | 35 | clearscreen. 36 | print "Desired inclination: " + round(ti,2) at (0,1). 37 | print "Reached inclination: " + round(orbit:inclination,2) at (0,2). 38 | print "Desired LAN: " + round(tlan,2) at (30,1). 39 | print "Reached LAN: " + round(orbit:lan,2) at (30,2). 40 | until false AlignToSun(). 41 | } 42 | 43 | local satmode to 0. 44 | local Hsat to altitude. 45 | local LVmode to 0. 46 | if exists("mode.ks") { runpath("mode.ks"). } 47 | else nextmode(0). 48 | 49 | satprogram(). 50 | -------------------------------------------------------------------------------- /Kommsat-incl/mode2.ks: -------------------------------------------------------------------------------- 1 | require("liborbital","orbdir.ks"). 2 | 3 | function aneta { 4 | local vecs to orbdir(). 5 | local anangle to arctan2( vdot(vcrs(body:position, vecs:vector), vecs:upvector), -vdot(vecs:vector, body:position)). 6 | if anangle < 0 { set anangle to 360 + anangle. } 7 | return anangle / 360 * orbit:period. 8 | } 9 | 10 | clearscreen. 11 | set target to vessel("Kommsat III"). 12 | local trsma to (orbit:semimajoraxis+target:orbit:semimajoraxis)/2. 13 | local trperiod to 2*constant:pi*(trsma^3/body:mu)^0.5. 14 | print "Transfer orbit period: " + round(trperiod) at (0,15). 15 | local maxphase to 360*(1-trperiod/target:orbit:period). 16 | print "Max phase gain: " + round(maxphase) at (0,16). 17 | local ttr to time:seconds+aneta. 18 | local apphase to phase(positionat(target,ttr+trperiod/2)-body:position,body:position-positionat(ship,ttr)). 19 | until apphase>90 and apphase-90<=maxphase { 20 | set ttr to ttr+orbit:period. 21 | set apphase to phase(positionat(target,ttr+trperiod/2)-body:position,body:position-positionat(ship,ttr)). 22 | } 23 | print "Phase to target at AP: "+round(apphase). 24 | local Vpe to sqrt( body:mu*(2/orbit:semimajoraxis - 1/trsma) ). 25 | local deltav to Vpe - velocity:orbit:mag. 26 | print "Transfer burn: " + round(velocity:orbit:mag) + " -> " + round(Vpe) + "m/s". 27 | local nd to node(ttr, 0, 0, deltav). 28 | add nd. 29 | deletepath("orbdir.ks"). 30 | -------------------------------------------------------------------------------- /Dockee/satprogram.ks: -------------------------------------------------------------------------------- 1 | function AlignToSun { 2 | lock steering to lookdirup(V(0,1,0),Sun:position). 3 | } 4 | 5 | function nextmode { 6 | parameter newmode is satmode+1. 7 | set satmode to newmode. 8 | log "set satmode to " + newmode + "." to "mode.ks". 9 | AlignToSun(). 10 | } 11 | 12 | function waitconnect { 13 | if not addons:rt:haskscconnection(ship) { 14 | set warp to 0. 15 | wait 10. 16 | set warp to 3. 17 | wait until addons:rt:haskscconnection(ship). 18 | set warp to 0. 19 | } 20 | } 21 | 22 | function satprogram { 23 | if satmode = 0 { 24 | require("Dockee","launch-incl.ks"). 25 | gettoorbit(Hsat,21.5,550,55000). 26 | deletepath("launch-incl.ks"). 27 | wait 5. 28 | nextmode(). 29 | } 30 | if satmode = 1 { 31 | print "Aligning for optimal solar panel performance.". 32 | waitconnect(). 33 | nextmode(). 34 | } 35 | if satmode = 2 { 36 | require("liborbital","aponode.ks"). 37 | aponode(Hsat). 38 | deletepath("aponode.ks"). 39 | nextmode(). 40 | } 41 | if satmode = 3 { 42 | require("liborbital","exenode.ks"). 43 | exenode(). 44 | nextmode(). 45 | } 46 | if satmode = 4 { 47 | require("liborbital","circularize.ks"). 48 | circularize(). 49 | deletepath("circularize.ks"). 50 | nextmode(). 51 | } 52 | AlignToSun(). 53 | wait until ship:elements:length>1. 54 | unlock steering. 55 | wait until ship:elements:length=1. 56 | reboot. 57 | } 58 | 59 | local satmode to 0. 60 | local Hsat to 90000. 61 | if exists("mode.ks") { runpath("mode.ks"). } 62 | else nextmode(0). 63 | satprogram(). 64 | -------------------------------------------------------------------------------- /liborbital/altNodes.ks: -------------------------------------------------------------------------------- 1 | require("liborbital","orbdir.ks"). 2 | 3 | function TAofAN2 { 4 | parameter ti, tlan, taop. 5 | local T_AN_NRM to lookdirup(SolarPrimeVector, V(0,1,0))*R(0,-tlan,-ti). 6 | local refNRM to T_AN_NRM:upvector. 7 | local T_PE_NRM to angleaxis(-taop, refNRM) * T_AN_NRM. 8 | local PEvec to T_PE_NRM:vector. 9 | local ANvec to orbdir(refNRM):vector. 10 | local taAN to arctan2( vdot(refNRM, vcrs(ANvec, PEvec)), vdot(ANvec, PEvec) ). 11 | until taAN >= 0 { set taAN to taAN + 360. } 12 | until taAN < 360 { set taAN to taAN - 360. } 13 | return taAN. 14 | } 15 | 16 | function AltTA2 { 17 | parameter tsma, tecc, ti, tlan, taop, tta. 18 | return tsma*(1 - tecc*tecc) / (1 + tecc * cos(tta)). 19 | } 20 | 21 | function UniPosTA2 { 22 | parameter tsma, tecc, ti, tlan, taop, tta. 23 | local T_AN_NRM to lookdirup(SolarPrimeVector, V(0,1,0))*R(0,-tlan,-ti). 24 | return (angleaxis(-taop-tta, T_AN_NRM:upvector)*T_AN_NRM):vector. 25 | } 26 | 27 | function VelTA2 { 28 | parameter tsma, tecc, ti, tlan, taop, tta. 29 | local int_e to -body:mu / (2*tsma). 30 | local refNRM to lookdirup(SolarPrimeVector, V(0,1,0))*R(0,-tlan,-ti):upvector. 31 | local AltAP to tsma * (1 + tecc). 32 | local AltTA to AltTA2(tsma, tecc, ti, tlan, taop, tta). 33 | local UniPos to UniPosTA2(tsma, tecc, ti, tlan, taop, tta). 34 | local SpdAP to sqrt( 2 * (body:mu / AltAP + int_e ) ). 35 | local SpdTA to sqrt( 2 * (body:mu / AltTA + int_e ) ). 36 | local int_l to AltAP * SpdAP. 37 | local Vtr to int_l / AltTA. 38 | local Vr to sqrt(SpdTA*SpdTA - Vtr*Vtr). 39 | if sin(tta) < 0 { set Vr to -Vr. } 40 | return Vr * UniPos + Vtr * vcrs(UniPos, refNRM). 41 | } 42 | -------------------------------------------------------------------------------- /Moona/1/sat.ks: -------------------------------------------------------------------------------- 1 | require("libwarp","warpfor.ks"). 2 | 3 | function AlignToSun { 4 | lock steering to lookdirup(Sun:position,north:vector). 5 | } 6 | 7 | function nextmode { 8 | parameter newmode is satmode+1. 9 | set satmode to newmode. 10 | log "set satmode to " + newmode + "." to "mode.ks". 11 | AlignToSun(). 12 | } 13 | 14 | function waitwindow { 15 | parameter Horb. 16 | 17 | local lngdiff to ship:longitude + 90 - Mun:longitude. 18 | 19 | local a1 to (Mun:apoapsis + Horb)/2 + body:radius. 20 | local t12 to constant:pi*sqrt(a1^3/body:mu). 21 | 22 | local phitrans to 180*(2*t12/Mun:orbit:period - 1). 23 | local omegaeff to 360*(1/body:rotationperiod - 1/Mun:orbit:period). 24 | local etatrans to (phitrans - lngdiff)/omegaeff - constant:pi/2*sqrt((body:radius + Horb)^3/body:mu) - 120. 25 | if etatrans < 0 set etatrans to etatrans + 360/omegaeff. 26 | 27 | wait until kuniverse:timewarp:issettled. 28 | set kuniverse:timewarp:mode to "rails". 29 | warpfor(etatrans). 30 | } 31 | 32 | function satprogram { 33 | if satmode = 0 { 34 | local Hb to 75000. 35 | waitwindow(Hb). 36 | require("Moona/1","launch.ks"). 37 | gettoorbit(Hb,600). 38 | startnextstage(). 39 | deletepath("launch.ks"). 40 | deletepath("warpheight.ks"). 41 | panels on. 42 | wait 20. 43 | nextmode(). 44 | } 45 | if satmode = 1 { 46 | require("Moona/1","mode1.ks"). 47 | nextmode(). 48 | } 49 | if satmode = 2 { 50 | deletepath("mode1.ks"). 51 | require("liborbital","exenode.ks"). 52 | exenode(). 53 | nextmode(). 54 | } 55 | if satmode = 3 { 56 | set dish to ship:partsnamed("HighGainAntenna5")[0]. 57 | set d to dish:getmodule("ModuleRTAntenna"). 58 | d:doevent("activate"). 59 | d:setfield("target", Kerbin). 60 | nextmode(). 61 | } 62 | until false AlignToSun(). 63 | } 64 | 65 | local satmode to 0. 66 | if exists("mode.ks") { runpath("mode.ks"). } 67 | else nextmode(0). 68 | satprogram(). 69 | -------------------------------------------------------------------------------- /libmath/ridders.ks: -------------------------------------------------------------------------------- 1 | @lazyglobal off. 2 | // Ridders' algorithm for finding zeros of functions 3 | // Ridders (1979), IEEE Transactions on Circuits and Systems, 26(11), 979-980 4 | // DOI: 10.1109/TCS.1979.1084580 5 | 6 | function solv_ridders { 7 | parameter fn, x0, x1, rtol to 0.0, verbose to False. 8 | 9 | local MAXITER to 50. 10 | set rtol to max(rtol, 2^(-53)). 11 | 12 | local xlo to x0. 13 | local xhi to x1. 14 | local xmid to 0. 15 | local flo to fn(x0). 16 | local fhi to fn(x1). 17 | local fmid to 0. 18 | local iter to 1. 19 | local delta to rtol * (1 + min(abs(x0), abs(x1))) * 0.5. 20 | local denom to 0. 21 | local xans to x0. 22 | 23 | if flo * fhi > 0 { 24 | print "ERROR in SOLV_RIDDERS: root not bracketed between endpoints". 25 | return 1 / 0. 26 | } 27 | 28 | if flo = 0 {return xlo.} 29 | if fhi = 0 {return xhi.} 30 | 31 | until iter > MAXITER { 32 | set xmid to (xlo + xhi) / 2. 33 | set delta to rtol * (1 + abs(xmid)) / 2. 34 | set fmid to fn(xmid). 35 | local r1 to fmid / flo. 36 | local r2 to fhi / flo. 37 | set denom to sqrt(r1 * r1 - r2). 38 | 39 | local dx to (xhi - xlo) * 0.5 * r1 / denom. 40 | if abs(dx) < delta { 41 | if dx > 0 {set dx to delta.} 42 | else {set dx to -delta.} 43 | } 44 | set xans to xmid + dx. 45 | 46 | if verbose { 47 | print iter + ". x = " + xans + "; est_err = " + abs(xhi - xlo) / 2. 48 | } 49 | 50 | if (abs(xhi - xlo) < 2 * delta) {return xans.} 51 | local fans to fn(xans). 52 | if fans = 0 { return fans. } 53 | if fans * fmid < 0 { 54 | set xlo to xmid. 55 | set xhi to xans. 56 | set flo to fmid. 57 | set fhi to fans. 58 | } 59 | else if fans * flo < 0 { 60 | set xhi to xans. 61 | set fhi to fans. 62 | } 63 | else { 64 | set xlo to xans. 65 | set flo to fans. 66 | } 67 | set iter to iter + 1. 68 | } 69 | print "WARNING: exceeded MAXITER in SOLV_RIDDERS". 70 | return xans. 71 | } 72 | -------------------------------------------------------------------------------- /L3project/lander/launch.ks: -------------------------------------------------------------------------------- 1 | require("liborbital","circularize.ks"). 2 | require("liborbital","aponode.ks"). 3 | require("liborbital","exenode.ks"). 4 | 5 | function printtlm { 6 | local pitch to 90 - vang( up:vector, velocity:surface ). 7 | print "Apoapsis: " + round( apoapsis/1000, 2 ) + " km " at (0,30). 8 | print "Periapsis: " + round( periapsis/1000, 2 ) + " km " at (0,31). 9 | print " Altitude: " + round( altitude/1000, 2 ) + " km " at (24,30). 10 | print " Pitch: " + round( pitch ) + " deg " at (24,31). 11 | } 12 | 13 | function PitchCtrl { 14 | parameter vstart, h0, v45, AP45, APstop. 15 | 16 | if alt:radar < h0 {return 90.} 17 | 18 | local vsm to velocity:surface:mag. 19 | local pitch to 0. 20 | 21 | if vsm < v45 { 22 | set pitch to 90 - arctan( (vsm - vstart)/(v45 - vstart) ). 23 | } 24 | else { 25 | set pitch to max(0, 45*(apoapsis - APstop) / (AP45 - APstop) ). 26 | } 27 | return pitch. 28 | } 29 | 30 | function gettoorbit { 31 | parameter Horb to 15000. 32 | parameter GTstart to 2*alt:radar. 33 | parameter GTv1 to 80. 34 | parameter GTendAP to Horb - 1000. 35 | 36 | lock throttle to 1. 37 | lock steering to lookdirup(-body:position,facing:upvector). 38 | stage. 39 | wait 0.1. 40 | ship:partsnamed("liquidEngineMini")[0]:activate. 41 | 42 | local vsm to velocity:surface:mag. 43 | local GTStartSpd to vsm. 44 | local Apo2 to apoapsis. 45 | 46 | until apoapsis >= Horb { 47 | set vsm to velocity:surface:mag. 48 | local pitch to PitchCtrl(GTStartSpd,GTstart,GTv1,Apo2,GTendAP). 49 | if alt:radar <= GTstart { set GTStartSpd to vsm. } 50 | if vsm < GTv1 { 51 | if apoapsis < GTendAP { set Apo2 to apoapsis. } 52 | else { set Apo2 to GTendAP*0.5. } 53 | } 54 | 55 | if alt:radar > GTstart lock steering to heading(270, pitch). 56 | printtlm(). 57 | wait 0. 58 | } 59 | 60 | lock throttle to 0. 61 | 62 | aponode(). 63 | exenode(). 64 | circularize(). 65 | deletepath("liborbital/circularize.ks"). 66 | } 67 | -------------------------------------------------------------------------------- /libmath/cse.ks: -------------------------------------------------------------------------------- 1 | // Conic State Extrapolation 2 | // Formulas follow H.D. Curtis, Orbital Mechanics for Engineering Students, Chapter 3.7 3 | 4 | // Stumpff S and C functions 5 | function SnC { 6 | parameter z. 7 | local az to abs(z). 8 | if az < 1e-4 { 9 | return lexicon("S", (1 - z * ( 0.05 - z / 840) ) / 6, "C", 0.5 - z * ( 1 - z / 30) / 24). 10 | } 11 | else { 12 | local saz to sqrt(az). 13 | if z > 0 { 14 | local x to saz * constant:radtodeg. 15 | return lexicon("S", (saz - sin(x)) / (saz * az), "C", (1 - cos(x)) / az). 16 | } 17 | else { 18 | local x to constant:e^saz. 19 | return lexicon("S", (0.5 * (x - 1 / x) - saz) / (saz * az), "C", (0.5 * (x + 1 / x) - 1) / az). 20 | } 21 | } 22 | } 23 | 24 | // Conic State Extrapolation Routine 25 | function CSER { 26 | parameter r0v0, dt, mu to body:mu, x0 to 0, tol to 5e-12. 27 | local rscale to r0v0[0]:mag. 28 | local vscale to sqrt(mu / rscale). 29 | local r0s to r0v0[0] / rscale. 30 | local v0s to r0v0[1] / vscale. 31 | local dts to dt * vscale / rscale. 32 | local v2s to r0v0[1]:sqrmagnitude * rscale / mu. 33 | local alpha to 2 - v2s. 34 | local armd1 to v2s - 1. 35 | local rvr0s to vdot(r0v0[0], r0v0[1]) / sqrt(mu * rscale). 36 | 37 | local x to x0. 38 | if x0 = 0 { set x to dts * abs(alpha). } 39 | local ratio to 1. 40 | local x2 to x * x. 41 | local z to alpha * x2. 42 | local SCz to SnC(z). 43 | local x2Cz to x2 * SCz["C"]. 44 | local f to 0. 45 | local df to 0. 46 | 47 | until abs(ratio) < tol { 48 | set f to x + rvr0s * x2Cz + armd1 * x * x2 * SCz["S"] - dts. 49 | set df to x * rvr0s * (1 - z * SCz["S"]) + armd1 * x2Cz + 1. 50 | set ratio to f / df. 51 | set x to x - ratio. 52 | set x2 to x * x. 53 | set z to alpha * x2. 54 | set SCz to SnC(z). 55 | set x2Cz to x2 * SCz["C"]. 56 | } 57 | 58 | local Lf to 1 - x2Cz. 59 | local Lg to dts - x2 * x * SCz["S"]. 60 | 61 | local r1 to Lf * r0s + Lg * v0s. 62 | local ir1 to 1 / r1:mag. 63 | local Lfdot to ir1 * x * (z * SCz["S"] - 1). 64 | local Lgdot to 1 - x2Cz * ir1. 65 | 66 | local v1 to Lfdot * r0s + Lgdot * v0s. 67 | 68 | return list(r1 * rscale, v1 * vscale, x). 69 | } 70 | -------------------------------------------------------------------------------- /Moona/Pol/sat.ks: -------------------------------------------------------------------------------- 1 | function runfiles { 2 | parameter fl. 3 | for f in fl if exists(f) runpath(f). 4 | } 5 | 6 | function AlignToSun { 7 | lock steering to lookdirup(Sun:position,Kerbin:position). 8 | } 9 | 10 | function nextmode { 11 | parameter newmode is satmode+1. 12 | set satmode to newmode. 13 | log "set satmode to " + newmode + "." to "mode.ks". 14 | AlignToSun(). 15 | } 16 | 17 | function satprogram { 18 | runfiles(list("exenode.ks","polorb.ks","perinode.ks","aponode.ks")). 19 | local hmun to 35000. 20 | if satmode = 0 { 21 | local Hb to 75000. 22 | require("Moona/Pol","wait.ks"). 23 | waitwindow(Hb). 24 | deletepath("wait.ks"). 25 | require("Moona/Pol","launch.ks"). 26 | gettoorbit(Hb,750). 27 | startnextstage(). 28 | deletepath("launch.ks"). 29 | deletepath("warpheight.ks"). 30 | panels on. 31 | wait 20. 32 | nextmode(). 33 | } 34 | if satmode = 1 { 35 | require("Moona/Pol","mode1.ks"). 36 | nextmode(). 37 | } 38 | if satmode = 2 { 39 | deletepath("mode1.ks"). 40 | require("liborbital","exenode.ks"). 41 | exenode(). 42 | nextmode(). 43 | } 44 | if satmode = 3 { 45 | ship:partsnamed("HighGainAntenna5")[0]:getmodule("ModuleRTAntenna"):setfield("target",Kerbin). 46 | nextmode(). 47 | } 48 | if satmode = 4 { 49 | if body:name = "Kerbin" warpfor(eta:transition-60). 50 | wait until body:name = "Mun". 51 | nextmode(). 52 | } 53 | if satmode = 5 { 54 | require("Moona/Pol","polorb.ks"). 55 | polorb(60). 56 | deletepath("polorb.ks"). 57 | nextmode(). 58 | } 59 | if satmode = 6 { 60 | exenode(). 61 | nextmode(). 62 | } 63 | if satmode = 7 { 64 | require("liborbital","perinode.ks"). 65 | require("liborbital","aponode.ks"). 66 | perinode(hmun). 67 | nextmode(). 68 | } 69 | if satmode = 8 { 70 | exenode(). 71 | nextmode(). 72 | } 73 | if satmode = 9 { 74 | if abs(periapsis - hmun) < abs(apoapsis - hmun) perinode(). 75 | else aponode(). 76 | nextmode(). 77 | } 78 | if satmode = 10 { 79 | exenode(). 80 | nextmode(). 81 | } 82 | until false AlignToSun(). 83 | } 84 | 85 | local satmode to 0. 86 | if exists("mode.ks") { runpath("mode.ks"). } 87 | else nextmode(0). 88 | satprogram(). 89 | -------------------------------------------------------------------------------- /Kommsat-incl/satprogram.ks: -------------------------------------------------------------------------------- 1 | function AlignToSun { 2 | lock steering to lookdirup(north:vector,Sun:position). 3 | } 4 | 5 | function aneta { 6 | local vecs to orbdir(). 7 | local anangle to arctan2( vdot(vcrs(body:position, vecs:vector), vecs:upvector), -vdot(vecs:vector, body:position)). 8 | if anangle < 0 { set anangle to 360 + anangle. } 9 | return anangle / 360 * orbit:period. 10 | } 11 | 12 | function nextmode { 13 | parameter newmode is satmode+1. 14 | set satmode to newmode. 15 | log "set satmode to " + newmode + "." to "mode.ks". 16 | AlignToSun(). 17 | } 18 | 19 | function waitconnect { 20 | wait 15. 21 | set warp to 3. 22 | wait until addons:rt:haskscconnection(ship). 23 | set warp to 0. 24 | } 25 | 26 | function satprogram { 27 | if satmode = 0 { 28 | require("Kommsat-incl","launch.ks"). 29 | gettoorbit(). 30 | deletepath("launch.ks"). 31 | startnextstage(). 32 | circularize(). 33 | deletepath("circularize.ks"). 34 | wait 20. 35 | nextmode(). 36 | } 37 | if satmode = 1 { 38 | print "Aligning for optimal solar panel performance.". 39 | waitconnect(). 40 | nextmode(). 41 | } 42 | if satmode = 2 { 43 | require("liborbital","orbdir.ks"). 44 | require("Kommsat-incl","transfernode.ks"). 45 | require("liborbital","exenode.ks"). 46 | transfernode(7200, aneta). 47 | deletepath("transfernode.ks"). 48 | deletepath("orbdir.ks"). 49 | nextmode(). 50 | } 51 | if satmode = 3 { 52 | exenode(). 53 | nextmode(). 54 | } 55 | if satmode = 4 { 56 | waitconnect(). 57 | require("Kommsat-incl","fltper.ks"). 58 | fltper(7200). 59 | deletepath("fltper.ks"). 60 | nextmode(). 61 | } 62 | if satmode = 5 { 63 | exenode(). 64 | nextmode(). 65 | } 66 | if satmode = 6 { 67 | waitconnect(). 68 | require("liborbital","circularize.ks"). 69 | circularize(). 70 | require("liborbital","trimperiod.ks"). 71 | TrimPeriod(7200). 72 | nextmode(). 73 | } 74 | if satmode = 7 { 75 | set dish to ship:partsnamed("HighGainAntenna5")[0]. 76 | set d to dish:getmodule("ModuleRTAntenna"). 77 | d:doevent("activate"). 78 | d:setfield("target", Mun). 79 | print "Satellite deployed to operational orbit.". 80 | nextmode(). 81 | } 82 | until false AlignToSun(). 83 | } 84 | 85 | local satmode to 0. 86 | if exists("mode.ks") { runpath("mode.ks"). } 87 | else nextmode(0). 88 | satprogram(). 89 | -------------------------------------------------------------------------------- /libinput/require.ks: -------------------------------------------------------------------------------- 1 | function require { 2 | parameter lib is "", fn is "". 3 | local wd to path(). 4 | if exists("1:/reqlex.json") = false { 5 | writejson(lexicon(), "1:/reqlex.json"). 6 | } 7 | local reqlex to readjson("1:/reqlex.json"). 8 | if lib = "" { 9 | if fn = "" { 10 | for l in reqlex:keys { 11 | for fname in reqlex[l] { 12 | print "1:/" + l + "/" + fname. 13 | runpath("1:/" + l + "/" + fname). 14 | } 15 | } 16 | } 17 | else { 18 | for l in reqlex:keys { 19 | for fname in reqlex[l] { 20 | if fname:contains(fn) runpath("1:/" + lib + "/" + fname). 21 | } 22 | } 23 | } 24 | } 25 | else { 26 | if reqlex:haskey(lib) = false { 27 | reqlex:add(lib, list()). 28 | } 29 | local prefix to "1:/" + lib + "/". 30 | local fhere to False. 31 | if (homeconnection:isconnected = false) or homeconnection:delay > 2 { 32 | for fname in reqlex[lib] { 33 | if fname:contains(fn) { 34 | set fhere to exists(prefix + fname). 35 | } 36 | } 37 | } 38 | if (homeconnection:isconnected and homeconnection:delay <= 2) or fhere = false { 39 | cd("0:/" + lib). 40 | list files in fl. 41 | for f in fl { 42 | if f:name:contains(fn) { 43 | if reqlex[lib]:contains(f:name) = false { 44 | reqlex[lib]:add(f:name). 45 | } 46 | copypath(f:name, prefix + f:name). 47 | writejson(reqlex, "1:/reqlex.json"). 48 | set fhere to exists(prefix + f:name). 49 | } 50 | } 51 | cd(wd). 52 | } 53 | if fhere = false { 54 | print "ERROR: Cannot load file". 55 | print 1/0. 56 | } 57 | for fname in reqlex[lib] { 58 | if fname:contains(fn) { runpath(prefix + fname). } 59 | } 60 | } 61 | } 62 | 63 | function unrequire { 64 | parameter fn. 65 | local reqlex to readjson("1:/reqlex.json"). 66 | for l in reqlex:keys { 67 | local it to reqlex[l]:iterator. 68 | until it:next = false { 69 | print it:value. 70 | if it:value:startswith(fn) { 71 | deletepath("1:/" + l + "/" + it:value). 72 | print("Removing file " + l + "/" + it:value). 73 | reqlex[l]:remove(it:index). 74 | break. 75 | } 76 | } 77 | if reqlex[l]:empty() { 78 | reqlex:remove(l). 79 | break. 80 | } 81 | } 82 | writejson(reqlex, "1:/reqlex.json"). 83 | } 84 | -------------------------------------------------------------------------------- /liborbital/exenode.ks: -------------------------------------------------------------------------------- 1 | require("libwarp","warpfor.ks"). 2 | require("libvessel","thrustisp.ks"). 3 | 4 | function exenode { 5 | local nd to nextnode. 6 | local done to False. 7 | local once to True. 8 | local lock tm to round(missiontime). 9 | 10 | set ship:control:pilotmainthrottle to 0. 11 | print "T+" + tm + " Node in: " + round(nd:eta) + ", DeltaV: " + round(nd:deltav:mag). 12 | local TIsp to ThrustIsp(). 13 | local tt to TIsp[0]. 14 | local vex to TIsp[1]. 15 | if tt = 0 { 16 | print "ERROR: No active engines!". 17 | set ship:control:pilotmainthrottle to 0. 18 | return. 19 | } 20 | local maxa to tt/mass. 21 | local dob to vex / maxa * (1 - constant:e^(-nd:deltav:mag/vex)). 22 | print "Burn duration: " + round(dob) + " s". 23 | local dob2 to vex/maxa - vex*dob/nd:deltav:mag. 24 | warpfor(nd:eta-dob2-60). 25 | sas off. 26 | rcs off. 27 | 28 | print "T+" + tm + " Turning ship to burn direction.". 29 | lock steering to lookdirup(nd:deltav*(tt/abs(tt)),-body:position). 30 | wait until vang( nd:deltav*(tt/abs(tt)),facing:vector ) < 0.05 and ship:angularvel:mag < 0.05. 31 | warpfor(nd:eta-dob2-10). 32 | print "T+" + tm + " Burn start " + round(dob2) + " s before node.". 33 | local tset to 0. 34 | lock throttle to tset. 35 | 36 | local dv0 to nd:deltav. 37 | wait until nd:eta <= dob2. 38 | until done { 39 | set tset to min(nd:deltav:mag*mass/abs(tt), 1). 40 | if once and tset < 1 { 41 | print "T+" + tm + " Throttling down, remain dv " + round(nd:deltav:mag) + "m/s". 42 | set once to False. 43 | } 44 | if vdot(dv0, nd:deltav) < 0 { 45 | print "T+" + tm + " Burn aborted, remain dv " + round(nd:deltav:mag,1) + "m/s, vdot: " + round(vdot(dv0, nd:deltav),1). 46 | lock throttle to 0. 47 | break. 48 | } 49 | if nd:deltav:mag < 0.1 { 50 | print "T+" + tm + " Finalizing, remain dv " + round(nd:deltav:mag,1) + "m/s". 51 | wait until vdot(dv0, nd:deltav) < 0.5. 52 | lock throttle to 0. 53 | print "T+" + tm + " End burn, remain dv " + round(nd:deltav:mag,1) + "m/s". 54 | set done to True. 55 | } 56 | } 57 | unlock steering. 58 | set ship:control:pilotmainthrottle to 0. 59 | print "T+" + tm + " Ap: " + round(apoapsis/1000,2) + " km, Pe: " + round(periapsis/1000,2) + " km". 60 | print "T+" + tm + " Remaining LF: " + round(stage:liquidfuel,1). 61 | wait 1. 62 | remove nd. 63 | unlock tm. 64 | unlock throttle. 65 | } 66 | -------------------------------------------------------------------------------- /Moona/6/sat.ks: -------------------------------------------------------------------------------- 1 | function runfiles { 2 | parameter fl. 3 | for f in fl if exists(f) runpath(f). 4 | } 5 | 6 | function AlignToSun { 7 | lock steering to lookdirup(Sun:position,Kerbin:position). 8 | } 9 | 10 | function nextmode { 11 | parameter newmode is satmode+1. 12 | set satmode to newmode. 13 | log "set satmode to " + newmode + "." to "mode.ks". 14 | AlignToSun(). 15 | } 16 | 17 | function satprogram { 18 | runfiles(list("warpfor.ks","exenode.ks","perinode.ks","aponode.ks","landing1.ks")). 19 | local hmun to 25500. 20 | if satmode = 0 { 21 | local Hb to 75000. 22 | require("Moona/5","wait.ks"). 23 | waitwindow(Hb). 24 | deletepath("wait.ks"). 25 | require("Moona/5","launch.ks"). 26 | gettoorbit(Hb,650,55000). 27 | startnextstage(). 28 | deletepath("launch.ks"). 29 | deletepath("warpheight.ks"). 30 | panels on. 31 | wait 20. 32 | nextmode(). 33 | } 34 | if satmode = 1 { 35 | require("Moona/5","mode1.ks"). 36 | nextmode(). 37 | } 38 | if satmode = 2 { 39 | deletepath("mode1.ks"). 40 | require("liborbital","exenode.ks"). 41 | exenode(). 42 | nextmode(). 43 | } 44 | if satmode = 3 { 45 | ship:partsnamed("HighGainAntenna5")[0]:getmodule("ModuleRTAntenna"):setfield("target",Kerbin). 46 | nextmode(). 47 | } 48 | if satmode = 4 { 49 | if body:name = "Kerbin" warpfor(eta:transition-60). 50 | wait until body:name = "Mun". 51 | nextmode(). 52 | } 53 | if satmode = 5 { 54 | require("liborbital","perinode.ks"). 55 | require("liborbital","aponode.ks"). 56 | require("Moona/5","landing1.ks"). 57 | perinode(hmun). 58 | nextmode(). 59 | } 60 | if satmode = 6 { 61 | exenode(). 62 | nextmode(). 63 | } 64 | if satmode = 7 { 65 | if abs(periapsis - hmun) < abs(apoapsis - hmun) perinode(). 66 | else aponode(). 67 | nextmode(). 68 | } 69 | if satmode = 8 { 70 | exenode(). 71 | nextmode(). 72 | } 73 | if satmode = 9 { 74 | deletepath("exenode.ks"). 75 | deletepath("aponode.ks"). 76 | deletepath("perinode.ks"). 77 | 78 | local Isp to 315. 79 | local tmax to 0.9. 80 | 81 | if lmode = 0 nextlmode(). 82 | landing(landsite, 0.85, 4.0, Isp). 83 | nextmode(). 84 | } 85 | unlock steering. 86 | sas on. 87 | return. 88 | } 89 | 90 | local satmode to 0. 91 | local lmode to 0. 92 | if exists("lmode.ks") runpath("lmode.ks"). 93 | if exists("mode.ks") runpath("mode.ks"). 94 | else nextmode(0). 95 | satprogram(). 96 | -------------------------------------------------------------------------------- /Kommsat-incl/sat2.ks: -------------------------------------------------------------------------------- 1 | function AlignToSun { 2 | lock steering to lookdirup(north:vector,Sun:position). 3 | } 4 | 5 | function nextmode { 6 | parameter newmode is satmode+1. 7 | set satmode to newmode. 8 | log "set satmode to " + newmode + "." to "mode.ks". 9 | AlignToSun(). 10 | } 11 | 12 | function waitconnect { 13 | wait 15. 14 | set warp to 3. 15 | wait until addons:rt:haskscconnection(ship). 16 | set warp to 0. 17 | } 18 | 19 | function phase { 20 | parameter pos1, pos2. 21 | local p to arctan2( vcrs(pos1,pos2):y,vdot(pos1,pos2) ). 22 | if p<0 set p to 360+p. 23 | return p. 24 | } 25 | 26 | function satprogram { 27 | if satmode = 0 { 28 | require("Kommsat-incl","launch2.ks"). 29 | startnextstage(). 30 | deletepath("launch2.ks"). 31 | panels on. 32 | wait 20. 33 | nextmode(). 34 | } 35 | if satmode = 1 { 36 | print "Aligning for optimal solar panel performance.". 37 | waitconnect(). 38 | nextmode(). 39 | } 40 | if satmode = 2 { 41 | require("Kommsat-incl","mode2.ks"). 42 | nextmode(). 43 | } 44 | if satmode = 3 { 45 | deletepath("mode2.ks"). 46 | exenode(). 47 | nextmode(). 48 | } 49 | if satmode = 4 { 50 | clearscreen. 51 | waitconnect(). 52 | require("Kommsat-incl","fltper.ks"). 53 | local dphi to phase(positionat(target,time:seconds+eta:apoapsis)-body:position,positionat(ship,time:seconds+eta:apoapsis)-body:position)-90. 54 | print "Phasing angle: "+round(dphi). 55 | fltper(target:orbit:period*(1-dphi/360)). 56 | nextmode(). 57 | } 58 | if satmode = 5 { 59 | exenode(). 60 | nextmode(). 61 | } 62 | if satmode = 6 { 63 | fltper(target:orbit:period). 64 | deletepath("fltper.ks"). 65 | nextmode(). 66 | } 67 | if satmode = 7 { 68 | exenode(). 69 | nextmode(). 70 | } 71 | if satmode = 8 { 72 | waitconnect(). 73 | require("liborbital","circularize.ks"). 74 | circularize(). 75 | require("liborbital","trimperiod.ks"). 76 | TrimPeriod(target:orbit:period). 77 | nextmode(). 78 | } 79 | if satmode = 9 { 80 | set dish to ship:partsnamed("HighGainAntenna5")[0]. 81 | set d to dish:getmodule("ModuleRTAntenna"). 82 | d:doevent("activate"). 83 | d:setfield("target", Mun). 84 | print "Satellite deployed to operational orbit.". 85 | nextmode(). 86 | } 87 | until false AlignToSun(). 88 | } 89 | 90 | local satmode to 0. 91 | if exists("mode.ks") { runpath("mode.ks"). } 92 | else nextmode(0). 93 | satprogram(). 94 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # kOS 2 | set of kOS utilities and complete mission profiles (with craft files) 3 | 4 | Utilities: 5 | * libinput - currently only has library loader 6 | * require.ks - load (require) and delete (unrequire) other libraries to the vessel storage 7 | 8 | * libmath - set of mathematical functions and solvers 9 | * math.ks - useful mathematical functions (direct and inverse hyperbolic functions, sign, short aliases for Euler e, pi, degtorad and radtodeg) 10 | * frame.ks - functions to convert coordinates between reference frames 11 | * cse.ks - conic state extrapolation from arbitrary initial state 12 | * brent.ks - Brent-Dekker's root-finding algorithm 13 | * lambert.ks - Lambert solver 14 | 15 | * liborbital - library for orbital operations. 16 | * altNodes - gives altitude (AltTA2), direction (UniPosTA2) and velocity (VelTA2) at given true anomaly, and true anomaly of ascending node (TAofAN2) 17 | * annorm.ks - calculate body-centric AN and normal vectors given orbital inclination and LAN 18 | * aponode.ks and perinode.ks - plan prograde maneuver nodes at apoapsis / periapsis to change the opposite apsis to a set value 19 | * circularize.ks - circularize orbit at ship's current position 20 | * dock.ks - dock to the target port of another vessel 21 | * etaNodes.ks - functions to calculate time to a given true anomaly, ascending node and descending node (only for elliptic orbits) 22 | * exenode.ks - execute maneuver node 23 | * orbdir.ks - calculate body-centric AN and normal vectors of ship's current orbit 24 | * trimperiod.ks - fine-tune orbital period burning prograde or retrograde 25 | 26 | * libvessel - functions to get vessel properties 27 | * thrustisp.ks - get projection of thrust onto current facing vector and effective exhaust velocity for all active engines 28 | * vesselsize.ks - estimate maximum size of the vessel (useful for safe docking) 29 | 30 | * libwarp - functions to control time warp 31 | * warpfor - warp for specified time (unlike kuniverse:timewarp:warpto() will not be interrupted by external events such as KAC alarms or whatnot) 32 | * warpheight - warp to the specified altitude ASL 33 | 34 | Missions: 35 | * KOT - 1-person spacecraft 36 | * KOT-1 - get to LKO and back 37 | * KOT-D - equipped with a docking port, designed to dock to a target vessel 38 | 39 | * Dockee - docking target vessel 40 | 41 | * Kommsat - spacecraft for medium-altitude relay network. Designed to start from nonzero latitude and get to equatorial orbit 42 | * Kommsat 2 - same as Kommsat, designed to get into orbit 90 degrees apart from Kommsat 1 43 | 44 | * Mapsat - SCANSat probe designed for polar orbit 45 | 46 | * Moona - Munar robotic exploration project 47 | * Moona 1 - impactor probe 48 | * Moona 2 - orbiter probe 49 | * Moona Pol - polar orbiter with SCANSat scanner 50 | * Moona 6 - lander (needs coordinates to land at) 51 | 52 | * L3project - Soviet-themed manned Munar landing 53 | * video: https://youtu.be/KP_vmEz1-34 54 | * parts from Home-Grown Rockets are highly customized, so no craft file, sorry 55 | -------------------------------------------------------------------------------- /KOT/launch.ks: -------------------------------------------------------------------------------- 1 | require("liborbital","circularize.ks"). 2 | 3 | function VertAscent { 4 | lock steering to heading(90,90). 5 | } 6 | 7 | function CapTWR { 8 | parameter maxTWR is 3.0. 9 | local g0 to Kerbin:mu/Kerbin:radius^2. 10 | lock throttle to min(1, ship:mass*g0*maxTWR / max( ship:availablethrust, 0.001 ) ). 11 | } 12 | 13 | function printtlm { 14 | local pitch to 90 - vang( up:vector, velocity:surface ). 15 | print "Apoapsis: " + round( apoapsis/1000, 2 ) + " km " at (0,30). 16 | print "Periapsis: " + round( periapsis/1000, 2 ) + " km " at (0,31). 17 | print " Altitude: " + round( altitude/1000, 2 ) + " km " at (24,30). 18 | print " Pitch: " + round( pitch ) + " deg " at (24,31). 19 | } 20 | 21 | function GravityTurn { 22 | parameter vstart. 23 | parameter AP45 is apoapsis. 24 | parameter APstop is 60000. 25 | parameter v45 is 500. 26 | 27 | local vsm to velocity:surface:mag. 28 | local pitch to 0. 29 | if ( vsm < v45 ) { 30 | set pitch to 90 - arctan( (vsm - vstart)/(v45 - vstart) ). 31 | } 32 | else { 33 | set pitch to max(0, 45*(apoapsis - APstop) / (AP45 - APstop) ). 34 | } 35 | lock steering to heading( 90, pitch ). 36 | printtlm(). 37 | } 38 | 39 | function startnextstage { 40 | until ship:availablethrust > 0 { 41 | if altitude apw { lock throttle to 0. } 51 | else { lock throttle to max( 0.05, Kp*(apw - apoapsis)/apw ). } 52 | printtlm(). 53 | } 54 | 55 | function gettoorbit { 56 | parameter Horb to body:atm:height + 10000. 57 | parameter GTstart to 800. 58 | parameter GTendAP to 55000. 59 | 60 | local maxTWR to 3.0. 61 | lock throttle to 1. 62 | local initialpos to ship:facing. 63 | lock steering to initialpos. 64 | startnextstage(). 65 | 66 | until alt:radar > GTstart { 67 | VertAscent(). 68 | startnextstage(). 69 | CapTWR(maxTWR). 70 | wait 0.01. 71 | } 72 | 73 | local GTStartSpd to velocity:surface:mag. 74 | local Apo45 to apoapsis. 75 | local lock pitch to 90 - vang( up:vector, velocity:surface ). 76 | 77 | until apoapsis >= Horb { 78 | if pitch >= 45 { set Apo45 to apoapsis. } 79 | GravityTurn(GTStartSpd,Apo45,GTendAP). 80 | startnextstage(). 81 | CapTWR(maxTWR). 82 | wait 0.01. 83 | } 84 | 85 | lock throttle to 0. 86 | 87 | lock steering to prograde. 88 | until altitude > body:atm:height { 89 | APkeep(Horb). 90 | wait 0.01. 91 | } 92 | lock throttle to 0. 93 | print "We are in space. Deploying fairing. ". 94 | wait 5. 95 | stage. 96 | 97 | wait until altitude > apoapsis - 20. 98 | circularize(). 99 | 100 | print "We are in orbit: " + round(apoapsis/1000,2) + "x" + round(periapsis/1000,2) + " km. ". 101 | wait 5. 102 | 103 | print "Dumping carrier stage.". 104 | lock steering to prograde. 105 | wait 5. 106 | stage. 107 | } 108 | -------------------------------------------------------------------------------- /Moona/Pol/launch.ks: -------------------------------------------------------------------------------- 1 | require("liborbital","circularize.ks"). 2 | require("libwarp","warpheight.ks"). 3 | 4 | function CapTWR { 5 | parameter maxTWR is 3.0. 6 | local g0 to 9.80665. 7 | lock throttle to min(1, ship:mass*g0*maxTWR / max(ship:availablethrust, 0.001) ). 8 | } 9 | 10 | function printtlm { 11 | local pitch to 90 - vang( up:vector, velocity:surface ). 12 | print "Apoapsis: " + round(apoapsis/1000, 2) + " km " at (0,30). 13 | print "Periapsis: " + round(periapsis/1000, 2) + " km " at (0,31). 14 | print " Altitude: " + round(altitude/1000, 2) + " km " at (24,30). 15 | print " Pitch: " + round( pitch ) + " deg " at (24,31). 16 | } 17 | 18 | function PitchCtrl { 19 | parameter vstart, h0, v45, Ap45, APstop is 60000. 20 | 21 | if alt:radar < h0 {return 90.} 22 | 23 | local vsm to velocity:surface:mag. 24 | local pitch to 0. 25 | if ( vsm < v45 ) { 26 | set pitch to 90 - arctan( (vsm - vstart)/(v45 - vstart) ). 27 | } 28 | else { 29 | set pitch to max(0, 45*(apoapsis - APstop) / (AP45 - APstop) ). 30 | } 31 | 32 | return pitch. 33 | } 34 | 35 | function startnextstage { 36 | until ship:availablethrust > 0 { 37 | if altitude apw { lock throttle to 0. } 47 | else { lock throttle to max( 0.05, Kp*(apw - apoapsis)/apw ). } 48 | printtlm(). 49 | } 50 | 51 | function gettoorbit { 52 | parameter Horb to body:atm:height + 10000. 53 | parameter GTv45 to 500. 54 | parameter GTstart to alt:radar*2. 55 | parameter GTendAP to 60000. 56 | 57 | local maxTWR to 3.0. 58 | lock throttle to 1. 59 | local initialpos to ship:facing. 60 | lock steering to initialpos. 61 | startnextstage(). 62 | 63 | local vsm to velocity:surface:mag. 64 | local GTStartSpd to vsm. 65 | local Apo45 to apoapsis. 66 | 67 | until apoapsis >= Horb { 68 | set vsm to velocity:surface:mag. 69 | if vsm <= GTv45 { set Apo45 to apoapsis. } 70 | if alt:radar <= GTstart { set GTStartSpd to vsm. } 71 | 72 | lock steering to heading( 90,pitchctrl(GTStartSpd,GTstart,GTv45,Apo45,GTendAP) ). 73 | startnextstage(). 74 | CapTWR(maxTWR). 75 | 76 | printtlm(). 77 | wait 0. 78 | } 79 | 80 | lock throttle to 0. 81 | 82 | lock steering to prograde. 83 | set warp to 3. 84 | 85 | until altitude > body:atm:height { 86 | APkeep(Horb). 87 | wait 0. 88 | } 89 | set warp to 0. 90 | lock throttle to 0. 91 | print "We are in space. Deploying payload fairing. ". 92 | wait 5. 93 | stage. 94 | wait 5. 95 | 96 | warpheight(apoapsis - 10). 97 | circularize(). 98 | 99 | print "We are in orbit: " + round(apoapsis/1000,2) + "x" + round(periapsis/1000,2) + " km. ". 100 | 101 | wait 5. 102 | 103 | local d to ship:partsnamed("HighGainAntenna5")[0]:getmodule("ModuleRTAntenna"). 104 | d:doevent("activate"). 105 | d:setfield("target","KSC Mission Control"). 106 | 107 | print "Releasing payload.". 108 | lock steering to prograde. 109 | wait 5. 110 | stage. 111 | } 112 | -------------------------------------------------------------------------------- /Moona/6/launch.ks: -------------------------------------------------------------------------------- 1 | require("liborbital","circularize.ks"). 2 | require("libwarp","warpheight.ks"). 3 | 4 | function CapTWR { 5 | parameter maxTWR is 3.0. 6 | local g0 to 9.80665. 7 | lock throttle to min(1, ship:mass*g0*maxTWR / max(ship:availablethrust, 0.001) ). 8 | } 9 | 10 | function printtlm { 11 | local pitch to 90 - vang( up:vector, velocity:surface ). 12 | print "Apoapsis: " + round(apoapsis/1000, 2) + " km " at (0,30). 13 | print "Periapsis: " + round(periapsis/1000, 2) + " km " at (0,31). 14 | print " Altitude: " + round(altitude/1000, 2) + " km " at (24,30). 15 | print " Pitch: " + round( pitch ) + " deg " at (24,31). 16 | } 17 | 18 | function PitchCtrl { 19 | parameter vstart, h0, v45, Ap45, APstop is 60000. 20 | 21 | if alt:radar < h0 {return 90.} 22 | 23 | local vsm to velocity:surface:mag. 24 | local pitch to 0. 25 | if ( vsm < v45 ) { 26 | set pitch to 90 - arctan( (vsm - vstart)/(v45 - vstart) ). 27 | } 28 | else { 29 | set pitch to max(0, 45*(apoapsis - APstop) / (AP45 - APstop) ). 30 | } 31 | 32 | return pitch. 33 | } 34 | 35 | function startnextstage { 36 | until ship:availablethrust > 0 { 37 | if altitude 0 wait 2. 41 | } 42 | } 43 | 44 | function APkeep { 45 | parameter apw. 46 | local Kp to 200. 47 | if apoapsis > apw { lock throttle to 0. } 48 | else { lock throttle to max( 0.05, Kp*(apw - apoapsis)/apw ). } 49 | printtlm(). 50 | } 51 | 52 | function gettoorbit { 53 | parameter Horb to body:atm:height + 10000. 54 | parameter GTv45 to 500. 55 | parameter GTendAP to 60000. 56 | parameter GTstart to alt:radar*2. 57 | 58 | local maxTWR to 3.0. 59 | lock throttle to 1. 60 | lock steering to heading(90,90). 61 | startnextstage(). 62 | 63 | local vsm to velocity:surface:mag. 64 | local GTStartSpd to vsm. 65 | local Apo45 to apoapsis. 66 | 67 | until apoapsis >= Horb { 68 | set vsm to velocity:surface:mag. 69 | if vsm <= GTv45 { set Apo45 to apoapsis. } 70 | if alt:radar <= GTstart { set GTStartSpd to vsm. } 71 | 72 | lock steering to heading(90,pitchctrl(GTStartSpd,GTstart,GTv45,Apo45,GTendAP) ). 73 | startnextstage(). 74 | CapTWR(maxTWR). 75 | 76 | printtlm(). 77 | wait 0. 78 | } 79 | 80 | lock throttle to 0. 81 | 82 | lock steering to prograde. 83 | set warp to 3. 84 | 85 | until altitude > body:atm:height { 86 | APkeep(Horb). 87 | wait 0. 88 | } 89 | set warp to 0. 90 | lock throttle to 0. 91 | print "We are in space. Deploying payload fairing. ". 92 | wait 5. 93 | stage. 94 | wait 5. 95 | 96 | warpheight(apoapsis - 10). 97 | circularize(). 98 | 99 | print "We are in orbit: " + round(apoapsis/1000,2) + "x" + round(periapsis/1000,2) + " km. ". 100 | 101 | wait 5. 102 | 103 | local d to ship:partsnamed("HighGainAntenna5")[0]:getmodule("ModuleRTAntenna"). 104 | d:doevent("activate"). 105 | d:setfield("target","KSC Mission Control"). 106 | 107 | print "Releasing payload.". 108 | lock steering to prograde. 109 | wait 5. 110 | stage. 111 | } 112 | -------------------------------------------------------------------------------- /Moona/1/launch.ks: -------------------------------------------------------------------------------- 1 | require("liborbital","circularize.ks"). 2 | require("libwarp","warpheight.ks"). 3 | 4 | function CapTWR { 5 | parameter maxTWR is 3.0. 6 | local g0 to 9.80665. 7 | lock throttle to min(1, ship:mass*g0*maxTWR / max(ship:availablethrust, 0.001) ). 8 | } 9 | 10 | function printtlm { 11 | local pitch to 90 - vang( up:vector, velocity:surface ). 12 | print "Apoapsis: " + round(apoapsis/1000, 2) + " km " at (0,30). 13 | print "Periapsis: " + round(periapsis/1000, 2) + " km " at (0,31). 14 | print " Altitude: " + round(altitude/1000, 2) + " km " at (24,30). 15 | print " Pitch: " + round( pitch ) + " deg " at (24,31). 16 | } 17 | 18 | function PitchCtrl { 19 | parameter vstart, h0, v45, Ap45, APstop is 60000. 20 | 21 | if alt:radar < h0 {return 90.} 22 | 23 | local vsm to velocity:surface:mag. 24 | local pitch to 0. 25 | if ( vsm < v45 ) { 26 | set pitch to 90 - arctan( (vsm - vstart)/(v45 - vstart) ). 27 | } 28 | else { 29 | set pitch to max(0, 45*(apoapsis - APstop) / (AP45 - APstop) ). 30 | } 31 | 32 | return pitch. 33 | } 34 | 35 | function startnextstage { 36 | until ship:availablethrust > 0 { 37 | if altitude apw { lock throttle to 0. } 47 | else { lock throttle to max( 0.05, Kp*(apw - apoapsis)/apw ). } 48 | printtlm(). 49 | } 50 | 51 | function gettoorbit { 52 | parameter Horb to body:atm:height + 10000. 53 | parameter GTv45 to 500. 54 | parameter GTstart to 150. 55 | parameter GTendAP to 55000. 56 | 57 | local maxTWR to 3.0. 58 | lock throttle to 1. 59 | local initialpos to ship:facing. 60 | lock steering to initialpos. 61 | startnextstage(). 62 | 63 | local vsm to velocity:surface:mag. 64 | local GTStartSpd to vsm. 65 | local Apo45 to apoapsis. 66 | 67 | until apoapsis >= Horb { 68 | set vsm to velocity:surface:mag. 69 | if vsm <= GTv45 { set Apo45 to apoapsis. } 70 | if alt:radar <= GTstart { set GTStartSpd to vsm. } 71 | 72 | lock steering to heading( 90,pitchctrl(GTStartSpd,GTstart,GTv45,Apo45,GTendAP) ). 73 | startnextstage(). 74 | CapTWR(maxTWR). 75 | 76 | printtlm(). 77 | wait 0. 78 | } 79 | 80 | lock throttle to 0. 81 | 82 | lock steering to prograde. 83 | set warp to 3. 84 | 85 | until altitude > body:atm:height { 86 | APkeep(Horb). 87 | wait 0. 88 | } 89 | set warp to 0. 90 | lock throttle to 0. 91 | print "We are in space. Deploying payload fairing. ". 92 | wait 5. 93 | stage. 94 | wait 5. 95 | 96 | warpheight(apoapsis - 10). 97 | circularize(). 98 | 99 | print "We are in orbit: " + round(apoapsis/1000,2) + "x" + round(periapsis/1000,2) + " km. ". 100 | wait 5. 101 | 102 | print "Deploying omni antennae.". 103 | set alist to ship:partsnamed("longAntenna"). 104 | for an in alist { 105 | set d to an:getmodule("ModuleRTAntenna"). 106 | d:doevent("activate"). 107 | } 108 | 109 | print "Releasing payload.". 110 | lock steering to prograde. 111 | wait 5. 112 | stage. 113 | } 114 | -------------------------------------------------------------------------------- /Moona/2/launch.ks: -------------------------------------------------------------------------------- 1 | require("liborbital","circularize.ks"). 2 | require("libwarp","warpheight.ks"). 3 | 4 | function CapTWR { 5 | parameter maxTWR is 3.0. 6 | local g0 to 9.80665. 7 | lock throttle to min(1, ship:mass*g0*maxTWR / max(ship:availablethrust, 0.001) ). 8 | } 9 | 10 | function printtlm { 11 | local pitch to 90 - vang( up:vector, velocity:surface ). 12 | print "Apoapsis: " + round(apoapsis/1000, 2) + " km " at (0,30). 13 | print "Periapsis: " + round(periapsis/1000, 2) + " km " at (0,31). 14 | print " Altitude: " + round(altitude/1000, 2) + " km " at (24,30). 15 | print " Pitch: " + round( pitch ) + " deg " at (24,31). 16 | } 17 | 18 | function PitchCtrl { 19 | parameter vstart, h0, v45, Ap45, APstop is 60000. 20 | 21 | if alt:radar < h0 {return 90.} 22 | 23 | local vsm to velocity:surface:mag. 24 | local pitch to 0. 25 | if ( vsm < v45 ) { 26 | set pitch to 90 - arctan( (vsm - vstart)/(v45 - vstart) ). 27 | } 28 | else { 29 | set pitch to max(0, 45*(apoapsis - APstop) / (AP45 - APstop) ). 30 | } 31 | 32 | return pitch. 33 | } 34 | 35 | function startnextstage { 36 | until ship:availablethrust > 0 { 37 | if altitude apw { lock throttle to 0. } 47 | else { lock throttle to max( 0.05, Kp*(apw - apoapsis)/apw ). } 48 | printtlm(). 49 | } 50 | 51 | function gettoorbit { 52 | parameter Horb to body:atm:height + 10000. 53 | parameter GTv45 to 500. 54 | parameter GTstart to 150. 55 | parameter GTendAP to 60000. 56 | 57 | local maxTWR to 3.0. 58 | lock throttle to 1. 59 | local initialpos to ship:facing. 60 | lock steering to initialpos. 61 | startnextstage(). 62 | 63 | local vsm to velocity:surface:mag. 64 | local GTStartSpd to vsm. 65 | local Apo45 to apoapsis. 66 | 67 | until apoapsis >= Horb { 68 | set vsm to velocity:surface:mag. 69 | if vsm <= GTv45 { set Apo45 to apoapsis. } 70 | if alt:radar <= GTstart { set GTStartSpd to vsm. } 71 | 72 | lock steering to heading( 90,pitchctrl(GTStartSpd,GTstart,GTv45,Apo45,GTendAP) ). 73 | startnextstage(). 74 | CapTWR(maxTWR). 75 | 76 | printtlm(). 77 | wait 0. 78 | } 79 | 80 | lock throttle to 0. 81 | 82 | lock steering to prograde. 83 | set warp to 3. 84 | 85 | until altitude > body:atm:height { 86 | APkeep(Horb). 87 | wait 0. 88 | } 89 | set warp to 0. 90 | lock throttle to 0. 91 | print "We are in space. Deploying payload fairing. ". 92 | wait 5. 93 | stage. 94 | wait 5. 95 | 96 | warpheight(apoapsis - 10). 97 | circularize(). 98 | 99 | print "We are in orbit: " + round(apoapsis/1000,2) + "x" + round(periapsis/1000,2) + " km. ". 100 | 101 | ship:partsnamed("ServiceBay.125")[0]:getmodule("ModuleAnimateGeneric"):doevent("Open"). 102 | wait 5. 103 | 104 | print "Deploying omni antennae.". 105 | ship:partsnamed("longAntenna")[0]:getmodule("ModuleRTAntenna"):doevent("activate"). 106 | 107 | print "Releasing payload.". 108 | lock steering to prograde. 109 | wait 5. 110 | stage. 111 | } 112 | -------------------------------------------------------------------------------- /Kommsat-incl/launch.ks: -------------------------------------------------------------------------------- 1 | require("liborbital","circularize.ks"). 2 | 3 | function VertAscent { 4 | lock steering to heading(90,90). 5 | } 6 | 7 | function CapTWR { 8 | parameter maxTWR is 3.0. 9 | local g0 to Kerbin:mu/Kerbin:radius^2. 10 | lock throttle to min(1, ship:mass*g0*maxTWR / max( ship:availablethrust, 0.001 ) ). 11 | } 12 | 13 | function printtlm { 14 | local pitch to 90 - vang( up:vector, velocity:surface ). 15 | print "Apoapsis: " + round( apoapsis/1000, 2 ) + " km " at (0,30). 16 | print "Periapsis: " + round( periapsis/1000, 2 ) + " km " at (0,31). 17 | print " Altitude: " + round( altitude/1000, 2 ) + " km " at (24,30). 18 | print " Pitch: " + round( pitch ) + " deg " at (24,31). 19 | } 20 | 21 | function GravityTurn { 22 | parameter vstart. 23 | parameter AP45 is apoapsis. 24 | parameter APstop is 60000. 25 | parameter v45 is 500. 26 | 27 | local vsm to velocity:surface:mag. 28 | local pitch to 0. 29 | if ( vsm < v45 ) { 30 | set pitch to 90 - arctan( (vsm - vstart)/(v45 - vstart) ). 31 | } 32 | else { 33 | set pitch to max(0, 45*(apoapsis - APstop) / (AP45 - APstop) ). 34 | } 35 | lock steering to heading( 90, pitch ). 36 | printtlm(). 37 | } 38 | 39 | function startnextstage { 40 | until ship:availablethrust > 0 { 41 | if altitude apw { lock throttle to 0. } 51 | else { lock throttle to max( 0.05, Kp*(apw - apoapsis)/apw ). } 52 | printtlm(). 53 | } 54 | 55 | function gettoorbit { 56 | parameter Horb to body:atm:height + 10000. 57 | parameter GTstart to 800. 58 | parameter GTendAP to 55000. 59 | 60 | local maxTWR to 3.0. 61 | lock throttle to 1. 62 | local initialpos to ship:facing. 63 | lock steering to initialpos. 64 | startnextstage(). 65 | 66 | until alt:radar > GTstart { 67 | VertAscent(). 68 | startnextstage(). 69 | CapTWR(maxTWR). 70 | wait 0.01. 71 | } 72 | 73 | local GTStartSpd to velocity:surface:mag. 74 | local Apo45 to apoapsis. 75 | local lock pitch to 90 - vang( up:vector, velocity:surface ). 76 | 77 | until apoapsis >= Horb { 78 | if pitch >= 45 { set Apo45 to apoapsis. } 79 | GravityTurn(GTStartSpd,Apo45,GTendAP). 80 | startnextstage(). 81 | CapTWR(maxTWR). 82 | wait 0.01. 83 | } 84 | 85 | lock throttle to 0. 86 | 87 | lock steering to prograde. 88 | until altitude > body:atm:height { 89 | APkeep(Horb). 90 | wait 0.01. 91 | } 92 | lock throttle to 0. 93 | print "We are in space. Deploying payload fairing. ". 94 | wait 5. 95 | stage. 96 | 97 | wait until altitude > apoapsis - 20. 98 | circularize(). 99 | 100 | print "We are in orbit: " + round(apoapsis/1000,2) + "x" + round(periapsis/1000,2) + " km. ". 101 | wait 5. 102 | 103 | print "Deploying omni antennae.". 104 | set alist to ship:partsnamed("longAntenna"). 105 | for an in alist { 106 | set d to an:getmodule("ModuleRTAntenna"). 107 | d:doevent("activate"). 108 | } 109 | 110 | print "Releasing payload.". 111 | lock steering to prograde. 112 | wait 5. 113 | stage. 114 | } 115 | gettoorbit(80000,100). 116 | -------------------------------------------------------------------------------- /libmath/lambert.ks: -------------------------------------------------------------------------------- 1 | require("libmath", "math.ks"). 2 | 3 | function lambert2 { 4 | // Following: Gooding, A procedure for the solution of Lambert's orbital boundary-value problem, Celestial Mechanics and Astronomy 48 (1990), 145-165 5 | // Der, The superior Lambert algorithm 6 | parameter r0, r1, dt, mu, prg to 1, tol to 5e-7, utol to 5*tol. 7 | 8 | local smu to sqrt(mu). 9 | local alpha to prg * vcrs(r1, r0):y. 10 | 11 | local psi to vang(r0, r1). 12 | if alpha < 0 { 13 | set psi to 360 - psi. 14 | } 15 | print psi. 16 | 17 | local r0m to r0:mag. 18 | local r1m to r1:mag. 19 | local unir0 to r0 / r0m. 20 | local unir1 to r1 / r1m. 21 | local c to (r1 - r0):mag. 22 | local uniC to (r1 - r0) / c. 23 | local m to r0m + r1m + c. 24 | local n to m - 2 * c. 25 | local ism to 1 / sqrt(m). 26 | local isn to 1 / sqrt(n). 27 | 28 | local tau to 4 * dt * smu / m^1.5. 29 | local ssign to sign(sin(psi)). 30 | local s to ssign * sqrt(n / m). 31 | local s2 to n / m. 32 | local ds3 to 2 * s2 * s. 33 | local s2fm1 to 2 * c / m. // 1 - s^2 34 | 35 | 36 | local tau_p to (2 - ds3) / 3. 37 | 38 | local ttype to 0. // ellipse 39 | if abs(tau - tau_p) < utol { set ttype to 1. } // parabola 40 | if tau < tau_p { set ttype to 2. } // hyperbola 41 | 42 | local x to ttype. 43 | local z to 0. 44 | 45 | local tau_me to arccos(s) * m_dtr + s * sqrt(s2fm1). 46 | 47 | local converged to false. 48 | local order to 2. 49 | local nmax to 10. 50 | local f0 to 0. 51 | local f1 to 1. 52 | local f2 to 1. 53 | 54 | until converged { 55 | if ttype <> 1 { 56 | if tau < tau_me { 57 | set x to tau_me * (tau_me / tau - 1). 58 | } 59 | else { 60 | set x to sqrt((tau - tau_me) / (tau + 0.5 * tau_me)). 61 | } 62 | } 63 | local U to 1 - x * x. 64 | set z to sqrt(s2 * x * x + s2fm1). 65 | local niter to 0. 66 | local ratio to 1. 67 | 68 | until abs(ratio) < tol or niter > nmax { 69 | local y to sqrt(abs(U)). 70 | local f to y * (z - s * x). 71 | local g to x * z + s * U. 72 | local d to 0. 73 | if U > utol { 74 | set d to (90 - arctan(g / f)) * m_dtr. 75 | } 76 | else if U < -utol { 77 | set d to ln(f + g). 78 | } 79 | if abs(U) > utol { 80 | set f0 to (s * z + d / y - x) / U. 81 | set f1 to (x * (3 * f0 + ds3 / z) - 2) / U. 82 | set f2 to (5 * x * f1 + 3 * f0 - ds3 * s2fm1 / z^3) / U. 83 | } 84 | else { 85 | set f0 to tau_p. 86 | } 87 | 88 | local diff to f0 - tau. 89 | local rooted to (order - 1) * ((order - 1) * f1 * f1 - order * diff * f2). 90 | if rooted > 0 { 91 | set ratio to order * diff / (f1 * (sqrt(rooted) / abs(f1) + 1)). 92 | } 93 | else { 94 | set ratio to diff / f1. 95 | } 96 | print diff / tau + " " + x. 97 | set x to x - ratio. 98 | set U to 1 - x * x. 99 | set z to sqrt(s2 * x * x + s2fm1). 100 | set niter to niter + 1. 101 | } 102 | if abs(ratio) < tol set converged to true. 103 | set order to order + 1. 104 | } 105 | 106 | local v to ssign * z * isn. 107 | local w to x * ism. 108 | local vcvec to smu * (v + w) * uniC. 109 | local vr to smu * (v - w). 110 | 111 | return lexicon("v0", vcvec + vr * unir0, "v1", vcvec - vr * unir1). 112 | } 113 | -------------------------------------------------------------------------------- /liborbital/dock.ks: -------------------------------------------------------------------------------- 1 | require("libvessel","vesselsize.ks"). 2 | 3 | function bnd { 4 | parameter val, minval, maxval. 5 | return min(maxval, max(minval, val)). 6 | } 7 | 8 | function tgtmove { 9 | parameter tgtport, dr, vmax. 10 | 11 | local vtgt to ship:velocity:orbit - tgtport:ship:velocity:orbit. 12 | local v0 to vmax*dr:normalized. 13 | local dv to v0-vtgt. 14 | local fc to ship:facing. 15 | local tf to bnd(vdot(dv, fc:vector),-1,1). 16 | local ts to bnd(vdot(dv, fc:starvector),-1,1). 17 | local tt to bnd(vdot(dv, fc:topvector),-1,1). 18 | set ship:control:translation to V(ts,tt,tf). 19 | } 20 | 21 | function ControlBackup { 22 | if not exists("controlrestore.ks") 23 | log "for p in ship:parts if p:uid = " + char(34) + ship:controlpart:uid + char(34) + " p:controlfrom." to "controlrestore.ks". 24 | } 25 | 26 | function dockto { 27 | parameter tgtport. 28 | 29 | print tgtport. 30 | rcs on. 31 | controlbackup(). 32 | 33 | if (not ship:dockingports:contains(ship:controlpart)) or (ship:controlpart:nodetype <> tgtport:nodetype) { 34 | for myport in ship:dockingports { 35 | if myport:nodetype = tgtport:nodetype { 36 | myport:controlfrom. 37 | break. 38 | } 39 | } 40 | } 41 | 42 | local eln to ship:elements:length. 43 | local safedst to vesselsize(tgtport:ship)+vesselsize(ship). 44 | local safedst0 to safedst. 45 | print "Safety bubble radius: " + round(safedst). 46 | 47 | local lock vtgt to ship:velocity:orbit - tgtport:ship:velocity:orbit. 48 | 49 | local f0 to ship:facing. 50 | lock steering to f0. 51 | 52 | local lock tgtpos to tgtport:nodeposition:normalized*(safedst+1). 53 | local lock dr to tgtport:nodeposition - ship:controlpart:position - tgtpos. 54 | until tgtport:nodeposition:mag > safedst { 55 | tgtmove(tgtport, dr, 3). 56 | wait 0. 57 | } 58 | set ship:control:translation to V(0,0,0). 59 | unlock steering. wait 0.2. 60 | 61 | lock steering to lookdirup(-tgtport:facing:vector, tgtport:facing:upvector). 62 | until vtgt:sqrmagnitude < 0.04 { 63 | local fc to ship:facing. 64 | set ship:control:fore to bnd(vdot(-vtgt, fc:vector),-1,1). 65 | set ship:control:starboard to bnd(vdot(-vtgt, fc:starvector),-1,1). 66 | set ship:control:top to bnd(vdot(-vtgt, fc:topvector),-1,1). 67 | print ship:control:translation + " " at (0,10). 68 | wait 0. 69 | } 70 | set ship:control:translation to V(0,0,0). 71 | 72 | local lock tgtpos to (vxcl(tgtport:facing:vector,tgtport:nodeposition):normalized-tgtport:facing:vector)*safedst. 73 | local lock vsafe to min(5,max(0.15,(tgtport:nodeposition - ship:controlpart:position):mag/safedst0)). 74 | if vdot(tgtport:nodeposition, facing:vector) < safedst - 1 { 75 | until dr:sqrmagnitude < 1 { 76 | tgtmove(tgtport,dr,vsafe). 77 | print "Safe docking speed: " + round(vsafe,2) at (0,20). 78 | wait 0. 79 | } 80 | } 81 | 82 | local lock tgtpos to -safedst*tgtport:facing:vector. 83 | print "Getting in front of target port". 84 | until dr:mag < vsafe { 85 | tgtmove(tgtport,dr,vsafe). 86 | wait 0. 87 | } 88 | 89 | unlock tgtpos. 90 | print "Performing final docking approach". 91 | until (tgtport:nodeposition - ship:controlpart:position):mag < tgtport:acquirerange*1.25 or ship:elements:length > eln { 92 | set safedst to safedst*0.75. 93 | set tgtpos to -safedst*tgtport:facing:vector. 94 | until dr:mag < tgtport:acquirerange*0.5 { 95 | set tgtpos to -safedst*tgtport:facing:vector. 96 | tgtmove(tgtport,dr,max(vsafe,0.1)). 97 | wait 0. 98 | } 99 | } 100 | 101 | set ship:control:translation to V(0,0,0). 102 | rcs off. 103 | unlock steering. 104 | wait 0. 105 | runpath("controlrestore.ks"). 106 | wait until ship:elements:length > eln. 107 | wait 0.2. 108 | } 109 | -------------------------------------------------------------------------------- /libmath/brent.ks: -------------------------------------------------------------------------------- 1 | @lazyglobal off. 2 | // Brent's algorithm for finding zeros of functions 3 | // Coded after Press W.H. et al., Numerical Recipes, 3rd ed. 4 | 5 | function solv_brent { 6 | parameter fn, x0, x1, rtol to 0.0, verbose to False. 7 | 8 | local MAXITER to 150. 9 | set rtol to max(rtol, 2^(-53)). 10 | 11 | local xpre to x0. // previous best approx 12 | local xcur to x1. // current best approx 13 | local xopp to xcur. // x with opposite sign to xcur 14 | local fpre to fn(x0). // correspondng function values 15 | local fcur to fn(x1). 16 | local fopp to fcur. 17 | local dxpre to 0. // increment on previous iteration 18 | local dxcur to 0. // increment on current iteration 19 | local dxtry to 0. // trial increment 20 | local dxbin to 0. // would-be increment for binary search 21 | local dxmax to 1. 22 | local delta to rtol. // tolerable absolute uncertainty 23 | local rco to 1. // ratio fcur / fopp 24 | local rcp to 1. // ratio fcur / fpre 25 | local rpo to 1. // ratio fpre / fopp 26 | local interptype to "". // interpolation type (verbose only) 27 | 28 | local function rearrange { 29 | set xopp to xpre. 30 | set fopp to fpre. 31 | set dxpre to xcur - xpre. 32 | set dxcur to dxpre. 33 | } 34 | 35 | local function change_best_approximant { 36 | set fpre to fcur. 37 | set fcur to fopp. 38 | set fopp to fpre. 39 | 40 | set xpre to xcur. 41 | set xcur to xopp. 42 | set xopp to xpre. 43 | } 44 | 45 | local function interpolate { 46 | set rcp to fcur / fpre. 47 | if (xpre = xopp) {lininterp().} 48 | else {iquadinterp().} 49 | } 50 | 51 | local function lininterp { 52 | set interptype to " secant ". 53 | set dxtry to 2 * dxbin * rcp / (rcp - 1). 54 | } 55 | 56 | local function iquadinterp { 57 | set interptype to " inverse quadratic ". 58 | set rpo to fpre / fopp. 59 | set rco to fcur / fopp. 60 | local dxnum to rcp * (2 * dxbin * rpo * (rpo - rco) - (xcur - xpre) * (rco - 1)). 61 | local dxden to (rpo - 1) * (rco - 1) * (rcp - 1). 62 | set dxtry to -dxnum / dxden. 63 | } 64 | 65 | local function acceptinterp { 66 | if verbose {print "Using" + interptype + "interpolation".} 67 | set dxpre to dxcur. 68 | set dxcur to dxtry. 69 | } 70 | 71 | local function usebisect { 72 | if verbose {print "Using bisection".} 73 | set dxcur to dxbin. 74 | set dxpre to dxbin. 75 | } 76 | 77 | local iter to 1. 78 | 79 | if fpre * fcur > 0 { 80 | print "ERROR in SOLV_BRENT: root not bracketed between endpoints". 81 | return 1 / 0. 82 | } 83 | 84 | if fpre = 0 {return xpre.} 85 | if fcur = 0 {return xcur.} 86 | 87 | until iter > MAXITER { 88 | if verbose {print "Iteration #" + iter.} 89 | set iter to iter + 1. 90 | 91 | if (fopp * fcur > 0) { rearrange(). } 92 | 93 | if abs(fopp) < abs(fcur) { change_best_approximant(). } 94 | 95 | set delta to rtol * (1 + abs(xcur)) * 0.5. 96 | set dxbin to (xopp - xcur) / 2. 97 | set dxmax to min(3 * abs(dxbin) - delta, abs(dxpre)). 98 | 99 | if verbose {print "x = " + xcur +"; est_err = " + 2 * abs(dxbin).} 100 | if ((fcur = 0) or (abs(dxbin) < delta)) { 101 | if verbose {print "SOLV_BRENT converged in " + iter + " iterations".} 102 | return xcur.} 103 | 104 | if ((abs(dxpre) >= delta) and (abs(fcur) < abs(fpre))) { 105 | interpolate(). 106 | if (2 * abs(dxtry) < dxmax) and (dxtry * dxbin > 0) { 107 | acceptinterp(). 108 | } 109 | else { 110 | usebisect(). 111 | } 112 | } 113 | else { 114 | usebisect(). 115 | } 116 | 117 | set xpre to xcur. 118 | set fpre to fcur. 119 | 120 | if abs(dxcur) < delta { 121 | if dxcur < 0 {set dxcur to -delta.} 122 | else {set dxcur to delta.} 123 | } 124 | set xcur to xcur + dxcur. 125 | set fcur to fn(xcur). 126 | } 127 | 128 | print "WARNING: SOLV_BRENT exceeded maximum number of iterations.". 129 | return xcur. 130 | } 131 | -------------------------------------------------------------------------------- /Kommsat-incl/launch2.ks: -------------------------------------------------------------------------------- 1 | require("liborbital","exenode"). 2 | 3 | function VertAscent { 4 | lock steering to heading(90,90). 5 | } 6 | 7 | function CapTWR { 8 | parameter maxTWR is 3.0. 9 | local g0 to Kerbin:mu/Kerbin:radius^2. 10 | lock throttle to min(1, ship:mass*g0*maxTWR / max(ship:availablethrust, 0.001) ). 11 | } 12 | 13 | function printtlm { 14 | local pitch to 90 - vang( up:vector, velocity:surface ). 15 | print "Apoapsis: " + round(apoapsis/1000, 2) + " km " at (0,30). 16 | print "Periapsis: " + round(periapsis/1000, 2) + " km " at (0,31). 17 | print " Altitude: " + round(altitude/1000, 2) + " km " at (24,30). 18 | print " Pitch: " + round( pitch ) + " deg " at (24,31). 19 | } 20 | 21 | function GravityTurn { 22 | parameter vstart. 23 | parameter AP45 is apoapsis. 24 | parameter APstop is 60000. 25 | parameter v45 is 500. 26 | 27 | local vsm to velocity:surface:mag. 28 | local pitch to 0. 29 | if ( vsm < v45 ) { 30 | set pitch to 90 - arctan( (vsm - vstart)/(v45 - vstart) ). 31 | } 32 | else { 33 | set pitch to max(0, 45*(apoapsis - APstop) / (AP45 - APstop) ). 34 | } 35 | lock steering to heading( 90, pitch ). 36 | printtlm(). 37 | } 38 | 39 | function startnextstage { 40 | until ship:availablethrust > 0 { 41 | if altitude apw { lock throttle to 0. } 51 | else { lock throttle to max( 0.05, Kp*(apw - apoapsis)/apw ). } 52 | printtlm(). 53 | } 54 | 55 | function gettoorbit { 56 | parameter Horb to body:atm:height + 10000. 57 | parameter GTstart to 800. 58 | parameter GTendAP to 55000. 59 | 60 | local maxTWR to 3.0. 61 | lock throttle to 1. 62 | local initialpos to ship:facing. 63 | lock steering to initialpos. 64 | startnextstage(). 65 | 66 | until alt:radar > GTstart { 67 | VertAscent(). 68 | startnextstage(). 69 | CapTWR(maxTWR). 70 | wait 0.01. 71 | } 72 | 73 | local GTStartSpd to velocity:surface:mag. 74 | local Apo45 to apoapsis. 75 | local lock pitch to 90 - vang( up:vector, velocity:surface ). 76 | 77 | until apoapsis >= Horb { 78 | if pitch >= 45 { set Apo45 to apoapsis. } 79 | GravityTurn(GTStartSpd,Apo45,GTendAP). 80 | startnextstage(). 81 | CapTWR(maxTWR). 82 | wait 0.01. 83 | } 84 | 85 | lock throttle to 0. 86 | 87 | lock steering to prograde. 88 | until altitude > body:atm:height { 89 | APkeep(Horb). 90 | wait 0.01. 91 | } 92 | lock throttle to 0. 93 | print "We are in space. Deploying payload fairing. ". 94 | wait 5. 95 | stage. 96 | 97 | local a0 to orbit:semimajoraxis. 98 | local Ra to body:radius + apoapsis. 99 | local Va to sqrt( body:mu * (2/Ra - 1/a0) ). 100 | local Vc is sqrt(body:mu/Ra). 101 | list engines in el. 102 | local ispeff to 0. 103 | local ff to 0. 104 | local tt to 0. 105 | for e in el { 106 | set ff to ff + e:availablethrust/max(e:isp,0.01)/9.80665. 107 | set tt to tt + e:availablethrust. 108 | } 109 | set ispeff to tt/ff. 110 | local dv to ispeff*ln(mass/(mass-stage:liquidfuel/90))-5. 111 | local cphi to (Vc^2+Va^2-dv^2)/(2*Vc*Va). 112 | local slp to sin(orbit:argumentofperiapsis)*sin(orbit:inclination). 113 | local cae to cos(orbit:inclination)/sqrt(1-slp^2). 114 | set cphi to max(cphi,cae). 115 | local nd to node(time:seconds + eta:apoapsis, 0, Vc*sqrt(1-cphi^2), Vc*cphi-Va). 116 | add nd. 117 | exenode(). 118 | 119 | print "We are in orbit: " + round(apoapsis/1000,2) + "x" + round(periapsis/1000,2) + " km. ". 120 | wait 5. 121 | 122 | print "Deploying omni antennae.". 123 | set alist to ship:partsnamed("longAntenna"). 124 | for an in alist { 125 | set d to an:getmodule("ModuleRTAntenna"). 126 | d:doevent("activate"). 127 | } 128 | 129 | print "Releasing payload.". 130 | lock steering to prograde. 131 | wait 5. 132 | stage. 133 | } 134 | gettoorbit(80000,100). 135 | -------------------------------------------------------------------------------- /Moona/2/sat.ks: -------------------------------------------------------------------------------- 1 | require("libwarp","warpfor.ks"). 2 | 3 | function runfiles { 4 | parameter fl. 5 | for f in fl if exists(f) runpath(f). 6 | } 7 | 8 | function AlignToSun { 9 | lock steering to lookdirup(north:vector,Sun:position). 10 | } 11 | 12 | function nextmode { 13 | parameter newmode is satmode+1. 14 | set satmode to newmode. 15 | log "set satmode to " + newmode + "." to "mode.ks". 16 | AlignToSun(). 17 | } 18 | 19 | function frt { 20 | local tnode to time:seconds + 600. 21 | local nd to node(tnode,0,0,0). 22 | add nd. 23 | local lock returnpatch to nd:orbit:nextpatch:nextpatch. 24 | until returnpatch:periapsis > 15000 and returnpatch:periapsis < 35000 { 25 | until returnpatch:periapsis > 15000 set nd:prograde to nd:prograde - 0.02. 26 | until returnpatch:periapsis < 35000 set nd:prograde to nd:prograde + 0.02. 27 | } 28 | print "Free return trajectory computed". 29 | } 30 | 31 | function satprogram { 32 | runfiles(list("exenode.ks","warpfor.ks","warpheight.ks")). 33 | if satmode = 0 { 34 | local rh to alt:radar. 35 | local Hb to 75000. 36 | require("Moona/2","wait.ks"). 37 | waitwindow(Hb). 38 | deletepath("wait.ks"). 39 | require("Moona/2","launch.ks"). 40 | gettoorbit(Hb,650,rh*2). 41 | startnextstage(). 42 | deletepath("launch.ks"). 43 | deletepath("warpheight.ks"). 44 | panels on. 45 | wait 20. 46 | nextmode(). 47 | } 48 | if satmode = 1 { 49 | require("Moona/2","mode1.ks"). 50 | nextmode(). 51 | } 52 | if satmode = 2 { 53 | deletepath("mode1.ks"). 54 | require("liborbital","exenode.ks"). 55 | exenode(). 56 | nextmode(). 57 | } 58 | if satmode = 3 { 59 | frt(). 60 | nextmode(). 61 | } 62 | if satmode = 4 { 63 | exenode(). 64 | deletepath("exenode.ks"). 65 | require("libwarp","warpheight.ks"). 66 | nextmode(). 67 | } 68 | if satmode = 5 { 69 | if body:name = "Kerbin" warpfor(eta:transition). 70 | nextmode(). 71 | } 72 | if satmode = 6 { 73 | wait until body:name = "Mun". 74 | wait 5. 75 | for part in ship:parts { 76 | for m in part:modules { 77 | if m="ModuleScienceExperiment" or m="dmmodulescienceanimate" { 78 | for e in part:getmodule(m):allactionnames { 79 | if e:contains("Log") part:getmodule(m):doaction(e,True). 80 | } 81 | } 82 | } 83 | } 84 | wait 30. 85 | nextmode(). 86 | } 87 | if satmode = 7 { 88 | if body:name = "Mun" warpfor(eta:transition). 89 | wait until body:name = "Kerbin". 90 | nextmode(). 91 | } 92 | if satmode = 8 { 93 | if periapsis > 30000 { 94 | lock steering to retrograde. 95 | wait until vang(facing:vector,-velocity:orbit) < 1. 96 | lock throttle to 1. 97 | wait until periapsis < 30000. 98 | lock throttle to 0. 99 | } 100 | nextmode(). 101 | } 102 | if satmode = 9 { 103 | wait 5. 104 | warpheight(2*body:atm:height). 105 | nextmode(). 106 | } 107 | if satmode = 10 { 108 | for part in ship:parts { 109 | for m in part:modules { 110 | if m="ModuleScienceExperiment" or m="dmmodulescienceanimate" { 111 | for e in part:getmodule(m):alleventnames { 112 | if e:contains("Toggle Magnetometer") part:getmodule(m):doevent(e). 113 | } 114 | } 115 | } 116 | } 117 | wait 5. 118 | stage. 119 | ship:partsnamed("longAntenna")[0]:getmodule("ModuleRTAntenna"):doevent("deactivate"). 120 | ship:partsnamed("ServiceBay.125")[0]:getmodule("ModuleAnimateGeneric"):doevent("Close"). 121 | nextmode(). 122 | } 123 | if satmode = 11 { 124 | lock steering to srfretrograde. 125 | warpheight(periapsis + 500). 126 | set warp to 3. 127 | wait until alt:radar < 5000 and velocity:surface:mag < 250. 128 | set warp to 0. 129 | wait 1. 130 | stage. 131 | wait 1. 132 | chutes on. 133 | unlock steering. 134 | wait until status="landed" or status="splashed". 135 | return 0. 136 | } 137 | until false AlignToSun(). 138 | } 139 | 140 | local satmode to 0. 141 | if exists("mode.ks") { runpath("mode.ks"). } 142 | else nextmode(0). 143 | satprogram(). 144 | -------------------------------------------------------------------------------- /L3project/launch.ks: -------------------------------------------------------------------------------- 1 | require("liborbital","circularize.ks"). 2 | require("liborbital","aponode.ks"). 3 | require("liborbital","exenode.ks"). 4 | 5 | function printtlm { 6 | local pitch to 90 - vang( up:vector, velocity:surface ). 7 | print "Apoapsis: " + round( apoapsis/1000, 2 ) + " km " at (0,30). 8 | print "Periapsis: " + round( periapsis/1000, 2 ) + " km " at (0,31). 9 | print " Altitude: " + round( altitude/1000, 2 ) + " km " at (24,30). 10 | print " Pitch: " + round( pitch ) + " deg " at (24,31). 11 | } 12 | 13 | function PitchCtrl { 14 | parameter vstart, h0, v45, AP45, APstop. 15 | parameter aoalim to 2.5. 16 | parameter aoalh to 15000. 17 | 18 | if alt:radar < h0 {return 90.} 19 | 20 | local vsm to velocity:surface:mag. 21 | local pitch to 0. 22 | 23 | if vsm < v45 { 24 | set pitch to 90 - arctan( (vsm - vstart)/(v45 - vstart) ). 25 | } 26 | else { 27 | set pitch to max(0, 45*(apoapsis - APstop) / (AP45 - APstop) ). 28 | } 29 | 30 | local vpitch to 90-vang(up:vector, velocity:surface). 31 | if altitude > aoalh set aoalim to aoalim*constant:e^(2*(altitude/aoalh-1)). 32 | if pitch > vpitch + aoalim {set pitch to vpitch + aoalim.} 33 | if pitch < vpitch - aoalim {set pitch to vpitch - aoalim.} 34 | 35 | return pitch. 36 | } 37 | 38 | function startnextstage { 39 | local allengactive to 40 | { 41 | list engines in el. 42 | for e in el 43 | if e:flameout return False. 44 | return True. 45 | }. 46 | until ship:availablethrust > 0 and allengactive() { 47 | list engines in el. 48 | for e in el if e:ignition set e:thrustlimit to 100. 49 | if altitude 4 lock steering to srfprograde. 50 | if altitude>body:atm:height lock steering to lookdirup(velocity:orbit, -body:position). 51 | wait 0.5. 52 | stage. 53 | if ship:availablethrust > 0 wait 0.5. 54 | } 55 | } 56 | 57 | function APkeep { 58 | parameter apw. 59 | local Kp to 200. 60 | if apoapsis > apw { lock throttle to 0. } 61 | else { lock throttle to max( 0.05, Kp*(apw - apoapsis)/apw ). } 62 | printtlm(). 63 | } 64 | 65 | function gettoorbit { 66 | parameter Horb. 67 | parameter GTstart to 50. 68 | parameter GTv1 to 550. 69 | parameter GTendAP to 60000. 70 | 71 | lock throttle to 1. 72 | lock steering to heading(90,90). 73 | stage. 74 | 75 | local vsm to velocity:surface:mag. 76 | local GTStartSpd to vsm. 77 | local Apo2 to apoapsis. 78 | local tlesjett to time:seconds. 79 | local lesjett to False. 80 | local pitch to 90. 81 | 82 | until apoapsis >= Horb { 83 | if stage:number = 10 and not lesjett { set tlesjett to time:seconds + 3. set lesjett to True. } 84 | if not lesjett { set tlesjett to time:seconds + 1. } 85 | if time:seconds > tlesjett { toggle AG1. } 86 | set vsm to velocity:surface:mag. 87 | if stage:number > 10 { 88 | set pitch to PitchCtrl(GTStartSpd,GTstart,GTv1,Apo2,GTendAP). 89 | } 90 | else { 91 | set pitch to 0.4*(90 - vang(velocity:orbit, -body:position)). 92 | local fpitch to 90 - vang(facing:vector, -body:position). 93 | if pitch > fpitch + 1.5 {set pitch to fpitch + 1.5.} 94 | if pitch < fpitch - 1.5 {set pitch to fpitch - 1.5.} 95 | } 96 | if alt:radar <= GTstart { set GTStartSpd to vsm. } 97 | if vsm < GTv1 { set Apo2 to apoapsis. } 98 | 99 | local tisp to thrustisp(). 100 | if stage:number < 11 or (stage:liquidfuel + stage:oxidizer)*0.005*tisp[1]/max(1, tisp[0]) > 5 { 101 | lock steering to heading(90, pitch). 102 | } 103 | else { lock steering to srfprograde. } 104 | print "Pitch (prog): " + round(pitch) at (0,32). 105 | printtlm(). 106 | startnextstage(). 107 | wait 0. 108 | } 109 | 110 | lock throttle to 0. 111 | 112 | lock steering to prograde. 113 | set warp to 3. 114 | until altitude > body:atm:height { 115 | APkeep(Horb). 116 | startnextstage(). 117 | wait 0. 118 | } 119 | lock throttle to 0. 120 | set warp to 0. 121 | print "We are in space. Deploying fairing. ". 122 | wait 2. 123 | stage. 124 | wait 1. 125 | stage. 126 | wait 1. 127 | 128 | aponode(). 129 | exenode(). 130 | circularize(). 131 | wait 3. 132 | panels on. 133 | } 134 | -------------------------------------------------------------------------------- /KOT/D/dockprogram.ks: -------------------------------------------------------------------------------- 1 | require("liborbital","circularize.ks"). 2 | 3 | function runfiles { 4 | parameter fl. 5 | for f in fl if exists(f) runpath(f). 6 | } 7 | 8 | function AlignToSun { 9 | lock steering to lookdirup(V(0,1,0),Sun:position)+R(0,0,-90). 10 | } 11 | 12 | function nextmode { 13 | parameter newmode is satmode+1. 14 | set satmode to newmode. 15 | log "set satmode to " + newmode + "." to "mode.ks". 16 | AlignToSun(). 17 | } 18 | 19 | function OrbAngTo { 20 | parameter pos. 21 | local nvec to vcrs( body:position, velocity:orbit ):normalized. 22 | local proj to vxcl(nvec, pos - body:position). 23 | local angl to arctan2( vdot(nvec, vcrs(body:position, proj)), -vdot(body:position, proj) ). 24 | if angl < 0 set angl to 360 + angl. 25 | 26 | return angl. 27 | } 28 | 29 | function transferto { 30 | parameter tgt. 31 | parameter phitotgt is 0. 32 | 33 | local newsma to tgt:orbit:semimajoraxis. 34 | local r0 to orbit:semimajoraxis. 35 | local v0 to velocity:orbit:mag. 36 | 37 | local a1 to (newsma + r0)/2. 38 | local Vpe to sqrt( body:mu*(2/r0 - 1/a1) ). 39 | local deltav to Vpe - v0. 40 | 41 | local t12 to constant:pi*(a1^3/body:mu)^0.5. 42 | local tomega to 360/tgt:orbit:period. 43 | local phitrans to phitotgt - tomega*t12 + 180. 44 | until phitrans>=0 set phitrans to phitrans + 360. 45 | 46 | local phinow to orbangto(tgt:position). 47 | 48 | local omegaeff to 360/orbit:period - tomega. 49 | local etatrans to (phinow - phitrans) / omegaeff. 50 | if etatrans < (deltav*mass/ship:availablethrust + 5) { set etatrans to etatrans + 360/abs(omegaeff). } 51 | 52 | print "Current phase angle: " + round(phinow) + "; ". 53 | print "Needed phase angle: " + round(phitrans) + "; ". 54 | print "Transfer burn: " + round(v0) + " -> " + round(Vpe) + "m/s". 55 | set nd to node(time:seconds + etatrans, 0, 0, deltav). 56 | add nd. 57 | } 58 | 59 | function satprogram { 60 | runfiles(list("exenode.ks","aponode.ks")). 61 | 62 | local ti to 0. 63 | local tlan to 0. 64 | if hastarget { 65 | set ti to target:orbit:inclination. 66 | set tlan to target:orbit:lan. 67 | } 68 | 69 | print "Starting program in mode " + satmode. 70 | if satmode = 0 { 71 | require("KOT/D","launch-inclan.ks"). 72 | local Hsat to 75000. 73 | LVprogram(Hsat,ti,tlan,2*alt:radar,57500,575). 74 | deletepath("launch-inclan.ks"). 75 | nextmode(). 76 | } 77 | if satmode = 1 { 78 | startnextstage(). 79 | wait 1. 80 | circularize(). 81 | nextmode(). 82 | } 83 | if satmode = 2 { 84 | clearscreen. 85 | print "Desired inclination: " + round(ti,2) at (0,1). 86 | print "Reached inclination: " + round(orbit:inclination,2) at (0,2). 87 | print "Desired LAN: " + round(tlan,2) at (30,1). 88 | print "Reached LAN: " + round(orbit:lan,2) at (30,2). 89 | nextmode(). 90 | } 91 | if satmode = 3 { 92 | AlignToSun(). 93 | wait until hastarget. 94 | transferto(target). 95 | nextmode(). 96 | } 97 | if satmode = 4 { 98 | exenode(). 99 | nextmode(). 100 | } 101 | if satmode = 5 { 102 | aponode(). 103 | nextmode(). 104 | } 105 | if satmode = 6 { 106 | exenode(). 107 | nextmode(). 108 | } 109 | if satmode = 7 { 110 | if ship:elements:length = 1 { 111 | require("liborbital","dock.ks"). 112 | dockto(vessel("DockTarget"):partsnamed("dockingPort3")[0]). 113 | } 114 | nextmode(). 115 | } 116 | if satmode = 8 { 117 | print "Manual control on". 118 | unlock steering. 119 | unlock throttle. 120 | wait until not gear. 121 | print "Manual control off". 122 | nextmode(10). 123 | } 124 | if satmode = 9 { 125 | AlignToSun(). 126 | wait until altitude-body:atm:height < 100. 127 | kuniverse:timewarp:cancelwarp. 128 | wait until kuniverse:timewarp:issettled. 129 | wait 1. 130 | stage. 131 | wait 2. 132 | lock steering to srfretrograde. 133 | wait until altitude < 45000. 134 | unlock steering. 135 | wait until altitude < 6000 and velocity:surface:mag < 250. 136 | stage. 137 | wait until status="landed" or status="splashed". 138 | return. 139 | } 140 | print "Aligning for optimal solar panel performance". 141 | AlignToSun(). 142 | wait until false. 143 | } 144 | 145 | local satmode to 0. 146 | local LVmode to 0. 147 | if exists("mode.ks") { runpath("mode.ks"). } 148 | else nextmode(0). 149 | 150 | when satmode <> 8 and gear then { 151 | nextmode(8). 152 | reboot. 153 | } 154 | 155 | when satmode <> 9 and brakes then { 156 | nextmode(9). 157 | reboot. 158 | } 159 | 160 | satprogram(). 161 | -------------------------------------------------------------------------------- /Dockee/launch-incl.ks: -------------------------------------------------------------------------------- 1 | function CapTWR { 2 | parameter maxTWR is 3.0. 3 | local g0 to Kerbin:mu/Kerbin:radius^2. 4 | lock throttle to min(1, ship:mass*g0*maxTWR / max( ship:availablethrust, 0.001 ) ). 5 | } 6 | 7 | function pidtlm { 8 | parameter pid. 9 | print "Error: " + round(pid:error,2) at (0,16). 10 | print "PTerm: " + round(pid:pterm,2) at (0,17). 11 | print "ITerm: " + round(pid:iterm,2) at (0,18). 12 | print "DTerm: " + round(pid:dterm,2) at (0,19). 13 | print "Output: " + round(pid:output,2) at (0,20). 14 | } 15 | 16 | function printtlm { 17 | local pitch to 90 - vang( up:vector, velocity:surface ). 18 | print "Apoapsis: " + round( apoapsis/1000, 2 ) + " km " at (0,30). 19 | print "Periapsis: " + round( periapsis/1000, 2 ) + " km " at (0,31). 20 | print " Altitude: " + round( altitude/1000, 2 ) + " km " at (24,30). 21 | print " Pitch: " + round( pitch ) + " deg " at (24,31). 22 | } 23 | 24 | function PitchCtrl { 25 | parameter vstart, h0, v45, AP45, APstop. 26 | parameter aoalim to 2.5. 27 | parameter aoalh to 15000. 28 | 29 | if alt:radar < h0 {return 90.} 30 | 31 | local vsm to velocity:surface:mag. 32 | local pitch to 0. 33 | 34 | if vsm < v45 { 35 | set pitch to 90 - arctan( (vsm - vstart)/(v45 - vstart) ). 36 | } 37 | else { 38 | set pitch to max(0, 45*(apoapsis - APstop) / (AP45 - APstop) ). 39 | } 40 | 41 | local vpitch to 90-vang(up:vector, velocity:surface). 42 | if altitude > aoalh set aoalim to aoalim*constant:e^(2*(altitude/aoalh-1)). 43 | if pitch > vpitch + aoalim {set pitch to vpitch + aoalim.} 44 | if pitch < vpitch - aoalim {set pitch to vpitch - aoalim.} 45 | 46 | return pitch. 47 | } 48 | 49 | function HDGctrl { 50 | parameter ti. 51 | parameter hdgpid. 52 | parameter GTstart. 53 | 54 | if alt:radar < GTstart return 90. 55 | local vh to vxcl(up:vector,velocity:orbit). 56 | local svh to vxcl(up:vector,velocity:surface). 57 | 58 | local xi to arcsin( max(-1, min( 1, cos(ti) / cos(latitude) ) ) ). 59 | if svh:mag > 50 and vh:y < 0 { set xi to 180 - xi. } 60 | 61 | local thdg to heading( xi, 0 ). 62 | local vside to vdot(vxcl(thdg:vector,vh),thdg:rightvector). 63 | 64 | local hdg to xi + hdgpid:update(time:seconds, vside). 65 | 66 | if hdgpid:pterm*hdgpid:iterm < 0 hdgpid:reset. 67 | 68 | local track to arctan2(vdot(vcrs(north:vector,vh:normalized), up:vector), vdot(north:vector,vh:normalized) ). 69 | 70 | print "Track: " + round(track) + " " at (0,14). 71 | print "Wanted track: " + round(xi) + " " at (20,14). 72 | print "Target heading: " + round(hdg) + " " at (0,15). 73 | 74 | return hdg. 75 | } 76 | 77 | function hdgpid_init { 78 | parameter ti, Horb. 79 | 80 | local vorb to sqrt(body:mu/Horb). 81 | local vsurf to velocity:orbit:mag. 82 | 83 | local xi to arcsin( max(-1, min( 1, cos(ti) / cos(latitude) ) ) ). 84 | 85 | local azl to arcsin( (vorb*sin(xi) - vsurf) / sqrt( vsurf^2 + vorb^2 - 2*vsurf*vorb*sin(xi) ) ). 86 | 87 | print "Launch azimuth: " + round(azl). 88 | 89 | local Kp to 1/vorb. 90 | if cos(azl) <> 0 { 91 | set Kp to (xi - azl) / (vsurf*cos(xi)). 92 | } 93 | local Ki to Kp/25. 94 | return pidloop(Kp,Ki,0). 95 | } 96 | 97 | function startnextstage { 98 | until ship:availablethrust > 0 { 99 | if altitude apw { lock throttle to 0. } 109 | else { lock throttle to max( 0.05, Kp*(apw - apoapsis)/apw ). } 110 | printtlm(). 111 | } 112 | 113 | function gettoorbit { 114 | parameter Horb to body:atm:height + 10000. 115 | parameter ti to 0. 116 | parameter GTv45 to 500. 117 | parameter GTendAP to 55000. 118 | parameter GTstart to 2*alt:radar. 119 | 120 | local maxTWR to 3.0. 121 | local hdgpid to hdgpid_init(ti, Horb). 122 | set hdgpid:setpoint to 0. 123 | 124 | lock throttle to 1. 125 | local initialpos to ship:facing. 126 | lock steering to initialpos. 127 | 128 | startnextstage(). 129 | 130 | local vsm to velocity:surface:mag. 131 | local GTStartSpd to vsm. 132 | local Apo45 to apoapsis. 133 | 134 | until apoapsis >= Horb { 135 | set vsm to velocity:surface:mag. 136 | if vsm <= GTv45 { set Apo45 to apoapsis. } 137 | if alt:radar <= GTstart { set GTStartSpd to vsm. } 138 | 139 | lock steering to heading( hdgctrl(ti, hdgpid, GTstart),pitchctrl(GTStartSpd,GTstart,GTv45,Apo45,GTendAP) ). 140 | startnextstage(). 141 | CapTWR(maxTWR). 142 | 143 | printtlm(). 144 | pidtlm(hdgpid). 145 | wait 0. 146 | } 147 | 148 | lock throttle to 0. 149 | 150 | lock steering to prograde. 151 | set warp to 3. 152 | until altitude > body:atm:height { 153 | APkeep(Horb). 154 | wait 0. 155 | } 156 | set warp to 0. 157 | lock throttle to 0. 158 | print "We are in space. Deploying antenna.". 159 | wait 2. 160 | ship:partsnamed("ServiceBay.125")[0]:getmodule("ModuleAnimateGeneric"):doevent("Open"). 161 | wait 2. 162 | ship:partsnamed("longAntenna")[0]:getmodule("ModuleRTAntenna"):doevent("activate"). 163 | } 164 | -------------------------------------------------------------------------------- /Mapsat/launch-inclan.ks: -------------------------------------------------------------------------------- 1 | require("liborbital","annorm.ks"). 2 | require("liborbital","aponode.ks"). 3 | require("liborbital","exenode.ks"). 4 | 5 | function HDGctrl { 6 | parameter ti. 7 | parameter tlan. 8 | parameter hdgpid. 9 | 10 | local vh to vxcl(up:vector,velocity:orbit). 11 | local svh to vxcl(up:vector,velocity:surface). 12 | 13 | local xi to arcsin( max(-1, min( 1, cos(ti) / cos(latitude) ) ) ). 14 | if svh:mag > 50 and vh:y < 0 { set xi to 180 - xi. } 15 | 16 | local thdg to heading( xi, 0 ). 17 | 18 | local distkm to vdot(annorm(tlan,ti):upvector,body:position)/1000. 19 | 20 | local hdg to xi + hdgpid:update(time:seconds, distkm). 21 | 22 | if hdgpid:pterm*hdgpid:iterm < 0 or hdgpid:pterm*hdgpid:iterm > hdgpid:pterm^2 { 23 | hdgpid:reset. 24 | } 25 | 26 | local track to arctan2(vdot(vcrs(north:vector,vh:normalized), up:vector), vdot(north:vector,vh:normalized) ). 27 | 28 | print "Track: " + round(track) + " " at (0,14). 29 | print "Wanted track: " + round(xi) + " " at (20,14). 30 | print "Target heading: " + round(hdg) + " " at (0,15). 31 | 32 | return hdg. 33 | } 34 | 35 | function hdgpid_init { 36 | parameter leadtime. 37 | local Kd to 200. 38 | local Kp to Kd^2*4e-5. 39 | local Ki to Kp/(10*leadtime). 40 | return pidloop(Kp,Ki,Kd). 41 | } 42 | 43 | function pidtlm { 44 | parameter pid. 45 | print "Error: " + round(pid:error,2) + " "at (0,16). 46 | print "PTerm: " + round(pid:pterm,2) + " " at (0,17). 47 | print "ITerm: " + round(pid:iterm,2) + " " at (0,18). 48 | print "DTerm: " + round(pid:dterm,2) + " " at (0,19). 49 | print "Output: " + round(pid:output,2) + " " at (0,20). 50 | } 51 | 52 | function printtlm { 53 | local pitch to 90 - vang( up:vector, velocity:surface ). 54 | print "Apoapsis: " + round( apoapsis/1000, 2 ) + " km " at (0,30). 55 | print "Periapsis: " + round( periapsis/1000, 2 ) + " km " at (0,31). 56 | print " Altitude: " + round( altitude/1000, 2 ) + " km " at (24,30). 57 | print " Pitch: " + round( pitch ) + " deg " at (24,31). 58 | print "Latitude: " + round(latitude) + " " at (24,6). 59 | print "Inclination: " + round(orbit:inclination, 2) + " " at (0,6). 60 | print "LAN: " + round(orbit:lan, 2) + " " at (0,7). 61 | } 62 | 63 | function PitchCtrl { 64 | parameter vstart. 65 | parameter h0. 66 | parameter AP45 is apoapsis. 67 | parameter APstop is 60000. 68 | parameter v45 is 500. 69 | 70 | if alt:radar < h0 {return 90.} 71 | 72 | local vsm to velocity:surface:mag. 73 | local pitch to 0. 74 | if ( vsm < v45 ) { 75 | set pitch to 90 - arctan( (vsm - vstart)/(v45 - vstart) ). 76 | } 77 | else { 78 | set pitch to max(0, 45*(apoapsis - APstop) / (AP45 - APstop) ). 79 | } 80 | 81 | return pitch. 82 | } 83 | 84 | function CapTWR { 85 | parameter maxTWR is 3.0. 86 | local g0 to 9.80665. 87 | lock throttle to min(1, ship:mass*g0*maxTWR / max( ship:availablethrust, 0.001 ) ). 88 | } 89 | 90 | function startnextstage { 91 | until ship:availablethrust > 0 { 92 | if altitude apw { lock throttle to 0. } 102 | else { lock throttle to max( 0.05, Kp*(apw - apoapsis)/apw ). } 103 | printtlm(). 104 | } 105 | 106 | function nextLVmode { 107 | parameter newmode is LVmode+1. 108 | set LVmode to newmode. 109 | log "set LVmode to " + newmode + "." to "mode.ks". 110 | } 111 | 112 | function waitwindow { 113 | parameter ti, tlan, leadtime. 114 | local xi to arcsin( max(-1, min( 1, cos(ti) / cos(latitude) ) ) ). 115 | local Vvirt to heading(xi, 0):vector. 116 | local nvirt to vcrs(body:position, Vvirt). 117 | local ANvirt to vcrs(nvirt, V(0,1,0)). 118 | 119 | local LANvirt to arctan2( vdot( V(0,1,0), vcrs(ANvirt, solarprimevector) ), vdot(ANvirt, solarprimevector) ). 120 | local landiff to tlan - LANvirt. 121 | until landiff > 0 { set landiff to landiff + 360. }. 122 | 123 | warpfor(landiff/360 * body:rotationperiod - leadtime). 124 | } 125 | 126 | function LVprogram { 127 | parameter Horb to body:atm:height + 10000. 128 | parameter ti to 0. 129 | parameter tlan to 0. 130 | parameter GTstart to 800. 131 | parameter GTendAP to 55000. 132 | parameter GTv45 to 500. 133 | 134 | local maxTWR to 3.0. 135 | local lt to 75. 136 | 137 | if LVmode = 0 { 138 | waitwindow(ti,tlan,lt). 139 | nextlvmode(). 140 | } 141 | 142 | local hdgpid to hdgpid_init(lt). 143 | set hdgpid:setpoint to 0. 144 | 145 | if LVmode = 1 { 146 | lock throttle to 1. 147 | local initialpos to ship:facing. 148 | lock steering to initialpos. 149 | startnextstage(). 150 | wait 0. 151 | nextlvmode(). 152 | } 153 | if LVmode = 2 { 154 | local vsm to velocity:surface:mag. 155 | local GTStartSpd to vsm. 156 | local Apo45 to apoapsis. 157 | 158 | until apoapsis >= Horb { 159 | set vsm to velocity:surface:mag. 160 | if vsm <= GTv45 { set Apo45 to apoapsis. } 161 | if alt:radar <= GTstart { set GTStartSpd to vsm. } 162 | 163 | lock steering to heading( hdgctrl(ti, tlan, hdgpid),pitchctrl(GTStartSpd,GTstart,Apo45,GTendAP,GTv45) ). 164 | startnextstage(). 165 | CapTWR(maxTWR). 166 | 167 | printtlm(). 168 | pidtlm(hdgpid). 169 | wait 0. 170 | } 171 | nextlvmode(). 172 | } 173 | if lvmode = 3 { 174 | lock throttle to 0. 175 | lock steering to prograde. 176 | 177 | until altitude > body:atm:height { 178 | APkeep(Horb). 179 | wait 0. 180 | } 181 | nextlvmode(). 182 | } 183 | if lvmode = 4 { 184 | lock throttle to 0. 185 | clearscreen. 186 | print "We are in space. Deploying payload fairing. ". 187 | wait 5. 188 | stage. 189 | nextlvmode(). 190 | } 191 | if lvmode = 5 { 192 | print "Deploying antenna.". 193 | wait 3. 194 | set an to ship:partsnamed("longAntenna")[0]. 195 | an:getmodule("ModuleRTAntenna"):doevent("activate"). 196 | nextlvmode(). 197 | } 198 | if lvmode = 6 { 199 | aponode(20000). 200 | nextlvmode(). 201 | } 202 | if lvmode = 7 { 203 | exenode(). 204 | nextlvmode(). 205 | } 206 | if lvmode = 8 { 207 | print "Releasing payload.". 208 | lock steering to prograde. 209 | wait 5. 210 | stage. 211 | } 212 | } 213 | -------------------------------------------------------------------------------- /L3project/lander/program.ks: -------------------------------------------------------------------------------- 1 | require("liborbital","exenode.ks"). 2 | 3 | function AlignToSun { 4 | if status = "landed" lock steering to lookdirup(-body:position, facing:upvector). 5 | else lock steering to lookdirup(Sun:position, -body:position). 6 | } 7 | 8 | function runfiles { 9 | parameter fl. 10 | for f in fl if exists(f) runpath(f). 11 | } 12 | 13 | function nextmode { 14 | parameter newmode is mode+1. 15 | set mode to newmode. 16 | deletepath("mode.ks"). 17 | log "set mode to " + newmode + "." to "mode.ks". 18 | if mode > 4 and mode < 19 and ship:elements:length = 1 aligntosun(). 19 | } 20 | 21 | function OrbAngTo { 22 | parameter pos. 23 | local nvec to vcrs( body:position, velocity:orbit ):normalized. 24 | local proj to vxcl(nvec, pos - body:position). 25 | local angl to arctan2( vdot(nvec, vcrs(body:position, proj)), -vdot(body:position, proj) ). 26 | if angl < 0 set angl to 360 + angl. 27 | 28 | return angl. 29 | } 30 | 31 | function transferto { 32 | parameter tgt. 33 | parameter phitotgt is 0. 34 | 35 | local newsma to tgt:orbit:semimajoraxis. 36 | local r0 to orbit:semimajoraxis. 37 | local v0 to velocity:orbit:mag. 38 | 39 | local a1 to (newsma + r0)/2. 40 | local Vpe to sqrt( body:mu*(2/r0 - 1/a1) ). 41 | local deltav to Vpe - v0. 42 | 43 | local t12 to constant:pi*(a1^3/body:mu)^0.5. 44 | local tomega to 360/tgt:orbit:period. 45 | local phitrans to phitotgt - tomega*t12 + 180. 46 | until phitrans>=0 set phitrans to phitrans + 360. 47 | 48 | local phinow to orbangto(tgt:position). 49 | 50 | local omegaeff to 360/orbit:period - tomega. 51 | local etatrans to (phinow - phitrans) / omegaeff. 52 | if etatrans < (deltav*mass/ship:availablethrust + 5) { set etatrans to etatrans + 360/abs(omegaeff). } 53 | 54 | print "Current phase angle: " + round(phinow) + "; ". 55 | print "Needed phase angle: " + round(phitrans) + "; ". 56 | print "Transfer burn: " + round(v0) + " -> " + round(Vpe) + "m/s". 57 | set nd to node(time:seconds + etatrans, 0, 0, deltav). 58 | add nd. 59 | } 60 | 61 | function landprogram { 62 | runfiles(list("L3/lander/landing1.ks","liborbital/exenode.ks","liborbital/aponode.ks","liborbital/circularize.ks")). 63 | local dprt to ship:partstagged("landerPort")[0]. 64 | if mode = 0 { 65 | require("L3/lander","landing1.ks"). 66 | wait until not core:messages:empty. 67 | local msg to core:messages:pop(). 68 | wait 0.2. 69 | nextmode(). 70 | } 71 | if mode = 1 { 72 | dprt:getmodule("ModuleDockingNode"):doevent("decouple node"). 73 | wait 0.1. 74 | lock steering to "kill". 75 | wait 0.2. 76 | nextmode(). 77 | } 78 | if mode = 2 { 79 | wait 1. 80 | set ship:name to "MunKraft1". 81 | ship:partsnamed("RTShortAntenna1")[0]:getmodule("ModuleRTAntenna"):doevent("activate"). 82 | for res in ship:partsnamed("landerCabinSmall")[0]:resources { set res:enabled to true. } 83 | nextmode(). 84 | } 85 | local mship to vessel("7K-LOK"). 86 | if mode = 3 { 87 | lock steering to lookdirup(mship:position, Sun:position). 88 | wait until dprt:state <> "Ready". 89 | unlock steering. 90 | nextmode(). 91 | } 92 | if mode = 4 { 93 | wait until ship:elements:length = 1 and ship:crew:length = 1. 94 | nextmode(). 95 | } 96 | if mode = 5 { 97 | wait 10. 98 | list engines in el. 99 | for e in el if e:ignition set e:thrustlimit to 100*2.5*mass*body:mu/(body:radius^2*ship:maxthrust). 100 | nextmode(). 101 | } 102 | if mode = 6 { 103 | landing(latlng(2.3934, 81.703), 0.85, 8, 320). 104 | deletepath("L3/lander/landing1.ks"). 105 | nextmode(). 106 | } 107 | if mode = 7 { 108 | lock steering to lookdirup(-body:position, facing:upvector). 109 | local amdl to ship:partstagged("landerAntenna")[0]:getmodule("ModuleRTAntenna"). 110 | amdl:doevent("activate"). 111 | amdl:setfield("target", Kerbin). 112 | nextmode(). 113 | } 114 | lock steering to lookdirup(-body:position, facing:upvector). 115 | if mode = 8 { 116 | ship:partsnamed("liquidEngineMini")[0]:shutdown. 117 | set ship:partsnamed("liquidEngineMini")[0]:thrustlimit to 30. 118 | until ship:crew:length < ship:crewcapacity { 119 | hudtext("Waiting for crew EVA",1,2,18,YELLOW,True). 120 | wait 2. 121 | } 122 | nextmode(). 123 | } 124 | if mode = 9 { 125 | wait until ship:crew:length = ship:crewcapacity. 126 | nextmode(). 127 | } 128 | if mode = 10 { 129 | brakes off. 130 | wait 0.5. 131 | until brakes { 132 | hudtext("Activate Brakes group when you're ready for takeoff",1,2,18,YELLOW,True). 133 | wait 2. 134 | } 135 | nextmode(). 136 | } 137 | if mode = 11 { 138 | require("L3/lander","launch.ks"). 139 | local lngdiff to mship:longitude - ship:longitude + 4. 140 | until lngdiff > 0 { 141 | set lngdiff to 360 + lngdiff. 142 | } 143 | local omegaeff to 360/mship:orbit:period + 360/body:rotationperiod. 144 | warpfor(lngdiff / omegaeff). 145 | brakes off. 146 | gettoorbit(). 147 | nextmode(). 148 | } 149 | deletepath("L3/lander/launch.ks"). 150 | if mode = 12 { 151 | require("L3","flttraj.ks"). 152 | deletepath("L3/flttraj.ks"). 153 | nextmode(). 154 | } 155 | if mode = 13 { 156 | exenode(). 157 | nextmode(). 158 | } 159 | if mode = 14 { 160 | transferto(mship). 161 | nextmode(). 162 | } 163 | if mode = 15 { 164 | exenode(). 165 | nextmode(). 166 | } 167 | if mode = 16 { 168 | aponode(). 169 | nextmode(). 170 | } 171 | if mode = 17 { 172 | exenode(). 173 | nextmode(). 174 | } 175 | if mode = 18 { 176 | local conn to mship:connection. 177 | conn:sendmessage("Rendezvous"). 178 | nextmode(). 179 | } 180 | if mode = 19 { 181 | rcs on. 182 | lights on. 183 | lock steering to lookdirup(mship:position, Sun:position). 184 | wait until dprt:state <> "Ready". 185 | unlock steering. 186 | rcs off. 187 | nextmode(). 188 | } 189 | wait until ship:elements:length = 1 and ship:crew:empty. 190 | rcs on. 191 | set ship:control:fore to -1. 192 | wait 2. 193 | set ship:control:translation to V(0,0,0). 194 | lock steering to retrograde. 195 | wait 10. 196 | set ship:control:fore to 1. 197 | lock throttle to 1. 198 | wait until false. 199 | } 200 | 201 | local mode to 0. 202 | local lmode to 1. 203 | if exists("mode.ks") { runpath("mode.ks"). } 204 | else nextmode(0). 205 | 206 | landprogram(). 207 | -------------------------------------------------------------------------------- /L3project/capsule/flight.ks: -------------------------------------------------------------------------------- 1 | require("libwarp",""). 2 | require("liborbital","orbdir.ks"). 3 | require("liborbital","dock.ks"). 4 | 5 | function runfiles { 6 | parameter fl. 7 | for f in fl if exists(f) runpath(f). 8 | } 9 | 10 | function AlignToSun { 11 | lock steering to lookdirup(V(0,1,0), Sun:position) + R(0,0,90). 12 | } 13 | 14 | function nextmode { 15 | parameter newmode is satmode+1. 16 | set satmode to newmode. 17 | deletepath("mode.ks"). 18 | log "set satmode to " + newmode + "." to "mode.ks". 19 | AlignToSun(). 20 | } 21 | 22 | function satprogram { 23 | runfiles(list("libwarp/warpfor.ks","libwarp/warpheight.ks","liborbital/exenode.ks","liborbital/perinode.ks","liborbital/circularize.ks","liborbital/orbdir.ks","liborbital/dock.ks")). 24 | 25 | print "Starting program in mode " + satmode. 26 | local aomni to ship:partsnamed("SurfAntenna")[0]:getmodule("ModuleRTAntenna"). 27 | local adish to ship:partstagged("OMAntenna")[0]:getmodule("ModuleRTAntenna"). 28 | if satmode = 0 { 29 | local Hsat to 75000. 30 | runpath("0:/L3/wait.ks"). 31 | waitwindow(Hsat). 32 | require("L3","launch.ks"). 33 | gettoorbit(Hsat). 34 | deletepath("L3/launch.ks"). 35 | nextmode(). 36 | } 37 | aligntosun(). 38 | if satmode = 1 { 39 | require("L3","mode1.ks"). 40 | nextmode(). 41 | } 42 | if satmode = 2 { 43 | deletepath("L3/mode1.ks"). 44 | require("liborbital","exenode.ks"). 45 | exenode(). 46 | nextmode(). 47 | } 48 | if satmode = 3 { 49 | adish:doevent("activate"). 50 | adish:setfield("target", Kerbin). 51 | nextmode(). 52 | } 53 | if satmode = 4 { 54 | require("L3","flttraj.ks"). 55 | deletepath("L3/flttraj.ks"). 56 | nextmode(). 57 | } 58 | if satmode = 5 { 59 | wait min(nextnode:eta, 10). 60 | require("liborbital","perinode.ks"). 61 | exenode(). 62 | aomni:doevent("deactivate"). 63 | nextmode(). 64 | } 65 | if satmode = 6 { 66 | if body:name = "Kerbin" warpfor(eta:transition). 67 | wait until body:name = "Mun". 68 | nextmode(). 69 | } 70 | if satmode = 7 { 71 | wait 1. 72 | add node(time:seconds + 120, 0.01, 0, 0). 73 | wait 0.1. 74 | local dpedv to (nextnode:orbit:periapsis - orbit:periapsis)*100. 75 | until abs(nextnode:orbit:periapsis - 25000) < 30 { 76 | local oldpe to nextnode:orbit:periapsis. 77 | local dv to (25000 - oldPe)/dpedv. 78 | set nextnode:radialout to nextnode:radialout + dv. 79 | set dpedv to (nextnode:orbit:periapsis - oldPe)/dv. 80 | } 81 | nextmode(). 82 | } 83 | if satmode = 8 { 84 | exenode(). 85 | nextmode(). 86 | } 87 | if satmode = 9 { 88 | perinode(). 89 | nextmode(). 90 | } 91 | if satmode = 10 { 92 | if hasnode exenode(). 93 | circularize(). 94 | nextmode(). 95 | } 96 | if satmode = 11 { 97 | wait until vang(steering:vector, facing:vector) < 1 and ship:angularvel:mag < 0.1. 98 | processor("landerCPU"):connection:sendmessage("release"). 99 | wait until ship:partsnamed("landerCabinSmall"):length = 0. 100 | set ship:name to "7K-LOK". 101 | nextmode(). 102 | } 103 | if satmode = 12 { 104 | aomni:doevent("activate"). 105 | wait 2. 106 | rcs on. 107 | wait 1. 108 | set ship:control:fore to 1. 109 | wait 2. 110 | set ship:control:translation to V(0,0,0). 111 | rcs off. 112 | nextmode(). 113 | } 114 | if satmode = 13 { 115 | wait 5. 116 | dockto(vessel("MunKraft1"):partstagged("landerPort")[0]). 117 | nextmode(). 118 | } 119 | if satmode = 14 { 120 | ladders on. 121 | local lcan to ship:partsnamed("landerCabinSmall")[0]. 122 | local landerocc to false. 123 | until landerocc { 124 | hudtext("Waiting for crew transfer to lander",1,2,18,YELLOW,True). 125 | wait 2. 126 | for knaut in ship:crew if knaut:part = lcan set landerocc to true. 127 | } 128 | ladders off. 129 | wait 1. 130 | nextmode(). 131 | } 132 | if satmode = 15 { 133 | ship:dockingports[0]:undock. 134 | wait 0.5. 135 | if ship:dockingports:length > 1 { ship:dockingports[1]:undock. } 136 | wait 0.5. 137 | if ship:availablethrust = 0 { stage. } 138 | nextmode(). 139 | } 140 | if satmode = 16 { 141 | wait 1. 142 | rcs on. 143 | wait 1. 144 | set ship:control:fore to -1. 145 | wait 1. 146 | set ship:control:translation to V(0,0,0). 147 | rcs off. 148 | nextmode(). 149 | } 150 | if satmode = 17 { 151 | local mesq to ship:messages. 152 | wait until not mesq:empty. 153 | local chk to mesq:pop:content. 154 | if chk = "Rendezvous" nextmode(). 155 | } 156 | if satmode = 18 { 157 | dockto(vessel("MunKraft1"):partstagged("landerPort")[0]). 158 | nextmode(). 159 | } 160 | if satmode = 19 { 161 | ladders on. 162 | if aomni:hasevent("deactivate") aomni:doevent("deactivate"). 163 | local rpod to ship:partsnamedpattern("Soy")[0]. 164 | local rpodcrew to 0. 165 | until rpodcrew = 2 { 166 | set rpodcrew to 0. 167 | hudtext("Waiting for crew return to pod",1,2,18,YELLOW,True). 168 | for knaut in ship:crew if knaut:part = rpod set rpodcrew to rpodcrew+1. 169 | wait 2. 170 | } 171 | nextmode(). 172 | } 173 | if satmode = 20 { 174 | ladders off. 175 | ship:dockingports[0]:undock. 176 | wait 0.5. 177 | if ship:dockingports:length > 1 { ship:dockingports[1]:undock. } 178 | wait 0.5. 179 | if ship:availablethrust = 0 { stage. } 180 | nextmode(). 181 | } 182 | if satmode = 21 { 183 | brakes off. 184 | wait 0.2. 185 | until brakes { 186 | hudtext("Activate Brakes group when you're ready for return",1,2,18,YELLOW,True). 187 | wait 2. 188 | } 189 | nextmode(). 190 | } 191 | if satmode = 22 { 192 | add node(time:seconds + 60, 0, 0, 300). 193 | wait 0.1. 194 | until abs(nextnode:orbit:nextpatch:periapsis - 33000) < 3000 { 195 | set nextnode:eta to nextnode:eta + 0.5. 196 | } 197 | nextmode(). 198 | } 199 | if satmode = 23 { 200 | exenode(). 201 | brakes off. 202 | nextmode(). 203 | } 204 | if satmode = 24 { 205 | wait 10. 206 | if body:name = "Mun" warpfor(eta:transition). 207 | wait until body:name = "Kerbin". 208 | adish:doevent("deactivate"). 209 | aomni:doevent("activate"). 210 | nextmode(). 211 | } 212 | if satmode = 25 { 213 | wait 2. 214 | warpheight(body:atm:height + 10000). 215 | nextmode(). 216 | } 217 | if satmode = 26 { 218 | until ship:partstitledpattern("Onion"):length = 0 { 219 | stage. 220 | wait 0.5. 221 | } 222 | nextmode(). 223 | } 224 | if satmode = 27 { 225 | wait 1. 226 | lock steering to lookdirup(-velocity:surface,body:position). 227 | warpheight(55000). 228 | unlock steering. 229 | warpheight(periapsis + 500). 230 | set warp to 3. 231 | wait until alt:radar < 7500 and velocity:surface:mag < 250. 232 | set warp to 0. 233 | wait 1. 234 | stage. //parachutes 235 | wait until velocity:surface:mag < 20. 236 | stage. //heatshield 237 | unlock steering. 238 | wait until alt:radar < 5. 239 | stage. //soft landing motors 240 | wait until status="landed" or status="splashed". 241 | return 0. 242 | } 243 | AlignToSun(). 244 | wait until false. 245 | } 246 | 247 | local satmode to 0. 248 | if exists("mode.ks") { runpath("mode.ks"). } 249 | else nextmode(0). 250 | 251 | wait 2. 252 | 253 | satprogram(). 254 | -------------------------------------------------------------------------------- /KOT/D/launch-inclan.ks: -------------------------------------------------------------------------------- 1 | require("liborbital","annorm.ks"). 2 | require("liborbital","aponode.ks"). 3 | require("liborbital","exenode.ks"). 4 | 5 | function HDGctrl { 6 | parameter ti, tlan, GTh0. 7 | parameter hdgpid. 8 | 9 | if alt:radar < GTh0 return 90. 10 | local vh to vxcl(up:vector,velocity:orbit). 11 | local svh to vxcl(up:vector,velocity:surface). 12 | 13 | local xi to arcsin( max(-1, min( 1, cos(ti) / cos(latitude) ) ) ). 14 | local ANNRM to ANNorm(tlan,ti). 15 | if vang(body:position, ANNRM:vector) < 90 set xi to 180 - xi. 16 | 17 | local thdg to heading( xi, 0 ). 18 | 19 | local distkm to vdot(ANNRM:upvector,body:position)/1000. 20 | 21 | local hdg to xi + hdgpid:update(time:seconds, distkm). 22 | 23 | if hdgpid:pterm*hdgpid:iterm < 0 or hdgpid:pterm*hdgpid:iterm > hdgpid:pterm^2 { 24 | hdgpid:reset. 25 | } 26 | 27 | local track to arctan2(vdot(vcrs(north:vector,vh:normalized), up:vector), vdot(north:vector,vh:normalized) ). 28 | 29 | print "Track: " + round(track) + " " at (0,14). 30 | print "Wanted track: " + round(xi) + " " at (20,14). 31 | print "Target heading: " + round(hdg) + " " at (0,15). 32 | 33 | return hdg. 34 | } 35 | 36 | function hdgpid_init { 37 | parameter leadtime. 38 | local Kd to 200. 39 | local Kp to Kd^2*4e-5. 40 | local Ki to Kp/(10*leadtime). 41 | return pidloop(Kp,Ki,Kd). 42 | } 43 | 44 | function pidtlm { 45 | parameter pid. 46 | print "Error: " + round(pid:error,2) + " "at (0,16). 47 | print "PTerm: " + round(pid:pterm,2) + " " at (0,17). 48 | print "ITerm: " + round(pid:iterm,2) + " " at (0,18). 49 | print "DTerm: " + round(pid:dterm,2) + " " at (0,19). 50 | print "Output: " + round(pid:output,2) + " " at (0,20). 51 | } 52 | 53 | function printtlm { 54 | local pitch to 90 - vang( up:vector, velocity:surface ). 55 | print "Apoapsis: " + round( apoapsis/1000, 2 ) + " km " at (0,30). 56 | print "Periapsis: " + round( periapsis/1000, 2 ) + " km " at (0,31). 57 | print " Altitude: " + round( altitude/1000, 2 ) + " km " at (24,30). 58 | print " Pitch: " + round( pitch ) + " deg " at (24,31). 59 | print "Latitude: " + round(latitude) + " " at (24,6). 60 | print "Inclination: " + round(orbit:inclination, 2) + " " at (0,6). 61 | print "LAN: " + round(orbit:lan, 2) + " " at (0,7). 62 | } 63 | 64 | function PitchCtrl { 65 | parameter vstart, h0, v45, AP45, APstop. 66 | parameter aoalim to 2.5. 67 | parameter aoalh to 15000. 68 | 69 | if alt:radar < h0 {return 90.} 70 | 71 | local vsm to velocity:surface:mag. 72 | local pitch to 0. 73 | 74 | if vsm < v45 { 75 | set pitch to 90 - arctan( (vsm - vstart)/(v45 - vstart) ). 76 | } 77 | else { 78 | set pitch to max(0, 45*(apoapsis - APstop) / (AP45 - APstop) ). 79 | } 80 | 81 | local vpitch to 90-vang(up:vector, velocity:surface). 82 | if altitude > aoalh set aoalim to aoalim*constant:e^(2*(altitude/aoalh-1)). 83 | if pitch > vpitch + aoalim {set pitch to vpitch + aoalim.} 84 | if pitch < vpitch - aoalim {set pitch to vpitch - aoalim.} 85 | 86 | return pitch. 87 | } 88 | 89 | function CapTWR { 90 | parameter maxTWR is 3.0. 91 | local g0 to 9.80665. 92 | lock throttle to min(1, ship:mass*g0*maxTWR / max( ship:availablethrust, 0.001 ) ). 93 | } 94 | 95 | function startnextstage { 96 | local allengactive to 97 | { 98 | list engines in el. 99 | for e in el 100 | if e:flameout return False. 101 | return True. 102 | }. 103 | until ship:availablethrust > 0 and allengactive() { 104 | if altitude 4 lock steering to srfprograde. 105 | if altitude>body:atm:height lock steering to lookdirup(velocity:orbit, -body:position). 106 | wait 1. 107 | stage. 108 | if ship:availablethrust > 0 wait 1. 109 | } 110 | } 111 | 112 | function APkeep { 113 | parameter apw. 114 | local Kp to 200. 115 | if apoapsis > apw { lock throttle to 0. } 116 | else { lock throttle to max( 0.05, Kp*(apw - apoapsis)/apw ). } 117 | printtlm(). 118 | } 119 | 120 | function nextLVmode { 121 | parameter newmode is LVmode+1. 122 | set LVmode to newmode. 123 | log "set LVmode to " + newmode + "." to "mode.ks". 124 | } 125 | 126 | function azlan { 127 | parameter xi. 128 | 129 | local Vvirt to heading(xi, 0):vector. 130 | local nvirt to vcrs(body:position, Vvirt). 131 | local ANvirt to vcrs(nvirt, V(0,1,0)). 132 | local vlan to arctan2( vdot( V(0,1,0), vcrs(ANvirt, solarprimevector) ), vdot(ANvirt, solarprimevector) ). 133 | if vlan<0 set vlan to vlan+360. 134 | return vlan. 135 | } 136 | 137 | function waitwindow { 138 | parameter ti, tlan, leadtime. 139 | local xi to arcsin( max(-1, min( 1, cos(ti) / cos(latitude) ) ) ). 140 | 141 | local LANvirt to azlan(xi). 142 | local landiff to tlan - LANvirt. 143 | until landiff > 0 { set landiff to landiff + 360. }. 144 | 145 | local xi2 to 180-xi. 146 | local LANvirt2 to azlan(xi2). 147 | local landiff2 to tlan - LANvirt2. 148 | until landiff2 > 0 { set landiff2 to landiff2 + 360. }. 149 | 150 | print round(tlan,2). 151 | print round(LANvirt,2). 152 | print round(LANvirt2,2). 153 | 154 | local dt to min(landiff, landiff2)/360 * body:rotationperiod - leadtime. 155 | if dt > 0 warpfor(dt). 156 | else warpfor(max(landiff, landiff2)/360 * body:rotationperiod - leadtime). 157 | } 158 | 159 | function LVprogram { 160 | parameter Horb. 161 | parameter ti to 0. 162 | parameter tlan to 0. 163 | parameter GTstart to 2*alt:radar. 164 | parameter GTendAP to 50000. 165 | parameter GTv45 to 500. 166 | 167 | local maxTWR to 3.0. 168 | local lt to 75. 169 | 170 | if LVmode = 0 { 171 | waitwindow(ti,tlan,lt). 172 | nextlvmode(). 173 | } 174 | 175 | clearscreen. 176 | print "Desired inclination: " + round(ti,2). 177 | print "Desired LAN: " + round(tlan,2). 178 | 179 | local hdgpid to hdgpid_init(lt). 180 | set hdgpid:setpoint to 0. 181 | 182 | if LVmode = 1 { 183 | lock throttle to 1. 184 | local initialpos to ship:facing. 185 | lock steering to initialpos. 186 | startnextstage(). 187 | wait 0. 188 | nextlvmode(). 189 | } 190 | if LVmode = 2 { 191 | local vsm to velocity:surface:mag. 192 | local GTStartSpd to vsm. 193 | local Apo45 to apoapsis. 194 | 195 | until apoapsis >= Horb { 196 | set vsm to velocity:surface:mag. 197 | if vsm <= GTv45 { set Apo45 to apoapsis. } 198 | if alt:radar <= GTstart { set GTStartSpd to vsm. } 199 | 200 | lock steering to heading( hdgctrl(ti, tlan, GTstart, hdgpid),pitchctrl(GTStartSpd,GTstart,GTv45,Apo45,GTendAP) ). 201 | startnextstage(). 202 | CapTWR(maxTWR). 203 | 204 | printtlm(). 205 | pidtlm(hdgpid). 206 | wait 0. 207 | } 208 | nextlvmode(). 209 | } 210 | if lvmode = 3 { 211 | lock throttle to 0. 212 | lock steering to prograde. 213 | set warp to 3. 214 | 215 | until altitude > body:atm:height { 216 | APkeep(Horb). 217 | wait 0. 218 | } 219 | nextlvmode(). 220 | } 221 | if lvmode = 4 { 222 | set warp to 0. 223 | lock throttle to 0. 224 | clearscreen. 225 | print "We are in space. Ejecting nosecone. ". 226 | wait 2. 227 | stage. 228 | nextlvmode(). 229 | } 230 | if lvmode = 5 { 231 | print "Deploying antenna.". 232 | wait 2. 233 | ship:partsnamed("ServiceBay.125")[0]:getmodule("ModuleAnimateGeneric"):doevent("Open"). 234 | wait 2. 235 | ship:partsnamed("longAntenna")[0]:getmodule("ModuleRTAntenna"):doevent("activate"). 236 | nextlvmode(). 237 | } 238 | if lvmode = 6 { 239 | aponode(20000). 240 | nextlvmode(). 241 | } 242 | if lvmode = 7 { 243 | exenode(). 244 | nextlvmode(). 245 | } 246 | if lvmode = 8 { 247 | print "Releasing payload.". 248 | lock steering to prograde. 249 | wait 5. 250 | stage. 251 | } 252 | } 253 | -------------------------------------------------------------------------------- /L3project/lander/landing1.ks: -------------------------------------------------------------------------------- 1 | require("libwarp","warpfor.ks"). 2 | 3 | function GeoDist { 4 | parameter geocoord. 5 | parameter normvec to V(0,1,0). 6 | return abs( vdot(geocoord:altitudeposition(0), normvec:normalized) ). 7 | } 8 | 9 | function OrbAngTo { 10 | parameter pos. 11 | local nvec to vcrs( body:position, velocity:orbit ):normalized. 12 | local proj to vxcl(nvec, pos - body:position). 13 | local angl to arctan2( vdot(nvec, vcrs(body:position, proj)), -vdot(body:position, proj) ). 14 | if angl < 0 set angl to 360 + angl. 15 | 16 | return angl. 17 | } 18 | 19 | function WaitOrient { 20 | parameter tgtcoord. 21 | parameter maxangle to arcsin(50/velocity:orbit:mag). 22 | 23 | if abs(tgtcoord:lat) > orbit:inclination + maxangle or abs(tgtcoord:lat) > 180 - orbit:inclination + maxangle {return 1/0.} 24 | local corrlng to tgtcoord:lng + OrbAngTo(tgtcoord:position)*orbit:period/body:rotationperiod. 25 | local corrtgt to latlng(tgtcoord:lat, corrlng). 26 | local nvec to vcrs( body:position, velocity:orbit ). 27 | until GeoDist(corrtgt, nvec) < body:radius * sin(maxangle) and OrbAngTo(corrtgt:position) > 90 { 28 | set warp to 4. 29 | wait 10. 30 | set corrlng to tgtcoord:lng + OrbAngTo(tgtcoord:position)*orbit:period/body:rotationperiod. 31 | set corrtgt to latlng(tgtcoord:lat, corrlng). 32 | set nvec to vcrs( body:position, velocity:orbit ). 33 | print "Angle to target projection: " + round(OrbAngTo(tgtcoord:position)) + " " at (0,9). 34 | } 35 | set warp to 0. 36 | } 37 | 38 | function RotateOrbit { 39 | parameter tgtcoord. 40 | parameter newpe to -5000. 41 | 42 | local corrlng to tgtcoord:lng + 90*orbit:period/body:rotationperiod. 43 | local corrtgt to latlng(tgtcoord:lat, corrlng). 44 | 45 | warpfor((OrbAngTo(corrtgt:position) - 90)/360*orbit:period). 46 | 47 | local newvdir to heading(corrtgt:heading, 0):vector. 48 | 49 | local newsma to body:radius + (newpe + altitude)*0.5. 50 | local newvmag to sqrt( body:mu * (2/body:position:mag - 1/newsma) ). 51 | local newv to newvmag*newvdir. 52 | local deltav to newv - velocity:orbit. 53 | 54 | lock steering to lookdirup(deltav, up:vector). 55 | wait until vang(facing:vector, deltav) < 1. 56 | lock throttle to max(0.05, GeoDist(corrtgt, vcrs(body:position, velocity:orbit))/500). 57 | wait until periapsis < newpe or availablethrust=0. 58 | lock throttle to 0. 59 | unlock steering. 60 | } 61 | 62 | function waitdownrange { 63 | // assumed acceleration: maxah from 0 to ftfrac*th, change to 0 during last th 64 | parameter tgtcoord. 65 | parameter maxahfrac to 0.95. 66 | parameter ftfrac to min(4,availablethrust*body:radius^2/(mass*body:mu)). 67 | 68 | local maxah to maxahfrac*availablethrust/mass. 69 | local hland to tgtcoord:terrainheight. 70 | local lock vh to vxcl(up:vector,velocity:orbit - tgtcoord:altitudevelocity(hland):orbit):mag. 71 | local th to vh/(maxah*(ftfrac + 0.5)). 72 | 73 | lock steering to lookdirup(srfretrograde:vector,up:vector). 74 | until false { 75 | wait 0. 76 | set th to vh/(maxah*(ftfrac + 0.5)). 77 | local stopdist to maxah*th^2*0.5*(1/3 + ftfrac * (1+ftfrac) ). 78 | local tgtdist to (body:radius + (altitude - hland)/3)*vang(up:vector,tgtcoord:position - body:position)*constant:degtorad. 79 | if tgtdist < stopdist break. 80 | set kuniverse:timewarp:rate to (tgtdist - stopdist)/(vh*10). 81 | } 82 | return th. 83 | } 84 | 85 | function GetVA { 86 | // acceleration changes from a0 to a1 at tau, then to a2 at ts 87 | parameter hland, v0, geff. 88 | parameter ts, Isp. 89 | 90 | local dh to altitude - hland. 91 | 92 | local g1 to body:mu/(body:radius + hland + dh/3)^2. 93 | local dv to sqrt(velocity:surface:sqrmagnitude + 2*g1*dh ) + g1*ts/3. 94 | local a2 to availablethrust/mass - body:mu/(body:radius + hland)^2. 95 | 96 | local a0 to -geff. 97 | local tau to ( ts*(a2*ts - 2*v0) - 6*dh ) / ( 2*v0 + (a0 + a2)*ts ). 98 | local a1 to ( tau*(a2 - a0) - 2*v0 ) / ts - a2. 99 | 100 | print "ts = " + round(ts) + " ; tau = " + round(tau) + " ; a0 = " + round(a0,2) + " ; a1 = " + round(a1,2) + " ; a2 = " + round(a2,2) at (0,11). 101 | return list(a1, a2, tau). 102 | } 103 | 104 | function Descent { 105 | parameter tgtcoord. 106 | parameter th, shipheight, Isp. 107 | parameter ftfrac to min(4,availablethrust*body:radius^2/(mass*body:mu)). 108 | 109 | local tburn to th*(1+ftfrac). 110 | local tend to time:seconds + tburn. 111 | local hland to tgtcoord:terrainheight + shipheight. 112 | 113 | local vv0 to verticalspeed. 114 | local vh to vxcl(up:vector,velocity:orbit - tgtcoord:altitudevelocity(hland):orbit). 115 | local ah0 to vh:mag/(th * (ftfrac + 0.5)). 116 | 117 | local hpid to pidloop(0.04, 0, 0.4). 118 | local vpid to pidloop(0.04, 0, 0.4). 119 | set hpid:setpoint to 0. 120 | set vpid:setpoint to 0. 121 | set hpid:minoutput to -ah0/2. 122 | set hpid:maxoutput to ah0/2. 123 | set vpid:minoutput to -body:mu/(body:radius^2*2). 124 | 125 | local av to 0. 126 | local expdr to ah0*th^2*0.5*(1/3 + ftfrac * (1+ftfrac) ). 127 | local expalt to altitude. 128 | 129 | local alt0 to expalt. 130 | local tleft to tburn. 131 | 132 | local dcenter to body:position:mag. 133 | local geff to (body:mu/dcenter - vxcl(up:vector,velocity:orbit):sqrmagnitude)/dcenter. 134 | 135 | local a1a2tau to getva(hland, vv0, geff, tleft, Isp). 136 | local a0 to -geff. 137 | local a1 to a1a2tau[0]. 138 | local a2 to a1a2tau[1]. 139 | local tau to a1a2tau[2]. 140 | 141 | until tleft <= 0 { 142 | local hdir to vxcl(up:vector,tgtcoord:position):normalized. 143 | set vh to vxcl(up:vector,velocity:orbit - tgtcoord:altitudevelocity(hland):orbit). 144 | set dcenter to body:position:mag. 145 | set geff to (body:mu/dcenter - vxcl(up:vector,velocity:orbit):sqrmagnitude)/dcenter. 146 | local maxa to ship:availablethrust / mass. 147 | 148 | set tleft to tend - time:seconds. 149 | local td to tburn - tleft. 150 | if td < tau set av to a0 + (a1 - a0)*td/tau. 151 | else set av to a2 + (a1 - a2)*tleft/(tburn - tau). 152 | local ah to ah0 * min(1, tleft/th). 153 | 154 | // expected downrange and altitude 155 | if tleft > th set expdr to ah0*th^2/6 + ah0 * th/2*(tleft - th) + ah0*(tleft - th)^2/2. 156 | else set expdr to ah0*tleft^3/(6*th). 157 | 158 | if td < tau set expalt to alt0 + vv0*td + a0*td^2 / 2 + (a1 - a0)*td^3/(6*tau). 159 | else set expalt to hland + a2*tleft^2 / 2 + (a1 - a2)*tleft^3/(6*(tburn - tau)). 160 | 161 | // real values 162 | local hasl to altitude. 163 | local dr to (body:radius + (hasl - hland)/3)*vang(up:vector, tgtcoord:position - body:position)*constant:degtorad. 164 | 165 | // side velocity component 166 | local latvel to vxcl(hdir, vh). 167 | if vdot(hdir, vh) < 0 { 168 | set dr to -dr. 169 | set latvel to V(0,0,0). 170 | set hdir to -hdir. 171 | } 172 | local alatvec to -latvel*5/max(tleft,1). 173 | local ahvec to -hdir*(ah + hpid:update(time:seconds, dr - expdr)). 174 | local avvec to up:vector*(av + geff + vpid:update(time:seconds, hasl - expalt)). 175 | 176 | print "Hacc: " + round(ahvec:mag,2) + " Vacc: " + round(avvec:mag,2) + " Lacc: " + round(alatvec:mag,2) + " " at (0,13). 177 | print "Downrange current / predicted: " + round(dr/1000, 2) + " / " + round(expdr/1000, 2) + " " at (0,14). 178 | print "Altitude current / predicted: " + round(hasl/1000, 2) + " / " + round(expalt/1000, 2) + " " at (0,15). 179 | 180 | print "HPID output: " + round(hpid:output, 2) + " " at (0,16). 181 | set avec to ahvec + avvec + alatvec. 182 | 183 | local dup to -body:position. 184 | if dr <= 0 or vang(facing:vector, up:vector) <= 1 set dup to facing:upvector. 185 | lock steering to lookdirup(avec,dup). 186 | lock throttle to avec:mag/maxa. 187 | if avec:mag/maxa > 1.005 { print " WARNING: not enough TWR" at (25,33). } 188 | else print " " at (25,33). 189 | if alt:radar < 2*shipheight and verticalspeed > -2 break. 190 | if velocity:surface:mag < 100 { 191 | until stage:number = 1 { 192 | list engines in el. 193 | for e in el if e:ignition e:shutdown. 194 | wait 0.2. 195 | stage. 196 | wait 0.2. 197 | } 198 | gear on. 199 | } 200 | wait 0. 201 | } 202 | } 203 | 204 | function VertDescent { 205 | parameter shipheight. 206 | parameter endspeed to 1.5. 207 | 208 | unlock steering. 209 | wait 0. 210 | local av to ship:verticalspeed^2 * 0.5 / max(alt:radar - shipheight, 0.1). 211 | 212 | until status = "Landed" { 213 | local vh to vxcl(up:vector, velocity:surface). 214 | set vh to vh / max(1, vh:mag). 215 | lock steering to lookdirup(up:vector - 0.2*min(1, groundspeed)*vh, facing:upvector). 216 | if verticalspeed < -abs(endspeed) { 217 | set av to ship:verticalspeed^2 * 0.5 / max(alt:radar - shipheight, 0.1). 218 | } 219 | else set av to -0.1. 220 | local dcenter to body:position:mag. 221 | local geff to (body:mu/dcenter - vxcl(up:vector,velocity:orbit):sqrmagnitude)/dcenter. 222 | lock throttle to mass * (av + geff) / (availablethrust * vdot(facing:vector, up:vector)). 223 | wait 0. 224 | } 225 | lock throttle to 0. 226 | } 227 | 228 | function nextlmode { 229 | parameter newmode is lmode+1. 230 | set lmode to newmode. 231 | deletepath("lmode.ks"). 232 | log "set lmode to " + newmode + "." to "lmode.ks". 233 | } 234 | 235 | function landing { 236 | parameter landsite. 237 | parameter ahmaxfrac, shipheight, Isp. 238 | 239 | local stoptime to 0. 240 | 241 | if lmode = 1 { 242 | waitorient(landsite, 5). 243 | nextlmode(). 244 | } 245 | 246 | if lmode = 2 { 247 | rotateorbit(landsite). 248 | wait 1. 249 | nextlmode(). 250 | } 251 | 252 | if lmode = 3 { 253 | set tmax to min(ahmaxfrac, 3*mass*body:mu/(body:radius^2*availablethrust)). 254 | set stoptime to waitdownrange(landsite, tmax). 255 | nextlmode(). 256 | } 257 | 258 | if lmode = 4 { 259 | clearscreen. 260 | Descent(landsite, stoptime, shipheight, Isp). 261 | nextlmode(). 262 | } 263 | 264 | if lmode = 5 { 265 | VertDescent(shipheight). 266 | lock steering to lookdirup(up:vector, facing:upvector). 267 | wait 5. 268 | nextlmode(). 269 | } 270 | set ship:control:pilotmainthrottle to 0. 271 | unlock throttle. 272 | unlock steering. 273 | wait 0. 274 | lock steering to "kill". 275 | wait 10. 276 | } 277 | -------------------------------------------------------------------------------- /Moona/6/landing1.ks: -------------------------------------------------------------------------------- 1 | function GeoDist { 2 | parameter geocoord. 3 | parameter normvec to V(0,1,0). 4 | return abs( vdot(geocoord:altitudeposition(0), normvec:normalized) ). 5 | } 6 | 7 | function OrbAngTo { 8 | parameter pos. 9 | local nvec to vcrs( body:position, velocity:orbit ):normalized. 10 | local proj to vxcl(nvec, pos - body:position). 11 | local angl to arctan2( vdot(nvec, vcrs(body:position, proj)), -vdot(body:position, proj) ). 12 | if angl < 0 set angl to 360 + angl. 13 | 14 | return angl. 15 | } 16 | 17 | function WaitOrient { 18 | parameter tgtcoord. 19 | parameter maxangle to arcsin(50/velocity:orbit:mag). 20 | 21 | if abs(tgtcoord:lat) > orbit:inclination + maxangle or abs(tgtcoord:lat) > 180 - orbit:inclination + maxangle {return 1/0.} 22 | local corrlng to tgtcoord:lng + OrbAngTo(tgtcoord:position)*orbit:period/body:rotationperiod. 23 | local corrtgt to latlng(tgtcoord:lat, corrlng). 24 | local nvec to vcrs( body:position, velocity:orbit ). 25 | until GeoDist(corrtgt, nvec) < body:radius * sin(maxangle) and OrbAngTo(corrtgt:position) > 90 { 26 | set warp to 4. 27 | wait 10. 28 | set corrlng to tgtcoord:lng + OrbAngTo(tgtcoord:position)*orbit:period/body:rotationperiod. 29 | set corrtgt to latlng(tgtcoord:lat, corrlng). 30 | set nvec to vcrs( body:position, velocity:orbit ). 31 | print "Angle to target projection: " + round(OrbAngTo(tgtcoord:position)) + " " at (0,9). 32 | } 33 | set warp to 0. 34 | } 35 | 36 | function RotateOrbit { 37 | parameter tgtcoord. 38 | parameter newpe to 0. 39 | 40 | local corrlng to tgtcoord:lng + 90*orbit:period/body:rotationperiod. 41 | local corrtgt to latlng(tgtcoord:lat, corrlng). 42 | 43 | warpfor((OrbAngTo(corrtgt:position) - 90)/360*orbit:period). 44 | 45 | local newvdir to heading(corrtgt:heading, 0):vector. 46 | 47 | local newsma to body:radius + (newpe + altitude)*0.5. 48 | local newvmag to sqrt( body:mu * (2/body:position:mag - 1/newsma) ). 49 | local newv to newvmag*newvdir. 50 | local deltav to newv - velocity:orbit. 51 | 52 | lock steering to lookdirup(deltav, up:vector). 53 | wait until vang(facing:vector, deltav) < 1. 54 | lock throttle to GeoDist(corrtgt, vcrs(body:position, velocity:orbit))/500. 55 | wait until periapsis < newpe or availablethrust=0. 56 | lock throttle to 0. 57 | unlock steering. 58 | } 59 | 60 | function waitdownrange { 61 | // assumed acceleration: maxah from 0 to ftfrac*th, change to 0 during last th 62 | parameter tgtcoord. 63 | parameter maxahfrac to 0.95. 64 | parameter ftfrac to min(4,availablethrust*body:radius^2/(mass*body:mu)). 65 | 66 | local maxah to maxahfrac*availablethrust/mass. 67 | local hland to tgtcoord:terrainheight. 68 | local lock vh to vxcl(up:vector,velocity:orbit - tgtcoord:altitudevelocity(hland):orbit):mag. 69 | local th to vh/(maxah*(ftfrac + 0.5)). 70 | 71 | lock steering to lookdirup(srfretrograde:vector,up:vector). 72 | until false { 73 | wait 0. 74 | set th to vh/(maxah*(ftfrac + 0.5)). 75 | local stopdist to maxah*th^2*0.5*(1/3 + ftfrac * (1+ftfrac) ). 76 | local tgtdist to (body:radius + (altitude - hland)/3)*vang(up:vector,tgtcoord:position - body:position)*constant:degtorad. 77 | if tgtdist < stopdist break. 78 | set kuniverse:timewarp:rate to (tgtdist - stopdist)/(vh*10). 79 | } 80 | return th. 81 | } 82 | 83 | function GetVA { 84 | // acceleration changes from a0 to a1 at tau, then to a2 at ts 85 | parameter hland, v0, geff. 86 | parameter ts, Isp. 87 | 88 | local dh to altitude - hland. 89 | 90 | local g1 to body:mu/(body:radius + hland + dh/3)^2. 91 | local dv to sqrt(velocity:surface:sqrmagnitude + 2*g1*dh ) + g1*ts/3. 92 | local endmass to mass*constant:e^(-dv/(Isp*9.80665)). 93 | local a2 to availablethrust/endmass - body:mu/(body:radius + hland)^2. 94 | 95 | local a0 to -geff. 96 | local tau to ( ts*(a2*ts - 2*v0) - 6*dh ) / ( 2*v0 + (a0 + a2)*ts ). 97 | local a1 to ( tau*(a2 - a0) - 2*v0 ) / ts - a2. 98 | 99 | print "ts = " + round(ts) + " ; tau = " + round(tau) + " ; a0 = " + round(a0,2) + " ; a1 = " + round(a1,2) + " ; a2 = " + round(a2,2) at (0,11). 100 | return list(a1, a2, tau). 101 | } 102 | 103 | function Descent { 104 | parameter tgtcoord. 105 | parameter th, shipheight, Isp. 106 | parameter ftfrac to min(4,availablethrust*body:radius^2/(mass*body:mu)). 107 | 108 | local tburn to th*(1+ftfrac). 109 | local tend to time:seconds + tburn. 110 | local hland to tgtcoord:terrainheight + shipheight. 111 | 112 | local vv0 to verticalspeed. 113 | local vh to vxcl(up:vector,velocity:orbit - tgtcoord:altitudevelocity(hland):orbit). 114 | local ah0 to vh:mag/(th * (ftfrac + 0.5)). 115 | 116 | local hpid to pidloop(0.04, 0, 0.4). 117 | local vpid to pidloop(0.04, 0, 0.4). 118 | set hpid:setpoint to 0. 119 | set vpid:setpoint to 0. 120 | set hpid:minoutput to -ah0/2. 121 | set hpid:maxoutput to ah0/2. 122 | set vpid:minoutput to -body:mu/(body:radius^2*2). 123 | 124 | local uf to facing:upvector. 125 | local av to 0. 126 | local expdr to ah0*th^2*0.5*(1/3 + ftfrac * (1+ftfrac) ). 127 | local expalt to altitude. 128 | 129 | local alt0 to expalt. 130 | local tleft to tburn. 131 | 132 | local dcenter to body:position:mag. 133 | local geff to (body:mu/dcenter - vxcl(up:vector,velocity:orbit):sqrmagnitude)/dcenter. 134 | 135 | local a1a2tau to getva(hland, vv0, geff, tleft, Isp). 136 | local a0 to -geff. 137 | local a1 to a1a2tau[0]. 138 | local a2 to a1a2tau[1]. 139 | local tau to a1a2tau[2]. 140 | 141 | until tleft <= 0 { 142 | local hdir to vxcl(up:vector,tgtcoord:position):normalized. 143 | set vh to vxcl(up:vector,velocity:orbit - tgtcoord:altitudevelocity(hland):orbit). 144 | set dcenter to body:position:mag. 145 | set geff to (body:mu/dcenter - vxcl(up:vector,velocity:orbit):sqrmagnitude)/dcenter. 146 | local maxa to ship:availablethrust / mass. 147 | 148 | set tleft to tend - time:seconds. 149 | local td to tburn - tleft. 150 | if td < tau set av to a0 + (a1 - a0)*td/tau. 151 | else set av to a2 + (a1 - a2)*tleft/(tburn - tau). 152 | local ah to ah0 * min(1, tleft/th). 153 | 154 | // expected downrange and altitude 155 | if tleft > th set expdr to ah0*th^2/6 + ah0 * th/2*(tleft - th) + ah0*(tleft - th)^2/2. 156 | else set expdr to ah0*tleft^3/(6*th). 157 | 158 | if td < tau set expalt to alt0 + vv0*td + a0*td^2 / 2 + (a1 - a0)*td^3/(6*tau). 159 | else set expalt to hland + a2*tleft^2 / 2 + (a1 - a2)*tleft^3/(6*(tburn - tau)). 160 | 161 | // real values 162 | local hasl to altitude. 163 | local dr to (body:radius + (hasl - hland)/3)*vang(up:vector, tgtcoord:position - body:position)*constant:degtorad. 164 | 165 | // side velocity component 166 | local latvel to vxcl(hdir, vh). 167 | if vdot(hdir, vh) < 0 { 168 | set dr to -dr. 169 | set latvel to V(0,0,0). 170 | set hdir to -hdir. 171 | } 172 | local alatvec to -latvel*5/max(tleft,1). 173 | local ahvec to -hdir*(ah + hpid:update(time:seconds, dr - expdr)). 174 | local avvec to up:vector*(av + geff + vpid:update(time:seconds, hasl - expalt)). 175 | 176 | print "Hacc: " + round(ahvec:mag,2) + " Vacc: " + round(avvec:mag,2) + " Lacc: " + round(alatvec:mag,2) + " " at (0,13). 177 | print "Downrange current / predicted: " + round(dr/1000, 2) + " / " + round(expdr/1000, 2) + " " at (0,14). 178 | print "Altitude current / predicted: " + round(hasl/1000, 2) + " / " + round(expalt/1000, 2) + " " at (0,15). 179 | 180 | print "HPID output: " + round(hpid:output, 2) + " " at (0,16). 181 | set avec to ahvec + avvec + alatvec. 182 | 183 | local dup to up:vector. 184 | if dr <= 0 or vang(facing:vector, up:vector) <= 1 set dup to uf. 185 | lock steering to lookdirup(avec,dup). 186 | lock throttle to avec:mag/maxa. 187 | if avec:mag/maxa > 1.005 { print " WARNING: not enough TWR" at (25,33). } 188 | else print " " at (25,33). 189 | if dr > 0 and vang(facing:vector, up:vector) > 1 set uf to facing:upvector. 190 | if alt:radar < 2*shipheight and verticalspeed > -2 break. 191 | wait 0. 192 | } 193 | return uf. 194 | } 195 | 196 | function VertDescent { 197 | parameter shipheight. 198 | parameter upfacing. 199 | parameter endspeed to 1.5. 200 | 201 | unlock steering. 202 | wait 0. 203 | local av to ship:verticalspeed^2 * 0.5 / max(alt:radar - shipheight, 0.1). 204 | 205 | until status = "Landed" { 206 | local vh to vxcl(up:vector, velocity:surface). 207 | set vh to vh / max(1, vh:mag). 208 | lock steering to lookdirup(up:vector - 0.2*min(1, groundspeed)*vh, upfacing). 209 | if verticalspeed < -abs(endspeed) { 210 | set av to ship:verticalspeed^2 * 0.5 / max(alt:radar - shipheight, 0.1). 211 | } 212 | else set av to -0.1. 213 | local dcenter to body:position:mag. 214 | local geff to (body:mu/dcenter - vxcl(up:vector,velocity:orbit):sqrmagnitude)/dcenter. 215 | lock throttle to mass * (av + geff) / (availablethrust * vdot(facing:vector, up:vector)). 216 | wait 0. 217 | } 218 | lock throttle to 0. 219 | } 220 | 221 | function nextlmode { 222 | parameter newmode is lmode+1. 223 | set lmode to newmode. 224 | log "set lmode to " + newmode + "." to "lmode.ks". 225 | } 226 | 227 | function landing { 228 | parameter landsite. 229 | parameter ahmaxfrac, shipheight, Isp. 230 | 231 | local uf to V(0,1,0). 232 | local stoptime to 0. 233 | 234 | if lmode = 1 { 235 | local dv to 320*9.80665*ln(mass/(mass-stage:liquidfuel/90))-5. 236 | waitorient(landsite, arcsin(min(1,dv/velocity:orbit:mag))*0.8). 237 | nextlmode(). 238 | } 239 | 240 | if lmode = 2 { 241 | rotateorbit(landsite). 242 | wait 1. 243 | stage. 244 | nextlmode(). 245 | } 246 | 247 | if lmode = 3 { 248 | wait 1. 249 | stage. 250 | set tmax to min(ahmaxfrac, 3*mass*body:mu/(body:radius^2*availablethrust)). 251 | set stoptime to waitdownrange(landsite, tmax). 252 | nextlmode(). 253 | } 254 | 255 | if lmode = 4 { 256 | clearscreen. 257 | if not gear { gear on. } 258 | set uf to Descent(landsite, stoptime, shipheight, Isp). 259 | nextlmode(). 260 | } 261 | 262 | if lmode = 5 { 263 | VertDescent(shipheight, uf). 264 | lock steering to lookdirup(up:vector, uf). 265 | wait 5. 266 | nextlmode(). 267 | } 268 | set ship:control:pilotmainthrottle to 0. 269 | unlock throttle. 270 | unlock steering. 271 | wait 0. 272 | lock steering to "kill". 273 | wait 10. 274 | } 275 | --------------------------------------------------------------------------------