From d4d1d827d0e7543091516479c8d370b2361ab2c4 Mon Sep 17 00:00:00 2001 From: jmt Date: Wed, 16 Sep 2009 00:17:12 +0000 Subject: [PATCH 1/3] Make FGRunway track reciprocal runways. --- src/Airports/apt_loader.cxx | 9 +++++++++ src/Airports/runways.cxx | 12 +++++++++++- src/Airports/runways.hxx | 9 +++++++-- 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/src/Airports/apt_loader.cxx b/src/Airports/apt_loader.cxx index a8af8ca47..320a57150 100644 --- a/src/Airports/apt_loader.cxx +++ b/src/Airports/apt_loader.cxx @@ -286,6 +286,9 @@ private: displ_thresh2, stopway2, surface_code, true); runways.push_back(reciprocal); + + rwy->setReciprocalRunway(reciprocal); + reciprocal->setReciprocalRunway(rwy); } } @@ -335,6 +338,9 @@ private: pos, heading_2, length, width, displ_thresh2, stopway2, surface_code, true); runways.push_back(reciprocal); + + rwy->setReciprocalRunway(reciprocal); + reciprocal->setReciprocalRunway(rwy); } void parseWaterRunwayLine850(const vector& token) @@ -373,6 +379,9 @@ private: pos, heading_2, length, width, 0.0, 0.0, 13, true); runways.push_back(reciprocal); + + rwy->setReciprocalRunway(reciprocal); + reciprocal->setReciprocalRunway(rwy); } void parseHelipadLine850(const vector& token) diff --git a/src/Airports/runways.cxx b/src/Airports/runways.cxx index f97cd14e8..c076d8cfc 100644 --- a/src/Airports/runways.cxx +++ b/src/Airports/runways.cxx @@ -71,7 +71,8 @@ FGRunway::FGRunway(FGAirport* aAirport, const string& aIdent, bool reciprocal) : FGRunwayBase(RUNWAY, cleanRunwayNo(aIdent), aGeod, heading, length, width, surface_code, true), _airport(aAirport), - _reciprocal(reciprocal), + _isReciprocal(reciprocal), + _reciprocal(NULL), _displ_thresh(displ_thresh), _stopway(stopway), _ils(NULL) @@ -158,3 +159,12 @@ void FGRunway::processThreshold(SGPropertyNode* aThreshold) SGGeodesy::direct(newThreshold, _heading, offsetFt * SG_FEET_TO_METER, newCenter, dummy); mPosition = newCenter; } + +void FGRunway::setReciprocalRunway(FGRunway* other) +{ + assert(_reciprocal==NULL); + assert((other->_reciprocal == NULL) || (other->_reciprocal == this)); + + _reciprocal = other; +} + diff --git a/src/Airports/runways.hxx b/src/Airports/runways.hxx index 15d39c2af..e6f97ea95 100644 --- a/src/Airports/runways.hxx +++ b/src/Airports/runways.hxx @@ -36,7 +36,8 @@ class SGPropertyNode; class FGRunway : public FGRunwayBase { FGAirport* _airport; - bool _reciprocal; + bool _isReciprocal; + FGRunway* _reciprocal; double _displ_thresh; double _stopway; FGNavRecord* _ils; @@ -68,7 +69,7 @@ public: * over runways to avoid counting runways twice, if desired. */ bool isReciprocal() const - { return _reciprocal; } + { return _isReciprocal; } /** * Get the runway begining point - this is syntatic sugar, equivalent to @@ -106,6 +107,10 @@ public: FGNavRecord* ILS() const { return _ils; } void setILS(FGNavRecord* nav) { _ils = nav; } + FGRunway* reciprocalRunway() const + { return _reciprocal; } + void setReciprocalRunway(FGRunway* other); + /** * Helper to process property data loaded from an ICAO.threshold.xml file */ From 44bc440d32e74fe90efafb0cf2007d0dc1436a17 Mon Sep 17 00:00:00 2001 From: jmt Date: Wed, 16 Sep 2009 00:23:34 +0000 Subject: [PATCH 2/3] Associate non-ILS localisers with their runway. --- src/Navaids/navrecord.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Navaids/navrecord.cxx b/src/Navaids/navrecord.cxx index 2029d2b7d..49b624244 100644 --- a/src/Navaids/navrecord.cxx +++ b/src/Navaids/navrecord.cxx @@ -101,7 +101,7 @@ void FGNavRecord::initAirportRelation() mPosition.setElevationFt(mRunway->elevation()); } - if (type() == ILS) { + if (type() == ILS || type() == LOC) { mRunway->setILS(this); } From 29f84492a2cdc40a3275e6ff11b4b9520f8774d9 Mon Sep 17 00:00:00 2001 From: jmt Date: Wed, 16 Sep 2009 09:35:22 +0000 Subject: [PATCH 3/3] Different approach to handling the paired-ILS-on-opposite-runways situation. This uses additional information we now store (in FGRunway) to be more explicit about the behaviour (i.e only look at paired navids), and crucially, does not misbehave near either threshold. Instead it always switches about the runway midpoint (so back-course/missed-approaches are broken as before), leading to stable behaviour when touching down. I am pretty confident this is (was, from FS2004) also the 'solution' taken by MSFS. --- src/Navaids/navlist.cxx | 76 +++++++++++++++++------------------------ 1 file changed, 31 insertions(+), 45 deletions(-) diff --git a/src/Navaids/navlist.cxx b/src/Navaids/navlist.cxx index f49052125..bbe3eb424 100644 --- a/src/Navaids/navlist.cxx +++ b/src/Navaids/navlist.cxx @@ -31,6 +31,8 @@ #include "navlist.hxx" +#include + using std::string; // FGNavList ------------------------------------------------------------------ @@ -108,49 +110,38 @@ FGNavRecord *FGNavList::findByIdentAndFreq(const string& ident, const double fre return NULL; } -// LOC, ILS, GS, and DME antenna's could potentially be -// installed at the opposite end of the runway. So it's not -// enough to simply find the closest antenna with the right -// frequency. We need the closest antenna with the right -// frequency that is most oriented towards us. (We penalize -// stations that are facing away from us by adding 5000 meters -// which is further than matching stations would ever be -// placed from each other. (Do the expensive check only for -// directional atennas and only when there is a chance it is -// the closest station.) - -static bool penaltyForNav(FGNavRecord* aNav, const SGGeod &aGeod) +// discount navids if they conflict with another on the same frequency +// this only applies to navids associated with opposite ends of a runway, +// with matching frequencies. +static bool navidUsable(FGNavRecord* aNav, const SGGeod &aircraft) { - switch (aNav->type()) { - case FGPositioned::ILS: - case FGPositioned::LOC: - case FGPositioned::GS: -// FIXME -// case FGPositioned::DME: we can't get the heading for a DME transmitter, oops - break; - default: - return false; + FGRunway* r(aNav->runway()); + if (!r || !r->reciprocalRunway()) { + return true; } - double hdg_deg = 0.0; - if (aNav->type() == FGPositioned::GS) { - int tmp = (int)(aNav->get_multiuse() / 1000.0); - hdg_deg = aNav->get_multiuse() - (tmp * 1000); - } else { - hdg_deg = aNav->get_multiuse(); +// check if the runway frequency is paired + FGNavRecord* locA = r->ILS(); + FGNavRecord* locB = r->reciprocalRunway()->ILS(); + + if (!locA || !locB || (locA->get_freq() != locB->get_freq())) { + return true; // not paired, ok } - double az1, az2, s; - SGGeodesy::inverse(aGeod, aNav->geod(), az1, az2, s); - az1 = az1 - hdg_deg; - SG_NORMALIZE_RANGE(az1, -180.0, 180.0); - return fabs(az1) > 90.0; +// okay, both ends have an ILS, and they're paired. We need to select based on +// aircraft position. What we're going to use is *runway* (not navid) position, +// ie whichever runway end we are closer too. This makes back-course / missed +// approach behaviour incorrect, but that's the price we accept. + double crs = SGGeodesy::courseDeg(aircraft, r->geod()); + double hdgDiff = crs - r->headingDeg(); + SG_NORMALIZE_RANGE(hdgDiff, -180.0, 180.0); + return (fabs(hdgDiff) < 90.0); } -// Given a point and a list of stations, return the closest one to the -// specified point. -FGNavRecord *FGNavList::findNavFromList( const SGGeod &aircraft, - const nav_list_type &stations ) +// Given a point and a list of stations, return the closest one to +// the specified point. +FGNavRecord* FGNavList::findNavFromList( const SGGeod &aircraft, + const nav_list_type &stations ) { FGNavRecord *nav = NULL; double d2; // in meters squared @@ -163,18 +154,13 @@ FGNavRecord *FGNavList::findNavFromList( const SGGeod &aircraft, // find the closest station within a sensible range (FG_NAV_MAX_RANGE) for ( it = stations.begin(); it != end; ++it ) { FGNavRecord *station = *it; - // cout << "testing " << current->get_ident() << endl; d2 = distSqr(station->cart(), aircraftCart); - if ( d2 < min_dist && penaltyForNav(station, aircraft)) - { - double dist = sqrt(d2); - d2 = (dist + 5000) * (dist + 5000); + if ( d2 > min_dist || !navidUsable(station, aircraft)) { + continue; } - if ( d2 < min_dist ) { - min_dist = d2; - nav = station; - } + min_dist = d2; + nav = station; } return nav;