ADS-B Demod Updates

Add support for animated 3D models.
Downloaded zipped airplane database as 1/4 of the size.
Add table context menu.
Add airline and country images to text bubbles on maps.
Fix calculation of ground speed when on surface.
Fix position calculation when aircraft transistions from surface to air.
Fix altitude calculation when Q-bit is set.
Speed up processing of large log files.
Add new airline logos.
This commit is contained in:
Jon Beniston 2022-02-04 16:57:45 +00:00
parent 7b6708a256
commit 97f55be6e9
58 changed files with 1928 additions and 493 deletions

View File

@ -29,6 +29,7 @@ set(adsb_HEADERS
include_directories(
${CMAKE_SOURCE_DIR}/swagger/sdrangel/code/qt5/client
${Boost_INCLUDE_DIRS}
${Qt5Gui_PRIVATE_INCLUDE_DIRS}
)
if(NOT SERVER_MODE)
@ -94,3 +95,8 @@ if(WIN32)
include(DeployQt)
windeployqt(${TARGET_NAME} ${SDRANGEL_BINARY_BIN_DIR} ${PROJECT_SOURCE_DIR}/map)
endif()
# Install debug symbols
if (WIN32)
install(FILES $<TARGET_PDB_FILE:${TARGET_NAME}> CONFIGURATIONS Debug RelWithDebInfo DESTINATION ${INSTALL_FOLDER} )
endif()

View File

@ -20,36 +20,35 @@
#include "adsbdemoddisplaydialog.h"
ADSBDemodDisplayDialog::ADSBDemodDisplayDialog(
int removeTimeout, float airportRange, ADSBDemodSettings::AirportType airportMinimumSize,
bool displayHeliports, bool siUnits, QString fontName, int fontSize, bool displayDemodStats,
bool autoResizeTableColumns, const QString& apiKey, QStringList airspaces, float airspaceRange,
ADSBDemodSettings::MapType mapType, bool displayNavAids, bool displayPhotos, QWidget* parent) :
ADSBDemodDisplayDialog::ADSBDemodDisplayDialog(ADSBDemodSettings *settings, QWidget* parent) :
QDialog(parent),
m_fontName(fontName),
m_fontSize(fontSize),
ui(new Ui::ADSBDemodDisplayDialog)
ui(new Ui::ADSBDemodDisplayDialog),
m_settings(settings),
m_fontName(settings->m_tableFontName),
m_fontSize(settings->m_tableFontSize)
{
ui->setupUi(this);
ui->timeout->setValue(removeTimeout);
ui->airportRange->setValue(airportRange);
ui->airportSize->setCurrentIndex((int)airportMinimumSize);
ui->heliports->setChecked(displayHeliports);
ui->units->setCurrentIndex((int)siUnits);
ui->displayStats->setChecked(displayDemodStats);
ui->autoResizeTableColumns->setChecked(autoResizeTableColumns);
ui->apiKey->setText(apiKey);
for (const auto& airspace: airspaces)
ui->timeout->setValue(settings->m_removeTimeout);
ui->airportRange->setValue(settings->m_airportRange);
ui->airportSize->setCurrentIndex((int)settings->m_airportMinimumSize);
ui->heliports->setChecked(settings->m_displayHeliports);
ui->units->setCurrentIndex((int)settings->m_siUnits);
ui->displayStats->setChecked(settings->m_displayDemodStats);
ui->autoResizeTableColumns->setChecked(settings->m_autoResizeTableColumns);
ui->apiKey->setText(settings->m_apiKey);
for (const auto& airspace: settings->m_airspaces)
{
QList<QListWidgetItem *> items = ui->airspaces->findItems(airspace, Qt::MatchExactly);
for (const auto& item: items) {
item->setCheckState(Qt::Checked);
}
}
ui->airspaceRange->setValue(airspaceRange);
ui->mapType->setCurrentIndex((int)mapType);
ui->navAids->setChecked(displayNavAids);
ui->photos->setChecked(displayPhotos);
ui->airspaceRange->setValue(settings->m_airspaceRange);
ui->mapType->setCurrentIndex((int)settings->m_mapType);
ui->navAids->setChecked(settings->m_displayNavAids);
ui->photos->setChecked(settings->m_displayPhotos);
ui->verboseModelMatching->setChecked(settings->m_verboseModelMatching);
ui->airfieldElevation->setValue(settings->m_airfieldElevation);
}
ADSBDemodDisplayDialog::~ADSBDemodDisplayDialog()
@ -59,26 +58,30 @@ ADSBDemodDisplayDialog::~ADSBDemodDisplayDialog()
void ADSBDemodDisplayDialog::accept()
{
m_removeTimeout = ui->timeout->value();
m_airportRange = ui->airportRange->value();
m_airportMinimumSize = (ADSBDemodSettings::AirportType)ui->airportSize->currentIndex();
m_displayHeliports = ui->heliports->isChecked();
m_siUnits = ui->units->currentIndex() == 0 ? false : true;
m_displayDemodStats = ui->displayStats->isChecked();
m_autoResizeTableColumns = ui->autoResizeTableColumns->isChecked();
m_apiKey = ui->apiKey->text();
m_airspaces = QStringList();
m_settings->m_removeTimeout = ui->timeout->value();
m_settings->m_airportRange = ui->airportRange->value();
m_settings->m_airportMinimumSize = (ADSBDemodSettings::AirportType)ui->airportSize->currentIndex();
m_settings->m_displayHeliports = ui->heliports->isChecked();
m_settings->m_siUnits = ui->units->currentIndex() == 0 ? false : true;
m_settings->m_displayDemodStats = ui->displayStats->isChecked();
m_settings->m_autoResizeTableColumns = ui->autoResizeTableColumns->isChecked();
m_settings->m_apiKey = ui->apiKey->text();
m_settings->m_airspaces = QStringList();
for (int i = 0; i < ui->airspaces->count(); i++)
{
QListWidgetItem *item = ui->airspaces->item(i);
if (item->checkState() == Qt::Checked) {
m_airspaces.append(item->text());
m_settings->m_airspaces.append(item->text());
}
}
m_airspaceRange = ui->airspaceRange->value();
m_mapType = (ADSBDemodSettings::MapType)ui->mapType->currentIndex();
m_displayNavAids = ui->navAids->isChecked();
m_displayPhotos = ui->photos->isChecked();
m_settings->m_airspaceRange = ui->airspaceRange->value();
m_settings->m_mapType = (ADSBDemodSettings::MapType)ui->mapType->currentIndex();
m_settings->m_displayNavAids = ui->navAids->isChecked();
m_settings->m_displayPhotos = ui->photos->isChecked();
m_settings->m_verboseModelMatching = ui->verboseModelMatching->isChecked();
m_settings->m_airfieldElevation = ui->airfieldElevation->value();
m_settings->m_tableFontName = m_fontName;
m_settings->m_tableFontSize = m_fontSize;
QDialog::accept();
}
@ -88,7 +91,6 @@ void ADSBDemodDisplayDialog::on_font_clicked()
QFont font = QFontDialog::getFont(&ok, QFont(m_fontName, m_fontSize), this);
if (ok)
{
qDebug() << font;
m_fontName = font.family();
m_fontSize = font.pointSize();
}

View File

@ -25,34 +25,18 @@ class ADSBDemodDisplayDialog : public QDialog {
Q_OBJECT
public:
explicit ADSBDemodDisplayDialog(int removeTimeout, float airportRange, ADSBDemodSettings::AirportType airportMinimumSize,
bool displayHeliports, bool siUnits, QString fontName, int fontSize, bool displayDemodStats,
bool autoResizeTableColumns, const QString& apiKey, QStringList airspaces, float airspaceRange,
ADSBDemodSettings::MapType mapType, bool displayNavAids, bool displayPhotos, QWidget* parent = 0);
explicit ADSBDemodDisplayDialog(ADSBDemodSettings *settings, QWidget* parent = 0);
~ADSBDemodDisplayDialog();
int m_removeTimeout;
float m_airportRange;
ADSBDemodSettings::AirportType m_airportMinimumSize;
bool m_displayHeliports;
bool m_siUnits;
QString m_fontName;
int m_fontSize;
bool m_displayDemodStats;
bool m_autoResizeTableColumns;
QString m_apiKey;
QStringList m_airspaces;
float m_airspaceRange;
ADSBDemodSettings::MapType m_mapType;
bool m_displayNavAids;
bool m_displayPhotos;
private slots:
void accept();
void on_font_clicked();
private:
Ui::ADSBDemodDisplayDialog* ui;
ADSBDemodSettings *m_settings;
QString m_fontName;
int m_fontSize;
};
#endif // INCLUDE_ADSBDEMODDISPLAYDIALOG_H

View File

@ -7,12 +7,11 @@
<x>0</x>
<y>0</y>
<width>417</width>
<height>638</height>
<height>692</height>
</rect>
</property>
<property name="font">
<font>
<family>Liberation Sans</family>
<pointsize>9</pointsize>
</font>
</property>
@ -23,20 +22,57 @@
<item>
<widget class="QGroupBox" name="groupBox">
<layout class="QGridLayout" name="gridLayout">
<item row="14" column="0">
<widget class="QLabel" name="displayStatsLabel">
<property name="text">
<item row="14" column="1">
<widget class="QCheckBox" name="displayStats">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Display demodulator statistics</string>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QSpinBox" name="airportRange">
<property name="toolTip">
<string>Displays airports within the specified distance in kilometres from My Position</string>
<item row="7" column="0">
<widget class="QLabel" name="displayNavAids">
<property name="text">
<string>Display NAVAIDs</string>
</property>
<property name="maximum">
<number>20000</number>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="units">
<property name="toolTip">
<string>The units to use for altitude, speed and climb rate</string>
</property>
<item>
<property name="text">
<string>ft, kn, ft/min</string>
</property>
</item>
<item>
<property name="text">
<string>m, kph, m/s</string>
</property>
</item>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="airspacesLabel">
<property name="text">
<string>Airspaces to display</string>
</property>
</widget>
</item>
<item row="16" column="0">
<widget class="QLabel" name="apiKeyLabel">
<property name="text">
<string>avaitionstack API key</string>
</property>
</widget>
</item>
@ -50,6 +86,47 @@
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="heliportsLabel">
<property name="text">
<string>Display heliports</string>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QSpinBox" name="airspaceRange">
<property name="toolTip">
<string>Displays airspace within the specified distance in kilometres from My Position</string>
</property>
<property name="maximum">
<number>20000</number>
</property>
</widget>
</item>
<item row="15" column="0">
<widget class="QLabel" name="verboseModelMatchingLabel">
<property name="text">
<string>Log 3D model matching information</string>
</property>
</widget>
</item>
<item row="13" column="0">
<widget class="QLabel" name="autoResizeTableColumnsLabel">
<property name="text">
<string>Resize columns after adding aircraft</string>
</property>
</widget>
</item>
<item row="7" column="1">
<widget class="QCheckBox" name="navAids">
<property name="toolTip">
<string>Display NAVAIDs such as VORs and NDBs</string>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="mapTypeLabel">
<property name="text">
@ -57,20 +134,109 @@
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="airspacesLabel">
<item row="4" column="0">
<widget class="QLabel" name="airportRangeLabel">
<property name="text">
<string>Airspaces to display</string>
<string>Airport display distance (km)</string>
</property>
</widget>
</item>
<item row="15" column="1">
<item row="4" column="1">
<widget class="QSpinBox" name="airportRange">
<property name="toolTip">
<string>Displays airports within the specified distance in kilometres from My Position</string>
</property>
<property name="maximum">
<number>20000</number>
</property>
</widget>
</item>
<item row="14" column="0">
<widget class="QLabel" name="displayStatsLabel">
<property name="text">
<string>Display demodulator statistics</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="airportSizeLabel">
<property name="text">
<string>Display airports with size</string>
</property>
</widget>
</item>
<item row="16" column="1">
<widget class="QLineEdit" name="apiKey">
<property name="toolTip">
<string>aviationstack.com API key for accessing flight information</string>
</property>
</widget>
</item>
<item row="8" column="0">
<widget class="QLabel" name="photosLabel">
<property name="text">
<string>Display aircraft photos</string>
</property>
</widget>
</item>
<item row="15" column="1">
<widget class="QCheckBox" name="verboseModelMatching">
<property name="toolTip">
<string>Log information about how aircraft are matched to 3D models</string>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="9" column="0">
<widget class="QLabel" name="timeoutLabel">
<property name="text">
<string>Aircraft timeout (s)</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="unitsLabel">
<property name="text">
<string>Units</string>
</property>
</widget>
</item>
<item row="10" column="0">
<widget class="QLabel" name="fontLabel">
<property name="text">
<string>Table font</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="mapType">
<property name="toolTip">
<string>Type of map to display</string>
</property>
<item>
<property name="text">
<string>Aviation</string>
</property>
</item>
<item>
<property name="text">
<string>Aviation (Dark)</string>
</property>
</item>
<item>
<property name="text">
<string>Street</string>
</property>
</item>
<item>
<property name="text">
<string>Satellite</string>
</property>
</item>
</widget>
</item>
<item row="5" column="1">
<widget class="QListWidget" name="airspaces">
<property name="toolTip">
@ -228,27 +394,13 @@
</item>
</widget>
</item>
<item row="13" column="1">
<widget class="QCheckBox" name="autoResizeTableColumns">
<item row="10" column="1">
<widget class="QPushButton" name="font">
<property name="toolTip">
<string>Resize the columns in the table after an aircraft is added to it</string>
<string>Select a font for the table</string>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QLabel" name="displayNavAids">
<property name="text">
<string>Display NAVAIDs</string>
</property>
</widget>
</item>
<item row="13" column="0">
<widget class="QLabel" name="autoResizeTableColumnsLabel">
<property name="text">
<string>Resize columns after adding aircraft</string>
<string>Select...</string>
</property>
</widget>
</item>
@ -274,128 +426,16 @@
</item>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="heliportsLabel">
<property name="text">
<string>Display heliports</string>
</property>
</widget>
</item>
<item row="14" column="1">
<widget class="QCheckBox" name="displayStats">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<item row="8" column="1">
<widget class="QCheckBox" name="photos">
<property name="toolTip">
<string>Display demodulator statistics</string>
<string>Download and display photos of highlighted aircraft</string>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="airportSizeLabel">
<property name="text">
<string>Display airports with size</string>
</property>
</widget>
</item>
<item row="15" column="0">
<widget class="QLabel" name="apiKeyLabel">
<property name="text">
<string>avaitionstack API key</string>
</property>
</widget>
</item>
<item row="9" column="0">
<widget class="QLabel" name="timeoutLabel">
<property name="text">
<string>Aircraft timeout (s)</string>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QSpinBox" name="airspaceRange">
<property name="toolTip">
<string>Displays airspace within the specified distance in kilometres from My Position</string>
</property>
<property name="maximum">
<number>20000</number>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="units">
<property name="toolTip">
<string>The units to use for altitude, speed and climb rate</string>
</property>
<item>
<property name="text">
<string>ft, kn, ft/min</string>
</property>
</item>
<item>
<property name="text">
<string>m, kph, m/s</string>
</property>
</item>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="unitsLabel">
<property name="text">
<string>Units</string>
</property>
</widget>
</item>
<item row="10" column="1">
<widget class="QPushButton" name="font">
<property name="toolTip">
<string>Select a font for the table</string>
</property>
<property name="text">
<string>Select...</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="airportRangeLabel">
<property name="text">
<string>Airport display distance (km)</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="mapType">
<property name="toolTip">
<string>Type of map to display</string>
</property>
<item>
<property name="text">
<string>Aviation</string>
</property>
</item>
<item>
<property name="text">
<string>Aviation (Dark)</string>
</property>
</item>
<item>
<property name="text">
<string>Street</string>
</property>
</item>
<item>
<property name="text">
<string>Satellite</string>
</property>
</item>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="airspaceRangeLabel">
<property name="text">
@ -403,6 +443,16 @@
</property>
</widget>
</item>
<item row="13" column="1">
<widget class="QCheckBox" name="autoResizeTableColumns">
<property name="toolTip">
<string>Resize the columns in the table after an aircraft is added to it</string>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QCheckBox" name="heliports">
<property name="toolTip">
@ -413,37 +463,26 @@
</property>
</widget>
</item>
<item row="10" column="0">
<widget class="QLabel" name="fontLabel">
<item row="17" column="0">
<widget class="QLabel" name="airfieldElevationLabel">
<property name="text">
<string>Table font</string>
<string>Airfield barometric altitude (ft)</string>
</property>
</widget>
</item>
<item row="7" column="1">
<widget class="QCheckBox" name="navAids">
<item row="17" column="1">
<widget class="QSpinBox" name="airfieldElevation">
<property name="toolTip">
<string>Display NAVAIDs such as VORs and NDBs</string>
<string>Barometric altitude reported by aircraft when on airfield surface</string>
</property>
<property name="text">
<string/>
<property name="minimum">
<number>-10000</number>
</property>
</widget>
</item>
<item row="8" column="0">
<widget class="QLabel" name="photosLabel">
<property name="text">
<string>Display aircraft photos</string>
<property name="maximum">
<number>30000</number>
</property>
</widget>
</item>
<item row="8" column="1">
<widget class="QCheckBox" name="photos">
<property name="toolTip">
<string>Download and display photos of highlighted aircraft</string>
</property>
<property name="text">
<string/>
<property name="singleStep">
<number>10</number>
</property>
</widget>
</item>

File diff suppressed because it is too large Load Diff

View File

@ -41,6 +41,8 @@
#include "settings/rollupstate.h"
#include "maincore.h"
#include "SWGMapItem.h"
#include "adsbdemodsettings.h"
#include "ourairportsdb.h"
#include "osndb.h"
@ -83,11 +85,14 @@ public:
// Data about an aircraft extracted from an ADS-B frames
struct Aircraft {
int m_icao; // 24-bit ICAO aircraft address
QString m_icaoHex;
QString m_callsign; // Flight callsign
QString m_flight; // Guess at flight number
Real m_latitude; // Latitude in decimal degrees
Real m_longitude; // Longitude in decimal degrees
int m_altitude; // Altitude in feet
bool m_onSurface; // Indicates if on surface or airbourne
bool m_altitudeGNSS; // Altitude is GNSS HAE (Height above WGS-84 ellipsoid) rather than barometric alitute (relative to 29.92 Hg)
int m_speed; // Speed in knots
enum SpeedType {
GS, // Ground speed
@ -95,14 +100,14 @@ struct Aircraft {
IAS // Indicated air speed
} m_speedType;
static const char *m_speedTypeNames[];
int m_heading; // Heading in degrees
float m_heading; // Heading in degrees
int m_verticalRate; // Vertical climb rate in ft/min
QString m_emitterCategory; // Aircraft type
QString m_status; // Aircraft status
int m_squawk; // Mode-A code
Real m_range; // Distance from station to aircraft
Real m_azimuth; // Azimuth from station to aircraft
Real m_elevation; // Elevation from station to aicraft;
Real m_elevation; // Elevation from station to aicraft
QDateTime m_time; // When last updated
bool m_positionValid; // Indicates if we have valid data for the above fields
@ -130,7 +135,28 @@ struct Aircraft {
QVariantList m_coordinates; // Coordinates we've recorded the aircraft at
AircraftInformation *m_aircraftInfo; // Info about the aircraft from the database
QString m_aircraft3DModel; // 3D model for map based on aircraft type
QString m_aircraftCat3DModel; // 3D model based on aircraft category
float m_modelAltitudeOffset; // Altitude adjustment so aircraft model doesn't go underground
float m_labelAltitudeOffset; // How height to position label above aircraft
ADSBDemodGUI *m_gui;
QString m_flagIconURL;
QString m_airlineIconURL;
// For animation on 3D map
float m_runwayAltitude;
bool m_runwayAltitudeValid;
bool m_gearDown;
float m_flaps; // 0 - no flaps, 1 - full flaps
bool m_rotorStarted; // Rotors started on 'Rotorcraft'
bool m_engineStarted; // Engines started (typically propellors)
QDateTime m_positionDateTime;
QDateTime m_orientationDateTime;
QDateTime m_headingDateTime;
QDateTime m_prevHeadingDateTime;
int m_prevHeading;
float m_pitch; // Estimated pitch based on vertical rate
float m_roll; // Estimated roll based on rate of change in heading
bool m_notified; // Set when a notification has been made for this aircraft, so we don't repeat it
@ -175,7 +201,10 @@ struct Aircraft {
m_latitude(0),
m_longitude(0),
m_altitude(0),
m_onSurface(false),
m_altitudeGNSS(false),
m_speed(0),
m_speedType(GS),
m_heading(0),
m_verticalRate(0),
m_azimuth(0),
@ -193,7 +222,17 @@ struct Aircraft {
m_isHighlighted(false),
m_showAll(false),
m_aircraftInfo(nullptr),
m_modelAltitudeOffset(0.0f),
m_labelAltitudeOffset(5.0f),
m_gui(gui),
m_runwayAltitude(0.0),
m_runwayAltitudeValid(false),
m_gearDown(false),
m_flaps(0.0),
m_rotorStarted(false),
m_engineStarted(false),
m_pitch(0.0),
m_roll(0.0),
m_notified(false)
{
for (int i = 0; i < 2; i++)
@ -237,8 +276,8 @@ struct Aircraft {
m_ataItem = new QTableWidgetItem();
}
QString getImage();
QString getText(bool all=false);
QString getImage() const;
QString getText(bool all=false) const;
// Name to use when selected as a target
QString targetName()
@ -348,6 +387,8 @@ public:
allAircraftUpdated();
}
Q_INVOKABLE void findOnMap(int index);
private:
QList<Aircraft *> m_aircrafts;
bool m_flightPaths;
@ -637,6 +678,65 @@ private:
QList<bool> m_selected;
};
// Match 3D models to Opensky-Network Aircraft database
// The database doesn't use consistent names for aircraft, so we use regexps
class ModelMatch {
public:
ModelMatch(const QString &aircraftRegExp, const QString &model) :
m_aircraftRegExp(aircraftRegExp),
m_model(model)
{
m_aircraftRegExp.optimize();
}
virtual bool match(const QString &aircraft, const QString &manufacturer, QString &model)
{
QRegularExpressionMatch match = m_aircraftRegExp.match(aircraft);
if (match.hasMatch())
{
model = m_model;
return true;
}
else
{
return false;
}
}
protected:
QRegularExpression m_aircraftRegExp;
QString m_model;
};
// For very generic aircraft names, also match against manufacturer name
class ManufacturerModelMatch : public ModelMatch {
public:
ManufacturerModelMatch(const QString &modelRegExp, const QString &manufacturerRegExp, const QString &model) :
ModelMatch(modelRegExp, model),
m_manufacturerRegExp(manufacturerRegExp)
{
m_manufacturerRegExp.optimize();
}
virtual bool match(const QString &aircraft, const QString &manufacturer, QString &model) override
{
QRegularExpressionMatch matchManufacturer = m_manufacturerRegExp.match(manufacturer);
if (matchManufacturer.hasMatch())
{
QRegularExpressionMatch matchAircraft = m_aircraftRegExp.match(aircraft);
if (matchAircraft.hasMatch())
{
model = m_model;
return true;
}
}
return false;
}
protected:
QRegularExpression m_manufacturerRegExp;
};
class ADSBDemodGUI : public ChannelGUI {
Q_OBJECT
@ -652,8 +752,11 @@ public:
void targetAircraft(Aircraft *aircraft);
void target(const QString& name, float az, float el, float range);
bool setFrequency(float frequency);
bool useSIUints() { return m_settings.m_siUnits; }
bool useSIUints() const { return m_settings.m_siUnits; }
Q_INVOKABLE void clearHighlighted();
QString get3DModel(const QString &aircraft, const QString &operatorICAO) const;
QString get3DModel(const QString &aircraft) const;
void get3DModel(Aircraft *aircraft);
public slots:
void channelMarkerChangedByCursor();
@ -683,6 +786,7 @@ private:
AirspaceModel m_airspaceModel;
NavAidModel m_navAidModel;
QHash<QString, QIcon *> m_airlineIcons; // Hashed on airline ICAO
QHash<QString, bool> m_airlineMissingIcons; // Hash containing which ICAOs we don't have icons for
QHash<QString, QIcon *> m_flagIcons; // Hashed on country
QHash<QString, QString> *m_prefixMap; // Registration to country (flag name)
QHash<QString, QString> *m_militaryMap; // Operator airforce to military (flag name)
@ -710,6 +814,10 @@ private:
quint16 m_osmPort;
OpenAIP m_openAIP;
ADSBOSMTemplateServer *m_templateServer;
QHash<QString, QString> m_3DModels; // Hashed aircraft_icao or just aircraft
QList<ModelMatch *> m_3DModelMatch; // Map of database aircraft names to 3D model names
QHash<QString, float> m_modelAltitudeOffset;
QHash<QString, float> m_labelAltitudeOffset;
explicit ADSBDemodGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSampleSink *rxChannel, QWidget* parent = 0);
virtual ~ADSBDemodGUI();
@ -721,11 +829,19 @@ private:
bool handleMessage(const Message& message);
void updatePosition(Aircraft *aircraft);
bool updateLocalPosition(Aircraft *aircraft, double latitude, double longitude, bool surfacePosition);
void sendToMap(Aircraft *aircraft, QList<SWGSDRangel::SWGMapAnimation *> *animations);
void handleADSB(
const QByteArray data,
const QDateTime dateTime,
float correlation,
float correlationOnes);
float correlationOnes,
bool updateModel);
QList<SWGSDRangel::SWGMapAnimation *> *animate(QDateTime dateTime, Aircraft *aircraft, bool prevAltitudeValid, int prevAltitude);
SWGSDRangel::SWGMapAnimation *gearAnimation(QDateTime startDateTime, bool up);
SWGSDRangel::SWGMapAnimation *flapsAnimation(QDateTime startDateTime, float currentFlaps, float flaps);
SWGSDRangel::SWGMapAnimation *slatsAnimation(QDateTime startDateTime, bool retract);
SWGSDRangel::SWGMapAnimation *rotorAnimation(QDateTime startDateTime, bool stop);
SWGSDRangel::SWGMapAnimation *engineAnimation(QDateTime startDateTime, int engine, bool stop);
void checkStaticNotification(Aircraft *aircraft);
void checkDynamicNotification(Aircraft *aircraft);
void speechNotification(Aircraft *aircraft, const QString &speech);
@ -735,6 +851,7 @@ private:
QString getDataDir();
QString getAirportDBFilename();
QString getAirportFrequenciesDBFilename();
QString getOSNDBZipFilename();
QString getOSNDBFilename();
QString getFastDBFilename();
qint64 fileAgeInDays(QString filename);
@ -743,10 +860,13 @@ private:
void readAirportFrequenciesDB(const QString& filename);
bool readOSNDB(const QString& filename);
bool readFastDB(const QString& filename);
void update3DModels();
void updateAirports();
void updateAirspaces();
void updateNavAids();
QString getAirlineIconPath(const QString &operatorICAO);
QIcon *getAirlineIcon(const QString &operatorICAO);
QString getFlagIconPath(const QString &country);
QIcon *getFlagIcon(const QString &country);
void updateDeviceSetList();
QAction *createCheckableItem(QString& text, int idx, bool checked);
@ -756,6 +876,9 @@ private:
void applyMapSettings();
void updatePhotoText(Aircraft *aircraft);
void updatePhotoFlightInformation(Aircraft *aircraft);
void findOnChannelMap(Aircraft *aircraft);
int grayToBinary(int gray, int bits) const;
void redrawMap();
void leaveEvent(QEvent*);
void enterEvent(QEvent*);
@ -766,6 +889,7 @@ private slots:
void on_threshold_valueChanged(int value);
void on_phaseSteps_valueChanged(int value);
void on_tapsPerPhase_valueChanged(int value);
void adsbData_customContextMenuRequested(QPoint point);
void on_adsbData_cellClicked(int row, int column);
void on_adsbData_cellDoubleClicked(int row, int column);
void adsbData_sectionMoved(int logicalIndex, int oldVisualIndex, int newVisualIndex);
@ -778,6 +902,7 @@ private slots:
void on_feed_clicked(bool checked);
void on_notifications_clicked();
void on_flightInfo_clicked();
void on_findOnMapFeature_clicked();
void on_getOSNDB_clicked();
void on_getAirportDB_clicked();
void on_getAirspacesDB_clicked();
@ -801,6 +926,8 @@ private slots:
void downloadAirspaceFinished();
void downloadNavAidsFinished();
void photoClicked();
virtual void showEvent(QShowEvent *event);
virtual bool eventFilter(QObject *obj, QEvent *event);
signals:
void homePositionChanged();

View File

@ -24,7 +24,6 @@
</property>
<property name="font">
<font>
<family>Liberation Sans</family>
<pointsize>9</pointsize>
</font>
</property>
@ -101,7 +100,6 @@
</property>
<property name="font">
<font>
<family>Liberation Mono</family>
<pointsize>12</pointsize>
</font>
</property>
@ -190,7 +188,6 @@
</property>
<property name="font">
<font>
<family>Liberation Mono</family>
<pointsize>8</pointsize>
</font>
</property>
@ -691,6 +688,23 @@
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="findOnMapFeature">
<property name="toolTip">
<string>Find selected aircraft on feature map</string>
</property>
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset resource="../../../sdrgui/resources/res.qrc">
<normaloff>:/gridpolar.png</normaloff>:/gridpolar.png</iconset>
</property>
<property name="checkable">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="stats">
<property name="toolTip">

View File

@ -43,10 +43,11 @@ public:
static MsgReportADSB* create(
QByteArray data,
float preambleCorrelation,
float correlationOnes
float correlationOnes,
QDateTime dateTime
)
{
return new MsgReportADSB(data, preambleCorrelation, correlationOnes);
return new MsgReportADSB(data, preambleCorrelation, correlationOnes, dateTime);
}
private:
@ -58,14 +59,15 @@ public:
MsgReportADSB(
QByteArray data,
float preambleCorrelation,
float correlationOnes
float correlationOnes,
QDateTime dateTime
) :
Message(),
m_data(data),
m_preambleCorrelation(preambleCorrelation),
m_correlationOnes(correlationOnes)
m_correlationOnes(correlationOnes),
m_dateTime(dateTime)
{
m_dateTime = QDateTime::currentDateTime();
}
};

View File

@ -81,6 +81,8 @@ void ADSBDemodSettings::resetToDefaults()
m_mapType = AVIATION_LIGHT;
m_displayNavAids = true;
m_displayPhotos = true;
m_verboseModelMatching = false;
m_airfieldElevation = 0;
}
QByteArray ADSBDemodSettings::serialize() const
@ -141,6 +143,9 @@ QByteArray ADSBDemodSettings::serialize() const
s.writeBlob(43, m_rollupState->serialize());
}
s.writeBool(44, m_verboseModelMatching);
s.writeS32(45, m_airfieldElevation);
for (int i = 0; i < ADSBDEMOD_COLUMNS; i++) {
s.writeS32(100 + i, m_columnIndexes[i]);
}
@ -245,6 +250,9 @@ bool ADSBDemodSettings::deserialize(const QByteArray& data)
m_rollupState->deserialize(bytetmp);
}
d.readBool(44, &m_verboseModelMatching, false);
d.readS32(45, &m_airfieldElevation, 0);
for (int i = 0; i < ADSBDEMOD_COLUMNS; i++) {
d.readS32(100 + i, &m_columnIndexes[i], i);
}

View File

@ -145,6 +145,8 @@ struct ADSBDemodSettings
bool m_displayNavAids;
bool m_displayPhotos;
Serializable *m_rollupState;
bool m_verboseModelMatching;
int m_airfieldElevation; //!< QFE in ft so aircraft takeoff/land from correct position
ADSBDemodSettings();
void resetToDefaults();

View File

@ -134,6 +134,11 @@ void ADSBDemodSink::processOneSample(Real magsq)
m_magsqCount++;
m_sampleBuffer[m_writeBuffer][m_writeIdx] = magsq;
m_writeIdx++;
if (!m_bufferDateTimeValid[m_writeBuffer])
{
m_bufferFirstSampleDateTime[m_writeBuffer] = QDateTime::currentDateTime();
m_bufferDateTimeValid[m_writeBuffer] = true;
}
if (m_writeIdx >= m_bufferSize)
{
m_bufferRead[m_writeBuffer].release();
@ -152,6 +157,8 @@ void ADSBDemodSink::processOneSample(Real magsq)
m_startPoint = boost::chrono::steady_clock::now();
m_writeIdx = m_samplesPerFrame - 1; // Leave space for copying samples from previous buffer
m_bufferDateTimeValid[m_writeBuffer] = false;
}
}
@ -213,6 +220,7 @@ void ADSBDemodSink::init(int samplesPerBit)
m_samplesPerFrame = samplesPerBit*(ADS_B_PREAMBLE_BITS+ADS_B_ES_BITS);
m_samplesPerChip = samplesPerBit/ADS_B_CHIPS_PER_BIT;
m_writeIdx = m_samplesPerFrame - 1; // Leave space for copying samples from previous buffer
m_bufferDateTimeValid[m_writeBuffer] = false;
for (int i = 0; i < m_buffers; i++)
m_sampleBuffer[i] = new Real[m_bufferSize];

View File

@ -97,6 +97,8 @@ private:
Real *m_sampleBuffer[3]; //!< Each buffer is m_bufferSize samples
QSemaphore m_bufferWrite[3]; //!< Sempahore to control write access to the buffers
QSemaphore m_bufferRead[3]; //!< Sempahore to control read access from the buffers
QDateTime m_bufferFirstSampleDateTime[3]; //!< Time for first sample in the buffer
bool m_bufferDateTimeValid[3];
ADSBDemodSinkWorker m_worker; //!< Worker thread that does the actual demodulation
int m_writeBuffer; //!< Which of the 3 buffers we're writing in to
int m_writeIdx; //!< Index to to current write buffer

View File

@ -140,6 +140,8 @@ void ADSBDemodSinkWorker::run()
if ((preambleCorrelation > m_correlationThresholdLinear) && (preambleCorrelationOnes != 0.0f))
{
int firstIdx = startIdx;
m_demodStats.m_correlatorMatches++;
// Skip over preamble
startIdx += samplesPerBit*ADS_B_PREAMBLE_BITS;
@ -202,7 +204,8 @@ void ADSBDemodSinkWorker::run()
ADSBDemodReport::MsgReportADSB *msg = ADSBDemodReport::MsgReportADSB::create(
QByteArray((char*)data, sizeof(data)),
preambleCorrelation * m_correlationScale,
preambleCorrelationOnes / samplesPerChip);
preambleCorrelationOnes / samplesPerChip,
rxDateTime(firstIdx, readBuffer));
m_sink->getMessageQueueToGUI()->push(msg);
}
// Pass to worker to feed to other servers
@ -211,7 +214,8 @@ void ADSBDemodSinkWorker::run()
ADSBDemodReport::MsgReportADSB *msg = ADSBDemodReport::MsgReportADSB::create(
QByteArray((char*)data, sizeof(data)),
preambleCorrelation * m_correlationScale,
preambleCorrelationOnes / samplesPerChip);
preambleCorrelationOnes / samplesPerChip,
rxDateTime(firstIdx, readBuffer));
m_sink->getMessageQueueToWorker()->push(msg);
}
}
@ -245,7 +249,8 @@ void ADSBDemodSinkWorker::run()
ADSBDemodReport::MsgReportADSB *msg = ADSBDemodReport::MsgReportADSB::create(
QByteArray((char*)data, sizeof(data)),
preambleCorrelation * m_correlationScale,
preambleCorrelationOnes / samplesPerChip);
preambleCorrelationOnes / samplesPerChip,
rxDateTime(firstIdx, readBuffer));
m_sink->getMessageQueueToWorker()->push(msg);
}
}
@ -312,7 +317,6 @@ void ADSBDemodSinkWorker::run()
}
}
}
void ADSBDemodSinkWorker::handleInputMessages()
{
Message* message;
@ -344,3 +348,10 @@ void ADSBDemodSinkWorker::handleInputMessages()
}
}
}
QDateTime ADSBDemodSinkWorker::rxDateTime(int firstIdx, int readBuffer) const
{
const qint64 samplesPerSecondMSec = ADS_B_BITS_PER_SECOND * m_settings.m_samplesPerBit / 1000;
const qint64 offsetMSec = (firstIdx - m_sink->m_samplesPerFrame - 1) / samplesPerSecondMSec;
return m_sink->m_bufferFirstSampleDateTime[readBuffer].addMSecs(offsetMSec);
}

View File

@ -76,6 +76,9 @@ private:
Real m_correlationThresholdLinear;
Real m_correlationScale;
crcadsb m_crc; //!< Have as member to avoid recomputing LUT
QDateTime rxDateTime(int firstIdx, int readBuffer) const;
};
#endif // INCLUDE_ADSBDEMODSINKWORKER_H

View File

@ -1638,6 +1638,30 @@
<file>airlinelogos/YEL.bmp</file>
<file>airlinelogos/YZR.bmp</file>
<file>airlinelogos/ZOM.bmp</file>
<file>airlinelogos/BCS.bmp</file>
<file>airlinelogos/BEA.bmp</file>
<file>airlinelogos/CATa.bmp</file>
<file>airlinelogos/DHA.bmp</file>
<file>airlinelogos/FJO.bmp</file>
<file>airlinelogos/FPYb.bmp</file>
<file>airlinelogos/GGT.bmp</file>
<file>airlinelogos/GPX.bmp</file>
<file>airlinelogos/HGB.bmp</file>
<file>airlinelogos/ITY.bmp</file>
<file>airlinelogos/JOS.bmp</file>
<file>airlinelogos/KRU.bmp</file>
<file>airlinelogos/NDA.bmp</file>
<file>airlinelogos/NVROLD.bmp</file>
<file>airlinelogos/OCN.bmp</file>
<file>airlinelogos/PXT.bmp</file>
<file>airlinelogos/RBS.bmp</file>
<file>airlinelogos/RYS.bmp</file>
<file>airlinelogos/SKYPARK.bmp</file>
<file>airlinelogos/TES.bmp</file>
<file>airlinelogos/TMT.bmp</file>
<file>airlinelogos/WDY.bmp</file>
<file>airlinelogos/SHF.bmp</file>
<file>airlinelogos/AIO.bmp</file>
</qresource>
</RCC>

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

View File

@ -1,5 +1,6 @@
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12
import QtLocation 5.12
import QtPositioning 5.12
import QtGraphicalEffects 1.12
@ -246,8 +247,13 @@ Item {
visible: !lightIcons
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.LeftButton | Qt.RightButton
onClicked: {
highlighted = true
if (mouse.button === Qt.LeftButton) {
highlighted = true
} else if (mouse.button === Qt.RightButton) {
contextMenu.popup()
}
}
onDoubleClicked: {
target = true
@ -283,11 +289,28 @@ Item {
id: text
anchors.centerIn: parent
text: adsbData
textFormat: TextEdit.RichText
}
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.LeftButton | Qt.RightButton
onClicked: {
showAll = !showAll
if (mouse.button === Qt.LeftButton) {
showAll = !showAll
} else if (mouse.button === Qt.RightButton) {
contextMenu.popup()
}
}
Menu {
id: contextMenu
MenuItem {
text: "Set as target"
onTriggered: target = true
}
MenuItem {
text: "Find on feature map"
onTriggered: aircraftModel.findOnMap(index)
}
}
}
}

View File

@ -30,7 +30,7 @@
#include "util/csv.h"
#define OSNDB_URL "https://opensky-network.org/datasets/metadata/aircraftDatabase.csv"
#define OSNDB_URL "https://opensky-network.org/datasets/metadata/aircraftDatabase.zip"
struct AircraftInformation {

View File

@ -8,6 +8,10 @@ As well as displaying information received via ADS-B, the plugin can also combin
![ADS-B Demodulator plugin GUI](../../../doc/img/ADSBDemod_plugin.png)
The ADS-B plugin can send aicraft for display on the [Map Feature](../../feature/map/readme.md) alongside objects from other plugins and in 3D.
![ADS-B on 3D Map](../../../doc/img/ADSBDemod_plugin_map_3d.png)
<h2>Interface</h2>
![ADS-B Demodulator plugin settings](../../../doc/img/ADSBDemod_plugin_settings.png)
@ -262,6 +266,7 @@ The map displays aircraft locations and data geographically. Four types of map c
![ADS-B Demodulator Map](../../../doc/img/ADSBDemod_plugin_map2.png)
The initial antenna location is placed according to My Position set under the Preferences > My Position menu. The position is only updated when the ADS-B demodulator plugin is first opened.
If My Position is not set correctly, the position of aircraft may not be computed correctly.
Aircraft are only placed upon the map when a position can be calculated, which can require several frames to be received.