mirror of
https://github.com/f4exb/sdrangel.git
synced 2024-11-26 09:48:45 -05:00
VOR Localizer: Send radials and estimated position to Map feature
This commit is contained in:
parent
9c7aa8b333
commit
60a3dfcee7
@ -50,6 +50,8 @@
|
|||||||
#include "vorlocalizersettings.h"
|
#include "vorlocalizersettings.h"
|
||||||
#include "vorlocalizergui.h"
|
#include "vorlocalizergui.h"
|
||||||
|
|
||||||
|
#include "SWGMapItem.h"
|
||||||
|
|
||||||
// Lats and longs in decimal degrees. Distance in metres. Bearing in degrees.
|
// Lats and longs in decimal degrees. Distance in metres. Bearing in degrees.
|
||||||
// https://www.movable-type.co.uk/scripts/latlong.html
|
// https://www.movable-type.co.uk/scripts/latlong.html
|
||||||
static void calcRadialEndPoint(float startLatitude, float startLongitude, float distance, float bearing, float &endLatitude, float &endLongitude)
|
static void calcRadialEndPoint(float startLatitude, float startLongitude, float distance, float bearing, float &endLatitude, float &endLongitude)
|
||||||
@ -351,6 +353,18 @@ bool VORModel::findIntersection(float &lat, float &lon)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString VORModel::getRadials() const
|
||||||
|
{
|
||||||
|
QStringList text;
|
||||||
|
for (int i = 0; i < m_vors.size(); i++)
|
||||||
|
{
|
||||||
|
if (m_radials[i] >= 0) {
|
||||||
|
text.append(QString("%1: %2%3").arg(m_vors[i]->m_name).arg(std::round(m_radials[i])).arg(QChar(0xb0)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return text.join("\n");
|
||||||
|
}
|
||||||
|
|
||||||
void VORLocalizerGUI::resizeTable()
|
void VORLocalizerGUI::resizeTable()
|
||||||
{
|
{
|
||||||
// Fill table with a row of dummy data that will size the columns nicely
|
// Fill table with a row of dummy data that will size the columns nicely
|
||||||
@ -462,6 +476,8 @@ void VORLocalizerGUI::selectVOR(VORGUI *vorGUI, bool selected)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
QString radialName = QString("VOR Radial %1").arg(vorGUI->m_navAid->m_name);
|
||||||
|
|
||||||
VORLocalizer::MsgRemoveVORChannel *msg = VORLocalizer::MsgRemoveVORChannel::create(navId);
|
VORLocalizer::MsgRemoveVORChannel *msg = VORLocalizer::MsgRemoveVORChannel::create(navId);
|
||||||
m_vorLocalizer->getInputMessageQueue()->push(msg);
|
m_vorLocalizer->getInputMessageQueue()->push(msg);
|
||||||
|
|
||||||
@ -470,6 +486,10 @@ void VORLocalizerGUI::selectVOR(VORGUI *vorGUI, bool selected)
|
|||||||
// Remove from settings to remove corresponding demodulator
|
// Remove from settings to remove corresponding demodulator
|
||||||
m_settings.m_subChannelSettings.remove(navId);
|
m_settings.m_subChannelSettings.remove(navId);
|
||||||
|
|
||||||
|
// Remove radial from Map feature
|
||||||
|
m_mapFeatureRadialNames.removeOne(radialName);
|
||||||
|
clearFromMapFeature(radialName, 3);
|
||||||
|
|
||||||
applySettings();
|
applySettings();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -479,7 +499,7 @@ void VORLocalizerGUI::updateVORs()
|
|||||||
m_vorModel.removeAllVORs();
|
m_vorModel.removeAllVORs();
|
||||||
AzEl azEl = m_azEl;
|
AzEl azEl = m_azEl;
|
||||||
|
|
||||||
for (auto vor : m_vors)
|
for (const auto vor : *m_vors)
|
||||||
{
|
{
|
||||||
if (vor->m_type.contains("VOR")) // Exclude DMEs
|
if (vor->m_type.contains("VOR")) // Exclude DMEs
|
||||||
{
|
{
|
||||||
@ -534,6 +554,130 @@ bool VORLocalizerGUI::deserialize(const QByteArray& data)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VORLocalizerGUI::clearFromMapFeature(const QString& name, int type)
|
||||||
|
{
|
||||||
|
QList<ObjectPipe*> mapPipes;
|
||||||
|
MainCore::instance()->getMessagePipes().getMessagePipes(m_vorLocalizer, "mapitems", mapPipes);
|
||||||
|
for (const auto& pipe : mapPipes)
|
||||||
|
{
|
||||||
|
MessageQueue *messageQueue = qobject_cast<MessageQueue*>(pipe->m_element);
|
||||||
|
SWGSDRangel::SWGMapItem *swgMapItem = new SWGSDRangel::SWGMapItem();
|
||||||
|
swgMapItem->setName(new QString(name));
|
||||||
|
swgMapItem->setImage(new QString(""));
|
||||||
|
swgMapItem->setType(type);
|
||||||
|
MainCore::MsgMapItem *msg = MainCore::MsgMapItem::create(m_vorLocalizer, swgMapItem);
|
||||||
|
messageQueue->push(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VORLocalizerGUI::sendPositionToMapFeature(float lat, float lon)
|
||||||
|
{
|
||||||
|
// Send to Map feature
|
||||||
|
QList<ObjectPipe*> mapPipes;
|
||||||
|
MainCore::instance()->getMessagePipes().getMessagePipes(m_vorLocalizer, "mapitems", mapPipes);
|
||||||
|
|
||||||
|
if (mapPipes.size() > 0)
|
||||||
|
{
|
||||||
|
QString name = MainCore::instance()->getSettings().getStationName();
|
||||||
|
if (name != m_mapFeaturePositionName)
|
||||||
|
{
|
||||||
|
clearFromMapFeature(m_mapFeaturePositionName, 0);
|
||||||
|
m_mapFeaturePositionName = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString details = QString("%1\nEstimated position based on VORs\n").arg(name);
|
||||||
|
details.append(m_vorModel.getRadials());
|
||||||
|
|
||||||
|
for (const auto& pipe : mapPipes)
|
||||||
|
{
|
||||||
|
MessageQueue *messageQueue = qobject_cast<MessageQueue*>(pipe->m_element);
|
||||||
|
SWGSDRangel::SWGMapItem *swgMapItem = new SWGSDRangel::SWGMapItem();
|
||||||
|
|
||||||
|
swgMapItem->setName(new QString(name));
|
||||||
|
swgMapItem->setLatitude(lat);
|
||||||
|
swgMapItem->setLongitude(lon);
|
||||||
|
swgMapItem->setAltitude(0);
|
||||||
|
swgMapItem->setImage(new QString("antenna.png"));
|
||||||
|
swgMapItem->setImageRotation(0);
|
||||||
|
swgMapItem->setText(new QString(details));
|
||||||
|
swgMapItem->setModel(new QString("antenna.glb"));
|
||||||
|
swgMapItem->setFixedPosition(false);
|
||||||
|
swgMapItem->setLabel(new QString(name));
|
||||||
|
swgMapItem->setLabelAltitudeOffset(4.5);
|
||||||
|
swgMapItem->setAltitudeReference(1);
|
||||||
|
swgMapItem->setType(0);
|
||||||
|
|
||||||
|
MainCore::MsgMapItem *msg = MainCore::MsgMapItem::create(m_vorLocalizer, swgMapItem);
|
||||||
|
messageQueue->push(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VORLocalizerGUI::sendRadialToMapFeature(VORGUI *vorGUI, Real radial)
|
||||||
|
{
|
||||||
|
// Send to Map feature
|
||||||
|
QList<ObjectPipe*> mapPipes;
|
||||||
|
MainCore::instance()->getMessagePipes().getMessagePipes(m_vorLocalizer, "mapitems", mapPipes);
|
||||||
|
|
||||||
|
if (mapPipes.size() > 0)
|
||||||
|
{
|
||||||
|
float endLat, endLong;
|
||||||
|
float bearing;
|
||||||
|
|
||||||
|
if (m_settings.m_magDecAdjust && !vorGUI->m_navAid->m_alignedTrueNorth) {
|
||||||
|
bearing = radial - vorGUI->m_navAid->m_magneticDeclination;
|
||||||
|
} else {
|
||||||
|
bearing = radial;
|
||||||
|
}
|
||||||
|
|
||||||
|
calcRadialEndPoint(vorGUI->m_navAid->m_latitude, vorGUI->m_navAid->m_longitude, vorGUI->m_navAid->getRangeMetres(), bearing, endLat, endLong);
|
||||||
|
|
||||||
|
QString name = QString("VOR Radial %1").arg(vorGUI->m_navAid->m_name);
|
||||||
|
QString details = QString("%1%2").arg(std::round(bearing)).arg(QChar(0x00b0));
|
||||||
|
|
||||||
|
if (!m_mapFeatureRadialNames.contains(name)) {
|
||||||
|
m_mapFeatureRadialNames.append(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& pipe : mapPipes)
|
||||||
|
{
|
||||||
|
MessageQueue *messageQueue = qobject_cast<MessageQueue*>(pipe->m_element);
|
||||||
|
SWGSDRangel::SWGMapItem *swgMapItem = new SWGSDRangel::SWGMapItem();
|
||||||
|
|
||||||
|
swgMapItem->setName(new QString(name));
|
||||||
|
swgMapItem->setLatitude(vorGUI->m_navAid->m_latitude);
|
||||||
|
swgMapItem->setLongitude(vorGUI->m_navAid->m_longitude);
|
||||||
|
swgMapItem->setAltitude(Units::feetToMetres(vorGUI->m_navAid->m_elevation));
|
||||||
|
QString image = QString("none");
|
||||||
|
swgMapItem->setImage(new QString(image));
|
||||||
|
swgMapItem->setImageRotation(0);
|
||||||
|
swgMapItem->setText(new QString(details)); // Not used - label is used instead for now
|
||||||
|
//swgMapItem->setFixedPosition(true);
|
||||||
|
swgMapItem->setLabel(new QString(details));
|
||||||
|
swgMapItem->setAltitudeReference(0);
|
||||||
|
QList<SWGSDRangel::SWGMapCoordinate *> *coords = new QList<SWGSDRangel::SWGMapCoordinate *>();
|
||||||
|
|
||||||
|
SWGSDRangel::SWGMapCoordinate* c = new SWGSDRangel::SWGMapCoordinate();
|
||||||
|
c->setLatitude(vorGUI->m_navAid->m_latitude);
|
||||||
|
c->setLongitude(vorGUI->m_navAid->m_longitude); // Centre of VOR
|
||||||
|
c->setAltitude(Units::feetToMetres(vorGUI->m_navAid->m_elevation));
|
||||||
|
coords->append(c);
|
||||||
|
|
||||||
|
c = new SWGSDRangel::SWGMapCoordinate();
|
||||||
|
c->setLatitude(endLat);
|
||||||
|
c->setLongitude(endLong);
|
||||||
|
c->setAltitude(Units::feetToMetres(vorGUI->m_navAid->m_elevation));
|
||||||
|
coords->append(c);
|
||||||
|
|
||||||
|
swgMapItem->setCoordinates(coords);
|
||||||
|
swgMapItem->setType(3);
|
||||||
|
|
||||||
|
MainCore::MsgMapItem *msg = MainCore::MsgMapItem::create(m_vorLocalizer, swgMapItem);
|
||||||
|
messageQueue->push(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool VORLocalizerGUI::handleMessage(const Message& message)
|
bool VORLocalizerGUI::handleMessage(const Message& message)
|
||||||
{
|
{
|
||||||
if (VORLocalizer::MsgConfigureVORLocalizer::match(message))
|
if (VORLocalizer::MsgConfigureVORLocalizer::match(message))
|
||||||
@ -598,6 +742,31 @@ bool VORLocalizerGUI::handleMessage(const Message& message)
|
|||||||
|
|
||||||
// Update radial on map
|
// Update radial on map
|
||||||
m_vorModel.setRadial(subChannelId, validRadial, report.getRadial());
|
m_vorModel.setRadial(subChannelId, validRadial, report.getRadial());
|
||||||
|
|
||||||
|
// Send to map feature as well
|
||||||
|
sendRadialToMapFeature(vorGUI, report.getRadial());
|
||||||
|
|
||||||
|
// Try to determine position, based on intersection of two radials
|
||||||
|
float lat, lon;
|
||||||
|
|
||||||
|
if (m_vorModel.findIntersection(lat, lon))
|
||||||
|
{
|
||||||
|
// Move antenna icon to estimated position
|
||||||
|
QQuickItem *item = ui->map->rootObject();
|
||||||
|
QObject *stationObject = item->findChild<QObject*>("station");
|
||||||
|
|
||||||
|
if (stationObject != NULL)
|
||||||
|
{
|
||||||
|
QGeoCoordinate coords = stationObject->property("coordinate").value<QGeoCoordinate>();
|
||||||
|
coords.setLatitude(lat);
|
||||||
|
coords.setLongitude(lon);
|
||||||
|
stationObject->setProperty("coordinate", QVariant::fromValue(coords));
|
||||||
|
stationObject->setProperty("stationName", QVariant::fromValue(MainCore::instance()->getSettings().getStationName()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send estimated position to Map Feature as well
|
||||||
|
sendPositionToMapFeature(lat, lon);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -738,7 +907,7 @@ void VORLocalizerGUI::on_getOpenAIPVORDB_clicked()
|
|||||||
|
|
||||||
void VORLocalizerGUI::readNavAids()
|
void VORLocalizerGUI::readNavAids()
|
||||||
{
|
{
|
||||||
m_vors = OpenAIP::readNavAids();
|
m_vors = OpenAIP::getNavAids();
|
||||||
updateVORs();
|
updateVORs();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1052,10 +1221,13 @@ VORLocalizerGUI::VORLocalizerGUI(PluginAPI* pluginAPI, FeatureUISet *featureUISe
|
|||||||
|
|
||||||
VORLocalizerGUI::~VORLocalizerGUI()
|
VORLocalizerGUI::~VORLocalizerGUI()
|
||||||
{
|
{
|
||||||
|
clearFromMapFeature(m_mapFeaturePositionName, 0);
|
||||||
|
for (auto const &radialName : m_mapFeatureRadialNames) {
|
||||||
|
clearFromMapFeature(radialName, 3);
|
||||||
|
}
|
||||||
disconnect(&m_redrawMapTimer, &QTimer::timeout, this, &VORLocalizerGUI::redrawMap);
|
disconnect(&m_redrawMapTimer, &QTimer::timeout, this, &VORLocalizerGUI::redrawMap);
|
||||||
m_redrawMapTimer.stop();
|
m_redrawMapTimer.stop();
|
||||||
delete ui;
|
delete ui;
|
||||||
qDeleteAll(m_vors);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void VORLocalizerGUI::setWorkspaceIndex(int index)
|
void VORLocalizerGUI::setWorkspaceIndex(int index)
|
||||||
@ -1145,27 +1317,8 @@ void VORLocalizerGUI::updateStatus()
|
|||||||
|
|
||||||
void VORLocalizerGUI::tick()
|
void VORLocalizerGUI::tick()
|
||||||
{
|
{
|
||||||
// Try to determine position, based on intersection of two radials - every second
|
|
||||||
if (++m_tickCount == 20)
|
if (++m_tickCount == 20)
|
||||||
{
|
{
|
||||||
float lat, lon;
|
|
||||||
|
|
||||||
if (m_vorModel.findIntersection(lat, lon))
|
|
||||||
{
|
|
||||||
// Move antenna icon to estimated position
|
|
||||||
QQuickItem *item = ui->map->rootObject();
|
|
||||||
QObject *stationObject = item->findChild<QObject*>("station");
|
|
||||||
|
|
||||||
if (stationObject != NULL)
|
|
||||||
{
|
|
||||||
QGeoCoordinate coords = stationObject->property("coordinate").value<QGeoCoordinate>();
|
|
||||||
coords.setLatitude(lat);
|
|
||||||
coords.setLongitude(lon);
|
|
||||||
stationObject->setProperty("coordinate", QVariant::fromValue(coords));
|
|
||||||
stationObject->setProperty("stationName", QVariant::fromValue(MainCore::instance()->getSettings().getStationName()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_rrSecondsCount++;
|
m_rrSecondsCount++;
|
||||||
ui->rrTurnTimeProgress->setMaximum(m_settings.m_rrTime);
|
ui->rrTurnTimeProgress->setMaximum(m_settings.m_rrTime);
|
||||||
ui->rrTurnTimeProgress->setValue(m_rrSecondsCount <= m_settings.m_rrTime ? m_rrSecondsCount : m_settings.m_rrTime);
|
ui->rrTurnTimeProgress->setValue(m_rrSecondsCount <= m_settings.m_rrTime ? m_rrSecondsCount : m_settings.m_rrTime);
|
||||||
@ -1286,3 +1439,4 @@ void VORLocalizerGUI::makeUIConnections()
|
|||||||
QObject::connect(ui->rrTime, &QDial::valueChanged, this, &VORLocalizerGUI::on_rrTime_valueChanged);
|
QObject::connect(ui->rrTime, &QDial::valueChanged, this, &VORLocalizerGUI::on_rrTime_valueChanged);
|
||||||
QObject::connect(ui->centerShift, &QDial::valueChanged, this, &VORLocalizerGUI::on_centerShift_valueChanged);
|
QObject::connect(ui->centerShift, &QDial::valueChanged, this, &VORLocalizerGUI::on_centerShift_valueChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -191,6 +191,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool findIntersection(float &lat, float &lon);
|
bool findIntersection(float &lat, float &lon);
|
||||||
|
QString getRadials() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
VORLocalizerGUI *m_gui;
|
VORLocalizerGUI *m_gui;
|
||||||
@ -242,7 +243,7 @@ private:
|
|||||||
OpenAIP m_openAIP;
|
OpenAIP m_openAIP;
|
||||||
int m_countryIndex;
|
int m_countryIndex;
|
||||||
VORModel m_vorModel;
|
VORModel m_vorModel;
|
||||||
QList<NavAid *> m_vors;
|
QSharedPointer<const QList<NavAid *>> m_vors;
|
||||||
QHash<int, VORGUI *> m_selectedVORs;
|
QHash<int, VORGUI *> m_selectedVORs;
|
||||||
AzEl m_azEl; // Position of station
|
AzEl m_azEl; // Position of station
|
||||||
QIcon m_muteIcon;
|
QIcon m_muteIcon;
|
||||||
@ -250,6 +251,8 @@ private:
|
|||||||
int m_lastFeatureState;
|
int m_lastFeatureState;
|
||||||
int m_rrSecondsCount;
|
int m_rrSecondsCount;
|
||||||
QTimer m_redrawMapTimer;
|
QTimer m_redrawMapTimer;
|
||||||
|
QString m_mapFeaturePositionName;
|
||||||
|
QStringList m_mapFeatureRadialNames;
|
||||||
|
|
||||||
explicit VORLocalizerGUI(PluginAPI* pluginAPI, FeatureUISet *featureUISet, Feature *feature, QWidget* parent = nullptr);
|
explicit VORLocalizerGUI(PluginAPI* pluginAPI, FeatureUISet *featureUISet, Feature *feature, QWidget* parent = nullptr);
|
||||||
virtual ~VORLocalizerGUI();
|
virtual ~VORLocalizerGUI();
|
||||||
@ -270,6 +273,9 @@ private:
|
|||||||
void readNavAids();
|
void readNavAids();
|
||||||
void updateChannelList();
|
void updateChannelList();
|
||||||
void applyMapSettings();
|
void applyMapSettings();
|
||||||
|
void clearFromMapFeature(const QString& name, int type);
|
||||||
|
void sendPositionToMapFeature(float lat, float lon);
|
||||||
|
void sendRadialToMapFeature(VORGUI *vorGUI, Real radial);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void on_startStop_toggled(bool checked);
|
void on_startStop_toggled(bool checked);
|
||||||
@ -296,3 +302,4 @@ private slots:
|
|||||||
};
|
};
|
||||||
|
|
||||||
#endif // INCLUDE_VORLOCALIZERGUI_H
|
#endif // INCLUDE_VORLOCALIZERGUI_H
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user