Howto:Implementing a simple GCA system: Difference between revisions

From FlightGear wiki
Jump to navigation Jump to search
Line 229: Line 229:
* add input validation to the GUI dialog
* add input validation to the GUI dialog
* show tooltips
* show tooltips
* add a static label as a status bar to show internal state


== References ==
== References ==
{{Appendix}}
{{Appendix}}

Revision as of 17:51, 19 August 2017

Canvas GUI dialog showing a simple UI for setting up a GCA approach/controller.

Objective

use Nasal to script AI/ATC interactions that pilots need to respond to properly. For example, another simple idea to get you started might be a Nasal script to implement a GCA ("ground controlled approach") mission: http://de.wikipedia.org/wiki/Ground_Controlled_Approach This would simulate an air traffic controller "talking you down", i.e. providing all the feedback an ILS would normally provide (vertical/horiontal deviation from the glide path). This could be very easily implemented in Nasal space. You would just need to configure the script (airport, runway, touchdown point, altitude, glide path) and the GCA script could vector you onto the right course and request you to change altitude as required.[1]


the helpers in geo.nas should be more than sufficient to help us come up with a GCA module and a simple "controller" class that controls an aircraft by monitoring its glide path/vector and issuing instructions accordingly. As a matter of fact, it would also not be that far-fetched to hook up the same control logic to a tanker.nas based AI-piloted aircraft[2]

Status

Background

GCA is surprisingly accurate and easy to use, both as a pilot and a controller. In the 1970´s we tried it on the simulator that I ran at BAC Weybridge. My impression was that it was easier than watching ILS /GLS deviations, At decision height (200ft) when the runway light display projector was turned on, I as pilot) or the pilot that I was directing (as ATC operator) were always perfectly lined up. GCA, with the RAF vocabulary that we used, is very good for teaching students how to follow the glidepath.[3]


we may need to add some features, especially for piloting/flying, i.e. route manager/waypoint awareness, and ability to track course/bearing to certain positions (via geo.nas) - e.g. for navigating via VORs, NDBs or DMEs Currently, the tutorial system doesn't have any built-in support for "fly to the SFO VOR" - but once we have that, we could even support flying holding patterns ( "fly to sfo maintain 8000, hold left on the 180 radial"). Such things would be useful also for virtual flight instruction - but also for an ATC adventure, i.e. where a virtual ATC controller guides pilots down a GCA path using radar vectors and AGL altitudes[4]


All this stuff is already exposed to Nasal thanks to the work that Zakalawe & TheTom have done as part of "NasalPositioned" and those flightplan() APIs - so we really only need to expose a handful of building blocks so that people can create route/navaid-aware missions. This would be primarily useful for any "flight instructions"-based scenarios, i.e. perfectly in line with the original purpose of the "tutorials" system, while also allowing additional functionality to be developed on top, i.e. having scripted virtual pilots or ATC controller.[5]

Design

the logic used by glideslope.nas is definitely a good start - for starters, what is needed is a loop that is monitoring an aircraft, and then, it will be polling that aircraft's position and compute the vertical/horiontal offset to the destination airport/runway using a configurable glideslope (gradient, i.e. altitude change over ground per time interval) - once we have a vertical/horizontal "delta", we can convert those to instructions that are issued to the pilot, while monitoring the aircraft to see if the requested changes (in altitude/heading) are implemented or not, and adjust the gradient/vector accordingly.

[6]


We will be implementing a simple class that merely operates using 3 properties:

  • position/altitude-ft
  • position/latitude_deg
  • position/longitude_deg

This approach makes it possible to reuse the same class for both, the main aircraft, as well as arbitrary AI traffic - e.g. imagine controlling a tanker.nas based AI aircraft using this AI controller.

Good to know

Proof of concept

WIP.png Work in progress
This article or section will be worked on in the upcoming hours or days.
See history for the latest developments.
var GCAController = {
new: func(timer_interval_secs) {
 var m = {parents:[GCAController] };
 m.aircraft_properties = {altitude_ft: "altitude-ft", latitude_deg: "latitude-deg", longitude_deg: "longitude-deg"};
 m.aircraft_state = {latitude_deg:0.00, longitude_deg:0.00, altitude_ft:0.00 }; 
 m.aircraft_object = geo.Coord.new();

 m.receivers = []; # callbacks to receive instructions from the GCA controller
 m.timer = maketimer(timer_interval_secs, func m.update() );
 
 return m;
}, # new()
del: func() {
}, # del()

#####
update: func() {
print("Updating GCA controller");

me.updatePosition();
me.computeRequiredAltitude();
me.computeRequiredHeading();
# compute offset/delta
# build instruction
var instruction = "Turn left";
me.notifyReceivers(instruction);

}, # update()

##### setup APIs: 

setAircraft: func(root) {
me.root = root;
}, # setAircraft()

setDestination: func(airport, runway, glidepath) {
 var apt = airportinfo(airport);
 if (apt == nil) die("Invalid ICAO for airport:"~ airport);

 var runways = apt.runways;
 # debug.dump(runways);
 if (typeof(runways)!="hash" or !size(keys(runways))) die ("runways invalid for "~airport);

 if (runways[runway] == nil) die("runway not found at airport:"~runway);
 
 print("Valid airport/runway combo found");
 me.destination = {airport:airport, runway:runway, glidepath:glidepath, runways:runways, rwy_object: runways[runway] };
}, # setDestination()

registerReceiver: func(receiver) {
append(me.receivers, receiver);
}, #registerReceiver()

notifyReceivers: func(instruction) {
foreach(var r; me.receivers) {
  r(instruction);
 }
},

start: func() {
 me.timer.start();
}, # start()

stop: func() {
 me.timer.stop();
}, # stop()

###
## Update helpers
###


# TODO: this can be easily optimized
updatePosition: func() {
foreach(var p; keys(me.aircraft_properties)) {
#print(me.aircraft_properties[p]);
me.aircraft_state[p] = getprop(me.root ~'/'~ me.aircraft_properties[p]);
}

#debug.dump( me.aircraft_state);

# FIXME: alt meters/feet conversion
me.aircraft_object.set_latlon(me.aircraft_state['latitude_deg'], me.aircraft_state['longitude_deg'], me.aircraft_state['altitude-ft']);

}, # updatePosition()

computeRequiredAltitude: func() {
}, # computeRequiredAltitude()

computeRequiredHeading: func() {
}, # computeRequiredHeading()

}; # GCAController

###
## test the class: 
###

var demo = GCAController.new( timer_interval_secs: 0.5 );
demo.setAircraft( root: "/position", callsign:"foo");
demo.setDestination( airport: "KSFO", runway:  "28R", glidepath: 3.00 );

# this callback will be invoked by the GCA controller when it has a new instruction
# (could be just as well a tooltip or multiplayer chat message)
var receiver = func(instruction) {
print("GCA instruction is: ", instruction);
};


demo.registerReceiver( receiver );
demo.start();

Ideas

  • make the touchdown point configurable ?
  • Implement the whole thing as a GUI dialog for prototyping purposes (e.g. allow the aircraft/airport etc to be entered/changed easily) 60}% completed
  • support multiple instances ?
  • add terrain awareness support (querying the approach profile) ?
  • show a vertical/horizontal map visualizing the approach ?
  • use a subset of tanker.nas to add an ATC-enabled version that actually responds to GCA instructions ?

Roadmap

  • generalize the code to come up with a "TrackingController" for GCA, ASR/PAR respectively
  • add input validation to the GUI dialog
  • show tooltips
  • add a static label as a status bar to show internal state

References

References
  1. Hooray  (Dec 22nd, 2011).  Re: Achievements: New Motivator and Feature Introduction Met .
  2. Hooray  (Aug 14th, 2017).  Re: Spoken .
  3. Alant  (Aug 13th, 2017).  Re: Spoken .
  4. Hooray  (Apr 14th, 2014).  Re: Tutorials/Missions/Adventures: requests for features .
  5. Hooray  (Apr 14th, 2014).  Re: Tutorials/Missions/Adventures: requests for features .
  6. Hooray  (Aug 17th, 2017).  Re: Spoken ATC .
  7. Hooray  (Aug 18th, 2017).  Re: Spoken ATC .