]> git.mxchange.org Git - flightgear.git/commitdiff
TACAN: fix distance calculations and some other problems.
authorThomas Geymayer <tomgey@gmail.com>
Sun, 2 Mar 2014 15:52:00 +0000 (16:52 +0100)
committerThomas Geymayer <tomgey@gmail.com>
Sun, 2 Mar 2014 15:52:00 +0000 (16:52 +0100)
 - 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)

src/Instrumentation/tacan.cxx
src/Instrumentation/tacan.hxx
src/Navaids/NavDataCache.cxx
src/Navaids/navdb.cxx
src/Navaids/navrecord.cxx
src/Navaids/navrecord.hxx
src/Navaids/positioned.cxx
src/Navaids/positioned.hxx

index ca0320abbb38b3c880d053f7ae3753c126abf1e7..1a808e5b8e4fe725e41d8eab5572d0c819facf89 100644 (file)
  * 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;
index 92f57c7d348748c1d97d0bd6efc81f8869cb6059..fcbc737c840de59d33bed1d55e9fc7509974d671 100644 (file)
@@ -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);
index bbd399032c1b3654a8cafc3b3e18f0bceabc673b..17b982e5db310a241fe657b86a21f11c46cdd65d 100644 (file)
@@ -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
index 99453022a826c45185b2b48a032939adffd3ca1e..77a82c99b2898441583ed8262273e0bf830b135a 100644 (file)
@@ -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;
 }
index 37bd5a194aea4f83221831c42b0f4a7189283e8c..fabc9a0d08ffe4c6ab6129e200439daf30422b0d 100644 (file)
@@ -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();
 }
index 8aa6fb1bd98b36594b8be9845aa38f4375ea5f90..0091ac6518651e0b447fc4529926c02ecdfdb45d 100644 (file)
@@ -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 
index 89d41475583e0a8e87a353e53dd592033b8bc836..73f9ff05e88ad42fb1270b644cd15acab8657f43 100644 (file)
@@ -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<SGGeod&>(mPosition) = newPos;
   const_cast<SGVec3d&>(mCart) = SGVec3d::fromGeod(newPos);
 }
 
+//------------------------------------------------------------------------------
+void FGPositioned::invalidatePosition()
+{
+  const_cast<SGGeod&>(mPosition) = SGGeod::fromDeg(999,999);
+  const_cast<SGVec3d&>(mCart) = SGVec3d::zeros();
+}
+
 //------------------------------------------------------------------------------
 FGPositionedRef FGPositioned::loadByIdImpl(PositionedID id)
 {
index b0059c89bbba382f1e3f1fc6beab58af2b6c3944..2d51e463af38d9b7b98847999f9c2fcf66506ea3 100644 (file)
@@ -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);