X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FEnvironment%2Fenvironment_ctrl.cxx;h=cf9c6505faefd68dff5f2cdfabb23f86666f19d2;hb=c6f88e5b9be767d93fd34f3b01c0e949fbd0044b;hp=82af0e02725cdb0a1d263db441ce7fe8b81d17da;hpb=e23f731ef773c79fe4cbd1c994a1f12eff661259;p=flightgear.git diff --git a/src/Environment/environment_ctrl.cxx b/src/Environment/environment_ctrl.cxx index 82af0e027..cf9c6505f 100644 --- a/src/Environment/environment_ctrl.cxx +++ b/src/Environment/environment_ctrl.cxx @@ -24,8 +24,6 @@ # include "config.h" #endif -#include -#include #include #include @@ -36,12 +34,20 @@ #include
#include
+#include "Environment/fgmetar.hxx" #include "environment_mgr.hxx" #include "environment_ctrl.hxx" -SG_USING_STD(sort); - +using std::sort; +class AirportWithMetar : public FGAirport::AirportFilter +{ +public: + virtual bool passAirport(FGAirport* aApt) const + { + return aApt->getMetar(); + } +}; //////////////////////////////////////////////////////////////////////// // Implementation of FGEnvironmentCtrl abstract base class. @@ -325,7 +331,6 @@ FGInterpolateEnvironmentCtrl::bucket::lessThan(bucket *a, bucket *b) FGMetarEnvironmentCtrl::FGMetarEnvironmentCtrl () : env( new FGInterpolateEnvironmentCtrl ), - _icao( "" ), metar_loaded( false ), search_interval_sec( 60.0 ), // 1 minute same_station_interval_sec( 900.0 ), // 15 minutes @@ -345,6 +350,7 @@ FGMetarEnvironmentCtrl::FGMetarEnvironmentCtrl () MaxCloudAltitudeChangeFtSec( 20.0 ), MaxCloudThicknessChangeFtSec( 50.0 ), MaxCloudInterpolationHeightFt( 5000.0 ), + MaxCloudInterpolationDeltaFt( 4000.0 ), _error_count( 0 ), _stale_count( 0 ), @@ -353,7 +359,8 @@ FGMetarEnvironmentCtrl::FGMetarEnvironmentCtrl () { #if defined(ENABLE_THREADS) thread = new MetarThread(this); - thread->start( 1 ); + thread->setProcessorAffinity(1); + thread->start(); #endif // ENABLE_THREADS } @@ -400,6 +407,9 @@ FGMetarEnvironmentCtrl::update_env_config () double pressure; double temp; double dewpoint; + + // If we aren't in the METAR scenario, don't attempt to interpolate. + if (strcmp(fgGetString("/environment/weather-scenario", "METAR"), "METAR")) return; if (metar_loaded) { // Generate interpolated values between the METAR and the current @@ -428,15 +438,19 @@ FGMetarEnvironmentCtrl::update_env_config () // factor by the maximum wind change. double x = fabs(current[0] - metar[0]); double y = fabs(current[1] - metar[1]); - double dx = x / (x + y); - double dy = 1 - dx; - double maxdx = dx * MaxWindChangeKtsSec; - double maxdy = dy * MaxWindChangeKtsSec; + // 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); + // 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)) { @@ -517,12 +531,15 @@ FGMetarEnvironmentCtrl::update_env_config () double current_alt = fgGetDouble(s); double required_alt = (*layer)->getDoubleValue("elevation-ft"); - if (current_alt < -9000 || required_alt < -9000 - || fabs(aircraft_alt - required_alt) > MaxCloudInterpolationHeightFt) { - // We don't interpolate any values that are too high above us, - // or too far below us to be visible. Nor do we interpolate - // values to or from -9999, which is used as a placeholder - // when there isn't actually a cloud layer present. + if (current_alt < -9000 || required_alt < -9000 || + fabs(aircraft_alt - required_alt) > MaxCloudInterpolationHeightFt || + fabs(current_alt - required_alt) > MaxCloudInterpolationDeltaFt) { + // We don't interpolate any layers that are + // - too far above us to be visible + // - too far below us to be visible + // - with too large a difference to make interpolation sensible + // - to or from -9999 (used as a placeholder) + // - any values that are too high above us, snprintf(s, 128, cl, i); strncat(s, "/elevation-ft", 128); if (current_alt != required_alt) @@ -568,7 +585,7 @@ FGMetarEnvironmentCtrl::update_env_config () dewpoint = fgGetDouble("/environment/metar/dewpoint-degc"); // Set the cloud layers by copying over the METAR versions. - SGPropertyNode * clouds = fgGetNode("/environment/metar/clouds"); + SGPropertyNode * clouds = fgGetNode("/environment/metar/clouds", true); vector layers = clouds->getChildren("layer"); vector::const_iterator layer; @@ -595,6 +612,9 @@ FGMetarEnvironmentCtrl::update_env_config () strncat(s, "/span-m", 128); fgSetDouble(s, 40000.0); } + + // Force an update of the 3D clouds + fgSetDouble("/environment/rebuild-layers", 1.0); } fgSetupWind(dir_from, dir_to, speed, gust); @@ -631,10 +651,9 @@ double FGMetarEnvironmentCtrl::interpolate_val(double currentval, void FGMetarEnvironmentCtrl::init () { - const SGPropertyNode *longitude - = fgGetNode( "/position/longitude-deg", true ); - const SGPropertyNode *latitude - = fgGetNode( "/position/latitude-deg", true ); + SGGeod pos = SGGeod::fromDeg( + fgGetDouble("/position/longitude-deg", true), + fgGetDouble( "/position/latitude-deg", true)); metar_loaded = false; bool found_metar = false; @@ -645,32 +664,31 @@ FGMetarEnvironmentCtrl::init () metar_max_age->setLongValue(0); while ( !found_metar && (_error_count < 3) ) { - const FGAirport* a = globals->get_airports() - ->search( longitude->getDoubleValue(), - latitude->getDoubleValue(), - true ); - if ( a ) { - FGMetarResult result = fetch_data( a->getId() ); - if ( result.m != NULL ) { - SG_LOG( SG_GENERAL, SG_INFO, "closest station w/ metar = " - << a->getId()); - last_apt = a; - _icao = a->getId(); - search_elapsed = 0.0; - fetch_elapsed = 0.0; - update_metar_properties( result.m ); - update_env_config(); - env->init(); - found_metar = true; - } else { - // mark as no metar so it doesn't show up in subsequent - // searches. - SG_LOG( SG_GENERAL, SG_INFO, "no metar at metar = " - << a->getId() ); - globals->get_airports()->no_metar( a->getId() ); - } + AirportWithMetar filter; + FGAirport* a = FGAirport::findClosest(pos, 10000.0, &filter); + if (!a) { + break; } - } + + FGMetarResult result = fetch_data(a); + if ( result.m != NULL ) { + SG_LOG( SG_GENERAL, SG_INFO, "closest station w/ metar = " + << a->ident()); + last_apt = a; + search_elapsed = 0.0; + fetch_elapsed = 0.0; + update_metar_properties( result.m ); + update_env_config(); + env->init(); + found_metar = true; + } else { + // mark as no metar so it doesn't show up in subsequent + // searches. + SG_LOG( SG_GENERAL, SG_INFO, "no metar at metar = " << a->ident() ); + a->setMetar(false); + } + } // of airprot-with-metar search iteration + metar_max_age->setLongValue(max_age); } @@ -679,10 +697,7 @@ FGMetarEnvironmentCtrl::reinit () { _error_count = 0; _error_dt = 0.0; - -#if 0 - update_env_config(); -#endif + metar_loaded = false; env->reinit(); } @@ -690,7 +705,6 @@ FGMetarEnvironmentCtrl::reinit () void FGMetarEnvironmentCtrl::update(double delta_time_sec) { - _dt += delta_time_sec; if (_error_count >= 3) return; @@ -701,6 +715,9 @@ FGMetarEnvironmentCtrl::update(double delta_time_sec) = fgGetNode( "/position/longitude-deg", true ); static const SGPropertyNode *latitude = fgGetNode( "/position/latitude-deg", true ); + SGGeod pos = SGGeod::fromDeg(longitude->getDoubleValue(), + latitude->getDoubleValue()); + search_elapsed += delta_time_sec; fetch_elapsed += delta_time_sec; interpolate_elapsed += delta_time_sec; @@ -708,19 +725,16 @@ FGMetarEnvironmentCtrl::update(double delta_time_sec) // if time for a new search request, push it onto the request // queue if ( search_elapsed > search_interval_sec ) { - const FGAirport* a = globals->get_airports() - ->search( longitude->getDoubleValue(), - latitude->getDoubleValue(), - true ); - if ( a ) { - if ( !last_apt || last_apt->getId() != a->getId() + AirportWithMetar filter; + FGAirport* a = FGAirport::findClosest(pos, 10000.0, &filter); + if (a) { + if ( !last_apt || last_apt->ident() != a->ident() || fetch_elapsed > same_station_interval_sec ) { SG_LOG( SG_GENERAL, SG_INFO, "closest station w/ metar = " - << a->getId()); - request_queue.push( a->getId() ); + << a->ident()); + request_queue.push(a); last_apt = a; - _icao = a->getId(); search_elapsed = 0.0; fetch_elapsed = 0.0; } else { @@ -728,8 +742,9 @@ FGMetarEnvironmentCtrl::update(double delta_time_sec) SG_LOG( SG_GENERAL, SG_INFO, "same station, waiting = " << same_station_interval_sec - fetch_elapsed ); } + } else { - SG_LOG( SG_GENERAL, SG_WARN, + SG_LOG( SG_GENERAL, SG_WARN, "Unable to find any airports with metar" ); } } else if ( interpolate_elapsed > EnvironmentUpdatePeriodSec ) { @@ -741,15 +756,15 @@ FGMetarEnvironmentCtrl::update(double delta_time_sec) #if !defined(ENABLE_THREADS) // No loader thread running so manually fetch the data - string id = ""; + FGAirport* apt = NULL; while ( !request_queue.empty() ) { - id = request_queue.front(); + apt = request_queue.front(); request_queue.pop(); } - if ( !id.empty() ) { - SG_LOG( SG_GENERAL, SG_INFO, "inline fetching = " << id ); - result = fetch_data( id ); + if (apt) { + SG_LOG( SG_GENERAL, SG_INFO, "inline fetching = " << apt->ident() ); + result = fetch_data( apt ); result_queue.push( result ); } #endif // ENABLE_THREADS @@ -767,8 +782,8 @@ FGMetarEnvironmentCtrl::update(double delta_time_sec) // mark as no metar so it doesn't show up in subsequent // searches, and signal an immediate re-search. SG_LOG( SG_GENERAL, SG_WARN, - "no metar at station = " << result.icao ); - globals->get_airports()->no_metar( result.icao ); + "no metar at station = " << result.airport->ident() ); + result.airport->setMetar(false); search_elapsed = 9999.0; } } @@ -784,10 +799,10 @@ FGMetarEnvironmentCtrl::setEnvironment (FGEnvironment * environment) } FGMetarResult -FGMetarEnvironmentCtrl::fetch_data( const string &icao ) +FGMetarEnvironmentCtrl::fetch_data(FGAirport* apt) { FGMetarResult result; - result.icao = icao; + result.airport = apt; // if the last error was more than three seconds ago, // then pretent nothing happened. @@ -799,18 +814,14 @@ FGMetarEnvironmentCtrl::fetch_data( const string &icao ) _error_count = 0; } - // fetch station elevation if exists - const FGAirport* a = globals->get_airports()->search( icao ); - if ( a ) { - station_elevation_ft = a->getElevation(); - } + station_elevation_ft = apt->getElevation(); // fetch current metar data try { string host = proxy_host->getStringValue(); string auth = proxy_auth->getStringValue(); string port = proxy_port->getStringValue(); - result.m = new FGMetar( icao, host, port, auth); + result.m = new FGMetar( apt->ident(), host, port, auth); long max_age = metar_max_age->getLongValue(); long age = result.m->getAge_min(); @@ -952,7 +963,7 @@ FGMetarEnvironmentCtrl::update_metar_properties( const FGMetar *m ) void FGMetarEnvironmentCtrl::thread_stop() { - request_queue.push( string() ); // ask thread to terminate + request_queue.push(NULL); // ask thread to terminate thread->join(); } @@ -961,11 +972,11 @@ FGMetarEnvironmentCtrl::MetarThread::run() { while ( true ) { - string icao = fetcher->request_queue.pop(); - if (icao.empty()) + FGAirport* apt = fetcher->request_queue.pop(); + if (!apt) return; - SG_LOG( SG_GENERAL, SG_INFO, "Thread: fetch metar data = " << icao ); - FGMetarResult result = fetcher->fetch_data( icao ); + SG_LOG( SG_GENERAL, SG_INFO, "Thread: fetch metar data = " << apt->ident() ); + FGMetarResult result = fetcher->fetch_data( apt ); fetcher->result_queue.push( result ); } }