Add aircraft automation code, including flap control and stable autopilot flight.

This commit is contained in:
Anna Rose 2021-08-24 06:10:21 -04:00
parent a99912e3ae
commit 376629354b
9 changed files with 204 additions and 19 deletions

10
boot/aircraft.ks Normal file
View File

@ -0,0 +1,10 @@
RunOncePath("0:/lib/boot").
parameter debug is false.
Bootstrap(
"/boot/aircraft",
"/prog/aircraft",
List(), // no additional program files
debug
).

View File

@ -78,7 +78,9 @@ function addLibs {
if line:Contains("RunOncePath") { if line:Contains("RunOncePath") {
local start is line:Find(char(34)). local start is line:Find(char(34)).
local end is line:FindLast(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).
} }
} }
} }

32
lib/flap_control.ks Normal file
View File

@ -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.
}

View File

@ -1,5 +1,6 @@
RunOncePath("lib/throttle"). RunOncePath("lib/throttle").
RunOncePath("lib/navigation"). RunOncePath("lib/navigation").
RunOncePath("lib/navball").
// Calculate the direction to lock during ascent. // Calculate the direction to lock during ascent.
function getClampedDir { function getClampedDir {
@ -8,18 +9,12 @@ function getClampedDir {
// face just beneath prograde, but hold a solid eastern heading and don't // face just beneath prograde, but hold a solid eastern heading and don't
// rotate the ship // rotate the ship
local newHeading is lookdirup(SHIP:SRFPROGRADE:FOREVECTOR, heading(90, 0, 270):TOPVECTOR). 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). set newHeading to heading(90, minPitch, 270).
} }
return newHeading. 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, // Given a target (end) pitch, a target duration, and a start time,
// returns the correct current heading. // returns the correct current heading.
function pitchProgram { function pitchProgram {

9
lib/navball.ks Normal file
View File

@ -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).
}

34
lib/stabilize_aircraft.ks Normal file
View File

@ -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.
}

View File

@ -53,3 +53,25 @@ function MakeMenu {
set top:AddButton(execLabel):onClick to callback:Bind(optionList). 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).
}).
}

91
prog/aircraft.ks Normal file
View File

@ -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.

View File

@ -25,17 +25,7 @@ local rows is list(MakeRow(top), MakeRow(top), MakeRow(top)).
local stk is iface:AddStack(). local stk is iface:AddStack().
// Buttons and menus. // Buttons and menus.
local btn is rows[0]:AddButton("TERM"). AddStockButtons(rows[0], "rocket").
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").
}
}.
MakeMenu( MakeMenu(
stk, stk,