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)
This commit is contained in:
parent
5151f7f5e0
commit
c7c9fd67aa
8 changed files with 64 additions and 32 deletions
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue