From 781707fb7ec8a5c064c0d94932dd43e33277cb0c Mon Sep 17 00:00:00 2001 From: Roland Winklmeier Date: Mon, 28 Mar 2016 20:57:39 +0200 Subject: [PATCH] Simulator driver fetches and injects weather from weather manager --- src/blackmisc/weather/temperaturelayer.h | 2 +- src/blackmisc/weather/visibilitylayer.h | 2 +- src/plugins/simulator/fs9/simulatorfs9.cpp | 17 +++-- src/plugins/simulator/fs9/simulatorfs9.h | 2 + src/plugins/simulator/fscommon/fsuipc.cpp | 32 ++++++--- src/plugins/simulator/fsx/simulatorfsx.cpp | 12 ++-- src/plugins/simulator/fsx/simulatorfsx.h | 2 + .../simulator/xplane/simulatorxplane.cpp | 66 ++++++++++++++----- .../simulator/xplane/simulatorxplane.h | 2 + 9 files changed, 100 insertions(+), 37 deletions(-) diff --git a/src/blackmisc/weather/temperaturelayer.h b/src/blackmisc/weather/temperaturelayer.h index 43107b152..df7f59c6d 100644 --- a/src/blackmisc/weather/temperaturelayer.h +++ b/src/blackmisc/weather/temperaturelayer.h @@ -81,7 +81,7 @@ namespace BlackMisc private: BlackMisc::Aviation::CAltitude m_level; - PhysicalQuantities::CTemperature m_temperature; + PhysicalQuantities::CTemperature m_temperature = { 15.0, PhysicalQuantities::CTemperatureUnit::C() }; PhysicalQuantities::CTemperature m_dewPoint; double m_relativeHumidity = 0; diff --git a/src/blackmisc/weather/visibilitylayer.h b/src/blackmisc/weather/visibilitylayer.h index f77e1b251..19de64e1e 100644 --- a/src/blackmisc/weather/visibilitylayer.h +++ b/src/blackmisc/weather/visibilitylayer.h @@ -74,7 +74,7 @@ namespace BlackMisc private: BlackMisc::Aviation::CAltitude m_base; BlackMisc::Aviation::CAltitude m_top; - PhysicalQuantities::CLength m_visibility; + PhysicalQuantities::CLength m_visibility { 10, PhysicalQuantities::CLengthUnit::km() }; BLACK_METACLASS( CVisibilityLayer, diff --git a/src/plugins/simulator/fs9/simulatorfs9.cpp b/src/plugins/simulator/fs9/simulatorfs9.cpp index 5720e077a..a0be8056f 100644 --- a/src/plugins/simulator/fs9/simulatorfs9.cpp +++ b/src/plugins/simulator/fs9/simulatorfs9.cpp @@ -133,11 +133,6 @@ namespace BlackSimPlugin m_fsuipc->connect(); // connect FSUIPC too } m_dispatchTimerId = startTimer(50); - - // Pull weather data from core. - // Since we don't get weather data from core yet, use hard coded weather. - injectWeatherGrid(CWeatherGrid::getCavokGrid()); - return true; } @@ -333,7 +328,17 @@ namespace BlackSimPlugin { MPPositionVelocity mpPositionVelocity; MultiPlayerPacketParser::readMessage(message, mpPositionVelocity); - updateOwnSituation(aircraftSituationfromFS9(mpPositionVelocity)); + auto aircraftSituation = aircraftSituationfromFS9(mpPositionVelocity); + updateOwnSituation(aircraftSituation); + + const auto currentPosition = CCoordinateGeodetic { aircraftSituation.latitude(), aircraftSituation.longitude(), {0} }; + if (calculateGreatCircleDistance(m_lastWeatherPosition, currentPosition).value(CLengthUnit::mi()) > 20 ) + { + m_lastWeatherPosition = currentPosition; + const auto weatherGrid = CWeatherGrid { { "GLOB", currentPosition } }; + requestWeatherGrid(weatherGrid, { this, &CSimulatorFs9::injectWeatherGrid }); + } + break; } case CFs9Sdk::MPCHAT_PACKET_ID_CHAT_TEXT_SEND: diff --git a/src/plugins/simulator/fs9/simulatorfs9.h b/src/plugins/simulator/fs9/simulatorfs9.h index 0c5069270..02c3c4b90 100644 --- a/src/plugins/simulator/fs9/simulatorfs9.h +++ b/src/plugins/simulator/fs9/simulatorfs9.h @@ -115,6 +115,8 @@ namespace BlackSimPlugin bool m_simConnected = false; //!< Is simulator connected? QSharedPointer m_fs9Host; QSharedPointer m_lobbyClient; + + BlackMisc::Geo::CCoordinateGeodetic m_lastWeatherPosition; //!< Own aircraft position at which weather was fetched and injected last }; //! Listener for FS9 diff --git a/src/plugins/simulator/fscommon/fsuipc.cpp b/src/plugins/simulator/fscommon/fsuipc.cpp index 1c442ced6..34f9d19da 100644 --- a/src/plugins/simulator/fscommon/fsuipc.cpp +++ b/src/plugins/simulator/fscommon/fsuipc.cpp @@ -123,17 +123,26 @@ namespace BlackSimPlugin // todo: Take station from weather grid memcpy(nw.chICAO, "GLOB", 4); - const CVisibilityLayerList visibilityLayers = gridPoint.getVisibilityLayers(); + CVisibilityLayerList visibilityLayers = gridPoint.getVisibilityLayers(); + visibilityLayers.sortBy(&CVisibilityLayer::getBase); + auto surfaceVisibility = visibilityLayers.frontOrDefault(); + NewVis vis; + vis.LowerAlt = surfaceVisibility.getBase().value(CLengthUnit::m()); + vis.UpperAlt = surfaceVisibility.getTop().value(CLengthUnit::m()); + // Range is measured in: 1/100ths sm + vis.Range = surfaceVisibility.getVisibility().value(CLengthUnit::SM()) * 100; + nw.Vis = vis; + for (const auto &visibilityLayer : visibilityLayers) { - NewVis vis; vis.LowerAlt = visibilityLayer.getBase().value(CLengthUnit::m()); vis.UpperAlt = visibilityLayer.getTop().value(CLengthUnit::m()); - vis.Range = visibilityLayer.getVisibility().value(CLengthUnit::mi()) * 100; - nw.Vis = vis; + vis.Range = visibilityLayer.getVisibility().value(CLengthUnit::SM()) * 100; + nw.UpperVis[nw.nUpperVisCtr++] = vis; } - const CTemperatureLayerList temperatureLayers = gridPoint.getTemperatureLayers(); + CTemperatureLayerList temperatureLayers = gridPoint.getTemperatureLayers(); + temperatureLayers.sortBy(&CTemperatureLayer::getLevel); for (const auto &temperatureLayer : temperatureLayers) { NewTemp temp; @@ -144,7 +153,8 @@ namespace BlackSimPlugin nw.Temp[nw.nTempCtr++] = temp; } - const CCloudLayerList cloudLayers = gridPoint.getCloudLayers(); + CCloudLayerList cloudLayers = gridPoint.getCloudLayers(); + cloudLayers.sortBy(&CCloudLayer::getBase); for (const auto &cloudLayer : cloudLayers) { NewCloud cloud; @@ -184,12 +194,13 @@ namespace BlackSimPlugin default: cloud.Type = 0; } - cloud.UpperAlt = cloudLayer.getBase().value(CLengthUnit::m()); + cloud.UpperAlt = cloudLayer.getTop().value(CLengthUnit::m()); nw.Cloud[nw.nCloudsCtr++] = cloud; } - const CWindLayerList windLayers = gridPoint.getWindLayers(); - for (const auto &windLayer : windLayers) + CWindLayerList windLayers = gridPoint.getWindLayers(); + windLayers.sortBy(&CWindLayer::getLevel); + for (const auto &windLayer : as_const(windLayers)) { NewWind wind; wind.Direction = windLayer.getDirection().value(CAngleUnit::deg()) * 65536 / 360.0; @@ -206,7 +217,8 @@ namespace BlackSimPlugin NewPress press; press.Drift = 0; - press.Pressure = 15827; // 16 x mb + // Pressure is measured in: 16 x mb + press.Pressure = gridPoint.getSurfacePressure().value(CPressureUnit::mbar()) * 16; nw.Press = press; QByteArray weatherData(reinterpret_cast(&nw), sizeof(NewWeather)); diff --git a/src/plugins/simulator/fsx/simulatorfsx.cpp b/src/plugins/simulator/fsx/simulatorfsx.cpp index 4732c87a1..374aad42c 100644 --- a/src/plugins/simulator/fsx/simulatorfsx.cpp +++ b/src/plugins/simulator/fsx/simulatorfsx.cpp @@ -97,10 +97,6 @@ namespace BlackSimPlugin m_simconnectTimerId = startTimer(10); m_simConnected = true; emitSimulatorCombinedStatus(); - - // Pull weather data from core. - // Since we don't get weather data from core yet, use hard coded weather. - injectWeatherGrid(CWeatherGrid::getCavokGrid()); return true; } @@ -431,6 +427,14 @@ namespace BlackSimPlugin { --m_skipCockpitUpdateCycles; } + + const auto currentPosition = CCoordinateGeodetic { aircraftSituation.latitude(), aircraftSituation.longitude(), {0} }; + if (calculateGreatCircleDistance(m_lastWeatherPosition, currentPosition).value(CLengthUnit::mi()) > 20 ) + { + m_lastWeatherPosition = currentPosition; + const auto weatherGrid = CWeatherGrid { { "GLOB", currentPosition } }; + requestWeatherGrid(weatherGrid, { this, &CSimulatorFsx::injectWeatherGrid }); + } } void CSimulatorFsx::updateOwnAircraftFromSimulator(DataDefinitionClientAreaSb sbDataArea) diff --git a/src/plugins/simulator/fsx/simulatorfsx.h b/src/plugins/simulator/fsx/simulatorfsx.h index c75e4126a..c51a5f245 100644 --- a/src/plugins/simulator/fsx/simulatorfsx.h +++ b/src/plugins/simulator/fsx/simulatorfsx.h @@ -201,6 +201,8 @@ namespace BlackSimPlugin qint64 m_statsUpdateAircraftTimeTotal = 0; qint64 m_statsUpdateAircraftTimeAvg = 0; int m_statsUpdateAircraftCount = 0; + + BlackMisc::Geo::CCoordinateGeodetic m_lastWeatherPosition; //!< Own aircraft position at which weather was fetched and injected last }; //! Listener for FSX diff --git a/src/plugins/simulator/xplane/simulatorxplane.cpp b/src/plugins/simulator/xplane/simulatorxplane.cpp index 28cc84a86..9030ca602 100644 --- a/src/plugins/simulator/xplane/simulatorxplane.cpp +++ b/src/plugins/simulator/xplane/simulatorxplane.cpp @@ -18,6 +18,7 @@ #include #include #include +#include using namespace BlackMisc; using namespace BlackMisc::Aviation; @@ -126,6 +127,14 @@ namespace BlackSimPlugin Aviation::CTransponder::getStandardTransponder(m_xplaneData.xpdrCode, xpdrMode(m_xplaneData.xpdrMode, m_xplaneData.xpdrIdent)), identifier() ); + + const auto currentPosition = CCoordinateGeodetic { situation.latitude(), situation.longitude(), {0} }; + if (calculateGreatCircleDistance(m_lastWeatherPosition, currentPosition).value(CLengthUnit::mi()) > 20 ) + { + m_lastWeatherPosition = currentPosition; + const auto weatherGrid = CWeatherGrid { { "", currentPosition } }; + requestWeatherGrid(weatherGrid, { this, &CSimulatorXPlane::injectWeatherGrid }); + } } } @@ -210,10 +219,6 @@ namespace BlackSimPlugin m_traffic->updateInstalledModels(); m_watcher->setConnection(m_conn); emitSimulatorCombinedStatus(); - - // Pull weather data from core. - // Since we don't get weather data from core yet, use hard coded weather. - injectWeatherGrid(CWeatherGrid::getCavokGrid()); return true; } else @@ -525,21 +530,30 @@ namespace BlackSimPlugin CGridPoint gridPoint = weatherGrid.front(); // todo: find the closest - const CVisibilityLayer visibilityLayer = gridPoint.getVisibilityLayers().frontOrDefault(); + auto visibilityLayers = gridPoint.getVisibilityLayers(); + visibilityLayers.sortBy(&CVisibilityLayer::getBase); + const CVisibilityLayer visibilityLayer = visibilityLayers.frontOrDefault(); m_weather->setVisibility(visibilityLayer.getVisibility().value(CLengthUnit::m())); - const CTemperatureLayer temperatureLayer = gridPoint.getTemperatureLayers().frontOrDefault(); + CTemperatureLayerList temperatureLayers = gridPoint.getTemperatureLayers(); + temperatureLayers.sortBy(&CTemperatureLayer::getLevel); + const CTemperatureLayer temperatureLayer = temperatureLayers.frontOrDefault(); m_weather->setTemperature(temperatureLayer.getTemperature().value(CTemperatureUnit::C())); m_weather->setDewPoint(temperatureLayer.getDewPoint().value(CTemperatureUnit::C())); - - CPressure pressure(989.1875, CPressureUnit::hPa()); - m_weather->setQNH(pressure.value(CPressureUnit::inHg())); - - m_weather->setPrecipitationRatio(1.0); - m_weather->setThunderstormRatio(1.0); + m_weather->setQNH(gridPoint.getSurfacePressure().value(CPressureUnit::inHg())); int layerNumber = 0; - const CCloudLayerList cloudLayers = gridPoint.getCloudLayers(); + CCloudLayerList cloudLayers = gridPoint.getCloudLayers(); + auto numberOfLayers = cloudLayers.size(); + // Fill cloud layers if less then 3 + while (numberOfLayers < 3) + { + cloudLayers.push_back(CCloudLayer()); + numberOfLayers++; + } + cloudLayers.sortBy(&CCloudLayer::getBase); + // todo: Instead of truncate, find the 3 vertical closest cloud layers + cloudLayers.truncate(3); for (const auto &cloudLayer : cloudLayers) { int base = cloudLayer.getBase().value(CLengthUnit::m()); @@ -563,14 +577,36 @@ namespace BlackSimPlugin case CCloudLayer::NoClouds: type = 0; break; case CCloudLayer::Cirrus: type = 1; break; case CCloudLayer::Stratus: type = 5; break; - //case CCloudLayer::Cumulus: cloud.Type = 9; break; - //case CCloudLayer::Thunderstorm: cloud.Type = 10; break; default: type = 0; } m_weather->setCloudLayer(layerNumber, base, top, type, coverage); layerNumber++; } + + layerNumber = 0; + CWindLayerList windLayers = gridPoint.getWindLayers(); + numberOfLayers = windLayers.size(); + // Fill cloud layers if less then 3 + while (numberOfLayers < 3) + { + windLayers.push_back(CWindLayer()); + numberOfLayers++; + } + windLayers.sortBy(&CWindLayer::getLevel); + // todo: Instead of truncate, find the 3 vertical closest cloud layers + windLayers.truncate(3); + for (const auto &windLayer : windLayers) + { + int altitudeMeter = windLayer.getLevel().value(CLengthUnit::m()); + double directionDeg = windLayer.getDirection().value(CAngleUnit::deg()); + int speedKts = windLayer.getSpeed().value(CSpeedUnit::kts()); + m_weather->setWindLayer(layerNumber, altitudeMeter, directionDeg, speedKts, 0, 0, 0); + layerNumber++; + } + + m_weather->setPrecipitationRatio(cloudLayers.frontOrDefault().getPrecipitationRate()); + m_weather->setThunderstormRatio(0.0); } BlackCore::ISimulator *CSimulatorXPlaneFactory::create(const CSimulatorPluginInfo &info, diff --git a/src/plugins/simulator/xplane/simulatorxplane.h b/src/plugins/simulator/xplane/simulatorxplane.h index f4b22e64e..223b72086 100644 --- a/src/plugins/simulator/xplane/simulatorxplane.h +++ b/src/plugins/simulator/xplane/simulatorxplane.h @@ -152,6 +152,8 @@ namespace BlackSimPlugin BlackMisc::Simulation::CAircraftModelList m_installedModels; BlackMisc::Simulation::CAircraftMatcher m_modelMatcher { BlackMisc::Simulation::CAircraftMatcher::AllModes, this }; //!< Model matcher + BlackMisc::Geo::CCoordinateGeodetic m_lastWeatherPosition; //!< Own aircraft position at which weather was fetched and injected last + //! \todo Add units to members? pitchDeg?, altitudeFt? struct // data is written by DBus async method callbacks {