diff --git a/src/blackcore/context/contextnetworkimpl.cpp b/src/blackcore/context/contextnetworkimpl.cpp index b0c3a1739..beb2d5e2b 100644 --- a/src/blackcore/context/contextnetworkimpl.cpp +++ b/src/blackcore/context/contextnetworkimpl.cpp @@ -820,6 +820,13 @@ namespace BlackCore return c; } + bool CContextNetwork::updateCGAndModelString(const CCallsign &callsign, const CLength &cg, const QString &modelString) + { + if (this->isDebugEnabled()) { CLogMessage(this, CLogCategory::contextSlot()).debug() << Q_FUNC_INFO << callsign << cg.valueRoundedWithUnit(1) << modelString; } + const bool c = m_airspace->updateCGAndModelString(callsign, cg, modelString); + return c; + } + void CContextNetwork::requestAtcBookingsUpdate() const { if (this->isDebugEnabled()) { CLogMessage(this, CLogCategory::contextSlot()).debug() << Q_FUNC_INFO; } diff --git a/src/blackcore/context/contextnetworkimpl.h b/src/blackcore/context/contextnetworkimpl.h index 9fba46b65..d7b12ae49 100644 --- a/src/blackcore/context/contextnetworkimpl.h +++ b/src/blackcore/context/contextnetworkimpl.h @@ -158,6 +158,7 @@ namespace BlackCore virtual int reInitializeAllAircraft() override; virtual bool updateAircraftSupportingGndFLag(const BlackMisc::Aviation::CCallsign &callsign, bool supportGndFlag) override; virtual bool updateCG(const BlackMisc::Aviation::CCallsign &callsign, const BlackMisc::PhysicalQuantities::CLength &cg) override; + virtual bool updateCGAndModelString(const BlackMisc::Aviation::CCallsign &callsign, const BlackMisc::PhysicalQuantities::CLength &cg, const QString &modelString) override; virtual BlackMisc::Simulation::CSimulatedAircraftList getAircraftInRange() const override; virtual BlackMisc::Aviation::CCallsignSet getAircraftInRangeCallsigns() const override; virtual int getAircraftInRangeCount() const override; diff --git a/src/blackcore/context/contextsimulatorimpl.cpp b/src/blackcore/context/contextsimulatorimpl.cpp index c304eac6e..965986565 100644 --- a/src/blackcore/context/contextsimulatorimpl.cpp +++ b/src/blackcore/context/contextsimulatorimpl.cpp @@ -511,8 +511,10 @@ namespace BlackCore // coming from CAirspaceMonitor::sendReadyForModelMatching CStatusMessageList matchingMessages; CStatusMessageList *pMatchingMessages = m_enableMatchingMessages ? &matchingMessages : nullptr; - const CAircraftModel aircraftModel = m_aircraftMatcher.getClosestMatch(remoteAircraft, pMatchingMessages); + CAircraftModel aircraftModel = m_aircraftMatcher.getClosestMatch(remoteAircraft, pMatchingMessages); Q_ASSERT_X(remoteAircraft.getCallsign() == aircraftModel.getCallsign(), Q_FUNC_INFO, "Mismatching callsigns"); + const CLength cg = m_simulatorPlugin.second->getCGPerModelString(aircraftModel.getModelString()); + if (!cg.isNull()) { aircraftModel.setCG(cg); } this->updateAircraftModel(callsign, aircraftModel, this->identifier()); const CSimulatedAircraft aircraftAfterModelApplied = this->getAircraftInRangeForCallsign(remoteAircraft.getCallsign()); if (!aircraftAfterModelApplied.hasModelString()) @@ -520,7 +522,7 @@ namespace BlackCore if (!aircraftAfterModelApplied.hasCallsign()) { return; } // removed if (this->isAircraftInRange(aircraftAfterModelApplied.getCallsign())) { return; } // removed, but callsig, we did crosscheck - // callsign but not string + // callsign, but no model string CLogMessage(this).error("Matching error for '%1', no model string") << aircraftAfterModelApplied.getCallsign().asString(); CSimulatedAircraft brokenAircraft(aircraftAfterModelApplied); diff --git a/src/blackcore/simulator.cpp b/src/blackcore/simulator.cpp index 2afa92ea7..bc539666b 100644 --- a/src/blackcore/simulator.cpp +++ b/src/blackcore/simulator.cpp @@ -107,7 +107,7 @@ namespace BlackCore ISimulator::registerHelp(); } - void ISimulator::rememberElevationAndCG(const CCallsign &callsign, const Geo::CElevationPlane &elevation, const CLength &cg) + void ISimulator::rememberElevationAndCG(const CCallsign &callsign, const QString &modelString, const Geo::CElevationPlane &elevation, const CLength &cg) { if (callsign.isEmpty()) { return; } if (!elevation.isNull()) @@ -116,7 +116,7 @@ namespace BlackCore this->setRememberMaxElevations(aircraftCount * 3); // at least 3 elevations per aircraft, even better as not all are requesting elevations this->rememberGroundElevation(elevation); } - if (!cg.isNull() && !this->hasSameCG(cg, callsign)) { this->insertCG(cg, callsign); } + if (!cg.isNull() && !this->hasSameCG(cg, callsign)) { this->insertCG(cg, modelString, callsign); } } void ISimulator::emitSimulatorCombinedStatus(SimulatorStatus oldStatus) diff --git a/src/blackcore/simulator.h b/src/blackcore/simulator.h index ef5cfa999..2f5d6d312 100644 --- a/src/blackcore/simulator.h +++ b/src/blackcore/simulator.h @@ -290,7 +290,7 @@ namespace BlackCore virtual int physicallyRemoveAllRemoteAircraft() = 0; //! Set elevation and CG in the providers - void rememberElevationAndCG(const BlackMisc::Aviation::CCallsign &callsign, const BlackMisc::Geo::CElevationPlane &elevation, const BlackMisc::PhysicalQuantities::CLength &cg); + void rememberElevationAndCG(const BlackMisc::Aviation::CCallsign &callsign, const QString &modelString, 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); diff --git a/src/blackmisc/simulation/remoteaircraftprovider.cpp b/src/blackmisc/simulation/remoteaircraftprovider.cpp index 6ebd06c5a..e4130d2d1 100644 --- a/src/blackmisc/simulation/remoteaircraftprovider.cpp +++ b/src/blackmisc/simulation/remoteaircraftprovider.cpp @@ -511,6 +511,16 @@ namespace BlackMisc return true; } + bool CRemoteAircraftProvider::updateCGAndModelString(const CCallsign &callsign, const CLength &cg, const QString &modelString) + { + QWriteLocker l(&m_lockAircraft); + if (!m_aircraftInRange.contains(callsign)) { return false; } + CSimulatedAircraft &aircraft = m_aircraftInRange[callsign]; + if (!cg.isNull()) { aircraft.setCG(cg); } + if (!modelString.isEmpty()) { aircraft.setModelString(modelString); } + return true; + } + void CRemoteAircraftProvider::updateMarkAllAsNotRendered() { const CCallsignSet callsigns = this->getAircraftInRangeCallsigns(); @@ -856,6 +866,18 @@ namespace BlackMisc return this->provider()->updateAircraftGroundElevation(callsign, elevation, info); } + bool CRemoteAircraftAware::updateCG(const CCallsign &callsign, const CLength &cg) + { + Q_ASSERT_X(this->provider(), Q_FUNC_INFO, "No object available"); + return this->provider()->updateCG(callsign, cg); + } + + bool CRemoteAircraftAware::updateCGAndModelString(const CCallsign &callsign, const CLength &cg, const QString &modelString) + { + Q_ASSERT_X(this->provider(), Q_FUNC_INFO, "No object available"); + return this->provider()->updateCGAndModelString(callsign, cg, modelString); + } + void CRemoteAircraftAware::updateMarkAllAsNotRendered() { Q_ASSERT_X(this->provider(), Q_FUNC_INFO, "No object available"); diff --git a/src/blackmisc/simulation/remoteaircraftprovider.h b/src/blackmisc/simulation/remoteaircraftprovider.h index a8b7a9a35..4479da9e5 100644 --- a/src/blackmisc/simulation/remoteaircraftprovider.h +++ b/src/blackmisc/simulation/remoteaircraftprovider.h @@ -175,6 +175,10 @@ namespace BlackMisc //! \threadsafe virtual bool updateCG(const Aviation::CCallsign &callsign, const PhysicalQuantities::CLength &cg) = 0; + //! Update the CG and model string + //! \threadsafe + virtual bool updateCGAndModelString(const Aviation::CCallsign &callsign, const PhysicalQuantities::CLength &cg, const QString &modelString) = 0; + //! Get reverse lookup meesages //! \threadsafe virtual CStatusMessageList getReverseLookupMessages(const Aviation::CCallsign &callsign) const = 0; @@ -286,6 +290,7 @@ namespace BlackMisc virtual bool updateAircraftRendered(const Aviation::CCallsign &callsign, bool rendered) override; virtual int updateAircraftGroundElevation(const Aviation::CCallsign &callsign, const Geo::CElevationPlane &elevation, Aviation::CAircraftSituation::GndElevationInfo info) override; virtual bool updateCG(const Aviation::CCallsign &callsign, const PhysicalQuantities::CLength &cg) override; + virtual bool updateCGAndModelString(const Aviation::CCallsign &callsign, const PhysicalQuantities::CLength &cg, const QString &modelString) override; virtual void updateMarkAllAsNotRendered() override; virtual CStatusMessageList getAircraftPartsHistory(const Aviation::CCallsign &callsign) const override; virtual bool isAircraftPartsHistoryEnabled() const override; @@ -515,6 +520,12 @@ namespace BlackMisc //! \copydoc IRemoteAircraftProvider::updateAircraftGroundElevation int updateAircraftGroundElevation(const Aviation::CCallsign &callsign, const Geo::CElevationPlane &elevation, Aviation::CAircraftSituation::GndElevationInfo info); + //! \copydoc IRemoteAircraftProvider::updateCG + bool updateCG(const Aviation::CCallsign &callsign, const PhysicalQuantities::CLength &cg); + + //! \copydoc IRemoteAircraftProvider::updateCGAndModelString + bool updateCGAndModelString(const Aviation::CCallsign &callsign, const PhysicalQuantities::CLength &cg, const QString &modelString); + //! \copydoc IRemoteAircraftProvider::updateMarkAllAsNotRendered void updateMarkAllAsNotRendered(); diff --git a/src/blackmisc/simulation/simulationenvironmentprovider.cpp b/src/blackmisc/simulation/simulationenvironmentprovider.cpp index 733c17495..c886baef8 100644 --- a/src/blackmisc/simulation/simulationenvironmentprovider.cpp +++ b/src/blackmisc/simulation/simulationenvironmentprovider.cpp @@ -49,20 +49,37 @@ namespace BlackMisc if (remove) { QWriteLocker l(&m_lockCG); - m_cgs.remove(cs); + m_cgsPerCallsign.remove(cs); } else { QWriteLocker l(&m_lockCG); - m_cgs[cs] = cg; + m_cgsPerCallsign[cs] = cg; } return true; } + bool ISimulationEnvironmentProvider::insertCG(const CLength &cg, const QString &modelString, const CCallsign &cs) + { + bool ok = false; + QWriteLocker l(&m_lockCG); + if (!cs.isEmpty()) { m_cgsPerCallsign[cs] = cg; ok = true; } + if (!modelString.isEmpty()) { m_cgsPerModel[modelString.toLower()] = cg; ok = true; } + return ok; + } + + bool ISimulationEnvironmentProvider::insertCGForModelString(const CLength &cg, const QString &modelString) + { + if (modelString.isEmpty()) { return false; } + QWriteLocker l(&m_lockCG); + m_cgsPerModel[modelString.toLower()] = cg; + return true; + } + int ISimulationEnvironmentProvider::removeCG(const CCallsign &cs) { QWriteLocker l(&m_lockCG); - return m_cgs.remove(cs); + return m_cgsPerCallsign.remove(cs); } CLength ISimulationEnvironmentProvider::minRange(const CLength &range) @@ -170,23 +187,33 @@ namespace BlackMisc CLength ISimulationEnvironmentProvider::getCG(const Aviation::CCallsign &callsign) const { + if (callsign.isEmpty()) { return CLength::null(); } QReadLocker l(&m_lockCG); - if (!m_cgs.contains(callsign)) { return CLength::null(); } - return m_cgs.value(callsign); + if (!m_cgsPerCallsign.contains(callsign)) { return CLength::null(); } + return m_cgsPerCallsign.value(callsign); + } + + CLength ISimulationEnvironmentProvider::getCGPerModelString(const QString &modelString) const + { + if (modelString.isEmpty()) { return CLength::null(); } + const QString ms = modelString.toLower(); + QReadLocker l(&m_lockCG); + if (!m_cgsPerModel.contains(ms)) { return CLength::null(); } + return m_cgsPerModel.value(ms); } bool ISimulationEnvironmentProvider::hasCG(const Aviation::CCallsign &callsign) const { if (callsign.isEmpty()) { return false; } QReadLocker l(&m_lockCG); - return m_cgs.contains(callsign); + return m_cgsPerCallsign.contains(callsign); } bool ISimulationEnvironmentProvider::hasSameCG(const CLength &cg, const CCallsign &callsign) const { if (callsign.isEmpty()) { return false; } QReadLocker l(&m_lockCG); - return m_cgs[callsign] == cg; + return m_cgsPerCallsign[callsign] == cg; } int ISimulationEnvironmentProvider::setRememberMaxElevations(int max) @@ -262,7 +289,8 @@ namespace BlackMisc void ISimulationEnvironmentProvider::clearCGs() { QWriteLocker l(&m_lockCG); - m_cgs.clear(); + m_cgsPerCallsign.clear(); + // intentionally not cleaning CGs per model, as models will not change, callsign do! } void ISimulationEnvironmentProvider::clearSimulationEnvironmentData() diff --git a/src/blackmisc/simulation/simulationenvironmentprovider.h b/src/blackmisc/simulation/simulationenvironmentprovider.h index 5345bf560..84a5ac940 100644 --- a/src/blackmisc/simulation/simulationenvironmentprovider.h +++ b/src/blackmisc/simulation/simulationenvironmentprovider.h @@ -18,8 +18,7 @@ #include "blackmisc/pq/length.h" #include "blackmisc/geo/coordinategeodeticlist.h" #include "blackmisc/geo/elevationplane.h" - -#include +#include #include #include @@ -72,6 +71,10 @@ namespace BlackMisc //! \threadsafe PhysicalQuantities::CLength getCG(const Aviation::CCallsign &callsign) const; + //! Get CG per model string, NULL if not found + //! \threadsafe + PhysicalQuantities::CLength getCGPerModelString(const QString &modelString) const; + //! Has a CG? //! \threadsafe bool hasCG(const Aviation::CCallsign &callsign) const; @@ -153,6 +156,16 @@ namespace BlackMisc //! \threadsafe bool insertCG(const PhysicalQuantities::CLength &cg, const Aviation::CCallsign &cs); + //! Insert or replace a CG + //! \remark passing a NULL value will remove the CG + //! \threadsafe + bool insertCG(const PhysicalQuantities::CLength &cg, const QString &modelString, const Aviation::CCallsign &cs); + + //! Insert or replace a CG + //! \remark passing a NULL value will remove the CG + //! \threadsafe + bool insertCGForModelString(const PhysicalQuantities::CLength &cg, const QString &modelString); + //! Remove a CG //! \threadsafe int removeCG(const Aviation::CCallsign &cs); @@ -162,15 +175,16 @@ namespace BlackMisc private: CSimulatorPluginInfo m_simulatorPluginInfo; //!< info object - QString m_simulatorName; //!< name of simulator - QString m_simulatorDetails; //!< describes version etc. - QString m_simulatorVersion; //!< Simulator version + QString m_simulatorName; //!< name of simulator + QString m_simulatorDetails; //!< describes version etc. + QString m_simulatorVersion; //!< Simulator version CAircraftModel m_defaultModel; //!< default model - int m_maxElevations = 100; //!< How many elevations we keep + int m_maxElevations = 100; //!< How many elevations we keep Geo::CCoordinateGeodeticList m_elvCoordinates; - QMap m_cgs; //! CGs - mutable int m_elvFound = 0; //!< statistics only - mutable int m_elvMissed = 0; //!< statistics only + QHash m_cgsPerCallsign; //! CGs per callsign + QHash m_cgsPerModel; //!< CGs per model string + mutable int m_elvFound = 0; //!< statistics only + mutable int m_elvMissed = 0; //!< statistics only mutable QReadWriteLock m_lockElvCoordinates; //!< lock m_coordinates mutable QReadWriteLock m_lockCG; //!< lock CGs mutable QReadWriteLock m_lockModel; //!< lock models diff --git a/src/plugins/simulator/xplane/simulatorxplane.cpp b/src/plugins/simulator/xplane/simulatorxplane.cpp index 3a2072aad..53c2768fa 100644 --- a/src/plugins/simulator/xplane/simulatorxplane.cpp +++ b/src/plugins/simulator/xplane/simulatorxplane.cpp @@ -782,15 +782,13 @@ namespace BlackSimPlugin if (!m_xplaneAircraftObjects.contains(cs)) { continue; } // we skip if we are not near ground - if (m_xplaneAircraftObjects[cs].getSituationAsSent().canLikelySkipNearGroundInterpolation()) { continue; } + const CXPlaneMPAircraft xpAircraft = m_xplaneAircraftObjects[cs]; + if (xpAircraft.getSituationAsSent().canLikelySkipNearGroundInterpolation()) { continue; } - CAltitude elevationAlt(elevationsM[i], CLengthUnit::m()); - elevationAlt.switchUnit(CLengthUnit::ft()); - CElevationPlane elevation(CLatitude(latitudesDeg[i], CAngleUnit::deg()), CLongitude(longitudesDeg[i], CAngleUnit::deg()), elevationAlt); - elevation.setSinglePointRadius(); - CLength cg(verticalOffsets[i], CLengthUnit::m()); - cg.switchUnit(CLengthUnit::ft()); - this->rememberElevationAndCG(callsigns[i], elevation, cg); + const CAltitude elevationAlt(elevationsM[i], CLengthUnit::m(), CLengthUnit::ft()); + const CElevationPlane elevation(CLatitude(latitudesDeg[i], CAngleUnit::deg()), CLongitude(longitudesDeg[i], CAngleUnit::deg()), elevationAlt, CElevationPlane::singlePointRadius()); + const CLength cg(verticalOffsets[i], CLengthUnit::m(), CLengthUnit::ft()); + this->rememberElevationAndCG(cs, xpAircraft.getAircraftModelString(), elevation, cg); } }