1
0
Fork 0

Merge branch 'jmt/reciprocal'

This commit is contained in:
Tim Moore 2009-09-23 07:44:02 +02:00
commit 13ff5da4be
5 changed files with 59 additions and 49 deletions

View file

@ -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)

View file

@ -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;
}

View file

@ -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
*/

View 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;

View file

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