1
0
Fork 0

This set of changes impliments the following:

- FG now directly supports Robin's native nav database file format.
- His latest data now separates out dme, gs, loc, and marker beacon
  transmitters rather than lumping them all into a single "ILS" record.
- These new data structure changes prompted me to do some code restructuring
  so that internally these different types of navaids are all kept as
  separate lists and searched and handled separately.
- This structural change had a cascading affect on any code that
  references or uses the nav databases.  I've gone and "touched" a lot of
  nav related code in a lot of places.
- As an added bonus, the new data (and code) adds DME bias so these will
  all now read as they do in real life.

- Added Navaids/navdb.cxx and Navaids/navdb.hxx which provide a front
  end loaders for the nav data.
- Added Navaids/navrecord.hxx which is a new "generic" nav data record.
- Removed Navaids/ils.hxx, Navaids/ilslist.cxx, Navaids/ilslist.hxx,
  Navaids/mkrbeacons.cxx, and Navaids/mkrbeacons.hxx which are all now
  depricated.
This commit is contained in:
curt 2004-05-28 05:24:54 +00:00
parent b7acd97f2c
commit b2b33f7582
26 changed files with 831 additions and 1218 deletions

View file

@ -31,8 +31,6 @@
#include <simgear/math/sg_random.h>
#include <Aircraft/aircraft.hxx>
#include <Navaids/ilslist.hxx>
#include <Navaids/mkrbeacons.hxx>
#include <Navaids/navlist.hxx>
#include "dme.hxx"
@ -80,6 +78,7 @@ FGDME::FGDME() :
navcom2_freq(fgGetNode("/radios/nav[1]/frequencies/selected-mhz", true)),
need_update(true),
freq(0.0),
bias(0.0),
dist(0.0),
prev_dist(0.0),
spd(0.0),
@ -161,6 +160,11 @@ FGDME::update(double dt)
SGTimeStamp current_time;
station = Point3D( x, y, z );
dist = aircraft.distance3D( station ) * SG_METER_TO_NM;
cout << "dist = " << dist << endl;
dist -= bias;
cout << " bias = " << bias << endl;
cout << " dist = " << dist << endl;
current_time.stamp();
long dMs = (current_time - last_time) / 1000;
// Update every second
@ -218,33 +222,20 @@ void FGDME::search()
inrange = false;
}
FGILS *ils;
FGNav *nav;
FGNavRecord *dme
= globals->get_dmelist()->findByFreq( freq, lon, lat, elev );
if ( (ils = globals->get_ilslist()->findByFreq( freq, lon, lat, elev )) != NULL ) {
if ( ils->get_has_dme() ) {
if ( dme != NULL ) {
valid = true;
lon = ils->get_loclon();
lat = ils->get_loclat();
elev = ils->get_gselev();
lon = dme->get_lon();
lat = dme->get_lat();
elev = dme->get_elev_ft();
bias = dme->get_multiuse();
range = FG_ILS_DEFAULT_RANGE;
effective_range = kludgeRange(elev, elev, range);
x = ils->get_dme_x();
y = ils->get_dme_y();
z = ils->get_dme_z();
}
} else if ( (nav = globals->get_navlist()->findByFreq(freq, lon, lat, elev)) != NULL ) {
if (nav->get_has_dme()) {
valid = true;
lon = nav->get_lon();
lat = nav->get_lat();
elev = nav->get_elev_ft();
range = nav->get_range();
effective_range = kludgeRange(elev, elev, range);
x = nav->get_x();
y = nav->get_y();
z = nav->get_z();
}
x = dme->get_x();
y = dme->get_y();
z = dme->get_z();
} else {
valid = false;
dist = 0;

View file

@ -65,6 +65,7 @@ class FGDME : public SGSubsystem
double x;
double y;
double z;
double bias;
double dist;
double prev_dist;
double spd;

View file

@ -97,8 +97,8 @@ FGKR_87::FGKR_87() :
last_flt_et_btn(false),
set_rst_btn(false),
last_set_rst_btn(false),
freq(0.0),
stby_freq(0.0),
freq(0),
stby_freq(0),
needle_deg(0.0),
flight_timer(0.0),
elapsed_timer(0.0),
@ -255,9 +255,10 @@ void FGKR_87::update( double dt ) {
} else {
ant_mode = 0;
}
// cout << "ant_mode = " << ant_mode << endl;
if ( frq_btn && frq_btn != last_frq_btn && stby_mode == 0 ) {
double tmp = freq;
int tmp = freq;
freq = stby_freq;
stby_freq = tmp;
} else if ( frq_btn ) {
@ -286,7 +287,7 @@ void FGKR_87::update( double dt ) {
// cout << "tmp_timer = " << tmp_timer << endl;
if ( tmp_timer > 2.0 ) {
// button held depressed for 2 seconds
cout << "entering elapsed count down mode" << endl;
// cout << "entering elapsed count down mode" << endl;
timer_mode = 1;
count_mode = 2;
elapsed_timer = 0.0;
@ -342,6 +343,7 @@ void FGKR_87::update( double dt ) {
}
if ( valid ) {
// cout << "adf is valid" << endl;
// staightline distance
station = Point3D( x, y, z );
dist = aircraft.distance3D( station );
@ -367,6 +369,8 @@ void FGKR_87::update( double dt ) {
inrange = false;
}
// cout << "inrange = " << inrange << endl;
if ( inrange ) {
goal_needle_deg = heading
- fgGetDouble("/orientation/heading-deg");
@ -487,28 +491,28 @@ void FGKR_87::search() {
// ADF.
////////////////////////////////////////////////////////////////////////
FGNav *nav
= globals->get_navlist()->findByFreq(freq, acft_lon, acft_lat, acft_elev);
if ( nav != NULL ) {
FGNavRecord *adf
= globals->get_navlist()->findByFreq( freq, acft_lon, acft_lat,
acft_elev );
if ( adf != NULL ) {
char sfreq[128];
snprintf( sfreq, 10, "%.0f", freq );
snprintf( sfreq, 10, "%d", freq );
ident = sfreq;
ident += nav->get_ident();
ident += adf->get_ident();
// cout << "adf ident = " << ident << endl;
valid = true;
if ( last_ident != ident ) {
last_ident = ident;
trans_ident = nav->get_trans_ident();
stn_lon = nav->get_lon();
stn_lat = nav->get_lat();
stn_elev = nav->get_elev_ft();
range = nav->get_range();
trans_ident = adf->get_trans_ident();
stn_lon = adf->get_lon();
stn_lat = adf->get_lat();
stn_elev = adf->get_elev_ft();
range = adf->get_range();
effective_range = kludgeRange(stn_elev, acft_elev, range);
x = nav->get_x();
y = nav->get_y();
z = nav->get_z();
x = adf->get_x();
y = adf->get_y();
z = adf->get_z();
if ( globals->get_soundmgr()->exists( "adf-ident" ) ) {
globals->get_soundmgr()->remove( "adf-ident" );
@ -541,14 +545,14 @@ void FGKR_87::search() {
}
double FGKR_87::get_stby_freq() const {
int FGKR_87::get_stby_freq() const {
if ( stby_mode == 0 ) {
return stby_freq;
} else {
if ( timer_mode == 0 ) {
return flight_timer;
return (int)flight_timer;
} else {
return elapsed_timer;
return (int)elapsed_timer;
}
}
}

View file

@ -88,8 +88,8 @@ class FGKR_87 : public SGSubsystem
bool last_set_rst_btn; // 0 = normal, 1 = depressed
// outputs
double freq;
double stby_freq;
int freq;
int stby_freq;
double needle_deg;
double flight_timer;
double elapsed_timer;
@ -163,13 +163,13 @@ public:
inline void set_set_rst_btn( bool val ) { set_rst_btn = val; }
// outputs
inline double get_freq () const { return freq; }
inline void set_freq( double f ) {
inline int get_freq () const { return freq; }
inline void set_freq( int f ) {
freq = f;
need_update = true;
}
double get_stby_freq () const;
inline void set_stby_freq( double freq ) { stby_freq = freq; }
int get_stby_freq () const;
inline void set_stby_freq( int f ) { stby_freq = f; }
inline double get_needle_deg() const { return needle_deg; }
inline double get_flight_timer() const { return flight_timer; }
inline double get_elapsed_timer() const { return elapsed_timer; }

View file

@ -31,7 +31,7 @@
#include <simgear/math/sg_random.h>
#include <Aircraft/aircraft.hxx>
#include <Navaids/mkrbeacons.hxx>
#include <Navaids/navlist.hxx>
#include "marker_beacon.hxx"
@ -160,37 +160,94 @@ FGMarkerBeacon::update(double dt)
}
static bool check_beacon_range( double lon_rad, double lat_rad, double elev_m,
FGNavRecord *b )
{
Point3D aircraft = sgGeodToCart( Point3D(lon_rad, lat_rad, elev_m) );
Point3D station = Point3D( b->get_x(), b->get_y(), b->get_z() );
// cout << " aircraft = " << aircraft << " station = " << station
// << endl;
double d = aircraft.distance3Dsquared( station ); // meters^2
// cout << " distance = " << d << " ("
// << FG_ILS_DEFAULT_RANGE * SG_NM_TO_METER
// * FG_ILS_DEFAULT_RANGE * SG_NM_TO_METER
// << ")" << endl;
// cout << " range = " << sqrt(d) << endl;
// cout << "elev = " << elev * SG_METER_TO_FEET
// << " current->get_elev() = " << current->get_elev() << endl;
double elev_ft = elev_m * SG_METER_TO_FEET;
double delev = elev_ft - b->get_elev_ft();
// max range is the area under r = 2.4 * alt or r^2 = 4000^2 - alt^2
// whichever is smaller. The intersection point is 1538 ...
double maxrange2; // feet^2
if ( delev < 1538.0 ) {
maxrange2 = 2.4 * 2.4 * delev * delev;
} else if ( delev < 4000.0 ) {
maxrange2 = 4000 * 4000 - delev * delev;
} else {
maxrange2 = 0.0;
}
maxrange2 *= SG_FEET_TO_METER * SG_FEET_TO_METER; // convert to meter^2
// cout << "delev = " << delev << " maxrange = " << maxrange << endl;
// match up to twice the published range so we can model
// reduced signal strength
if ( d < maxrange2 ) {
return true;
} else {
return false;
}
}
// Update current nav/adf radio stations based on current postition
void FGMarkerBeacon::search()
{
static FGMkrBeacon::fgMkrBeacType last_beacon = FGMkrBeacon::NOBEACON;
static fgMkrBeacType last_beacon = NOBEACON;
double lon = lon_node->getDoubleValue() * SGD_DEGREES_TO_RADIANS;
double lat = lat_node->getDoubleValue() * SGD_DEGREES_TO_RADIANS;
double elev = alt_node->getDoubleValue() * SG_FEET_TO_METER;
double lon_rad = lon_node->getDoubleValue() * SGD_DEGREES_TO_RADIANS;
double lat_rad = lat_node->getDoubleValue() * SGD_DEGREES_TO_RADIANS;
double elev_m = alt_node->getDoubleValue() * SG_FEET_TO_METER;
////////////////////////////////////////////////////////////////////////
// Beacons.
////////////////////////////////////////////////////////////////////////
FGMkrBeacon::fgMkrBeacType beacon_type
= globals->get_beacons()->query( lon * SGD_RADIANS_TO_DEGREES,
lat * SGD_RADIANS_TO_DEGREES, elev );
// get closest marker beacon
FGNavRecord *b
= globals->get_mkrlist()->findClosest( lon_rad, lat_rad, elev_m );
// cout << "marker beacon = " << b << " (" << b->get_type() << ")" << endl;
fgMkrBeacType beacon_type = NOBEACON;
bool inrange = false;
if ( b != NULL ) {
if ( b->get_type() == 7 ) {
beacon_type = OUTER;
} else if ( b->get_type() == 8 ) {
beacon_type = MIDDLE;
} else if ( b->get_type() == 9 ) {
beacon_type = INNER;
}
inrange = check_beacon_range( lon_rad, lat_rad, elev_m, b );
// cout << " inrange = " << inrange << endl;
}
outer_marker = middle_marker = inner_marker = false;
if ( beacon_type == FGMkrBeacon::NOBEACON
|| !has_power() || !serviceable->getBoolValue() )
if ( b == NULL || !inrange || !has_power() || !serviceable->getBoolValue() )
{
// cout << "no marker" << endl;
beacon_type = FGMkrBeacon::NOBEACON;
globals->get_soundmgr()->stop( "outer-marker" );
globals->get_soundmgr()->stop( "middle-marker" );
globals->get_soundmgr()->stop( "inner-marker" );
} else if ( beacon_type == FGMkrBeacon::OUTER ) {
} else if ( beacon_type == OUTER ) {
outer_marker = true;
// cout << "OUTER MARKER" << endl;
if ( last_beacon != FGMkrBeacon::OUTER ) {
if ( last_beacon != OUTER ) {
if ( ! globals->get_soundmgr()->exists( "outer-marker" ) ) {
SGSoundSample *sound = beacon.get_outer();
sound->set_volume( 0.3 );
@ -204,10 +261,10 @@ void FGMarkerBeacon::search()
} else {
globals->get_soundmgr()->stop( "outer-marker" );
}
} else if ( beacon_type == FGMkrBeacon::MIDDLE ) {
} else if ( beacon_type == MIDDLE ) {
middle_marker = true;
// cout << "MIDDLE MARKER" << endl;
if ( last_beacon != FGMkrBeacon::MIDDLE ) {
if ( last_beacon != MIDDLE ) {
if ( ! globals->get_soundmgr()->exists( "middle-marker" ) ) {
SGSoundSample *sound = beacon.get_middle();
sound->set_volume( 0.3 );
@ -221,10 +278,10 @@ void FGMarkerBeacon::search()
} else {
globals->get_soundmgr()->stop( "middle-marker" );
}
} else if ( beacon_type == FGMkrBeacon::INNER ) {
} else if ( beacon_type == INNER ) {
inner_marker = true;
// cout << "INNER MARKER" << endl;
if ( last_beacon != FGMkrBeacon::INNER ) {
if ( last_beacon != INNER ) {
if ( ! globals->get_soundmgr()->exists( "inner-marker" ) ) {
SGSoundSample *sound = beacon.get_inner();
sound->set_volume( 0.3 );
@ -239,5 +296,10 @@ void FGMarkerBeacon::search()
globals->get_soundmgr()->stop( "inner-marker" );
}
}
if ( inrange ) {
last_beacon = beacon_type;
} else {
last_beacon = NOBEACON;
}
}

View file

@ -66,6 +66,13 @@ class FGMarkerBeacon : public SGSubsystem
public:
enum fgMkrBeacType {
NOBEACON = 0,
INNER,
MIDDLE,
OUTER
};
FGMarkerBeacon();
~FGMarkerBeacon();

View file

@ -423,10 +423,11 @@ FGNavCom::update(double dt)
while ( offset < -180.0 ) { offset += 360.0; }
while ( offset > 180.0 ) { offset -= 360.0; }
// cout << "ils offset = " << offset << endl;
nav_effective_range = adjustILSRange(nav_elev, elev, offset,
nav_effective_range
= adjustILSRange( nav_elev, elev, offset,
nav_loc_dist * SG_METER_TO_NM );
} else {
nav_effective_range = adjustNavRange(nav_elev, elev, nav_range);
nav_effective_range = adjustNavRange( nav_elev, elev, nav_range );
}
// cout << "nav range = " << nav_effective_range
// << " (" << nav_range << ")" << endl;
@ -597,58 +598,73 @@ void FGNavCom::search()
double lat = lat_node->getDoubleValue() * SGD_DEGREES_TO_RADIANS;
double elev = alt_node->getDoubleValue() * SG_FEET_TO_METER;
FGILS *ils;
FGNav *nav;
FGNavRecord *nav = NULL;
FGNavRecord *loc = NULL;
FGNavRecord *dme = NULL;
FGNavRecord *gs = NULL;
////////////////////////////////////////////////////////////////////////
// Nav.
////////////////////////////////////////////////////////////////////////
if ( (ils = globals->get_ilslist()->findByFreq(nav_freq, lon, lat, elev)) != NULL ) {
nav_id = ils->get_locident();
nav = globals->get_navlist()->findByFreq(nav_freq, lon, lat, elev);
dme = globals->get_dmelist()->findByFreq(nav_freq, lon, lat, elev);
if ( nav == NULL ) {
loc = globals->get_loclist()->findByFreq(nav_freq, lon, lat, elev);
gs = globals->get_gslist()->findByFreq(nav_freq, lon, lat, elev);
}
if ( loc != NULL ) {
nav_id = loc->get_ident();
nav_valid = true;
if ( last_nav_id != nav_id || last_nav_vor ) {
nav_trans_ident = ils->get_trans_ident();
nav_trans_ident = loc->get_trans_ident();
last_nav_id = nav_id;
last_nav_vor = false;
nav_loc = true;
nav_has_dme = ils->get_has_dme();
nav_has_gs = ils->get_has_gs();
nav_loclon = ils->get_loclon();
nav_loclat = ils->get_loclat();
nav_gslon = ils->get_gslon();
nav_gslat = ils->get_gslat();
nav_elev = ils->get_gselev();
nav_twist = 0;
nav_range = FG_ILS_DEFAULT_RANGE;
nav_effective_range = nav_range;
nav_target_gs = ils->get_gsangle();
nav_target_radial = ils->get_locheading();
while ( nav_target_radial < 0.0 ) { nav_target_radial += 360.0; }
while ( nav_target_radial > 360.0 ) { nav_target_radial -= 360.0; }
nav_x = ils->get_x();
nav_y = ils->get_y();
nav_z = ils->get_z();
nav_gs_x = ils->get_gs_x();
nav_gs_y = ils->get_gs_y();
nav_gs_z = ils->get_gs_z();
nav_has_dme = (dme != NULL);
nav_has_gs = (gs != NULL);
if ( nav_has_gs ) {
nav_gslon = gs->get_lon();
nav_gslat = gs->get_lat();
int tmp = (int)(gs->get_multiuse() / 1000.0);
nav_target_gs = (double)tmp / 100.0;
nav_gs_x = gs->get_x();
nav_gs_y = gs->get_y();
nav_gs_z = gs->get_z();
// derive GS baseline
double tlon, tlat, taz;
geo_direct_wgs_84 ( 0.0, nav_gslat, nav_gslon, nav_target_radial + 90,
geo_direct_wgs_84 ( 0.0, nav_gslat, nav_gslon,
nav_target_radial + 90,
100.0, &tlat, &tlon, &taz );
// cout << nav_gslon << "," << nav_gslat << " "
// << tlon << "," << tlat << " (" << nav_elev << ")" << endl;
// << tlon << "," << tlat << " (" << nav_elev << ")"
// << endl;
Point3D p1 = sgGeodToCart( Point3D(tlon*SGD_DEGREES_TO_RADIANS,
tlat*SGD_DEGREES_TO_RADIANS,
nav_elev*SG_FEET_TO_METER) );
// cout << nav_gs_x << "," << nav_gs_y << "," << nav_gs_z << endl;
// cout << nav_gs_x << "," << nav_gs_y << "," << nav_gs_z
// << endl;
// cout << p1 << endl;
sgdSetVec3( gs_base_vec,
p1.x()-nav_gs_x, p1.y()-nav_gs_y, p1.z()-nav_gs_z );
// cout << gs_base_vec[0] << "," << gs_base_vec[1] << ","
// << gs_base_vec[2] << endl;
}
nav_loclon = loc->get_lon();
nav_loclat = loc->get_lat();
nav_elev = loc->get_elev_ft();
nav_twist = 0;
nav_range = FG_LOC_DEFAULT_RANGE;
nav_effective_range = nav_range;
nav_target_radial = loc->get_multiuse();
while ( nav_target_radial < 0.0 ) { nav_target_radial += 360.0; }
while ( nav_target_radial > 360.0 ) { nav_target_radial -= 360.0; }
nav_x = loc->get_x();
nav_y = loc->get_y();
nav_z = loc->get_z();
if ( globals->get_soundmgr()->exists( nav_fx_name ) ) {
globals->get_soundmgr()->remove( nav_fx_name );
@ -675,23 +691,23 @@ void FGNavCom::search()
// << " current time = "
// << globals->get_time_params()->get_cur_time() << endl;
// cout << "Found an ils station in range" << endl;
// cout << " id = " << ils->get_locident() << endl;
// cout << "Found an loc station in range" << endl;
// cout << " id = " << loc->get_locident() << endl;
}
} else if ( (nav = globals->get_navlist()->findByFreq(nav_freq, lon, lat, elev)) != NULL ) {
} else if ( nav != NULL ) {
nav_id = nav->get_ident();
nav_valid = (nav->get_type() == 'V');
nav_valid = true;
if ( last_nav_id != nav_id || !last_nav_vor ) {
last_nav_id = nav_id;
last_nav_vor = true;
nav_trans_ident = nav->get_trans_ident();
nav_loc = false;
nav_has_dme = nav->get_has_dme();
nav_has_dme = (dme != NULL);
nav_has_gs = false;
nav_loclon = nav->get_lon();
nav_loclat = nav->get_lat();
nav_elev = nav->get_elev_ft();
nav_twist = nav->get_magvar();
nav_twist = nav->get_multiuse();
nav_range = nav->get_range();
nav_effective_range = adjustNavRange(nav_elev, elev, nav_range);
nav_target_gs = 0.0;

View file

@ -163,22 +163,20 @@ ADF::search (double frequency_khz, double longitude_rad,
_time_before_search_sec = 1.0;
// try the ILS list first
FGNav *nav =
FGNavRecord *nav =
globals->get_navlist()->findByFreq(frequency_khz, longitude_rad,
latitude_rad, altitude_m);
if (nav !=0) {
_transmitter_valid = true;
_transmitter_valid = (nav != NULL);
if ( _transmitter_valid ) {
ident = nav->get_trans_ident();
if (ident !=_last_ident) {
if ( ident != _last_ident ) {
_transmitter_lon_deg = nav->get_lon();
_transmitter_lat_deg = nav->get_lat();
_transmitter = Point3D(nav->get_x(), nav->get_y(), nav->get_z());
_transmitter_elevation_ft = nav->get_elev_ft();
_transmitter_range_nm = nav->get_range();
}
} else {
_transmitter_valid = false;
}
_last_ident = ident;
_ident_node->setStringValue(ident.c_str());

View file

@ -43,7 +43,8 @@ DME::DME ()
_time_before_search_sec(0),
_transmitter_valid(false),
_transmitter_elevation_ft(0),
_transmitter_range_nm(0)
_transmitter_range_nm(0),
_transmitter_bias(0.0)
{
}
@ -128,7 +129,7 @@ DME::update (double delta_time_sec)
_last_distance_nm = distance_nm;
_in_range_node->setBoolValue(true);
_distance_node->setDoubleValue(distance_nm);
_distance_node->setDoubleValue(distance_nm - _transmitter_bias);
_speed_node->setDoubleValue(speed_kt);
_time_node->setDoubleValue(distance_nm/speed_kt*60.0);
@ -149,36 +150,18 @@ DME::search (double frequency_mhz, double longitude_rad,
_time_before_search_sec = 1.0;
// try the ILS list first
FGILS *ils = globals->get_ilslist()->findByFreq(frequency_mhz,
longitude_rad,
latitude_rad,
altitude_m);
if (ils !=0 && ils->get_has_dme()) {
_transmitter_valid = true;
_transmitter = Point3D(ils->get_dme_x(),
ils->get_dme_y(),
ils->get_dme_z());
_transmitter_elevation_ft = ils->get_gselev() * SG_METER_TO_FEET;
_transmitter_range_nm = 50; // arbitrary
return;
}
FGNavRecord *dme
= globals->get_dmelist()->findByFreq( frequency_mhz, longitude_rad,
latitude_rad, altitude_m);
// try the VORs next
FGNav *nav = globals->get_navlist()->findByFreq(frequency_mhz,
longitude_rad,
latitude_rad,
altitude_m);
if (nav != 0 && nav->get_has_dme()) {
_transmitter_valid = true;
_transmitter = Point3D(nav->get_x(),
nav->get_y(),
nav->get_z());
_transmitter_elevation_ft = nav->get_elev_ft();
_transmitter_range_nm = nav->get_range(); // fixme
return;
}
_transmitter_valid = (dme != NULL);
_transmitter_valid = false;
if ( _transmitter_valid ) {
_transmitter = Point3D(dme->get_x(), dme->get_y(), dme->get_z());
_transmitter_elevation_ft = dme->get_elev_ft();
_transmitter_range_nm = dme->get_range();
_transmitter_bias = dme->get_multiuse();
}
}
// end of dme.cxx

View file

@ -73,6 +73,7 @@ private:
Point3D _transmitter;
double _transmitter_elevation_ft;
double _transmitter_range_nm;
double _transmitter_bias;
};

View file

@ -326,12 +326,11 @@ GPS::update (double delta_time_sec)
}
}
else if (waypont_type == "nav") {
FGNav *n;
if ( (n = globals->get_navlist()->findByIdent(wp0_ID.c_str(),
FGNavRecord *n
= globals->get_navlist()->findByIdent(wp0_ID.c_str(),
longitude_deg,
latitude_deg))
!= NULL)
{
latitude_deg);
if ( n != NULL ) {
//cout << "Nav found" << endl;
wp0_longitude_deg = n->get_lon();
wp0_latitude_deg = n->get_lat();
@ -366,12 +365,11 @@ GPS::update (double delta_time_sec)
}
}
else if (waypont_type == "nav") {
FGNav * n;
if ( (n = globals->get_navlist()->findByIdent(wp1_ID.c_str(),
FGNavRecord *n
= globals->get_navlist()->findByIdent(wp1_ID.c_str(),
longitude_deg,
latitude_deg))
!= NULL)
{
latitude_deg);
if ( n != NULL ) {
//cout << "Nav found" << endl;
wp1_longitude_deg = n->get_lon();
wp1_latitude_deg = n->get_lat();

View file

@ -98,9 +98,7 @@
#include <Instrumentation/instrument_mgr.hxx>
#include <Model/acmodel.hxx>
#include <AIModel/AIManager.hxx>
#include <Navaids/fixlist.hxx>
#include <Navaids/ilslist.hxx>
#include <Navaids/mkrbeacons.hxx>
#include <Navaids/navdb.hxx>
#include <Navaids/navlist.hxx>
#include <Replay/replay.hxx>
#include <Scenery/scenery.hxx>
@ -906,7 +904,8 @@ static void fgSetDistOrAltFromGlideSlope() {
// Set current_options lon/lat given an airport id and heading (degrees)
static bool fgSetPosFromNAV( const string& id, const double& freq ) {
FGNav *nav = globals->get_navlist()->findByIdentAndFreq( id.c_str(), freq );
FGNavRecord *nav
= globals->get_navlist()->findByIdentAndFreq( id.c_str(), freq );
// set initial position from runway and heading
if ( nav != NULL ) {
@ -1046,29 +1045,27 @@ fgInitNav ()
FGRunwayList *runways = new FGRunwayList( p_runway.str() );
globals->set_runways( runways );
SG_LOG(SG_GENERAL, SG_INFO, "Loading Navaids");
SG_LOG(SG_GENERAL, SG_INFO, " VOR/NDB");
FGNavList *navlist = new FGNavList;
SGPath p_nav( globals->get_fg_root() );
p_nav.append( "Navaids/default.nav" );
navlist->init( p_nav );
globals->set_navlist( navlist );
FGNavList *loclist = new FGNavList;
FGNavList *gslist = new FGNavList;
FGNavList *dmelist = new FGNavList;
FGNavList *mkrlist = new FGNavList;
SG_LOG(SG_GENERAL, SG_INFO, " ILS and Marker Beacons");
FGMarkerBeacons *beacons = new FGMarkerBeacons;
beacons->init();
globals->set_beacons( beacons );
FGILSList *ilslist = new FGILSList;
SGPath p_ils( globals->get_fg_root() );
p_ils.append( "Navaids/default.ils" );
ilslist->init( p_ils );
globals->set_ilslist( ilslist );
globals->set_navlist( navlist );
globals->set_loclist( loclist );
globals->set_gslist( gslist );
globals->set_dmelist( dmelist );
globals->set_mkrlist( mkrlist );
if ( !fgNavDBInit( navlist, loclist, gslist, dmelist, mkrlist ) ) {
SG_LOG( SG_GENERAL, SG_ALERT,
"Problems loading one or more navigational database" );
}
SG_LOG(SG_GENERAL, SG_INFO, " Fixes");
FGFixList *fixlist = new FGFixList;
SGPath p_fix( globals->get_fg_root() );
p_fix.append( "Navaids/fix.dat" );
FGFixList *fixlist = new FGFixList;
fixlist->init( p_fix );
globals->set_fixlist( fixlist );

View file

@ -77,9 +77,11 @@ FGGlobals::FGGlobals() :
tile_mgr( NULL ),
io( new FGIO ),
navlist( NULL ),
fixlist( NULL ),
ilslist( NULL ),
beacons( NULL )
loclist( NULL ),
gslist( NULL ),
dmelist( NULL ),
mkrlist( NULL ),
fixlist( NULL )
{
}

View file

@ -72,8 +72,6 @@ class FGControls;
class FGIO;
class FGNavList;
class FGFixList;
class FGILSList;
class FGMarkerBeacons;
class FGLight;
class FGModelMgr;
class FGRouteMgr;
@ -197,9 +195,11 @@ private:
// Navigational Aids
FGNavList *navlist;
FGNavList *loclist;
FGNavList *gslist;
FGNavList *dmelist;
FGNavList *mkrlist;
FGFixList *fixlist;
FGILSList *ilslist;
FGMarkerBeacons *beacons;
#ifdef FG_MPLAYER_AS
//Mulitplayer managers
@ -359,17 +359,18 @@ public:
inline FGNavList *get_navlist() const { return navlist; }
inline void set_navlist( FGNavList *n ) { navlist = n; }
inline FGNavList *get_loclist() const { return loclist; }
inline void set_loclist( FGNavList *n ) { loclist = n; }
inline FGNavList *get_gslist() const { return gslist; }
inline void set_gslist( FGNavList *n ) { gslist = n; }
inline FGNavList *get_dmelist() const { return dmelist; }
inline void set_dmelist( FGNavList *n ) { dmelist = n; }
inline FGNavList *get_mkrlist() const { return mkrlist; }
inline void set_mkrlist( FGNavList *n ) { mkrlist = n; }
inline FGFixList *get_fixlist() const { return fixlist; }
inline void set_fixlist( FGFixList *f ) { fixlist = f; }
inline FGILSList *get_ilslist() const { return ilslist; }
inline void set_ilslist( FGILSList *i ) { ilslist = i; }
inline FGMarkerBeacons *get_beacons() const { return beacons; }
inline void set_beacons( FGMarkerBeacons *b ) { beacons = b; }
/**
* Save the current state as the initial state.
*/

View file

@ -3,12 +3,14 @@ noinst_LIBRARIES = libNavaids.a
# noinst_PROGRAMS = testnavs
libNavaids_a_SOURCES = \
navdb.hxx navdb.cxx \
fix.hxx fixlist.hxx fixlist.cxx \
ils.hxx ilslist.hxx ilslist.cxx \
mkrbeacons.hxx mkrbeacons.cxx \
nav.hxx navlist.hxx navlist.cxx \
navrecord.hxx
# ils.hxx ilslist.hxx ilslist.cxx \
# mkrbeacons.hxx mkrbeacons.cxx \
# testnavs_SOURCES = testnavs.cxx
# testnavs_LDADD = \
# libNavaids.a \

View file

@ -1,230 +0,0 @@
// ils.hxx -- navaid class
//
// Written by Curtis Olson, started April 2000.
//
// Copyright (C) 2000 Curtis L. Olson - curt@flightgear.org
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// $Id$
#ifndef _FG_ILS_HXX
#define _FG_ILS_HXX
#include <simgear/compiler.h>
#include <simgear/constants.h>
#include <simgear/math/sg_geodesy.hxx>
#include <simgear/misc/sgstream.hxx>
#ifdef SG_HAVE_STD_INCLUDES
# include <istream>
#elif defined( __BORLANDC__ ) || (__APPLE__)
# include <iostream>
#else
# include <istream.h>
#endif
SG_USING_STD(istream);
#define FG_ILS_DEFAULT_RANGE 18
class FGILS {
char ilstype;
char ilstypename[6];
char aptcode[5];
char rwyno[4];
int locfreq;
char locident[5]; // official ident
double locheading;
double loclat;
double loclon;
double x, y, z;
bool has_gs;
double gselev;
double gsangle;
double gslat;
double gslon;
double gs_x, gs_y, gs_z;
bool has_dme;
double dmelat;
double dmelon;
double dme_x, dme_y, dme_z;
double omlat;
double omlon;
double mmlat;
double mmlon;
double imlat;
double imlon;
// for failure modeling
string trans_ident; // transmitted ident
bool loc_failed; // localizer failed?
bool gs_failed; // glide slope failed?
bool dme_failed; // dme failed?
public:
inline FGILS(void);
inline ~FGILS(void) {}
inline char get_ilstype() const { return ilstype; }
inline char *get_ilstypename() { return ilstypename; }
inline char *get_aptcode() { return aptcode; }
inline char *get_rwyno() { return rwyno; }
inline int get_locfreq() const { return locfreq; }
inline char *get_locident() { return locident; }
inline string get_trans_ident() { return trans_ident; }
inline double get_locheading() const { return locheading; }
inline double get_loclat() const { return loclat; }
inline double get_loclon() const { return loclon; }
inline double get_x() const { return x; }
inline double get_y() const { return y; }
inline double get_z() const { return z; }
inline bool get_has_gs() const { return has_gs; }
inline double get_gselev() const { return gselev; }
inline double get_gsangle() const { return gsangle; }
inline double get_gslat() const { return gslat; }
inline double get_gslon() const { return gslon; }
inline double get_gs_x() const { return gs_x; }
inline double get_gs_y() const { return gs_y; }
inline double get_gs_z() const { return gs_z; }
inline bool get_has_dme() const { return has_dme; }
inline double get_dmelat() const { return dmelat; }
inline double get_dmelon() const { return dmelon; }
inline double get_dme_x() const { return dme_x; }
inline double get_dme_y() const { return dme_y; }
inline double get_dme_z() const { return dme_z; }
inline double get_omlat() const { return omlat; }
inline double get_omlon() const { return omlon; }
inline double get_mmlat() const { return mmlat; }
inline double get_mmlon() const { return mmlon; }
inline double get_imlat() const { return imlat; }
inline double get_imlon() const { return imlon; }
friend istream& operator>> ( istream&, FGILS& );
};
inline
FGILS::FGILS(void)
: ilstype(0),
locfreq(0),
locheading(0.0),
loclat(0.0),
loclon(0.0),
x(0.0), y(0.0), z(0.0),
has_gs(false),
gselev(0.0),
gsangle(0.0),
gslat(0.0),
gslon(0.0),
gs_x(0.0), gs_y(0.0), gs_z(0.0),
has_dme(false),
dmelat(0.0),
dmelon(0.0),
dme_x(0.0), dme_y(0.0), dme_z(0.0),
omlat(0.0),
omlon(0.0),
mmlat(0.0),
mmlon(0.0),
imlat(0.0),
imlon(0.0),
trans_ident(""),
loc_failed(false),
gs_failed(false),
dme_failed(false)
{
ilstypename[0] = '\0';
aptcode[0] = '\0';
rwyno[0] = '\0';
locident[0] = '\0';
}
inline istream&
operator >> ( istream& in, FGILS& i )
{
double f;
in >> i.ilstype;
if ( i.ilstype == '[' )
return in;
in >> i.ilstypename >> i.aptcode >> i.rwyno
>> f >> i.locident >> i.locheading >> i.loclat >> i.loclon
>> i.gselev >> i.gsangle >> i.gslat >> i.gslon
>> i.dmelat >> i.dmelon
>> i.omlat >> i.omlon
>> i.mmlat >> i.mmlon
>> i.imlat >> i.imlon;
i.locfreq = (int)(f*100.0 + 0.5);
// generate cartesian coordinates
Point3D geod, cart;
geod = Point3D( i.loclon * SGD_DEGREES_TO_RADIANS,
i.loclat * SGD_DEGREES_TO_RADIANS,
i.gselev * SG_FEET_TO_METER );
cart = sgGeodToCart( geod );
i.x = cart.x();
i.y = cart.y();
i.z = cart.z();
if ( i.gslon < SG_EPSILON && i.gslat < SG_EPSILON ) {
i.has_gs = false;
} else {
i.has_gs = true;
geod = Point3D( i.gslon * SGD_DEGREES_TO_RADIANS,
i.gslat * SGD_DEGREES_TO_RADIANS,
i.gselev * SG_FEET_TO_METER );
cart = sgGeodToCart( geod );
i.gs_x = cart.x();
i.gs_y = cart.y();
i.gs_z = cart.z();
// cout << "gs = " << cart << endl;
}
if ( i.dmelon < SG_EPSILON && i.dmelat < SG_EPSILON ) {
i.has_dme = false;
} else {
i.has_dme = true;
geod = Point3D( i.dmelon * SGD_DEGREES_TO_RADIANS,
i.dmelat * SGD_DEGREES_TO_RADIANS,
i.gselev * SG_FEET_TO_METER );
cart = sgGeodToCart( geod );
i.dme_x = cart.x();
i.dme_y = cart.y();
i.dme_z = cart.z();
// cout << "dme = " << cart << endl;
}
i.trans_ident = "I";
i.trans_ident += i.locident;
i.loc_failed = i.gs_failed = i.dme_failed = false;
// return in >> skipeol;
return in;
}
#endif // _FG_ILS_HXX

View file

@ -1,194 +0,0 @@
// ilslist.cxx -- ils management class
//
// Written by Curtis Olson, started April 2000.
//
// Copyright (C) 2000 Curtis L. Olson - curt@flightgear.org
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// $Id$
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <simgear/debug/logstream.hxx>
#include <simgear/misc/sgstream.hxx>
#include <simgear/math/sg_geodesy.hxx>
#include <Main/globals.hxx>
#include "mkrbeacons.hxx"
#include "ilslist.hxx"
FGILSList *current_ilslist;
// Constructor
FGILSList::FGILSList( void ) {
}
// Destructor
FGILSList::~FGILSList( void ) {
}
// load the navaids and build the map
bool FGILSList::init( SGPath path ) {
ilslist.erase( ilslist.begin(), ilslist.end() );
sg_gzifstream in( path.str() );
if ( !in.is_open() ) {
SG_LOG( SG_GENERAL, SG_ALERT, "Cannot open file: " << path.str() );
exit(-1);
}
// read in each line of the file
in >> skipeol;
in >> skipcomment;
// double min = 1000000.0;
// double max = 0.0;
#ifdef __MWERKS__
char c = 0;
while ( in.get(c) && c != '\0' ) {
in.putback(c);
#else
while ( ! in.eof() ) {
#endif
FGILS *ils = new FGILS;
in >> (*ils);
if ( ils->get_ilstype() == '[' ) {
break;
}
/* cout << "typename = " << ils.get_ilstypename() << endl;
cout << " aptcode = " << ils.get_aptcode() << endl;
cout << " twyno = " << ils.get_rwyno() << endl;
cout << " locfreq = " << ils.get_locfreq() << endl;
cout << " locident = " << ils.get_locident() << endl << endl; */
ilslist[ils->get_locfreq()].push_back(ils);
in >> skipcomment;
/* if ( ils.get_locfreq() < min ) {
min = ils.get_locfreq();
}
if ( ils.get_locfreq() > max ) {
max = ils.get_locfreq();
} */
// update the marker beacon list
if ( fabs(ils->get_omlon()) > SG_EPSILON ||
fabs(ils->get_omlat()) > SG_EPSILON ) {
globals->get_beacons()->add( ils->get_omlon(), ils->get_omlat(),
ils->get_gselev(),
FGMkrBeacon::OUTER );
}
if ( fabs(ils->get_mmlon()) > SG_EPSILON ||
fabs(ils->get_mmlat()) > SG_EPSILON ) {
globals->get_beacons()->add( ils->get_mmlon(), ils->get_mmlat(),
ils->get_gselev(),
FGMkrBeacon::MIDDLE );
}
if ( fabs(ils->get_imlon()) > SG_EPSILON ||
fabs(ils->get_imlat()) > SG_EPSILON ) {
globals->get_beacons()->add( ils->get_imlon(), ils->get_imlat(),
ils->get_gselev(),
FGMkrBeacon::INNER );
}
}
// cout << "min freq = " << min << endl;
// cout << "max freq = " << max << endl;
return true;
}
// Query the database for the specified frequency. It is assumed that
// there will be multiple stations with matching frequencies so a
// position must be specified. Lon and lat are in degrees, elev is in
// meters.
FGILS *FGILSList::findByFreq( double freq,
double lon, double lat, double elev )
{
FGILS *ils = NULL;
ils_list_type stations = ilslist[(int)(freq*100.0 + 0.5)];
double best_angle = 362.0;
// double az1, az2, s;
Point3D aircraft = sgGeodToCart( Point3D(lon, lat, elev) );
Point3D station;
double d2;
for ( unsigned int i = 0; i < stations.size(); ++i ) {
// cout << " testing " << current->get_locident() << endl;
station = Point3D(stations[i]->get_x(),
stations[i]->get_y(),
stations[i]->get_z());
// cout << " aircraft = " << aircraft << " station = " << station
// << endl;
d2 = aircraft.distance3Dsquared( station );
// cout << " distance = " << d << " ("
// << FG_ILS_DEFAULT_RANGE * SG_NM_TO_METER
// * FG_ILS_DEFAULT_RANGE * SG_NM_TO_METER
// << ")" << endl;
// cout << " dist = " << s << endl;
// match up to twice the published range so we can model
// reduced signal strength. The assumption is that there will
// be maximum of two possbile stations of a particular
// frequency in range. If two exist, one will be associated
// with each end of the runway. In this case, pick the
// station pointing most directly at us.
if ( d2 < (2* FG_ILS_DEFAULT_RANGE * SG_NM_TO_METER
* 2 * FG_ILS_DEFAULT_RANGE * SG_NM_TO_METER) ) {
// Get our bearing from this station.
double reciprocal_bearing, dummy;
double a_lat_deg = lat * SGD_RADIANS_TO_DEGREES;
double a_lon_deg = lon * SGD_RADIANS_TO_DEGREES;
// Locator beam direction
double s_ils_deg = stations[i]->get_locheading() - 180.0;
if ( s_ils_deg < 0.0 ) { s_ils_deg += 360.0; }
double angle_to_beam_deg;
// printf("**ALI geting geo_inverse_wgs_84 with elev = %.2f, a.lat = %.2f, a.lon = %.2f,
// s.lat = %.2f, s.lon = %.2f\n", elev,a_lat_deg,a_lon_deg,stations[i]->get_loclat(),stations[i]->get_loclon());
geo_inverse_wgs_84( elev, stations[i]->get_loclat(),
stations[i]->get_loclon(), a_lat_deg, a_lon_deg,
&reciprocal_bearing, &dummy, &dummy );
angle_to_beam_deg = fabs(reciprocal_bearing - s_ils_deg);
if ( angle_to_beam_deg <= best_angle ) {
ils = stations[i];
best_angle = angle_to_beam_deg;
}
}
}
return ils;
}

View file

@ -1,75 +0,0 @@
// ilslist.hxx -- ils management class
//
// Written by Curtis Olson, started April 2000.
//
// Copyright (C) 2000 Curtis L. Olson - curt@flightgear.org
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// $Id$
#ifndef _FG_ILSLIST_HXX
#define _FG_ILSLIST_HXX
#include <simgear/compiler.h>
#include <simgear/misc/sg_path.hxx>
#include <map>
#include <vector>
#include "ils.hxx"
SG_USING_STD(map);
SG_USING_STD(vector);
class FGILSList {
// convenience types
typedef vector < FGILS* > ils_list_type;
typedef ils_list_type::iterator ils_list_iterator;
typedef ils_list_type::const_iterator ils_list_const_iterator;
// typedef map < int, ils_list_type, less<int> > ils_map_type;
typedef map < int, ils_list_type > ils_map_type;
typedef ils_map_type::iterator ils_map_iterator;
typedef ils_map_type::const_iterator ils_map_const_iterator;
ils_map_type ilslist;
public:
FGILSList();
~FGILSList();
// load the navaids and build the map
bool init( SGPath path );
// query the database for the specified frequency, lon and lat are
// in degrees, elev is in meters
// bool query( double lon, double lat, double elev, double freq, FGILS *i );
// Query the database for the specified frequency. It is assumed
// that there will be multiple stations with matching frequencies
// so a position must be specified. Lon and lat are in degrees,
// elev is in meters.
FGILS *findByFreq( double freq, double lon, double lat, double elev );
};
#endif // _FG_ILSLIST_HXX

View file

@ -1,222 +0,0 @@
// mkrbeacons.cxx -- marker beacon management class
//
// Written by Curtis Olson, started March 2001.
//
// Copyright (C) 2001 Curtis L. Olson - curt@flightgear.org
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// $Id$
#include "mkrbeacons.hxx"
// constructor
FGMkrBeacon::FGMkrBeacon() {
FGMkrBeacon( 0, 0, 0, NOBEACON );
}
FGMkrBeacon::FGMkrBeacon( double _lon, double _lat, double _elev,
fgMkrBeacType _type ) {
lon = _lon;
lat = _lat;
elev = _elev;
type = _type;
Point3D pos = sgGeodToCart(Point3D(lon * SGD_DEGREES_TO_RADIANS, lat * SGD_DEGREES_TO_RADIANS, 0));
// cout << "pos = " << pos << endl;
x = pos.x();
y = pos.y();
z = pos.z();
}
// destructor
FGMkrBeacon::~FGMkrBeacon() {
}
// constructor
FGMarkerBeacons::FGMarkerBeacons() {
}
// destructor
FGMarkerBeacons::~FGMarkerBeacons() {
}
// initialize the structures
bool FGMarkerBeacons::init() {
// erase the beacon map
beacon_map.clear();
return true;
}
// real add a marker beacon
bool FGMarkerBeacons::real_add( const int master_index, const FGMkrBeacon& b ) {
// cout << "Master index = " << master_index << endl;
beacon_map[master_index].push_back( b );
return true;
}
// front end for add a marker beacon
bool FGMarkerBeacons::add( double lon, double lat, double elev,
FGMkrBeacon::fgMkrBeacType type ) {
double diff;
int lonidx = (int)lon;
diff = lon - (double)lonidx;
if ( (lon < 0.0) && (fabs(diff) > SG_EPSILON) ) {
lonidx -= 1;
}
double lonfrac = lon - (double)lonidx;
lonidx += 180;
int latidx = (int)lat;
diff = lat - (double)latidx;
if ( (lat < 0.0) && (fabs(diff) > SG_EPSILON) ) {
latidx -= 1;
}
double latfrac = lat - (double)latidx;
latidx += 90;
int master_index = lonidx * 1000 + latidx;
FGMkrBeacon b( lon, lat, elev, type );
// add to the actual bucket
real_add( master_index, b );
// if we are close to the edge, add to adjacent buckets so we only
// have to search one bucket at run time
// there are 8 cases since there are 8 adjacent tiles
if ( lonfrac < 0.2 ) {
real_add( master_index - 1000, b );
if ( latfrac < 0.2 ) {
real_add( master_index - 1000 - 1, b );
} else if ( latfrac > 0.8 ) {
real_add( master_index - 1000 + 1, b );
}
} else if ( lonfrac > 0.8 ) {
real_add( master_index + 1000, b );
if ( latfrac < 0.2 ) {
real_add( master_index + 1000 - 1, b );
} else if ( latfrac > 0.8 ) {
real_add( master_index+- 1000 + 1, b );
}
} else if ( latfrac < 0.2 ) {
real_add( master_index - 1, b );
} else if ( latfrac > 0.8 ) {
real_add( master_index + 1, b );
}
return true;
}
// returns marker beacon type if we are over a marker beacon, NOBEACON
// otherwise
FGMkrBeacon::fgMkrBeacType FGMarkerBeacons::query( double lon, double lat,
double elev )
{
double diff;
int lonidx = (int)lon;
diff = lon - (double)lonidx;
if ( (lon < 0.0) && (fabs(diff) > SG_EPSILON) ) {
lonidx -= 1;
}
lonidx += 180;
int latidx = (int)lat;
diff = lat - (double)latidx;
if ( (lat < 0.0) && (fabs(diff) > SG_EPSILON) ) {
latidx -= 1;
}
latidx += 90;
int master_index = lonidx * 1000 + latidx;
beacon_list_type beacons = beacon_map[ master_index ];
// cout << "Master index = " << master_index << endl;
// cout << "beacon search length = " << beacons.size() << endl;
beacon_list_iterator current = beacons.begin();
beacon_list_iterator last = beacons.end();
Point3D aircraft = sgGeodToCart( Point3D(lon*SGD_DEGREES_TO_RADIANS,
lat*SGD_DEGREES_TO_RADIANS, 0) );
double min_dist = 999999999.0;
for ( ; current != last ; ++current ) {
// cout << " testing " << current->get_locident() << endl;
Point3D station = Point3D( current->get_x(),
current->get_y(),
current->get_z() );
// cout << " aircraft = " << aircraft << " station = " << station
// << endl;
double d = aircraft.distance3Dsquared( station ); // meters^2
// cout << " distance = " << d << " ("
// << FG_ILS_DEFAULT_RANGE * SG_NM_TO_METER
// * FG_ILS_DEFAULT_RANGE * SG_NM_TO_METER
// << ")" << endl;
// cout << " range = " << sqrt(d) << endl;
if ( d < min_dist ) {
min_dist = d;
}
// cout << "elev = " << elev * SG_METER_TO_FEET
// << " current->get_elev() = " << current->get_elev() << endl;
double delev = elev * SG_METER_TO_FEET - current->get_elev();
// max range is the area under r = 2.4 * alt or r^2 = 4000^2 - alt^2
// whichever is smaller. The intersection point is 1538 ...
double maxrange2; // feet^2
if ( delev < 1538.0 ) {
maxrange2 = 2.4 * 2.4 * delev * delev;
} else if ( delev < 4000.0 ) {
maxrange2 = 4000 * 4000 - delev * delev;
} else {
maxrange2 = 0.0;
}
maxrange2 *= SG_FEET_TO_METER * SG_FEET_TO_METER; // convert to meter^2
// cout << "delev = " << delev << " maxrange = " << maxrange << endl;
// match up to twice the published range so we can model
// reduced signal strength
if ( d < maxrange2 ) {
// cout << "lon = " << lon << " lat = " << lat
// << " closest beacon = " << sqrt( min_dist ) << endl;
return current->get_type();
}
}
// cout << "lon = " << lon << " lat = " << lat
// << " closest beacon = " << sqrt( min_dist ) << endl;
return FGMkrBeacon::NOBEACON;
}
FGMarkerBeacons *current_beacons;

View file

@ -1,113 +0,0 @@
// mkrbeacons.hxx -- marker beacon management class
//
// Written by Curtis Olson, started March 2001.
//
// Copyright (C) 2001 Curtis L. Olson - curt@flightgear.org
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// $Id$
#ifndef _FG_MKRBEACON_HXX
#define _FG_MKRBEACON_HXX
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <simgear/compiler.h>
#include <simgear/misc/sg_path.hxx>
#include <map>
#include <vector>
#include "nav.hxx"
SG_USING_STD(map);
SG_USING_STD(vector);
class FGMkrBeacon {
public:
enum fgMkrBeacType {
NOBEACON = 0,
INNER,
MIDDLE,
OUTER
};
private:
double lon;
double lat;
double elev;
fgMkrBeacType type;
double x, y, z;
public:
FGMkrBeacon();
FGMkrBeacon( double _lon, double _lat, double _elev, fgMkrBeacType _type );
~FGMkrBeacon();
inline double get_elev() const { return elev; }
inline fgMkrBeacType get_type() const { return type; }
inline double get_x() const { return x; }
inline double get_y() const { return y; }
inline double get_z() const { return z; }
};
class FGMarkerBeacons {
// convenience types
typedef vector < FGMkrBeacon > beacon_list_type;
typedef beacon_list_type::iterator beacon_list_iterator;
typedef beacon_list_type::const_iterator beacon_list_const_iterator;
typedef map < int, beacon_list_type > beacon_map_type;
typedef beacon_map_type::iterator beacon_map_iterator;
typedef beacon_map_type::const_iterator beacon_map_const_iterator;
beacon_map_type beacon_map;
// real add a marker beacon
bool real_add( const int master_index, const FGMkrBeacon& b );
public:
FGMarkerBeacons();
~FGMarkerBeacons();
// initialize the structures
bool init();
// add a marker beacon
bool add( double lon, double lat, double elev,
FGMkrBeacon::fgMkrBeacType type );
// returns marker beacon type if we are over a marker beacon, NOBEACON
// otherwise
FGMkrBeacon::fgMkrBeacType query( double lon, double lat, double elev );
};
#endif // _FG_MKRBEACON_HXX

View file

@ -44,29 +44,30 @@ SG_USING_STD(istream);
class FGNav {
char type;
int type;
double lon, lat;
double elev_ft;
double x, y, z;
int freq;
int range;
bool has_dme;
string ident; // to avoid a core dump with corrupt data
double range;
string ident;
double magvar; // magvar from true north (negative = W)
string name;
// for failure modeling
bool serviceable;
string trans_ident; // transmitted ident
bool nav_failed; // nav failed?
bool dme_failed; // dme failed?
public:
inline FGNav(void);
inline ~FGNav(void) {}
inline FGNav();
inline FGNav( int _type, double _lat, double _lon, double _elev_ft,
int _freq, double _range, double _magvar,
string _ident, string _name,
bool _serviceable );
inline ~FGNav() {}
inline char get_type() const { return type; }
inline int get_type() const { return type; }
inline double get_lon() const { return lon; }
inline double get_lat() const { return lat; }
inline double get_elev_ft() const { return elev_ft; }
@ -74,118 +75,71 @@ public:
inline double get_y() const { return y; }
inline double get_z() const { return z; }
inline int get_freq() const { return freq; }
inline int get_range() const { return range; }
inline bool get_has_dme() const { return has_dme; }
inline double get_range() const { return range; }
// inline bool get_has_dme() const { return has_dme; }
inline const char *get_ident() { return ident.c_str(); }
inline string get_trans_ident() { return trans_ident; }
inline double get_magvar () const { return magvar; }
inline string get_name () { return name; }
friend istream& operator>> ( istream&, FGNav& );
inline double get_magvar() const { return magvar; }
inline string get_name() { return name; }
};
inline
FGNav::FGNav(void) :
FGNav::FGNav() :
type(0),
lon(0.0), lat(0.0),
elev_ft(0.0),
x(0.0), y(0.0), z(0.0),
freq(0),
range(0),
has_dme(false),
range(0.0),
// has_dme(false),
ident(""),
magvar(0.0),
name(""),
trans_ident(""),
nav_failed(false),
dme_failed(false)
serviceable(true),
trans_ident("")
{
}
inline istream&
operator >> ( istream& in, FGNav& n )
inline
FGNav::FGNav( int _type, double _lat, double _lon, double _elev_ft,
int _freq, double _range, double _magvar,
string _ident, string _name,
bool _serviceable ) :
type(0),
lon(0.0), lat(0.0),
elev_ft(0.0),
x(0.0), y(0.0), z(0.0),
freq(0),
range(0.0),
// has_dme(false),
ident(""),
magvar(0.0),
name(""),
serviceable(true),
trans_ident("")
{
double f;
char c /* , magvar_dir */ ;
string magvar_s;
static bool first_time = true;
static double julian_date = 0;
static const double MJD0 = 2415020.0;
if ( first_time ) {
julian_date = sgTimeCurrentMJD(0,0) + MJD0;
first_time = false;
}
in >> n.type;
if ( n.type == '[' )
return in >> skipeol;
in >> n.lat >> n.lon >> n.elev_ft >> f >> n.range
>> c >> n.ident >> magvar_s;
getline(in,n.name);
// Remove the space before the name
if ( n.name.substr(0,1) == " " ) {
n.name = n.name.erase(0,1);
}
n.freq = (int)(f*100.0 + 0.5);
if ( c == 'Y' ) {
n.has_dme = true;
} else {
n.has_dme = false;
}
// Calculate the magvar from true north.
// cout << "Calculating magvar for navaid " << n.ident << endl;
if (magvar_s == "XXX") {
// default to mag var as of 1990-01-01 (Julian 2447892.5)
// cout << "lat = " << n.lat << " lon = " << n.lon << " elev_ft = "
// << n.elev_ft << " JD = "
// << julian_date << endl;
n.magvar = sgGetMagVar( n.lon * SGD_DEGREES_TO_RADIANS,
n.lat * SGD_DEGREES_TO_RADIANS,
n.elev_ft * SG_FEET_TO_METER,
julian_date )
* SGD_RADIANS_TO_DEGREES;
// cout << "Default variation at " << n.lon << ',' << n.lat
// << " is " << var << endl;
#if 0
// I don't know what this is for - CLO 1 Feb 2001
if (var - int(var) >= 0.5)
n.magvar = int(var) + 1;
else if (var - int(var) <= -0.5)
n.magvar = int(var) - 1;
else
n.magvar = int(var);
#endif
// cout << "Defaulted to magvar of " << n.magvar << endl;
} else {
char direction;
int var;
sscanf(magvar_s.c_str(), "%d%c", &var, &direction);
n.magvar = var;
if (direction == 'W')
n.magvar = -n.magvar;
// cout << "Explicit magvar of " << n.magvar << endl;
}
// cout << n.ident << " " << n.magvar << endl;
type = _type;
lat = _lat;
lon = _lon;
elev_ft = _elev_ft;
freq = _freq;
range = _range;
magvar = _magvar;
ident = _ident;
name = _name;
trans_ident = _ident;
serviceable = _serviceable;
// generate cartesian coordinates
Point3D geod( n.lon * SGD_DEGREES_TO_RADIANS, n.lat * SGD_DEGREES_TO_RADIANS, n.elev_ft * SG_FEET_TO_METER );
Point3D geod( lon * SGD_DEGREES_TO_RADIANS,
lat * SGD_DEGREES_TO_RADIANS,
elev_ft * SG_FEET_TO_METER );
Point3D cart = sgGeodToCart( geod );
n.x = cart.x();
n.y = cart.y();
n.z = cart.z();
n.trans_ident = n.ident;
n.nav_failed = n.dme_failed = false;
return in;
x = cart.x();
y = cart.y();
z = cart.z();
}

112
src/Navaids/navdb.cxx Normal file
View file

@ -0,0 +1,112 @@
// navdb.cxx -- top level navaids management routines
//
// Written by Curtis Olson, started May 2004.
//
// Copyright (C) 2004 Curtis L. Olson - curt@flightgear.org
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// $Id$
#include <simgear/debug/logstream.hxx>
#include <Main/globals.hxx>
#include "navrecord.hxx"
#include "navdb.hxx"
// load and initialize the navigational databases
bool fgNavDBInit( FGNavList *navlist, FGNavList *loclist, FGNavList *gslist,
FGNavList *dmelist, FGNavList *mkrlist )
{
SG_LOG(SG_GENERAL, SG_INFO, "Loading Navaid Databases");
// SG_LOG(SG_GENERAL, SG_INFO, " VOR/NDB");
// SGPath p_nav( globals->get_fg_root() );
// p_nav.append( "Navaids/default.nav" );
// navlist->init( p_nav );
// SG_LOG(SG_GENERAL, SG_INFO, " ILS and Marker Beacons");
// beacons->init();
// SGPath p_ils( globals->get_fg_root() );
// p_ils.append( "Navaids/default.ils" );
// ilslist->init( p_ils );
SGPath path( globals->get_fg_root() );
path.append( "Navaids/nav.dat" );
sg_gzifstream in( path.str() );
if ( !in.is_open() ) {
SG_LOG( SG_GENERAL, SG_ALERT, "Cannot open file: " << path.str() );
exit(-1);
}
// skip first two lines
in >> skipeol;
in >> skipeol;
#ifdef __MWERKS__
char c = 0;
while ( in.get(c) && c != '\0' ) {
in.putback(c);
#else
while ( ! in.eof() ) {
#endif
FGNavRecord *r = new FGNavRecord;
in >> (*r);
if ( r->get_type() > 95 ) {
break;
}
/* cout << "id = " << n.get_ident() << endl;
cout << " type = " << n.get_type() << endl;
cout << " lon = " << n.get_lon() << endl;
cout << " lat = " << n.get_lat() << endl;
cout << " elev = " << n.get_elev() << endl;
cout << " freq = " << n.get_freq() << endl;
cout << " range = " << n.get_range() << endl << endl; */
if ( r->get_type() == 2 || r->get_type() == 3 ) {
// NDB=2, VOR=3
navlist->add( r );
} else if ( r->get_type() == 4 || r->get_type() == 5 ) {
// ILS=4, LOC(only)=5
loclist->add( r );
} else if ( r->get_type() == 6 ) {
// GS=6
gslist->add( r );
} else if ( r->get_type() == 7 || r->get_type() == 8
|| r->get_type() == 9 )
{
// Marker Beacon = 7,8,9
mkrlist->add( r );
} else if ( r->get_type() == 12 ) {
// DME=12
dmelist->add( r );
}
in >> skipcomment;
}
// cout << "min freq = " << min << endl;
// cout << "max freq = " << max << endl;
return true;
}

50
src/Navaids/navdb.hxx Normal file
View file

@ -0,0 +1,50 @@
// navdb.hxx -- top level navaids management routines
//
// Written by Curtis Olson, started May 2004.
//
// Copyright (C) 2004 Curtis L. Olson - curt@flightgear.org
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// $Id$
#ifndef _FG_NAVDB_HXX
#define _FG_NAVDB_HXX
#include <simgear/compiler.h>
#include <simgear/misc/sg_path.hxx>
// #include <map>
// #include <vector>
// #include STL_STRING
#include "navlist.hxx"
#include "ilslist.hxx"
#include "mkrbeacons.hxx"
#include "fixlist.hxx"
// SG_USING_STD(map);
// SG_USING_STD(vector);
// SG_USING_STD(string);
// load and initialize the navigational databases
bool fgNavDBInit( FGNavList *navlist, FGNavList *loclist, FGNavList *gslist,
FGNavList *dmelist, FGNavList *mkrbeacons );
#endif // _FG_NAVDB_HXX

View file

@ -32,9 +32,6 @@
#include "navlist.hxx"
FGNavList *current_navlist;
// Constructor
FGNavList::FGNavList( void ) {
}
@ -46,64 +43,88 @@ FGNavList::~FGNavList( void ) {
// load the navaids and build the map
bool FGNavList::init( SGPath path ) {
bool FGNavList::init() {
// FIXME: leaves all the individual navaid entries leaked
navaids.erase( navaids.begin(), navaids.end() );
navaids_by_tile.erase( navaids_by_tile.begin(), navaids_by_tile.end() );
ident_navaids.erase( ident_navaids.begin(), ident_navaids.end() );
sg_gzifstream in( path.str() );
if ( !in.is_open() ) {
SG_LOG( SG_GENERAL, SG_ALERT, "Cannot open file: " << path.str() );
exit(-1);
return true;
}
// real add a marker beacon
static void real_add( nav_map_type &navmap, const int master_index,
FGNavRecord *n )
{
navmap[master_index].push_back( n );
}
// front end for add a marker beacon
static void tile_add( nav_map_type &navmap, FGNavRecord *n ) {
double diff;
double lon = n->get_lon();
double lat = n->get_lat();
int lonidx = (int)lon;
diff = lon - (double)lonidx;
if ( (lon < 0.0) && (fabs(diff) > SG_EPSILON) ) {
lonidx -= 1;
}
double lonfrac = lon - (double)lonidx;
lonidx += 180;
// read in each line of the file
in >> skipeol;
in >> skipcomment;
// double min = 100000;
// double max = 0;
#ifdef __MWERKS__
char c = 0;
while ( in.get(c) && c != '\0' ) {
in.putback(c);
#else
while ( ! in.eof() ) {
#endif
FGNav *n = new FGNav;
in >> (*n);
if ( n->get_type() == '[' ) {
break;
int latidx = (int)lat;
diff = lat - (double)latidx;
if ( (lat < 0.0) && (fabs(diff) > SG_EPSILON) ) {
latidx -= 1;
}
double latfrac = lat - (double)latidx;
latidx += 90;
/* cout << "id = " << n.get_ident() << endl;
cout << " type = " << n.get_type() << endl;
cout << " lon = " << n.get_lon() << endl;
cout << " lat = " << n.get_lat() << endl;
cout << " elev = " << n.get_elev() << endl;
cout << " freq = " << n.get_freq() << endl;
cout << " range = " << n.get_range() << endl << endl; */
int master_index = lonidx * 1000 + latidx;
// cout << "lonidx = " << lonidx << " latidx = " << latidx << " ";
// cout << "Master index = " << master_index << endl;
navaids [n->get_freq() ].push_back(n);
// add to the actual bucket
real_add( navmap, master_index, n );
// if we are close to the edge, add to adjacent buckets so we only
// have to search one bucket at run time
// there are 8 cases since there are 8 adjacent tiles
if ( lonfrac < 0.2 ) {
real_add( navmap, master_index - 1000, n );
if ( latfrac < 0.2 ) {
real_add( navmap, master_index - 1000 - 1, n );
} else if ( latfrac > 0.8 ) {
real_add( navmap, master_index - 1000 + 1, n );
}
} else if ( lonfrac > 0.8 ) {
real_add( navmap, master_index + 1000, n );
if ( latfrac < 0.2 ) {
real_add( navmap, master_index + 1000 - 1, n );
} else if ( latfrac > 0.8 ) {
real_add( navmap, master_index + 1000 + 1, n );
}
} else if ( latfrac < 0.2 ) {
real_add( navmap, master_index - 1, n );
} else if ( latfrac > 0.8 ) {
real_add( navmap, master_index + 1, n );
}
}
// add an entry to the lists
bool FGNavList::add( FGNavRecord *n ) {
navaids[n->get_freq()].push_back(n);
ident_navaids[n->get_ident()].push_back(n);
in >> skipcomment;
/* if ( n.get_type() != 'N' ) {
if ( n.get_freq() < min ) {
min = n.get_freq();
}
if ( n.get_freq() > max ) {
max = n.get_freq();
}
} */
}
// cout << "min freq = " << min << endl;
// cout << "max freq = " << max << endl;
tile_add( navaids_by_tile, n );
return true;
}
@ -112,7 +133,7 @@ bool FGNavList::init( SGPath path ) {
// there will be multiple stations with matching frequencies so a
// position must be specified. Lon and lat are in degrees, elev is in
// meters.
FGNav *FGNavList::findByFreq( double freq, double lon, double lat, double elev )
FGNavRecord *FGNavList::findByFreq( double freq, double lon, double lat, double elev )
{
nav_list_type stations = navaids[(int)(freq*100.0 + 0.5)];
Point3D aircraft = sgGeodToCart( Point3D(lon, lat, elev) );
@ -121,7 +142,7 @@ FGNav *FGNavList::findByFreq( double freq, double lon, double lat, double elev )
}
FGNav *FGNavList::findByIdent( const char* ident,
FGNavRecord *FGNavList::findByIdent( const char* ident,
const double lon, const double lat )
{
nav_list_type stations = ident_navaids[ident];
@ -133,7 +154,7 @@ FGNav *FGNavList::findByIdent( const char* ident,
// Given an Ident and optional freqency, return the first matching
// station.
FGNav *FGNavList::findByIdentAndFreq( const char* ident, const double freq )
FGNavRecord *FGNavList::findByIdentAndFreq( const char* ident, const double freq )
{
nav_list_type stations = ident_navaids[ident];
@ -156,10 +177,10 @@ FGNav *FGNavList::findByIdentAndFreq( const char* ident, const double freq )
// Given a point and a list of stations, return the closest one to the
// specified point.
FGNav *FGNavList::findNavFromList( const Point3D &aircraft,
FGNavRecord *FGNavList::findNavFromList( const Point3D &aircraft,
const nav_list_type &stations )
{
FGNav *nav = NULL;
FGNavRecord *nav = NULL;
Point3D station;
double d2;
double min_dist = 999999999.0;
@ -192,3 +213,70 @@ FGNav *FGNavList::findNavFromList( const Point3D &aircraft,
return nav;
}
// returns the closest entry to the give lon/lat/elev
FGNavRecord *FGNavList::findClosest( double lon_rad, double lat_rad,
double elev_m )
{
FGNavRecord *result = NULL;
double diff;
double lon_deg = lon_rad * SG_RADIANS_TO_DEGREES;
double lat_deg = lat_rad * SG_RADIANS_TO_DEGREES;
int lonidx = (int)lon_deg;
diff = lon_deg - (double)lonidx;
if ( (lon_deg < 0.0) && (fabs(diff) > SG_EPSILON) ) {
lonidx -= 1;
}
lonidx += 180;
int latidx = (int)lat_deg;
diff = lat_deg - (double)latidx;
if ( (lat_deg < 0.0) && (fabs(diff) > SG_EPSILON) ) {
latidx -= 1;
}
latidx += 90;
int master_index = lonidx * 1000 + latidx;
nav_list_type navs = navaids_by_tile[ master_index ];
// cout << "Master index = " << master_index << endl;
// cout << "beacon search length = " << beacons.size() << endl;
nav_list_iterator current = navs.begin();
nav_list_iterator last = navs.end();
Point3D aircraft = sgGeodToCart( Point3D(lon_rad,
lat_rad,
elev_m) );
double min_dist = 999999999.0;
for ( ; current != last ; ++current ) {
// cout << " testing " << (*current)->get_ident() << endl;
Point3D station = Point3D( (*current)->get_x(),
(*current)->get_y(),
(*current)->get_z() );
// cout << " aircraft = " << aircraft << " station = " << station
// << endl;
double d = aircraft.distance3Dsquared( station ); // meters^2
// cout << " distance = " << d << " ("
// << FG_ILS_DEFAULT_RANGE * SG_NM_TO_METER
// * FG_ILS_DEFAULT_RANGE * SG_NM_TO_METER
// << ")" << endl;
// cout << " range = " << sqrt(d) << endl;
if ( d < min_dist ) {
min_dist = d;
result = (*current);
}
}
// cout << "lon = " << lon << " lat = " << lat
// << " closest beacon = " << sqrt( min_dist ) << endl;
return result;
}

View file

@ -32,31 +32,35 @@
#include <vector>
#include STL_STRING
#include "nav.hxx"
#include "navrecord.hxx"
SG_USING_STD(map);
SG_USING_STD(vector);
SG_USING_STD(string);
// convenience types
typedef vector < FGNavRecord* > nav_list_type;
typedef nav_list_type::iterator nav_list_iterator;
typedef nav_list_type::const_iterator nav_list_const_iterator;
typedef map < int, nav_list_type > nav_map_type;
typedef nav_map_type::iterator nav_map_iterator;
typedef nav_map_type::const_iterator nav_map_const_iterator;
typedef map < string, nav_list_type > nav_ident_map_type;
class FGNavList {
// convenience types
typedef vector < FGNav* > nav_list_type;
typedef nav_list_type::iterator nav_list_iterator;
typedef nav_list_type::const_iterator nav_list_const_iterator;
typedef map < int, nav_list_type > nav_map_type;
typedef nav_map_type::iterator nav_map_iterator;
typedef nav_map_type::const_iterator nav_map_const_iterator;
typedef map < string, nav_list_type > nav_ident_map_type;
nav_list_type navlist;
nav_map_type navaids;
nav_map_type navaids_by_tile;
nav_ident_map_type ident_navaids;
// Given a point and a list of stations, return the closest one to
// the specified point.
FGNav *findNavFromList( const Point3D &aircraft,
FGNavRecord *findNavFromList( const Point3D &aircraft,
const nav_list_type &stations );
public:
@ -64,21 +68,35 @@ public:
FGNavList();
~FGNavList();
// load the navaids and build the map
bool init( SGPath path );
// initialize the nav list
bool init();
// add an entry
bool add( FGNavRecord *n );
// Query the database for the specified frequency. It is assumed
// that there will be multiple stations with matching frequencies
// so a position must be specified. Lon and lat are in degrees,
// elev is in meters.
FGNav *findByFreq( double freq, double lon, double lat, double elev );
FGNavRecord *findByFreq( double freq, double lon, double lat, double elev );
// Query the database for the specified frequency. It is assumed
// that there will be multiple stations with matching frequencies
// so a position must be specified. Lon and lat are in degrees,
// elev is in meters.
FGNavRecord *findByLoc( double lon, double lat, double elev );
// locate closest item in the DB matching the requested ident
FGNav *findByIdent( const char* ident, const double lon, const double lat );
FGNavRecord *findByIdent( const char* ident, const double lon, const double lat );
// Given an Ident and optional freqency, return the first matching
// station.
FGNav *findByIdentAndFreq( const char* ident, const double freq = 0.0 );
FGNavRecord *findByIdentAndFreq( const char* ident,
const double freq = 0.0 );
// returns the closest entry to the give lon/lat/elev
FGNavRecord *findClosest( double lon_rad, double lat_rad, double elev_m );
};

162
src/Navaids/navrecord.hxx Normal file
View file

@ -0,0 +1,162 @@
// navrecord.hxx -- generic vor/dme/ndb class
//
// Written by Curtis Olson, started May 2004.
//
// Copyright (C) 2004 Curtis L. Olson - curt@flightgear.org
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// $Id$
#ifndef _FG_NAVRECORD_HXX
#define _FG_NAVRECORD_HXX
#include <stdio.h>
#include <simgear/compiler.h>
#include <simgear/math/sg_geodesy.hxx>
#include <simgear/misc/sgstream.hxx>
#include <simgear/magvar/magvar.hxx>
#include <simgear/timing/sg_time.hxx>
#ifdef SG_HAVE_STD_INCLUDES
# include <istream>
#elif defined( __BORLANDC__ ) || (__APPLE__)
# include <iostream>
#else
# include <istream.h>
#endif
SG_USING_STD(istream);
#define FG_NAV_DEFAULT_RANGE 50
#define FG_LOC_DEFAULT_RANGE 18
#define FG_DME_DEFAULT_RANGE 50
class FGNavRecord {
int type;
double lon, lat; // location in geodetic coords
double elev_ft;
double x, y, z; // location in cartesian coords (earth centered)
int freq;
int range;
double multiuse; // can be slaved variation of VOR
// (degrees) or localizer heading
// (degrees) or dme bias (nm)
string ident; // navaid ident
string name; // "given" name
bool serviceable; // for failure modeling
string trans_ident; // for failure modeling
public:
inline FGNavRecord(void);
inline ~FGNavRecord(void) {}
inline int get_type() const { return type; }
inline double get_lon() const { return lon; }
inline double get_lat() const { return lat; }
inline double get_elev_ft() const { return elev_ft; }
inline double get_x() const { return x; }
inline double get_y() const { return y; }
inline double get_z() const { return z; }
inline int get_freq() const { return freq; }
inline int get_range() const { return range; }
inline double get_multiuse() const { return multiuse; }
inline const char *get_ident() { return ident.c_str(); }
inline string get_name() { return name; }
inline bool get_serviceable() { return serviceable; }
inline const char *get_trans_ident() { return trans_ident.c_str(); }
friend istream& operator>> ( istream&, FGNavRecord& );
};
inline
FGNavRecord::FGNavRecord(void) :
type(0),
lon(0.0), lat(0.0),
elev_ft(0.0),
x(0.0), y(0.0), z(0.0),
freq(0),
range(0),
multiuse(0.0),
ident(""),
name(""),
serviceable(true),
trans_ident("")
{
}
inline istream&
operator >> ( istream& in, FGNavRecord& n )
{
in >> n.type;
if ( n.type == 99 ) {
return in >> skipeol;
}
in >> n.lat >> n.lon >> n.elev_ft >> n.freq >> n.multiuse
>> n.ident;
getline( in, n.name );
// silently multiply adf frequencies by 100 so that adf
// vs. nav/loc frequency lookups can use the same code.
if ( n.type == 2 ) {
n.freq *= 100;
}
// Remove the space before the name
if ( n.name.substr(0,1) == " " ) {
n.name = n.name.erase(0,1);
}
// assign default ranges
if ( n.type == 2 || n.type == 3 ) {
n.range = FG_NAV_DEFAULT_RANGE;
} else if ( n.type == 4 || n.type == 5 || n.type == 6 ) {
n.range = FG_LOC_DEFAULT_RANGE;
} else if ( n.type == 12 ) {
n.range = FG_DME_DEFAULT_RANGE;
} else {
n.range = FG_LOC_DEFAULT_RANGE;
}
// transmitted ident (same as ident unless modeling a fault)
n.trans_ident = n.ident;
// generate cartesian coordinates
Point3D geod( n.lon * SGD_DEGREES_TO_RADIANS,
n.lat * SGD_DEGREES_TO_RADIANS,
n.elev_ft * SG_FEET_TO_METER );
Point3D cart = sgGeodToCart( geod );
n.x = cart.x();
n.y = cart.y();
n.z = cart.z();
return in;
}
#endif // _FG_NAVRECORD_HXX