From d311045018450d5bbecc846c9dab0b496b51cff0 Mon Sep 17 00:00:00 2001 From: James Turner Date: Sat, 29 Dec 2012 13:45:27 +0000 Subject: [PATCH] Bug 974, GPS exceptions at end-of-route. One of the two route termination conditions was improperly handled, leading to bad leg/wpt indices and exceptions from the GPS code. Detect passing the final waypoint in a more robust way now. Also fix the GPS code to avoid turn computation on the final leg. --- src/Autopilot/route_mgr.cxx | 44 ++++++++++++++++++++----------------- src/Autopilot/route_mgr.hxx | 5 +++++ src/Instrumentation/gps.cxx | 12 ++++------ 3 files changed, 33 insertions(+), 28 deletions(-) diff --git a/src/Autopilot/route_mgr.cxx b/src/Autopilot/route_mgr.cxx index b084c45ad..5fe1466cb 100644 --- a/src/Autopilot/route_mgr.cxx +++ b/src/Autopilot/route_mgr.cxx @@ -453,7 +453,7 @@ void FGRouteMgr::update( double dt ) } if (checkFinished()) { - // maybe we're done + endOfRoute(); } // basic course/distance information @@ -535,14 +535,11 @@ int FGRouteMgr::currentIndex() const Waypt* FGRouteMgr::wayptAtIndex(int index) const { - if (_plan) { - FlightPlan::Leg* leg = _plan->legAtIndex(index); - if (leg) { - return leg->waypoint(); - } + if (!_plan) { + throw sg_range_exception("wayptAtindex: no flightplan"); } - return NULL; + return _plan->legAtIndex(index)->waypoint(); } int FGRouteMgr::numLegs() const @@ -590,8 +587,12 @@ void FGRouteMgr::removeLegAtIndex(int aIndex) void FGRouteMgr::waypointsChanged() { update_mirror(); - _edited->fireValueChanged(); - checkFinished(); + _edited->fireValueChanged(); + +// removing waypoints, deactivate if we hit the end. + if (currentIndex() >= numLegs()) { + endOfRoute(); + } } // mirror internal route to the property system for inspection by other subsystems @@ -802,11 +803,21 @@ void FGRouteMgr::sequence() return; } - if (checkFinished()) { + int nextIndex = _plan->currentIndex() + 1; + if (nextIndex >= _plan->numLegs()) { + SG_LOG(SG_AUTOPILOT, SG_INFO, "sequenced on final leg, deactivating route"); + endOfRoute(); return; } - - _plan->setCurrentIndex(_plan->currentIndex() + 1); + + _plan->setCurrentIndex(nextIndex); +} + +void FGRouteMgr::endOfRoute() +{ + SG_LOG(SG_AUTOPILOT, SG_INFO, "reached end of active route"); + _finished->fireValueChanged(); + active->setBoolValue(false); } bool FGRouteMgr::checkFinished() @@ -824,15 +835,8 @@ bool FGRouteMgr::checkFinished() done = weightOnWheels->getBoolValue() && (gs < 25); } -// also done if we hit the final waypoint - if (_plan->currentIndex() >= _plan->numLegs()) { - done = true; - } - if (done) { - SG_LOG(SG_AUTOPILOT, SG_INFO, "reached end of active route"); - _finished->fireValueChanged(); - active->setBoolValue(false); + SG_LOG(SG_AUTOPILOT, SG_INFO, "checkFinished: on the ground on destination runway, we're done"); } return done; diff --git a/src/Autopilot/route_mgr.hxx b/src/Autopilot/route_mgr.hxx index baa5e2c50..b66a06b72 100644 --- a/src/Autopilot/route_mgr.hxx +++ b/src/Autopilot/route_mgr.hxx @@ -194,6 +194,11 @@ private: */ bool checkFinished(); + /* + * update state when we pass the final waypoint + */ + void endOfRoute(); + /** * Predicate for helping the UI - test if at least one waypoint was * entered by the user (as opposed to being generated by the route-manager) diff --git a/src/Instrumentation/gps.cxx b/src/Instrumentation/gps.cxx index 84ef13e35..5f04de2e6 100644 --- a/src/Instrumentation/gps.cxx +++ b/src/Instrumentation/gps.cxx @@ -877,18 +877,14 @@ double GPS::computeTurnProgress(double aBearing) const void GPS::computeTurnData() { _computeTurnData = false; - if (_mode != "leg") { // and approach modes in the future + int nextIndex = _routeMgr->currentIndex() + 1; + if ((_mode != "leg") || (nextIndex >= _routeMgr->numWaypts())) { _anticipateTurn = false; return; } - WayptRef next = _routeMgr->wayptAtIndex(_routeMgr->currentIndex() + 1); - if (!next || next->flag(WPT_DYNAMIC)) { - _anticipateTurn = false; - return; - } - - if (!_config.turnAnticipationEnabled()) { + WayptRef next = _routeMgr->wayptAtIndex(nextIndex); + if (next->flag(WPT_DYNAMIC) || !_config.turnAnticipationEnabled()) { _anticipateTurn = false; return; }