diff --git a/src/Cockpit/dme.cxx b/src/Cockpit/dme.cxx index 9371c0cc5..8e1519d98 100644 --- a/src/Cockpit/dme.cxx +++ b/src/Cockpit/dme.cxx @@ -31,8 +31,6 @@ #include #include -#include -#include #include #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() ) { - valid = true; - lon = ils->get_loclon(); - lat = ils->get_loclat(); - elev = ils->get_gselev(); - 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(); - } + if ( dme != NULL ) { + valid = true; + 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 = dme->get_x(); + y = dme->get_y(); + z = dme->get_z(); } else { valid = false; dist = 0; diff --git a/src/Cockpit/dme.hxx b/src/Cockpit/dme.hxx index 5b1483fc5..4a8e7e0ed 100644 --- a/src/Cockpit/dme.hxx +++ b/src/Cockpit/dme.hxx @@ -65,6 +65,7 @@ class FGDME : public SGSubsystem double x; double y; double z; + double bias; double dist; double prev_dist; double spd; diff --git a/src/Cockpit/kr_87.cxx b/src/Cockpit/kr_87.cxx index 3df7832b3..b297055a8 100644 --- a/src/Cockpit/kr_87.cxx +++ b/src/Cockpit/kr_87.cxx @@ -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; } } } diff --git a/src/Cockpit/kr_87.hxx b/src/Cockpit/kr_87.hxx index b056f5e8d..4888b8bc9 100644 --- a/src/Cockpit/kr_87.hxx +++ b/src/Cockpit/kr_87.hxx @@ -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; } diff --git a/src/Cockpit/marker_beacon.cxx b/src/Cockpit/marker_beacon.cxx index eaaf8a302..7f01ff72d 100644 --- a/src/Cockpit/marker_beacon.cxx +++ b/src/Cockpit/marker_beacon.cxx @@ -31,7 +31,7 @@ #include #include -#include +#include #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" ); } } - last_beacon = beacon_type; + + if ( inrange ) { + last_beacon = beacon_type; + } else { + last_beacon = NOBEACON; + } } diff --git a/src/Cockpit/marker_beacon.hxx b/src/Cockpit/marker_beacon.hxx index aa6d930bf..2a5ac3a9f 100644 --- a/src/Cockpit/marker_beacon.hxx +++ b/src/Cockpit/marker_beacon.hxx @@ -66,6 +66,13 @@ class FGMarkerBeacon : public SGSubsystem public: + enum fgMkrBeacType { + NOBEACON = 0, + INNER, + MIDDLE, + OUTER + }; + FGMarkerBeacon(); ~FGMarkerBeacon(); diff --git a/src/Cockpit/navcom.cxx b/src/Cockpit/navcom.cxx index 025a9e32d..4c763d386 100644 --- a/src/Cockpit/navcom.cxx +++ b/src/Cockpit/navcom.cxx @@ -319,7 +319,7 @@ double FGNavCom::adjustNavRange( double stationElev, double aircraftElev, // model standard ILS service volumes as per AIM 1-1-9 double FGNavCom::adjustILSRange( double stationElev, double aircraftElev, - double offsetDegrees, double distance ) + double offsetDegrees, double distance ) { // assumptions we model the standard service volume, plus @@ -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_loc_dist * SG_METER_TO_NM ); + 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_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(); - 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(); + // derive GS baseline + double tlon, tlat, taz; + 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; + 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 << 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_ILS_DEFAULT_RANGE; + nav_range = FG_LOC_DEFAULT_RANGE; nav_effective_range = nav_range; - nav_target_gs = ils->get_gsangle(); - nav_target_radial = ils->get_locheading(); + 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 = 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(); - - // derive GS baseline - double tlon, tlat, taz; - 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; - 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 << 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_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; diff --git a/src/Instrumentation/adf.cxx b/src/Instrumentation/adf.cxx index c1865da34..85b18b92d 100644 --- a/src/Instrumentation/adf.cxx +++ b/src/Instrumentation/adf.cxx @@ -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()); diff --git a/src/Instrumentation/dme.cxx b/src/Instrumentation/dme.cxx index 907640a8e..b660f1539 100644 --- a/src/Instrumentation/dme.cxx +++ b/src/Instrumentation/dme.cxx @@ -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); @@ -145,40 +146,22 @@ void DME::search (double frequency_mhz, double longitude_rad, double latitude_rad, double altitude_m) { - // reset search time + // reset search time _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; - } + // try the ILS list first + 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 diff --git a/src/Instrumentation/dme.hxx b/src/Instrumentation/dme.hxx index 39fbf2eaa..2604b831d 100644 --- a/src/Instrumentation/dme.hxx +++ b/src/Instrumentation/dme.hxx @@ -73,6 +73,7 @@ private: Point3D _transmitter; double _transmitter_elevation_ft; double _transmitter_range_nm; + double _transmitter_bias; }; diff --git a/src/Instrumentation/gps.cxx b/src/Instrumentation/gps.cxx index 1fae6b5d0..847d6a2e8 100644 --- a/src/Instrumentation/gps.cxx +++ b/src/Instrumentation/gps.cxx @@ -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(), - longitude_deg, - latitude_deg)) - != NULL) - { + FGNavRecord *n + = globals->get_navlist()->findByIdent(wp0_ID.c_str(), + longitude_deg, + 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(), - longitude_deg, - latitude_deg)) - != NULL) - { + FGNavRecord *n + = globals->get_navlist()->findByIdent(wp1_ID.c_str(), + longitude_deg, + latitude_deg); + if ( n != NULL ) { //cout << "Nav found" << endl; wp1_longitude_deg = n->get_lon(); wp1_latitude_deg = n->get_lat(); diff --git a/src/Main/fg_init.cxx b/src/Main/fg_init.cxx index 9ae3e3299..4e6988aff 100644 --- a/src/Main/fg_init.cxx +++ b/src/Main/fg_init.cxx @@ -98,9 +98,7 @@ #include #include #include -#include -#include -#include +#include #include #include #include @@ -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 ); diff --git a/src/Main/globals.cxx b/src/Main/globals.cxx index d000cc954..20c1c2076 100644 --- a/src/Main/globals.cxx +++ b/src/Main/globals.cxx @@ -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 ) { } diff --git a/src/Main/globals.hxx b/src/Main/globals.hxx index 07ccbc4eb..2545cd12f 100644 --- a/src/Main/globals.hxx +++ b/src/Main/globals.hxx @@ -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. */ diff --git a/src/Navaids/Makefile.am b/src/Navaids/Makefile.am index bf38322ed..bf53a5c82 100644 --- a/src/Navaids/Makefile.am +++ b/src/Navaids/Makefile.am @@ -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 \ diff --git a/src/Navaids/ils.hxx b/src/Navaids/ils.hxx deleted file mode 100644 index 95b37cf34..000000000 --- a/src/Navaids/ils.hxx +++ /dev/null @@ -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 -#include -#include -#include - -#ifdef SG_HAVE_STD_INCLUDES -# include -#elif defined( __BORLANDC__ ) || (__APPLE__) -# include -#else -# include -#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 diff --git a/src/Navaids/ilslist.cxx b/src/Navaids/ilslist.cxx deleted file mode 100644 index 8cbf6fe2d..000000000 --- a/src/Navaids/ilslist.cxx +++ /dev/null @@ -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 -#endif - -#include -#include -#include - -#include
- -#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; -} diff --git a/src/Navaids/ilslist.hxx b/src/Navaids/ilslist.hxx deleted file mode 100644 index da5a6f025..000000000 --- a/src/Navaids/ilslist.hxx +++ /dev/null @@ -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 -#include - -#include -#include - -#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 > 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 diff --git a/src/Navaids/mkrbeacons.cxx b/src/Navaids/mkrbeacons.cxx deleted file mode 100644 index be1cbed74..000000000 --- a/src/Navaids/mkrbeacons.cxx +++ /dev/null @@ -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; diff --git a/src/Navaids/mkrbeacons.hxx b/src/Navaids/mkrbeacons.hxx deleted file mode 100644 index 75944d839..000000000 --- a/src/Navaids/mkrbeacons.hxx +++ /dev/null @@ -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 -#endif - -#include -#include - -#include -#include - -#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 diff --git a/src/Navaids/nav.hxx b/src/Navaids/nav.hxx index 074670651..2ead9fd8c 100644 --- a/src/Navaids/nav.hxx +++ b/src/Navaids/nav.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(); } diff --git a/src/Navaids/navdb.cxx b/src/Navaids/navdb.cxx new file mode 100644 index 000000000..5ca43646e --- /dev/null +++ b/src/Navaids/navdb.cxx @@ -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 + +#include
+ +#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; +} diff --git a/src/Navaids/navdb.hxx b/src/Navaids/navdb.hxx new file mode 100644 index 000000000..959d81003 --- /dev/null +++ b/src/Navaids/navdb.hxx @@ -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 +#include + +// #include +// #include +// #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 diff --git a/src/Navaids/navlist.cxx b/src/Navaids/navlist.cxx index 44c830166..f8aab3e0d 100644 --- a/src/Navaids/navlist.cxx +++ b/src/Navaids/navlist.cxx @@ -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; - } - - /* 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; */ - - 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(); - } - } */ + 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 << "min freq = " << min << endl; - // cout << "max freq = " << max << endl; + int master_index = lonidx * 1000 + latidx; + // cout << "lonidx = " << lonidx << " latidx = " << latidx << " "; + // cout << "Master index = " << master_index << endl; + // 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); + 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, - const nav_list_type &stations ) +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; +} diff --git a/src/Navaids/navlist.hxx b/src/Navaids/navlist.hxx index de0bfa7f4..aee404196 100644 --- a/src/Navaids/navlist.hxx +++ b/src/Navaids/navlist.hxx @@ -32,31 +32,35 @@ #include #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 ); + }; diff --git a/src/Navaids/navrecord.hxx b/src/Navaids/navrecord.hxx new file mode 100644 index 000000000..544d2d1aa --- /dev/null +++ b/src/Navaids/navrecord.hxx @@ -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 + +#include +#include +#include +#include +#include + +#ifdef SG_HAVE_STD_INCLUDES +# include +#elif defined( __BORLANDC__ ) || (__APPLE__) +# include +#else +# include +#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