From 6061a61d500a79818b7fcf888b82f08eb32319f8 Mon Sep 17 00:00:00 2001 From: Klaus Basan Date: Sat, 7 Apr 2018 04:41:22 +0200 Subject: [PATCH] Ref T260, changed elevation handling in provider, simulator and FSX common driver * split functions, added findClosestElevationWithinRangeOrRequest * obtain elevation ids (separate ids are easier to track) * also added experimental "physicallyAddAITerrainProbe" (FSX) for the FSX elevation probing * callback / signal when requested elevation is received (async) --- src/blackcore/airspacemonitor.cpp | 2 +- src/blackcore/simulator.cpp | 17 +++- src/blackcore/simulator.h | 8 +- .../simulationenvironmentprovider.cpp | 30 ++++-- .../simulationenvironmentprovider.h | 17 +++- .../fsxcommon/simulatorfsxcommon.cpp | 73 +++++++++++++-- .../simulator/fsxcommon/simulatorfsxcommon.h | 64 +++++++++---- src/plugins/simulator/p3d/p3d.pro | 1 - src/plugins/simulator/p3d/simulatorp3d.cpp | 91 +++++++++++++++++++ src/plugins/simulator/p3d/simulatorp3d.h | 7 ++ .../simulator/xplane/simulatorxplane.cpp | 4 +- .../simulator/xplane/simulatorxplane.h | 2 +- 12 files changed, 268 insertions(+), 48 deletions(-) diff --git a/src/blackcore/airspacemonitor.cpp b/src/blackcore/airspacemonitor.cpp index ef479d827..d93487615 100644 --- a/src/blackcore/airspacemonitor.cpp +++ b/src/blackcore/airspacemonitor.cpp @@ -922,7 +922,7 @@ namespace BlackCore CAircraftSituation correctedSituation(situation); if (!correctedSituation.hasGroundElevation() && !correctedSituation.canLikelySkipNearGroundInterpolation()) { - const CElevationPlane ep = this->findClosestElevationWithinRange(correctedSituation, correctedSituation.getDistancePerTime(1000), true); + const CElevationPlane ep = this->findClosestElevationWithinRangeOrRequest(correctedSituation, correctedSituation.getDistancePerTime(1000), callsign); correctedSituation.setGroundElevation(ep); } diff --git a/src/blackcore/simulator.cpp b/src/blackcore/simulator.cpp index 7ac982756..c7270dd2c 100644 --- a/src/blackcore/simulator.cpp +++ b/src/blackcore/simulator.cpp @@ -9,6 +9,7 @@ #include "blackcore/simulator.h" #include "blackcore/application.h" +#include "blackmisc/logmessage.h" #include #include @@ -42,14 +43,24 @@ namespace BlackCore return setup; } - bool ISimulator::requestElevation(const Geo::ICoordinateGeodetic &reference) const + bool ISimulator::requestElevation(const Geo::ICoordinateGeodetic &reference, const CCallsign &callsign) { - if (this->isShuttingDown()) { return false; } - if (reference.isNull()) { return false; } Q_UNUSED(reference); + Q_UNUSED(callsign); return false; } + void ISimulator::callbackReceivedRequestedElevation(const Geo::CElevationPlane &plane, const CCallsign &callsign) + { + if (this->isShuttingDown()) { return; } + + // CLogMessage(this).info("'%1' Received req. elevation") << callsign.asString(); + this->rememberGroundElevation(plane); + const int updated = this->updateAircraftGroundElevation(callsign, plane); + if (updated < 1) { return; } + emit this->receivedRequestedElevation(plane, callsign); + } + void ISimulator::registerHelp() { if (CSimpleCommandParser::registered("BlackCore::ISimulator")) { return; } diff --git a/src/blackcore/simulator.h b/src/blackcore/simulator.h index 47bfa9911..086a94c31 100644 --- a/src/blackcore/simulator.h +++ b/src/blackcore/simulator.h @@ -182,7 +182,7 @@ namespace BlackCore //! \copydoc BlackMisc::Simulation::ISimulationEnvironmentProvider::requestElevation //! \remark needs to be overridden if the concrete driver supports such an option - virtual bool requestElevation(const BlackMisc::Geo::ICoordinateGeodetic &reference) const override; + virtual bool requestElevation(const BlackMisc::Geo::ICoordinateGeodetic &reference, const BlackMisc::Aviation::CCallsign &callsign) override; //! \copydoc BlackMisc::IProvider::asQObject virtual QObject *asQObject() override { return this; } @@ -235,6 +235,9 @@ namespace BlackCore //! Request a console message (whatever the console maybe) void requestUiConsoleMessage(const QString &driverMessage, bool clear); + //! A requested elevation has been received + void receivedRequestedElevation(const BlackMisc::Geo::CElevationPlane &plane, const BlackMisc::Aviation::CCallsign &callsign); + protected: //! Default constructor ISimulator(const BlackMisc::Simulation::CSimulatorPluginInfo &pluginInfo, @@ -268,6 +271,9 @@ namespace BlackCore //! Set elevation and CG in the providers void rememberElevationAndCG(const BlackMisc::Aviation::CCallsign &callsign, const BlackMisc::Geo::CElevationPlane &elevation, const BlackMisc::PhysicalQuantities::CLength &cg); + //! A requested elevation has been received + virtual void callbackReceivedRequestedElevation(const BlackMisc::Geo::CElevationPlane &plane, const BlackMisc::Aviation::CCallsign &callsign); + //! Emit the combined status //! \param oldStatus optionally one can capture and provide the old status for comparison. In case of equal status values no signal will be sent //! \sa simulatorStatusChanged; diff --git a/src/blackmisc/simulation/simulationenvironmentprovider.cpp b/src/blackmisc/simulation/simulationenvironmentprovider.cpp index 093918de8..a3ff94d3b 100644 --- a/src/blackmisc/simulation/simulationenvironmentprovider.cpp +++ b/src/blackmisc/simulation/simulationenvironmentprovider.cpp @@ -91,7 +91,7 @@ namespace BlackMisc return delta; } - CElevationPlane ISimulationEnvironmentProvider::findClosestElevationWithinRange(const ICoordinateGeodetic &reference, const PhysicalQuantities::CLength &range, bool autoRequest) const + CElevationPlane ISimulationEnvironmentProvider::findClosestElevationWithinRange(const ICoordinateGeodetic &reference, const PhysicalQuantities::CLength &range) const { const CCoordinateGeodetic coordinate = this->getElevationCoordinates().findClosestWithinRange(reference, minRange(range)); const bool found = !coordinate.isNull(); @@ -100,14 +100,24 @@ namespace BlackMisc if (found) { m_elvFound++; + return CElevationPlane(coordinate, reference); // plane with radis = distance to reference } else { m_elvMissed++; - if (autoRequest) { this->requestElevation(reference); } + return CElevationPlane::null(); } } - return CElevationPlane(coordinate, reference); // plane with radis = distance to reference + } + + CElevationPlane ISimulationEnvironmentProvider::findClosestElevationWithinRangeOrRequest(const ICoordinateGeodetic &reference, const CLength &range, const CCallsign &callsign) + { + const CElevationPlane ep = ISimulationEnvironmentProvider::findClosestElevationWithinRange(reference, range); + if (ep.isNull()) + { + this->requestElevation(reference, callsign); + } + return ep; } QPair ISimulationEnvironmentProvider::getElevationsFoundMissed() const @@ -196,16 +206,22 @@ namespace BlackMisc this->clearCGs(); } - CElevationPlane CSimulationEnvironmentAware::findClosestElevationWithinRange(const ICoordinateGeodetic &reference, const PhysicalQuantities::CLength &range, bool autoRequest) const + CElevationPlane CSimulationEnvironmentAware::findClosestElevationWithinRange(const ICoordinateGeodetic &reference, const PhysicalQuantities::CLength &range) const { if (!this->hasProvider()) { return CElevationPlane::null(); } - return this->provider()->findClosestElevationWithinRange(reference, range, autoRequest); + return this->provider()->findClosestElevationWithinRange(reference, range); } - bool CSimulationEnvironmentAware::requestElevation(const ICoordinateGeodetic &reference) const + CElevationPlane CSimulationEnvironmentAware::findClosestElevationWithinRangeOrRequest(const ICoordinateGeodetic &reference, const CLength &range, const CCallsign &callsign) + { + if (!this->hasProvider()) { return CElevationPlane::null(); } + return this->provider()->findClosestElevationWithinRangeOrRequest(reference, range, callsign); + } + + bool CSimulationEnvironmentAware::requestElevation(const ICoordinateGeodetic &reference, const CCallsign &callsign) { if (!this->hasProvider()) { return false; } - return this->provider()->requestElevation(reference); + return this->provider()->requestElevation(reference, callsign); } QPair CSimulationEnvironmentAware::getElevationsFoundMissed() const diff --git a/src/blackmisc/simulation/simulationenvironmentprovider.h b/src/blackmisc/simulation/simulationenvironmentprovider.h index b9c1b2164..aa48893c7 100644 --- a/src/blackmisc/simulation/simulationenvironmentprovider.h +++ b/src/blackmisc/simulation/simulationenvironmentprovider.h @@ -38,11 +38,15 @@ namespace BlackMisc //! Find closest elevation //! \threadsafe - Geo::CElevationPlane findClosestElevationWithinRange(const Geo::ICoordinateGeodetic &reference, const PhysicalQuantities::CLength &range, bool autoRequest = false) const; + Geo::CElevationPlane findClosestElevationWithinRange(const Geo::ICoordinateGeodetic &reference, const PhysicalQuantities::CLength &range) const; + + //! Find closest elevation + //! \threadsafe + Geo::CElevationPlane findClosestElevationWithinRangeOrRequest(const Geo::ICoordinateGeodetic &reference, const PhysicalQuantities::CLength &range, const Aviation::CCallsign &callsign); //! Request elevation, there is no guaranteed the requested elevation will be available in the provider //! \threadsafe - virtual bool requestElevation(const Geo::ICoordinateGeodetic &reference) const = 0; + virtual bool requestElevation(const Geo::ICoordinateGeodetic &reference, const Aviation::CCallsign &callsign) = 0; //! Elevations found/missed statistics //! \threadsafe @@ -146,10 +150,13 @@ namespace BlackMisc void setSimulationEnvironmentProvider(ISimulationEnvironmentProvider *provider) { this->setProvider(provider); } //! \copydoc ISimulationEnvironmentProvider::findClosestElevationWithinRange - Geo::CElevationPlane findClosestElevationWithinRange(const Geo::ICoordinateGeodetic &reference, const PhysicalQuantities::CLength &range, bool autoRequest = false) const; + Geo::CElevationPlane findClosestElevationWithinRange(const Geo::ICoordinateGeodetic &reference, const PhysicalQuantities::CLength &range) const; - //! \copydoc ISimulationEnvironmentProvider::findClosestElevationWithinRange - bool requestElevation(const Geo::ICoordinateGeodetic &reference) const; + //! \copydoc ISimulationEnvironmentProvider::findClosestElevationWithinRangeOrRequest + Geo::CElevationPlane findClosestElevationWithinRangeOrRequest(const Geo::ICoordinateGeodetic &reference, const PhysicalQuantities::CLength &range, const Aviation::CCallsign &callsign); + + //! \copydoc ISimulationEnvironmentProvider::requestElevation + bool requestElevation(const Geo::ICoordinateGeodetic &reference, const Aviation::CCallsign &callsign); //! \copydoc ISimulationEnvironmentProvider::getElevationsFoundMissed QPair getElevationsFoundMissed() const; diff --git a/src/plugins/simulator/fsxcommon/simulatorfsxcommon.cpp b/src/plugins/simulator/fsxcommon/simulatorfsxcommon.cpp index afe339396..8eebf2c91 100644 --- a/src/plugins/simulator/fsxcommon/simulatorfsxcommon.cpp +++ b/src/plugins/simulator/fsxcommon/simulatorfsxcommon.cpp @@ -267,6 +267,15 @@ namespace BlackSimPlugin return msgs; } + bool CSimulatorFsxCommon::requestElevation(const ICoordinateGeodetic &reference, const CCallsign &callsign) + { + Q_UNUSED(callsign); + if (this->isShuttingDown()) { return false; } + if (reference.isNull()) { return false; } + this->physicallyAddAITerrainProbe(reference); + return false; + } + bool CSimulatorFsxCommon::stillDisplayReceiveExceptions() { m_receiveExceptionCount++; @@ -359,7 +368,14 @@ namespace BlackSimPlugin SIMCONNECT_DATA_REQUEST_ID CSimulatorFsxCommon::obtainRequestIdForSimData() { const SIMCONNECT_DATA_REQUEST_ID id = m_requestIdSimData++; - if (id > RequestSimDataEnd) { m_requestIdSimData = RequestSimDataStart; } + if (id > RequestIdSimDataEnd) { m_requestIdSimData = RequestIdSimDataStart; } + return id; + } + + SIMCONNECT_DATA_REQUEST_ID CSimulatorFsxCommon::obtainRequestIdForProbe() + { + const SIMCONNECT_DATA_REQUEST_ID id = m_requestIdProbe++; + if (id > RequestIdTerrainProbeEnd) { m_requestIdProbe = RequestIdTerrainProbeStart; } return id; } @@ -745,6 +761,7 @@ namespace BlackSimPlugin void CSimulatorFsxCommon::timerEvent(QTimerEvent *event) { Q_UNUSED(event); + if (this->isShuttingDown()) { return; } this->dispatch(); } @@ -768,6 +785,13 @@ namespace BlackSimPlugin CSimpleCommandParser::registerCommand({".drv sendid on|off", "Trace simConnect sendId on|off"}); } + CCallsign CSimulatorFsxCommon::getCallsignForPendingProbeRequests(DWORD requestId, bool remove) + { + const CCallsign cs = m_pendingProbeRequests.value(requestId); + if (remove) { m_pendingProbeRequests.remove(requestId); } + return cs; + } + const QString &CSimulatorFsxCommon::modeToString(CSimulatorFsxCommon::AircraftAddMode mode) { static const QString e("external call"); @@ -789,7 +813,9 @@ namespace BlackSimPlugin void CSimulatorFsxCommon::dispatch() { - const HRESULT hr = SimConnect_CallDispatch(m_hSimConnect, SimConnectProc, this); + // call CSimulatorFsxCommon::SimConnectProc or specialized P3D version + Q_ASSERT_X(m_dispatchProc, Q_FUNC_INFO, "Missing DispatchProc"); + const HRESULT hr = SimConnect_CallDispatch(m_hSimConnect, m_dispatchProc, this); if (hr != S_OK) { m_dispatchErrors++; @@ -899,6 +925,28 @@ namespace BlackSimPlugin return adding; } + bool CSimulatorFsxCommon::physicallyAddAITerrainProbe(const ICoordinateGeodetic &coordinate) + { + if (coordinate.isNull()) { return false; } + return false; + + // entry checks + /** + Q_ASSERT_X(CThreadUtils::isCurrentThreadObjectThread(this), Q_FUNC_INFO, "thread"); + + const SIMCONNECT_DATA_REQUEST_ID requestId = this->obtainRequestIdForProbe(); + const SIMCONNECT_DATA_INITPOSITION initialPosition = CSimulatorFsxCommon::coordinateToFsxPosition(coordinate); + const HRESULT hr = SimConnect_AICreateNonATCAircraft(m_hSimConnect, qPrintable(""), qPrintable(""), initialPosition, requestId); + if (hr != S_OK) + { + const CStatusMessage msg = CStatusMessage(this).error("SimConnect, can not create terrain AI: '%1'") << requestId; + CLogMessage::preformatted(msg); + } + + return hr == S_OK; + **/ + } + bool CSimulatorFsxCommon::physicallyRemoveRemoteAircraft(const CCallsign &callsign) { // only remove from sim @@ -1278,10 +1326,7 @@ namespace BlackSimPlugin Q_ASSERT_X(!situation.isGeodeticHeightNull(), Q_FUNC_INFO, "Missing height"); Q_ASSERT_X(!situation.isPositionNull(), Q_FUNC_INFO, "Missing position"); - SIMCONNECT_DATA_INITPOSITION position; - position.Latitude = situation.latitude().value(CAngleUnit::deg()); - position.Longitude = situation.longitude().value(CAngleUnit::deg()); - position.Altitude = situation.getAltitude().value(CLengthUnit::ft()); // already corrected in interpolator if there is an underflow + SIMCONNECT_DATA_INITPOSITION position = CSimulatorFsxCommon::coordinateToFsxPosition(situation); position.Heading = situation.getHeading().value(CAngleUnit::deg()); position.Airspeed = situation.getGroundSpeed().value(CSpeedUnit::kts()); @@ -1298,6 +1343,20 @@ namespace BlackSimPlugin return position; } + SIMCONNECT_DATA_INITPOSITION CSimulatorFsxCommon::coordinateToFsxPosition(const ICoordinateGeodetic &coordinate) + { + SIMCONNECT_DATA_INITPOSITION position; + position.Latitude = coordinate.latitude().value(CAngleUnit::deg()); + position.Longitude = coordinate.longitude().value(CAngleUnit::deg()); + position.Altitude = coordinate.geodeticHeight().value(CLengthUnit::ft()); // already corrected in interpolator if there is an underflow + position.Heading = 0; + position.Airspeed = 0; + position.Pitch = 0; + position.Bank = 0; + position.OnGround = 0; + return position; + } + void CSimulatorFsxCommon::synchronizeTime(const CTime &zuluTimeSim, const CTime &localTimeSim) { if (!m_simTimeSynced) { return; } @@ -1432,7 +1491,7 @@ namespace BlackSimPlugin m_syncDeferredCounter = 0; m_skipCockpitUpdateCycles = 0; m_interpolationRequest = 0; - m_requestIdSimData = static_cast(RequestSimDataStart); + m_requestIdSimData = static_cast(RequestIdSimDataStart); m_dispatchErrors = 0; m_receiveExceptionCount = 0; m_sendIdTraces.clear(); diff --git a/src/plugins/simulator/fsxcommon/simulatorfsxcommon.h b/src/plugins/simulator/fsxcommon/simulatorfsxcommon.h index f0546cfbc..55cf86c66 100644 --- a/src/plugins/simulator/fsxcommon/simulatorfsxcommon.h +++ b/src/plugins/simulator/fsxcommon/simulatorfsxcommon.h @@ -113,9 +113,6 @@ namespace BlackSimPlugin //! Destructor virtual ~CSimulatorFsxCommon(); - //! SimConnect Callback - static void CALLBACK SimConnectProc(SIMCONNECT_RECV *pData, DWORD cbData, void *pContext); - //! \name ISimulator implementations //! @{ virtual bool connectTo() override; @@ -134,7 +131,13 @@ namespace BlackSimPlugin virtual BlackMisc::CStatusMessageList debugVerifyStateAfterAllAircraftRemoved() const override; //! @} + //! \copydoc BlackMisc::Simulation::ISimulationEnvironmentProvider::requestElevation + virtual bool requestElevation(const BlackMisc::Geo::ICoordinateGeodetic &reference, const BlackMisc::Aviation::CCallsign &callsign) override; + protected: + //! SimConnect Callback + static void CALLBACK SimConnectProc(SIMCONNECT_RECV *pData, DWORD cbData, void *pContext); + //! \name Interface implementations //! @{ virtual bool isConnected() const override; @@ -161,9 +164,31 @@ namespace BlackSimPlugin //! @} virtual bool parseDetails(const BlackMisc::CSimpleCommandParser &parser) override; + //! Get new request id, overflow safe + SIMCONNECT_DATA_REQUEST_ID obtainRequestIdForSimData(); + + //! Get new request id, overflow safe + SIMCONNECT_DATA_REQUEST_ID obtainRequestIdForProbe(); + + //! Request for sim data (request in range of sim data)? + static bool isRequestForSimData(DWORD requestId) { return requestId >= (RequestIdSimDataStart + RequestSimDataOffset) && requestId < (RequestIdSimDataStart + RequestSimDataOffset + MaxSimObjects); } + + //! Request for lights (request in range of lights)? + static bool isRequestForLights(DWORD requestId) { return requestId >= (RequestIdSimDataStart + RequestLightsOffset) && requestId < (RequestIdSimDataStart + RequestLightsOffset + MaxSimObjects); } + + //! Request for probe (elevation)? + static bool isRequestForProbe(DWORD requestId) { return requestId >= RequestIdTerrainProbeStart && requestId <= RequestIdTerrainProbeEnd; } + //! Register help static void registerHelp(); + //! Callsign for pending request + BlackMisc::Aviation::CCallsign getCallsignForPendingProbeRequests(DWORD requestId, bool remove); + + HANDLE m_hSimConnect = nullptr; //!< handle to SimConnect object + DispatchProc m_dispatchProc = &CSimulatorFsxCommon::SimConnectProc; //!< called function for dispatch, can be overriden by specialized P3D function + QMap m_pendingProbeRequests; //!< pending elevation requests + private: //! Reason for adding an aircraft enum AircraftAddMode @@ -182,10 +207,13 @@ namespace BlackSimPlugin void dispatch(); //! Implementation of add remote aircraft, which also handles FSX specific adding one by one - //! \remark main purpose of this function is to only add one aircraft at a time, - //! and only if simulator is not paused/stopped + //! \remark main purpose of this function is to only add one aircraft at a time, and only if simulator is not paused/stopped bool physicallyAddRemoteAircraftImpl(const BlackMisc::Simulation::CSimulatedAircraft &newRemoteAircraft, AircraftAddMode addMode); + //! Add AI object for terrain probe + //! \remark experimental + bool physicallyAddAITerrainProbe(const BlackMisc::Geo::ICoordinateGeodetic &coordinate); + //! Remove aircraft no longer in provider //! \remark kind of cleanup function, in an ideal this should never need to cleanup something BlackMisc::Aviation::CCallsignSet physicallyRemoveAircraftNotInProvider(); @@ -224,9 +252,6 @@ namespace BlackSimPlugin //! Simulator is going down void onSimExit(); - //! Get new request id, overflow safe - SIMCONNECT_DATA_REQUEST_ID obtainRequestIdForSimData(); - //! Init when connected HRESULT initWhenConnected(); @@ -285,6 +310,9 @@ namespace BlackSimPlugin //! Format conversion SIMCONNECT_DATA_INITPOSITION aircraftSituationToFsxPosition(const BlackMisc::Aviation::CAircraftSituation &situation); + //! Format conversion + SIMCONNECT_DATA_INITPOSITION coordinateToFsxPosition(const BlackMisc::Geo::ICoordinateGeodetic &coordinate); + //! Sync time with user's computer void synchronizeTime(const BlackMisc::PhysicalQuantities::CTime &zuluTimeSim, const BlackMisc::PhysicalQuantities::CTime &localTimeSim); @@ -315,12 +343,6 @@ namespace BlackSimPlugin //! Insert an new SimConnect object CSimConnectObject insertNewSimConnectObject(const BlackMisc::Simulation::CSimulatedAircraft &aircraft, DWORD requestId); - //! Request for sim data (request in range of sim data)? - static bool isRequestForSimData(DWORD requestId) { return requestId >= (RequestSimDataStart + RequestSimDataOffset) && requestId < (RequestSimDataStart + RequestSimDataOffset + MaxSimObjects); } - - //! Request for lights (request in range of lights)? - static bool isRequestForLights(DWORD requestId) { return requestId >= (RequestSimDataStart + RequestLightsOffset) && requestId < (RequestSimDataStart + RequestLightsOffset + MaxSimObjects); } - //! Encapsulates creating QString from FSX string data static QString fsxCharToQString(const char *fsxChar, int size = -1); @@ -329,10 +351,12 @@ namespace BlackSimPlugin static constexpr int IgnoreReceiveExceptions = 10; //!< skip exceptions when displayed more than x times static constexpr int MaxSimObjects = 10000; //!< max.number of SimObjects at the same time static constexpr int MaxSendIdTraces = 10000; //!< max.traces of send id - static constexpr int RequestSimDataStart = static_cast(CSimConnectDefinitions::RequestEndMarker); - static constexpr int RequestSimDataEnd = RequestSimDataStart + MaxSimObjects - 1; - static constexpr int RequestSimDataOffset = 0 * MaxSimObjects; - static constexpr int RequestLightsOffset = 1 * MaxSimObjects; + static constexpr int RequestIdSimDataStart = static_cast(CSimConnectDefinitions::RequestEndMarker); + static constexpr int RequestIdSimDataEnd = RequestIdSimDataStart + MaxSimObjects - 1; + static constexpr int RequestSimDataOffset = 0 * MaxSimObjects; //!< range for sim data requests + static constexpr int RequestLightsOffset = 1 * MaxSimObjects; //!< range for lights + static constexpr int RequestIdTerrainProbeStart = 2 * MaxSimObjects + RequestIdSimDataEnd + 1; //!< range for terrain probe + static constexpr int RequestIdTerrainProbeEnd = (RequestIdTerrainProbeStart + 1000) - 1; static constexpr int AddPendingAircraftIntervalMs = 20 * 1000; static constexpr int DispatchIntervalMs = 10; //!< how often with run the FSX event queue static constexpr int DeferSimulatingFlagMs = 1500; //!< simulating can jitter at startup (simulating->stopped->simulating, multiple start events), so we defer detection @@ -349,11 +373,11 @@ namespace BlackSimPlugin int m_interpolationRequest = 0; //!< current interpolation request int m_dispatchErrors = 0; //!< number of dispatched failed, \sa dispatch int m_receiveExceptionCount = 0; //!< exceptions - HANDLE m_hSimConnect = nullptr; //!< handle to SimConnect object QList m_sendIdTraces; //!< Send id traces for debugging CSimConnectObjects m_simConnectObjects; //!< AI objects and their object / request ids CSimConnectObjects m_simConnectObjectsPositionAndPartsTraces; //!< position/parts received, but object not yet added, excluded, disabled etc. - SIMCONNECT_DATA_REQUEST_ID m_requestIdSimData = static_cast(RequestSimDataStart); //!< request id, use obtainRequestId() to get id + SIMCONNECT_DATA_REQUEST_ID m_requestIdSimData = static_cast(RequestIdSimDataStart); //!< request id, use obtainRequestIdForSimData() to get id + SIMCONNECT_DATA_REQUEST_ID m_requestIdProbe = static_cast(RequestIdTerrainProbeStart); //!< request id, use obtainRequestIdForProbe() to get id BlackMisc::Simulation::CSimulatedAircraftList m_addPendingAircraft; //!< aircraft awaiting to be added QTimer m_addPendingAircraftTimer; //!< updating of aircraft awaiting to be added }; diff --git a/src/plugins/simulator/p3d/p3d.pro b/src/plugins/simulator/p3d/p3d.pro index eee8347e7..138b3bf75 100644 --- a/src/plugins/simulator/p3d/p3d.pro +++ b/src/plugins/simulator/p3d/p3d.pro @@ -43,7 +43,6 @@ addStaticLibraryDependency(fsuipc) msvc: QMAKE_LFLAGS *= /ignore:4099 DISTFILES += simulatorp3d.json - DESTDIR = $$DestRoot/bin/plugins/simulator win32 { diff --git a/src/plugins/simulator/p3d/simulatorp3d.cpp b/src/plugins/simulator/p3d/simulatorp3d.cpp index 93882f47a..4b8d34a83 100644 --- a/src/plugins/simulator/p3d/simulatorp3d.cpp +++ b/src/plugins/simulator/p3d/simulatorp3d.cpp @@ -10,7 +10,10 @@ #include "simulatorp3d.h" #include "blackcore/application.h" #include "blackmisc/threadutils.h" +#include "blackmisc/logmessage.h" +#include "blackconfig/buildconfig.h" +using namespace BlackConfig; using namespace BlackMisc; using namespace BlackMisc::Aviation; using namespace BlackMisc::PhysicalQuantities; @@ -32,8 +35,96 @@ namespace BlackSimPlugin QObject *parent) : CSimulatorFsxCommon(info, ownAircraftProvider, remoteAircraftProvider, weatherGridProvider, parent) { + if (CBuildConfig::isCompiledWithP3DSupport() && CBuildConfig::isRunningOnWindowsNtPlatform() && CBuildConfig::buildWordSize() == 64) + { + m_dispatchProc = &CSimulatorP3D::SimConnectProc; + } this->setDefaultModel(CAircraftModel("LOCKHEED L049_2", CAircraftModel::TypeModelMatchingDefaultModel, "Constellation in TWA livery", CAircraftIcaoCode("CONI", "L4P"))); } + +#ifdef Q_OS_WIN64 + void CSimulatorP3D::SimConnectProc(SIMCONNECT_RECV *pData, DWORD cbData, void *pContext) + { + CSimulatorP3D *simulatorP3D = static_cast(pContext); + Q_ASSERT_X(simulatorP3D, Q_FUNC_INFO, "Cannot convert context to CSimulatorP3D"); + + switch (pData->dwID) + { + case SIMCONNECT_RECV_ID_GROUND_INFO: + { + // https://www.prepar3d.com/SDKv4/sdk/simconnect_api/references/structures_and_enumerations.html#SIMCONNECT_RECV_GROUND_INFO + const SIMCONNECT_RECV_GROUND_INFO *pObjData = (SIMCONNECT_RECV_GROUND_INFO *) pData; + const DWORD requestId = pObjData->dwRequestID; + if (!CSimulatorFsxCommon::isRequestForProbe(requestId)) { break; } + // valid elevation request + // https://www.prepar3d.com/SDKv4/sdk/simconnect_api/references/structures_and_enumerations.html#SIMCONNECT_DATA_GROUND_INFO + if (pObjData->dwArraySize != 1) { break; } + const SIMCONNECT_DATA_GROUND_INFO gi = pObjData->rgData[0]; + if (!gi.bIsValid) { break; } + const CLatitude lat(gi.fLat, CAngleUnit::deg()); + const CLongitude lng(gi.fLon, CAngleUnit::deg()); + const CAltitude alt(gi.fAlt, CAltitude::MeanSeaLevel, CAltitude::TrueAltitude, CLengthUnit::ft()); + const CCoordinateGeodetic coordinate(lat, lng, alt); + const CElevationPlane ep(coordinate, CElevationPlane::singlePointRadius()); + + const CCallsign cs(simulatorP3D->getCallsignForPendingProbeRequests(requestId, true)); + simulatorP3D->callbackReceivedRequestedElevation(ep, cs); + } + break; + default: + CSimulatorFsxCommon::SimConnectProc(pData, cbData, pContext); + break; + } + } + + // P3D version with new P3D simconnect functions + bool CSimulatorP3D::requestElevation(const ICoordinateGeodetic &reference, const CCallsign &callsign) + { + if (reference.isNull()) { return false; } + if (this->isShuttingDown()) { return false; } + if (!this->isConnected()) { return false; } + + Q_ASSERT_X(CThreadUtils::isCurrentThreadObjectThread(this), Q_FUNC_INFO, "thread"); + const double latDeg = reference.latitude().value(CAngleUnit::deg()); + const double lngDeg = reference.longitude().value(CAngleUnit::deg()); + const double maxAltFt = reference.geodeticHeight().value(CLengthUnit::ft()); + const DWORD dwGridWidth = 1.0; + const DWORD dwGridHeight = 1.0; + + const SIMCONNECT_DATA_REQUEST_ID requestId = this->obtainRequestIdForProbe(); + + // returns SIMCONNECT_RECV_GROUND_INFO -> SIMCONNECT_DATA_GROUND_INFO + const HRESULT hr = SimConnect_RequestGroundInfo( + m_hSimConnect, requestId, latDeg, lngDeg, 0, latDeg, lngDeg, maxAltFt, + dwGridWidth, dwGridHeight, + SIMCONNECT_GROUND_INFO_LATLON_FORMAT_DEGREES, + SIMCONNECT_GROUND_INFO_ALT_FORMAT_FEET, + SIMCONNECT_GROUND_INFO_SOURCE_FLAG_PLATFORMS); + bool ok = false; + if (hr == S_OK) + { + ok = true; + m_pendingProbeRequests.insert(requestId, callsign); + } + else + { + const CStatusMessage msg = CStatusMessage(this).error("SimConnect, can not request ground info: '%1' '%2'") << requestId << callsign.asString(); + CLogMessage::preformatted(msg); + } + + return ok; + } +#else + void CSimulatorP3D::SimConnectProc(SIMCONNECT_RECV *pData, DWORD cbData, void *pContext) + { + CSimulatorFsxCommon::SimConnectProc(pData, cbData, pContext); + } + + bool CSimulatorP3D::requestElevation(const ICoordinateGeodetic &reference, const CCallsign &callsign) + { + return CSimulatorFsxCommon::requestElevation(reference, callsign); + } +#endif } // namespace } // namespace diff --git a/src/plugins/simulator/p3d/simulatorp3d.h b/src/plugins/simulator/p3d/simulatorp3d.h index d49284c21..413495665 100644 --- a/src/plugins/simulator/p3d/simulatorp3d.h +++ b/src/plugins/simulator/p3d/simulatorp3d.h @@ -31,6 +31,13 @@ namespace BlackSimPlugin BlackMisc::Simulation::IRemoteAircraftProvider *remoteAircraftProvider, BlackMisc::Weather::IWeatherGridProvider *weatherGridProvider, QObject *parent = nullptr); + + //! \copydoc BlackMisc::Simulation::ISimulationEnvironmentProvider::requestElevation + virtual bool requestElevation(const BlackMisc::Geo::ICoordinateGeodetic &reference, const BlackMisc::Aviation::CCallsign &callsign) override; + + protected: + //! SimConnect Callback + static void CALLBACK SimConnectProc(SIMCONNECT_RECV *pData, DWORD cbData, void *pContext); }; //! Listener for P3D diff --git a/src/plugins/simulator/xplane/simulatorxplane.cpp b/src/plugins/simulator/xplane/simulatorxplane.cpp index 15317f063..333b861f0 100644 --- a/src/plugins/simulator/xplane/simulatorxplane.cpp +++ b/src/plugins/simulator/xplane/simulatorxplane.cpp @@ -114,10 +114,10 @@ namespace BlackSimPlugin m_watcher = nullptr; } - bool CSimulatorXPlane::requestElevation(const Geo::ICoordinateGeodetic &reference) const + bool CSimulatorXPlane::requestElevation(const ICoordinateGeodetic &reference, const CCallsign &callsign) { //! \todo KB 2018-04 implement a function fetching the probe value (async) and write it back to provider - return ISimulator::requestElevation(reference); + return ISimulator::requestElevation(reference, callsign); } // convert xplane squawk mode to swift squawk mode diff --git a/src/plugins/simulator/xplane/simulatorxplane.h b/src/plugins/simulator/xplane/simulatorxplane.h index 190f42e42..9682f4f90 100644 --- a/src/plugins/simulator/xplane/simulatorxplane.h +++ b/src/plugins/simulator/xplane/simulatorxplane.h @@ -138,7 +138,7 @@ namespace BlackSimPlugin //! @} //! \copydoc BlackMisc::Simulation::ISimulationEnvironmentProvider::requestElevation - virtual bool requestElevation(const BlackMisc::Geo::ICoordinateGeodetic &reference) const override; + virtual bool requestElevation(const BlackMisc::Geo::ICoordinateGeodetic &reference, const BlackMisc::Aviation::CCallsign &callsign) override; //! Creates an appropriate dbus connection from the string describing it static QDBusConnection connectionFromString(const QString &str);