]> git.mxchange.org Git - flightgear.git/blob - src/WeatherCM/FGLocalWeatherDatabase.cpp
Changes to keep the various autopilot properties from stepping on each
[flightgear.git] / src / WeatherCM / FGLocalWeatherDatabase.cpp
1 /*****************************************************************************
2
3  Module:       FGLocalWeatherDatabase.cpp
4  Author:       Christian Mayer
5  Date started: 28.05.99
6  Called by:    main program
7
8  -------- Copyright (C) 1999 Christian Mayer (fgfs@christianmayer.de) --------
9
10  This program is free software; you can redistribute it and/or modify it under
11  the terms of the GNU General Public License as published by the Free Software
12  Foundation; either version 2 of the License, or (at your option) any later
13  version.
14
15  This program is distributed in the hope that it will be useful, but WITHOUT
16  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17  FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
18  details.
19
20  You should have received a copy of the GNU General Public License along with
21  this program; if not, write to the Free Software Foundation, Inc., 59 Temple
22  Place - Suite 330, Boston, MA  02111-1307, USA.
23
24  Further information about the GNU General Public License can also be found on
25  the world wide web at http://www.gnu.org.
26
27 FUNCTIONAL DESCRIPTION
28 ------------------------------------------------------------------------------
29 Database for the local weather
30 This database is the only one that gets called from FG
31
32 HISTORY
33 ------------------------------------------------------------------------------
34 28.05.1999 Christian Mayer      Created
35 16.06.1999 Durk Talsma          Portability for Linux
36 20.06.1999 Christian Mayer      added lots of consts
37 11.10.1999 Christian Mayer      changed set<> to map<> on Bernie Bright's 
38                                 suggestion
39 19.10.1999 Christian Mayer      change to use PLIB's sg instead of Point[2/3]D
40                                 and lots of wee code cleaning
41 14.12.1999 Christian Mayer      Changed the internal structure to use Dave
42                                 Eberly's spherical interpolation code. This
43                                 stops our dependancy on the (ugly) voronoi
44                                 code and simplyfies the code structure a lot.
45 07.05.2000 Tony Peden           Added functionality to get the weather data
46                                 on 'the bus'
47 18.05.2000 Christian Mayer      Minor clean-ups. Changed the code to use 
48                                 FGWeatherUtils.h for unit conversion
49 18.07.2001 Christian Mayer      Added the posibility to limit the amount of 
50                                 stations for a faster init.
51 *****************************************************************************/
52
53 /****************************************************************************/
54 /* INCLUDES                                                                 */
55 /****************************************************************************/
56 #include <simgear/compiler.h>
57 #include <simgear/constants.h>
58
59 #include <Aircraft/aircraft.hxx>
60 #include <Main/fg_props.hxx>
61
62 #include "FGLocalWeatherDatabase.h"
63
64 #include "FGWeatherParse.h"
65
66 #include "FGWeatherUtils.h"
67
68 /****************************************************************************/
69 /********************************** CODE ************************************/
70 /****************************************************************************/
71
72 FGLocalWeatherDatabase* FGLocalWeatherDatabase::theFGLocalWeatherDatabase = 0;
73 FGLocalWeatherDatabase *WeatherDatabase;
74
75 void FGLocalWeatherDatabase::init( const WeatherPrecision visibility,
76                                    const DatabaseWorkingType type,
77                                    const string &root )
78 {
79     cerr << "Initializing FGLocalWeatherDatabase\n";
80     cerr << "-----------------------------------\n";
81
82     if (theFGLocalWeatherDatabase)
83     {
84         cerr << "Error: only one local weather allowed";
85         exit(-1);
86     }
87
88     setWeatherVisibility(visibility);
89
90     DatabaseStatus = type;
91     database = 0;           //just get sure...
92
93     Thunderstorm = false;
94     //I don't need to set theThunderstorm as Thunderstorm == false
95
96     switch(DatabaseStatus)
97     {
98     case use_global:
99         {
100             cerr << "Error: there's no global database anymore!\n";
101             exit(-1);
102         }
103         break;
104
105     case use_internet:
106         {
107             FGWeatherParse *parsed_data = new FGWeatherParse();
108             sgVec2               *p;
109             FGPhysicalProperties *f;
110             string path_to_weather = root + "/weather/current.txt.gz";
111             parsed_data->input( path_to_weather.c_str() );
112             unsigned int n = parsed_data->stored_stations();
113             int m = fgGetInt("/environment/weather/max-stations", -1);
114
115             if ( ( m < 0 ) || ( m > n ) )
116             {
117                 m = n;
118
119                 p = new sgVec2              [n];
120                 f = new FGPhysicalProperties[n];
121
122                 // fill the database
123                 for (unsigned int i = 0; i < n; i++) 
124                 {
125                     f[i] = parsed_data->getFGPhysicalProperties(i);
126                     parsed_data->getPosition(i, p[i]);
127
128                     if ( (i%100) == 0)
129                         cerr << ".";
130                 }
131             }
132             else
133             {   // we have to limit the amount of stations
134
135                 //store the "distance" between the station and the current
136                 //position. As the distance is calculated from the lat/lon
137                 //values it's not worth much - but it's good enough for
138                 //comparison
139                 map<float, unsigned int> squared_distance;
140                 sgVec2 cur_pos;
141
142                 cur_pos[0] = cache->last_known_position[0];
143                 cur_pos[1] = cache->last_known_position[1];
144                 
145                 unsigned int i;
146                 for( i = 0; i < n; i++ )
147                 {
148                   sgVec2 pos;
149                   parsed_data->getPosition(i, pos);
150                   squared_distance[sgDistanceSquaredVec2(cur_pos, pos)] = i;
151                 }
152
153                 p = new sgVec2              [m];
154                 f = new FGPhysicalProperties[m];
155
156                 map<float, unsigned int>::const_iterator ci;
157                 ci = squared_distance.begin();
158
159                 // fill the database
160                 for ( i = 0; i < m; i++ ) 
161                 { 
162                     f[i] = parsed_data->getFGPhysicalProperties(ci->second);
163                     parsed_data->getPosition(ci->second, p[i]);
164
165                     if ( (i%100) == 0)
166                         cerr << ".";
167
168                     ci++;
169                 }
170             }
171
172             // free the memory of the parsed data to ease the required memory
173             // for the very memory consuming spherical interpolation
174             delete parsed_data;
175
176             //and finally init the interpolation
177             cerr << "\nInitialiating Interpolation. (2-3 minutes on a PII-350 for ca. 3500 stations)\n";
178             database = new SphereInterpolate<FGPhysicalProperties>(m, p, f);
179
180             //and free my allocations:
181             delete[] p;
182             delete[] f;
183             cerr << "Finished weather init.\n";
184
185         }
186         break;
187
188     case distant:
189         cerr << "FGLocalWeatherDatabase error: Distant database isn't implemented yet!\n";
190         cerr << "  using random mode instead!\n";
191     case random:
192     case manual:
193     case default_mode:
194         {
195             double x[2] = {0.0,  0.0};  //make an standard weather that's the same at the whole world
196             double y[2] = {0.0,  0.0};  //make an standard weather that's the same at the whole world
197             double z[2] = {1.0, -1.0};  //make an standard weather that's the same at the whole world
198             FGPhysicalProperties *f = new FGPhysicalProperties[2];  //make an standard weather that's the same at the whole world
199             database = new SphereInterpolate<FGPhysicalProperties>(2,x,y,z,f);
200             delete[] f;
201         }
202         break;
203
204     default:
205         cerr << "FGLocalWeatherDatabase error: Unknown database type specified!\n";
206     };
207
208     cache->latitude_deg  = fgGetNode("/position/latitude-deg" );
209     cache->longitude_deg = fgGetNode("/position/longitude-deg");
210     cache->altitude_ft   = fgGetNode("/position/altitude-ft"  );
211
212     fgTie("/environment/weather/wind-north-mps", this, &FGLocalWeatherDatabase::get_wind_north);
213     fgTie("/environment/weather/wind-east-mps", this, &FGLocalWeatherDatabase::get_wind_east);
214     fgTie("/environment/weather/wind-up-mps", this, &FGLocalWeatherDatabase::get_wind_up);
215     fgTie("/environment/weather/temperature-K", this, &FGLocalWeatherDatabase::get_temperature);
216     fgTie("/environment/weather/air-pressure-Pa", this, &FGLocalWeatherDatabase::get_air_pressure);
217     fgTie("/environment/weather/vapor-pressure-Pa", this, &FGLocalWeatherDatabase::get_vapor_pressure);
218     fgTie("/environment/weather/air-density", this, &FGLocalWeatherDatabase::get_air_density);
219 }
220
221 FGLocalWeatherDatabase::~FGLocalWeatherDatabase()
222 {
223     //Tidying up:
224     delete database;
225 }
226
227 /****************************************************************************/
228 /* reset the whole database                                                 */
229 /****************************************************************************/
230 void FGLocalWeatherDatabase::reset(const DatabaseWorkingType type)
231 {
232     cerr << "FGLocalWeatherDatabase::reset isn't supported yet\n";
233 }
234
235 /****************************************************************************/
236 /* update the database. Since the last call we had dt seconds               */
237 /****************************************************************************/
238 void FGLocalWeatherDatabase::update(const WeatherPrecision dt)
239 {
240     //if (DatabaseStatus==use_global)
241     //  global->update(dt);
242 }
243
244 void FGLocalWeatherDatabase::update(const sgVec3& p) //position has changed
245 {
246     //uncomment this when you are using the GlobalDatabase
247     /*
248     cerr << "****\nupdate(p) inside\n";
249     cerr << "Parameter: " << p[0] << "/" << p[1] << "/" << p[2] << "\n";
250     cerr << FGPhysicalProperties2D(get(p2d), p2d);
251     cerr << "****\n";
252     */
253     
254 }
255
256 void FGLocalWeatherDatabase::update(const sgVec3& p, const WeatherPrecision dt)   //time and/or position has changed
257 {
258 }
259
260 /****************************************************************************/
261 /* Get the physical properties on the specified point p out of the database */
262 /****************************************************************************/
263 FGPhysicalProperty FGLocalWeatherDatabase::get(const sgVec3& p) const
264 {
265   // check for bogous altitudes. Dunno why, but FGFS want's to know the
266   // weather at an altitude of roughly -3000 meters...
267   if (p[2] < -500.0f)
268     return FGPhysicalProperty(database->Evaluate(p), -500.0f);
269
270   return FGPhysicalProperty(database->Evaluate(p), p[2]);
271 }
272
273 #ifdef macintosh
274     /* fix a problem with mw compilers in that they don't know the
275        difference between the next two methods. Since the first one
276        doesn't seem to be used anywhere, I commented it out. This is
277        supposed to be fixed in the forthcoming CodeWarrior Release
278        6. */
279 #else
280 FGPhysicalProperties FGLocalWeatherDatabase::get(const sgVec2& p) const
281 {
282     return database->Evaluate(p);
283 }
284 #endif
285
286 WeatherPrecision FGLocalWeatherDatabase::getAirDensity(const sgVec3& p) const
287 {
288     FGPhysicalProperty dummy(database->Evaluate(p), p[2]);
289
290     return 
291         (dummy.AirPressure*FG_WEATHER_DEFAULT_AIRDENSITY*FG_WEATHER_DEFAULT_TEMPERATURE) / 
292         (dummy.Temperature*FG_WEATHER_DEFAULT_AIRPRESSURE);
293 }
294
295
296 void FGLocalWeatherDatabase::setSnowRainIntensity(const WeatherPrecision x, const sgVec2& p)
297 {
298     /* not supported yet */
299 }
300
301 void FGLocalWeatherDatabase::setSnowRainType(const SnowRainType x, const sgVec2& p)
302 {
303     /* not supported yet */
304 }
305
306 void FGLocalWeatherDatabase::setLightningProbability(const WeatherPrecision x, const sgVec2& p)
307 {
308     /* not supported yet */
309 }
310
311 void FGLocalWeatherDatabase::setProperties(const FGPhysicalProperties2D& x)
312 {
313     /* not supported yet */
314 }
315
316 void fgUpdateWeatherDatabase(void)
317 {
318     sgVec3 position;
319     
320     sgSetVec3(position, 
321         current_aircraft.fdm_state->get_Latitude(),
322         current_aircraft.fdm_state->get_Longitude(),
323         current_aircraft.fdm_state->get_Altitude() * SG_FEET_TO_METER);
324     
325     WeatherDatabase->update( position );
326        
327     // get the data on 'the bus' for the FDM
328
329    /*  FGPhysicalProperty porperty = WeatherDatabase->get(position);
330
331     current_aircraft.fdm_state->set_Static_temperature( Kelvin2Rankine(porperty.Temperature) );
332     current_aircraft.fdm_state->set_Static_pressure( Pascal2psf(porperty.AirPressure) );
333
334     current_aircraft.fdm_state->set_Density( SIdensity2JSBsim( Density(porperty.AirPressure, porperty.Temperature) ) );
335     
336 #define MSTOFPS  3.2808 //m/s to ft/s
337     current_aircraft.fdm_state->set_Velocities_Local_Airmass(porperty.Wind[1]*MSTOFPS,
338         porperty.Wind[0]*MSTOFPS,
339         porperty.Wind[2]*MSTOFPS); */
340
341     
342 }
343