]> git.mxchange.org Git - flightgear.git/blob - src/Environment/environment_ctrl.cxx
Removed FGEnvironmentMgr as a special case in globals, initialization,
[flightgear.git] / src / Environment / environment_ctrl.cxx
1 // environment_ctrl.cxx -- manager for natural environment information.
2 //
3 // Written by David Megginson, started February 2002.
4 //
5 // Copyright (C) 2002  David Megginson - david@megginson.com
6 //
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License as
9 // published by the Free Software Foundation; either version 2 of the
10 // License, or (at your option) any later version.
11 //
12 // This program is distributed in the hope that it will be useful, but
13 // WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 // General Public License for more details.
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 //
21 // $Id$
22
23 #include <simgear/debug/logstream.hxx>
24
25 #include <stdlib.h>
26 #include <Main/fg_props.hxx>
27
28 #include "environment_ctrl.hxx"
29
30
31 \f
32 ////////////////////////////////////////////////////////////////////////
33 // Implementation of FGEnvironmentCtrl abstract base class.
34 ////////////////////////////////////////////////////////////////////////
35
36 FGEnvironmentCtrl::FGEnvironmentCtrl ()
37   : _environment(0),
38     _lon_deg(0),
39     _lat_deg(0),
40     _elev_ft(0)
41 {
42 }
43
44 FGEnvironmentCtrl::~FGEnvironmentCtrl ()
45 {
46 }
47
48 void
49 FGEnvironmentCtrl::setEnvironment (FGEnvironment * environment)
50 {
51   _environment = environment;
52 }
53
54 void
55 FGEnvironmentCtrl::setLongitudeDeg (double lon_deg)
56 {
57   _lon_deg = lon_deg;
58 }
59
60 void
61 FGEnvironmentCtrl::setLatitudeDeg (double lat_deg)
62 {
63   _lat_deg = lat_deg;
64 }
65
66 void
67 FGEnvironmentCtrl::setElevationFt (double elev_ft)
68 {
69   _elev_ft = elev_ft;
70 }
71
72 void
73 FGEnvironmentCtrl::setPosition (double lon_deg, double lat_deg, double elev_ft)
74 {
75   _lon_deg = lon_deg;
76   _lat_deg = lat_deg;
77   _elev_ft = elev_ft;
78 }
79
80
81 \f
82 ////////////////////////////////////////////////////////////////////////
83 // Implementation of FGUserDefEnvironmentCtrl.
84 ////////////////////////////////////////////////////////////////////////
85
86 FGUserDefEnvironmentCtrl::FGUserDefEnvironmentCtrl ()
87   : _base_wind_speed_node(0),
88     _gust_wind_speed_node(0),
89     _current_wind_speed_kt(0),
90     _delta_wind_speed_kt(0)
91 {
92 }
93
94 FGUserDefEnvironmentCtrl::~FGUserDefEnvironmentCtrl ()
95 {
96 }
97
98 void
99 FGUserDefEnvironmentCtrl::init ()
100 {
101                                 // Fill in some defaults.
102   if (!fgHasNode("/environment/params/base-wind-speed-kt"))
103     fgSetDouble("/environment/params/base-wind-speed-kt",
104                 fgGetDouble("/environment/wind-speed-kt"));
105   if (!fgHasNode("/environment/params/gust-wind-speed-kt"))
106     fgSetDouble("/environment/params/gust-wind-speed-kt",
107                 fgGetDouble("/environment/params/base-wind-speed-kt"));
108
109   _base_wind_speed_node =
110     fgGetNode("/environment/params/base-wind-speed-kt", true);
111   _gust_wind_speed_node =
112     fgGetNode("/environment/params/gust-wind-speed-kt", true);
113
114   _current_wind_speed_kt = _base_wind_speed_node->getDoubleValue();
115   _delta_wind_speed_kt = 0.1;
116 }
117
118 void
119 FGUserDefEnvironmentCtrl::update (double dt)
120 {
121   double base_wind_speed = _base_wind_speed_node->getDoubleValue();
122   double gust_wind_speed = _gust_wind_speed_node->getDoubleValue();
123
124   if (gust_wind_speed < base_wind_speed) {
125       gust_wind_speed = base_wind_speed;
126       _gust_wind_speed_node->setDoubleValue(gust_wind_speed);
127   }
128
129   if (base_wind_speed == gust_wind_speed) {
130     _current_wind_speed_kt = base_wind_speed;
131   } else {
132     int rn = rand() % 128;
133     int sign = (_delta_wind_speed_kt < 0 ? -1 : 1);
134     double gust = _current_wind_speed_kt - base_wind_speed;
135     double incr = gust / 50;
136
137     if (rn == 0)
138       _delta_wind_speed_kt = - _delta_wind_speed_kt;
139     else if (rn < 4)
140       _delta_wind_speed_kt -= incr * sign;
141     else if (rn < 16)
142       _delta_wind_speed_kt += incr * sign;
143
144     _current_wind_speed_kt += _delta_wind_speed_kt;
145
146     if (_current_wind_speed_kt < base_wind_speed) {
147       _current_wind_speed_kt = base_wind_speed;
148       _delta_wind_speed_kt = 0.01;
149     } else if (_current_wind_speed_kt > gust_wind_speed) {
150       _current_wind_speed_kt = gust_wind_speed;
151       _delta_wind_speed_kt = -0.01;
152     }
153   }
154   
155   if (_environment != 0)
156     _environment->set_wind_speed_kt(_current_wind_speed_kt);
157 }
158
159
160 \f
161 ////////////////////////////////////////////////////////////////////////
162 // Implementation of FGInterpolateEnvironmentCtrl.
163 ////////////////////////////////////////////////////////////////////////
164
165 FGInterpolateEnvironmentCtrl::FGInterpolateEnvironmentCtrl ()
166 {
167 }
168
169 FGInterpolateEnvironmentCtrl::~FGInterpolateEnvironmentCtrl ()
170 {
171     for (int i = 0; i < _boundary_table.size(); i++)
172         delete _boundary_table[i];
173     for (int i = 0; i < _aloft_table.size(); i++)
174         delete _aloft_table[i];
175 }
176
177
178
179 void
180 FGInterpolateEnvironmentCtrl::init ()
181 {
182     read_table(fgGetNode("/environment/config/boundary", true),
183                _boundary_table);
184     read_table(fgGetNode("/environment/config/aloft", true),
185                _aloft_table);
186 }
187
188 void
189 FGInterpolateEnvironmentCtrl::reinit ()
190 {
191     for (int i = 0; i < _boundary_table.size(); i++)
192         delete _boundary_table[i];
193     for (int i = 0; i < _aloft_table.size(); i++)
194         delete _aloft_table[i];
195     _boundary_table.clear();
196     _aloft_table.clear();
197     init();
198 }
199
200 void
201 FGInterpolateEnvironmentCtrl::read_table (const SGPropertyNode * node,
202                                           vector<bucket *> &table)
203 {
204     for (int i = 0; i < node->nChildren(); i++) {
205         const SGPropertyNode * child = node->getChild(i);
206         if (!strcmp(child->getName(), "entry") &&
207             child->getStringValue("elevation-ft", "")[0] != '\0') {
208             bucket * b = new bucket;
209             if (i > 0)
210                 b->environment.copy(table[i-1]->environment);
211             b->environment.read(child);
212             b->altitude_ft = b->environment.get_elevation_ft();
213             table.push_back(b);
214         }
215     }
216     sort(table.begin(), table.end());
217 }
218
219 void
220 FGInterpolateEnvironmentCtrl::update (double delta_time_sec)
221 {
222                                 // FIXME
223     double altitude_ft = fgGetDouble("/position/altitude-ft");
224     double altitude_agl_ft = fgGetDouble("/position/altitude-agl-ft");
225     double boundary_transition =
226         fgGetDouble("/environment/config/boundary-transition-ft", 500);
227
228     double ground_elevation_ft = altitude_ft - altitude_agl_ft;
229
230     int length = _boundary_table.size();
231
232     if (length > 0) {
233                                 // boundary table
234         double boundary_limit = _boundary_table[length-1]->altitude_ft;
235         if (boundary_limit >= altitude_agl_ft) {
236             do_interpolate(_boundary_table, altitude_agl_ft,
237                            _environment);
238             return;
239         } else if ((boundary_limit + boundary_transition) >= altitude_agl_ft) {
240                                 // both tables
241             do_interpolate(_boundary_table, altitude_agl_ft, &env1);
242             do_interpolate(_aloft_table, altitude_ft, &env2);
243             double fraction =
244                 (altitude_agl_ft - boundary_limit) / boundary_transition;
245             interpolate(&env1, &env2, fraction, _environment);
246             return;
247         }
248     }
249
250                                 // aloft table
251     do_interpolate(_aloft_table, altitude_ft, _environment);
252 }
253
254 void
255 FGInterpolateEnvironmentCtrl::do_interpolate (vector<bucket *> &table,
256                                               double altitude_ft,
257                                               FGEnvironment * environment)
258 {
259     int length = table.size();
260     if (length == 0)
261         return;
262
263                                 // Boundary conditions
264     if ((length == 1) || (table[0]->altitude_ft >= altitude_ft)) {
265         environment->copy(table[0]->environment);
266         return;
267     } else if (table[length-1]->altitude_ft <= altitude_ft) {
268         environment->copy(table[length-1]->environment);
269         return;
270     }
271         
272                                 // Search the interpolation table
273     for (int i = 0; i < length - 1; i++) {
274         if ((i == length - 1) || (table[i]->altitude_ft <= altitude_ft)) {
275                 FGEnvironment * env1 = &(table[i]->environment);
276                 FGEnvironment * env2 = &(table[i+1]->environment);
277                 double fraction;
278                 if (table[i]->altitude_ft == table[i+1]->altitude_ft)
279                     fraction = 1.0;
280                 else
281                     fraction =
282                         ((altitude_ft - table[i]->altitude_ft) /
283                          (table[i+1]->altitude_ft - table[i]->altitude_ft));
284                 interpolate(env1, env2, fraction, environment);
285
286                 return;
287         }
288     }
289 }
290
291 bool
292 FGInterpolateEnvironmentCtrl::bucket::operator< (const bucket &b) const
293 {
294     return (altitude_ft < b.altitude_ft);
295 }
296
297
298 // end of environment_ctrl.cxx