Merge branch 'jmt/reciprocal'
This commit is contained in:
commit
13ff5da4be
5 changed files with 59 additions and 49 deletions
|
@ -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<string>& 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<string>& token)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -31,6 +31,8 @@
|
|||
|
||||
#include "navlist.hxx"
|
||||
|
||||
#include <Airports/runways.hxx>
|
||||
|
||||
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;
|
||||
|
|
|
@ -101,7 +101,7 @@ void FGNavRecord::initAirportRelation()
|
|||
mPosition.setElevationFt(mRunway->elevation());
|
||||
}
|
||||
|
||||
if (type() == ILS) {
|
||||
if (type() == ILS || type() == LOC) {
|
||||
mRunway->setILS(this);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue