1
0
Fork 0

Merge branch 'jmt/reciprocal' into next

This commit is contained in:
Tim Moore 2009-09-17 22:52:17 +02:00
commit 19d2d70da6
5 changed files with 59 additions and 49 deletions

View file

@ -286,6 +286,9 @@ private:
displ_thresh2, stopway2, surface_code, true); displ_thresh2, stopway2, surface_code, true);
runways.push_back(reciprocal); runways.push_back(reciprocal);
rwy->setReciprocalRunway(reciprocal);
reciprocal->setReciprocalRunway(rwy);
} }
} }
@ -335,6 +338,9 @@ private:
pos, heading_2, length, width, pos, heading_2, length, width,
displ_thresh2, stopway2, surface_code, true); displ_thresh2, stopway2, surface_code, true);
runways.push_back(reciprocal); runways.push_back(reciprocal);
rwy->setReciprocalRunway(reciprocal);
reciprocal->setReciprocalRunway(rwy);
} }
void parseWaterRunwayLine850(const vector<string>& token) void parseWaterRunwayLine850(const vector<string>& token)
@ -373,6 +379,9 @@ private:
pos, heading_2, length, width, pos, heading_2, length, width,
0.0, 0.0, 13, true); 0.0, 0.0, 13, true);
runways.push_back(reciprocal); runways.push_back(reciprocal);
rwy->setReciprocalRunway(reciprocal);
reciprocal->setReciprocalRunway(rwy);
} }
void parseHelipadLine850(const vector<string>& token) void parseHelipadLine850(const vector<string>& token)

View file

@ -71,7 +71,8 @@ FGRunway::FGRunway(FGAirport* aAirport, const string& aIdent,
bool reciprocal) : bool reciprocal) :
FGRunwayBase(RUNWAY, cleanRunwayNo(aIdent), aGeod, heading, length, width, surface_code, true), FGRunwayBase(RUNWAY, cleanRunwayNo(aIdent), aGeod, heading, length, width, surface_code, true),
_airport(aAirport), _airport(aAirport),
_reciprocal(reciprocal), _isReciprocal(reciprocal),
_reciprocal(NULL),
_displ_thresh(displ_thresh), _displ_thresh(displ_thresh),
_stopway(stopway), _stopway(stopway),
_ils(NULL) _ils(NULL)
@ -158,3 +159,12 @@ void FGRunway::processThreshold(SGPropertyNode* aThreshold)
SGGeodesy::direct(newThreshold, _heading, offsetFt * SG_FEET_TO_METER, newCenter, dummy); SGGeodesy::direct(newThreshold, _heading, offsetFt * SG_FEET_TO_METER, newCenter, dummy);
mPosition = newCenter; mPosition = newCenter;
} }
void FGRunway::setReciprocalRunway(FGRunway* other)
{
assert(_reciprocal==NULL);
assert((other->_reciprocal == NULL) || (other->_reciprocal == this));
_reciprocal = other;
}

View file

@ -36,7 +36,8 @@ class SGPropertyNode;
class FGRunway : public FGRunwayBase class FGRunway : public FGRunwayBase
{ {
FGAirport* _airport; FGAirport* _airport;
bool _reciprocal; bool _isReciprocal;
FGRunway* _reciprocal;
double _displ_thresh; double _displ_thresh;
double _stopway; double _stopway;
FGNavRecord* _ils; FGNavRecord* _ils;
@ -68,7 +69,7 @@ public:
* over runways to avoid counting runways twice, if desired. * over runways to avoid counting runways twice, if desired.
*/ */
bool isReciprocal() const bool isReciprocal() const
{ return _reciprocal; } { return _isReciprocal; }
/** /**
* Get the runway begining point - this is syntatic sugar, equivalent to * Get the runway begining point - this is syntatic sugar, equivalent to
@ -106,6 +107,10 @@ public:
FGNavRecord* ILS() const { return _ils; } FGNavRecord* ILS() const { return _ils; }
void setILS(FGNavRecord* nav) { _ils = nav; } 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 * Helper to process property data loaded from an ICAO.threshold.xml file
*/ */

View file

@ -31,6 +31,8 @@
#include "navlist.hxx" #include "navlist.hxx"
#include <Airports/runways.hxx>
using std::string; using std::string;
// FGNavList ------------------------------------------------------------------ // FGNavList ------------------------------------------------------------------
@ -108,49 +110,38 @@ 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 )
{ {
FGNavRecord *nav = NULL; FGNavRecord *nav = NULL;
double d2; // in meters squared 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) // 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;

View file

@ -101,7 +101,7 @@ void FGNavRecord::initAirportRelation()
mPosition.setElevationFt(mRunway->elevation()); mPosition.setElevationFt(mRunway->elevation());
} }
if (type() == ILS) { if (type() == ILS || type() == LOC) {
mRunway->setILS(this); mRunway->setILS(this);
} }