From b85be56a555c9518d46508a72910c9ebdf3b6b83 Mon Sep 17 00:00:00 2001 From: curt Date: Wed, 7 Nov 2001 17:55:28 +0000 Subject: [PATCH] Changes to support Dave Luff's initial ATC/ATIS module. --- aclocal.m4 | 2 +- src/Airports/runways.cxx | 130 ++++++++++++++++++++++++++++++++++++- src/Airports/runways.hxx | 7 ++ src/Cockpit/radiostack.cxx | 124 +++++++++++++++++++++++++++++++++++ src/Cockpit/radiostack.hxx | 72 ++++++++++++++++++++ src/Include/config.h.in | 2 +- src/Main/Makefile.am | 1 + src/Main/fg_init.cxx | 20 ++++++ src/Main/main.cxx | 6 ++ src/Main/options.cxx | 5 +- src/Makefile.am | 1 + src/Navaids/testnavs.cxx | 16 +++-- 12 files changed, 377 insertions(+), 9 deletions(-) diff --git a/aclocal.m4 b/aclocal.m4 index 7d5836b91..78a4037e5 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -1,4 +1,4 @@ -dnl aclocal.m4 generated automatically by aclocal 1.4-p4 +dnl aclocal.m4 generated automatically by aclocal 1.4 dnl Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation diff --git a/src/Airports/runways.cxx b/src/Airports/runways.cxx index 2db4a7fad..bbc617a73 100644 --- a/src/Airports/runways.cxx +++ b/src/Airports/runways.cxx @@ -25,8 +25,7 @@ # include #endif -// #include // for gdbm open flags -// #include // for gdbm open flags +#include // sprintf() #include @@ -207,6 +206,133 @@ bool FGRunways::next( FGRunway* r ) { } +// Return the runway closest to a given heading +bool FGRunways::search( const string& aptid, const int tgt_hdg, + FGRunway* runway ) +{ + FGRunway r; + double found_dir = 0.0; + + if ( !search( aptid, &r ) ) { + SG_LOG( SG_GENERAL, SG_ALERT, + "Failed to find " << aptid << " in database." ); + return false; + } + + double diff; + double min_diff = 360.0; + + while ( r.id == aptid ) { + // forward direction + diff = tgt_hdg - r.heading; + while ( diff < -180.0 ) { diff += 360.0; } + while ( diff > 180.0 ) { diff -= 360.0; } + diff = fabs(diff); + // SG_LOG( SG_GENERAL, SG_INFO, + // "Runway " << r.rwy_no << " heading = " << r.heading << + // " diff = " << diff ); + if ( diff < min_diff ) { + min_diff = diff; + runway = &r; + found_dir = 0; + } + + // reverse direction + diff = tgt_hdg - r.heading - 180.0; + while ( diff < -180.0 ) { diff += 360.0; } + while ( diff > 180.0 ) { diff -= 360.0; } + diff = fabs(diff); + // SG_LOG( SG_GENERAL, SG_INFO, + // "Runway -" << r.rwy_no << " heading = " << + // r.heading + 180.0 << + // " diff = " << diff ); + if ( diff < min_diff ) { + min_diff = diff; + runway = &r; + found_dir = 180.0; + } + + next( &r ); + } + + // SG_LOG( SG_GENERAL, SG_INFO, "closest runway = " << runway->rwy_no + // << " + " << found_dir ); + + double heading = runway->heading + found_dir; + while ( heading >= 360.0 ) { heading -= 360.0; } + runway->heading = heading; + + return true; +} + + +// Return the runway number of the runway closest to a given heading +string FGRunways::search( const string& aptid, const int tgt_hdg ) { + FGRunway r; + string rn; + double found_dir = 0.0; + + if ( !search( aptid, &r ) ) { + SG_LOG( SG_GENERAL, SG_ALERT, + "Failed to find " << aptid << " in database." ); + return "NN"; + } + + double diff; + double min_diff = 360.0; + + while ( r.id == aptid ) { + // forward direction + diff = tgt_hdg - r.heading; + while ( diff < -180.0 ) { diff += 360.0; } + while ( diff > 180.0 ) { diff -= 360.0; } + diff = fabs(diff); + // SG_LOG( SG_GENERAL, SG_INFO, + // "Runway " << r.rwy_no << " heading = " << r.heading << + // " diff = " << diff ); + if ( diff < min_diff ) { + min_diff = diff; + rn = r.rwy_no; + found_dir = 0; + } + + // reverse direction + diff = tgt_hdg - r.heading - 180.0; + while ( diff < -180.0 ) { diff += 360.0; } + while ( diff > 180.0 ) { diff -= 360.0; } + diff = fabs(diff); + // SG_LOG( SG_GENERAL, SG_INFO, + // "Runway -" << r.rwy_no << " heading = " << + // r.heading + 180.0 << + // " diff = " << diff ); + if ( diff < min_diff ) { + min_diff = diff; + rn = r.rwy_no; + found_dir = 180.0; + } + + next( &r ); + } + + // SG_LOG( SG_GENERAL, SG_INFO, "closest runway = " << r.rwy_no + // << " + " << found_dir ); + // rn = r.rwy_no; + // cout << "In search, rn = " << rn << endl; + if ( found_dir == 180 ) { + int irn = atoi(rn.c_str()); + irn += 18; + if ( irn > 36 ) { + irn -= 36; + } + char buf[4]; // 2 chars + string terminator + 1 for safety + sprintf(buf, "%i", irn); + rn = buf; + } + + return rn; +} + + // Destructor FGRunways::~FGRunways( void ) { delete storage; diff --git a/src/Airports/runways.hxx b/src/Airports/runways.hxx index 5512097d8..49fd41d0f 100644 --- a/src/Airports/runways.hxx +++ b/src/Airports/runways.hxx @@ -125,6 +125,13 @@ public: // "runway" is not changed if "apt" is not found. bool search( const string& aptid, FGRunway* runway ); bool search( const string& aptid, const string& rwyno, FGRunway* runway ); + + // DCL - search for runway closest to desired heading in degrees + bool search( const string& aptid, const int hdg, FGRunway* runway ); + + // Return the runway number of the runway closest to a given heading + string FGRunways::search( const string& aptid, const int tgt_hdg ); + FGRunway search( const string& aptid ); bool next( FGRunway* runway ); FGRunway next(); diff --git a/src/Cockpit/radiostack.cxx b/src/Cockpit/radiostack.cxx index cf6d798af..25a56c60d 100644 --- a/src/Cockpit/radiostack.cxx +++ b/src/Cockpit/radiostack.cxx @@ -29,6 +29,8 @@ #include #include +#include +//#include #include #include #include @@ -36,6 +38,9 @@ #include "radiostack.hxx" +#include +SG_USING_STD(string); + static int nav1_play_count = 0; static int nav2_play_count = 0; static int adf_play_count = 0; @@ -83,6 +88,10 @@ FGRadioStack::FGRadioStack() : lat_node(fgGetNode("/position/latitude-deg", true)), alt_node(fgGetNode("/position/altitude-ft", true)), need_update(true), + comm1_freq(0.0), + comm1_alt_freq(0.0), + comm2_freq(0.0), + comm2_alt_freq(0.0), nav1_freq(0.0), nav1_alt_freq(0.0), nav1_radial(0.0), @@ -142,6 +151,36 @@ void FGRadioStack::bind () { // User inputs + fgTie("/radios/comm[0]/frequencies/selected-mhz", this, + &FGRadioStack::get_comm1_freq, &FGRadioStack::set_comm1_freq); + fgSetArchivable("/radios/comm[0]/frequencies/selected-mhz"); + fgTie("/radios/comm[0]/frequencies/standby-mhz", this, + &FGRadioStack::get_comm1_alt_freq, &FGRadioStack::set_comm1_alt_freq); + fgSetArchivable("/radios/comm[0]/frequencies/standby-mhz"); + fgTie("/radios/comm[0]/volume", this, + &FGRadioStack::get_comm1_vol_btn, + &FGRadioStack::set_comm1_vol_btn); + fgSetArchivable("/radios/comm[0]/volume"); + fgTie("/radios/comm[0]/ident", this, + &FGRadioStack::get_comm1_ident_btn, + &FGRadioStack::set_comm1_ident_btn); + fgSetArchivable("/radios/comm[0]/ident"); + + fgTie("/radios/comm[1]/frequencies/selected-mhz", this, + &FGRadioStack::get_comm2_freq, &FGRadioStack::set_comm2_freq); + fgSetArchivable("/radios/comm[0]/frequencies/selected-mhz"); + fgTie("/radios/comm[1]/frequencies/standby-mhz", this, + &FGRadioStack::get_comm2_alt_freq, &FGRadioStack::set_comm2_alt_freq); + fgSetArchivable("/radios/comm[0]/frequencies/standby-mhz"); + fgTie("/radios/comm[1]/volume", this, + &FGRadioStack::get_comm2_vol_btn, + &FGRadioStack::set_comm2_vol_btn); + fgSetArchivable("/radios/comm[0]/volume"); + fgTie("/radios/comm[1]/ident", this, + &FGRadioStack::get_comm2_ident_btn, + &FGRadioStack::set_comm2_ident_btn); + fgSetArchivable("/radios/comm[1]/ident"); + fgTie("/radios/nav[0]/frequencies/selected-mhz", this, &FGRadioStack::get_nav1_freq, &FGRadioStack::set_nav1_freq); fgSetArchivable("/radios/nav[0]/frequencies/selected-mhz"); @@ -243,6 +282,16 @@ FGRadioStack::bind () void FGRadioStack::unbind () { + fgUntie("/radios/comm[0]/frequencies/selected-mhz"); + fgUntie("/radios/comm[0]/frequencies/standby-mhz"); + fgUntie("/radios/comm[0]/on"); + fgUntie("/radios/comm[0]/ident"); + + fgUntie("/radios/comm[1]/frequencies/selected-mhz"); + fgUntie("/radios/comm[1]/frequencies/standby-mhz"); + fgUntie("/radios/comm[1]/on"); + fgUntie("/radios/comm[1]/ident"); + fgUntie("/radios/nav[0]/frequencies/selected-mhz"); fgUntie("/radios/nav[0]/frequencies/standby-mhz"); fgUntie("/radios/nav[0]/radials/actual-deg"); @@ -353,6 +402,9 @@ double FGRadioStack::adjustILSRange( double stationElev, double aircraftElev, void FGRadioStack::update() { + //DCL + string transmission; + 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; @@ -363,6 +415,48 @@ FGRadioStack::update() Point3D station; double az1, az2, s; + //////////////////////////////////////////////////////////////////////// + // Comm1. + //////////////////////////////////////////////////////////////////////// + + static bool repeating_message_registered = false; + static int dcl_i = 0; //Hack to only call the transmission now and then - should use the event scheduler + if ( comm1_valid ) { + station = Point3D( comm1_x, comm1_y, comm1_z ); + comm1_dist = aircraft.distance3D( station ); + if ( comm1_dist < comm1_effective_range * SG_NM_TO_METER ) { + comm1_inrange = true; + // TODO - only get the transmission and register every now and then + if(dcl_i == 0) { + transmission = atis.get_transmission(); + //ChangeRepeatingMessage(transmission); + } + if(!repeating_message_registered) { + current_atcdisplay->RegisterRepeatingMessage( transmission ); + repeating_message_registered = true; + } + dcl_i++; + if(dcl_i == 3000) { + dcl_i = 0; + } + } else { + comm1_inrange = false; + if(repeating_message_registered) { + current_atcdisplay->CancelRepeatingMessage(); + repeating_message_registered = false; + } + dcl_i = 0; + } + } else { + comm1_inrange = false; + if(repeating_message_registered) { + current_atcdisplay->CancelRepeatingMessage(); + repeating_message_registered = false; + } + dcl_i = 0; + // cout << "not picking up comm1. :-(" << endl; + } + //////////////////////////////////////////////////////////////////////// // Nav1. //////////////////////////////////////////////////////////////////////// @@ -716,6 +810,8 @@ void FGRadioStack::search() FGILS ils; FGNav nav; + static string last_comm1_ident = ""; + static string last_comm2_ident = ""; static string last_nav1_ident = ""; static string last_nav2_ident = ""; static string last_adf_ident = ""; @@ -723,6 +819,34 @@ void FGRadioStack::search() static bool last_nav2_vor = false; + //////////////////////////////////////////////////////////////////////// + // Comm1. + //////////////////////////////////////////////////////////////////////// + + if ( current_atislist->query( lon, lat, elev, comm1_freq, &atis ) ) { + //cout << "atis found in radiostack search !!!!" << endl; + comm1_ident = atis.get_ident(); + comm1_valid = true; + if ( last_comm1_ident != comm1_ident ) { + //nav1_trans_ident = ils.get_trans_ident(); + last_comm1_ident = comm1_ident; + comm1_elev = atis.get_elev(); + comm1_range = FG_ATIS_DEFAULT_RANGE; + comm1_effective_range = comm1_range; + comm1_x = atis.get_x(); + comm1_y = atis.get_y(); + comm1_z = atis.get_z(); + //cout << "Found a new atis station in range" << endl; + //cout << " id = " << atis.get_ident() << endl; + } + } else { + comm1_valid = false; + comm1_ident = ""; + //comm1_trans_ident = ""; + last_comm1_ident = ""; + // cout << "not picking up atis" << endl; + } + //////////////////////////////////////////////////////////////////////// // Nav1. //////////////////////////////////////////////////////////////////////// diff --git a/src/Cockpit/radiostack.hxx b/src/Cockpit/radiostack.hxx index 2e96c0305..f96e1f432 100644 --- a/src/Cockpit/radiostack.hxx +++ b/src/Cockpit/radiostack.hxx @@ -35,6 +35,7 @@ #include #include +#include #include #include @@ -54,6 +55,38 @@ class FGRadioStack : public FGSubsystem bool need_update; + FGATIS atis; + + string comm1_ident; + bool comm1_valid; + bool comm1_inrange; + double comm1_freq; + double comm1_alt_freq; + double comm1_vol_btn; + bool comm1_ident_btn; + double comm1_x; + double comm1_y; + double comm1_z; + double comm1_dist; + double comm1_elev; + double comm1_range; + double comm1_effective_range; + + string comm2_ident; + bool comm2_valid; + bool comm2_inrange; + double comm2_freq; + double comm2_alt_freq; + double comm2_vol_btn; + bool comm2_ident_btn; + double comm2_x; + double comm2_y; + double comm2_z; + double comm2_dist; + double comm2_elev; + double comm2_range; + double comm2_effective_range; + string nav1_ident; string nav1_trans_ident; bool nav1_valid; @@ -187,6 +220,30 @@ public: // Update nav/adf radios based on current postition void search (); + // COMM1 Setters + inline void set_comm1_freq( double freq ) { + comm1_freq = freq; need_update = true; + } + inline void set_comm1_alt_freq( double freq ) { comm1_alt_freq = freq; } + inline void set_comm1_vol_btn( double val ) { + if ( val < 0.0 ) val = 0.0; + if ( val > 1.0 ) val = 1.0; + comm1_vol_btn = val; + } + inline void set_comm1_ident_btn( bool val ) { comm1_ident_btn = val; } + + // COMM2 Setters + inline void set_comm2_freq( double freq ) { + comm2_freq = freq; need_update = true; + } + inline void set_comm2_alt_freq( double freq ) { comm2_alt_freq = freq; } + inline void set_comm2_vol_btn( double val ) { + if ( val < 0.0 ) val = 0.0; + if ( val > 1.0 ) val = 1.0; + comm2_vol_btn = val; + } + inline void set_comm2_ident_btn( bool val ) { comm2_ident_btn = val; } + // NAV1 Setters inline void set_nav1_freq( double freq ) { nav1_freq = freq; need_update = true; @@ -235,6 +292,13 @@ public: } inline void set_adf_ident_btn( bool val ) { adf_ident_btn = val; } + // COMM1 Accessors + inline double get_comm1_freq () const { return comm1_freq; } + inline double get_comm1_alt_freq () const { return comm1_alt_freq; } + + // COMM2 Accessors + inline double get_comm2_freq () const { return comm2_freq; } + inline double get_comm2_alt_freq () const { return comm2_alt_freq; } // NAV1 Accessors inline double get_nav1_freq () const { return nav1_freq; } @@ -260,6 +324,14 @@ public: inline bool get_outer_blink () const { return outer_blink; } // Calculated values. + inline bool get_comm1_inrange() const { return comm1_inrange; } + inline double get_comm1_vol_btn() const { return comm1_vol_btn; } + inline bool get_comm1_ident_btn() const { return comm1_ident_btn; } + + inline bool get_comm2_inrange() const { return comm2_inrange; } + inline double get_comm2_vol_btn() const { return comm2_vol_btn; } + inline bool get_comm2_ident_btn() const { return comm2_ident_btn; } + inline bool get_nav1_inrange() const { return nav1_inrange; } bool get_nav1_to_flag () const; bool get_nav1_from_flag () const; diff --git a/src/Include/config.h.in b/src/Include/config.h.in index 553a55a5a..3c18956c7 100644 --- a/src/Include/config.h.in +++ b/src/Include/config.h.in @@ -1,4 +1,4 @@ -/* src/Include/config.h.in. Generated automatically from configure.in by autoheader 2.13. */ +/* src/Include/config.h.in. Generated automatically from configure.in by autoheader. */ /* Define to empty if the keyword does not work. */ #undef const diff --git a/src/Main/Makefile.am b/src/Main/Makefile.am index 74fb36660..7f0cf1cb8 100644 --- a/src/Main/Makefile.am +++ b/src/Main/Makefile.am @@ -56,6 +56,7 @@ fgfs_SOURCES = \ fgfs_LDADD = \ $(top_builddir)/src/Aircraft/libAircraft.a \ + $(top_builddir)/src/ATC/libATC.a \ $(top_builddir)/src/Autopilot/libAutopilot.a \ $(top_builddir)/src/Cockpit/libCockpit.a \ $(top_builddir)/src/Controls/libControls.a \ diff --git a/src/Main/fg_init.cxx b/src/Main/fg_init.cxx index 5b4e91a8d..d39a22457 100644 --- a/src/Main/fg_init.cxx +++ b/src/Main/fg_init.cxx @@ -68,6 +68,7 @@ #include #include #include +#include #include #include #include @@ -732,6 +733,25 @@ bool fgInitSubsystems( void ) { p_fix.append( "Navaids/default.fix" ); current_fixlist->init( p_fix ); + //////////////////////////////////////////////////////////////////// + // Initialize ATC list management and query systems + //////////////////////////////////////////////////////////////////// + + //DCL + SG_LOG(SG_GENERAL, SG_INFO, " ATIS"); + current_atislist = new FGATISList; + SGPath p_atis( globals->get_fg_root() ); + p_atis.append( "ATC/default.atis" ); + current_atislist->init( p_atis ); + + //////////////////////////////////////////////////////////////////// + // Initialise ATC display system + //////////////////////////////////////////////////////////////////// + + //DCL + SG_LOG(SG_GENERAL, SG_INFO, " ATC Display"); + current_atcdisplay = new FGATCDisplay; + current_atcdisplay->init(); //////////////////////////////////////////////////////////////////// // Initialize the built-in commands. diff --git a/src/Main/main.cxx b/src/Main/main.cxx index 42b6ce059..3bf277d52 100644 --- a/src/Main/main.cxx +++ b/src/Main/main.cxx @@ -73,7 +73,9 @@ #include +#include #include + #include #include #include @@ -867,6 +869,10 @@ void fgRenderFrame( void ) { hud_and_panel->apply(); fgCockpitUpdate(); + // Use the hud_and_panel ssgSimpleState for rendering the ATC output + // This only works properly if called before the panel call + current_atcdisplay->update(); + // update the panel subsystem if ( current_panel != NULL ) { current_panel->update(); diff --git a/src/Main/options.cxx b/src/Main/options.cxx index c22a2b3b3..0662cf676 100644 --- a/src/Main/options.cxx +++ b/src/Main/options.cxx @@ -871,7 +871,10 @@ parse_option (const string& arg) double speed = atof(val.substr(pos+1).c_str()); SG_LOG(SG_GENERAL, SG_INFO, "WIND: " << dir << '@' << speed << " knots" << endl); - // convert to fps + fgSetDouble("/environment/wind-from-heading-deg", dir); + fgSetDouble("/environment/wind-speed-knots", speed); + + // convert to fps speed *= SG_NM_TO_METER * SG_METER_TO_FEET * (1.0/3600); dir += 180; if (dir >= 360) diff --git a/src/Makefile.am b/src/Makefile.am index 0054b534f..fe99f9d72 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -14,6 +14,7 @@ SUBDIRS = \ Include \ Aircraft \ Airports \ + ATC \ Autopilot \ Cockpit \ Controls \ diff --git a/src/Navaids/testnavs.cxx b/src/Navaids/testnavs.cxx index 3ac45eb73..920249a3a 100644 --- a/src/Navaids/testnavs.cxx +++ b/src/Navaids/testnavs.cxx @@ -11,7 +11,10 @@ int main() { SGPath p_nav( "/home/curt/FlightGear/Navaids/default.nav" ); current_navlist->init( p_nav ); FGNav n; - if ( current_navlist->query( -93.2, 45.14, 3000, 117.30, &n) ) { + if ( current_navlist->query( -93.2 * SG_DEGREES_TO_RADIANS, + 45.14 * SG_DEGREES_TO_RADIANS, + 3000, 117.30, &n) ) + { cout << "Found a vor station in range" << endl; cout << " id = " << n.get_ident() << endl; } else { @@ -22,7 +25,10 @@ int main() { SGPath p_ils( "/home/curt/FlightGear/Navaids/default.ils" ); current_ilslist->init( p_ils ); FGILS i; - if ( current_ilslist->query( -93.1, 45.24, 3000, 110.30, &i) ) { + if ( current_ilslist->query( -93.1 * SG_DEGREES_TO_RADIANS, + 45.24 * SG_DEGREES_TO_RADIANS, + 3000, 110.30, &i) ) + { cout << "Found an ils station in range" << endl; cout << " apt = " << i.get_aptcode() << endl; cout << " rwy = " << i.get_rwyno() << endl; @@ -34,8 +40,10 @@ int main() { SGPath p_fix( "/home/curt/FlightGear/Navaids/default.fix" ); current_fixlist->init( p_fix ); FGFix fix; - if ( current_fixlist->query( "SHELL", -82, 41, 3000, - &fix, &heading, &dist) ) { + if ( current_fixlist->query( "SHELL", -82 * SG_DEGREES_TO_RADIANS, + 41 * SG_DEGREES_TO_RADIANS, 3000, + &fix, &heading, &dist) ) + { cout << "Found a matching fix" << endl; cout << " id = " << fix.get_ident() << endl; cout << " heading = " << heading << " dist = " << dist << endl;