void
FGInterpolateEnvironmentCtrl::reinit ()
{
-// TODO: do we really need to throw away the old tables on reinit? Better recycle
- unsigned int i;
- for (i = 0; i < _boundary_table.size(); i++)
- delete _boundary_table[i];
- for (i = 0; i < _aloft_table.size(); i++)
- delete _aloft_table[i];
- _boundary_table.clear();
- _aloft_table.clear();
init();
}
void
FGInterpolateEnvironmentCtrl::read_table (const SGPropertyNode * node, vector<bucket *> &table)
{
- for (int i = 0; i < node->nChildren(); i++) {
+ double last_altitude_ft = 0.0;
+ double sort_required = false;
+ int i;
+
+ for (i = 0; i < node->nChildren(); i++) {
const SGPropertyNode * child = node->getChild(i);
if ( strcmp(child->getName(), "entry") == 0
&& child->getStringValue("elevation-ft", "")[0] != '\0'
&& ( child->getDoubleValue("elevation-ft") > 0.1 || i == 0 ) )
{
- bucket * b = new bucket;
+ bucket * b;
+ if( i < table.size() ) {
+ // recycle existing bucket
+ b = table[i];
+ } else {
+ // more nodes than buckets in table, add a new one
+ b = new bucket;
+ table.push_back(b);
+ }
if (i > 0)
b->environment.copy(table[i-1]->environment);
b->environment.read(child);
b->altitude_ft = b->environment.get_elevation_ft();
- table.push_back(b);
+
+ // check, if altitudes are in ascending order
+ if( b->altitude_ft < last_altitude_ft )
+ sort_required = true;
+ last_altitude_ft = b->altitude_ft;
}
}
- sort(table.begin(), table.end(), bucket::lessThan);
+ // remove leftover buckets
+ vector<bucket*>::iterator it = table.begin() + i;
+ while( it != table.end() )
+ table.erase( it );
+
+ if( sort_required )
+ sort(table.begin(), table.end(), bucket::lessThan);
}
void
do_interpolate(_boundary_table, altitude_agl_ft, _environment);
return;
} else if ((boundary_limit + boundary_transition) >= altitude_agl_ft) {
+ //TODO: this is 500ft above the top altitude of boundary layer
+ //shouldn't this be +/-250 ft off of the top altitude?
// both tables
do_interpolate(_boundary_table, altitude_agl_ft, &env1);
do_interpolate(_aloft_table, altitude_ft, &env2);
station_elevation_ft(0.0),
metar_valid(false),
setup_winds_aloft(true),
+ wind_interpolation_required(true),
// Interpolation constant definitions.
EnvironmentUpdatePeriodSec( 0.2 ),
MaxWindChangeKtsSec( 0.2 ),
MaxCloudInterpolationHeightFt( 5000.0 ),
MaxCloudInterpolationDeltaFt( 4000.0 )
{
+ windModulator = new FGBasicWindModulator();
+
metar_base_n = fgGetNode( "/environment/metar", true );
station_id_n = metar_base_n->getNode("station-id", true );
station_elevation_n = metar_base_n->getNode("station-elevation-ft", true );
base_wind_range_from_n = metar_base_n->getNode("base-wind-range-from", true );
base_wind_range_to_n = metar_base_n->getNode("base-wind-range-to", true );
base_wind_speed_n = metar_base_n->getNode("base-wind-speed-kt", true );
- base_wind_dir_n = metar_base_n->getNode("base-wind-dir-deg", true );
+ base_wind_dir_n = metar_base_n->getNode("base-wind-dir-deg", true );
gust_wind_speed_n = metar_base_n->getNode("gust-wind-speed-kt", true );
temperature_n = metar_base_n->getNode("temperature-degc", true );
dewpoint_n = metar_base_n->getNode("dewpoint-degc", true );
void FGMetarCtrl::bind ()
{
- fgTie("/environment/metar/valid", this, &FGMetarCtrl::get_valid );
- fgTie("/environment/params/metar-updates-environment", this, &FGMetarCtrl::get_enabled, &FGMetarCtrl::set_enabled );
- fgTie("/environment/params/metar-updates-winds-aloft", this, &FGMetarCtrl::get_setup_winds_aloft, &FGMetarCtrl::set_setup_winds_aloft );
+ fgTie("/environment/metar/valid", this, &FGMetarCtrl::get_valid );
+ fgTie("/environment/params/metar-updates-environment", this, &FGMetarCtrl::get_enabled, &FGMetarCtrl::set_enabled );
+ fgTie("/environment/params/metar-updates-winds-aloft", this, &FGMetarCtrl::get_setup_winds_aloft, &FGMetarCtrl::set_setup_winds_aloft );
}
void FGMetarCtrl::unbind ()
{
- fgUntie("/environment/metar/valid");
- fgUntie("/environment/params/metar-updates-environment");
- fgUntie("/environment/params/metar-updates-winds-aloft");
+ fgUntie("/environment/metar/valid");
+ fgUntie("/environment/params/metar-updates-environment");
+ fgUntie("/environment/params/metar-updates-winds-aloft");
}
// use a "command" to set station temp at station elevation
}
}
-static void setupWind( bool setup_aloft, double dir, double speed, double gust )
+static void setupWind( bool setup_boundary, bool setup_aloft, double dir, double speed, double gust )
{
- setupWindBranch( "boundary", dir, speed, gust );
+ if( setup_boundary )
+ setupWindBranch( "boundary", dir, speed, gust );
+
if( setup_aloft )
setupWindBranch( "aloft", dir, speed, gust );
}
FGMetarCtrl::init ()
{
first_update = true;
+ wind_interpolation_required = true;
}
void
init();
}
+static inline double convert_to_360( double d )
+{
+ if( d < 0.0 ) return d + 360.0;
+ if( d >= 360.0 ) return d - 360.0;
+ return d;
+}
+
+static inline double convert_to_180( double d )
+{
+ return d > 180.0 ? d - 360.0 : d;
+}
+
void
FGMetarCtrl::update(double dt)
{
if( dt <= 0 || !metar_valid ||!enabled)
return;
+ windModulator->update(dt);
// Interpolate the current configuration closer to the actual METAR
bool reinit_required = false;
double dir = base_wind_dir_n->getDoubleValue();
double speed = base_wind_speed_n->getDoubleValue();
double gust = gust_wind_speed_n->getDoubleValue();
- setupWind(setup_winds_aloft, dir, speed, gust);
+ setupWind(true, setup_winds_aloft, dir, speed, gust);
double metarvis = min_visibility_n->getDoubleValue();
fgDefaultWeatherValue("visibility-m", metarvis);
layer_rebuild_required = true;
} else {
- // Generate interpolated values between the METAR and the current
- // configuration.
-
- // Pick up the METAR wind values and convert them into a vector.
- double metar[2];
- double metar_speed = base_wind_speed_n->getDoubleValue();
- double metar_heading = base_wind_dir_n->getDoubleValue();
-
- metar[0] = metar_speed * sin(metar_heading * SG_DEGREES_TO_RADIANS );
- metar[1] = metar_speed * cos(metar_heading * SG_DEGREES_TO_RADIANS);
-
- // Convert the current wind values and convert them into a vector
- double current[2];
- double speed = boundary_wind_speed_n->getDoubleValue();
- double dir_from = boundary_wind_from_heading_n->getDoubleValue();;
-
- current[0] = speed * sin(dir_from * SG_DEGREES_TO_RADIANS );
- current[1] = speed * cos(dir_from * SG_DEGREES_TO_RADIANS );
-
- // Determine the maximum component-wise value that the wind can change.
- // First we determine the fraction in the X and Y component, then
- // factor by the maximum wind change.
- double x = fabs(current[0] - metar[0]);
- double y = fabs(current[1] - metar[1]);
-
- // only interpolate if we have a difference
- if (x + y > 0) {
- double dx = x / (x + y);
- double dy = 1 - dx;
-
- double maxdx = dx * MaxWindChangeKtsSec;
- double maxdy = dy * MaxWindChangeKtsSec;
-
- // Interpolate each component separately.
- current[0] = interpolate_val(current[0], metar[0], maxdx);
- current[1] = interpolate_val(current[1], metar[1], maxdy);
-
- // Now convert back to polar coordinates.
- if ((current[0] == 0.0) && (current[1] == 0.0)) {
- // Special case where there is no wind (otherwise atan2 barfs)
- speed = 0.0;
- } else {
- // Some real wind to convert back from. Work out the speed
- // and direction value in degrees.
- speed = sqrt((current[0] * current[0]) + (current[1] * current[1]));
- dir_from = (atan2(current[0], current[1]) * SG_RADIANS_TO_DEGREES );
-
- // Normalize the direction.
- if (dir_from < 0.0)
- dir_from += 360.0;
-
- SG_LOG( SG_GENERAL, SG_DEBUG, "Wind : " << dir_from << "@" << speed);
+ if( wind_interpolation_required ) {
+ // Generate interpolated values between the METAR and the current
+ // configuration.
+
+ // Pick up the METAR wind values and convert them into a vector.
+ double metar[2];
+ double metar_speed = base_wind_speed_n->getDoubleValue();
+ double metar_heading = base_wind_dir_n->getDoubleValue();
+
+ metar[0] = metar_speed * sin(metar_heading * SG_DEGREES_TO_RADIANS );
+ metar[1] = metar_speed * cos(metar_heading * SG_DEGREES_TO_RADIANS);
+
+ // Convert the current wind values and convert them into a vector
+ double current[2];
+ double speed = boundary_wind_speed_n->getDoubleValue();
+ double dir_from = boundary_wind_from_heading_n->getDoubleValue();;
+
+ current[0] = speed * sin(dir_from * SG_DEGREES_TO_RADIANS );
+ current[1] = speed * cos(dir_from * SG_DEGREES_TO_RADIANS );
+
+ // Determine the maximum component-wise value that the wind can change.
+ // First we determine the fraction in the X and Y component, then
+ // factor by the maximum wind change.
+ double x = fabs(current[0] - metar[0]);
+ double y = fabs(current[1] - metar[1]);
+
+ // only interpolate if we have a difference
+ if (x + y > 0.01 ) {
+ double dx = x / (x + y);
+ double dy = 1 - dx;
+
+ double maxdx = dx * MaxWindChangeKtsSec;
+ double maxdy = dy * MaxWindChangeKtsSec;
+
+ // Interpolate each component separately.
+ current[0] = interpolate_val(current[0], metar[0], maxdx);
+ current[1] = interpolate_val(current[1], metar[1], maxdy);
+
+ // Now convert back to polar coordinates.
+ if ((current[0] == 0.0) && (current[1] == 0.0)) {
+ // Special case where there is no wind (otherwise atan2 barfs)
+ speed = 0.0;
+ } else {
+ // Some real wind to convert back from. Work out the speed
+ // and direction value in degrees.
+ speed = sqrt((current[0] * current[0]) + (current[1] * current[1]));
+ dir_from = (atan2(current[0], current[1]) * SG_RADIANS_TO_DEGREES );
+
+ // Normalize the direction.
+ if (dir_from < 0.0)
+ dir_from += 360.0;
+
+ SG_LOG( SG_GENERAL, SG_DEBUG, "Wind : " << dir_from << "@" << speed);
+ }
+ double gust = gust_wind_speed_n->getDoubleValue();
+ setupWind(true, setup_winds_aloft, dir_from, speed, gust);
+ reinit_required = true;
+ } else {
+ wind_interpolation_required = false;
}
- double gust = gust_wind_speed_n->getDoubleValue();
- setupWind(setup_winds_aloft, dir_from, speed, gust);
+ } else { // if(wind_interpolation_required)
+ // interpolation of wind vector is finished, apply wind
+ // variations and gusts for the boundary layer only
+
+ // start with the main wind direction
+ double wind_dir = base_wind_dir_n->getDoubleValue();
+ double min = convert_to_180(base_wind_range_from_n->getDoubleValue());
+ double max = convert_to_180(base_wind_range_to_n->getDoubleValue());
+ if( max > min ) {
+ // if variable winds configured, modulate the wind direction
+ double f = windModulator->get_direction_offset_norm();
+ wind_dir = min+(max-min)*f;
+ double old = convert_to_180(boundary_wind_from_heading_n->getDoubleValue());
+ wind_dir = convert_to_360(fgGetLowPass(old, wind_dir, dt ));
+ }
+
+ // start with main wind speed
+ double wind_speed = base_wind_speed_n->getDoubleValue();
+ max = gust_wind_speed_n->getDoubleValue();
+ if( max > wind_speed ) {
+ // if gusts are configured, modulate wind magnitude
+ double f = windModulator->get_magnitude_factor_norm();
+ wind_speed = wind_speed+(max-wind_speed)*f;
+ wind_speed = fgGetLowPass(boundary_wind_speed_n->getDoubleValue(), wind_speed, dt );
+ }
+ setupWind(true, false, wind_dir, wind_speed, max);
reinit_required = true;
}
set_temp_at_altitude(temperature_n->getDoubleValue(), station_elevation_ft);
set_dewpoint_at_altitude(dewpoint_n->getDoubleValue(), station_elevation_ft);
+ //TODO: check if temperature/dewpoint have changed. This requires reinit.
// Force an update of the 3D clouds
if( layer_rebuild_required )
return;
}
+ wind_interpolation_required = true;
+
min_visibility_n->setDoubleValue( m->getMinVisibility().getVisibility_m() );
max_visibility_n->setDoubleValue( m->getMaxVisibility().getVisibility_m() );
}
#endif
-FGMetarFetcher::FGMetarFetcher()
- :
+FGMetarFetcher::FGMetarFetcher() :
#if defined(ENABLE_THREADS)
metar_thread(NULL),
#endif
{
longitude_n = fgGetNode( "/position/longitude-deg", true );
latitude_n = fgGetNode( "/position/latitude-deg", true );
- enable_n = fgGetNode( "/environment/params/real-world-weather-fetch", true );
+ enable_n = fgGetNode( "/environment/params/real-world-weather-fetch", true );
proxy_host_n = fgGetNode("/sim/presets/proxy/host", true);
proxy_port_n = fgGetNode("/sim/presets/proxy/port", true);
proxy_auth_n = fgGetNode("/sim/presets/proxy/authentication", true);
- max_age_n = fgGetNode("/environment/params/metar-max-age-min", true);
+ max_age_n = fgGetNode("/environment/params/metar-max-age-min", true);
output_n = fgGetNode("/environment/metar/data", true );
#if defined(ENABLE_THREADS)
#include <Navaids/positioned.hxx>
#include <Environment/environment.hxx>
+#include "fgwind.hxx"
// forward decls
class SGPropertyNode;
public:
- FGEnvironmentCtrl ();
- virtual ~FGEnvironmentCtrl ();
+ FGEnvironmentCtrl ();
+ virtual ~FGEnvironmentCtrl ();
- virtual void setEnvironment (FGEnvironment * environment);
+ virtual void setEnvironment (FGEnvironment * environment);
- virtual const FGEnvironment * getEnvironment () const { return _environment; }
+ virtual const FGEnvironment * getEnvironment () const { return _environment; }
- virtual void setLongitudeDeg (double lon_deg);
- virtual void setLatitudeDeg (double lat_deg);
- virtual void setElevationFt (double elev_ft);
- virtual void setPosition (double lon_deg, double lat_deg, double elev_ft);
+ virtual void setLongitudeDeg (double lon_deg);
+ virtual void setLatitudeDeg (double lat_deg);
+ virtual void setElevationFt (double elev_ft);
+ virtual void setPosition (double lon_deg, double lat_deg, double elev_ft);
- virtual double getLongitudeDeg () const { return _lon_deg; }
- virtual double getLatitudeDeg () const { return _lat_deg; }
- virtual double getElevationFt () const { return _elev_ft; }
+ virtual double getLongitudeDeg () const { return _lon_deg; }
+ virtual double getLatitudeDeg () const { return _lat_deg; }
+ virtual double getElevationFt () const { return _elev_ft; }
protected:
- FGEnvironment * _environment;
- double _lon_deg;
- double _lat_deg;
- double _elev_ft;
+ FGEnvironment * _environment;
+ double _lon_deg;
+ double _lat_deg;
+ double _elev_ft;
};
class FGInterpolateEnvironmentCtrl : public FGEnvironmentCtrl
{
public:
- FGInterpolateEnvironmentCtrl ();
- virtual ~FGInterpolateEnvironmentCtrl ();
-
- virtual void init ();
- virtual void reinit ();
- virtual void update (double delta_time_sec);
+ FGInterpolateEnvironmentCtrl ();
+ virtual ~FGInterpolateEnvironmentCtrl ();
+
+ virtual void init ();
+ virtual void reinit ();
+ virtual void update (double delta_time_sec);
private:
-
- struct bucket {
- double altitude_ft;
- FGEnvironment environment;
- bool operator< (const bucket &b) const;
- // LessThan predicate for bucket pointers.
- static bool lessThan(bucket *a, bucket *b);
- };
+
+ struct bucket {
+ double altitude_ft;
+ FGEnvironment environment;
+ bool operator< (const bucket &b) const;
+ // LessThan predicate for bucket pointers.
+ static bool lessThan(bucket *a, bucket *b);
+ };
- void read_table (const SGPropertyNode * node, std::vector<bucket *> &table);
- void do_interpolate (std::vector<bucket *> &table, double altitude_ft,
- FGEnvironment * environment);
+ void read_table (const SGPropertyNode * node, std::vector<bucket *> &table);
+ void do_interpolate (std::vector<bucket *> &table, double altitude_ft,
+ FGEnvironment * environment);
- FGEnvironment env1, env2; // temporaries
+ FGEnvironment env1, env2; // temporaries
- std::vector<bucket *> _boundary_table;
- std::vector<bucket *> _aloft_table;
+ std::vector<bucket *> _boundary_table;
+ std::vector<bucket *> _aloft_table;
SGPropertyNode_ptr altitude_n;
SGPropertyNode_ptr altitude_agl_n;
class FGMetarCtrl : public SGSubsystem
{
public:
- FGMetarCtrl (SGSubsystem * environmentCtrl);
- virtual ~FGMetarCtrl ();
+ FGMetarCtrl (SGSubsystem * environmentCtrl);
+ virtual ~FGMetarCtrl ();
- virtual void init ();
- virtual void reinit ();
- virtual void update (double delta_time_sec);
+ virtual void init ();
+ virtual void reinit ();
+ virtual void update (double delta_time_sec);
- void set_metar( const char * metar );
- const char * get_metar(void) const;
+ void set_metar( const char * metar );
+ const char * get_metar(void) const;
bool get_valid(void) const { return metar_valid; }
void set_enabled(bool _enabled) { enabled = _enabled; }
bool get_enabled(void) const { return enabled; }
private:
void bind();
void unbind();
- bool metar_valid;
- bool enabled;
+
+ SGSharedPtr<FGWindModulator> windModulator;
+ bool metar_valid;
+ bool enabled;
bool setup_winds_aloft;
- bool first_update;
- double station_elevation_ft;
- string metar;
- double interpolate_prop(const char * currentname, const char * requiredname, double dvalue);
- double interpolate_val(double currentval, double requiredval, double dvalue);
- const double EnvironmentUpdatePeriodSec; // Seconds between interpolations
- const double MaxWindChangeKtsSec; // Max wind change in kts/sec
- const double MaxVisChangePercentSec; // Max visibility change in %/sec
- const double MaxPressureChangeInHgSec; // Max pressure change in InHg/sec
- const double MaxCloudAltitudeChangeFtSec; // Max cloud altitude change in ft/s
- const double MaxCloudThicknessChangeFtSec; // Max cloud thickness change in ft/s
- const double MaxCloudInterpolationHeightFt; // Max distance from aircraft to
- // interpolate at. Any cloud
- // changes above this height
- // difference are not interpolated
- const double MaxCloudInterpolationDeltaFt; // Max difference in altitude to
- // interpolate. Any cloud changing height
- // by more than this value is not
- // interpolated
-
- SGSubsystem * _environmentCtrl;
-
- SGPropertyNode_ptr metar_base_n;
- SGPropertyNode_ptr station_id_n;
- SGPropertyNode_ptr station_elevation_n;
- SGPropertyNode_ptr min_visibility_n;
- SGPropertyNode_ptr max_visibility_n;
- SGPropertyNode_ptr base_wind_range_from_n;
- SGPropertyNode_ptr base_wind_range_to_n;
- SGPropertyNode_ptr base_wind_dir_n;
- SGPropertyNode_ptr base_wind_speed_n;
- SGPropertyNode_ptr gust_wind_speed_n;
- SGPropertyNode_ptr temperature_n;
- SGPropertyNode_ptr dewpoint_n;
- SGPropertyNode_ptr humidity_n;
- SGPropertyNode_ptr pressure_n;
- SGPropertyNode_ptr clouds_n;
- SGPropertyNode_ptr environment_clouds_n;
- SGPropertyNode_ptr rain_n;
- SGPropertyNode_ptr hail_n;
- SGPropertyNode_ptr snow_n;
- SGPropertyNode_ptr snow_cover_n;
- SGPropertyNode_ptr ground_elevation_n;
- SGPropertyNode_ptr longitude_n;
- SGPropertyNode_ptr latitude_n;
-
- SGPropertyNode_ptr boundary_wind_speed_n;
- SGPropertyNode_ptr boundary_wind_from_heading_n;
- SGPropertyNode_ptr boundary_visibility_n;
- SGPropertyNode_ptr boundary_sea_level_pressure_n;
+ bool first_update;
+ bool wind_interpolation_required;
+ double station_elevation_ft;
+ string metar;
+ double interpolate_prop(const char * currentname, const char * requiredname, double dvalue);
+ double interpolate_val(double currentval, double requiredval, double dvalue);
+ const double EnvironmentUpdatePeriodSec; // Seconds between interpolations
+ const double MaxWindChangeKtsSec; // Max wind change in kts/sec
+ const double MaxVisChangePercentSec; // Max visibility change in %/sec
+ const double MaxPressureChangeInHgSec; // Max pressure change in InHg/sec
+ const double MaxCloudAltitudeChangeFtSec; // Max cloud altitude change in ft/s
+ const double MaxCloudThicknessChangeFtSec; // Max cloud thickness change in ft/s
+ const double MaxCloudInterpolationHeightFt; // Max distance from aircraft to
+ // interpolate at. Any cloud
+ // changes above this height
+ // difference are not interpolated
+ const double MaxCloudInterpolationDeltaFt; // Max difference in altitude to
+ // interpolate. Any cloud changing height
+ // by more than this value is not
+ // interpolated
+
+ SGSubsystem * _environmentCtrl;
+
+ SGPropertyNode_ptr metar_base_n;
+ SGPropertyNode_ptr station_id_n;
+ SGPropertyNode_ptr station_elevation_n;
+ SGPropertyNode_ptr min_visibility_n;
+ SGPropertyNode_ptr max_visibility_n;
+ SGPropertyNode_ptr base_wind_range_from_n;
+ SGPropertyNode_ptr base_wind_range_to_n;
+ SGPropertyNode_ptr base_wind_dir_n;
+ SGPropertyNode_ptr base_wind_speed_n;
+ SGPropertyNode_ptr gust_wind_speed_n;
+ SGPropertyNode_ptr temperature_n;
+ SGPropertyNode_ptr dewpoint_n;
+ SGPropertyNode_ptr humidity_n;
+ SGPropertyNode_ptr pressure_n;
+ SGPropertyNode_ptr clouds_n;
+ SGPropertyNode_ptr environment_clouds_n;
+ SGPropertyNode_ptr rain_n;
+ SGPropertyNode_ptr hail_n;
+ SGPropertyNode_ptr snow_n;
+ SGPropertyNode_ptr snow_cover_n;
+ SGPropertyNode_ptr ground_elevation_n;
+ SGPropertyNode_ptr longitude_n;
+ SGPropertyNode_ptr latitude_n;
+
+ SGPropertyNode_ptr boundary_wind_speed_n;
+ SGPropertyNode_ptr boundary_wind_from_heading_n;
+ SGPropertyNode_ptr boundary_visibility_n;
+ SGPropertyNode_ptr boundary_sea_level_pressure_n;
private:
};
class FGMetarFetcher : public SGSubsystem
{
public:
- FGMetarFetcher();
- virtual ~FGMetarFetcher();
+ FGMetarFetcher();
+ virtual ~FGMetarFetcher();
- virtual void init ();
- virtual void reinit ();
- virtual void update (double delta_time_sec);
+ virtual void init ();
+ virtual void reinit ();
+ virtual void update (double delta_time_sec);
private:
- friend class MetarThread;
+ friend class MetarThread;
#if defined(ENABLE_THREADS)
- /**
- * FIFO queue which holds a pointer to the metar requests.
- */
- SGBlockingQueue <string> request_queue;
+ /**
+ * FIFO queue which holds a pointer to the metar requests.
+ */
+ SGBlockingQueue <string> request_queue;
- OpenThreads::Thread * metar_thread;
+ OpenThreads::Thread * metar_thread;
#endif
- void fetch( const string & id );
+ void fetch( const string & id );
- SGPropertyNode_ptr enable_n;
+ SGPropertyNode_ptr enable_n;
- SGPropertyNode_ptr longitude_n;
- SGPropertyNode_ptr latitude_n;
+ SGPropertyNode_ptr longitude_n;
+ SGPropertyNode_ptr latitude_n;
- SGPropertyNode_ptr proxy_host_n;
- SGPropertyNode_ptr proxy_port_n;
- SGPropertyNode_ptr proxy_auth_n;
- SGPropertyNode_ptr max_age_n;
+ SGPropertyNode_ptr proxy_host_n;
+ SGPropertyNode_ptr proxy_port_n;
+ SGPropertyNode_ptr proxy_auth_n;
+ SGPropertyNode_ptr max_age_n;
- SGPropertyNode_ptr output_n;
+ SGPropertyNode_ptr output_n;
- string current_airport_id;
- double fetch_timer;
- double search_timer;
- double error_timer;
+ string current_airport_id;
+ double fetch_timer;
+ double search_timer;
+ double error_timer;
- long _stale_count;
- long _error_count;
+ long _stale_count;
+ long _error_count;
};