1 // environment_ctrl.cxx -- manager for natural environment information.
3 // Written by David Megginson, started February 2002.
5 // Copyright (C) 2002 David Megginson - david@megginson.com
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.
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.
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.
23 #include <simgear/debug/logstream.hxx>
28 #include <Main/fg_props.hxx>
30 #include "environment_ctrl.hxx"
36 ////////////////////////////////////////////////////////////////////////
37 // Implementation of FGEnvironmentCtrl abstract base class.
38 ////////////////////////////////////////////////////////////////////////
40 FGEnvironmentCtrl::FGEnvironmentCtrl ()
48 FGEnvironmentCtrl::~FGEnvironmentCtrl ()
53 FGEnvironmentCtrl::setEnvironment (FGEnvironment * environment)
55 _environment = environment;
59 FGEnvironmentCtrl::setLongitudeDeg (double lon_deg)
65 FGEnvironmentCtrl::setLatitudeDeg (double lat_deg)
71 FGEnvironmentCtrl::setElevationFt (double elev_ft)
77 FGEnvironmentCtrl::setPosition (double lon_deg, double lat_deg, double elev_ft)
86 ////////////////////////////////////////////////////////////////////////
87 // Implementation of FGUserDefEnvironmentCtrl.
88 ////////////////////////////////////////////////////////////////////////
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)
98 FGUserDefEnvironmentCtrl::~FGUserDefEnvironmentCtrl ()
103 FGUserDefEnvironmentCtrl::init ()
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"));
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);
118 _current_wind_speed_kt = _base_wind_speed_node->getDoubleValue();
119 _delta_wind_speed_kt = 0.1;
123 FGUserDefEnvironmentCtrl::update (double dt)
125 double base_wind_speed = _base_wind_speed_node->getDoubleValue();
126 double gust_wind_speed = _gust_wind_speed_node->getDoubleValue();
128 if (gust_wind_speed < base_wind_speed) {
129 gust_wind_speed = base_wind_speed;
130 _gust_wind_speed_node->setDoubleValue(gust_wind_speed);
133 if (base_wind_speed == gust_wind_speed) {
134 _current_wind_speed_kt = base_wind_speed;
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;
142 _delta_wind_speed_kt = - _delta_wind_speed_kt;
144 _delta_wind_speed_kt -= incr * sign;
146 _delta_wind_speed_kt += incr * sign;
148 _current_wind_speed_kt += _delta_wind_speed_kt;
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;
159 if (_environment != 0)
160 _environment->set_wind_speed_kt(_current_wind_speed_kt);
165 ////////////////////////////////////////////////////////////////////////
166 // Implementation of FGInterpolateEnvironmentCtrl.
167 ////////////////////////////////////////////////////////////////////////
169 FGInterpolateEnvironmentCtrl::FGInterpolateEnvironmentCtrl ()
173 FGInterpolateEnvironmentCtrl::~FGInterpolateEnvironmentCtrl ()
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];
185 FGInterpolateEnvironmentCtrl::init ()
187 read_table(fgGetNode("/environment/config/boundary", true),
189 read_table(fgGetNode("/environment/config/aloft", true),
194 FGInterpolateEnvironmentCtrl::reinit ()
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();
207 FGInterpolateEnvironmentCtrl::read_table (const SGPropertyNode * node,
208 vector<bucket *> &table)
210 for (int i = 0; i < node->nChildren(); i++) {
211 const SGPropertyNode * child = node->getChild(i);
212 if ( strcmp(child->getName(), "entry") == 0
213 && child->getStringValue("elevation-ft", "")[0] != '\0'
214 && ( child->getDoubleValue("elevation-ft") > 0.1 || i == 0 ) )
216 bucket * b = new bucket;
218 b->environment.copy(table[i-1]->environment);
219 b->environment.read(child);
220 b->altitude_ft = b->environment.get_elevation_ft();
224 sort(table.begin(), table.end());
228 FGInterpolateEnvironmentCtrl::update (double delta_time_sec)
231 double altitude_ft = fgGetDouble("/position/altitude-ft");
232 double altitude_agl_ft = fgGetDouble("/position/altitude-agl-ft");
233 double boundary_transition =
234 fgGetDouble("/environment/config/boundary-transition-ft", 500);
236 double ground_elevation_ft = altitude_ft - altitude_agl_ft;
238 int length = _boundary_table.size();
242 double boundary_limit = _boundary_table[length-1]->altitude_ft;
243 if (boundary_limit >= altitude_agl_ft) {
244 do_interpolate(_boundary_table, altitude_agl_ft,
247 } else if ((boundary_limit + boundary_transition) >= altitude_agl_ft) {
249 do_interpolate(_boundary_table, altitude_agl_ft, &env1);
250 do_interpolate(_aloft_table, altitude_ft, &env2);
252 (altitude_agl_ft - boundary_limit) / boundary_transition;
253 interpolate(&env1, &env2, fraction, _environment);
259 do_interpolate(_aloft_table, altitude_ft, _environment);
263 FGInterpolateEnvironmentCtrl::do_interpolate (vector<bucket *> &table,
265 FGEnvironment * environment)
267 int length = table.size();
271 // Boundary conditions
272 if ((length == 1) || (table[0]->altitude_ft >= altitude_ft)) {
273 environment->copy(table[0]->environment);
275 } else if (table[length-1]->altitude_ft <= altitude_ft) {
276 environment->copy(table[length-1]->environment);
280 // Search the interpolation table
281 for (int i = 0; i < length - 1; i++) {
282 if ((i == length - 1) || (table[i]->altitude_ft <= altitude_ft)) {
283 FGEnvironment * env1 = &(table[i]->environment);
284 FGEnvironment * env2 = &(table[i+1]->environment);
286 if (table[i]->altitude_ft == table[i+1]->altitude_ft)
290 ((altitude_ft - table[i]->altitude_ft) /
291 (table[i+1]->altitude_ft - table[i]->altitude_ft));
292 interpolate(env1, env2, fraction, environment);
300 FGInterpolateEnvironmentCtrl::bucket::operator< (const bucket &b) const
302 return (altitude_ft < b.altitude_ft);
306 // end of environment_ctrl.cxx