From: Thomas Geymayer Date: Sun, 2 Mar 2014 15:52:00 +0000 (+0100) Subject: TACAN: fix distance calculations and some other problems. X-Git-Url: https://git.mxchange.org/?a=commitdiff_plain;h=c7c9fd67aa69081d65c4a01351b976e3ed797d57;p=flightgear.git TACAN: fix distance calculations and some other problems. - Calculate line of sight distance instead of distance over ground - Do a nav cache update if carrier_nav.dat.gz timestamp has changed - Allow comments in carrier_nav.dat.gz - "Fix" range calculations (still does not take terrain/weather and other influences into account) --- diff --git a/src/Instrumentation/tacan.cxx b/src/Instrumentation/tacan.cxx index ca0320abb..1a808e5b8 100644 --- a/src/Instrumentation/tacan.cxx +++ b/src/Instrumentation/tacan.cxx @@ -25,19 +25,22 @@ * borderline reception. */ static double -adjust_range (double transmitter_elevation_ft, double aircraft_altitude_ft, - double max_range_nm) +adjust_range( double station_elevation_ft, + double aircraft_altitude_ft, + double max_range_nm ) { - max_range_nm = 150; // TODO why a fixed range? - double delta_elevation_ft = - fabs(aircraft_altitude_ft - transmitter_elevation_ft); - double range_nm = 1.23 * sqrt(delta_elevation_ft); - if (range_nm > max_range_nm) - range_nm = max_range_nm; - else if (range_nm < 20.0) - range_nm = 20.0; - double rand = sg_random(); - return range_nm + (range_nm * rand * rand); + // See http://en.wikipedia.org/wiki/Line-of-sight_propagation for approximate + // line-of-sight distance to the horizon + + double range_nm = 0; + if( station_elevation_ft > 5 ) + range_nm += 1.23 * sqrt(station_elevation_ft); + + if( aircraft_altitude_ft > 5 ) + range_nm += 1.23 * sqrt(aircraft_altitude_ft); + + return std::max(20., std::min(range_nm, max_range_nm)) + * (1 + SGMiscd::pow<2>(0.3 * sg_random())); } //------------------------------------------------------------------------------ @@ -101,6 +104,8 @@ void TACAN::init() _channel_in2_node->addChangeListener(this); _channel_in3_node->addChangeListener(this); _channel_in4_node->addChangeListener(this, true); + + disabled(true); } //------------------------------------------------------------------------------ @@ -130,19 +135,25 @@ void TACAN::update(double delta_time_sec) if( !_active_station || !_active_station->get_serviceable() ) return disabled(); + const SGGeod& nav_pos = _active_station->geod(); + // Calculate the bearing and range of the station from the aircraft double az = 0; double bearing = 0; double distance = SGLimitsd::max(); - if( !SGGeodesy::inverse(pos, _active_station->geod(), bearing, az, distance) ) + if( !SGGeodesy::inverse(pos, nav_pos, bearing, az, distance) ) return disabled(); - double range_nm = adjust_range( _active_station->get_elev_ft(), + // Increase distance due to difference in altitude + distance = + sqrt( SGMiscd::pow<2>(distance) + + SGMiscd::pow<2>(pos.getElevationM() - nav_pos.getElevationM()) ); + double distance_nm = distance * SG_METER_TO_NM; + + double range_nm = adjust_range( nav_pos.getElevationFt(), pos.getElevationFt(), _active_station->get_range() ); - double distance_nm = distance * SG_METER_TO_NM; - if( distance_nm > range_nm ) return disabled(); @@ -184,9 +195,9 @@ void TACAN::update(double delta_time_sec) } //------------------------------------------------------------------------------ -void TACAN::disabled() +void TACAN::disabled(bool force) { - if( _was_disabled ) + if( _was_disabled && !force ) return; _last_distance_nm = 0; diff --git a/src/Instrumentation/tacan.hxx b/src/Instrumentation/tacan.hxx index 92f57c7d3..fcbc737c8 100644 --- a/src/Instrumentation/tacan.hxx +++ b/src/Instrumentation/tacan.hxx @@ -45,7 +45,7 @@ class TACAN : public SGSubsystem, public SGPropertyChangeListener private: - void disabled(); + void disabled(bool force = false); void search (double frequency, const SGGeod& pos); double searchChannel (const std::string& channel); diff --git a/src/Navaids/NavDataCache.cxx b/src/Navaids/NavDataCache.cxx index bbd399032..17b982e5d 100644 --- a/src/Navaids/NavDataCache.cxx +++ b/src/Navaids/NavDataCache.cxx @@ -1129,6 +1129,7 @@ bool NavDataCache::isRebuildRequired() if (isCachedFileModified(d->aptDatPath) || isCachedFileModified(d->metarDatPath) || isCachedFileModified(d->navDatPath) || + isCachedFileModified(d->carrierDatPath) || isCachedFileModified(d->fixDatPath) || // since POI loading is disabled on Windows, don't check for it // this caused: https://code.google.com/p/flightgear-bugs/issues/detail?id=1227 diff --git a/src/Navaids/navdb.cxx b/src/Navaids/navdb.cxx index 99453022a..77a82c99b 100644 --- a/src/Navaids/navdb.cxx +++ b/src/Navaids/navdb.cxx @@ -118,8 +118,15 @@ static double defaultNavRange(const string& ident, FGPositioned::Type type) case FGPositioned::GS: return FG_LOC_DEFAULT_RANGE; - case FGPositioned::DME: return FG_DME_DEFAULT_RANGE; - default: return FG_LOC_DEFAULT_RANGE; + case FGPositioned::DME: + return FG_DME_DEFAULT_RANGE; + + case FGPositioned::TACAN: + case FGPositioned::MOBILE_TACAN: + return FG_TACAN_DEFAULT_RANGE; + + default: + return FG_LOC_DEFAULT_RANGE; } } @@ -134,9 +141,8 @@ static PositionedID readNavFromStream(std::istream& aStream, int rawType; aStream >> rawType; - if (aStream.eof() || (rawType == 99)) { + if( aStream.eof() || (rawType == 99) || (rawType == 0) ) return 0; // happens with, eg, carrier_nav.dat - } double lat, lon, elev_ft, multiuse; int freq, range; @@ -146,7 +152,7 @@ static PositionedID readNavFromStream(std::istream& aStream, SGGeod pos(SGGeod::fromDegFt(lon, lat, elev_ft)); name = simgear::strutils::strip(name); - + // the type can be forced by our caller, but normally we use th value // supplied in the .dat file if (type == FGPositioned::INVALID) { @@ -282,9 +288,10 @@ bool loadCarrierNav(const SGPath& path) } while ( ! incarrier.eof() ) { + incarrier >> skipcomment; // force the type to be MOBILE_TACAN readNavFromStream(incarrier, FGPositioned::MOBILE_TACAN); - } // end while + } return true; } diff --git a/src/Navaids/navrecord.cxx b/src/Navaids/navrecord.cxx index 37bd5a194..fabc9a0d0 100644 --- a/src/Navaids/navrecord.cxx +++ b/src/Navaids/navrecord.cxx @@ -213,8 +213,7 @@ void FGMobileNavRecord::updatePos() : _vehicle_node->getDoubleValue("position/altitude-ft") )); else - // If no match was found set 'invalid' position (lat = lon = 0) - modifyPosition(SGGeod()); + invalidatePosition(); serviceable = _vehicle_node.valid(); } diff --git a/src/Navaids/navrecord.hxx b/src/Navaids/navrecord.hxx index 8aa6fb1bd..0091ac651 100644 --- a/src/Navaids/navrecord.hxx +++ b/src/Navaids/navrecord.hxx @@ -36,6 +36,7 @@ const double FG_NAV_DEFAULT_RANGE = 50; // nm const double FG_LOC_DEFAULT_RANGE = 18; // nm const double FG_DME_DEFAULT_RANGE = 50; // nm +const double FG_TACAN_DEFAULT_RANGE = 250; // nm const double FG_NAV_MAX_RANGE = 300; // nm class FGNavRecord : public FGPositioned diff --git a/src/Navaids/positioned.cxx b/src/Navaids/positioned.cxx index 89d414755..73f9ff05e 100644 --- a/src/Navaids/positioned.cxx +++ b/src/Navaids/positioned.cxx @@ -67,13 +67,17 @@ static bool validateFilter(FGPositioned::Filter* filter) /////////////////////////////////////////////////////////////////////////////// -FGPositioned::FGPositioned(PositionedID aGuid, Type ty, const std::string& aIdent, const SGGeod& aPos) : +FGPositioned::FGPositioned( PositionedID aGuid, + Type ty, + const std::string& aIdent, + const SGGeod& aPos ): mGuid(aGuid), - mPosition(aPos), - mCart(SGVec3d::fromGeod(mPosition)), mType(ty), - mIdent(aIdent) -{ + mIdent(aIdent), + mPosition(aPos), + mCart(SGVec3d::fromGeod(mPosition)) +{ + } FGPositioned::~FGPositioned() @@ -353,12 +357,20 @@ FGPositioned::sortByRange(FGPositionedList& aResult, const SGGeod& aPos) } } +//------------------------------------------------------------------------------ void FGPositioned::modifyPosition(const SGGeod& newPos) { const_cast(mPosition) = newPos; const_cast(mCart) = SGVec3d::fromGeod(newPos); } +//------------------------------------------------------------------------------ +void FGPositioned::invalidatePosition() +{ + const_cast(mPosition) = SGGeod::fromDeg(999,999); + const_cast(mCart) = SGVec3d::zeros(); +} + //------------------------------------------------------------------------------ FGPositionedRef FGPositioned::loadByIdImpl(PositionedID id) { diff --git a/src/Navaids/positioned.hxx b/src/Navaids/positioned.hxx index b0059c89b..2d51e463a 100644 --- a/src/Navaids/positioned.hxx +++ b/src/Navaids/positioned.hxx @@ -276,6 +276,7 @@ protected: FGPositioned(PositionedID aGuid, Type ty, const std::string& aIdent, const SGGeod& aPos); void modifyPosition(const SGGeod& newPos); + void invalidatePosition(); static FGPositionedRef loadByIdImpl(PositionedID id);