diff --git a/boot/aircraft.ks b/boot/aircraft.ks new file mode 100644 index 0000000..6a04de6 --- /dev/null +++ b/boot/aircraft.ks @@ -0,0 +1,10 @@ +RunOncePath("0:/lib/boot"). + +parameter debug is false. + +Bootstrap( +"/boot/aircraft", +"/prog/aircraft", +List(), // no additional program files +debug +). diff --git a/lib/boot.ks b/lib/boot.ks index cb0be86..3211f7e 100644 --- a/lib/boot.ks +++ b/lib/boot.ks @@ -78,7 +78,9 @@ function addLibs { if line:Contains("RunOncePath") { local start is line:Find(char(34)). local end is line:FindLast(char(34)). - libs:Add(line:Substring(start + 1, end - start - 1)). + local libFile is line:Substring(start + 1, end - start - 1). + libs:Add(libFile). + addLibs(libs, libFile). } } } diff --git a/lib/flap_control.ks b/lib/flap_control.ks new file mode 100644 index 0000000..cffcfc2 --- /dev/null +++ b/lib/flap_control.ks @@ -0,0 +1,32 @@ + +function SetFlapAngle { + parameter angle. + + local flaps is getFlaps(). + if flaps:LENGTH = 0 { return. } + for flap in flaps { + flap:GetModule("ModuleControlSurface"):SetField("deploy angle", angle). + print("DEBUG: Set flap angle to " + angle). + } +} + +function SetFlaps { + parameter extend is true. + local flaps is getFlaps(). + if flaps:LENGTH = 0 { return. } + for flap in flaps { + flap:GetModule("ModuleControlSurface"):SetField("deploy", extend). + print("DEBUG: Set flap deployment to " + extend). + } +} + +function getFlaps { + local flaps is SHIP:PartsTagged("flap"). + for flap in flaps { + if flap:MODULES:Find("ModuleControlSurface") = -1 { + print "WARNING: Flap is not a control surface. Aborting operation.". + return List(). + } + } + return flaps. +} diff --git a/lib/launch_rocket.ks b/lib/launch_rocket.ks index 7842828..8dbf6b2 100644 --- a/lib/launch_rocket.ks +++ b/lib/launch_rocket.ks @@ -1,5 +1,6 @@ RunOncePath("lib/throttle"). RunOncePath("lib/navigation"). +RunOncePath("lib/navball"). // Calculate the direction to lock during ascent. function getClampedDir { @@ -8,18 +9,12 @@ function getClampedDir { // face just beneath prograde, but hold a solid eastern heading and don't // rotate the ship local newHeading is lookdirup(SHIP:SRFPROGRADE:FOREVECTOR, heading(90, 0, 270):TOPVECTOR). - if getPitch(newHeading:FOREVECTOR) < minPitch { + if GetPitch(newHeading:FOREVECTOR) < minPitch { set newHeading to heading(90, minPitch, 270). } return newHeading. } -// Returns the navball pitch of a given vector. -function getPitch { - parameter v is SHIP:FACING:FOREVECTOR. - return 90 - vectorangle(SHIP:UP:FOREVECTOR, v). -} - // Given a target (end) pitch, a target duration, and a start time, // returns the correct current heading. function pitchProgram { diff --git a/lib/navball.ks b/lib/navball.ks new file mode 100644 index 0000000..7c53383 --- /dev/null +++ b/lib/navball.ks @@ -0,0 +1,9 @@ +// Returns the navball pitch of a given vector. +function GetPitch { + parameter v is SHIP:FACING:FOREVECTOR. + return 90 - vectorangle(SHIP:UP:FOREVECTOR, v). +} + +function GetHeading { + return mod(360 - LatLng(90,0):BEARING, 360). +} diff --git a/lib/stabilize_aircraft.ks b/lib/stabilize_aircraft.ks new file mode 100644 index 0000000..b7dcee2 --- /dev/null +++ b/lib/stabilize_aircraft.ks @@ -0,0 +1,34 @@ +RunOncePath("lib/navball"). + +// Fly level toward the current compass heading. +function HoldHorizon { + parameter Kp is 0.02. + parameter Ki is 0.04. + parameter Kd is 0.0066. + + SAS off. + + local pitchPID is PidLoop(Kp, Ki, Kd). + + // local rollPID is PidLoop(Kp, Ki, Kd). + // lock rollVec to VXCL(SHIP:FACING:FOREVECTOR, SHIP:FACING:TOPVECTOR). + // lock upVec to VXCL(SHIP:FACING:FOREVECTOR, SHIP:UP:FOREVECTOR). + + local h is GetHeading(). + + local p is 0. + lock p to pitchPID:Update(TIME:SECONDS, SHIP:VERTICALSPEED). + lock STEERING to Heading(h, p, 0). + + // until done { + // set SHIP:CONTROL:PITCH to pitchPID:Update(TIME:SECONDS, GetPitch(SHIP:SRFPROGRADE:FOREVECTOR)). + // set SHIP:CONTROL:ROLL to rollPID:Update(TIME:SECONDS, VAng(rollVec, upVec)). + // } + + wait until done. + set done to false. + unlock STEERING. + SAS on. + // set SHIP:CONTROL:PITCH to 0. + // set SHIP:CONTROL:ROLL to 0. +} diff --git a/lib/ui.ks b/lib/ui.ks index a472a52..604e322 100644 --- a/lib/ui.ks +++ b/lib/ui.ks @@ -53,3 +53,25 @@ function MakeMenu { set top:AddButton(execLabel):onClick to callback:Bind(optionList). } } + +function AddStockButtons { + parameter row. + parameter bootname. + + local btn is row:AddButton("Term"). + set btn:TOGGLE to true. + set btn:ONTOGGLE to { + parameter d. + + if d { + CORE:PART:GETMODULE("kOSProcessor"):DOEVENT("Open Terminal"). + } else { + CORE:PART:GETMODULE("kOSProcessor"):DOEVENT("Close Terminal"). + } + }. + + MakeButton(row, "Update", { + switch to 0. + run reinstall(bootname). + }). +} diff --git a/prog/aircraft.ks b/prog/aircraft.ks new file mode 100644 index 0000000..a47f659 --- /dev/null +++ b/prog/aircraft.ks @@ -0,0 +1,91 @@ + +RunOncePath("lib/flap_control"). +RunOncePath("lib/stabilize_aircraft"). +RunOncePath("lib/ui"). + +clearguis(). + +global done is false. +on AG9 { + set done to true. + return true. +} + +function landingMode { + print "Setting flaps to landing mode.". + SetFlapAngle(20). + when SHIP:VELOCITY:SURFACE:MAG < 0.1 then { + takeoffMode(). + } +} + +function takeoffMode { + print "Setting flaps to takeoff mode.". + SetFlapAngle(10). + on GEAR { + if GEAR = true { + return true. + } + landingMode(). + } +} + +if SHIP:STATUS = "LANDED" or SHIP:STATUS = "PRELAUNCH" { + takeoffMode(). +} else { + landingMode(). +} + +// Top-level elements. +local iface is gui(250, 300). +set iface:X to 200. +set iface:Y to 700. +local top is iface:AddVLayout(). +local rows is List(MakeRow(top), MakeRow(top)). +local stk is iface:AddStack(). + +AddStockButtons(rows[0], "aircraft"). + +// rows[0]:AddLabel("FLAPS"). +// // Todo: make angles configurable... +// set rows[1]:AddButton("Takeoff"):onClick to { +// SetFlapAngle(10). +// }. + +// set rows[1]:AddButton("Land"):onClick to { +// SetFlapAngle(20). +// }. + +// set rows[2]:AddButton("Extend"):onClick to { +// SetFlaps(true). +// }. + +// set rows[2]:AddButton("Retract"):onClick to { +// SetFlaps(true). +// }. + +// rows[3]:AddLabel("AUTO"). + +MakeMenu( + stk, + MakeButton(rows[1], "Level"), + List( + List("Kp", "SCALAR", "0.02"), + List("Ki", "SCALAR", "0.01"), + List("Kd", "SCALAR", "1") + ), + "Execute", + { + parameter options. + HoldHorizon( + options["Kp"]:TEXT:ToNumber(), + options["Ki"]:TEXT:ToNumber(), + options["Kd"]:TEXT:ToNumber() + ). + } +). + + +iface:show(). + +wait until false. diff --git a/prog/rocket.ks b/prog/rocket.ks index fe006d8..4bbc917 100644 --- a/prog/rocket.ks +++ b/prog/rocket.ks @@ -25,17 +25,7 @@ local rows is list(MakeRow(top), MakeRow(top), MakeRow(top)). local stk is iface:AddStack(). // Buttons and menus. -local btn is rows[0]:AddButton("TERM"). -set btn:TOGGLE to true. -set btn:ONTOGGLE to { - parameter d. - - if d { - CORE:PART:GETMODULE("kOSProcessor"):DOEVENT("Open Terminal"). - } else { - CORE:PART:GETMODULE("kOSProcessor"):DOEVENT("Close Terminal"). - } -}. +AddStockButtons(rows[0], "rocket"). MakeMenu( stk,