refs #395, prepared for snapshot handling

* logical / physical add/remote member functions in drivers, renamed functions
* added access to snapshot
* snapshot generation in analyzer
* snapshot handling in driver
* moved simulator base class in own files (.h/.cpp)
* added functions as required to context
This commit is contained in:
Klaus Basan
2015-05-06 02:45:17 +02:00
committed by Mathew Sutcliffe
parent e9f7810efc
commit 1c3bb8d463
19 changed files with 314 additions and 140 deletions

View File

@@ -63,6 +63,15 @@ namespace BlackCore
return m_latestAircraftSnapshot;
}
void CAirspaceAnalyzer::setSimulatorRenderRestrictionsChanged(bool restricted, int maxAircraft, const CLength &maxRenderedDistance, const CLength &maxRenderedBoundary)
{
QWriteLocker l(&m_lockRestrictions);
this->m_simulatorRenderedAircraftRestricted = restricted;
this->m_simulatorMaxRenderedAircraft = maxAircraft;
this->m_simulatorMaxRenderedDistance = maxRenderedDistance;
this->m_simulatorMaxRenderedBoundary = maxRenderedBoundary;
}
void CAirspaceAnalyzer::ps_watchdogTouchAircraftCallsign(const CAircraftSituation &situation, const CTransponder &transponder)
{
Q_ASSERT_X(!situation.getCallsign().isEmpty(), Q_FUNC_INFO, "No callsign in situaton");
@@ -150,16 +159,28 @@ namespace BlackCore
void CAirspaceAnalyzer::analyzeAirspace()
{
bool restricted;
int maxAircraft;
CLength maxRenderedDistance, maxRenderedBoundary;
{
QReadLocker l(&m_lockRestrictions);
restricted = this->m_simulatorRenderedAircraftRestricted;
maxAircraft = this->m_simulatorMaxRenderedAircraft;
maxRenderedDistance = this->m_simulatorMaxRenderedDistance;
maxRenderedBoundary = this->m_simulatorMaxRenderedBoundary;
}
CAirspaceAircraftSnapshot snapshot(
getAircraftInRange() // thread safe copy
getAircraftInRange(), // thread safe copy
restricted, maxAircraft, maxRenderedDistance, maxRenderedBoundary
);
// lock block
{
QWriteLocker l(&m_lockSnapshot);
snapshot.setRestrictionChanged(m_latestAircraftSnapshot);
m_latestAircraftSnapshot = snapshot;
}
emit airspaceAircraftSnapshot(snapshot);
}

View File

@@ -51,6 +51,9 @@ namespace BlackCore
//! \threadsafe
BlackMisc::Simulation::CAirspaceAircraftSnapshot getLatestAirspaceAircraftSnapshot() const;
//! Render restrictions in simulator
void setSimulatorRenderRestrictionsChanged(bool restricted, int maxAircraft, const BlackMisc::PhysicalQuantities::CLength &maxRenderedDistance, const BlackMisc::PhysicalQuantities::CLength &maxRenderedBoundary);
public slots:
//! Clear
void clear();
@@ -103,7 +106,12 @@ namespace BlackCore
// snapshot
BlackMisc::Simulation::CAirspaceAircraftSnapshot m_latestAircraftSnapshot;
mutable QReadWriteLock m_lockSnapshot; //!< lock snapshot
bool m_simulatorRenderedAircraftRestricted = false;
int m_simulatorMaxRenderedAircraft = -1;
BlackMisc::PhysicalQuantities::CLength m_simulatorMaxRenderedDistance { 0.0, BlackMisc::PhysicalQuantities::CLengthUnit::nullUnit() };
BlackMisc::PhysicalQuantities::CLength m_simulatorMaxRenderedBoundary { 0.0, BlackMisc::PhysicalQuantities::CLengthUnit::nullUnit() };
mutable QReadWriteLock m_lockSnapshot; //!< lock snapshot
mutable QReadWriteLock m_lockRestrictions; //!< lock simulator restrictions
};
} // namespace

View File

@@ -160,6 +160,9 @@ namespace BlackCore
//! Enable interim position sending
void enableFastPositionSending(bool enable);
//! Analyzer
CAirspaceAnalyzer *analyzer() const { return m_analyzer; }
static const qint64 AircraftSituationsRemovedOffsetMs = 30 * 1000; //!< situations older than now - offset will be removed
static const qint64 AircraftPartsRemoveOffsetMs = 30 * 1000; //!< parts older than now - offset will be removed

View File

@@ -436,6 +436,13 @@ namespace BlackCore
emit this->connectionStatusChanged(from, to);
}
void CContextNetwork::ps_simulatorRenderRestrictionsChanged(bool restricted, int maxAircraft, const CLength &maxRenderedDistance, const CLength &maxRenderedBoundary)
{
if (!m_airspace) { return; }
if (!m_airspace->analyzer()) { return; }
m_airspace->analyzer()->setSimulatorRenderRestrictionsChanged(restricted, maxAircraft, maxRenderedDistance, maxRenderedBoundary);
}
void CContextNetwork::ps_dataFileRead()
{
if (this->isDebugEnabled()) { CLogMessage(this, CLogCategory::contextSlot()).debug() << Q_FUNC_INFO; }

View File

@@ -269,6 +269,11 @@ namespace BlackCore
//! Connection status changed
void ps_fsdConnectionStatusChanged(INetwork::ConnectionStatus from, INetwork::ConnectionStatus to);
//! Render restrictions have been changed, used with analyzer
//! \sa CAirspaceAnalyzer
void ps_simulatorRenderRestrictionsChanged(bool restricted, int maxAircraft, const BlackMisc::PhysicalQuantities::CLength &maxRenderedDistance, const BlackMisc::PhysicalQuantities::CLength &maxRenderedBoundary);
};
}

View File

@@ -71,17 +71,23 @@ namespace BlackCore
//! \sa ISimulator::SimulatorStatus
void simulatorStatusChanged(int status);
//! Only a limited number of aircraft displayed
void restrictedRenderingChanged(bool restricted);
//! Simulator plugin loaded / unloaded (default info)
void simulatorPluginChanged(const BlackMisc::Simulation::CSimulatorPluginInfo &info);
//! Render restrictions have been changed
void renderRestrictionsChanged(bool restricted, int maxAircraft, const BlackMisc::PhysicalQuantities::CLength &maxRenderedDistance, const BlackMisc::PhysicalQuantities::CLength &maxRenderedBoundary);
//! Installed aircraft models ready or changed
void installedAircraftModelsChanged();
//! A single model has been matched for given aircraft
void modelMatchingCompleted(BlackMisc::Simulation::CSimulatedAircraft aircraft);
void modelMatchingCompleted(const BlackMisc::Simulation::CSimulatedAircraft &aircraft);
//! Emitted when own aircraft model changes
void ownAircraftModelChanged(BlackMisc::Simulation::CSimulatedAircraft aircraft);
void ownAircraftModelChanged(const BlackMisc::Simulation::CSimulatedAircraft &aircraft);
//! An airspace snapshot was handled
void airspaceSnapshotHandled();
public slots:
//! Return list of available simulator plugins
@@ -153,9 +159,12 @@ namespace BlackCore
//! Delete all restrictions (if any) -> unlimited number of aircraft
virtual void deleteAllRenderingRestrictions() = 0;
//! Is number of aircraft restricted
//! Is number of aircraft restricted ormax distance set?
virtual bool isRenderingRestricted() const = 0;
//! Rendering enabled at all
virtual bool isRenderingEnabled() const = 0;
//! Time synchronization offset
virtual BlackMisc::PhysicalQuantities::CTime getTimeSynchronizationOffset() const = 0;
@@ -164,13 +173,13 @@ namespace BlackCore
//! Load specific simulator plugin as set in settings
virtual bool loadSimulatorPluginFromSettings() = 0;
//! Listen for the specific simulator to start, load plugin automatically
virtual void listenForSimulator(const BlackMisc::Simulation::CSimulatorPluginInfo &simulatorInfo) = 0;
//! Listen for all available simulators
virtual void listenForAllSimulators() = 0;
//! Listen for simulator as set in settings
virtual void listenForSimulatorFromSettings() = 0;

View File

@@ -126,10 +126,7 @@ namespace BlackCore
BlackMisc::Simulation::CSimulatorPluginInfo CContextSimulator::getSimulatorPluginInfo() const
{
if (m_debugEnabled) { CLogMessage(this, CLogCategory::contextSlot()).debug() << Q_FUNC_INFO; }
if (!m_simulatorPlugin)
{
return BlackMisc::Simulation::CSimulatorPluginInfo();
}
if (!m_simulatorPlugin) { return BlackMisc::Simulation::CSimulatorPluginInfo(); }
Q_ASSERT(m_simulatorPlugin->simulator);
return m_simulatorPlugin->info;
@@ -208,10 +205,7 @@ namespace BlackCore
CAircraftIcao CContextSimulator::getIcaoForModelString(const QString &modelString) const
{
if (m_debugEnabled) { CLogMessage(this, CLogCategory::contextSlot()).debug() << Q_FUNC_INFO << modelString; }
if (!m_simulatorPlugin)
{
return CAircraftIcao();
}
if (!m_simulatorPlugin) { return CAircraftIcao(); }
Q_ASSERT(m_simulatorPlugin->simulator);
return m_simulatorPlugin->simulator->getIcaoForModelString(modelString);
@@ -220,17 +214,11 @@ namespace BlackCore
bool CContextSimulator::setTimeSynchronization(bool enable, CTime offset)
{
if (m_debugEnabled) { CLogMessage(this, CLogCategory::contextSlot()).debug() << Q_FUNC_INFO; }
if (!m_simulatorPlugin)
{
return false;
}
if (!m_simulatorPlugin) { return false; }
Q_ASSERT(m_simulatorPlugin->simulator);
bool c = m_simulatorPlugin->simulator->setTimeSynchronization(enable, offset);
if (!c)
{
return false;
}
if (!c) { return false; }
CLogMessage(this).info(enable ? QStringLiteral("Set time syncronization to %1").arg(offset.toQString()) : QStringLiteral("Disabled time syncrhonization"));
return true;
@@ -239,10 +227,7 @@ namespace BlackCore
bool CContextSimulator::isTimeSynchronized() const
{
if (m_debugEnabled) { CLogMessage(this, CLogCategory::contextSlot()).debug() << Q_FUNC_INFO; }
if (!m_simulatorPlugin)
{
return false;
}
if (!m_simulatorPlugin) { return false; }
Q_ASSERT(m_simulatorPlugin->simulator);
return m_simulatorPlugin->simulator->isTimeSynchronized();
@@ -336,21 +321,23 @@ namespace BlackCore
bool CContextSimulator::isRenderingRestricted() const
{
if (m_debugEnabled) { CLogMessage(this, CLogCategory::contextSlot()).debug() << Q_FUNC_INFO; }
if (!m_simulatorPlugin)
{
return false;
}
if (!m_simulatorPlugin) { return false; }
Q_ASSERT(m_simulatorPlugin->simulator);
return this->m_simulatorPlugin->simulator->isRenderingRestricted();
}
bool CContextSimulator::isRenderingEnabled() const
{
if (m_debugEnabled) { CLogMessage(this, CLogCategory::contextSlot()).debug() << Q_FUNC_INFO; }
if (!m_simulatorPlugin) { return false; }
Q_ASSERT(m_simulatorPlugin->simulator);
return this->m_simulatorPlugin->simulator->isRenderingEnabled();
}
CTime CContextSimulator::getTimeSynchronizationOffset() const
{
if (m_debugEnabled) { CLogMessage(this, CLogCategory::contextSlot()).debug() << Q_FUNC_INFO; }
if (!m_simulatorPlugin)
{
return CTime(0, CTimeUnit::hrmin());
}
if (!m_simulatorPlugin) { return CTime(0, CTimeUnit::hrmin()); }
Q_ASSERT(m_simulatorPlugin->simulator);
return this->m_simulatorPlugin->simulator->getTimeSynchronizationOffset();
}
@@ -386,15 +373,25 @@ namespace BlackCore
plugin->simulator = newSimulator;
m_simulatorPlugin = plugin;
connect(m_simulatorPlugin->simulator, &ISimulator::simulatorStatusChanged, this, &CContextSimulator::ps_onSimulatorStatusChanged);
connect(m_simulatorPlugin->simulator, &ISimulator::ownAircraftModelChanged, this, &IContextSimulator::ownAircraftModelChanged);
connect(m_simulatorPlugin->simulator, &ISimulator::modelMatchingCompleted, this, &IContextSimulator::modelMatchingCompleted);
connect(m_simulatorPlugin->simulator, &ISimulator::installedAircraftModelsChanged, this, &IContextSimulator::installedAircraftModelsChanged);
connect(m_simulatorPlugin->simulator, &ISimulator::restrictedRenderingChanged, this, &IContextSimulator::restrictedRenderingChanged);
bool c = connect(m_simulatorPlugin->simulator, &ISimulator::simulatorStatusChanged, this, &CContextSimulator::ps_onSimulatorStatusChanged);
Q_ASSERT(c);
c = connect(m_simulatorPlugin->simulator, &ISimulator::ownAircraftModelChanged, this, &IContextSimulator::ownAircraftModelChanged);
Q_ASSERT(c);
c = connect(m_simulatorPlugin->simulator, &ISimulator::modelMatchingCompleted, this, &IContextSimulator::modelMatchingCompleted);
Q_ASSERT(c);
c = connect(m_simulatorPlugin->simulator, &ISimulator::installedAircraftModelsChanged, this, &IContextSimulator::installedAircraftModelsChanged);
Q_ASSERT(c);
c = connect(m_simulatorPlugin->simulator, &ISimulator::renderRestrictionsChanged, this, &IContextSimulator::renderRestrictionsChanged);
Q_ASSERT(c);
c = connect(m_simulatorPlugin->simulator, &ISimulator::airspaceSnapshotHandled, this, &IContextSimulator::airspaceSnapshotHandled);
Q_ASSERT(c);
// log from context to simulator
connect(CLogHandler::instance(), &CLogHandler::localMessageLogged, m_simulatorPlugin->simulator, &ISimulator::displayStatusMessage);
connect(CLogHandler::instance(), &CLogHandler::remoteMessageLogged, m_simulatorPlugin->simulator, &ISimulator::displayStatusMessage);
c = connect(CLogHandler::instance(), &CLogHandler::localMessageLogged, m_simulatorPlugin->simulator, &ISimulator::displayStatusMessage);
Q_ASSERT(c);
c = connect(CLogHandler::instance(), &CLogHandler::remoteMessageLogged, m_simulatorPlugin->simulator, &ISimulator::displayStatusMessage);
Q_ASSERT(c);
Q_UNUSED(c);
// connect with network
IContextNetwork *networkContext = this->getIContextNetwork();
@@ -414,6 +411,7 @@ namespace BlackCore
m_simulatorPlugin->simulator->asyncConnectTo();
// info about what is going on
emit simulatorPluginChanged(this->m_simulatorPlugin->info);
CLogMessage(this).info("Simulator plugin loaded: %1") << this->m_simulatorPlugin->info.toQString(true);
return true;
}
@@ -532,6 +530,8 @@ namespace BlackCore
if (m_simulatorPlugin)
{
// depending on shutdown order, network might already have been deleted
emit simulatorPluginChanged(CSimulatorPluginInfo());
IContextNetwork *networkContext = this->getIContextNetwork();
Q_ASSERT(networkContext);
Q_ASSERT(networkContext->isLocalObject());
@@ -543,7 +543,9 @@ namespace BlackCore
this->disconnect(m_simulatorPlugin->simulator);
if (m_simulatorPlugin->simulator->isConnected())
{
m_simulatorPlugin->simulator->disconnectFrom(); // disconnect from simulator
}
m_simulatorPlugin->simulator->deleteLater();
m_simulatorPlugin->simulator = nullptr;

View File

@@ -118,6 +118,9 @@ namespace BlackCore
//! \copydoc IContextSimulator::isRenderingRestricted
virtual bool isRenderingRestricted() const override;
//! \copydoc IContextSimulator::isRenderingEnabled
virtual bool isRenderingEnabled() const override;
//! \copydoc IContextSimulator::getTimeSynchronizationOffset
virtual BlackMisc::PhysicalQuantities::CTime getTimeSynchronizationOffset() const override;

View File

@@ -49,7 +49,13 @@ namespace BlackCore
"modelMatchingCompleted", this, SIGNAL(modelMatchingCompleted(BlackMisc::Simulation::CSimulatedAircraft)));
Q_ASSERT(s);
s = connection.connect(serviceName, IContextSimulator::ObjectPath(), IContextSimulator::InterfaceName(),
"restrictedRenderingChanged", this, SIGNAL(restrictedRenderingChanged(bool)));
"renderRestrictionsChanged", this, SIGNAL(renderRestrictionsChanged(bool, int, BlackMisc::PhysicalQuantities::CLength, BlackMisc::PhysicalQuantities::CLength)));
Q_ASSERT(s);
s = connection.connect(serviceName, IContextSimulator::ObjectPath(), IContextSimulator::InterfaceName(),
"simulatorPluginChanged", this, SIGNAL(simulatorPluginChanged(BlackMisc::Simulation::CSimulatorPluginInfo &)));
Q_ASSERT(s);
s = connection.connect(serviceName, IContextSimulator::ObjectPath(), IContextSimulator::InterfaceName(),
"airspaceSnapshotHandled", this, SIGNAL(airspaceSnapshotHandled()));
Q_ASSERT(s);
Q_UNUSED(s);
}
@@ -144,6 +150,11 @@ namespace BlackCore
return m_dBusInterface->callDBusRet<bool>(QLatin1Literal("isRenderingRestricted"));
}
bool CContextSimulatorProxy::isRenderingEnabled() const
{
return m_dBusInterface->callDBusRet<bool>(QLatin1Literal("isRenderingEnabled"));
}
CLength CContextSimulatorProxy::getMaxRenderedDistance() const
{
return m_dBusInterface->callDBusRet<CLength>(QLatin1Literal("getMaxRenderedDistance"));

View File

@@ -108,6 +108,9 @@ namespace BlackCore
//! \copydoc IContextSimulator::isRenderingRestricted
virtual bool isRenderingRestricted() const override;
//! \copydoc IContextSimulator::isRenderingEnabled
virtual bool isRenderingEnabled() const override;
//! \copydoc IContextSimulator::getMaxRenderedDistance
virtual BlackMisc::PhysicalQuantities::CLength getMaxRenderedDistance() const override;

View File

@@ -154,6 +154,9 @@ namespace BlackCore
//! Is there a restriction? No rendering -> limited number of aircraft -> unlimited number of aircraft
virtual bool isRenderingRestricted() const = 0;
//! Is rendering enabled?
virtual bool isRenderingEnabled() const = 0;
//! Delete all restrictions (if any) -> unlimited number of aircraft
virtual void deleteAllRenderingRestrictions() = 0;
@@ -171,9 +174,6 @@ namespace BlackCore
//! Highlight the aircraft for given time (or disable highlight)
virtual void highlightAircraft(const BlackMisc::Simulation::CSimulatedAircraft &aircraftToHighlight, bool enableHighlight, const BlackMisc::PhysicalQuantities::CTime &displayTime) = 0;
//! Is rendering enabled
virtual bool isRenderingEnabled() const = 0;
//! Originator
const QString &simulatorOriginator();
@@ -184,8 +184,8 @@ namespace BlackCore
//! Emitted when own aircraft model has changed
void ownAircraftModelChanged(BlackMisc::Simulation::CSimulatedAircraft aircraft);
//! Only a limited number of aircraft displayed
void restrictedRenderingChanged(bool restricted);
//! Render restrictions have been changed
void renderRestrictionsChanged(bool restricted, int maxAircraft, const BlackMisc::PhysicalQuantities::CLength &maxRenderedDistance, const BlackMisc::PhysicalQuantities::CLength &maxRenderedBoundary);
//! A single model has been matched
void modelMatchingCompleted(BlackMisc::Simulation::CSimulatedAircraft aircraft);
@@ -193,6 +193,9 @@ namespace BlackCore
//! Installed aircraft models ready or changed
void installedAircraftModelsChanged();
//! An airspace snapshot was handled
void airspaceSnapshotHandled();
protected:
//! Default constructor
ISimulator(QObject *parent = nullptr) : QObject(parent) {}
@@ -204,6 +207,9 @@ namespace BlackCore
//! Remove remote aircraft from simulator
virtual bool physicallyRemoveRemoteAircraft(const BlackMisc::Aviation::CCallsign &callsign) = 0;
//! Remove remote aircraft from simulator
virtual bool physicallyRemoveMultipleRemoteAircraft(const BlackMisc::Aviation::CCallsignSet &callsigns) = 0;
//! Remove all remote aircraft
virtual void physicallyRemoveAllRemoteAircraft() = 0;

View File

@@ -8,7 +8,8 @@
*/
#include "simulator_common.h"
#include "interpolator.h"
#include "blackcore/interpolator.h"
#include "blackcore/blackcorefreefunctions.h"
#include "blackmisc/logmessage.h"
#include "blackmisc/collection.h"
@@ -40,7 +41,7 @@ namespace BlackCore
std::bind(&CSimulatorCommon::ps_remoteProviderAddAircraftSituation, this, std::placeholders::_1),
std::bind(&CSimulatorCommon::ps_remoteProviderAddAircraftParts, this, std::placeholders::_1),
std::bind(&CSimulatorCommon::ps_remoteProviderRemovedAircraft, this, std::placeholders::_1),
std::bind(&CSimulatorCommon::ps_remoteProviderAircraftSnapshot, this, std::placeholders::_1)
std::bind(static_cast<void(CSimulatorCommon::*)(const CAirspaceAircraftSnapshot &)>(&CSimulatorCommon::ps_recalculateRenderedAircraft), this, std::placeholders::_1)
);
Q_ASSERT(c);
Q_UNUSED(c);
@@ -56,8 +57,8 @@ namespace BlackCore
// if not restriced, directly change
if (!isRenderingRestricted()) { return this->physicallyAddRemoteAircraft(remoteAircraft); }
//! \todo Go thru logic
return this->physicallyAddRemoteAircraft(remoteAircraft);
// will be added with next snapshot
return false;
}
bool CSimulatorCommon::logicallyRemoveRemoteAircraft(const CCallsign &callsign)
@@ -65,8 +66,8 @@ namespace BlackCore
// if not restriced, directly change
if (!isRenderingRestricted()) { return this->physicallyRemoveRemoteAircraft(callsign); }
//! \todo Go thru logic
return this->physicallyRemoveRemoteAircraft(callsign);
// will be added with next snapshot
return false;
}
void CSimulatorCommon::blinkHighlightedAircraft()
@@ -104,26 +105,6 @@ namespace BlackCore
}
}
void CSimulatorCommon::recalculateRestrictedAircraft()
{
if (!isMaxAircraftRestricted()) { return; }
if (!isRenderingEnabled()) { return; }
CSimulatedAircraftList newAircraftInRange(getAircraftInRange().getClosestObjects(getMaxRenderedAircraft()));
CCallsignSet newAircraftCallsigns(newAircraftInRange.getCallsigns());
CCallsignSet toBeRemovedCallsigns(m_callsignsToBeRendered.difference(newAircraftCallsigns));
CCallsignSet toBeAddedCallsigns(newAircraftCallsigns.difference(m_callsignsToBeRendered));
for (const CCallsign &cs : toBeRemovedCallsigns)
{
physicallyRemoveRemoteAircraft(cs);
}
for (const CCallsign &cs : toBeAddedCallsigns)
{
physicallyAddRemoteAircraft(newAircraftInRange.findFirstByCallsign(cs));
}
this->m_callsignsToBeRendered = newAircraftCallsigns;
}
void CSimulatorCommon::resetAircraftFromBacked(const CCallsign &callsign)
{
CSimulatedAircraft aircraft(this->getAircraftInRangeForCallsign(callsign));
@@ -138,7 +119,7 @@ namespace BlackCore
}
else
{
physicallyRemoveRemoteAircraft(callsign);
this->physicallyRemoveRemoteAircraft(callsign);
}
}
@@ -147,15 +128,14 @@ namespace BlackCore
if (!this->m_interpolator) { return; }
const CCallsign callsign(aircraft.getCallsign());
if (!(this->remoteAircraftSituationsCount(callsign) < 1)) { return; }
if (this->remoteAircraftSituationsCount(callsign) < 1) { return; }
// with an interpolator the interpolated situation is used
// to avoid position jittering
qint64 time = QDateTime::currentMSecsSinceEpoch();
IInterpolator::InterpolationStatus is;
CAircraftSituation as(m_interpolator->getInterpolatedSituation(callsign, time, aircraft.isVtol(), is));
if (is.interpolationSucceeded) { aircraft.setSituation(as); }
IInterpolator::InterpolationStatus interpolationStatus;
CAircraftSituation as(m_interpolator->getInterpolatedSituation(callsign, time, aircraft.isVtol(), interpolationStatus));
if (interpolationStatus.interpolationSucceeded) { aircraft.setSituation(as); }
}
int CSimulatorCommon::getMaxRenderedAircraft() const
@@ -180,24 +160,24 @@ namespace BlackCore
}
bool r = isRenderingRestricted();
emit restrictedRenderingChanged(r);
emit renderRestrictionsChanged(r, getMaxRenderedAircraft(), getMaxRenderedDistance(), getRenderedDistanceBoundary());
}
void CSimulatorCommon::setMaxRenderedDistance(CLength &distance)
{
if (distance == m_maxRenderedDistance) { return; }
if (distance.isNull() || distance >= getRenderedDistanceBoundary())
if (distance.isNull() || distance > getRenderedDistanceBoundary() || distance.isNegativeWithEpsilonConsidered())
{
m_maxRenderedDistance = CLength(0.0, CLengthUnit::nullUnit());
}
else
{
Q_ASSERT(distance.isPositiveWithEpsilonConsidered());
Q_ASSERT(!distance.isNegativeWithEpsilonConsidered());
m_maxRenderedDistance = distance;
}
bool r = isRenderingRestricted();
emit restrictedRenderingChanged(r);
emit renderRestrictionsChanged(r, getMaxRenderedAircraft(), getMaxRenderedDistance(), getRenderedDistanceBoundary());
}
CLength CSimulatorCommon::getMaxRenderedDistance() const
@@ -223,7 +203,7 @@ namespace BlackCore
bool CSimulatorCommon::isMaxAircraftRestricted() const
{
return m_maxRenderedAircraft < MaxAircraftInfinite && isRenderingEnabled();
return m_maxRenderedAircraft < MaxAircraftInfinite;
}
bool CSimulatorCommon::isMaxDistanceRestricted() const
@@ -258,8 +238,7 @@ namespace BlackCore
{
if (m_maxRenderedAircraft < 1) { return false; }
if (!isMaxDistanceRestricted()) { return true; }
return m_maxRenderedDistance.valueRounded(CLengthUnit::NM(), 2) > 0.1;
return m_maxRenderedDistance.isPositiveWithEpsilonConsidered();
}
bool CSimulatorCommon::isRenderingRestricted() const
@@ -269,22 +248,24 @@ namespace BlackCore
void CSimulatorCommon::deleteAllRenderingRestrictions()
{
if (!isRenderingEnabled()) { return; }
this->m_maxRenderedDistance = CLength(0, CLengthUnit::nullUnit());
this->m_maxRenderedAircraft = MaxAircraftInfinite;
emit restrictedRenderingChanged(false);
emit renderRestrictionsChanged(false, getMaxRenderedAircraft(), getMaxRenderedDistance(), getRenderedDistanceBoundary());
}
bool CSimulatorCommon::physicallyRemoveMultipleRemoteAircraft(const CCallsignSet &callsigns)
{
int removed = 0;
for (const CCallsign &callsign : callsigns)
{
if (physicallyRemoveRemoteAircraft(callsign)) { removed++; }
}
return removed > 0;
}
void CSimulatorCommon::ps_oneSecondTimer()
{
m_timerCounter++;
blinkHighlightedAircraft();
// any <n> seconds
if (m_timerCounter % 10 == 0)
{
recalculateRestrictedAircraft();
}
}
void CSimulatorCommon::ps_recalculateRenderedAircraft()
@@ -294,9 +275,39 @@ namespace BlackCore
void CSimulatorCommon::ps_recalculateRenderedAircraft(const CAirspaceAircraftSnapshot &snapshot)
{
if (!snapshot.isValidSnapshot()) { return;}
CCallsignSet callsignsInSimuator(physicallyRenderedAircraft());
Q_ASSERT(BlackCore::isCurrentThreadCreatingThread(this));
if (!snapshot.isValidSnapshot()) { return;}
// for unrestricted values all add/remove actions are directly linked
// when changing back from restricted->unrestricted an one time update is required
if (!snapshot.isRestricted() && !snapshot.isRestrictionChanged()) { return; }
// we will handle snapshot
emit airspaceSnapshotHandled();
// restricted snapshot values
if (!snapshot.isRenderingEnabled())
{
this->physicallyRemoveAllRemoteAircraft();
return;
}
CCallsignSet callsignsInSimulator(physicallyRenderedAircraft());
CCallsignSet callsignsToBeRemoved(callsignsInSimulator.difference(snapshot.getEnabledAircraftCallsignsByDistance()));
CCallsignSet callsignsToBeAdded(snapshot.getEnabledAircraftCallsignsByDistance().difference(callsignsInSimulator));
this->physicallyRemoveMultipleRemoteAircraft(callsignsToBeRemoved);
if (!callsignsToBeAdded.isEmpty())
{
CSimulatedAircraftList aircraftToBeAdded(getAircraftInRange().findByCallsigns(callsignsToBeAdded)); // thread safe copy
for (const CSimulatedAircraft &aircraft : aircraftToBeAdded)
{
Q_ASSERT_X(aircraft.isEnabled(), Q_FUNC_INFO, "Disabled aircraft detected as to be added");
this->physicallyAddRemoteAircraft(aircraft);
}
}
}
void CSimulatorCommon::ps_remoteProviderAddAircraftSituation(const CAircraftSituation &situation)
@@ -314,9 +325,4 @@ namespace BlackCore
Q_UNUSED(callsign);
}
void CSimulatorCommon::ps_remoteProviderAircraftSnapshot(const CAirspaceAircraftSnapshot &aircraftSnapshot)
{
ps_recalculateRenderedAircraft(aircraftSnapshot);
}
} // namespace

View File

@@ -83,7 +83,10 @@ namespace BlackCore
virtual const BlackMisc::Simulation::CSimulatorSetup &getSimulatorSetup() const override;
//! \copydoc IContextSimulator::deleteAllRenderingRestrictions
virtual void deleteAllRenderingRestrictions();
virtual void deleteAllRenderingRestrictions() override;
//! \copydoc IContextSimulator::physicallyRemoveRemoteAircraft
virtual bool physicallyRemoveMultipleRemoteAircraft(const BlackMisc::Aviation::CCallsignSet &callsigns) override;
protected slots:
//! Slow timer used to highlight aircraft, can be used for other things too
@@ -104,9 +107,6 @@ namespace BlackCore
//! Provider removed aircraft
virtual void ps_remoteProviderRemovedAircraft(const BlackMisc::Aviation::CCallsign &callsign);
//! Provider aircraft snapshot
virtual void ps_remoteProviderAircraftSnapshot(const BlackMisc::Simulation::CAirspaceAircraftSnapshot &aircraftSnapshot);
protected:
//! Constructor
CSimulatorCommon(const BlackMisc::Simulation::CSimulatorPluginInfo &info,
@@ -123,9 +123,6 @@ namespace BlackCore
//! Blink the highlighted aircraft
void blinkHighlightedAircraft();
//! Recalculate the restricted aircraft
void recalculateRestrictedAircraft();
//! Restore aircraft from backedn data
void resetAircraftFromBacked(const BlackMisc::Aviation::CCallsign &callsign);

View File

@@ -10,6 +10,7 @@
#include "airspaceaircraftsnapshot.h"
using namespace BlackMisc::Aviation;
using namespace BlackMisc::PhysicalQuantities;
namespace BlackMisc
{
@@ -18,20 +19,66 @@ namespace BlackMisc
CAirspaceAircraftSnapshot::CAirspaceAircraftSnapshot()
{ }
CAirspaceAircraftSnapshot::CAirspaceAircraftSnapshot(const CSimulatedAircraftList &allAircraft) :
m_timestampMsSinceEpoch(QDateTime::currentMSecsSinceEpoch())
CAirspaceAircraftSnapshot::CAirspaceAircraftSnapshot(
const CSimulatedAircraftList &allAircraft,
bool restricted, int maxAircraft, const CLength &maxRenderedDistance, const CLength &maxRenderedBoundary) :
m_timestampMsSinceEpoch(QDateTime::currentMSecsSinceEpoch()),
m_restricted(restricted)
{
if (!allAircraft.isEmpty())
m_renderingEnabled = !restricted || (
maxAircraft > 0 &&
(maxRenderedBoundary.isNull() || maxRenderedBoundary.isPositiveWithEpsilonConsidered()) &&
(maxRenderedDistance.isNull() || maxRenderedDistance.isPositiveWithEpsilonConsidered())
);
if (allAircraft.isEmpty()) { return; }
CSimulatedAircraftList aircraft(allAircraft);
aircraft.sortByDistanceToOwnAircraft();
CSimulatedAircraftList vtolAircraft(aircraft.findByVtol(true));
m_aircraftCallsignsByDistance = aircraft.getCallsigns();
m_vtolAircraftCallsignsByDistance = vtolAircraft.getCallsigns();
if (!restricted)
{
CSimulatedAircraftList aircraft(allAircraft);
aircraft.sortByDistanceToOwnAircraft();
CSimulatedAircraftList vtolAircraft(aircraft.findByVtol(true));
m_aircraftCallsignsByDistance = aircraft.getCallsigns();
m_enabledAircraftCallsignsByDistance = aircraft.findByEnabled(true).getCallsigns();
m_disabledAircraftCallsignsByDistance = aircraft.findByEnabled(false).getCallsigns();
m_vtolAircraftCallsignsByDistance = vtolAircraft.getCallsigns();
m_enabledVtolAircraftCallsignsByDistance = vtolAircraft.findByEnabled(true).getCallsigns();
}
else
{
// if no rendering all aircraft are disabled
if (!m_renderingEnabled)
{
m_disabledAircraftCallsignsByDistance = aircraft.getCallsigns();
return;
}
int count = 0;
for (const CSimulatedAircraft &currentAircraft : aircraft)
{
CCallsign cs(currentAircraft.getCallsign());
if (currentAircraft.isEnabled())
{
CLength distance(currentAircraft.getDistanceToOwnAircraft());
if (count >= maxAircraft ||
(!maxRenderedDistance.isNull() && distance >= maxRenderedBoundary) ||
(!maxRenderedBoundary.isNull() && distance >= maxRenderedBoundary))
{
m_disabledAircraftCallsignsByDistance.push_back(cs);
}
else
{
count++;
m_enabledAircraftCallsignsByDistance.push_back(cs);
if (currentAircraft.isVtol()) { m_enabledVtolAircraftCallsignsByDistance.push_back(cs); }
}
}
else
{
m_disabledAircraftCallsignsByDistance.push_back(cs);
}
}
}
}
bool CAirspaceAircraftSnapshot::isValidSnapshot() const
@@ -39,6 +86,18 @@ namespace BlackMisc
return m_timestampMsSinceEpoch > 0;
}
void CAirspaceAircraftSnapshot::setRestrictionChanged(const CAirspaceAircraftSnapshot &snapshot)
{
if (this->isValidSnapshot() == snapshot.isValidSnapshot())
{
this->m_restrictionChanged = (snapshot.m_restricted != this->m_restricted);
}
else
{
this->m_restrictionChanged = true;
}
}
CVariant CAirspaceAircraftSnapshot::propertyByIndex(const CPropertyIndex &index) const
{
if (index.isMyself()) { return this->toCVariant(); }

View File

@@ -29,7 +29,13 @@ namespace BlackMisc
CAirspaceAircraftSnapshot();
//! Constructor
CAirspaceAircraftSnapshot(const BlackMisc::Simulation::CSimulatedAircraftList &allAircraft);
CAirspaceAircraftSnapshot(
const BlackMisc::Simulation::CSimulatedAircraftList &allAircraft,
bool restricted = false,
int maxAircraft = 100,
const BlackMisc::PhysicalQuantities::CLength &maxRenderedDistance = BlackMisc::PhysicalQuantities::CLength(0, BlackMisc::PhysicalQuantities::CLengthUnit::nullUnit()),
const BlackMisc::PhysicalQuantities::CLength &maxRenderedBoundary = BlackMisc::PhysicalQuantities::CLength(0, BlackMisc::PhysicalQuantities::CLengthUnit::nullUnit())
);
//! Time when snapshot was taken
const QDateTime getTimestamp() const { return QDateTime::fromMSecsSinceEpoch(m_timestampMsSinceEpoch); }
@@ -52,6 +58,21 @@ namespace BlackMisc
//! Valid snapshot?
bool isValidSnapshot() const;
//! Restricted snapshot?
bool isValidRestricted() const { return m_restricted; }
//! Did restriction change compared to last snapshot
void setRestrictionChanged(const CAirspaceAircraftSnapshot &snapshot);
//! Did the restriction flag change?
bool isRestrictionChanged() const { return m_restrictionChanged; }
//! Restricted values?
bool isRestricted() const { return m_restricted; }
//! Rendering enabled or all aircraft disabled?
bool isRenderingEnabled() const { return m_renderingEnabled; }
//! \copydoc CValueObject::propertyByIndex
virtual CVariant propertyByIndex(const BlackMisc::CPropertyIndex &index) const override;
@@ -65,6 +86,9 @@ namespace BlackMisc
private:
BLACK_ENABLE_TUPLE_CONVERSION(CAirspaceAircraftSnapshot)
qint64 m_timestampMsSinceEpoch = -1;
bool m_restricted = false;
bool m_restrictionChanged = false;
bool m_renderingEnabled = true;
// remark closest aircraft always first
BlackMisc::Aviation::CCallsignSet m_aircraftCallsignsByDistance;

View File

@@ -57,7 +57,6 @@ namespace BlackSimPlugin
connect(fs9Host.data(), &CFs9Host::customPacketReceived, this, &CSimulatorFs9::ps_processFs9Message);
this->m_interpolator = new BlackCore::CInterpolatorLinear(remoteAircraftProvider, this);
this->m_interpolator->start();
}
bool CSimulatorFs9::isConnected() const

View File

@@ -17,5 +17,10 @@ namespace BlackSimPlugin
namespace Fsx
{
CSimConnectObject::CSimConnectObject() { }
CSimConnectObject::CSimConnectObject(const BlackMisc::Aviation::CCallsign &callsign, int requestId, int objectId, bool vtol) :
m_callsign(callsign), m_requestId(requestId), m_objectId(objectId), m_vtol(vtol)
{ }
} // namespace
} // namespace

View File

@@ -28,6 +28,9 @@ namespace BlackSimPlugin
//! Constructor
CSimConnectObject();
//! Constructor
CSimConnectObject(const BlackMisc::Aviation::CCallsign &callsign, int requestId, int objectId, bool vtol);
//! Destructor
~CSimConnectObject() {}
@@ -49,11 +52,17 @@ namespace BlackSimPlugin
//! Set Simconnect object id
int getObjectId() const { return m_objectId; }
private:
//! VTOL?
bool isVtol() const { return m_vtol; }
//! VTOL?
void setVtol(bool vtol) { m_vtol = vtol; }
private:
BlackMisc::Aviation::CCallsign m_callsign;
int m_requestId = -1;
int m_objectId = -1;
bool m_vtol = false;
};
} // namespace
} // namespace

View File

@@ -8,7 +8,8 @@
*/
#include "simulator_fsx.h"
#include "simconnect_datadefinition.h"
#include "blackcore/interpolator_linear.h"
#include "blackcore/blackcorefreefunctions.h"
#include "blackmisc/simulation/fscommon/bcdconversions.h"
#include "blackmisc/simulation/fsx/simconnectutilities.h"
#include "blackmisc/simulation/fsx/fsxsimulatorsetup.h"
@@ -18,7 +19,6 @@
#include "blackmisc/aviation/airportlist.h"
#include "blackmisc/logmessage.h"
#include "blackmisc/network/aircraftmappinglist.h"
#include "blackcore/interpolator_linear.h"
#include <QTimer>
#include <type_traits>
@@ -51,7 +51,6 @@ namespace BlackSimPlugin
m_useFsuipc = false; // do not use FSUIPC at the moment with FSX
this->m_interpolator = new CInterpolatorLinear(remoteAircraftProvider, this);
this->m_interpolator->start();
}
CSimulatorFsx::~CSimulatorFsx()
@@ -139,8 +138,9 @@ namespace BlackSimPlugin
bool CSimulatorFsx::physicallyAddRemoteAircraft(const Simulation::CSimulatedAircraft &newRemoteAircraft)
{
CCallsign callsign = newRemoteAircraft.getCallsign();
Q_ASSERT(!callsign.isEmpty());
CCallsign callsign(newRemoteAircraft.getCallsign());
Q_ASSERT_X(BlackCore::isCurrentThreadCreatingThread(this), Q_FUNC_INFO, "thread");
Q_ASSERT_X(!callsign.isEmpty(), Q_FUNC_INFO, "empty callsign");
if (callsign.isEmpty()) { return false; }
bool aircraftAlreadyExistsInSim = this->m_simConnectObjects.contains(callsign);
@@ -155,10 +155,7 @@ namespace BlackSimPlugin
this->setInitialAircraftSituationAndParts(newRemoteAircraftCopy); // set interpolated data/parts if available
SIMCONNECT_DATA_INITPOSITION initialPosition = aircraftSituationToFsxInitPosition(newRemoteAircraftCopy.getSituation());
CSimConnectObject simObj;
simObj.setCallsign(callsign);
simObj.setRequestId(m_nextObjID);
simObj.setObjectId(0);
CSimConnectObject simObj(callsign, m_nextObjID, 0, newRemoteAircraft.isVtol());
++m_nextObjID;
// matched models
@@ -519,6 +516,7 @@ namespace BlackSimPlugin
bool CSimulatorFsx::physicallyRemoveRemoteAircraft(const CCallsign &callsign)
{
// only remove from sim
Q_ASSERT(BlackCore::isCurrentThreadCreatingThread(this));
if (!m_simConnectObjects.contains(callsign)) { return false; }
return physicallyRemoveRemoteAircraft(m_simConnectObjects.value(callsign));
}
@@ -622,8 +620,8 @@ namespace BlackSimPlugin
void CSimulatorFsx::updateRemoteAircraft()
{
static_assert(sizeof(DataDefinitionRemoteAircraftParts) == 120, "DataDefinitionRemoteAircraftParts has an incorrect size.");
Q_ASSERT(this->m_interpolator);
Q_ASSERT_X(this->m_interpolator->thread() != this->thread(), Q_FUNC_INFO, "interpolator should run in its own thread");
Q_ASSERT_X(this->m_interpolator, Q_FUNC_INFO, "missing interpolator");
Q_ASSERT_X(BlackCore::isCurrentThreadCreatingThread(this), Q_FUNC_INFO, "thread");
// nothing to do, reset request id and exit
if (this->isPaused()) { return; } // no interpolation while paused
@@ -635,19 +633,18 @@ namespace BlackSimPlugin
// values used for position and parts
bool isOnGround = false;
bool isVtolAircraft = false; //! \todo determine VTOL aircraft in interpolator
qint64 currentTimestamp = QDateTime::currentMSecsSinceEpoch();
CCallsignSet aircraftWithParts(this->remoteAircraftSupportingParts()); // optimization, fetch all parts supporting aircraft in one step (one lock)
for (const CSimConnectObject &simObj : m_simConnectObjects)
const QList<CSimConnectObject> simObjects(m_simConnectObjects.values());
for (const CSimConnectObject &simObj : simObjects)
{
if (simObj.getObjectId() < 1) { continue; }
const CCallsign callsign(simObj.getCallsign());
Q_ASSERT_X(!callsign.isEmpty(), Q_FUNC_INFO, "missing callsign");
IInterpolator::InterpolationStatus interpolatorStatus;
CAircraftSituation interpolatedSituation = this->m_interpolator->getInterpolatedSituation(callsign, currentTimestamp, isVtolAircraft, interpolatorStatus);
CAircraftSituation interpolatedSituation = this->m_interpolator->getInterpolatedSituation(callsign, currentTimestamp, simObj.isVtol(), interpolatorStatus);
// having the onGround flag in parts forces me to obtain parts here
// which is not the smartest thing regarding performance