refs #386, performance issues

* keep split per callsign map in IInterpolator (so it is available for all interpolators)
* Interpolator using CWorker, so it can run in background
* added signals to provider to add split situations / callsigns
* adjustments to airspace / context for those signals
* thread safe access to those from interpolator
* renamed from rendered to remote aircraft as discussed
* adjust samples
* removed no longer required functions in timestampobjectlist
* changed connectioStatusChanged from uint -> int
This commit is contained in:
Klaus Basan
2015-02-20 03:14:49 +01:00
parent 1ff0cfa618
commit f8bebf5ffa
37 changed files with 835 additions and 583 deletions

View File

@@ -27,7 +27,8 @@ namespace BlackCore
{
CAirspaceMonitor::CAirspaceMonitor(QObject *parent, const BlackMisc::Simulation::IOwnAircraftProviderReadOnly *ownAircraftProvider, INetwork *network, CVatsimBookingReader *bookings, CVatsimDataFileReader *dataFile)
: QObject(parent), COwnAircraftProviderSupportReadOnly(ownAircraftProvider),
: QObject(parent),
COwnAircraftProviderSupportReadOnly(ownAircraftProvider),
m_network(network), m_vatsimBookingReader(bookings), m_vatsimDataFileReader(dataFile),
m_atcWatchdog(this), m_aircraftWatchdog(this)
{
@@ -59,28 +60,28 @@ namespace BlackCore
this->connect(&this->m_atcWatchdog, &CAirspaceWatchdog::timeout, this, &CAirspaceMonitor::ps_atcControllerDisconnected);
}
const CSimulatedAircraftList &CAirspaceMonitor::renderedAircraft() const
const CSimulatedAircraftList &CAirspaceMonitor::remoteAircraft() const
{
// not thread safe, check
Q_ASSERT(this->thread() == QThread::currentThread());
return m_aircraftInRange;
}
CSimulatedAircraftList &CAirspaceMonitor::renderedAircraft()
CSimulatedAircraftList &CAirspaceMonitor::remoteAircraft()
{
// not thread safe, check
Q_ASSERT(this->thread() == QThread::currentThread());
return m_aircraftInRange;
}
const CAircraftSituationList &CAirspaceMonitor::renderedAircraftSituations() const
const CAircraftSituationList &CAirspaceMonitor::remoteAircraftSituations() const
{
// not thread safe, check
Q_ASSERT(this->thread() == QThread::currentThread());
return m_aircraftSituations;
}
CAircraftSituationList &CAirspaceMonitor::renderedAircraftSituations()
CAircraftSituationList &CAirspaceMonitor::remoteAircraftSituations()
{
// not thread safe, check
Q_ASSERT(this->thread() == QThread::currentThread());
@@ -89,26 +90,18 @@ namespace BlackCore
CAircraftSituationList CAirspaceMonitor::getRenderedAircraftSituations() const
{
if (this->thread() == QThread::currentThread()) { return this->m_aircraftSituations; }
CAircraftSituationList situations;
bool s = QMetaObject::invokeMethod(const_cast<CAirspaceMonitor *>(this), // strip away const, invoke will not change anything,
"getRenderedAircraftSituations",
Qt::BlockingQueuedConnection,
Q_RETURN_ARG(CAircraftSituationList, situations)
);
Q_ASSERT(s);
Q_UNUSED(s);
return situations;
Q_ASSERT(this->thread() == QThread::currentThread());
return this->m_aircraftSituations;
}
const CAircraftPartsList &CAirspaceMonitor::renderedAircraftParts() const
const CAircraftPartsList &CAirspaceMonitor::remoteAircraftParts() const
{
// not thread safe, check
Q_ASSERT(this->thread() == QThread::currentThread());
return m_aircraftParts;
}
CAircraftPartsList &CAirspaceMonitor::renderedAircraftParts()
CAircraftPartsList &CAirspaceMonitor::remoteAircraftParts()
{
// not thread safe, check
Q_ASSERT(this->thread() == QThread::currentThread());
@@ -117,16 +110,20 @@ namespace BlackCore
CAircraftPartsList CAirspaceMonitor::getRenderedAircraftParts() const
{
if (this->thread() == QThread::currentThread()) { return this->m_aircraftParts; }
CAircraftPartsList parts;
bool s = QMetaObject::invokeMethod(const_cast<CAirspaceMonitor *>(this), // strip away const, invoke will not change anything
"getRenderedAircraftParts",
Qt::BlockingQueuedConnection,
Q_RETURN_ARG(CAircraftPartsList, parts)
);
Q_ASSERT(s);
Q_UNUSED(s);
return parts;
Q_ASSERT(this->thread() == QThread::currentThread());
return this->m_aircraftParts;
}
bool CAirspaceMonitor::connectRemoteAircraftProviderSignals(
std::function<void(const CAircraftSituation &)> situationSlot,
std::function<void(const CAircraftParts &)> partsSlot,
std::function<void(const CCallsign &)> removedAircraftSlot
)
{
bool s1 = connect(this, &CAirspaceMonitor::addedRemoteAircraftSituation, situationSlot);
bool s2 = connect(this, &CAirspaceMonitor::addedRemoteAircraftParts, partsSlot);
bool s3 = connect(this, &CAirspaceMonitor::removedAircraft, removedAircraftSlot);
return s1 && s2 && s3;
}
bool CAirspaceMonitor::updateAircraftEnabled(const CCallsign &callsign, bool enabledForRedering, const QString &originator)
@@ -738,7 +735,7 @@ namespace BlackCore
CAircraftSituation situationWithCallsign(situation);
situationWithCallsign.setCallsign(callsign);
this->m_aircraftSituations.insert(situationWithCallsign);
this->m_aircraftSituations.removeOlderThanNowMinusOffset(30000);
this->m_aircraftSituations.removeOlderThanNowMinusOffset(AircraftSituationsRemovedOffsetMs);
bool exists = this->m_aircraftInRange.containsCallsign(callsign);
if (!exists)
@@ -811,6 +808,7 @@ namespace BlackCore
this->m_aircraftWatchdog.resetCallsign(callsign);
}
emit this->addedRemoteAircraftSituation(situationWithCallsign);
emit this->changedAircraftInRange();
}
@@ -852,13 +850,15 @@ namespace BlackCore
CAircraftParts parts = m_aircraftParts.findBackByCallsign(callsign);
parts.setCurrentUtcTime();
parts.setCallsign(callsign);
parts.setCallsign(callsign); // for default values
// update
QJsonObject config = applyIncrementalObject(parts.toJson(), incremental);
parts.convertFromJson(config);
// store part history
this->m_aircraftParts.insert(parts);
emit this->addedRemoteAircraftParts(parts);
CPropertyIndexVariantMap vm;
vm.addValue(CAircraft::IndexParts, parts);

View File

@@ -14,7 +14,7 @@
#include "blackmisc/simulation/simulatedaircraftlist.h"
#include "blackmisc/simulation/simdirectaccessownaircraft.h"
#include "blackmisc/simulation/simdirectaccessrenderedaircraft.h"
#include "blackmisc/simulation/simdirectaccessremoteaircraft.h"
#include "blackmisc/avatcstationlist.h"
#include "blackmisc/avaircraftsituationlist.h"
#include "blackmisc/nwclientlist.h"
@@ -34,37 +34,38 @@ namespace BlackCore
*/
class CAirspaceMonitor :
public QObject,
public BlackMisc::Simulation::COwnAircraftProviderSupportReadOnly,
public BlackMisc::Simulation::IRenderedAircraftProvider
public BlackMisc::Simulation::IRemoteAircraftProvider, // those data will be provided from the class CAirspaceMonitor
public BlackMisc::Simulation::COwnAircraftProviderSupportReadOnly // used to obtain in memory inofmration about own aircraft
{
Q_OBJECT
Q_INTERFACES(BlackMisc::Simulation::IRemoteAircraftProvider)
public:
//! Constructor
CAirspaceMonitor(QObject *parent, const BlackMisc::Simulation::IOwnAircraftProviderReadOnly *ownAircraft, INetwork *network, CVatsimBookingReader *bookings, CVatsimDataFileReader *dataFile);
//! \copydoc IRenderedAircraftProviderReadOnly::renderedAircraft
virtual const BlackMisc::Simulation::CSimulatedAircraftList &renderedAircraft() const override;
//! \copydoc IRemoteAircraftProviderReadOnly::renderedAircraft
virtual const BlackMisc::Simulation::CSimulatedAircraftList &remoteAircraft() const override;
//! \copydoc IRenderedAircraftProvider::renderedAircraft
virtual BlackMisc::Simulation::CSimulatedAircraftList &renderedAircraft() override;
//! \copydoc IRemoteAircraftProvider::renderedAircraft
virtual BlackMisc::Simulation::CSimulatedAircraftList &remoteAircraft() override;
//! \copydoc IRenderedAircraftProvider::renderedAircraftSituations
virtual const BlackMisc::Aviation::CAircraftSituationList &renderedAircraftSituations() const override;
//! \copydoc IRemoteAircraftProvider::remoteAircraftSituations
virtual const BlackMisc::Aviation::CAircraftSituationList &remoteAircraftSituations() const override;
//! \copydoc IRenderedAircraftProvider::renderedAircraftSituations
virtual BlackMisc::Aviation::CAircraftSituationList &renderedAircraftSituations() override;
//! \copydoc IRemoteAircraftProvider::remoteAircraftSituations
virtual BlackMisc::Aviation::CAircraftSituationList &remoteAircraftSituations() override;
//! \copydoc IRenderedAircraftProvider::renderedAircraftParts
virtual const BlackMisc::Aviation::CAircraftPartsList &renderedAircraftParts() const override;
//! \copydoc IRemoteAircraftProvider::remoteAircraftParts
virtual const BlackMisc::Aviation::CAircraftPartsList &remoteAircraftParts() const override;
//! \copydoc IRenderedAircraftProvider::renderedAircraftParts
virtual BlackMisc::Aviation::CAircraftPartsList &renderedAircraftParts() override;
//! \copydoc IRemoteAircraftProvider::remoteAircraftParts
virtual BlackMisc::Aviation::CAircraftPartsList &remoteAircraftParts() override;
//! \copydoc IRenderedAircraftProvider::renderedAircraftParts
//! \copydoc IRemoteAircraftProvider::remoteAircraftParts
virtual bool updateAircraftEnabled(const BlackMisc::Aviation::CCallsign &callsign, bool enabledForRedering, const QString &originator) override;
//! \copydoc IRenderedAircraftProvider::updateAircraftModel
//! \copydoc IRemoteAircraftProvider::updateAircraftModel
virtual bool updateAircraftModel(const BlackMisc::Aviation::CCallsign &callsign, const BlackMisc::Simulation::CAircraftModel &model, const QString &originator) override;
//! Returns the list of users we know about
@@ -107,14 +108,35 @@ namespace BlackCore
//! Create dummy entries for performance tests
void testCreateDummyOnlineAtcStations(int number);
public slots:
//! \copydoc IRenderedAircraftProviderReadOnly::getRenderedAircraftSituations
virtual BlackMisc::Aviation::CAircraftSituationList getRenderedAircraftSituations() const override;
//! Aircraft situations
virtual BlackMisc::Aviation::CAircraftSituationList getRenderedAircraftSituations() const;
//! \copydoc IRenderedAircraftProviderReadOnly::getRenderedAircraftParts
virtual BlackMisc::Aviation::CAircraftPartsList getRenderedAircraftParts() const override;
//! Aircraft parts
virtual BlackMisc::Aviation::CAircraftPartsList getRenderedAircraftParts() const;
//! \copydoc IRemoteAircraftProviderReadOnly::connectSignals
//! \copydoc IRemoteAircraftProviderReadOnly::connectSignals
virtual bool connectRemoteAircraftProviderSignals(
std::function<void(const BlackMisc::Aviation::CAircraftSituation &)> situationSlot,
std::function<void(const BlackMisc::Aviation::CAircraftParts &)> partsSlot,
std::function<void(const BlackMisc::Aviation::CCallsign &)> removedAircraftSlot
) override;
const qint64 AircraftSituationsRemovedOffsetMs = 30 * 1000; //!< situations will be removed if older than
signals:
//--- signals for the provider, work locally only (not in DBus
//! \copydoc IRemoteAircraftProviderReadOnly::addedRemoteAircraftSituation
void addedRemoteAircraftSituation(const BlackMisc::Aviation::CAircraftSituation &situation) override;
//! \copydoc IRemoteAircraftProviderReadOnly::addedRemoteAircraftPart
void addedRemoteAircraftParts(const BlackMisc::Aviation::CAircraftParts &parts) override;
//! \copydoc IRemoteAircraftProviderReadOnly::removedAircraft
void removedAircraft(const BlackMisc::Aviation::CCallsign &callsign) override;
//! Online ATC stations were changed
void changedAtcStationsOnline();
@@ -128,13 +150,10 @@ namespace BlackCore
void changedAircraftInRange();
//! A new aircraft appeared
void addedAircraft(const BlackMisc::Simulation::CSimulatedAircraft &renderedAircraft);
//! An aircraft disappeared
void removedAircraft(const BlackMisc::Aviation::CCallsign &callsign);
void addedAircraft(const BlackMisc::Simulation::CSimulatedAircraft &remoteAircraft);
//! Read for model matching
void readyForModelMatching(const BlackMisc::Simulation::CSimulatedAircraft &renderedAircraft);
void readyForModelMatching(const BlackMisc::Simulation::CSimulatedAircraft &remoteAircraft);
private:
BlackMisc::Aviation::CAtcStationList m_atcStationsOnline;

View File

@@ -117,7 +117,7 @@ namespace BlackCore
* \remarks If I use the enum, adaptor / interface are not created correctly
* \see INetwork::ConnectionStatus
*/
void connectionStatusChanged(uint from, uint to);
void connectionStatusChanged(int from, int to);
//! Text messages received (also private chat messages, rfaio channel messages)
void textMessagesReceived(const BlackMisc::Network::CTextMessageList &textMessages);

View File

@@ -78,6 +78,8 @@ namespace BlackCore
connect(this->m_airspace, &CAirspaceMonitor::changedAircraftInRange, this, &CContextNetwork::changedAircraftInRange);
connect(this->m_airspace, &CAirspaceMonitor::removedAircraft, this, &CContextNetwork::removedAircraft);
connect(this->m_airspace, &CAirspaceMonitor::readyForModelMatching, this, &CContextNetwork::readyForModelMatching);
connect(this->m_airspace, &CAirspaceMonitor::addedRemoteAircraftParts, this, &CContextNetwork::addedRemoteAircraftParts);
connect(this->m_airspace, &CAirspaceMonitor::addedRemoteAircraftSituation, this, &CContextNetwork::addedRemoteAircraftSituation);
}
CContextNetwork::~CContextNetwork()
@@ -85,52 +87,49 @@ namespace BlackCore
this->gracefulShutdown();
}
const CSimulatedAircraftList &CContextNetwork::renderedAircraft() const
const CSimulatedAircraftList &CContextNetwork::remoteAircraft() const
{
Q_ASSERT(this->m_airspace);
return m_airspace->renderedAircraft();
return m_airspace->remoteAircraft();
}
CSimulatedAircraftList &CContextNetwork::renderedAircraft()
CSimulatedAircraftList &CContextNetwork::remoteAircraft()
{
Q_ASSERT(this->m_airspace);
return m_airspace->renderedAircraft();
return m_airspace->remoteAircraft();
}
CAircraftSituationList &CContextNetwork::renderedAircraftSituations()
CAircraftSituationList &CContextNetwork::remoteAircraftSituations()
{
Q_ASSERT(this->m_airspace);
return m_airspace->renderedAircraftSituations();
return m_airspace->remoteAircraftSituations();
}
CAircraftSituationList CContextNetwork::getRenderedAircraftSituations() const
const CAircraftSituationList &CContextNetwork::remoteAircraftSituations() const
{
Q_ASSERT(this->m_airspace);
return m_airspace->getRenderedAircraftSituations();
return m_airspace->remoteAircraftSituations();
}
const CAircraftSituationList &CContextNetwork::renderedAircraftSituations() const
const CAircraftPartsList &CContextNetwork::remoteAircraftParts() const
{
Q_ASSERT(this->m_airspace);
return m_airspace->renderedAircraftSituations();
return m_airspace->remoteAircraftParts();
}
const CAircraftPartsList &CContextNetwork::renderedAircraftParts() const
CAircraftPartsList &CContextNetwork::remoteAircraftParts()
{
Q_ASSERT(this->m_airspace);
return m_airspace->renderedAircraftParts();
return m_airspace->remoteAircraftParts();
}
CAircraftPartsList &CContextNetwork::renderedAircraftParts()
bool CContextNetwork::connectRemoteAircraftProviderSignals(
std::function<void (const CAircraftSituation &)> situationSlot,
std::function<void (const CAircraftParts &)> partsSlot,
std::function<void (const CCallsign &)> removedAircraftSlot)
{
Q_ASSERT(this->m_airspace);
return m_airspace->renderedAircraftParts();
}
CAircraftPartsList CContextNetwork::getRenderedAircraftParts() const
{
Q_ASSERT(this->m_airspace);
return m_airspace->getRenderedAircraftParts();
return this->m_airspace->connectRemoteAircraftProviderSignals(situationSlot, partsSlot, removedAircraftSlot);
}
void CContextNetwork::gracefulShutdown()
@@ -359,13 +358,13 @@ namespace BlackCore
CSimulatedAircraftList CContextNetwork::getAircraftInRange() const
{
BlackMisc::CLogMessage(this, BlackMisc::CLogCategory::contextSlot()).debug() << Q_FUNC_INFO;
return this->m_airspace->renderedAircraft();
return this->m_airspace->remoteAircraft();
}
CSimulatedAircraft CContextNetwork::getAircraftForCallsign(const CCallsign &callsign) const
{
BlackMisc::CLogMessage(this, BlackMisc::CLogCategory::contextSlot()).debug() << Q_FUNC_INFO << callsign;
return this->m_airspace->renderedAircraft().findFirstByCallsign(callsign);
return this->m_airspace->remoteAircraft().findFirstByCallsign(callsign);
}
void CContextNetwork::ps_receivedBookings(const CAtcStationList &)
@@ -400,7 +399,7 @@ namespace BlackCore
bool c = this->m_airspace->updateAircraftEnabled(callsign, enabledForRedering, originator);
if (c)
{
emit this->changedAircraftEnabled(this->renderedAircraft().findFirstByCallsign(callsign), originator);
emit this->changedAircraftEnabled(this->remoteAircraft().findFirstByCallsign(callsign), originator);
}
return c;
}
@@ -411,7 +410,7 @@ namespace BlackCore
bool c = this->m_airspace->updateAircraftModel(callsign, model, originator);
if (c)
{
emit this->changedRenderedAircraftModel(this->renderedAircraft().findFirstByCallsign(callsign), originator);
emit this->changedRenderedAircraftModel(this->remoteAircraft().findFirstByCallsign(callsign), originator);
}
return c;
}

View File

@@ -15,7 +15,7 @@
#include "blackcore/context_network.h"
#include "blackcore/context_settings.h"
#include "blackcore/context_runtime.h"
#include "blackmisc/simulation/simdirectaccessrenderedaircraft.h"
#include "blackmisc/simulation/simdirectaccessremoteaircraft.h"
#include "blackcore/dbus_server.h"
#include "blackcore/network.h"
#include "blackcore/airspace_monitor.h"
@@ -37,10 +37,12 @@ namespace BlackCore
//! Network context implementation
class CContextNetwork :
public IContextNetwork,
public BlackMisc::Simulation::IRenderedAircraftProvider
public BlackMisc::Simulation::IRemoteAircraftProvider
{
Q_OBJECT
Q_INTERFACES(BlackMisc::Simulation::IRemoteAircraftProvider)
Q_CLASSINFO("D-Bus Interface", BLACKCORE_CONTEXTNETWORK_INTERFACENAME)
friend class IContextNetwork;
friend class CRuntime;
@@ -48,26 +50,45 @@ namespace BlackCore
//! Destructor
virtual ~CContextNetwork();
//! \copydoc IRenderedAircraftProviderReadOnly::renderedAircraft
virtual const BlackMisc::Simulation::CSimulatedAircraftList &renderedAircraft() const override;
//! \copydoc IRemoteAircraftProviderReadOnly::renderedAircraft
virtual const BlackMisc::Simulation::CSimulatedAircraftList &remoteAircraft() const override;
//! \copydoc IRenderedAircraftProvider::renderedAircraft
virtual BlackMisc::Simulation::CSimulatedAircraftList &renderedAircraft() override;
virtual BlackMisc::Simulation::CSimulatedAircraftList &remoteAircraft() override;
//! \copydoc IRenderedAircraftProviderReadOnly::renderedAircraftSituations
virtual const BlackMisc::Aviation::CAircraftSituationList &renderedAircraftSituations() const override;
//! \copydoc IRemoteAircraftProviderReadOnly::renderedAircraftSituations
virtual const BlackMisc::Aviation::CAircraftSituationList &remoteAircraftSituations() const override;
//! \copydoc IRenderedAircraftProviderReadOnly::renderedAircraftSituations
virtual BlackMisc::Aviation::CAircraftSituationList &renderedAircraftSituations() override;
//! \copydoc IRemoteAircraftProviderReadOnly::renderedAircraftSituations
virtual BlackMisc::Aviation::CAircraftSituationList &remoteAircraftSituations() override;
//! \copydoc IRenderedAircraftProviderReadOnly::renderedAircraftParts
virtual const BlackMisc::Aviation::CAircraftPartsList &renderedAircraftParts() const override;
//! \copydoc IRemoteAircraftProviderReadOnly::renderedAircraftParts
virtual const BlackMisc::Aviation::CAircraftPartsList &remoteAircraftParts() const override;
//! \copydoc IRenderedAircraftProvider::renderedAircraftParts
virtual BlackMisc::Aviation::CAircraftPartsList &renderedAircraftParts() override;
virtual BlackMisc::Aviation::CAircraftPartsList &remoteAircraftParts() override;
//! \copydoc IRemoteAircraftProviderReadOnly::connectSignals
virtual bool connectRemoteAircraftProviderSignals(
std::function<void(const BlackMisc::Aviation::CAircraftSituation &)> situationSlot,
std::function<void(const BlackMisc::Aviation::CAircraftParts &)> partsSlot,
std::function<void(const BlackMisc::Aviation::CCallsign &)> removedAircraftSlot
) override;
signals:
// IRemoteAircraftProviderReadOnly must be implemented by concrete class
// must not prefixed virtual (though they are) -> warning
//! \copydoc IRemoteAircraftProviderReadOnly::addedRemoteAircraftSituation
void addedRemoteAircraftSituation(const BlackMisc::Aviation::CAircraftSituation &situation) override;
//! \copydoc IRemoteAircraftProviderReadOnly::addedRemoteAircraftPart
void addedRemoteAircraftParts(const BlackMisc::Aviation::CAircraftParts &parts) override;
//! \copydoc IRemoteAircraftProviderReadOnly::removedAircraft
void removedAircraft(const BlackMisc::Aviation::CCallsign &callsign) override;
public slots:
//! \copydoc IContextNetwork::readAtcBookingsFromSource()
virtual void readAtcBookingsFromSource() const override;
@@ -83,12 +104,6 @@ namespace BlackCore
//! \copydoc IContextNetwork::getAircraftForCallsign
virtual BlackMisc::Simulation::CSimulatedAircraft getAircraftForCallsign(const BlackMisc::Aviation::CCallsign &callsign) const override;
//! \copydoc IRenderedAircraftProviderReadOnly::getRenderedAircraftSituations
virtual BlackMisc::Aviation::CAircraftSituationList getRenderedAircraftSituations() const override;
//! \copydoc IRenderedAircraftProviderReadOnly::getRenderedAircraftParts
virtual BlackMisc::Aviation::CAircraftPartsList getRenderedAircraftParts() const override;
//! \copydoc IContextNetwork::connectToNetwork()
virtual BlackMisc::CStatusMessage connectToNetwork(const BlackMisc::Network::CServer &server, uint mode) override;

View File

@@ -37,7 +37,7 @@ namespace BlackCore
void CContextNetworkProxy::relaySignals(const QString &serviceName, QDBusConnection &connection)
{
bool s = connection.connect(serviceName, IContextNetwork::ObjectPath(), IContextNetwork::InterfaceName(),
"connectionStatusChanged", this, SIGNAL(connectionStatusChanged(uint, uint)));
"connectionStatusChanged", this, SIGNAL(connectionStatusChanged(int, int)));
Q_ASSERT(s);
s = connection.connect(serviceName, IContextNetwork::ObjectPath(), IContextNetwork::InterfaceName(),
"changedAtcStationsBooked", this, SIGNAL(changedAtcStationsBooked()));

View File

@@ -210,7 +210,7 @@ namespace BlackCore
Q_ASSERT(this->getIContextOwnAircraft()->isUsingImplementingObject());
Q_ASSERT(this->getIContextNetwork()->isUsingImplementingObject());
IOwnAircraftProvider *ownAircraftProvider = this->getRuntime()->getCContextOwnAircraft();
IRenderedAircraftProvider *renderedAircraftProvider = this->getRuntime()->getCContextNetwork();
IRemoteAircraftProvider *renderedAircraftProvider = this->getRuntime()->getCContextNetwork();
ISimulator *newSimulator = factory->create(ownAircraftProvider, renderedAircraftProvider, this);
Q_ASSERT(newSimulator);

View File

@@ -0,0 +1,174 @@
/* Copyright (C) 2015
* swift project Community / Contributors
*
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
* directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project,
* including this file, may be copied, modified, propagated, or distributed except according to the terms
* contained in the LICENSE file.
*/
#include "interpolator.h"
#include "blackmisc/logmessage.h"
#include <functional>
using namespace BlackMisc;
using namespace BlackMisc::Aviation;
using namespace BlackMisc::Simulation;
namespace BlackCore
{
IInterpolator::IInterpolator(IRemoteAircraftProviderReadOnly *provider, const QString &workerName, QObject *parent) :
CContinuousWorker(parent, workerName),
CRemoteAircraftProviderSupportReadOnly(provider)
{
Q_ASSERT(provider);
this->m_situationsByCallsign = this->remoteAircraftSituations().splitPerCallsign();
this->m_partsByCallsign = this->remoteAircraftParts().splitPerCallsign();
bool c = provider->connectRemoteAircraftProviderSignals(
std::bind(&IInterpolator::ps_onAddedAircraftSituation, this, std::placeholders::_1),
std::bind(&IInterpolator::ps_onAddedAircraftParts, this, std::placeholders::_1),
std::bind(&IInterpolator::ps_onRemoveAircraft, this, std::placeholders::_1)
);
Q_ASSERT(c);
Q_UNUSED(c);
}
QList<CAircraftSituationList> IInterpolator::getSituationsTimeSplit(const CCallsign &callsign, qint64 splitTimeMsSinceEpoch) const
{
QReadLocker l(&m_situationsLock);
static const QList<CAircraftSituationList> empty({ CAircraftSituationList(), CAircraftSituationList() });
if (!this->m_situationsByCallsign.contains(callsign)) { return empty; }
return this->m_situationsByCallsign[callsign].splitByTime(splitTimeMsSinceEpoch);
}
bool IInterpolator::hasEnoughAircraftSituations(const CCallsign &callsign) const
{
QReadLocker l(&m_situationsLock);
if (!this->m_situationsByCallsign.contains(callsign)) { return false; }
return this->m_situationsByCallsign[callsign].findBeforeNowMinusOffset(TimeOffsetMs).size() > 0;
}
CAircraftParts IInterpolator::getLatestPartsBeforeOffset(const CCallsign &callsign, qint64 timeOffset, bool *ok) const
{
QReadLocker l(&m_partsLock);
static const CAircraftParts empty;
if (ok) { *ok = false; }
if (this->m_partsByCallsign.contains(callsign)) { return empty; }
CAircraftPartsList partsList = this->m_partsByCallsign[callsign].findBeforeNowMinusOffset(timeOffset);
l.unlock();
if (partsList.isEmpty()) { return empty; }
if (ok) { *ok = true; }
return partsList.latestValue();
}
void IInterpolator::requestSituationsCalculationsForAllCallsigns(int requestId)
{
QReadLocker l(&m_situationsLock);
Q_ASSERT(requestId >= 0);
const QHash<BlackMisc::Aviation::CCallsign, BlackMisc::Aviation::CAircraftSituationList> situationsCopy = m_situationsByCallsign;
l.unlock();
CAircraftSituationList latestInterpolations;
for (const CCallsign &cs : situationsCopy.keys())
{
bool ok;
CAircraftSituation situation = getCurrentInterpolatedSituation(situationsCopy, cs, &ok);
if (ok)
{
latestInterpolations.push_back(situation);
}
else
{
// not OK can mean not enough situations
// further logging could go here
}
}
QWriteLocker wl(&m_requestedInterpolationsLock);
while (m_requestedInterpolations.size() >= MaxKeptInterpolationRequests - 1)
{
m_requestedInterpolations.erase(--m_requestedInterpolations.end());
}
m_requestedInterpolations.insert(requestId, latestInterpolations); // new to old
}
QHash<CCallsign, CAircraftSituationList> IInterpolator::getSituationsByCallsign() const
{
QReadLocker l(&m_requestedInterpolationsLock);
return m_situationsByCallsign;
}
int IInterpolator::latestFinishedRequestId() const
{
QReadLocker l(&m_requestedInterpolationsLock);
if (m_requestedInterpolations.isEmpty()) { return -1; }
return m_requestedInterpolations.keys().first();
}
CAircraftSituationList IInterpolator::latestFinishedRequest() const
{
QReadLocker l(&m_requestedInterpolationsLock);
static const CAircraftSituationList empty;
if (m_requestedInterpolations.isEmpty()) { return empty; }
return m_requestedInterpolations.values().first();
}
CAircraftSituationList IInterpolator::getRequest(int requestId, bool *ok) const
{
QReadLocker l(&m_requestedInterpolationsLock);
static const CAircraftSituationList empty;
if (!m_requestedInterpolations.contains(requestId))
{
if (ok) { *ok = false; }
return empty;
}
if (ok) { *ok = true; }
return m_requestedInterpolations[requestId];
}
void IInterpolator::ps_onAddedAircraftSituation(const CAircraftSituation &situation)
{
QWriteLocker lock(&m_situationsLock);
Q_ASSERT(!situation.getCallsign().isEmpty());
if (this->m_withDebugMsg) { CLogMessage(this, CLogCategory::contextSlot()).debug() << Q_FUNC_INFO << situation; }
// list from new to old
CAircraftSituationList &l = this->m_situationsByCallsign[situation.getCallsign()];
if (l.size() >= MaxSituationsPerCallsign - 1)
{
l.truncate(MaxSituationsPerCallsign - 1);
}
l.insert(situation);
}
void IInterpolator::ps_onAddedAircraftParts(const CAircraftParts &parts)
{
QWriteLocker lock(&m_partsLock);
Q_ASSERT(!parts.getCallsign().isEmpty());
if (this->m_withDebugMsg) { CLogMessage(this, CLogCategory::contextSlot()).debug() << Q_FUNC_INFO << parts; }
// list from new to old
CAircraftPartsList &l = this->m_partsByCallsign[parts.getCallsign()];
if (l.size() >= MaxPartsPerCallsign - 1)
{
l.truncate(MaxPartsPerCallsign - 1);
}
l.insert(parts);
}
void IInterpolator::ps_onRemoveAircraft(const CCallsign &callsign)
{
QWriteLocker ls(&m_situationsLock);
QWriteLocker lp(&m_partsLock);
Q_ASSERT(!callsign.isEmpty());
if (this->m_withDebugMsg) { CLogMessage(this, CLogCategory::contextSlot()).debug() << Q_FUNC_INFO << callsign; }
if (callsign.isEmpty()) { return; }
this->m_partsByCallsign.remove(callsign);
this->m_situationsByCallsign.remove(callsign);
}
} // namespace

View File

@@ -13,33 +13,98 @@
#define BLACKCORE_INTERPOLATOR_H
#include "blackmisc/avaircraftsituation.h"
#include "blackmisc/simulation/simdirectaccessremoteaircraft.h"
#include "blackmisc/worker.h"
#include "simulator.h"
#include <QHash>
#include <QList>
namespace BlackCore
{
//! Interpolator, calculation inbetween positions
class IInterpolator
class IInterpolator :
public BlackMisc::CContinuousWorker,
public BlackMisc::Simulation::CRemoteAircraftProviderSupportReadOnly
{
public:
Q_OBJECT
public:
//! Virtual destructor
virtual ~IInterpolator() {}
//! Has situations?
virtual bool hasEnoughAircraftSituations(const BlackMisc::Aviation::CCallsign &callsign) const
{
Q_ASSERT(m_provider);
//! \todo Interpolator, it would be more efficient to directly getting the values and decide then
return m_provider->renderedAircraftSituations().findBeforeNowMinusOffset(6000).findByCallsign(callsign).size() > 1;
}
//! \deprecated Try no to use, it would be more efficient to directly getting the values and decide then
//! \threadsafe
virtual bool hasEnoughAircraftSituations(const BlackMisc::Aviation::CCallsign &callsign) const;
//! Current interpolated situation
virtual BlackMisc::Aviation::CAircraftSituation getCurrentInterpolatedSituation(const BlackMisc::Aviation::CCallsign &callsign) const = 0;
//! \threadsafe
virtual BlackMisc::Aviation::CAircraftSituation getCurrentInterpolatedSituation(const QHash<BlackMisc::Aviation::CCallsign, BlackMisc::Aviation::CAircraftSituationList> &allSituations, const BlackMisc::Aviation::CCallsign &callsign, bool *ok = nullptr) const = 0;
//! Latest parts before time - offset
//! \threadsafe
BlackMisc::Aviation::CAircraftParts getLatestPartsBeforeOffset(const BlackMisc::Aviation::CCallsign &callsign, qint64 timeOffset = TimeOffsetMs, bool *ok = nullptr) const;
//! Do a complete calculation for all know callsigns in background.
//! Only use positive numbers.
//! \threadsafe
void requestSituationsCalculationsForAllCallsigns(int requestId);
//! The situations per callsign
//! \threadsafe
QHash<BlackMisc::Aviation::CCallsign, BlackMisc::Aviation::CAircraftSituationList> getSituationsByCallsign() const;
//! Last finished request id, -1 means none
//! \threadsafe
int latestFinishedRequestId() const;
//! Latest calculation
//! \threadsafe
BlackMisc::Aviation::CAircraftSituationList latestFinishedRequest() const;
//! Calculation by id
//! \threadsafe
BlackMisc::Aviation::CAircraftSituationList getRequest(int requestId, bool *ok = nullptr) const;
static const qint64 TimeOffsetMs = 6000; //!< offset for interpolation
static const int MaxSituationsPerCallsign = 6; //!< How many situations per callsign
static const int MaxPartsPerCallsign = 3; //!< How many parts per callsign
static const int MaxKeptInterpolationRequests = 3; //!< How many requests are stored
private slots:
//! New situation got added
//! \threadsafe
void ps_onAddedAircraftSituation(const BlackMisc::Aviation::CAircraftSituation &situation);
//! Added aircraft parts
//! \threadsafe
void ps_onAddedAircraftParts(const BlackMisc::Aviation::CAircraftParts &parts);
//! Removed aircraft
//! \threadsafe
void ps_onRemoveAircraft(const BlackMisc::Aviation::CCallsign &callsign);
protected:
//! Constructor
IInterpolator(BlackMisc::Simulation::IRenderedAircraftProviderReadOnly *provider) : m_provider(provider) { Q_ASSERT(provider);}
BlackMisc::Simulation::IRenderedAircraftProviderReadOnly *m_provider = nullptr; //!< access to provider
IInterpolator(BlackMisc::Simulation::IRemoteAircraftProviderReadOnly *provider, const QString &workerName, QObject *parent = nullptr);
//! Situations for times before / after
//! \sa ITimestampObjectList::splitByTime
//! \threadsafe
//! \deprecated For first version
QList<BlackMisc::Aviation::CAircraftSituationList> getSituationsTimeSplit(const BlackMisc::Aviation::CCallsign &callsign, qint64 splitTimeMsSinceEpoch) const;
bool m_withDebugMsg = true;
private:
mutable QReadWriteLock m_situationsLock;
mutable QReadWriteLock m_partsLock;
mutable QReadWriteLock m_requestedInterpolationsLock;
// hashs, because not sorted by key but keeping order
QHash<BlackMisc::Aviation::CCallsign, BlackMisc::Aviation::CAircraftSituationList> m_situationsByCallsign;
QHash<BlackMisc::Aviation::CCallsign, BlackMisc::Aviation::CAircraftPartsList> m_partsByCallsign;
QHash<int, BlackMisc::Aviation::CAircraftSituationList> m_requestedInterpolations;
};
} // namespace

View File

@@ -18,13 +18,18 @@ using namespace BlackMisc::Aviation;
namespace BlackCore
{
CAircraftSituation CInterpolatorLinear::getCurrentInterpolatedSituation(const CCallsign &callsign) const
CAircraftSituation CInterpolatorLinear::getCurrentInterpolatedSituation(const QHash<CCallsign, CAircraftSituationList> &allSituations, const CCallsign &callsign, bool *ok) const
{
QDateTime currentTime = QDateTime::currentDateTimeUtc().addSecs(-6);
CAircraftSituationList situationsBefore = renderedAircraftSituations().findBefore(currentTime).findByCallsign(callsign);
CAircraftSituationList situationsAfter = renderedAircraftSituations().findAfter(currentTime).findByCallsign(callsign);
Q_ASSERT_X(!situationsBefore.isEmpty(), "CInterpolatorLinear::getCurrentSituation()", "List previous situations is empty!");
const static CAircraftSituation empty;
qint64 splitTimeMsSinceEpoch = QDateTime::currentMSecsSinceEpoch() - TimeOffsetMs;
QList<CAircraftSituationList> splitSituations = allSituations[callsign].splitByTime(splitTimeMsSinceEpoch);
CAircraftSituationList &situationsBefore = splitSituations[0];
CAircraftSituationList &situationsAfter = splitSituations[1];
if (situationsBefore.isEmpty())
{
if (ok) { *ok = false; }
return empty;
}
CAircraftSituation beginSituation;
CAircraftSituation endSituation;
@@ -49,7 +54,7 @@ namespace BlackCore
double deltaTime = beginSituation.msecsToAbs(endSituation);
// Fraction of the deltaTime [0.0 - 1.0]
double simulationTimeFraction = beginSituation.getUtcTimestamp().msecsTo(currentTime) / deltaTime;
double simulationTimeFraction = (beginSituation.getMSecsSinceEpoch() - splitTimeMsSinceEpoch) / deltaTime;
// Interpolate latitude: Lat = (LatB - LatA) * t + LatA
currentPosition.setLatitude((endSituation.getPosition().latitude() - beginSituation.getPosition().latitude())
@@ -73,10 +78,14 @@ namespace BlackCore
CHeading headingEnd = endSituation.getHeading();
if ((headingEnd - headingBegin).value(CAngleUnit::deg()) < -180)
{
headingEnd += CHeading(360, CHeading::Magnetic, CAngleUnit::deg());
}
if ((headingEnd - headingBegin).value(CAngleUnit::deg()) > 180)
{
headingEnd -= CHeading(360, CHeading::Magnetic, CAngleUnit::deg());
}
currentSituation.setHeading(CHeading((headingEnd - headingBegin)
* simulationTimeFraction
@@ -86,7 +95,6 @@ namespace BlackCore
// Interpolate Pitch: Pitch = (PitchB - PitchA) * t + PitchA
CAngle pitchBegin = beginSituation.getPitch();
CAngle pitchEnd = endSituation.getPitch();
CAngle pitch = (pitchEnd - pitchBegin) * simulationTimeFraction + pitchBegin;
// TODO: According to the specification, pitch above horizon should be negative.
@@ -97,7 +105,6 @@ namespace BlackCore
// Interpolate bank: Bank = (BankB - BankA) * t + BankA
CAngle bankBegin = beginSituation.getBank();
CAngle bankEnd = endSituation.getBank();
CAngle bank = (bankEnd - bankBegin) * simulationTimeFraction + bankBegin;
// TODO: According to the specification, banks to the right should be negative.
@@ -108,7 +115,7 @@ namespace BlackCore
currentSituation.setGroundspeed((endSituation.getGroundSpeed() - beginSituation.getGroundSpeed())
* simulationTimeFraction
+ beginSituation.getGroundSpeed());
if (ok) { *ok = true; }
return currentSituation;
}

View File

@@ -20,19 +20,17 @@
namespace BlackCore
{
//! \brief Linear interpolator, calculation inbetween positions
class CInterpolatorLinear :
public IInterpolator,
public BlackMisc::Simulation::CRenderedAircraftProviderSupportReadOnly
//! Linear interpolator, calculation inbetween positions
class CInterpolatorLinear : public IInterpolator
{
public:
//! Constructor
CInterpolatorLinear(BlackMisc::Simulation::IRenderedAircraftProviderReadOnly *provider) :
IInterpolator(provider),
BlackMisc::Simulation::CRenderedAircraftProviderSupportReadOnly(provider) {}
CInterpolatorLinear(BlackMisc::Simulation::IRemoteAircraftProviderReadOnly *provider, QObject *parent = nullptr) :
IInterpolator(provider, "CInterpolatorLinear", parent)
{}
//! \copydoc IInterpolator::getCurrentInterpolatedSituation
virtual BlackMisc::Aviation::CAircraftSituation getCurrentInterpolatedSituation(const BlackMisc::Aviation::CCallsign &callsign) const override;
virtual BlackMisc::Aviation::CAircraftSituation getCurrentInterpolatedSituation(const QHash<BlackMisc::Aviation::CCallsign, BlackMisc::Aviation::CAircraftSituationList> &allSituations, const BlackMisc::Aviation::CCallsign &callsign, bool *ok = nullptr) const override;
};
} // namespace BlackCore

View File

@@ -19,8 +19,8 @@ namespace BlackCore
emit simulatorStatusChanged(isConnected(), isSimulating(), isPaused());
}
CSimulatorCommon::CSimulatorCommon(const BlackSim::CSimulatorInfo &simInfo, BlackMisc::Simulation::IOwnAircraftProvider *ownAircraftProvider, BlackMisc::Simulation::IRenderedAircraftProvider *renderedAircraftProvider, QObject *parent)
: ISimulator(parent), COwnAircraftProviderSupport(ownAircraftProvider), CRenderedAircraftProviderSupport(renderedAircraftProvider), m_simulatorInfo(simInfo)
CSimulatorCommon::CSimulatorCommon(const BlackSim::CSimulatorInfo &simInfo, BlackMisc::Simulation::IOwnAircraftProvider *ownAircraftProvider, BlackMisc::Simulation::IRemoteAircraftProvider *remoteAircraftProvider, QObject *parent)
: ISimulator(parent), COwnAircraftProviderSupport(ownAircraftProvider), CRemoteAircraftProviderSupport(remoteAircraftProvider), m_simulatorInfo(simInfo)
{ }
int CSimulatorCommon::getMaxRenderedAircraft() const

View File

@@ -16,7 +16,7 @@
#include "blackmisc/simulation/simulatedaircraftlist.h"
#include "blackmisc/simulation/aircraftmodellist.h"
#include "blackmisc/simulation/simdirectaccessownaircraft.h"
#include "blackmisc/simulation/simdirectaccessrenderedaircraft.h"
#include "blackmisc/simulation/simdirectaccessremoteaircraft.h"
#include "blackmisc/statusmessagelist.h"
#include "blackmisc/avairportlist.h"
#include "blackmisc/nwtextmessage.h"
@@ -177,7 +177,7 @@ namespace BlackCore
//!
virtual ISimulator *create(
BlackMisc::Simulation::IOwnAircraftProvider *ownAircraftProvider,
BlackMisc::Simulation::IRenderedAircraftProvider *renderedAircraftProvider,
BlackMisc::Simulation::IRemoteAircraftProvider *renderedAircraftProvider,
QObject *parent = nullptr) = 0;
//! Simulator info
@@ -188,7 +188,7 @@ namespace BlackCore
class CSimulatorCommon :
public BlackCore::ISimulator,
public BlackMisc::Simulation::COwnAircraftProviderSupport, // gain access to in memor own aircraft data
public BlackMisc::Simulation::CRenderedAircraftProviderSupport // gain access to in memory rendered aircraft data
public BlackMisc::Simulation::CRemoteAircraftProviderSupport // gain access to in memory rendered aircraft data
{
public:
@@ -206,7 +206,7 @@ namespace BlackCore
CSimulatorCommon(
const BlackSim::CSimulatorInfo &simInfo,
BlackMisc::Simulation::IOwnAircraftProvider *ownAircraftProvider,
BlackMisc::Simulation::IRenderedAircraftProvider *renderedAircraftProvider,
BlackMisc::Simulation::IRemoteAircraftProvider *remoteAircraftProvider,
QObject *parent = nullptr);
BlackSim::CSimulatorInfo m_simulatorInfo; //!< about the simulator