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"
34 ////////////////////////////////////////////////////////////////////////
35 // Implementation of FGEnvironmentCtrl abstract base class.
36 ////////////////////////////////////////////////////////////////////////
38 FGEnvironmentCtrl::FGEnvironmentCtrl ()
46 FGEnvironmentCtrl::~FGEnvironmentCtrl ()
51 FGEnvironmentCtrl::setEnvironment (FGEnvironment * environment)
53 _environment = environment;
57 FGEnvironmentCtrl::setLongitudeDeg (double lon_deg)
63 FGEnvironmentCtrl::setLatitudeDeg (double lat_deg)
69 FGEnvironmentCtrl::setElevationFt (double elev_ft)
75 FGEnvironmentCtrl::setPosition (double lon_deg, double lat_deg, double elev_ft)
84 ////////////////////////////////////////////////////////////////////////
85 // Implementation of FGUserDefEnvironmentCtrl.
86 ////////////////////////////////////////////////////////////////////////
88 FGUserDefEnvironmentCtrl::FGUserDefEnvironmentCtrl ()
89 : _base_wind_speed_node(0),
90 _gust_wind_speed_node(0),
91 _current_wind_speed_kt(0),
92 _delta_wind_speed_kt(0)
96 FGUserDefEnvironmentCtrl::~FGUserDefEnvironmentCtrl ()
101 FGUserDefEnvironmentCtrl::init ()
103 // Fill in some defaults.
104 if (!fgHasNode("/environment/params/base-wind-speed-kt"))
105 fgSetDouble("/environment/params/base-wind-speed-kt",
106 fgGetDouble("/environment/wind-speed-kt"));
107 if (!fgHasNode("/environment/params/gust-wind-speed-kt"))
108 fgSetDouble("/environment/params/gust-wind-speed-kt",
109 fgGetDouble("/environment/params/base-wind-speed-kt"));
111 _base_wind_speed_node =
112 fgGetNode("/environment/params/base-wind-speed-kt", true);
113 _gust_wind_speed_node =
114 fgGetNode("/environment/params/gust-wind-speed-kt", true);
116 _current_wind_speed_kt = _base_wind_speed_node->getDoubleValue();
117 _delta_wind_speed_kt = 0.1;
121 FGUserDefEnvironmentCtrl::update (double dt)
123 double base_wind_speed = _base_wind_speed_node->getDoubleValue();
124 double gust_wind_speed = _gust_wind_speed_node->getDoubleValue();
126 if (gust_wind_speed < base_wind_speed) {
127 gust_wind_speed = base_wind_speed;
128 _gust_wind_speed_node->setDoubleValue(gust_wind_speed);
131 if (base_wind_speed == gust_wind_speed) {
132 _current_wind_speed_kt = base_wind_speed;
134 int rn = rand() % 128;
135 int sign = (_delta_wind_speed_kt < 0 ? -1 : 1);
136 double gust = _current_wind_speed_kt - base_wind_speed;
137 double incr = gust / 50;
140 _delta_wind_speed_kt = - _delta_wind_speed_kt;
142 _delta_wind_speed_kt -= incr * sign;
144 _delta_wind_speed_kt += incr * sign;
146 _current_wind_speed_kt += _delta_wind_speed_kt;
148 if (_current_wind_speed_kt < base_wind_speed) {
149 _current_wind_speed_kt = base_wind_speed;
150 _delta_wind_speed_kt = 0.01;
151 } else if (_current_wind_speed_kt > gust_wind_speed) {
152 _current_wind_speed_kt = gust_wind_speed;
153 _delta_wind_speed_kt = -0.01;
157 if (_environment != 0)
158 _environment->set_wind_speed_kt(_current_wind_speed_kt);
163 ////////////////////////////////////////////////////////////////////////
164 // Implementation of FGInterpolateEnvironmentCtrl.
165 ////////////////////////////////////////////////////////////////////////
167 FGInterpolateEnvironmentCtrl::FGInterpolateEnvironmentCtrl ()
171 FGInterpolateEnvironmentCtrl::~FGInterpolateEnvironmentCtrl ()
174 for (i = 0; i < _boundary_table.size(); i++)
175 delete _boundary_table[i];
176 for (i = 0; i < _aloft_table.size(); i++)
177 delete _aloft_table[i];
183 FGInterpolateEnvironmentCtrl::init ()
185 read_table(fgGetNode("/environment/config/boundary", true),
187 read_table(fgGetNode("/environment/config/aloft", true),
192 FGInterpolateEnvironmentCtrl::reinit ()
195 for (i = 0; i < _boundary_table.size(); i++)
196 delete _boundary_table[i];
197 for (i = 0; i < _aloft_table.size(); i++)
198 delete _aloft_table[i];
199 _boundary_table.clear();
200 _aloft_table.clear();
205 FGInterpolateEnvironmentCtrl::read_table (const SGPropertyNode * node,
206 vector<bucket *> &table)
208 for (int i = 0; i < node->nChildren(); i++) {
209 const SGPropertyNode * child = node->getChild(i);
210 if (!strcmp(child->getName(), "entry") &&
211 child->getStringValue("elevation-ft", "")[0] != '\0') {
212 bucket * b = new bucket;
214 b->environment.copy(table[i-1]->environment);
215 b->environment.read(child);
216 b->altitude_ft = b->environment.get_elevation_ft();
220 sort(table.begin(), table.end());
224 FGInterpolateEnvironmentCtrl::update (double delta_time_sec)
227 double altitude_ft = fgGetDouble("/position/altitude-ft");
228 double altitude_agl_ft = fgGetDouble("/position/altitude-agl-ft");
229 double boundary_transition =
230 fgGetDouble("/environment/config/boundary-transition-ft", 500);
232 double ground_elevation_ft = altitude_ft - altitude_agl_ft;
234 int length = _boundary_table.size();
238 double boundary_limit = _boundary_table[length-1]->altitude_ft;
239 if (boundary_limit >= altitude_agl_ft) {
240 do_interpolate(_boundary_table, altitude_agl_ft,
243 } else if ((boundary_limit + boundary_transition) >= altitude_agl_ft) {
245 do_interpolate(_boundary_table, altitude_agl_ft, &env1);
246 do_interpolate(_aloft_table, altitude_ft, &env2);
248 (altitude_agl_ft - boundary_limit) / boundary_transition;
249 interpolate(&env1, &env2, fraction, _environment);
255 do_interpolate(_aloft_table, altitude_ft, _environment);
259 FGInterpolateEnvironmentCtrl::do_interpolate (vector<bucket *> &table,
261 FGEnvironment * environment)
263 int length = table.size();
267 // Boundary conditions
268 if ((length == 1) || (table[0]->altitude_ft >= altitude_ft)) {
269 environment->copy(table[0]->environment);
271 } else if (table[length-1]->altitude_ft <= altitude_ft) {
272 environment->copy(table[length-1]->environment);
276 // Search the interpolation table
277 for (int i = 0; i < length - 1; i++) {
278 if ((i == length - 1) || (table[i]->altitude_ft <= altitude_ft)) {
279 FGEnvironment * env1 = &(table[i]->environment);
280 FGEnvironment * env2 = &(table[i+1]->environment);
282 if (table[i]->altitude_ft == table[i+1]->altitude_ft)
286 ((altitude_ft - table[i]->altitude_ft) /
287 (table[i+1]->altitude_ft - table[i]->altitude_ft));
288 interpolate(env1, env2, fraction, environment);
296 FGInterpolateEnvironmentCtrl::bucket::operator< (const bucket &b) const
298 return (altitude_ft < b.altitude_ft);
302 // end of environment_ctrl.cxx