Ref T171, fetch interpolator values in emulated driver.

This allows to test and monitor the interpolator in the emulated driver.

* UI allows to start/stop interpolator logging
* Fetch data from interpolator
This commit is contained in:
Klaus Basan
2017-10-16 09:14:28 +02:00
parent 6e39b69933
commit 7b50917410
5 changed files with 300 additions and 32 deletions

View File

@@ -40,12 +40,14 @@ namespace BlackSimPlugin
Q_ASSERT_X(sApp && sApp->getIContextSimulator(), Q_FUNC_INFO, "Need context");
CSimulatorEmulated::registerHelp();
this->setObjectName(info.getSimulatorInfo());
m_myAircraft = this->getOwnAircraft(); // sync with provider
m_monitorWidget.reset(new CSimulatorEmulatedMonitorDialog(this, sGui->mainApplicationWindow()));
connect(qApp, &QApplication::aboutToQuit, this, &CSimulatorEmulated::closeMonitor);
this->onSettingsChanged();
connect(qApp, &QApplication::aboutToQuit, this, &CSimulatorEmulated::closeMonitor);
connect(&m_interpolatorFetchTimer, &QTimer::timeout, this, &CSimulatorEmulated::fetchFromInterpolator);
// connect own signals for monitoring
this->connectOwnSignals();
}
@@ -234,6 +236,24 @@ namespace BlackSimPlugin
return this->updateOwnParts(parts);
}
bool CSimulatorEmulated::setInterpolatorFetchTime(int timeMs)
{
if (timeMs < 1)
{
m_interpolatorFetchTimer.stop();
}
else
{
m_interpolatorFetchTimer.start(timeMs);
}
return m_interpolatorFetchTimer.isActive();
}
bool CSimulatorEmulated::isInterpolatorFetching() const
{
return m_interpolatorFetchTimer.isActive();
}
bool CSimulatorEmulated::isConnected() const
{
if (canLog()) m_monitorWidget->appendReceivingCall(Q_FUNC_INFO);
@@ -257,8 +277,9 @@ namespace BlackSimPlugin
if (canLog()) m_monitorWidget->appendReceivingCall(Q_FUNC_INFO, remoteAircraft.toQString());
CSimulatedAircraft aircraft(remoteAircraft);
aircraft.setRendered(true);
m_renderedAircraft.push_back(aircraft); // my simulator list
const CCallsign cs = aircraft.getCallsign();
m_interpolators.insert(cs, CInterpolatorMultiWrapper(cs, &m_interpolationLogger, this));
m_renderedAircraft.push_back(aircraft); // my simulator list
this->updateAircraftRendered(cs, true); // in provider
emit this->aircraftRenderingChanged(aircraft);
return true;
@@ -267,6 +288,7 @@ namespace BlackSimPlugin
bool CSimulatorEmulated::physicallyRemoveRemoteAircraft(const CCallsign &callsign)
{
if (canLog()) m_monitorWidget->appendReceivingCall(Q_FUNC_INFO, callsign.toQString());
m_interpolators.remove(callsign);
const int c = m_renderedAircraft.removeByCallsign(callsign);
return c > 0;
}
@@ -274,7 +296,9 @@ namespace BlackSimPlugin
bool CSimulatorEmulated::setInterpolatorMode(CInterpolatorMulti::Mode mode, const CCallsign &callsign)
{
if (canLog()) m_monitorWidget->appendReceivingCall(Q_FUNC_INFO, CInterpolatorMulti::modeToString(mode), callsign.toQString());
return false;
if (!m_interpolators.contains(callsign)) { return false; }
CInterpolatorMulti *im = m_interpolators[callsign];
return im->setMode(mode);
}
int CSimulatorEmulated::physicallyRemoveAllRemoteAircraft()
@@ -283,6 +307,23 @@ namespace BlackSimPlugin
return CSimulatorCommon::physicallyRemoveAllRemoteAircraft();
}
void CSimulatorEmulated::onRemoteProviderAddedAircraftSituation(const CAircraftSituation &situation)
{
const CCallsign cs = situation.getCallsign();
if (!m_interpolators.contains(cs)) { return; }
CInterpolatorMulti *im = m_interpolators[cs];
Q_ASSERT_X(im, Q_FUNC_INFO, "no interpolator");
im->addAircraftSituation(situation);
}
void BlackSimPlugin::Emulated::CSimulatorEmulated::onRemoteProviderAddedAircraftParts(const CCallsign &callsign, const CAircraftParts &parts)
{
if (!m_interpolators.contains(callsign)) { return; }
CInterpolatorMulti *im = m_interpolators[callsign];
Q_ASSERT_X(im, Q_FUNC_INFO, "no interpolator");
im->addAircraftParts(parts);
}
bool CSimulatorEmulated::parseDetails(const CSimpleCommandParser &parser)
{
if (m_monitorWidget && parser.isKnownCommand())
@@ -293,6 +334,12 @@ namespace BlackSimPlugin
return false;
}
void CSimulatorEmulated::setObjectName(const CSimulatorInfo &info)
{
QObject::setObjectName("Emulated driver for " + info.getSimulator());
m_interpolatorFetchTimer.setObjectName(this->objectName() + ":interpolatorFetchTimer");
}
bool CSimulatorEmulated::canLog() const
{
return sApp && !sApp->isShuttingDown() && m_log && m_monitorWidget;
@@ -311,8 +358,9 @@ namespace BlackSimPlugin
const CSwiftPluginSettings settings(m_settings.get());
m_log = settings.isLoggingFunctionCalls();
const CSimulatorInfo simulator = settings.getEmulatedSimulator();
const CSimulatorPluginInfoList plugins = sApp->getIContextSimulator()->getAvailableSimulatorPlugins();
const CSimulatorPluginInfo plugin = plugins.findBySimulator(settings.getEmulatedSimulator());
const CSimulatorPluginInfo plugin = plugins.findBySimulator(simulator);
if (plugin.isValid())
{
// ? restart driver, disconnect/reconnect
@@ -325,6 +373,9 @@ namespace BlackSimPlugin
// update provider
this->updateOwnModel(settings.getOwnModel());
// own name
this->setObjectName(simulator);
}
void CSimulatorEmulated::connectOwnSignals()
@@ -368,6 +419,31 @@ namespace BlackSimPlugin
}, Qt::QueuedConnection));
}
void CSimulatorEmulated::fetchFromInterpolator()
{
const qint64 now = QDateTime::currentMSecsSinceEpoch();
const CInterpolationAndRenderingSetup setup = this->getInterpolationAndRenderingSetup(); // threadsafe copy
for (const CSimulatedAircraft &aircraft : m_renderedAircraft)
{
const CCallsign cs = aircraft.getCallsign();
if (!m_interpolators.contains(cs)) { continue; }
const bool log = setup.logCallsign(cs);
CInterpolatorMulti *im = m_interpolators[cs];
CInterpolationStatus statusInterpolation;
CPartsStatus statusParts;
CInterpolationHints hints;
Q_ASSERT_X(im, Q_FUNC_INFO, "interpolator missing");
if (m_hints.contains(cs)) { hints = m_hints[cs]; }
hints.setLoggingInterpolation(log);
const CAircraftSituation s = im->getInterpolatedSituation(now, setup, hints, statusInterpolation);
const CAircraftParts p = im->getInterpolatedParts(now, setup, statusParts, log);
m_countInterpolatedParts++;
m_countInterpolatedSituations++;
Q_UNUSED(s);
Q_UNUSED(p);
}
}
CSimulatorEmulatedListener::CSimulatorEmulatedListener(const CSimulatorPluginInfo &info)
: ISimulatorListener(info)
{ }

View File

@@ -13,12 +13,17 @@
#define BLACKSIMPLUGIN_EMULATED_SIMULATOREMULATED_H
#include "blackcore/simulatorcommon.h"
#include "blackmisc/simulation/interpolatormulti.h"
#include "blackmisc/simulation/interpolationrenderingsetup.h"
#include "blackmisc/simulation/interpolationlogger.h"
#include "blackmisc/simulation/simulatorplugininfo.h"
#include "blackmisc/simulation/settings/swiftpluginsettings.h"
#include "blackmisc/pq/time.h"
#include "blackmisc/connectionguard.h"
#include "simulatoremulatedmonitordialog.h"
#include <QMap>
#include <QTimer>
#include <QScopedPointer>
namespace BlackSimPlugin
@@ -99,6 +104,12 @@ namespace BlackSimPlugin
//! \remark normally used by corresponding BlackSimPlugin::Emulated::CSimulatorEmulatedMonitorDialog
bool changeInternalParts(const BlackMisc::Aviation::CAircraftParts &parts);
//! Interpolator fetch time, <=0 stops
bool setInterpolatorFetchTime(int timeMs);
//! Is fetching from interpolator
bool isInterpolatorFetching() const;
//! Register help
static void registerHelp();
@@ -116,10 +127,19 @@ namespace BlackSimPlugin
// just logged
virtual int physicallyRemoveAllRemoteAircraft() override;
//! \name Remote aircraft provider overrides
//! @{
virtual void onRemoteProviderAddedAircraftSituation(const BlackMisc::Aviation::CAircraftSituation &situation) override;
virtual void onRemoteProviderAddedAircraftParts(const BlackMisc::Aviation::CCallsign &callsign, const BlackMisc::Aviation::CAircraftParts &parts) override;
//! @}
//! \copydoc BlackCore::CSimulatorCommon::parseDetails
virtual bool parseDetails(const BlackMisc::CSimpleCommandParser &parser) override;
private:
//! Set object name
void setObjectName(const BlackMisc::Simulation::CSimulatorInfo &info);
//! Can append log messages?
bool canLog() const;
@@ -135,18 +155,25 @@ namespace BlackSimPlugin
//! Connect own signals for monitoring
void connectOwnSignals();
//! Fetch data from interpolator
//! \remarks basically does the same as a real driver, obtains data from the interpolator
void fetchFromInterpolator();
bool m_log = false; //!< from settings
bool m_paused = false;
bool m_connected = true;
bool m_simulating = true;
bool m_timeSyncronized = false;
int m_countInterpolatedSituations = 0;
int m_countInterpolatedParts = 0;
QTimer m_interpolatorFetchTimer { this }; //!< fetch data from interpolator
BlackMisc::PhysicalQuantities::CTime m_offsetTime;
BlackMisc::Simulation::CSimulatedAircraft m_myAircraft; //!< represents own aircraft of simulator
BlackMisc::Simulation::CSimulatedAircraftList m_renderedAircraft; //!< represents remote aircraft in simulator
QScopedPointer<CSimulatorEmulatedMonitorDialog> m_monitorWidget; //!< parent will be main window, so we need to destroy widget when destroyed
BlackMisc::CConnectionGuard m_connectionGuard; //!< connected with provider
BlackMisc::CSettingReadOnly<BlackMisc::Simulation::Settings::TSwiftPlugin> m_settings { this, &CSimulatorEmulated::onSettingsChanged };
BlackMisc::CConnectionGuard m_connectionGuard;
QMap<BlackMisc::Aviation::CCallsign, BlackMisc::Simulation::CInterpolatorMultiWrapper> m_interpolators; //!< interpolators per callsign
};
//! Listener for swift

View File

@@ -10,6 +10,8 @@
#include "simulatoremulatedmonitordialog.h"
#include "simulatoremulated.h"
#include "ui_simulatoremulatedmonitordialog.h"
#include "blackmisc/logmessage.h"
#include <QIntValidator>
using namespace BlackMisc;
using namespace BlackMisc::Aviation;
@@ -29,6 +31,7 @@ namespace BlackSimPlugin
CSimulatorEmulatedMonitorDialog::CSimulatorEmulatedMonitorDialog(CSimulatorEmulated *simulator, QWidget *parent) :
QDialog(parent),
CIdentifiable("Emulated driver dialog"),
ui(new Ui::CSimulatorEmulatedMonitorDialog)
{
Q_ASSERT_X(simulator, Q_FUNC_INFO, "Need simulator");
@@ -41,9 +44,9 @@ namespace BlackSimPlugin
m_simulator = simulator;
m_uiUpdateTimer.setObjectName(this->objectName() + ":uiUpdateTimer");
m_uiUpdateTimer.start(2.5 * 1000);
connect(m_simulator, &CSimulatorEmulated::internalAircraftChanged, this, &CSimulatorEmulatedMonitorDialog::setInternalAircraftUiValues, Qt::QueuedConnection);
connect(&m_uiUpdateTimer, &QTimer::timeout, this, &CSimulatorEmulatedMonitorDialog::timerBasedUiUpdates);
connect(ui->pb_ResetStatistics, &QPushButton::clicked, this, &CSimulatorEmulatedMonitorDialog::resetStatistics);
connect(ui->cb_Connected, &QCheckBox::released, this, &CSimulatorEmulatedMonitorDialog::onSimulatorValuesChanged);
connect(ui->cb_Paused, &QCheckBox::released, this, &CSimulatorEmulatedMonitorDialog::onSimulatorValuesChanged);
@@ -54,11 +57,24 @@ namespace BlackSimPlugin
connect(ui->editor_Com, &CCockpitComForm::changedCockpitValues, this, &CSimulatorEmulatedMonitorDialog::changeComFromUi);
connect(ui->editor_Com, &CCockpitComForm::changedSelcal, this, &CSimulatorEmulatedMonitorDialog::changeSelcalFromUi);
ui->wi_LedReceiving->setToolTips("receiving", "idle");
ui->wi_LedReceiving->setShape(CLedWidget::Rounded);
ui->wi_LedSending->setToolTips("sending", "idle");
ui->wi_LedSending->setShape(CLedWidget::Rounded);
connect(ui->pb_ResetStatistics, &QPushButton::clicked, this, &CSimulatorEmulatedMonitorDialog::resetStatistics);
connect(ui->pb_InterpolatorStopLog, &QPushButton::clicked, this, &CSimulatorEmulatedMonitorDialog::interpolatorLogButton);
connect(ui->pb_InterpolatorWriteLog, &QPushButton::clicked, this, &CSimulatorEmulatedMonitorDialog::interpolatorLogButton);
connect(ui->pb_InterpolatorClearLog, &QPushButton::clicked, this, &CSimulatorEmulatedMonitorDialog::interpolatorLogButton);
connect(ui->pb_InterpolatorShowLogs, &QPushButton::clicked, this, &CSimulatorEmulatedMonitorDialog::interpolatorLogButton);
connect(ui->pb_InterpolatorStartLog, &QPushButton::clicked, this, &CSimulatorEmulatedMonitorDialog::interpolatorLogButton);
connect(ui->pb_InterpolatorFetch, &QPushButton::clicked, this, &CSimulatorEmulatedMonitorDialog::interpolatorLogButton);
ui->led_Receiving->setToolTips("receiving", "idle");
ui->led_Receiving->setShape(CLedWidget::Rounded);
ui->led_Sending->setToolTips("sending", "idle");
ui->led_Sending->setShape(CLedWidget::Rounded);
ui->led_Fetching->setToolTips("fetching interpolated", "not fetching interpolated");
ui->led_Fetching->setShape(CLedWidget::Rounded);
ui->le_InterpolatorTimeMs->setValidator(new QIntValidator(10, 20000, ui->le_InterpolatorTimeMs));
this->enableInterpolationLogButtons(false);
this->setSimulatorUiValues();
this->setInternalAircraftUiValues();
}
@@ -78,13 +94,13 @@ namespace BlackSimPlugin
void CSimulatorEmulatedMonitorDialog::appendReceivingCall(const QString &function, const QString &p1, const QString &p2, const QString &p3)
{
ui->wi_LedReceiving->blink();
ui->led_Receiving->blink();
this->appendFunctionCall(function, p1, p2, p3);
}
void CSimulatorEmulatedMonitorDialog::appendSendingCall(const QString &function, const QString &p1, const QString &p2, const QString &p3)
{
ui->wi_LedSending->blink();
ui->led_Sending->blink();
this->appendFunctionCall(function, p1, p2, p3);
}
@@ -196,5 +212,64 @@ namespace BlackSimPlugin
ui->le_SituationAdded->clear();
ui->le_PartsAdded->clear();
}
void CSimulatorEmulatedMonitorDialog::interpolatorLogButton()
{
const QObject *sender = QObject::sender();
bool ok = false;
if (sender == ui->pb_InterpolatorStopLog)
{
ok = m_simulator->parseCommandLine(".drv logint off", this->identifier());
}
else if (sender == ui->pb_InterpolatorWriteLog)
{
ok = m_simulator->parseCommandLine(".drv logint write", this->identifier());
}
else if (sender == ui->pb_InterpolatorClearLog)
{
ok = m_simulator->parseCommandLine(".drv logint clear", this->identifier());
}
else if (sender == ui->pb_InterpolatorShowLogs)
{
ok = m_simulator->parseCommandLine(".drv logint show", this->identifier());
}
else if (sender == ui->pb_InterpolatorStartLog)
{
const CCallsign cs = ui->comp_LogInterpolatorCallsign->getCallsign();
if (cs.isValid())
{
ok = m_simulator->parseCommandLine(".drv logint " + cs.asString(), this->identifier());
}
else
{
CLogMessage(this).warning("Need a (valid) callsign to write a log");
ok = true; // already a warning
}
}
else if (sender == ui->pb_InterpolatorFetch)
{
// toggle fetching
const int timeMs = m_simulator->isInterpolatorFetching() ? -1 : ui->le_InterpolatorTimeMs->text().toInt();
const bool fetching = m_simulator->setInterpolatorFetchTime(timeMs);
ui->led_Fetching->setOn(fetching);
ui->pb_InterpolatorFetch->setText(fetching ? "Stop" : "Fetch");
this->enableInterpolationLogButtons(fetching);
ok = true;
}
else
{
Q_ASSERT_X(false, Q_FUNC_INFO, "Unhandled button");
}
if (!ok) { CLogMessage(this).warning("Cannot parse command for button: %1") << sender->objectName(); }
}
void CSimulatorEmulatedMonitorDialog::enableInterpolationLogButtons(bool enable)
{
ui->pb_InterpolatorClearLog->setEnabled(enable);
ui->pb_InterpolatorShowLogs->setEnabled(enable);
ui->pb_InterpolatorStartLog->setEnabled(enable);
ui->pb_InterpolatorStopLog->setEnabled(enable);
ui->pb_InterpolatorWriteLog->setEnabled(enable);
}
} // ns
} // ns

View File

@@ -15,6 +15,7 @@
#include "blackmisc/simulation/simulatedaircraft.h"
#include "blackmisc/statusmessagelist.h"
#include "blackmisc/logcategorylist.h"
#include "blackmisc/identifiable.h"
#include <QDialog>
#include <QScopedPointer>
@@ -30,7 +31,7 @@ namespace BlackSimPlugin
/**
* Monitor widget for the pseudo driver
*/
class CSimulatorEmulatedMonitorDialog : public QDialog
class CSimulatorEmulatedMonitorDialog : public QDialog, public BlackMisc::CIdentifiable
{
Q_OBJECT
@@ -95,6 +96,12 @@ namespace BlackSimPlugin
//! Reset statistics
void resetStatistics();
//! Interpolator log button pressed
void interpolatorLogButton();
//! Enable/disable the interpolation log buttons
void enableInterpolationLogButtons(bool enable);
QScopedPointer<Ui::CSimulatorEmulatedMonitorDialog> ui;
CSimulatorEmulated *m_simulator = nullptr;
QTimer m_uiUpdateTimer { this };

View File

@@ -31,7 +31,7 @@
</widget>
</item>
<item>
<widget class="BlackGui::CLedWidget" name="wi_LedReceiving" native="true"/>
<widget class="BlackGui::CLedWidget" name="led_Receiving" native="true"/>
</item>
<item>
<widget class="QLabel" name="lbl_Sending">
@@ -41,7 +41,7 @@
</widget>
</item>
<item>
<widget class="BlackGui::CLedWidget" name="wi_LedSending" native="true"/>
<widget class="BlackGui::CLedWidget" name="led_Sending" native="true"/>
</item>
<item>
<spacer name="hs_LedHeader">
@@ -91,6 +91,19 @@
</property>
</widget>
</item>
<item>
<spacer name="vs_Situation">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<widget class="QWidget" name="tb_ComParts">
@@ -385,6 +398,83 @@
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="gb_Interpolator">
<property name="title">
<string>Interpolator</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="6">
<widget class="QPushButton" name="pb_InterpolatorStartLog">
<property name="text">
<string> start log. </string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QPushButton" name="pb_InterpolatorClearLog">
<property name="text">
<string> clear log </string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QPushButton" name="pb_InterpolatorStopLog">
<property name="text">
<string> stop logging </string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QPushButton" name="pb_InterpolatorWriteLog">
<property name="text">
<string> write log.file </string>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="QPushButton" name="pb_InterpolatorShowLogs">
<property name="text">
<string> log.files </string>
</property>
</widget>
</item>
<item row="1" column="5">
<widget class="BlackGui::Components::CCallsignCompleter" name="comp_LogInterpolatorCallsign">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QPushButton" name="pb_InterpolatorFetch">
<property name="text">
<string>fetch</string>
</property>
</widget>
</item>
<item row="0" column="0" colspan="2">
<widget class="QLineEdit" name="le_InterpolatorTimeMs">
<property name="text">
<string>40</string>
</property>
<property name="maxLength">
<number>10</number>
</property>
<property name="placeholderText">
<string>fetch time ms</string>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="BlackGui::CLedWidget" name="led_Fetching" native="true"/>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="gb_LogMessages">
<property name="sizePolicy">
@@ -426,19 +516,6 @@
</widget>
</widget>
</item>
<item>
<spacer name="vs_Situation">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QDialogButtonBox" name="bb_SwiftMonitorDialog">
<property name="orientation">
@@ -488,6 +565,12 @@
<header>blackgui/led.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>BlackGui::Components::CCallsignCompleter</class>
<extends>QFrame</extends>
<header>blackgui/components/callsigncompleter.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections>