293 lines
13 KiB
C++
293 lines
13 KiB
C++
#include "../src/MainWindow.h"
|
|
#include "../src/GlobeWidget.h"
|
|
#include "../src/MapWidget.h"
|
|
|
|
#include <QApplication>
|
|
#include <QAction>
|
|
#include <QCheckBox>
|
|
#include <QComboBox>
|
|
#include <QDoubleSpinBox>
|
|
#include <QLabel>
|
|
#include <QLineEdit>
|
|
#include <QMetaObject>
|
|
#include <QSpinBox>
|
|
#include <QPushButton>
|
|
#include <QTableView>
|
|
#include <QTabWidget>
|
|
#include <QSplitter>
|
|
#include <QTemporaryFile>
|
|
|
|
#include <cassert>
|
|
#include <cmath>
|
|
|
|
namespace {
|
|
|
|
void sendLine(MainWindow &window, const QString &line)
|
|
{
|
|
const bool invoked = QMetaObject::invokeMethod(
|
|
&window, "handleSerialLine", Qt::DirectConnection, Q_ARG(QString, line));
|
|
assert(invoked);
|
|
}
|
|
|
|
void flushUpdates(MainWindow &window)
|
|
{
|
|
const bool invoked = QMetaObject::invokeMethod(
|
|
&window, "flushUiUpdates", Qt::DirectConnection);
|
|
assert(invoked);
|
|
}
|
|
|
|
} // namespace
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
QApplication app(argc, argv);
|
|
qputenv("LOCATION_PLOTTER_PORT", "/dev/test-usb-uart");
|
|
MainWindow window;
|
|
qunsetenv("LOCATION_PLOTTER_PORT");
|
|
|
|
auto *table = window.findChild<QTableView *>();
|
|
auto *referenceLatInput = window.findChild<QLineEdit *>(QStringLiteral("referenceLatInput"));
|
|
auto *referenceLonInput = window.findChild<QLineEdit *>(QStringLiteral("referenceLonInput"));
|
|
auto *cepValue = window.findChild<QLabel *>(QStringLiteral("cepValue"));
|
|
auto *maxPointsInput = window.findChild<QSpinBox *>(QStringLiteral("maxPointsInput"));
|
|
auto *elevationMaskSpin = window.findChild<QDoubleSpinBox *>(QStringLiteral("elevationMaskSpin"));
|
|
auto *showTelemetry = window.findChild<QCheckBox *>(QStringLiteral("showTelemetryCheck"));
|
|
auto *showRecentPoints = window.findChild<QCheckBox *>(QStringLiteral("showRecentPointsCheck"));
|
|
auto *showAverage = window.findChild<QCheckBox *>(QStringLiteral("showAverageCheck"));
|
|
auto *portSelector = window.findChild<QComboBox *>(QStringLiteral("portSelector"));
|
|
auto *refreshRinexButton =
|
|
window.findChild<QPushButton *>(QStringLiteral("refreshRinexButton"));
|
|
auto *map = window.findChild<MapWidget *>();
|
|
auto *mainViewTabs = window.findChild<QTabWidget *>(QStringLiteral("mainViewTabs"));
|
|
auto *sideSplitter = window.findChild<QSplitter *>(QStringLiteral("sideSplitter"));
|
|
auto *rinexUpdateButton = window.findChild<QPushButton *>(QStringLiteral("rinexUpdateButton"));
|
|
auto *openLogAction = window.findChild<QAction *>(QStringLiteral("openLogAction"));
|
|
auto *toggleSerialAction = window.findChild<QAction *>(QStringLiteral("toggleSerialAction"));
|
|
auto *rinexUpdateAction = window.findChild<QAction *>(QStringLiteral("rinexUpdateAction"));
|
|
assert(table != nullptr);
|
|
assert(referenceLatInput != nullptr);
|
|
assert(referenceLonInput != nullptr);
|
|
assert(cepValue != nullptr);
|
|
assert(maxPointsInput != nullptr);
|
|
assert(elevationMaskSpin != nullptr);
|
|
assert(elevationMaskSpin->value() == 10);
|
|
assert(elevationMaskSpin->minimum() == 0);
|
|
assert(elevationMaskSpin->maximum() == 90.0);
|
|
elevationMaskSpin->setValue(12.5);
|
|
assert(elevationMaskSpin->value() == 12.5);
|
|
assert(showTelemetry != nullptr);
|
|
assert(showRecentPoints != nullptr);
|
|
assert(showAverage != nullptr);
|
|
assert(portSelector != nullptr);
|
|
assert(refreshRinexButton != nullptr);
|
|
assert(refreshRinexButton->text() == QStringLiteral("RINEX Guncelle")
|
|
|| refreshRinexButton->text() == QStringLiteral("RINEX indiriliyor..."));
|
|
assert(portSelector->isEditable());
|
|
assert(portSelector->count() >= 1);
|
|
assert(portSelector->currentText() == QStringLiteral("/dev/test-usb-uart"));
|
|
for (int i = 0; i < portSelector->count(); ++i) {
|
|
assert(portSelector->itemText(i).startsWith(QStringLiteral("/dev/")));
|
|
assert(!portSelector->itemText(i).trimmed().isEmpty());
|
|
}
|
|
assert(map != nullptr);
|
|
assert(mainViewTabs != nullptr);
|
|
assert(mainViewTabs->count() == 2);
|
|
assert(sideSplitter != nullptr);
|
|
assert(sideSplitter->orientation() == Qt::Vertical);
|
|
assert(rinexUpdateButton != nullptr);
|
|
assert(!rinexUpdateButton->toolTip().isEmpty());
|
|
assert(openLogAction != nullptr && !openLogAction->shortcut().isEmpty());
|
|
assert(toggleSerialAction != nullptr && !toggleSerialAction->shortcut().isEmpty());
|
|
assert(rinexUpdateAction != nullptr && !rinexUpdateAction->shortcut().isEmpty());
|
|
|
|
QVector<TelemetryPoint> followPoints;
|
|
TelemetryPoint gpsPoint;
|
|
gpsPoint.source = LocationSource::Gps;
|
|
gpsPoint.latitude = 40.0;
|
|
gpsPoint.longitude = 29.0;
|
|
followPoints.push_back(gpsPoint);
|
|
TelemetryPoint correctedPoint = gpsPoint;
|
|
correctedPoint.source = LocationSource::ImuCorrected;
|
|
correctedPoint.latitude = 40.25;
|
|
correctedPoint.longitude = 29.5;
|
|
followPoints.push_back(correctedPoint);
|
|
TelemetryPoint trajectoryPoint = gpsPoint;
|
|
trajectoryPoint.source = LocationSource::Trajectory;
|
|
trajectoryPoint.latitude = 41.0;
|
|
trajectoryPoint.longitude = 30.0;
|
|
followPoints.push_back(trajectoryPoint);
|
|
map->setPoints(followPoints);
|
|
assert(std::abs(map->centerCoordinate().x() - 40.25) < 0.000001);
|
|
assert(std::abs(map->centerCoordinate().y() - 29.5) < 0.000001);
|
|
map->clearPoints();
|
|
|
|
sendLine(window, QStringLiteral("[TRK] tracked satellites=2 prn_indices=[2,7]"));
|
|
assert(map != nullptr);
|
|
auto *globe = window.findChild<GlobeWidget *>();
|
|
assert(globe != nullptr);
|
|
assert(globe->observedPrns()
|
|
== QSet<QString>({QStringLiteral("G03"), QStringLiteral("G08")}));
|
|
sendLine(window, QStringLiteral("[TRK] tracked satellites=1 prn_indices=[13]"));
|
|
assert(globe->observedPrns() == QSet<QString>({QStringLiteral("G14")}));
|
|
|
|
assert(QMetaObject::invokeMethod(map, "referenceLocationSelected", Qt::DirectConnection,
|
|
Q_ARG(double, 40.25), Q_ARG(double, 29.5)));
|
|
assert(referenceLatInput->text() == QStringLiteral("40.250000000000000"));
|
|
assert(referenceLonInput->text() == QStringLiteral("29.500000000000000"));
|
|
referenceLatInput->clear();
|
|
referenceLonInput->clear();
|
|
assert(QMetaObject::invokeMethod(&window, "updateReferenceLocation", Qt::DirectConnection));
|
|
showTelemetry->setChecked(false);
|
|
assert(!showRecentPoints->isEnabled());
|
|
assert(!showAverage->isEnabled());
|
|
showTelemetry->setChecked(true);
|
|
assert(showRecentPoints->isEnabled());
|
|
assert(showAverage->isEnabled());
|
|
|
|
sendLine(window, QStringLiteral("lattitude : 40.78925034214206846173"));
|
|
sendLine(window, QStringLiteral("longitude : 29.46277530841727809729"));
|
|
assert(table->model()->rowCount() == 0);
|
|
|
|
sendLine(window, QStringLiteral("NAV solve done"));
|
|
flushUpdates(window);
|
|
assert(table->model()->rowCount() == 1);
|
|
assert(table->model()->data(table->model()->index(0, 2)).toString()
|
|
== QStringLiteral("40.78925034214206846173"));
|
|
assert(table->model()->data(table->model()->index(0, 3)).toString()
|
|
== QStringLiteral("29.46277530841727809729"));
|
|
|
|
sendLine(window, QStringLiteral(
|
|
"[LOCATION] source=gps lat=40.1 lon=29.1 height=100 gdop=2 pdop=1.5 "
|
|
"hdop=1 vdop=1.2 tdop=0.8 tracked=5 used=5"));
|
|
sendLine(window, QStringLiteral(
|
|
"[LOCATION] source=imu_corrected lat=40.10001 lon=29.10001 height=100.2 "
|
|
"gdop=2 pdop=1.5 hdop=1 vdop=1.2 tdop=0.8 tracked=5 used=5"));
|
|
flushUpdates(window);
|
|
assert(table->model()->rowCount() == 3);
|
|
assert(table->model()->data(table->model()->index(1, 1)).toString()
|
|
== QStringLiteral("GPS"));
|
|
assert(table->model()->data(table->model()->index(2, 1)).toString()
|
|
== QStringLiteral("IMU corrected"));
|
|
sendLine(window, QStringLiteral(
|
|
"[LOCATION] source=trajectory lat=40.10002 lon=29.10002 height=100 tracked=4 used=4"));
|
|
flushUpdates(window);
|
|
assert(table->model()->rowCount() == 4);
|
|
assert(table->model()->data(table->model()->index(3, 1)).toString()
|
|
== QStringLiteral("Trajectory (truth)"));
|
|
|
|
QTemporaryFile replayLog;
|
|
assert(replayLog.open());
|
|
replayLog.write(
|
|
"[LOCATION] source=trajectory lat=40.0 lon=29.0 height=100 tracked=4 used=4\n"
|
|
"[LOCATION] source=gps lat=40.0001 lon=29.0001 height=104 tracked=4 used=4\n"
|
|
"[LOCATION] source=imu_corrected lat=40.00002 lon=29.00002 height=101 tracked=4 used=4\n");
|
|
replayLog.flush();
|
|
assert(window.loadTelemetryLog(replayLog.fileName()));
|
|
assert(table->model()->rowCount() == 3);
|
|
assert(table->model()->data(table->model()->index(0, 1)).toString()
|
|
== QStringLiteral("Trajectory (truth)"));
|
|
|
|
QTemporaryFile splitReplayLog;
|
|
assert(splitReplayLog.open());
|
|
splitReplayLog.write("latitude: 40.25\nlongitude: 29.50\n");
|
|
splitReplayLog.flush();
|
|
assert(window.loadTelemetryLog(splitReplayLog.fileName()));
|
|
assert(table->model()->rowCount() == 1);
|
|
|
|
// A partial fix from an earlier solve must not be completed using a field
|
|
// from the following solve.
|
|
assert(QMetaObject::invokeMethod(&window, "clearPoints", Qt::DirectConnection));
|
|
sendLine(window, QStringLiteral("NAV solve start"));
|
|
sendLine(window, QStringLiteral("latitude: 40.0"));
|
|
sendLine(window, QStringLiteral("NAV solve start"));
|
|
sendLine(window, QStringLiteral("longitude: 29.0"));
|
|
sendLine(window, QStringLiteral("NAV solve done"));
|
|
flushUpdates(window);
|
|
assert(table->model()->rowCount() == 0);
|
|
|
|
assert(QMetaObject::invokeMethod(&window, "clearPoints", Qt::DirectConnection));
|
|
sendLine(window, QStringLiteral(
|
|
"lat=40.78925034214206846173 long=29.46277530841727809729"));
|
|
flushUpdates(window);
|
|
assert(table->model()->rowCount() == 1);
|
|
|
|
referenceLatInput->setText(QStringLiteral("40.78925034214206846173"));
|
|
referenceLonInput->setText(QStringLiteral("29.46277530841727809729"));
|
|
const bool referenceUpdated = QMetaObject::invokeMethod(
|
|
&window, "updateReferenceLocation", Qt::DirectConnection);
|
|
assert(referenceUpdated);
|
|
assert(cepValue->text().startsWith(QStringLiteral("0.00 m")));
|
|
assert(cepValue->text().contains(QStringLiteral("N=1")));
|
|
|
|
const bool cleared = QMetaObject::invokeMethod(&window, "clearPoints", Qt::DirectConnection);
|
|
assert(cleared);
|
|
assert(table->model()->rowCount() == 0);
|
|
assert(referenceLatInput->text() == QStringLiteral("40.78925034214206846173"));
|
|
assert(referenceLonInput->text() == QStringLiteral("29.46277530841727809729"));
|
|
assert(cepValue->text() == QStringLiteral("-"));
|
|
|
|
referenceLatInput->setText(QStringLiteral("40.0"));
|
|
referenceLonInput->setText(QStringLiteral("29.0"));
|
|
assert(QMetaObject::invokeMethod(&window, "updateReferenceLocation", Qt::DirectConnection));
|
|
sendLine(window, QStringLiteral("lat=40.000 long=29.000"));
|
|
sendLine(window, QStringLiteral("lat=40.001 long=29.000"));
|
|
sendLine(window, QStringLiteral("lat=40.002 long=29.000"));
|
|
flushUpdates(window);
|
|
assert(cepValue->text().startsWith(QStringLiteral("111 m")));
|
|
assert(cepValue->text().contains(QStringLiteral("N=3")));
|
|
assert(QMetaObject::invokeMethod(&window, "clearPoints", Qt::DirectConnection));
|
|
|
|
referenceLatInput->setText(QStringLiteral("40.78925034214206846173"));
|
|
referenceLonInput->setText(QStringLiteral("29.46277530841727809729"));
|
|
assert(QMetaObject::invokeMethod(&window, "updateReferenceLocation", Qt::DirectConnection));
|
|
|
|
maxPointsInput->setValue(10000);
|
|
for (int i = 0; i < 10000; ++i) {
|
|
sendLine(window, QStringLiteral("lat=40.78925 long=29.46277 sats=7"));
|
|
}
|
|
flushUpdates(window);
|
|
assert(table->model()->rowCount() == 10000);
|
|
assert(cepValue->text().contains(QStringLiteral("N=10000")));
|
|
assert(QMetaObject::invokeMethod(&window, "clearPoints", Qt::DirectConnection));
|
|
maxPointsInput->setValue(10);
|
|
|
|
{
|
|
MapWidget followMap;
|
|
TelemetryPoint corrected;
|
|
corrected.source = LocationSource::ImuCorrected;
|
|
corrected.latitude = 40.1;
|
|
corrected.longitude = 29.1;
|
|
corrected.receivedAt = QDateTime::currentDateTimeUtc();
|
|
|
|
TelemetryPoint rawGps;
|
|
rawGps.source = LocationSource::Gps;
|
|
rawGps.latitude = 41.0;
|
|
rawGps.longitude = 30.0;
|
|
rawGps.receivedAt = corrected.receivedAt.addMSecs(100);
|
|
followMap.setPoints({corrected, rawGps});
|
|
assert(followMap.centerCoordinate() == QPointF(40.1, 29.1));
|
|
|
|
rawGps.receivedAt = corrected.receivedAt.addMSecs(1100);
|
|
followMap.setPoints({corrected, rawGps});
|
|
assert(followMap.centerCoordinate() == QPointF(41.0, 30.0));
|
|
}
|
|
|
|
const QByteArray screenshotPath = qgetenv("LOCATION_PLOTTER_TEST_SCREENSHOT");
|
|
if (!screenshotPath.isEmpty()) {
|
|
sendLine(window, QStringLiteral("NAV solve start sats:5"));
|
|
sendLine(window, QStringLiteral("tracking PRNs: G03, G08, G14, G21, G27"));
|
|
sendLine(window, QStringLiteral(
|
|
"lat=40.78925034214206846173 long=29.46277530841727809729 "
|
|
"hheight=-89.05779508221894502640 sats=7 PDOP=1.235"));
|
|
flushUpdates(window);
|
|
mainViewTabs->setCurrentIndex(1);
|
|
window.show();
|
|
app.processEvents();
|
|
window.repaint();
|
|
app.processEvents();
|
|
assert(window.grab().save(QString::fromLocal8Bit(screenshotPath), "PNG"));
|
|
}
|
|
|
|
return 0;
|
|
}
|