]> git.mxchange.org Git - flightgear.git/blob - src/Environment/environment_ctrl.cxx
Try to make the replay system honor /sim/speed-up, but not fully working yet.
[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 <algorithm>
27
28 #include <Main/fg_props.hxx>
29
30 #include "environment_ctrl.hxx"
31
32 SG_USING_STD(sort);
33
34
35 \f
36 ////////////////////////////////////////////////////////////////////////
37 // Implementation of FGEnvironmentCtrl abstract base class.
38 ////////////////////////////////////////////////////////////////////////
39
40 FGEnvironmentCtrl::FGEnvironmentCtrl ()
41   : _environment(0),
42     _lon_deg(0),
43     _lat_deg(0),
44     _elev_ft(0)
45 {
46 }
47
48 FGEnvironmentCtrl::~FGEnvironmentCtrl ()
49 {
50 }
51
52 void
53 FGEnvironmentCtrl::setEnvironment (FGEnvironment * environment)
54 {
55   _environment = environment;
56 }
57
58 void
59 FGEnvironmentCtrl::setLongitudeDeg (double lon_deg)
60 {
61   _lon_deg = lon_deg;
62 }
63
64 void
65 FGEnvironmentCtrl::setLatitudeDeg (double lat_deg)
66 {
67   _lat_deg = lat_deg;
68 }
69
70 void
71 FGEnvironmentCtrl::setElevationFt (double elev_ft)
72 {
73   _elev_ft = elev_ft;
74 }
75
76 void
77 FGEnvironmentCtrl::setPosition (double lon_deg, double lat_deg, double elev_ft)
78 {
79   _lon_deg = lon_deg;
80   _lat_deg = lat_deg;
81   _elev_ft = elev_ft;
82 }
83
84
85 \f
86 ////////////////////////////////////////////////////////////////////////
87 // Implementation of FGUserDefEnvironmentCtrl.
88 ////////////////////////////////////////////////////////////////////////
89
90 FGUserDefEnvironmentCtrl::FGUserDefEnvironmentCtrl ()
91   : _base_wind_speed_node(0),
92     _gust_wind_speed_node(0),
93     _current_wind_speed_kt(0),
94     _delta_wind_speed_kt(0)
95 {
96 }
97
98 FGUserDefEnvironmentCtrl::~FGUserDefEnvironmentCtrl ()
99 {
100 }
101
102 void
103 FGUserDefEnvironmentCtrl::init ()
104 {
105                                 // Fill in some defaults.
106   if (!fgHasNode("/environment/params/base-wind-speed-kt"))
107     fgSetDouble("/environment/params/base-wind-speed-kt",
108                 fgGetDouble("/environment/wind-speed-kt"));
109   if (!fgHasNode("/environment/params/gust-wind-speed-kt"))
110     fgSetDouble("/environment/params/gust-wind-speed-kt",
111                 fgGetDouble("/environment/params/base-wind-speed-kt"));
112
113   _base_wind_speed_node =
114     fgGetNode("/environment/params/base-wind-speed-kt", true);
115   _gust_wind_speed_node =
116     fgGetNode("/environment/params/gust-wind-speed-kt", true);
117
118   _current_wind_speed_kt = _base_wind_speed_node->getDoubleValue();
119   _delta_wind_speed_kt = 0.1;
120 }
121
122 void
123 FGUserDefEnvironmentCtrl::update (double dt)
124 {
125   double base_wind_speed = _base_wind_speed_node->getDoubleValue();
126   double gust_wind_speed = _gust_wind_speed_node->getDoubleValue();
127
128   if (gust_wind_speed < base_wind_speed) {
129       gust_wind_speed = base_wind_speed;
130       _gust_wind_speed_node->setDoubleValue(gust_wind_speed);
131   }
132
133   if (base_wind_speed == gust_wind_speed) {
134     _current_wind_speed_kt = base_wind_speed;
135   } else {
136     int rn = rand() % 128;
137     int sign = (_delta_wind_speed_kt < 0 ? -1 : 1);
138     double gust = _current_wind_speed_kt - base_wind_speed;
139     double incr = gust / 50;
140
141     if (rn == 0)
142       _delta_wind_speed_kt = - _delta_wind_speed_kt;
143     else if (rn < 4)
144       _delta_wind_speed_kt -= incr * sign;
145     else if (rn < 16)
146       _delta_wind_speed_kt += incr * sign;
147
148     _current_wind_speed_kt += _delta_wind_speed_kt;
149
150     if (_current_wind_speed_kt < base_wind_speed) {
151       _current_wind_speed_kt = base_wind_speed;
152       _delta_wind_speed_kt = 0.01;
153     } else if (_current_wind_speed_kt > gust_wind_speed) {
154       _current_wind_speed_kt = gust_wind_speed;
155       _delta_wind_speed_kt = -0.01;
156     }
157   }
158   
159   if (_environment != 0)
160     _environment->set_wind_speed_kt(_current_wind_speed_kt);
161 }
162
163
164 \f
165 ////////////////////////////////////////////////////////////////////////
166 // Implementation of FGInterpolateEnvironmentCtrl.
167 ////////////////////////////////////////////////////////////////////////
168
169 FGInterpolateEnvironmentCtrl::FGInterpolateEnvironmentCtrl ()
170 {
171 }
172
173 FGInterpolateEnvironmentCtrl::~FGInterpolateEnvironmentCtrl ()
174 {
175     int i;
176     for (i = 0; i < _boundary_table.size(); i++)
177         delete _boundary_table[i];
178     for (i = 0; i < _aloft_table.size(); i++)
179         delete _aloft_table[i];
180 }
181
182
183
184 void
185 FGInterpolateEnvironmentCtrl::init ()
186 {
187     read_table(fgGetNode("/environment/config/boundary", true),
188                _boundary_table);
189     read_table(fgGetNode("/environment/config/aloft", true),
190                _aloft_table);
191 }
192
193 void
194 FGInterpolateEnvironmentCtrl::reinit ()
195 {
196     int i;
197     for (i = 0; i < _boundary_table.size(); i++)
198         delete _boundary_table[i];
199     for (i = 0; i < _aloft_table.size(); i++)
200         delete _aloft_table[i];
201     _boundary_table.clear();
202     _aloft_table.clear();
203     init();
204 }
205
206 void
207 FGInterpolateEnvironmentCtrl::read_table (const SGPropertyNode * node,
208                                           vector<bucket *> &table)
209 {
210     for (int i = 0; i < node->nChildren(); i++) {
211         const SGPropertyNode * child = node->getChild(i);
212         if (!strcmp(child->getName(), "entry") &&
213             child->getStringValue("elevation-ft", "")[0] != '\0') {
214             bucket * b = new bucket;
215             if (i > 0)
216                 b->environment.copy(table[i-1]->environment);
217             b->environment.read(child);
218             b->altitude_ft = b->environment.get_elevation_ft();
219             table.push_back(b);
220         }
221     }
222     sort(table.begin(), table.end());
223 }
224
225 void
226 FGInterpolateEnvironmentCtrl::update (double delta_time_sec)
227 {
228                                 // FIXME
229     double altitude_ft = fgGetDouble("/position/altitude-ft");
230     double altitude_agl_ft = fgGetDouble("/position/altitude-agl-ft");
231     double boundary_transition =
232         fgGetDouble("/environment/config/boundary-transition-ft", 500);
233
234     double ground_elevation_ft = altitude_ft - altitude_agl_ft;
235
236     int length = _boundary_table.size();
237
238     if (length > 0) {
239                                 // boundary table
240         double boundary_limit = _boundary_table[length-1]->altitude_ft;
241         if (boundary_limit >= altitude_agl_ft) {
242             do_interpolate(_boundary_table, altitude_agl_ft,
243                            _environment);
244             return;
245         } else if ((boundary_limit + boundary_transition) >= altitude_agl_ft) {
246                                 // both tables
247             do_interpolate(_boundary_table, altitude_agl_ft, &env1);
248             do_interpolate(_aloft_table, altitude_ft, &env2);
249             double fraction =
250                 (altitude_agl_ft - boundary_limit) / boundary_transition;
251             interpolate(&env1, &env2, fraction, _environment);
252             return;
253         }
254     }
255
256                                 // aloft table
257     do_interpolate(_aloft_table, altitude_ft, _environment);
258 }
259
260 void
261 FGInterpolateEnvironmentCtrl::do_interpolate (vector<bucket *> &table,
262                                               double altitude_ft,
263                                               FGEnvironment * environment)
264 {
265     int length = table.size();
266     if (length == 0)
267         return;
268
269                                 // Boundary conditions
270     if ((length == 1) || (table[0]->altitude_ft >= altitude_ft)) {
271         environment->copy(table[0]->environment);
272         return;
273     } else if (table[length-1]->altitude_ft <= altitude_ft) {
274         environment->copy(table[length-1]->environment);
275         return;
276     }
277         
278                                 // Search the interpolation table
279     for (int i = 0; i < length - 1; i++) {
280         if ((i == length - 1) || (table[i]->altitude_ft <= altitude_ft)) {
281                 FGEnvironment * env1 = &(table[i]->environment);
282                 FGEnvironment * env2 = &(table[i+1]->environment);
283                 double fraction;
284                 if (table[i]->altitude_ft == table[i+1]->altitude_ft)
285                     fraction = 1.0;
286                 else
287                     fraction =
288                         ((altitude_ft - table[i]->altitude_ft) /
289                          (table[i+1]->altitude_ft - table[i]->altitude_ft));
290                 interpolate(env1, env2, fraction, environment);
291
292                 return;
293         }
294     }
295 }
296
297 bool
298 FGInterpolateEnvironmentCtrl::bucket::operator< (const bucket &b) const
299 {
300     return (altitude_ft < b.altitude_ft);
301 }
302
303
304 // end of environment_ctrl.cxx