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.
This commit is contained in:
parent
44bc440d32
commit
29f84492a2
1 changed files with 31 additions and 45 deletions
|
@ -31,6 +31,8 @@
|
||||||
|
|
||||||
#include "navlist.hxx"
|
#include "navlist.hxx"
|
||||||
|
|
||||||
|
#include <Airports/runways.hxx>
|
||||||
|
|
||||||
using std::string;
|
using std::string;
|
||||||
|
|
||||||
// FGNavList ------------------------------------------------------------------
|
// FGNavList ------------------------------------------------------------------
|
||||||
|
@ -108,47 +110,36 @@ FGNavRecord *FGNavList::findByIdentAndFreq(const string& ident, const double fre
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// LOC, ILS, GS, and DME antenna's could potentially be
|
// discount navids if they conflict with another on the same frequency
|
||||||
// installed at the opposite end of the runway. So it's not
|
// this only applies to navids associated with opposite ends of a runway,
|
||||||
// enough to simply find the closest antenna with the right
|
// with matching frequencies.
|
||||||
// frequency. We need the closest antenna with the right
|
static bool navidUsable(FGNavRecord* aNav, const SGGeod &aircraft)
|
||||||
// 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)
|
|
||||||
{
|
{
|
||||||
switch (aNav->type()) {
|
FGRunway* r(aNav->runway());
|
||||||
case FGPositioned::ILS:
|
if (!r || !r->reciprocalRunway()) {
|
||||||
case FGPositioned::LOC:
|
return true;
|
||||||
case FGPositioned::GS:
|
|
||||||
// FIXME
|
|
||||||
// case FGPositioned::DME: we can't get the heading for a DME transmitter, oops
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
double hdg_deg = 0.0;
|
// check if the runway frequency is paired
|
||||||
if (aNav->type() == FGPositioned::GS) {
|
FGNavRecord* locA = r->ILS();
|
||||||
int tmp = (int)(aNav->get_multiuse() / 1000.0);
|
FGNavRecord* locB = r->reciprocalRunway()->ILS();
|
||||||
hdg_deg = aNav->get_multiuse() - (tmp * 1000);
|
|
||||||
} else {
|
if (!locA || !locB || (locA->get_freq() != locB->get_freq())) {
|
||||||
hdg_deg = aNav->get_multiuse();
|
return true; // not paired, ok
|
||||||
}
|
}
|
||||||
|
|
||||||
double az1, az2, s;
|
// okay, both ends have an ILS, and they're paired. We need to select based on
|
||||||
SGGeodesy::inverse(aGeod, aNav->geod(), az1, az2, s);
|
// aircraft position. What we're going to use is *runway* (not navid) position,
|
||||||
az1 = az1 - hdg_deg;
|
// ie whichever runway end we are closer too. This makes back-course / missed
|
||||||
SG_NORMALIZE_RANGE(az1, -180.0, 180.0);
|
// approach behaviour incorrect, but that's the price we accept.
|
||||||
return fabs(az1) > 90.0;
|
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
|
// Given a point and a list of stations, return the closest one to
|
||||||
// specified point.
|
// the specified point.
|
||||||
FGNavRecord* FGNavList::findNavFromList( const SGGeod &aircraft,
|
FGNavRecord* FGNavList::findNavFromList( const SGGeod &aircraft,
|
||||||
const nav_list_type &stations )
|
const nav_list_type &stations )
|
||||||
{
|
{
|
||||||
|
@ -163,19 +154,14 @@ FGNavRecord *FGNavList::findNavFromList( const SGGeod &aircraft,
|
||||||
// find the closest station within a sensible range (FG_NAV_MAX_RANGE)
|
// find the closest station within a sensible range (FG_NAV_MAX_RANGE)
|
||||||
for ( it = stations.begin(); it != end; ++it ) {
|
for ( it = stations.begin(); it != end; ++it ) {
|
||||||
FGNavRecord *station = *it;
|
FGNavRecord *station = *it;
|
||||||
// cout << "testing " << current->get_ident() << endl;
|
|
||||||
d2 = distSqr(station->cart(), aircraftCart);
|
d2 = distSqr(station->cart(), aircraftCart);
|
||||||
if ( d2 < min_dist && penaltyForNav(station, aircraft))
|
if ( d2 > min_dist || !navidUsable(station, aircraft)) {
|
||||||
{
|
continue;
|
||||||
double dist = sqrt(d2);
|
|
||||||
d2 = (dist + 5000) * (dist + 5000);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( d2 < min_dist ) {
|
|
||||||
min_dist = d2;
|
min_dist = d2;
|
||||||
nav = station;
|
nav = station;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return nav;
|
return nav;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue