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:
parent
b7acd97f2c
commit
b2b33f7582
26 changed files with 831 additions and 1218 deletions
|
@ -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;
|
||||
|
|
|
@ -65,6 +65,7 @@ class FGDME : public SGSubsystem
|
|||
double x;
|
||||
double y;
|
||||
double z;
|
||||
double bias;
|
||||
double dist;
|
||||
double prev_dist;
|
||||
double spd;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -66,6 +66,13 @@ class FGMarkerBeacon : public SGSubsystem
|
|||
|
||||
public:
|
||||
|
||||
enum fgMkrBeacType {
|
||||
NOBEACON = 0,
|
||||
INNER,
|
||||
MIDDLE,
|
||||
OUTER
|
||||
};
|
||||
|
||||
FGMarkerBeacon();
|
||||
~FGMarkerBeacon();
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -73,6 +73,7 @@ private:
|
|||
Point3D _transmitter;
|
||||
double _transmitter_elevation_ft;
|
||||
double _transmitter_range_nm;
|
||||
double _transmitter_bias;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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 );
|
||||
|
||||
|
|
|
@ -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 )
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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;
|
|
@ -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
|
|
@ -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
112
src/Navaids/navdb.cxx
Normal 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
50
src/Navaids/navdb.hxx
Normal 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
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
162
src/Navaids/navrecord.hxx
Normal 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
|
Loading…
Add table
Reference in a new issue