]> git.mxchange.org Git - flightgear.git/commitdiff
Changes to support voice ATIS
authordaveluff <daveluff>
Wed, 4 Dec 2002 19:51:21 +0000 (19:51 +0000)
committerdaveluff <daveluff>
Wed, 4 Dec 2002 19:51:21 +0000 (19:51 +0000)
src/ATC/atis.cxx
src/ATC/atis.hxx

index 0b2007aa0c0900373a7c09b21edb99dcfe4217b2..27f2200c429ce2a857889b6f2a0c9fb68ff14621 100644 (file)
@@ -55,22 +55,23 @@ SG_USING_STD(cout);
 #include "atislist.hxx"
 #include "ATCdisplay.hxx"
 #include "ATCutils.hxx"
+#include "ATCmgr.hxx"
 
 // Constructor
 FGATIS::FGATIS()
-  : type(0),
-    lon(0.0), lat(0.0),
-    elev(0.0),
-    x(0.0), y(0.0), z(0.0),
-    freq(0),
-    range(0),
-    display(false),
-    displaying(false),
-    ident(""),
-    name(""),
-    transmission(""),
-    trans_ident(""),
-    atis_failed(false)
+: type(0),
+lon(0.0), lat(0.0),
+elev(0.0),
+x(0.0), y(0.0), z(0.0),
+freq(0),
+range(0),
+display(false),
+displaying(false),
+ident(""),
+name(""),
+transmission(""),
+trans_ident(""),
+atis_failed(false)
 {
 }
 
@@ -80,166 +81,208 @@ FGATIS::~FGATIS() {
 
 // Main update function - checks whether we are displaying or not the correct message.
 void FGATIS::Update() {
-    if(display) {
-       if(displaying) {
-           // Check if we need to update the message
-           // - basically every hour and if the weather changes significantly at the station
-           //globals->get_ATC_display()->ChangeRepeatingMessage(transmission);
+       if(display) {
+               if(displaying) {
+                       // Check if we need to update the message
+                       // - basically every hour and if the weather changes significantly at the station
+                       //globals->get_ATC_display()->ChangeRepeatingMessage(transmission);
+               } else {
+                       // We need to get and display the message
+                       UpdateTransmission();
+                       //cout << "ATIS.CXX - calling ATCMgr to render transmission..." << endl;
+                       globals->get_ATC_mgr()->Render(transmission, true);
+                       displaying = true;
+               }
        } else {
-           // We need to get and display the message
-           UpdateTransmission();
-           globals->get_ATC_display()->RegisterRepeatingMessage(transmission);
-           displaying = true;
+               // We shouldn't be displaying
+               if(displaying) {
+                       //cout << "ATIS.CXX - calling NoRender()..." << endl;
+                       globals->get_ATC_mgr()->NoRender();
+                       displaying = false;
+               }
        }
-    } else {
-       // We shouldn't be displaying
-       if(displaying) {
-           globals->get_ATC_display()->CancelRepeatingMessage();
-           displaying = false;
-       }
-    }
 }
 
 // Sets the actual broadcast ATIS transmission.
 void FGATIS::UpdateTransmission() {
-    double visibility;
-    char buf[10];
-    int phonetic_id;
-    string phonetic_id_string;
-    string time_str = fgGetString("sim/time/gmt-string");
-    int hours;
-    // int minutes;
-
-#ifdef FG_WEATHERCM
-    sgVec3 position = { lat, lon, elev };
-    FGPhysicalProperty stationweather = WeatherDatabase->get(position);
-#else
-    FGEnvironment stationweather =
-      globals->get_environment_mgr()->getEnvironment(lat, lon, elev);
-#endif
-
-    transmission = "";
-
-    // Start with the transmitted station name.
-    transmission += name;
-    // Add "Information"
-    transmission += " Information";
-
-    //cout << "In atis.cxx, time_str = " << time_str << '\n';
-    // Add the recording identifier
-    // For now we will assume we only transmit every hour
-    hours = atoi((time_str.substr(1,2)).c_str());      //Warning - this is fragile if the 
-                                                       //time string format changes
-    //cout << "In atis.cxx, hours = " << hours << endl;
-    phonetic_id = current_atislist->GetCallSign(ident, hours, 0);
-    phonetic_id_string = GetPhoneticIdent(phonetic_id);
-    transmission += " ";
-    transmission += phonetic_id_string;
-
-    // Output the recording time. - we'll just output the last whole hour for now.
-    // FIXME - this only gets GMT time but that appears to be all the clock outputs for now
-    //cout << "in atis.cxx, time = " << time_str << endl;
-    transmission = transmission + "  Weather " + time_str.substr(0,3) + "00 hours Zulu";
-
-    // Get the temperature
-    // (Hardwire it for now since the global property returns the temperature at the current altitude
-    //temperature = fgGetDouble("/environment/weather/temperature-K");
-#ifdef FG_WEATHERCM
-    sprintf(buf, "%i", int(stationweather.Temperature - 273.15));
-#else
-    sprintf(buf, "%d", int(stationweather.get_temperature_degc()));
-#endif
-    transmission += "  Temperature ";
-    transmission += buf;
-    transmission += " degrees Celsius";
-
+       double visibility;
+       char buf[10];
+       int phonetic_id;
+       string phonetic_id_string;
+       string time_str = fgGetString("sim/time/gmt-string");
+       int hours;
+       // int minutes;
+       
+       #ifdef FG_WEATHERCM
+       sgVec3 position = { lat, lon, elev };
+       FGPhysicalProperty stationweather = WeatherDatabase->get(position);
+       #else
+       FGEnvironment stationweather =
+       globals->get_environment_mgr()->getEnvironment(lat, lon, elev);
+       #endif
+       
+       transmission = "";
+       
+       // UK CAA radiotelephony manual indicated ATIS transmissions start with "This is"
+       // Not sure about rest of the world though.
+       transmission += "This_is ";
+       // transmitted station name.
+       transmission += name;
+       // Add "Information"
+       transmission += " information";
+       
+       //cout << "In atis.cxx, time_str = " << time_str << '\n';
+       // Add the recording identifier
+       // For now we will assume we only transmit every hour
+       hours = atoi((time_str.substr(1,2)).c_str());   //Warning - this is fragile if the 
+       //time string format changes
+       //cout << "In atis.cxx, hours = " << hours << endl;
+       phonetic_id = current_atislist->GetCallSign(ident, hours, 0);
+       phonetic_id_string = GetPhoneticIdent(phonetic_id);
+       transmission += " ";
+       transmission += phonetic_id_string;
+       
+       // Output the recording time. - we'll just output the last whole hour for now.
+       // FIXME - this only gets GMT time but that appears to be all the clock outputs for now
+       //cout << "in atis.cxx, time = " << time_str << endl;
+       transmission = transmission + " / Weather " + ConvertNumToSpokenDigits((time_str.substr(0,3) + "00")) + " hours zulu";
+       
+       // Get the temperature
+       // (Hardwire it for now since the global property returns the temperature at the current altitude
+       //temperature = fgGetDouble("/environment/weather/temperature-K");
+       #ifdef FG_WEATHERCM
+       sprintf(buf, "%i", int(stationweather.Temperature - 273.15));
+       #else
+       // HACK ALERT - at the moment the new environment subsystem returns bogus temperatures
+       // FIXME - take out this hack when this gets fixed upstream
+       int temp = (int)stationweather.get_temperature_degc();
+       if((temp < -50) || (temp > 60)) {
+               temp = 15;
+       }
+       // original:
+       //sprintf(buf, "%d", int(stationweather.get_temperature_degc()));
+       // hack:
+       sprintf(buf, "%d", temp);
+       #endif
+       transmission += " / Temperature ";
+       if(temp < 0) {
+               transmission += "minus ";
+       }
+       string tempstr1 = buf;
+       string tempstr2;
+       transmission += ConvertNumToSpokenDigits(tempstr1);
+       transmission += " degrees_Celsius";
+       
        // Get the visibility
-#ifdef FG_WEATHERCM
+       #ifdef FG_WEATHERCM
        visibility = fgGetDouble("/environment/visibility-m");
-#else
-        visibility = stationweather.get_visibility_m();
-#endif
+       #else
+       visibility = stationweather.get_visibility_m();
+       #endif
        sprintf(buf, "%i", int(visibility/1600));
-       transmission += "  Visibility ";
-       transmission += buf;
+       transmission += " / Visibility ";
+       tempstr1 = buf;
+       transmission += ConvertNumToSpokenDigits(tempstr1);
        transmission += " miles";
-
+       
        // Get the cloudbase
        // FIXME: kludge for now
        if (strcmp(fgGetString("/environment/clouds/layer[0]/type"), "clear")) {
-           double cloudbase =
-             fgGetDouble("/environment/clouds/layer[0]/elevation-ft");
-           // For some reason the altitude returned doesn't seem to correspond to the actual cloud altitude.
-           char buf3[10];
-           // cout << "cloudbase = " << cloudbase << endl;
-           sprintf(buf3, "%i", int(cloudbase));
-           transmission = transmission + "  Cloudbase " + buf3 + " feet";
+               double cloudbase =
+               fgGetDouble("/environment/clouds/layer[0]/elevation-ft");
+               // For some reason the altitude returned doesn't seem to correspond to the actual cloud altitude.
+               char buf3[10];
+               char buf4[10];
+               // cout << "cloudbase = " << cloudbase << endl;
+               sprintf(buf3, "%i", int(cloudbase)/1000);
+               sprintf(buf4, "%i", ((int)cloudbase % 1000)/100);
+               transmission += " / Cloudbase";
+               if(int(cloudbase)/1000) {
+                       tempstr1 = buf3;
+                       transmission = transmission + " " + ConvertNumToSpokenDigits(tempstr1) + " thousand";
+               }
+               if(((int)cloudbase % 1000)/100) {
+                       tempstr1 = buf4;
+                       transmission = transmission + " " + ConvertNumToSpokenDigits(tempstr1) + " hundred";
+               }                       
+               transmission += " feet";
        }
-
+       
        // Get the pressure / altimeter
-
-#ifndef FG_WEATHERCM
-      double altimeter = stationweather.get_pressure_sea_level_inhg();
-      sprintf(buf, "%.2f", altimeter);
-      transmission += "  Altimeter ";
-      transmission += buf;
-#endif
-
+       
+       #ifndef FG_WEATHERCM
+       double altimeter = stationweather.get_pressure_sea_level_inhg();
+       sprintf(buf, "%.2f", altimeter);
+       transmission += " / Altimeter ";
+       tempstr1 = buf;
+       transmission += ConvertNumToSpokenDigits(tempstr1);
+       #endif
+       
        // Based on the airport-id and wind get the active runway
        //FGRunway *r;
        SGPath path( globals->get_fg_root() );
        path.append( "Airports" );
        path.append( "runways.mk4" );
        FGRunways runways( path.c_str() );
-
-#ifdef FG_WEATHERCM
+       
+       #ifdef FG_WEATHERCM
        //Set the heading to into the wind
-        double wind_x = stationweather.Wind[0];
-        double wind_y = stationweather.Wind[1];
-
-        double speed = sqrt( wind_x*wind_x + wind_y*wind_y ) * SG_METER_TO_NM / (60.0*60.0);
-        double hdg;
-
+       double wind_x = stationweather.Wind[0];
+       double wind_y = stationweather.Wind[1];
+       
+       double speed = sqrt( wind_x*wind_x + wind_y*wind_y ) * SG_METER_TO_NM / (60.0*60.0);
+       double hdg;
+       
        //If no wind use 270degrees
        if(speed == 0) {
-           hdg = 270;
-           transmission += "  Winds light and variable";
+               hdg = 270;
+               transmission += " / Winds_light_and_variable";
        } else {
-            // //normalize the wind to get the direction
-            //wind_x /= speed; wind_y /= speed;
-
-            hdg = - atan2 ( wind_x, wind_y ) * SG_RADIANS_TO_DEGREES ;
-            if (hdg < 0.0)
-              hdg += 360.0;
-
-           //add a description of the wind to the transmission
-           char buf2[72];
-           sprintf(buf2, "%s %i %s %i %s", "  Winds ", int(speed), " knots from ", int(hdg), " degrees");
-           transmission += buf2;
+               // //normalize the wind to get the direction
+               //wind_x /= speed; wind_y /= speed;
+               
+               hdg = - atan2 ( wind_x, wind_y ) * SG_RADIANS_TO_DEGREES ;
+               if (hdg < 0.0)
+                       hdg += 360.0;
+               
+               //add a description of the wind to the transmission
+               char buf5[10];
+               char buf6[10];
+               sprintf(buf5, "%i", int(speed));
+               sprintf(buf6, "%i", int(hdg));
+               tempstr1 = buf5;
+               tempstr2 = buf6;
+               transmission = transmission + " / Winds " + ConvertNumToSpokenDigits(tempstr1) + " knots from "
+                                           + ConvertNumToSpokenDigits(tempstr2) + " degrees";
        }
-#else
+       #else
        double speed = stationweather.get_wind_speed_kt();
        double hdg = stationweather.get_wind_from_heading_deg();
        if (speed == 0) {
-         transmission += "  Winds light and variable";
+               transmission += " / Winds_light_and_variable";
        } else {
-                               // FIXME: get gust factor in somehow
-           char buf2[72];
-           sprintf(buf2, "%s %i %s %i %s", "  Winds ", int(speed),
-                   " knots from ", int(hdg), " degrees");
-           transmission += buf2;
+               // FIXME: get gust factor in somehow
+               char buf5[10];
+               char buf6[10];
+               sprintf(buf5, "%i", int(speed));
+               sprintf(buf6, "%i", int(hdg));
+               tempstr1 = buf5;
+               tempstr2 = buf6;
+               transmission = transmission + " / Winds " + ConvertNumToSpokenDigits(tempstr1) + " knots from "
+                                           + ConvertNumToSpokenDigits(tempstr2) + " degrees";
        }
-#endif
-
+       #endif
+       
        string rwy_no = runways.search(ident, int(hdg));
        if(rwy_no != (string)"NN") {
-           transmission += "  Landing and departing runway ";
-           transmission += rwy_no;
-           //cout << "in atis.cxx, r.rwy_no = " << rwy_no << " r.id = " << r->id << " r.heading = " << r->heading << endl;
+               transmission += " / Landing_and_departing_runway ";
+               transmission += ConvertRwyNumToSpokenString(atoi(rwy_no.c_str()));
+               //cout << "in atis.cxx, r.rwy_no = " << rwy_no << " r.id = " << r->id << " r.heading = " << r->heading << endl;
        }
-
+       
        // Anything else?
-
-       transmission += "  Advise controller on initial contact you have ";
+       
+       transmission += " / Advise_controller_on_initial_contact_you_have ";
        transmission += phonetic_id_string;
+       transmission += " /// ";
 }
index 6d663a0eeab171623cde4f9af88f780e6b40695a..13f2b6b1a571b45b24aa0926af97a30a555f784e 100644 (file)
 
 #ifdef SG_HAVE_STD_INCLUDES
 #  include <istream>
-#include <iomanip>
+#  include <iomanip>
 #elif defined( SG_HAVE_NATIVE_SGI_COMPILERS )
 #  include <iostream.h>
 #elif defined( __BORLANDC__ ) || (__APPLE__)
 #  include <iostream>
 #else
 #  include <istream.h>
-#include <iomanip.h>
+#  include <iomanip.h>
 #endif
 
 #if ! defined( SG_HAVE_NATIVE_SGI_COMPILERS )
@@ -57,131 +57,131 @@ SG_USING_STD(string);
 #define FG_ATIS_DEFAULT_RANGE 30
 
 class FGATIS : public FGATC {
-
-    char type;
-    double lon, lat;
-    double elev;
-    double x, y, z;
-    int freq;
-    int range;
-    bool display;              // Flag to indicate whether we should be outputting to the ATC display.
-    bool displaying;           // Flag to indicate whether we are outputting to the ATC display.
-    string ident;              // Code of the airport its at.
-    string name;               // Name transmitted in the broadcast.
-    string transmission;       // The actual ATIS transmission
-                               // This is not stored in default.atis but is generated
-                               // from the prevailing conditions when required.
-
-    // for failure modeling
-    string trans_ident;                // transmitted ident
-    bool atis_failed;          // atis failed?
-
-    // Aircraft position
-    // ATIS is actually a special case in that unlike other ATC eg.tower it doesn't actually know about
-    // or the whereabouts of the aircraft it is transmitting to.  However, to ensure consistancy of
-    // operation with the other ATC classes the ATIS class must calculate range to the aircraft in order
-    // to decide whether to render the transmission - hence the users plane details must be stored.
-    //SGPropertyNode *airplane_lon_node; 
-    //SGPropertyNode *airplane_lat_node;
-    //SGPropertyNode *airplane_elev_node; 
-
-public:
-
-    FGATIS(void);
-    ~FGATIS(void);
-
-    //run the ATIS instance
-    void Update(void);
-
-    //Indicate that this instance should be outputting to the ATC display
-    inline void SetDisplay(void) {display = true;}
-
-    //Indicate that this instance should not be outputting to the ATC display
-    inline void SetNoDisplay(void) {display = false;}
-
-    inline char get_type() const { return type; }
-    inline double get_lon() const { return lon; }
-    inline double get_lat() const { return lat; }
-    inline double get_elev() const { return elev; }
-    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 const char* GetIdent() { return ident.c_str(); }
-    inline string get_trans_ident() { return trans_ident; }
-    inline atc_type GetType() { return ATIS; }
-
-private:
-
-    //Update the transmission string
-    void UpdateTransmission(void);
-
-    /* inline void set_type( char t ) { type = t; }
-    inline void set_lon( double l ) { lon = l; }
-    inline void set_lat( double l ) { lat = l; }
-    inline void set_elev( double e ) { elev = e; }
-    inline void set_freq( int f ) { freq = f; }
-    inline void set_range( int r ) { range = r; }
-    inline void set_dme( bool b ) { dme = b; }
-    inline void set_ident( char *i ) { strncpy( ident, i, 5 ); } */
-
-    friend istream& operator>> ( istream&, FGATIS& );
+       
+       char type;
+       double lon, lat;
+       double elev;
+       double x, y, z;
+       int freq;
+       int range;
+       bool display;           // Flag to indicate whether we should be outputting to the ATC display.
+       bool displaying;                // Flag to indicate whether we are outputting to the ATC display.
+       string ident;           // Code of the airport its at.
+       string name;            // Name transmitted in the broadcast.
+       string transmission;    // The actual ATIS transmission
+       // This is not stored in default.atis but is generated
+       // from the prevailing conditions when required.
+       
+       // for failure modeling
+       string trans_ident;             // transmitted ident
+       bool atis_failed;               // atis failed?
+       
+       // Aircraft position
+       // ATIS is actually a special case in that unlike other ATC eg.tower it doesn't actually know about
+       // or the whereabouts of the aircraft it is transmitting to.  However, to ensure consistancy of
+       // operation with the other ATC classes the ATIS class must calculate range to the aircraft in order
+       // to decide whether to render the transmission - hence the users plane details must be stored.
+       //SGPropertyNode *airplane_lon_node; 
+       //SGPropertyNode *airplane_lat_node;
+       //SGPropertyNode *airplane_elev_node; 
+       
+       public:
+       
+       FGATIS(void);
+       ~FGATIS(void);
+       
+       //run the ATIS instance
+       void Update(void);
+       
+       //Indicate that this instance should be outputting to the ATC display
+       inline void SetDisplay(void) {display = true;}
+       
+       //Indicate that this instance should not be outputting to the ATC display
+       inline void SetNoDisplay(void) {display = false;}
+       
+       inline char get_type() const { return type; }
+       inline double get_lon() const { return lon; }
+       inline double get_lat() const { return lat; }
+       inline double get_elev() const { return elev; }
+       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 const char* GetIdent() { return ident.c_str(); }
+       inline string get_trans_ident() { return trans_ident; }
+       inline atc_type GetType() { return ATIS; }
+       
+       private:
+       
+       //Update the transmission string
+       void UpdateTransmission(void);
+       
+       /* inline void set_type( char t ) { type = t; }
+       inline void set_lon( double l ) { lon = l; }
+       inline void set_lat( double l ) { lat = l; }
+       inline void set_elev( double e ) { elev = e; }
+       inline void set_freq( int f ) { freq = f; }
+       inline void set_range( int r ) { range = r; }
+       inline void set_dme( bool b ) { dme = b; }
+       inline void set_ident( char *i ) { strncpy( ident, i, 5 ); } */
+       
+       friend istream& operator>> ( istream&, FGATIS& );
 };
 
 
 inline istream&
 operator >> ( istream& in, FGATIS& a )
 {
-    double f;
-    char ch;
-
-    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 >> a.type;
-    
-    if ( a.type == '[' )
-      return in >> skipeol;
-
-    in >> a.lat >> a.lon >> a.elev >> f >> a.range 
-       >> a.ident;
-
-    a.name = "";
-    in >> ch;
-    a.name += ch;
-    while(1) {
-       //in >> noskipws
-       in.unsetf(ios::skipws);
+       double f;
+       char ch;
+       
+       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 >> a.type;
+       
+       if ( a.type == '[' )
+               return in >> skipeol;
+       
+       in >> a.lat >> a.lon >> a.elev >> f >> a.range 
+       >> a.ident;
+       
+       a.name = "";
        in >> ch;
        a.name += ch;
-       if((ch == '"') || (ch == 0x0A)) {
-           break;
-       }   // we shouldn't need the 0x0A but it makes a nice safely in case someone leaves off the "
-    }
-    in.setf(ios::skipws);
-    //cout << "atis.name = " << a.name << '\n';
-
-    a.freq = (int)(f*100.0 + 0.5);
-
-    // cout << a.ident << endl;
-
-    // generate cartesian coordinates
-    Point3D geod( a.lon * SGD_DEGREES_TO_RADIANS, a.lat * SGD_DEGREES_TO_RADIANS, a.elev );
-    Point3D cart = sgGeodToCart( geod );
-    a.x = cart.x();
-    a.y = cart.y();
-    a.z = cart.z();
-
-    a.trans_ident = a.ident;
-    a.atis_failed = false;
-
-    return in >> skipeol;
+       while(1) {
+               //in >> noskipws
+               in.unsetf(ios::skipws);
+               in >> ch;
+               a.name += ch;
+               if((ch == '"') || (ch == 0x0A)) {
+                       break;
+               }   // we shouldn't need the 0x0A but it makes a nice safely in case someone leaves off the "
+       }
+       in.setf(ios::skipws);
+       //cout << "atis.name = " << a.name << '\n';
+       
+       a.freq = (int)(f*100.0 + 0.5);
+       
+       // cout << a.ident << endl;
+       
+       // generate cartesian coordinates
+       Point3D geod( a.lon * SGD_DEGREES_TO_RADIANS, a.lat * SGD_DEGREES_TO_RADIANS, a.elev );
+       Point3D cart = sgGeodToCart( geod );
+       a.x = cart.x();
+       a.y = cart.y();
+       a.z = cart.z();
+       
+       a.trans_ident = a.ident;
+       a.atis_failed = false;
+       
+       return in >> skipeol;
 }
 
 #endif // _FG_ATIS_HXX