]> git.mxchange.org Git - flightgear.git/blob - src/ATC/atis.cxx
Preliminary support for AI planes from Dave Luff. This works only at
[flightgear.git] / src / ATC / atis.cxx
1 // atis.cxx - routines to generate the ATIS info string
2 // This is the implementation of the FGATIS class
3 //
4 // Written by David Luff, started October 2001.
5 //
6 // Copyright (C) 2001  David C Luff - david.luff@nottingham.ac.uk
7 //
8 // This program is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU General Public License as
10 // published by the Free Software Foundation; either version 2 of the
11 // License, or (at your option) any later version.
12 //
13 // This program is distributed in the hope that it will be useful, but
14 // WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 // General Public License for more details.
17 //
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the Free Software
20 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21
22
23 #ifdef HAVE_CONFIG_H
24 #  include <config.h>
25 #endif
26
27 #include <simgear/compiler.h>
28
29 #include <stdlib.h>     // atoi()
30 #include <stdio.h>      // sprintf
31 #include <string>
32 SG_USING_STD(string);
33
34 #include STL_IOSTREAM
35 #if !defined(SG_HAVE_NATIVE_SGI_COMPILERS)
36 SG_USING_STD(cout);
37 #endif
38
39 //#include <simgear/debug/logstream.hxx>
40 //#include <simgear/misc/sgstream.hxx>
41 #include <simgear/misc/sg_path.hxx>
42
43 #ifdef FG_WEATHERCM
44 # include <WeatherCM/FGLocalWeatherDatabase.h>
45 #else
46 # include <Environment/environment_mgr.hxx>
47 # include <Environment/environment.hxx>
48 #endif
49
50 #include <Main/fg_props.hxx>
51 #include <Main/globals.hxx>
52 #include <Airports/runways.hxx>
53
54 #include "atis.hxx"
55 #include "atislist.hxx"
56 #include "ATCdisplay.hxx"
57 #include "ATCutils.hxx"
58
59 // Constructor
60 FGATIS::FGATIS()
61   : type(0),
62     lon(0.0), lat(0.0),
63     elev(0.0),
64     x(0.0), y(0.0), z(0.0),
65     freq(0),
66     range(0),
67     display(false),
68     displaying(false),
69     ident(""),
70     name(""),
71     transmission(""),
72     trans_ident(""),
73     atis_failed(false)
74 {
75 }
76
77 // Destructor
78 FGATIS::~FGATIS() {
79 }
80
81 // Main update function - checks whether we are displaying or not the correct message.
82 void FGATIS::Update() {
83     if(display) {
84         if(displaying) {
85             // Check if we need to update the message
86             // - basically every hour and if the weather changes significantly at the station
87             //globals->get_ATC_display()->ChangeRepeatingMessage(transmission);
88         } else {
89             // We need to get and display the message
90             UpdateTransmission();
91             globals->get_ATC_display()->RegisterRepeatingMessage(transmission);
92             displaying = true;
93         }
94     } else {
95         // We shouldn't be displaying
96         if(displaying) {
97             globals->get_ATC_display()->CancelRepeatingMessage();
98             displaying = false;
99         }
100     }
101 }
102
103 // Sets the actual broadcast ATIS transmission.
104 void FGATIS::UpdateTransmission() {
105     double visibility;
106     char buf[10];
107     int phonetic_id;
108     string phonetic_id_string;
109     string time_str = fgGetString("sim/time/gmt-string");
110     int hours;
111     // int minutes;
112
113 #ifdef FG_WEATHERCM
114     sgVec3 position = { lat, lon, elev };
115     FGPhysicalProperty stationweather = WeatherDatabase->get(position);
116 #else
117     FGEnvironment stationweather =
118       globals->get_environment_mgr()->getEnvironment(lat, lon, elev);
119 #endif
120
121     transmission = "";
122
123     // Start with the transmitted station name.
124     transmission += name;
125     // Add "Information"
126     transmission += " Information";
127
128     //cout << "In atis.cxx, time_str = " << time_str << '\n';
129     // Add the recording identifier
130     // For now we will assume we only transmit every hour
131     hours = atoi((time_str.substr(1,2)).c_str());       //Warning - this is fragile if the 
132                                                         //time string format changes
133     //cout << "In atis.cxx, hours = " << hours << endl;
134     phonetic_id = current_atislist->GetCallSign(ident, hours, 0);
135     phonetic_id_string = GetPhoneticIdent(phonetic_id);
136     transmission += " ";
137     transmission += phonetic_id_string;
138
139     // Output the recording time. - we'll just output the last whole hour for now.
140     // FIXME - this only gets GMT time but that appears to be all the clock outputs for now
141     //cout << "in atis.cxx, time = " << time_str << endl;
142     transmission = transmission + "  Weather " + time_str.substr(0,3) + "00 hours Zulu";
143
144     // Get the temperature
145     // (Hardwire it for now since the global property returns the temperature at the current altitude
146     //temperature = fgGetDouble("/environment/weather/temperature-K");
147 #ifdef FG_WEATHERCM
148     sprintf(buf, "%i", int(stationweather.Temperature - 273.15));
149 #else
150     sprintf(buf, "%d", int(stationweather.get_temperature_degc()));
151 #endif
152     transmission += "  Temperature ";
153     transmission += buf;
154     transmission += " degrees Celsius";
155
156         // Get the visibility
157 #ifdef FG_WEATHERCM
158         visibility = fgGetDouble("/environment/visibility-m");
159 #else
160         visibility = stationweather.get_visibility_m();
161 #endif
162         sprintf(buf, "%i", int(visibility/1600));
163         transmission += "  Visibility ";
164         transmission += buf;
165         transmission += " miles";
166
167         // Get the cloudbase
168         // FIXME: kludge for now
169         if (strcmp(fgGetString("/environment/clouds/layer[0]/type"), "clear")) {
170             double cloudbase =
171               fgGetDouble("/environment/clouds/layer[0]/elevation-ft");
172             // For some reason the altitude returned doesn't seem to correspond to the actual cloud altitude.
173             char buf3[10];
174             // cout << "cloudbase = " << cloudbase << endl;
175             sprintf(buf3, "%i", int(cloudbase));
176             transmission = transmission + "  Cloudbase " + buf3 + " feet";
177         }
178
179         // Get the pressure / altimeter
180
181 #ifndef FG_WEATHERCM
182       double altimeter = stationweather.get_pressure_sea_level_inhg();
183       sprintf(buf, "%.2f", altimeter);
184       transmission += "  Altimeter ";
185       transmission += buf;
186 #endif
187
188         // Based on the airport-id and wind get the active runway
189         //FGRunway *r;
190         SGPath path( globals->get_fg_root() );
191         path.append( "Airports" );
192         path.append( "runways.mk4" );
193         FGRunways runways( path.c_str() );
194
195 #ifdef FG_WEATHERCM
196         //Set the heading to into the wind
197         double wind_x = stationweather.Wind[0];
198         double wind_y = stationweather.Wind[1];
199
200         double speed = sqrt( wind_x*wind_x + wind_y*wind_y ) * SG_METER_TO_NM / (60.0*60.0);
201         double hdg;
202
203         //If no wind use 270degrees
204         if(speed == 0) {
205             hdg = 270;
206             transmission += "  Winds light and variable";
207         } else {
208             // //normalize the wind to get the direction
209             //wind_x /= speed; wind_y /= speed;
210
211             hdg = - atan2 ( wind_x, wind_y ) * SG_RADIANS_TO_DEGREES ;
212             if (hdg < 0.0)
213               hdg += 360.0;
214
215             //add a description of the wind to the transmission
216             char buf2[72];
217             sprintf(buf2, "%s %i %s %i %s", "  Winds ", int(speed), " knots from ", int(hdg), " degrees");
218             transmission += buf2;
219         }
220 #else
221         double speed = stationweather.get_wind_speed_kt();
222         double hdg = stationweather.get_wind_from_heading_deg();
223         if (speed == 0) {
224           transmission += "  Winds light and variable";
225         } else {
226                                 // FIXME: get gust factor in somehow
227             char buf2[72];
228             sprintf(buf2, "%s %i %s %i %s", "  Winds ", int(speed),
229                     " knots from ", int(hdg), " degrees");
230             transmission += buf2;
231         }
232 #endif
233
234         string rwy_no = runways.search(ident, int(hdg));
235         if(rwy_no != (string)"NN") {
236             transmission += "  Landing and departing runway ";
237             transmission += rwy_no;
238             //cout << "in atis.cxx, r.rwy_no = " << rwy_no << " r.id = " << r->id << " r.heading = " << r->heading << endl;
239         }
240
241         // Anything else?
242
243         transmission += "  Advise controller on initial contact you have ";
244         transmission += phonetic_id_string;
245 }