]> git.mxchange.org Git - flightgear.git/commitdiff
ATIS improvements from John Denker
authorDave Luff <daveluff@ntlworld.com>
Wed, 5 Jan 2011 00:27:18 +0000 (00:27 +0000)
committerDave Luff <daveluff@ntlworld.com>
Wed, 5 Jan 2011 00:27:18 +0000 (00:27 +0000)
Primarily an improvment to the internationalisation.  Previously the ATIS considered
the world as either the UK or the rest of the world.  Now it considers it as US+Canada
or the rest of the world.  This is much more consistent with global usage of pressure
units as either inches or millibars, which is the most important difference.  Also
some other tweaks and cleanups.

src/ATCDCL/atis.cxx
src/ATCDCL/atis.hxx
src/ATCDCL/atis_lexicon.hxx
src/ATCDCL/atis_remap.hxx

index dfc1381c6be4db70956031e1cce74396d582adc0..16e94f67ae428468b9fb18ee2129e0fd61ec355a 100644 (file)
@@ -151,6 +151,7 @@ void FGATIS::Update(double dt) {
 // If !_prev_display, the radio had been detuned for a while and our
 // "transmission" variable was lost when we were de-instantiated.
     int rslt = GenTransmission(!_prev_display, attention);
+    TreeOut(msg_OK);
     if (rslt || volume != old_volume) {
       //cout << "ATIS calling ATC::render  volume: " << volume << endl;
       Render(transmission, volume, refname, true);
@@ -207,6 +208,28 @@ const int minute(60);              // measured in seconds
   const int ATIS_interval(60*minute);
 #endif
 
+// FIXME:  This is heuristic.  It gets the right answer for
+// more than 90% of the world's airports, which is a lot
+// better than nothing ... but it's not 100%.
+// We know "most" of the world uses millibars,
+// but the US, Canada and *some* other places use inches of mercury,
+// but (a) we have not implemented a reliable method of
+// ascertaining which airports are in the US, let alone
+// (b) ascertaining which other places use inches.
+//
+int Apt_US_CA(const string id) {
+// Assume all IDs have length 3 or 4.
+// No counterexamples have been seen.
+  if (id.length() == 4) {
+    if (id.substr(0,1) == "K") return 1;
+    if (id.substr(0,2) == "CY") return 1;
+  }
+  for (string::const_iterator ptr = id.begin(); ptr != id.end();  ptr++) {
+    if (isdigit(*ptr)) return 1;
+  }
+  return 0;
+}
+
 // Generate the actual broadcast ATIS transmission.
 // Regen means regenerate the /current/ transmission.
 // Special means generate a new transmission, with a new sequence.
@@ -238,7 +261,9 @@ int FGATIS::GenTransmission(const int regen, const int special) {
 
   transmission = "";
 
-  if (ident.substr(0,2) == "EG") {
+  int US_CA = Apt_US_CA(ident);
+
+  if (!US_CA) {
 // UK CAA radiotelephony manual indicates ATIS transmissions start
 // with "This is ..." 
     transmission += This_is + " ";
@@ -338,29 +363,39 @@ int FGATIS::GenTransmission(const int regen, const int special) {
     snprintf(buf, bs, "/environment/clouds/layer[%i]/elevation-ft", layer);
     double ceiling = int(fgGetDouble(buf) - _geod.getElevationFt());
     if (ceiling > 12000) continue;
-    if (coverage == scattered) {
-      if (!did_some) transmission += "   " + Sky_condition + ": ";
-      did_some++;
+
+// BEWARE:  At the present time, the environment system has no
+// way (so far as I know) to represent a "thin broken" or
+// "thin overcast" layer.  If/when such things are implemented
+// in the environment system, code will have to be written here
+// to handle them.
+
+// First, do the prefix if any:
+    if (coverage == scattered || coverage == few) {
+      if (!did_some) {
+        transmission += "   " + Sky_condition + ": ";
+        did_some++;
+      }
     } else /* must be a ceiling */  if (!did_ceiling) {
       transmission += "   " + Ceiling + ": ";
       did_ceiling++;
       did_some++;
     } else {
-      transmission += "   ";
+      transmission += "   ";    // no prefix required
     }
     int cig00  = int(SGMiscd::round(ceiling/100));  // hundreds of feet
     if (cig00) {
       int cig000 = cig00/10;
       cig00 -= cig000*10;       // just the hundreds digit
       if (cig000) {
-    snprintf(buf, bs, "%i", cig000);
-    transmission += ConvertNumToSpokenDigits(buf);
-    transmission += " " + thousand + " ";
+        snprintf(buf, bs, "%i", cig000);
+        transmission += ConvertNumToSpokenDigits(buf);
+        transmission += " " + thousand + " ";
       }
       if (cig00) {
-    snprintf(buf, bs, "%i", cig00);
-    transmission += ConvertNumToSpokenDigits(buf);
-    transmission += " " + hundred + " ";
+        snprintf(buf, bs, "%i", cig00);
+        transmission += ConvertNumToSpokenDigits(buf);
+        transmission += " " + hundred + " ";
       }
     } else {
       // Should this be "sky obscured?"
@@ -368,6 +403,7 @@ int FGATIS::GenTransmission(const int regen, const int special) {
     }
     transmission += coverage + BRK;
   }
+  if (!did_some) transmission += "   " + Sky + " " + clear + BRK;
 
   transmission += Temperature + ": ";
   double Tsl = fgGetDouble("/environment/temperature-sea-level-degc");
@@ -377,7 +413,7 @@ int FGATIS::GenTransmission(const int regen, const int special) {
   }
   snprintf(buf, bs, "%i", abs(temp));
   transmission += ConvertNumToSpokenDigits(buf);
-  transmission += " " + Celsius;
+  if (US_CA) transmission += " " + Celsius;
   transmission += " " + dewpoint + " ";
   double dpsl = fgGetDouble("/environment/dewpoint-sea-level-degc");
   temp = int(SGMiscd::round(FGAtmo().fake_dp_vs_a_us(dpsl, _geod.getElevationFt())));
@@ -386,7 +422,8 @@ int FGATIS::GenTransmission(const int regen, const int special) {
   }
   snprintf(buf, bs, "%i", abs(temp));
   transmission += ConvertNumToSpokenDigits(buf);
-  transmission += " " + Celsius + BRK;
+  if (US_CA) transmission += " " + Celsius;
+  transmission += BRK;
 
   transmission += Visibility + ": ";
   double visibility = fgGetDouble("/environment/config/boundary/entry[0]/visibility-m");
@@ -409,7 +446,6 @@ int FGATIS::GenTransmission(const int regen, const int special) {
   }
   transmission += BRK;
 
-  transmission += Altimeter + ": ";
   double myQNH;
   double Psl = fgGetDouble("/environment/pressure-sea-level-inhg");
   {
@@ -424,17 +460,21 @@ int FGATIS::GenTransmission(const int regen, const int special) {
 #endif
     myQNH = FGAtmo().QNH(_geod.getElevationM(), press);
   }
-  if(ident.substr(0,2) == "EG" && fgGetBool("/sim/atc/use-millibars")) {
-    // Convert to millibars for the UK!
+
+// Convert to millibars for most of the world (not US, not CA)
+  if((!US_CA) || fgGetBool("/sim/atc/use-millibars")) {
+    transmission += QNH + ": ";
     myQNH /= mbar;
     if  (myQNH > 1000) myQNH -= 1000;       // drop high digit
     snprintf(buf, bs, "%03.0f", myQNH);
+    transmission += ConvertNumToSpokenDigits(buf) + " " + millibars + BRK;
   } else {
-    myQNH /= inHg;
-    myQNH *= 100.;                        // shift two decimal places
-    snprintf(buf, bs, "%04.0f", myQNH);
+    transmission += Altimeter + ": ";
+    double asetting = myQNH / inHg;         // use inches of mercury
+    asetting *= 100.;                       // shift two decimal places
+    snprintf(buf, bs, "%04.0f", asetting);
+    transmission += ConvertNumToSpokenDigits(buf) + BRK;
   }
-  transmission += ConvertNumToSpokenDigits(buf) + BRK;
 
   if (_type == ATIS /* as opposed to AWOS */) {
     const FGAirport* apt = fgFindAirportID(ident);
@@ -456,27 +496,8 @@ int FGATIS::GenTransmission(const int regen, const int special) {
     transmission += phonetic_seq_string;
     transmission += "... " + BRK + PAUSE + PAUSE;
   }
-#ifdef ATIS_TEST
-  cout << "**** ATIS active on:";
-#endif
-  for (map<string,int>::iterator act = active_on.begin(); act != active_on.end(); act++){
-    string prop = "/instrumentation/" + act->first + "/atis";
-    globals->get_props()->setStringValue(prop.c_str(),
-      ("<pre>\n" + transmission + "</pre>\n").c_str());
-#ifdef ATIS_TEST
-    cout << "  " << prop;
-#endif
-  }
-#ifdef ATIS_TEST
-  cout << " ****" << endl;
-  cout << transmission << endl;
-// Note that even if we aren't outputting the transmission
-// on stdout, you can still see it by pointing a web browser
-// at the property tree.  The second comm radio is:
-// http://localhost:5400/instrumentation/comm[1]
-#endif
-
-// Take the previous English-looking string and munge it to
+  transmission_readable = transmission;
+// Take the previous readable string and munge it to
 // be relatively-more acceptable to the primitive tts system.
 // Note that : ; and . are among the token-delimeters recognized
 // by the tts system.
@@ -487,3 +508,27 @@ int FGATIS::GenTransmission(const int regen, const int special) {
   }
   return 1;
 }
+
+// Put the transmission into the property tree,
+// possibly in multiple places if multiple radios
+// are tuned to the same ATIS.
+// You can see it by pointing a web browser
+// at the property tree.  The second comm radio is:
+// http://localhost:5400/instrumentation/comm[1]
+//
+// (Also, if in debug mode, dump it to the console.)
+void FGATIS::TreeOut(int msg_OK){
+  for (map<string,int>::iterator act = active_on.begin();
+                act != active_on.end();
+                act++){
+    string prop = "/instrumentation/" + act->first + "/atis";
+    globals->get_props()->setStringValue(prop.c_str(),
+      ("<pre>\n" + transmission_readable + "</pre>\n").c_str());
+#ifdef ATIS_TEST
+    if (msg_OK) cout << "**** ATIS active on: " << prop << endl;
+#endif
+  }
+#ifdef ATIS_TEST
+  if (msg_OK) cout << transmission_readable << endl;
+#endif
+}
index cd35ea476fa4e6d7cdb887e5be57b123b88e1233..76809eb095cb8fd9d87d590ad2e25e7bc6538e7c 100644 (file)
@@ -39,10 +39,15 @@ typedef std::map<std::string,std::string> MSS;
 class FGATIS : public FGATC {
        
        //atc_type type;
-       std::string transmission;       // The actual ATIS transmission
-       // This is not stored in default.atis but is generated
-       // from the prevailing conditions when required.
+
+       // The actual ATIS transmission
+       // This is generated from the prevailing conditions when required.
+       // This is the version with markup, suitable for voice synthesis:
+       std::string transmission;
        
+       // Same as above, but in a form more readable as text.
+       std::string transmission_readable;
+
        // for failure modeling
        std::string trans_ident;                // transmitted ident
        double old_volume;
@@ -82,9 +87,13 @@ class FGATIS : public FGATC {
        
        std::string refname;            // Holds the refname of a transmission in progress
        
-       int GenTransmission(const int regen, 
-               const int special);             // Generate the transmission string
+       // Generate the ATIS transmission text:
+       int GenTransmission(const int regen, const int special);
        
+       // Put the text into the property tree
+       // (and in debug mode, print it on the console):
+       void TreeOut(int msgOK);
+
        friend std::istream& operator>> ( std::istream&, FGATIS& );
 };
 
index 37c2a03dfed7f1ebc196a51de9efe630f6ed534c..d201674ff20c64c395d678b25af8222f857627d8 100644 (file)
@@ -3,6 +3,9 @@
 
 #include <string>
 
+// NOTE:  This file serves as a database.
+// It is read by some utility programs that synthesize
+// the library of spoken words.
 
 #define Q(word) const std::string word(#word);
 
@@ -41,6 +44,7 @@ Q(broken)
 Q(overcast)
 Q(thin)
 Q(Sky_condition)
+Q(Sky)
 Q(Ceiling)
 Q(minus)
 Q(dewpoint)
@@ -51,6 +55,8 @@ Q(one_half)
 Q(three_quarters)
 Q(one_and_one_half)
 Q(Altimeter)
+Q(QNH)
+Q(millibars)
 Q(Landing_and_departing_runway)
 Q(On_initial_contact_advise_you_have_information)
 Q(This_is)
index c2341a2f0c79f339d44994a3c994f7d093df2f5f..2497197b371e534e0a0827b4891458a393094d55 100644 (file)
@@ -1,3 +1,7 @@
+// NOTE:  This file serves as a database.
+// It is read by some utility programs that synthesize
+// the library of spoken words.
+
 REMAP(Intl,  International)
 REMAP(Rgnl,  Regional)
 REMAP(Co,    County)