Add aircraft automation code, including flap control and stable autopilot flight.
This commit is contained in:
parent
a99912e3ae
commit
376629354b
10
boot/aircraft.ks
Normal file
10
boot/aircraft.ks
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
RunOncePath("0:/lib/boot").
|
||||||
|
|
||||||
|
parameter debug is false.
|
||||||
|
|
||||||
|
Bootstrap(
|
||||||
|
"/boot/aircraft",
|
||||||
|
"/prog/aircraft",
|
||||||
|
List(), // no additional program files
|
||||||
|
debug
|
||||||
|
).
|
|
@ -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
32
lib/flap_control.ks
Normal 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.
|
||||||
|
}
|
|
@ -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
9
lib/navball.ks
Normal 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
34
lib/stabilize_aircraft.ks
Normal 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.
|
||||||
|
}
|
22
lib/ui.ks
22
lib/ui.ks
|
@ -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
91
prog/aircraft.ks
Normal 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.
|
|
@ -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,
|
||||||
|
|
Loading…
Reference in New Issue
Block a user