]> git.mxchange.org Git - flightgear.git/commitdiff
Bugfix:
authortorsten <torsten>
Wed, 24 Mar 2010 14:25:36 +0000 (14:25 +0000)
committerTim Moore <timoore33@gmail.com>
Sat, 27 Mar 2010 13:19:05 +0000 (14:19 +0100)
- METAR changes caused strong aircraft movements if the station temperature or field elevation changed. Temperature and dewpoint are now also slowly interpolated to reach the new value.
- Probably unnoticed bug: calculation of the interpolation speed was wrong.
- some minor code-cleanup

src/Environment/environment_ctrl.cxx
src/Environment/environment_ctrl.hxx

index 0aa3572f6dca179ae109da33ddbe0ce45fc45490..6efcbde3ee747f3eb69bc90e32afcbfb4339fa56 100644 (file)
@@ -273,11 +273,13 @@ FGMetarCtrl::FGMetarCtrl( SGSubsystem * environmentCtrl )
        metar_valid(false),
        setup_winds_aloft(true),
        wind_interpolation_required(true),
+       metar_sealevel_temperature(15.0),
+       metar_sealevel_dewpoint(5.0),
        // Interpolation constant definitions.
-       EnvironmentUpdatePeriodSec( 0.2 ),
        MaxWindChangeKtsSec( 0.2 ),
        MaxVisChangePercentSec( 0.05 ),
-       MaxPressureChangeInHgSec( 0.0033 ),
+       MaxPressureChangeInHgSec( 0.0005 ), // approx 1hpa/min
+       MaxTemperatureChangeDegcSec(10.0/60.0), // approx 10degc/min
        MaxCloudAltitudeChangeFtSec( 20.0 ),
        MaxCloudThicknessChangeFtSec( 50.0 ),
        MaxCloudInterpolationHeightFt( 5000.0 ),
@@ -311,10 +313,12 @@ FGMetarCtrl::FGMetarCtrl( SGSubsystem * environmentCtrl )
        latitude_n = fgGetNode( "/position/latitude-deg", true );
        environment_clouds_n = fgGetNode("/environment/clouds");
 
-       boundary_wind_speed_n = fgGetNode("/environment/config/boundary/entry/wind-speed-kt");
-       boundary_wind_from_heading_n = fgGetNode("/environment/config/boundary/entry/wind-from-heading-deg");
-       boundary_visibility_n = fgGetNode("/environment/config/boundary/entry/visibility-m");
-       boundary_sea_level_pressure_n = fgGetNode("/environment/config/boundary/entry/pressure-sea-level-inhg");
+       boundary_wind_speed_n = fgGetNode("/environment/config/boundary/entry/wind-speed-kt", true );
+       boundary_wind_from_heading_n = fgGetNode("/environment/config/boundary/entry/wind-from-heading-deg", true );
+       boundary_visibility_n = fgGetNode("/environment/config/boundary/entry/visibility-m", true );
+       boundary_sea_level_pressure_n = fgGetNode("/environment/config/boundary/entry/pressure-sea-level-inhg", true );
+       boundary_sea_level_temperature_n = fgGetNode("/environment/config/boundary/entry/temperature-sea-level-degc", true );
+       boundary_sea_level_dewpoint_n = fgGetNode("/environment/config/boundary/entry/dewpoint-sea-level-degc", true );
 }
 
 FGMetarCtrl::~FGMetarCtrl ()
@@ -336,22 +340,26 @@ void FGMetarCtrl::unbind ()
 }
 
 // use a "command" to set station temp at station elevation
-static void set_temp_at_altitude( float temp_degc, float altitude_ft ) {
+static void set_temp_at_altitude( double temp_degc, double altitude_ft ) {
        SGPropertyNode args;
        SGPropertyNode *node = args.getNode("temp-degc", 0, true);
-       node->setFloatValue( temp_degc );
+       node->setDoubleValue( temp_degc );
        node = args.getNode("altitude-ft", 0, true);
-       node->setFloatValue( altitude_ft );
-       globals->get_commands()->execute("set-outside-air-temp-degc", &args);
+       node->setDoubleValue( altitude_ft );
+       globals->get_commands()->execute( altitude_ft == 0.0 ? 
+               "set-sea-level-air-temp-degc" : 
+               "set-outside-air-temp-degc", &args);
 }
 
-static void set_dewpoint_at_altitude( float dewpoint_degc, float altitude_ft ) {
+static void set_dewpoint_at_altitude( double dewpoint_degc, double altitude_ft ) {
        SGPropertyNode args;
        SGPropertyNode *node = args.getNode("dewpoint-degc", 0, true);
-       node->setFloatValue( dewpoint_degc );
+       node->setDoubleValue( dewpoint_degc );
        node = args.getNode("altitude-ft", 0, true);
-       node->setFloatValue( altitude_ft );
-       globals->get_commands()->execute("set-dewpoint-temp-degc", &args);
+       node->setDoubleValue( altitude_ft );
+       globals->get_commands()->execute( altitude_ft == 0.0 ?
+               "set-dewpoint-sea-level-air-temp-degc" :
+               "set-dewpoint-temp-degc", &args);
 }
 
 /*
@@ -403,10 +411,8 @@ static void setupWind( bool setup_aloft, double dir, double speed, double gust )
                setupWindBranch( "aloft", dir, speed, gust );
 }
 
-double FGMetarCtrl::interpolate_val(double currentval, double requiredval, double dt)
+double FGMetarCtrl::interpolate_val(double currentval, double requiredval, double dval )
 {
-       double dval = EnvironmentUpdatePeriodSec * dt;
-
        if (fabs(currentval - requiredval) < dval) return requiredval;
        if (currentval < requiredval) return (currentval + dval);
        if (currentval > requiredval) return (currentval - dval);
@@ -448,13 +454,12 @@ static inline double convert_to_180( double d )
 static double reducePressureSl(double metarPressure, double fieldHt,
                                double fieldTemp)
 {
-    double elev = fieldHt * SG_FEET_TO_METER;
-    double fieldPressure
-        = FGAtmo::fieldPressure(elev, metarPressure * atmodel::inHg);
-    double slPressure = P_layer(0, elev, fieldPressure,
-                                fieldTemp + atmodel::freezing,
-                                atmodel::ISA::lam0);
-    return slPressure / atmodel::inHg;
+       double elev = fieldHt * SG_FEET_TO_METER;
+       double fieldPressure
+               = FGAtmo::fieldPressure(elev, metarPressure * atmodel::inHg);
+       double slPressure = P_layer(0, elev, fieldPressure,
+               fieldTemp + atmodel::freezing, atmodel::ISA::lam0);
+       return slPressure / atmodel::inHg;
 }
 
 void
@@ -468,7 +473,7 @@ FGMetarCtrl::update(double dt)
 
        bool reinit_required = false;
        bool layer_rebuild_required = false;
-        double station_elevation_ft = station_elevation_n->getDoubleValue();
+       double station_elevation_ft = station_elevation_n->getDoubleValue();
 
        if (first_update) {
                double dir = base_wind_dir_n->getDoubleValue()+magnetic_variation_n->getDoubleValue();
@@ -479,11 +484,14 @@ FGMetarCtrl::update(double dt)
                double metarvis = min_visibility_n->getDoubleValue();
                fgDefaultWeatherValue("visibility-m", metarvis);
 
+               set_temp_at_altitude(temperature_n->getDoubleValue(), station_elevation_ft);
+               set_dewpoint_at_altitude(dewpoint_n->getDoubleValue(), station_elevation_ft);
+
                double metarpressure = pressure_n->getDoubleValue();
                fgDefaultWeatherValue("pressure-sea-level-inhg",
-                                      reducePressureSl(metarpressure,
-                                                       station_elevation_ft,
-                                                       temperature_n->getDoubleValue()));
+                       reducePressureSl(metarpressure,
+                       station_elevation_ft,
+                       temperature_n->getDoubleValue()));
 
                // We haven't already loaded a METAR, so apply it immediately.
                vector<SGPropertyNode_ptr> layers = clouds_n->getChildren("layer");
@@ -543,8 +551,8 @@ FGMetarCtrl::update(double dt)
                                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);
+                               current[0] = interpolate_val(current[0], metar[0], maxdx*dt);
+                               current[1] = interpolate_val(current[1], metar[1], maxdy*dt);
 
                                // Now convert back to polar coordinates.
                                if ((fabs(current[0]) > 0.1) || (fabs(current[1]) > 0.1)) {
@@ -615,7 +623,7 @@ FGMetarCtrl::update(double dt)
                        double currentxval = log(1000.0 + vis);
                        double metarxval = log(1000.0 + metarvis);
 
-                       currentxval = interpolate_val(currentxval, metarxval, MaxVisChangePercentSec);
+                       currentxval = interpolate_val(currentxval, metarxval, MaxVisChangePercentSec*dt);
 
                        // Now convert back from an X-value to a straightforward visibility.
                        vis = exp(currentxval) - 1000.0;
@@ -625,15 +633,28 @@ FGMetarCtrl::update(double dt)
 
                double pressure = boundary_sea_level_pressure_n->getDoubleValue();
                double metarpressure = pressure_n->getDoubleValue();
-                double newpressure = reducePressureSl(metarpressure,
-                                                      station_elevation_ft,
-                                                      temperature_n->getDoubleValue());
+               double newpressure = reducePressureSl(metarpressure,
+                       station_elevation_ft,
+                       temperature_n->getDoubleValue());
                if( pressure != newpressure ) {
-                       pressure = interpolate_val( pressure, newpressure, MaxPressureChangeInHgSec );
+                       pressure = interpolate_val( pressure, newpressure, MaxPressureChangeInHgSec*dt );
                        fgDefaultWeatherValue("pressure-sea-level-inhg", pressure);
                        reinit_required = true;
                }
 
+               {
+                       double temperature = boundary_sea_level_temperature_n->getDoubleValue();
+                       double dewpoint = boundary_sea_level_dewpoint_n->getDoubleValue();
+                       if( metar_sealevel_temperature != temperature ) {
+                               temperature = interpolate_val( temperature, metar_sealevel_temperature, MaxTemperatureChangeDegcSec*dt );
+                               set_temp_at_altitude( temperature, 0.0 );
+                       }
+                       if( metar_sealevel_dewpoint != dewpoint ) {
+                               dewpoint = interpolate_val( dewpoint, metar_sealevel_dewpoint, MaxTemperatureChangeDegcSec*dt );
+                               set_dewpoint_at_altitude( dewpoint, 0.0 );
+                       }
+               }
+
                // Set the cloud layers by interpolating over the METAR versions.
                vector<SGPropertyNode_ptr> layers = clouds_n->getChildren("layer");
                vector<SGPropertyNode_ptr>::const_iterator layer;
@@ -682,7 +703,7 @@ FGMetarCtrl::update(double dt)
                        } else {
                                // Interpolate the other values in the usual way
                                if (current_alt != required_alt) {
-                                       current_alt = interpolate_val(current_alt, required_alt, MaxCloudAltitudeChangeFtSec);
+                                       current_alt = interpolate_val(current_alt, required_alt, MaxCloudAltitudeChangeFtSec*dt);
                                        target->setDoubleValue("elevation-ft", current_alt);
                                }
 
@@ -691,15 +712,12 @@ FGMetarCtrl::update(double dt)
                                if (current_thickness != required_thickness) {
                                        current_thickness = interpolate_val(current_thickness,
                                                                                                 required_thickness,
-                                                                                                MaxCloudThicknessChangeFtSec);
+                                                                                                MaxCloudThicknessChangeFtSec*dt);
                                        thickness->setDoubleValue(current_thickness);
                                }
                        }
                }
        }
-        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 )
@@ -783,6 +801,15 @@ void FGMetarCtrl::set_metar( const char * metar_string )
 
        station_elevation_n->setDoubleValue( station_elevation_ft );
 
+       {       // calculate sea level temperature and dewpoint
+               FGEnvironment dummy; // instantiate a dummy so we can leech a method
+               dummy.set_elevation_ft( station_elevation_ft );
+               dummy.set_temperature_degc( temperature_n->getDoubleValue() );
+               dummy.set_dewpoint_degc( dewpoint_n->getDoubleValue() );
+               metar_sealevel_temperature = dummy.get_temperature_sea_level_degc();
+               metar_sealevel_dewpoint = dummy.get_dewpoint_sea_level_degc();
+       }
+
        vector<SGMetarCloud> cv = m->getClouds();
        vector<SGMetarCloud>::const_iterator cloud, cloud_end = cv.end();
 
index 0ecf8db8bb0198bd6ef091768914dbe04e06274e..aec1442cb375f56f142facb786ac5d46865d60c9 100644 (file)
@@ -152,12 +152,14 @@ private:
        bool first_update;
        bool wind_interpolation_required;
        string metar;
+       double metar_sealevel_temperature;
+       double metar_sealevel_dewpoint;
        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 MaxTemperatureChangeDegcSec;       // Max temperature change in degc/s
        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
@@ -200,6 +202,8 @@ private:
        SGPropertyNode_ptr boundary_wind_from_heading_n;
        SGPropertyNode_ptr boundary_visibility_n;
        SGPropertyNode_ptr boundary_sea_level_pressure_n;
+       SGPropertyNode_ptr boundary_sea_level_temperature_n;
+       SGPropertyNode_ptr boundary_sea_level_dewpoint_n;
 private:
 
 };