Runway Awareness and Advisory System: Difference between revisions
No edit summary |
No edit summary |
||
Line 27: | Line 27: | ||
== TODO == | == TODO == | ||
* Find a core dev to commit logger.nas and runway_announcer.nas to FlightGear's fgdata repository | * Find a core dev to commit logger.nas and runway_announcer.nas to FlightGear's fgdata repository {{Progressbar|50}} | ||
* Use *.groundnet.xml to detect when the aircraft is near a holding point to more accurately emit "approaching-runway" signal | * Use *.groundnet.xml to detect when the aircraft is near a holding point to more accurately emit "approaching-runway" signal {{Not done}} | ||
* Give an advisory of which runway the aircraft is lined up with when the aircraft is airborne and approaching a runway | * Give an advisory of which runway the aircraft is lined up with when the aircraft is airborne and approaching a runway {{Not done}} | ||
== Signals == | == Signals == |
Revision as of 23:15, 22 September 2014
Started in | 08/2014 |
---|---|
Description | System to give advisories about runways |
Contributor(s) | onox |
Status | Under active development as of 08/2014 |
Subforum | http://forum.flightgear.org/viewtopic.php?f=66&t=21266 |
Features
The Runway Advisory and Awareness System can give a number of advisories:
- Advisory when approaching a runway while taxiing
- Advisory when the aircraft is on the runway and pointing in the right direction for takeoff
- Advisory of remaining distance to the end of the runway during a landing
https://www.youtube.com/watch?feature=player_detailpage&v=59ymnKUi49A#t=117
https://www.youtube.com/watch?feature=player_detailpage&v=0jkRhIMZAZo#t=171
TODO
- Use *.groundnet.xml to detect when the aircraft is near a holding point to more accurately emit "approaching-runway" signal Not done
- Give an advisory of which runway the aircraft is lined up with when the aircraft is airborne and approaching a runway Not done
Signals
In order to give these advisories, callbacks for a number of signals can be registered to two announcers. Depending on the current mode of each announcer they will emit certain signals:
Takeoff announcer
Mode | Emitted signals |
---|---|
taxi-and-takeoff | approaching-runway, on-runway |
taxi | approaching-runway |
takeoff | on-runway |
Landing announcer
Mode | Emitted signals |
---|---|
landing | remaining-distance, landed-runway, vacated-runway, landed-outside-runway |
Installation
In case logger.nas and runway_announcer.nas have not been added to FlightGear's fgdata project yet, add the following to the beginning of the <nasal> element in your aircraft's -set.xml file:
<logger>
<file>Aircraft/$YOUR_AIRCRAFT_FOLDER/Nasal/logger.nas</file>
</logger>
<runway>
<file>Aircraft/$YOUR_AIRCRAFT_FOLDER/Nasal/runway_announcer.nas</file>
</runway>
Add the following to the <nasal> element below the previous two:
<file>Aircraft/$YOUR_AIRCRAFT_FOLDER/Nasal/runway.nas</file>
Add the file runway.nas to your aircraft's Nasal folder. The following example listens for gear[1] and gear[2] and overrides a number of properties of the takeoff_config object so that it can be used for large airliners:
# Copyright (C) 2014 onox
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
var copilot_say = func (message) {
setprop("/sim/messages/copilot", message);
};
var make_notification_cb = func (format, action=nil) {
return func (data=nil) {
if (format != nil) {
if (data != nil) {
var message = sprintf(format, data.getValue());
}
else {
var message = format;
}
copilot_say(message);
logger.info(sprintf("Announcing '%s'", message));
}
if (typeof(action) == "func") {
action();
}
};
};
var stop_announcer = func {
landing_announcer.stop();
logger.warn("Stopping landing announce");
takeoff_announcer.set_mode("taxi-and-takeoff");
};
var switch_to_takeoff = func {
# Switch to takeoff mode so that the "approaching-runway" signal
# is not emitted for any runways that are crossed during takeoff
if (takeoff_announcer.mode == "taxi-and-takeoff") {
takeoff_announcer.set_mode("takeoff");
}
};
var takeoff_config = { parents: [runway.TakeoffRunwayAnnounceConfig] };
# Will cause the announcer to emit the "on-runway" signal if the
# aircraft is within 600 meters of the beginning of the runway and
# at most 15 meters from the center line of the runway
takeoff_config.distance_center_line_m = 15;
takeoff_config.distance_start_m = 600;
# Let the announcer emit the "approaching-runway" signal if the
# aircraft comes within 200 meters of the runway
takeoff_config.distance_edge_max_m = 200;
var takeoff_announcer = runway.TakeoffRunwayAnnounceClass.new(takeoff_config);
takeoff_announcer.connect("on-runway", make_notification_cb("On runway %s", switch_to_takeoff));
takeoff_announcer.connect("approaching-runway", make_notification_cb("Approaching runway %s"));
var landing_config = { parents: [runway.LandingRunwayAnnounceConfig] };
var landing_announcer = runway.LandingRunwayAnnounceClass.new(landing_config);
landing_announcer.connect("remaining-distance", make_notification_cb("%d remaining"));
landing_announcer.connect("vacated-runway", make_notification_cb("Vacated runway %s", stop_announcer));
landing_announcer.connect("landed-runway", make_notification_cb("Touchdown on runway %s"));
landing_announcer.connect("landed-outside-runway", make_notification_cb(nil, stop_announcer));
var make_switch_mode_cb = func (wow_mode, no_wow_mode) {
return func (node) {
if (node.getBoolValue()) {
if (getprop("/gear/gear[1]/wow") and getprop("/gear/gear[2]/wow")) {
takeoff_announcer.set_mode(wow_mode);
}
else {
takeoff_announcer.set_mode(no_wow_mode);
}
}
else {
takeoff_announcer.set_mode("");
}
};
};
setlistener("/controls/lighting/nav-lights",
make_switch_mode_cb("taxi-and-takeoff", "taxi"),
startup=1, runtime=0);
var have_been_in_air = 0;
var test_on_ground = func (on_ground) {
if (on_ground) {
takeoff_announcer.start();
logger.warn("Starting takeoff announce");
if (have_been_in_air == 1) {
have_been_in_air = 0;
takeoff_announcer.set_mode("");
landing_announcer.start();
landing_announcer.set_mode("landing");
logger.warn("Starting landing announce");
}
}
else {
takeoff_announcer.stop();
logger.warn("Stopping takeoff announce");
landing_announcer.stop();
logger.warn("Stopping landing announce");
if (have_been_in_air == 0) {
have_been_in_air = 1;
}
}
};
var init_announcers = func {
setlistener("/gear/gear[1]/wow", func (n) {
test_on_ground(getprop("/gear/gear[1]/wow") and getprop("/gear/gear[2]/wow"));
}, startup=1, runtime=0);
setlistener("/gear/gear[2]/wow", func (n) {
test_on_ground(getprop("/gear/gear[1]/wow") and getprop("/gear/gear[2]/wow"));
}, startup=1, runtime=0);
};
setlistener("/sim/signals/fdm-initialized", func {
logger.warn("FDM initialized");
var timer = maketimer(5.0, func init_announcers());
timer.singleShot = 1;
timer.start();
});
Note In this case gear[1] and gear[2] are used to detect whether the aircraft is on the ground or in the air. You may want to modify this for your aircraft. |
Note It is your responsibility to start and stop the announcers and to set the correct modes. Therefore it is necessary to connect to signals like landed-outside-runway and vacated-runway, even if they appear to be useless for your specific aircraft. The example of runway.nas above already does this for you. |
Note You might want to replace copilot_say(). |
The configuration object takeoff_config has a number of properties with default values. These properties can be modified if you want to change when certain signals are emitted. For example, in the example of runway.nas above, distance_center_line_m, distance_start_m, and distance_edge_max_m where overridden for large airliners. The defaults are:
distance_start_m: 200,
# The maximum distance in meters from the starting position
# on the runway. Large runways are usually 40 to 60 meters wide.
diff_runway_heading_deg: 10,
# Difference in heading between runway and aircraft in order to
# get an announcement that the aircraft is on the runway for takeoff.
diff_approach_heading_deg: 40,
# Maximum angle at which the aircraft should approach the runway.
# Must be higher than 0 and lower than 90.
distance_center_line_m: 10,
# The distance in meters from the center line of the runway
distance_edge_min_m: 20,
distance_edge_max_m: 80,
# Minimum and maximum distance in meters from the edge of the runway
# for announcing approaches.
The same applies to the configuration object landing_config:
distances: [30, 100, 300, 600, 900, 1200, 2000, 3000, 4000],
diff_runway_heading_deg: 15,
# Difference in heading between runway and aircraft in order to
# detect the correct runway on which the aircraft is landing.