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>
26 #include <Main/fg_props.hxx>
28 #include "environment_ctrl.hxx"
32 ////////////////////////////////////////////////////////////////////////
33 // Implementation of FGEnvironmentCtrl abstract base class.
34 ////////////////////////////////////////////////////////////////////////
36 FGEnvironmentCtrl::FGEnvironmentCtrl ()
44 FGEnvironmentCtrl::~FGEnvironmentCtrl ()
49 FGEnvironmentCtrl::setEnvironment (FGEnvironment * environment)
51 _environment = environment;
55 FGEnvironmentCtrl::setLongitudeDeg (double lon_deg)
61 FGEnvironmentCtrl::setLatitudeDeg (double lat_deg)
67 FGEnvironmentCtrl::setElevationFt (double elev_ft)
73 FGEnvironmentCtrl::setPosition (double lon_deg, double lat_deg, double elev_ft)
82 ////////////////////////////////////////////////////////////////////////
83 // Implementation of FGUserDefEnvironmentCtrl.
84 ////////////////////////////////////////////////////////////////////////
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)
94 FGUserDefEnvironmentCtrl::~FGUserDefEnvironmentCtrl ()
99 FGUserDefEnvironmentCtrl::init ()
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"));
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);
114 _current_wind_speed_kt = _base_wind_speed_node->getDoubleValue();
115 _delta_wind_speed_kt = 0.1;
119 FGUserDefEnvironmentCtrl::update (double dt)
121 double base_wind_speed = _base_wind_speed_node->getDoubleValue();
122 double gust_wind_speed = _gust_wind_speed_node->getDoubleValue();
124 if (gust_wind_speed < base_wind_speed) {
125 gust_wind_speed = base_wind_speed;
126 _gust_wind_speed_node->setDoubleValue(gust_wind_speed);
129 if (base_wind_speed == gust_wind_speed) {
130 _current_wind_speed_kt = base_wind_speed;
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;
138 _delta_wind_speed_kt = - _delta_wind_speed_kt;
140 _delta_wind_speed_kt -= incr * sign;
142 _delta_wind_speed_kt += incr * sign;
144 _current_wind_speed_kt += _delta_wind_speed_kt;
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;
155 if (_environment != 0)
156 _environment->set_wind_speed_kt(_current_wind_speed_kt);
161 ////////////////////////////////////////////////////////////////////////
162 // Implementation of FGInterpolateEnvironmentCtrl.
163 ////////////////////////////////////////////////////////////////////////
165 FGInterpolateEnvironmentCtrl::FGInterpolateEnvironmentCtrl ()
169 FGInterpolateEnvironmentCtrl::~FGInterpolateEnvironmentCtrl ()
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];
180 FGInterpolateEnvironmentCtrl::init ()
182 read_table(fgGetNode("/environment/config/boundary", true),
184 read_table(fgGetNode("/environment/config/aloft", true),
189 FGInterpolateEnvironmentCtrl::reinit ()
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();
201 FGInterpolateEnvironmentCtrl::read_table (const SGPropertyNode * node,
202 vector<bucket *> &table)
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;
210 b->environment.copy(table[i-1]->environment);
211 b->environment.read(child);
212 b->altitude_ft = b->environment.get_elevation_ft();
216 sort(table.begin(), table.end());
220 FGInterpolateEnvironmentCtrl::update (double delta_time_sec)
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);
228 double ground_elevation_ft = altitude_ft - altitude_agl_ft;
230 int length = _boundary_table.size();
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,
239 } else if ((boundary_limit + boundary_transition) >= altitude_agl_ft) {
241 do_interpolate(_boundary_table, altitude_agl_ft, &env1);
242 do_interpolate(_aloft_table, altitude_ft, &env2);
244 (altitude_agl_ft - boundary_limit) / boundary_transition;
245 interpolate(&env1, &env2, fraction, _environment);
251 do_interpolate(_aloft_table, altitude_ft, _environment);
255 FGInterpolateEnvironmentCtrl::do_interpolate (vector<bucket *> &table,
257 FGEnvironment * environment)
259 int length = table.size();
263 // Boundary conditions
264 if ((length == 1) || (table[0]->altitude_ft >= altitude_ft)) {
265 environment->copy(table[0]->environment);
267 } else if (table[length-1]->altitude_ft <= altitude_ft) {
268 environment->copy(table[length-1]->environment);
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);
278 if (table[i]->altitude_ft == table[i+1]->altitude_ft)
282 ((altitude_ft - table[i]->altitude_ft) /
283 (table[i+1]->altitude_ft - table[i]->altitude_ft));
284 interpolate(env1, env2, fraction, environment);
292 FGInterpolateEnvironmentCtrl::bucket::operator< (const bucket &b) const
294 return (altitude_ft < b.altitude_ft);
298 // end of environment_ctrl.cxx