From 9d1299741eaa7e70bc29cbe159f5590d7cd8c1ad Mon Sep 17 00:00:00 2001 From: Roland Rossgotterer Date: Mon, 11 Feb 2019 14:34:13 +0100 Subject: [PATCH] [GFS] Use Pressure at MSL instead of surface Pressure at surface level was the wrong value. All barometers and altimeters use pressure reduced to mean sea level. Reading that value from GFS instead returns much more reasonable values. ref T537 --- samples/weatherdata/weatherdataprinter.cpp | 2 +- .../simulation/fsx/simconnectutilities.cpp | 2 +- src/blackmisc/weather/gridpoint.cpp | 14 +++++++------- src/blackmisc/weather/gridpoint.h | 16 ++++++++-------- src/plugins/simulator/fscommon/fsuipcimpl.cpp | 2 +- .../simulator/xplane/simulatorxplane.cpp | 2 +- src/plugins/weatherdata/gfs/weatherdatagfs.cpp | 17 ++++++++++------- src/plugins/weatherdata/gfs/weatherdatagfs.h | 5 +++-- 8 files changed, 32 insertions(+), 28 deletions(-) diff --git a/samples/weatherdata/weatherdataprinter.cpp b/samples/weatherdata/weatherdataprinter.cpp index 2f793a64c..713d17903 100644 --- a/samples/weatherdata/weatherdataprinter.cpp +++ b/samples/weatherdata/weatherdataprinter.cpp @@ -63,7 +63,7 @@ void CWeatherDataPrinter::ps_printWeatherData(const BlackMisc::Weather::CWeather { qtout << "Latitude:" << gridPoint.getPosition().latitude().toQString() << endl; qtout << "Longitude:" << gridPoint.getPosition().longitude().toQString() << endl; - qtout << " Surface Pressure: " << gridPoint.getSurfacePressure().toQString() << endl; + qtout << " MSL Pressure: " << gridPoint.getPressureAtMsl().toQString() << endl; CTemperatureLayerList temperatureLayers = gridPoint.getTemperatureLayers(); temperatureLayers.sort([](const CTemperatureLayer &a, const CTemperatureLayer &b) { return a.getLevel() < b.getLevel(); }); diff --git a/src/blackmisc/simulation/fsx/simconnectutilities.cpp b/src/blackmisc/simulation/fsx/simconnectutilities.cpp index 0510f6485..39e5688c1 100644 --- a/src/blackmisc/simulation/fsx/simconnectutilities.cpp +++ b/src/blackmisc/simulation/fsx/simconnectutilities.cpp @@ -246,7 +246,7 @@ namespace BlackMisc simconnectMetar += QLatin1String(" Q"); // NNNN = altimeter in millibars static const QString arg1s("%1"); - const auto altimeter = gridPoint.getSurfacePressure().valueInteger(CPressureUnit::mbar()); + const auto altimeter = gridPoint.getPressureAtMsl().valueInteger(CPressureUnit::mbar()); simconnectMetar += arg1s.arg(altimeter, 4, 10, QLatin1Char('0')); return simconnectMetar; diff --git a/src/blackmisc/weather/gridpoint.cpp b/src/blackmisc/weather/gridpoint.cpp index 0eb56272e..c172ab45b 100644 --- a/src/blackmisc/weather/gridpoint.cpp +++ b/src/blackmisc/weather/gridpoint.cpp @@ -33,14 +33,14 @@ namespace BlackMisc const CTemperatureLayerList &temperatureLayers, const CVisibilityLayerList &visibilityLayers, const CWindLayerList &windLayers, - const CPressure &surfacePressure) : + const CPressure &pressureAtMsl) : m_identifier(identifier), m_position(position), m_cloudLayers(cloudLayers), m_temperatureLayers(temperatureLayers), m_visibilityLayers(visibilityLayers), m_windLayers(windLayers), - m_surfacePressure(surfacePressure) + m_pressureAtMsl(pressureAtMsl) { } void CGridPoint::copyWeatherDataFrom(const CGridPoint &other) @@ -49,7 +49,7 @@ namespace BlackMisc setTemperatureLayers(other.getTemperatureLayers()); setVisibilityLayers(other.getVisibilityLayers()); setWindLayers(other.getWindLayers()); - setSurfacePressure(other.getSurfacePressure()); + setPressureAtMsl(other.getPressureAtMsl()); } CVariant CGridPoint::propertyByIndex(const BlackMisc::CPropertyIndex &index) const @@ -68,8 +68,8 @@ namespace BlackMisc return CVariant::fromValue(m_temperatureLayers); case IndexWindLayers: return CVariant::fromValue(m_windLayers); - case IndexSurfacePressure: - return CVariant::fromValue(m_surfacePressure); + case IndexPressureAtMsl: + return CVariant::fromValue(m_pressureAtMsl); default: return CValueObject::propertyByIndex(index); } @@ -96,8 +96,8 @@ namespace BlackMisc case IndexWindLayers: setWindLayers(variant.value()); break; - case IndexSurfacePressure: - setSurfacePressure(variant.value()); + case IndexPressureAtMsl: + setPressureAtMsl(variant.value()); break; default: CValueObject::setPropertyByIndex(index, variant); diff --git a/src/blackmisc/weather/gridpoint.h b/src/blackmisc/weather/gridpoint.h index 4e58960ea..13e606cbd 100644 --- a/src/blackmisc/weather/gridpoint.h +++ b/src/blackmisc/weather/gridpoint.h @@ -47,7 +47,7 @@ namespace BlackMisc IndexCloudLayers, IndexTemperatureLayers, IndexWindLayers, - IndexSurfacePressure + IndexPressureAtMsl }; //! Default constructor. @@ -64,7 +64,7 @@ namespace BlackMisc const CTemperatureLayerList &temperatureLayers, const CVisibilityLayerList &visibilityLayers, const CWindLayerList &windLayers, - const PhysicalQuantities::CPressure &surfacePressure); + const PhysicalQuantities::CPressure &pressureAtMsl); //! Set identifier void setIdentifier(const QString &identifier) { m_identifier = identifier; } @@ -105,11 +105,11 @@ namespace BlackMisc //! Copies all weather data from other without modifying identifier and position. void copyWeatherDataFrom(const CGridPoint &other); - //! Set surface pressure - void setSurfacePressure(const PhysicalQuantities::CPressure &pressure) { m_surfacePressure = pressure; } + //! Set pressure at mean sea level + void setPressureAtMsl(const PhysicalQuantities::CPressure &pressure) { m_pressureAtMsl = pressure; } - //! Get surface pressure - const PhysicalQuantities::CPressure &getSurfacePressure() const { return m_surfacePressure; } + //! Get pressure at mean sea level + const PhysicalQuantities::CPressure &getPressureAtMsl() const { return m_pressureAtMsl; } //! \copydoc BlackMisc::Mixin::Index::propertyByIndex CVariant propertyByIndex(const BlackMisc::CPropertyIndex &index) const; @@ -127,7 +127,7 @@ namespace BlackMisc CTemperatureLayerList m_temperatureLayers; CVisibilityLayerList m_visibilityLayers; CWindLayerList m_windLayers; - PhysicalQuantities::CPressure m_surfacePressure = { PhysicalQuantities::CPhysicalQuantitiesConstants::ISASeaLevelPressure() }; + PhysicalQuantities::CPressure m_pressureAtMsl = { PhysicalQuantities::CPhysicalQuantitiesConstants::ISASeaLevelPressure() }; BLACK_METACLASS( CGridPoint, @@ -137,7 +137,7 @@ namespace BlackMisc BLACK_METAMEMBER(temperatureLayers), BLACK_METAMEMBER(visibilityLayers), BLACK_METAMEMBER(windLayers), - BLACK_METAMEMBER(surfacePressure) + BLACK_METAMEMBER(pressureAtMsl) ); }; } // namespace diff --git a/src/plugins/simulator/fscommon/fsuipcimpl.cpp b/src/plugins/simulator/fscommon/fsuipcimpl.cpp index 114d62ab9..3092daa6b 100644 --- a/src/plugins/simulator/fscommon/fsuipcimpl.cpp +++ b/src/plugins/simulator/fscommon/fsuipcimpl.cpp @@ -290,7 +290,7 @@ namespace BlackSimPlugin NewPress press; press.Drift = 0; // Pressure is measured in: 16 x mb - press.Pressure = static_cast(gridPoint.getSurfacePressure().value(CPressureUnit::mbar()) * 16); + press.Pressure = static_cast(gridPoint.getPressureAtMsl().value(CPressureUnit::mbar()) * 16); nw.Press = press; // writing will take place in diff --git a/src/plugins/simulator/xplane/simulatorxplane.cpp b/src/plugins/simulator/xplane/simulatorxplane.cpp index feedd1158..dc8c04418 100644 --- a/src/plugins/simulator/xplane/simulatorxplane.cpp +++ b/src/plugins/simulator/xplane/simulatorxplane.cpp @@ -710,7 +710,7 @@ namespace BlackSimPlugin const CTemperatureLayer temperatureLayer = temperatureLayers.frontOrDefault(); m_weatherProxy->setTemperature(temperatureLayer.getTemperature().valueInteger(CTemperatureUnit::C())); m_weatherProxy->setDewPoint(temperatureLayer.getDewPoint().valueInteger(CTemperatureUnit::C())); - m_weatherProxy->setQNH(gridPoint.getSurfacePressure().value(CPressureUnit::inHg())); + m_weatherProxy->setQNH(gridPoint.getPressureAtMsl().value(CPressureUnit::inHg())); int layerNumber = 0; CCloudLayerList cloudLayers = gridPoint.getCloudLayers(); diff --git a/src/plugins/weatherdata/gfs/weatherdatagfs.cpp b/src/plugins/weatherdata/gfs/weatherdatagfs.cpp index 2a9f36a46..5b45c1823 100644 --- a/src/plugins/weatherdata/gfs/weatherdatagfs.cpp +++ b/src/plugins/weatherdata/gfs/weatherdatagfs.cpp @@ -141,6 +141,7 @@ namespace BlackWxPlugin static const QStringList grib2Levels = { + "mean_sea_level", "surface", "100_mb", "150_mb", @@ -329,12 +330,12 @@ namespace BlackWxPlugin cloudLayers.push_back(cloudLayer); } - auto surfacePressure = PhysicalQuantities::CPressure { gfsGridPoint.surfacePressure, PhysicalQuantities::CPressureUnit::Pa() }; + auto pressureAtMsl = PhysicalQuantities::CPressure { gfsGridPoint.pressureAtMsl, PhysicalQuantities::CPressureUnit::Pa() }; CLatitude latitude(gfsGridPoint.latitude, CAngleUnit::deg()); CLongitude longitude(gfsGridPoint.longitude, CAngleUnit::deg()); auto position = CCoordinateGeodetic { latitude, longitude, {0} }; - CGridPoint gridPoint({}, position, cloudLayers, temperatureLayers, {}, windLayers, surfacePressure); + CGridPoint gridPoint({}, position, cloudLayers, temperatureLayers, {}, windLayers, pressureAtMsl); m_weatherGrid.push_back(gridPoint); } } @@ -515,7 +516,7 @@ namespace BlackWxPlugin return; } - // http://www.nco.ncep.noaa.gov/pmb/docs/grib2/grib2_temp4-0.shtml + // https://www.nco.ncep.noaa.gov/pmb/docs/grib2/grib2_doc/grib2_temp4-0.shtml g2int parameterCategory = gfld->ipdtmpl[0]; g2int parameterNumber = gfld->ipdtmpl[1]; g2int typeFirstFixedSurface = gfld->ipdtmpl[9]; @@ -538,6 +539,9 @@ namespace BlackWxPlugin case IsobaricSurface: level = std::round(millibarToLevel(valueFirstFixedSurface)); break; + case MeanSeaLevel: + level = 0.0; + break; default: CLogMessage(this).warning(u"Unexpected first fixed surface type: %1") << typeFirstFixedSurface; return; @@ -559,9 +563,9 @@ namespace BlackWxPlugin setWindV(gfld->fld, level); break; case PRMSL: + setPressureAtMsl(gfld->fld); break; case PRES: - setCloudPressure(gfld->fld, level); break; default: Q_ASSERT(false); @@ -694,12 +698,11 @@ namespace BlackWxPlugin } } - void CWeatherDataGfs::setCloudPressure(const g2float *fld, double level) + void CWeatherDataGfs::setPressureAtMsl(const g2float *fld) { for (auto &gridPoint : m_gfsWeatherGrid) { - if (level > 0) { /* todo */ } - else { gridPoint.surfacePressure = fld[gridPoint.fieldPosition]; } + gridPoint.pressureAtMsl = fld[gridPoint.fieldPosition]; } } diff --git a/src/plugins/weatherdata/gfs/weatherdatagfs.h b/src/plugins/weatherdata/gfs/weatherdatagfs.h index 2948716ec..5c8056170 100644 --- a/src/plugins/weatherdata/gfs/weatherdatagfs.h +++ b/src/plugins/weatherdata/gfs/weatherdatagfs.h @@ -85,6 +85,7 @@ namespace BlackWxPlugin { GroundOrWaterSurface = 1, IsobaricSurface = 100, + MeanSeaLevel = 101, LowCloudBottomLevel = 212, LowCloudTopLevel = 213, LowCloudLayer = 214, @@ -130,7 +131,7 @@ namespace BlackWxPlugin double surfaceRain = 0; double surfaceSnow = 0; double surfacePrecipitationRate = 0; - double surfacePressure = 0; + double pressureAtMsl = 0.0; double surfaceTemperature = 0; }; @@ -151,7 +152,7 @@ namespace BlackWxPlugin void setWindU(const g2float *fld, double level); void setCloudCoverage(const g2float *fld, int level); void setCloudLevel(const g2float *fld, int surfaceType, int level); - void setCloudPressure(const g2float *fld, double level); + void setPressureAtMsl(const g2float *fld); void setSurfaceRain(const g2float *fld); void setSurfaceSnow(const g2float *fld); void setPrecipitationRate(const g2float *fld);