2013-04-07 20:45:29 +00:00
|
|
|
# route_manager.nas - FlightPlan delegate(s) corresponding to the built-
|
2014-12-19 17:02:55 +00:00
|
|
|
# in route-manager dialog and GPS. Intended to provide a sensible default behaviour,
|
2013-04-07 20:45:29 +00:00
|
|
|
# but can be disabled by an aircraft-specific FMS / GPS system.
|
2012-05-15 16:51:48 +00:00
|
|
|
|
|
|
|
var RouteManagerDelegate = {
|
2015-01-10 19:37:58 +00:00
|
|
|
new: func(fp) {
|
2013-04-07 20:45:29 +00:00
|
|
|
# if this property is set, don't build a delegate at all
|
|
|
|
if (getprop('/autopilot/route-manager/disable-route-manager'))
|
|
|
|
return nil;
|
2014-12-19 17:02:55 +00:00
|
|
|
|
2015-01-10 19:37:58 +00:00
|
|
|
var m = { parents: [RouteManagerDelegate] };
|
|
|
|
m.flightplan = fp;
|
|
|
|
return m;
|
|
|
|
},
|
2012-05-15 16:51:48 +00:00
|
|
|
|
|
|
|
departureChanged: func
|
|
|
|
{
|
2014-05-31 02:45:05 +00:00
|
|
|
printlog('info', 'saw departure changed');
|
2012-05-15 16:51:48 +00:00
|
|
|
me.flightplan.clearWPType('sid');
|
|
|
|
if (me.flightplan.departure == nil)
|
|
|
|
return;
|
2014-12-19 17:02:55 +00:00
|
|
|
|
2012-05-15 16:51:48 +00:00
|
|
|
if (me.flightplan.departure_runway == nil) {
|
|
|
|
# no runway, only an airport, use that
|
|
|
|
var wp = createWPFrom(me.flightplan.departure);
|
|
|
|
wp.wp_role = 'sid';
|
|
|
|
me.flightplan.insertWP(wp, 0);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
# first, insert the runway itself
|
|
|
|
var wp = createWPFrom(me.flightplan.departure_runway);
|
|
|
|
wp.wp_role = 'sid';
|
|
|
|
me.flightplan.insertWP(wp, 0);
|
|
|
|
if (me.flightplan.sid == nil)
|
|
|
|
return;
|
2014-12-19 17:02:55 +00:00
|
|
|
|
2012-05-15 16:51:48 +00:00
|
|
|
# and we have a SID
|
|
|
|
var sid = me.flightplan.sid;
|
2014-05-31 02:45:05 +00:00
|
|
|
printlog('info', 'routing via SID ' ~ sid.id);
|
2012-05-15 16:51:48 +00:00
|
|
|
me.flightplan.insertWaypoints(sid.route(me.flightplan.departure_runway), 1);
|
|
|
|
},
|
|
|
|
|
|
|
|
arrivalChanged: func
|
|
|
|
{
|
2014-05-31 02:45:05 +00:00
|
|
|
printlog('info', 'saw arrival changed');
|
2012-05-15 16:51:48 +00:00
|
|
|
me.flightplan.clearWPType('star');
|
|
|
|
me.flightplan.clearWPType('approach');
|
|
|
|
if (me.flightplan.destination == nil)
|
|
|
|
return;
|
2014-12-19 17:02:55 +00:00
|
|
|
|
2012-05-15 16:51:48 +00:00
|
|
|
if (me.flightplan.destination_runway == nil) {
|
|
|
|
# no runway, only an airport, use that
|
|
|
|
var wp = createWPFrom(me.flightplan.destination);
|
|
|
|
wp.wp_role = 'approach';
|
|
|
|
me.flightplan.appendWP(wp);
|
|
|
|
return;
|
|
|
|
}
|
2014-12-19 17:02:55 +00:00
|
|
|
|
|
|
|
var initialApproachFix = nil;
|
2012-05-15 16:51:48 +00:00
|
|
|
if (me.flightplan.star != nil) {
|
2014-05-31 02:45:05 +00:00
|
|
|
printlog('info', 'routing via STAR ' ~ me.flightplan.star.id);
|
2012-05-15 16:51:48 +00:00
|
|
|
var wps = me.flightplan.star.route(me.flightplan.destination_runway);
|
|
|
|
me.flightplan.insertWaypoints(wps, -1);
|
2014-12-19 17:02:55 +00:00
|
|
|
|
|
|
|
initialApproachFix = wps[-1]; # final waypoint of STAR
|
2012-05-15 16:51:48 +00:00
|
|
|
}
|
2014-12-19 17:02:55 +00:00
|
|
|
|
2012-05-15 16:51:48 +00:00
|
|
|
if (me.flightplan.approach != nil) {
|
2014-12-19 17:02:55 +00:00
|
|
|
var wps = me.flightplan.approach.route(initialApproachFix);
|
2015-01-10 19:37:58 +00:00
|
|
|
|
|
|
|
if ((initialApproachFix != nil) and (wps == nil)) {
|
|
|
|
# current GUI allows selected approach then STAR; but STAR
|
|
|
|
# might not be possible for the approach (no transition).
|
|
|
|
# since fixing the GUI flow is hard, let's route assuming no
|
|
|
|
# IAF. This will likely cause an ugly direct leg, but that's
|
|
|
|
# what the user asked for.
|
|
|
|
|
|
|
|
printlog('info', "couldn't route approach based on specified IAF "
|
|
|
|
~ initialApproachFix.wp_name);
|
|
|
|
wps = me.flightplan.approach.route(nil);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (wps == nil) {
|
|
|
|
printlog('warn', 'routing via approach ' ~ me.flightplan.approach.id
|
|
|
|
~ ' failed entirely.');
|
|
|
|
} else {
|
|
|
|
printlog('info', 'routing via approach ' ~ me.flightplan.approach.id);
|
|
|
|
me.flightplan.insertWaypoints(wps, -1);
|
|
|
|
}
|
2012-05-15 16:51:48 +00:00
|
|
|
} else {
|
2014-05-31 02:45:05 +00:00
|
|
|
printlog('info', 'routing direct to runway ' ~ me.flightplan.destination_runway.id);
|
2012-05-15 16:51:48 +00:00
|
|
|
# no approach, just use the runway waypoint
|
|
|
|
var wp = createWPFrom(me.flightplan.destination_runway);
|
|
|
|
wp.wp_role = 'approach';
|
|
|
|
me.flightplan.appendWP(wp);
|
|
|
|
}
|
|
|
|
},
|
2014-12-19 17:02:55 +00:00
|
|
|
|
2012-12-31 17:38:18 +00:00
|
|
|
cleared: func
|
|
|
|
{
|
2014-05-31 02:45:05 +00:00
|
|
|
printlog('info', "saw active flightplan cleared, deactivating");
|
2012-12-31 17:38:18 +00:00
|
|
|
# see http://https://code.google.com/p/flightgear-bugs/issues/detail?id=885
|
|
|
|
fgcommand("activate-flightplan", props.Node.new({"activate": 0}));
|
|
|
|
},
|
2014-12-19 17:02:55 +00:00
|
|
|
|
2013-03-20 12:24:14 +00:00
|
|
|
endOfFlightPlan: func
|
|
|
|
{
|
2014-05-31 02:45:05 +00:00
|
|
|
printlog('info', "end of flight-plan, deactivating");
|
2013-03-20 12:24:14 +00:00
|
|
|
fgcommand("activate-flightplan", props.Node.new({"activate": 0}));
|
2013-04-07 20:45:29 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
var FMSDelegate = {
|
2015-01-10 19:37:58 +00:00
|
|
|
new: func(fp) {
|
2013-04-07 20:45:29 +00:00
|
|
|
# if this property is set, don't build a delegate at all
|
|
|
|
if (getprop('/autopilot/route-manager/disable-fms'))
|
|
|
|
return nil;
|
2014-12-19 17:02:55 +00:00
|
|
|
|
2015-01-10 19:37:58 +00:00
|
|
|
var m = { parents: [FMSDelegate], flightplan:fp, landingCheck:nil };
|
2015-01-08 19:48:17 +00:00
|
|
|
|
|
|
|
# make FlightPlan behaviour match GPS config state
|
|
|
|
fp.followLegTrackToFix = getprop('/instrumentation/gps/config/follow-leg-track-to-fix');
|
|
|
|
|
|
|
|
# similarly, make FlightPlan follow the performance category settings
|
|
|
|
fp.aircraftCategory = getprop('/autopilot/settings/icao-aircraft-category');
|
|
|
|
|
2015-01-10 19:37:58 +00:00
|
|
|
return m;
|
|
|
|
},
|
2014-12-19 17:02:55 +00:00
|
|
|
|
2013-06-01 10:12:23 +00:00
|
|
|
_landingCheckTimeout: func
|
|
|
|
{
|
|
|
|
var wow = getprop('gear/gear[0]/wow');
|
|
|
|
var gs = getprop('velocities/groundspeed-kt');
|
|
|
|
if (wow and (gs < 25)) {
|
2014-05-31 02:45:05 +00:00
|
|
|
printlog('info', 'touchdown on destination runway, end of route.');
|
2013-06-01 10:12:23 +00:00
|
|
|
me.landingCheck.stop();
|
|
|
|
# record touch-down time?
|
|
|
|
me.flightplan.finish();
|
|
|
|
}
|
|
|
|
},
|
2014-12-19 17:02:55 +00:00
|
|
|
|
2012-05-15 16:51:48 +00:00
|
|
|
waypointsChanged: func
|
|
|
|
{
|
|
|
|
},
|
2014-12-19 17:02:55 +00:00
|
|
|
|
2013-04-07 20:45:29 +00:00
|
|
|
endOfFlightPlan: func
|
|
|
|
{
|
2014-05-31 02:45:05 +00:00
|
|
|
printlog('info', 'end of flight-plan');
|
2013-04-07 20:45:29 +00:00
|
|
|
},
|
2014-12-19 17:02:55 +00:00
|
|
|
|
2012-05-15 16:51:48 +00:00
|
|
|
currentWaypointChanged: func
|
|
|
|
{
|
2013-04-07 20:45:29 +00:00
|
|
|
if (me.landingCheck != nil) {
|
2013-06-01 10:12:23 +00:00
|
|
|
me.landingCheck.stop();
|
|
|
|
me.landingCheck = nil; # delete timer
|
2013-04-07 20:45:29 +00:00
|
|
|
}
|
2014-12-19 17:02:55 +00:00
|
|
|
|
2014-05-31 02:45:05 +00:00
|
|
|
#printlog('info', 'saw current WP changed, now ' ~ me.flightplan.current);
|
2013-04-07 20:45:29 +00:00
|
|
|
var active = me.flightplan.currentWP();
|
|
|
|
if (active == nil) return;
|
2014-12-19 17:02:55 +00:00
|
|
|
|
2014-01-18 08:45:20 +00:00
|
|
|
if (active.alt_cstr_type == "at") {
|
2014-05-31 02:45:05 +00:00
|
|
|
printlog('info', 'new WP has valid altitude restriction, setting on AP');
|
2013-06-01 10:12:23 +00:00
|
|
|
setprop('/autopilot/settings/target-altitude-ft', active.alt_cstr);
|
2013-04-07 20:45:29 +00:00
|
|
|
}
|
2014-12-19 17:02:55 +00:00
|
|
|
|
2013-04-07 20:45:29 +00:00
|
|
|
var activeRunway = active.runway();
|
2013-06-01 10:12:23 +00:00
|
|
|
# this check is needed to avoid problems with circular routes; when
|
|
|
|
# activating the FP we end up here, and without this check, immediately
|
|
|
|
# detect that we've 'landed' and finish the FP again.
|
|
|
|
var wow = getprop('gear/gear[0]/wow');
|
2014-12-19 17:02:55 +00:00
|
|
|
|
|
|
|
if (!wow and
|
|
|
|
(activeRunway != nil) and
|
2013-06-01 10:12:23 +00:00
|
|
|
(activeRunway.id == me.flightplan.destination_runway.id))
|
|
|
|
{
|
|
|
|
me.landingCheck = maketimer(2.0, me, FMSDelegate._landingCheckTimeout);
|
|
|
|
me.landingCheck.start();
|
2013-04-07 20:45:29 +00:00
|
|
|
}
|
2012-05-15 16:51:48 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2013-04-07 20:45:29 +00:00
|
|
|
registerFlightPlanDelegate(FMSDelegate.new);
|
2012-05-15 16:51:48 +00:00
|
|
|
registerFlightPlanDelegate(RouteManagerDelegate.new);
|
|
|
|
|