Merge branch 'jmt/reciprocal' into next
This commit is contained in:
commit
19d2d70da6
5 changed files with 59 additions and 49 deletions
|
@ -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)
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue