ADS-B: reworked correlation threshold. Added RSSI. Corrected latitude negative shift. Implements #696

This commit is contained in:
f4exb 2020-11-09 07:28:43 +01:00
parent fffac68b7f
commit 9024d3f6fa
8 changed files with 89 additions and 46 deletions

View File

@ -70,6 +70,7 @@
#define ADSB_COL_TIME 20
#define ADSB_COL_FRAMECOUNT 21
#define ADSB_COL_CORRELATION 22
#define ADSB_COL_RSSI 23
const char *Aircraft::m_speedTypeNames[] = {
"GS", "TAS", "IAS"
@ -529,7 +530,11 @@ QIcon *ADSBDemodGUI::getFlagIcon(const QString &country)
}
}
void ADSBDemodGUI::handleADSB(const QByteArray data, const QDateTime dateTime, float correlation)
void ADSBDemodGUI::handleADSB(
const QByteArray data,
const QDateTime dateTime,
float correlation,
float correlationOnes)
{
const char idMap[] = "?ABCDEFGHIJKLMNOPQRSTUVWXYZ????? ???????????????0123456789??????";
const QString categorySetA[] = {
@ -621,6 +626,7 @@ void ADSBDemodGUI::handleADSB(const QByteArray data, const QDateTime dateTime, f
ui->adsbData->setItem(row, ADSB_COL_TIME, aircraft->m_timeItem);
ui->adsbData->setItem(row, ADSB_COL_FRAMECOUNT, aircraft->m_adsbFrameCountItem);
ui->adsbData->setItem(row, ADSB_COL_CORRELATION, aircraft->m_correlationItem);
ui->adsbData->setItem(row, ADSB_COL_RSSI, aircraft->m_rssiItem);
// Look aircraft up in database
if (m_aircraftInfo != nullptr)
{
@ -709,7 +715,9 @@ void ADSBDemodGUI::handleADSB(const QByteArray data, const QDateTime dateTime, f
.arg(CalcDb::dbPower(aircraft->m_minCorrelation), 3, 'f', 1)
.arg(CalcDb::dbPower(aircraft->m_correlation), 3, 'f', 1)
.arg(CalcDb::dbPower(aircraft->m_maxCorrelation), 3, 'f', 1));
m_correlationOnesAvg(correlationOnes);
aircraft->m_rssiItem->setText(QString("%1")
.arg(CalcDb::dbPower(m_correlationOnesAvg.instantAverage()), 3, 'f', 1));
// ADS-B, non-transponder ADS-B or TIS-B rebroadcast of ADS-B (ADS-R)
if ((df == 17) || ((df == 18) && ((ca == 0) || (ca == 1) || (ca == 6))))
{
@ -796,9 +804,13 @@ void ADSBDemodGUI::handleADSB(const QByteArray data, const QDateTime dateTime, f
latEven = dLatEven * ((j % 60) + aircraft->m_cprLat[0]);
if (latEven >= 270.0f)
latEven -= 360.0f;
else if (latEven <= -270.0f)
latEven += 360.0f;
latOdd = dLatOdd * ((j % 59) + aircraft->m_cprLat[1]);
if (latOdd >= 270.0f)
latOdd -= 360.0f;
else if (latOdd <= -270.0f)
latOdd += 360.0f;
if (aircraft->m_cprTime[0] >= aircraft->m_cprTime[1])
latitude = latEven;
else
@ -980,8 +992,10 @@ bool ADSBDemodGUI::handleMessage(const Message& message)
{
ADSBDemodReport::MsgReportADSB& report = (ADSBDemodReport::MsgReportADSB&) message;
handleADSB(
report.getData(), report.getDateTime(),
report.getPreambleCorrelation());
report.getData(),
report.getDateTime(),
report.getPreambleCorrelation(),
report.getCorrelationOnes());
return true;
}
else if (ADSBDemodReport::MsgReportDemodStats::match(message))
@ -1516,7 +1530,7 @@ void ADSBDemodGUI::on_displaySettings_clicked(bool checked)
if (dialog.exec() == QDialog::Accepted)
{
bool unitsChanged = m_settings.m_siUnits != dialog.m_siUnits;
m_settings.m_removeTimeout = dialog.m_removeTimeout;
m_settings.m_airportRange = dialog.m_airportRange;
m_settings.m_airportMinimumSize = dialog.m_airportMinimumSize;
@ -1867,6 +1881,7 @@ void ADSBDemodGUI::resizeTable()
ui->adsbData->setItem(row, ADSB_COL_TIME, new QTableWidgetItem("99:99:99"));
ui->adsbData->setItem(row, ADSB_COL_FRAMECOUNT, new QTableWidgetItem("Frames"));
ui->adsbData->setItem(row, ADSB_COL_CORRELATION, new QTableWidgetItem("0.001/0.001/0.001"));
ui->adsbData->setItem(row, ADSB_COL_RSSI, new QTableWidgetItem("-100.0"));
ui->adsbData->resizeColumnsToContents();
ui->adsbData->removeCellWidget(row, ADSB_COL_ICAO);
ui->adsbData->removeCellWidget(row, ADSB_COL_FLIGHT);
@ -1891,5 +1906,6 @@ void ADSBDemodGUI::resizeTable()
ui->adsbData->removeCellWidget(row, ADSB_COL_TIME);
ui->adsbData->removeCellWidget(row, ADSB_COL_FRAMECOUNT);
ui->adsbData->removeCellWidget(row, ADSB_COL_CORRELATION);
ui->adsbData->removeCellWidget(row, ADSB_COL_RSSI);
ui->adsbData->setRowCount(row);
}

View File

@ -147,6 +147,7 @@ struct Aircraft {
QTableWidgetItem *m_timeItem;
QTableWidgetItem *m_adsbFrameCountItem;
QTableWidgetItem *m_correlationItem;
QTableWidgetItem *m_rssiItem;
Aircraft(ADSBDemodGUI *gui) :
m_icao(0),
@ -201,6 +202,7 @@ struct Aircraft {
m_timeItem = new QTableWidgetItem();
m_adsbFrameCountItem = new QTableWidgetItem();
m_correlationItem = new QTableWidgetItem();
m_rssiItem = new QTableWidgetItem();
}
};
@ -458,6 +460,7 @@ private:
AzEl m_azEl; // Position of station
Aircraft *m_trackAircraft; // Aircraft we want to track in Channel Report
MovingAverageUtil<float, double, 10> m_correlationAvg;
MovingAverageUtil<float, double, 10> m_correlationOnesAvg;
Aircraft *m_highlightAircraft; // Aircraft we want to highlight, when selected in table
float m_currentAirportRange; // Current settings, so we only update if changed
@ -479,7 +482,11 @@ private:
void displayStreamIndex();
bool handleMessage(const Message& message);
void updatePosition(Aircraft *aircraft);
void handleADSB(const QByteArray data, const QDateTime dateTime, float correlation);
void handleADSB(
const QByteArray data,
const QDateTime dateTime,
float correlation,
float correlationOnes);
void resizeTable();
QString getDataDir();
QString getAirportDBFilename();

View File

@ -6,7 +6,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>350</width>
<width>384</width>
<height>1046</height>
</rect>
</property>
@ -36,7 +36,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>340</width>
<width>381</width>
<height>141</height>
</rect>
</property>
@ -327,7 +327,7 @@
</widget>
</item>
<item>
<widget class="QToolButton" name="demodModeS">
<widget class="ButtonSwitch" name="demodModeS">
<property name="toolTip">
<string>Demodulate all Mode-S frames, not just ADS-B</string>
</property>
@ -347,7 +347,7 @@
</widget>
</item>
<item>
<widget class="QToolButton" name="correlateFullPreamble">
<widget class="ButtonSwitch" name="correlateFullPreamble">
<property name="toolTip">
<string>Correlate against full preamble.</string>
</property>
@ -378,16 +378,16 @@
<string>Correlation threshold in dB. Lower values will increase the number of frames that can be received, but require more processing and possibly result in invalid frames.</string>
</property>
<property name="minimum">
<number>-450</number>
<number>0</number>
</property>
<property name="maximum">
<number>0</number>
<number>200</number>
</property>
<property name="pageStep">
<number>1</number>
</property>
<property name="value">
<number>0</number>
<number>100</number>
</property>
</widget>
</item>
@ -400,7 +400,7 @@
</size>
</property>
<property name="text">
<string>-15.0</string>
<string>20.0</string>
</property>
</widget>
</item>
@ -451,7 +451,7 @@
</widget>
</item>
<item>
<widget class="QToolButton" name="flightPaths">
<widget class="ButtonSwitch" name="flightPaths">
<property name="toolTip">
<string>Display flight paths</string>
</property>
@ -471,7 +471,7 @@
</widget>
</item>
<item>
<widget class="QToolButton" name="feed">
<widget class="ButtonSwitch" name="feed">
<property name="toolTip">
<string>Enable feeding of received ADS-B messages to the specifed server. Right click for settings.</string>
</property>
@ -547,7 +547,7 @@
<rect>
<x>0</x>
<y>140</y>
<width>341</width>
<width>381</width>
<height>291</height>
</rect>
</property>
@ -765,6 +765,11 @@
<string>Correlation values for received frames. min/avg/max</string>
</property>
</column>
<column>
<property name="text">
<string>RSSI</string>
</property>
</column>
</widget>
</item>
</layout>
@ -774,7 +779,7 @@
<rect>
<x>10</x>
<y>450</y>
<width>331</width>
<width>361</width>
<height>581</height>
</rect>
</property>
@ -857,6 +862,11 @@
<header>gui/valuedialz.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>ButtonSwitch</class>
<extends>QToolButton</extends>
<header>gui/buttonswitch.h</header>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>deltaFrequency</tabstop>

View File

@ -38,21 +38,32 @@ public:
QByteArray getData() const { return m_data; }
QDateTime getDateTime() const { return m_dateTime; }
float getPreambleCorrelation() const { return m_preambleCorrelation; }
float getCorrelationOnes() const { return m_correlationOnes; }
static MsgReportADSB* create(QByteArray data, float preambleCorrelation)
static MsgReportADSB* create(
QByteArray data,
float preambleCorrelation,
float correlationOnes
)
{
return new MsgReportADSB(data, preambleCorrelation);
return new MsgReportADSB(data, preambleCorrelation, correlationOnes);
}
private:
QByteArray m_data;
QDateTime m_dateTime;
float m_preambleCorrelation;
float m_correlationOnes;
MsgReportADSB(QByteArray data, float preambleCorrelation) :
MsgReportADSB(
QByteArray data,
float preambleCorrelation,
float correlationOnes
) :
Message(),
m_data(data),
m_preambleCorrelation(preambleCorrelation)
m_preambleCorrelation(preambleCorrelation),
m_correlationOnes(correlationOnes)
{
m_dateTime = QDateTime::currentDateTime();
}

View File

@ -34,7 +34,7 @@ void ADSBDemodSettings::resetToDefaults()
{
m_inputFrequencyOffset = 0;
m_rfBandwidth = 2*1300000;
m_correlationThreshold = -20.0f;
m_correlationThreshold = 10.0f; //<! ones/zero powers correlation threshold in dB
m_samplesPerBit = 4;
m_removeTimeout = 60;
m_feedEnabled = false;

View File

@ -57,7 +57,7 @@ void ADSBDemodSinkWorker::run()
<< " samplesPerChip: " << samplesPerChip
<< " samplesPerBit: " << samplesPerBit
<< " correlateFullPreamble: " << m_settings.m_correlateFullPreamble
<< " correlationZerosScale: " << m_correlationZerosScale
<< " correlationScale: " << m_correlationScale
<< " correlationThreshold: " << m_settings.m_correlationThreshold;
int readIdx = m_sink->m_samplesPerFrame - 1;
@ -127,7 +127,7 @@ void ADSBDemodSinkWorker::run()
}
}
// Use the difference rather than absolute value, as we don't care how powerful the signal
// Use the ratio of ones power over zeros power, as we don't care how powerful the signal
// is, just whether there is a good correlation with the preamble. The absolute value varies
// too much with different radios, AGC settings and and the noise floor is not constant
// (E.g: it's quite possible to receive multiple frames simultaneously, so we don't
@ -135,11 +135,11 @@ void ADSBDemodSinkWorker::run()
// a stronger signals 0 chip position. Similarly a strong signal in an adjacent
// channel may casue AGC to reduce gain, reducing the ampltiude of an otherwise
// strong signal, as well as the noise floor)
// The scale factors account for different values of samplesPerBit and the different
// number of zeros and ones in the preamble
// The threshold accounts for the different number of zeros and ones in the preamble
// If the sum of ones is exactly 0, it's probably no signal
Real preambleCorrelation = (preambleCorrelationOnes * m_correlationZerosScale)
- (preambleCorrelationZeros * m_correlationOnesScale);
Real preambleCorrelation = preambleCorrelationOnes/preambleCorrelationZeros; // without one/zero ratio correction
if ((preambleCorrelation > m_correlationThresholdLinear) && (preambleCorrelationOnes != 0.0f))
{
m_demodStats.m_correlatorMatches++;
@ -203,7 +203,8 @@ void ADSBDemodSinkWorker::run()
{
ADSBDemodReport::MsgReportADSB *msg = ADSBDemodReport::MsgReportADSB::create(
QByteArray((char*)data, sizeof(data)),
preambleCorrelation);
preambleCorrelation * m_correlationScale,
preambleCorrelationOnes / samplesPerChip);
m_sink->getMessageQueueToGUI()->push(msg);
}
// Pass to worker to feed to other servers
@ -211,7 +212,8 @@ void ADSBDemodSinkWorker::run()
{
ADSBDemodReport::MsgReportADSB *msg = ADSBDemodReport::MsgReportADSB::create(
QByteArray((char*)data, sizeof(data)),
preambleCorrelation);
preambleCorrelation * m_correlationScale,
preambleCorrelationOnes / samplesPerChip);
m_sink->getMessageQueueToWorker()->push(msg);
}
}
@ -244,7 +246,8 @@ void ADSBDemodSinkWorker::run()
{
ADSBDemodReport::MsgReportADSB *msg = ADSBDemodReport::MsgReportADSB::create(
QByteArray((char*)data, sizeof(data)),
preambleCorrelation);
preambleCorrelation * m_correlationScale,
preambleCorrelationOnes / samplesPerChip);
m_sink->getMessageQueueToWorker()->push(msg);
}
}
@ -325,23 +328,19 @@ void ADSBDemodSinkWorker::handleInputMessages()
ADSBDemodSettings settings = cfg->getSettings();
bool force = cfg->getForce();
if (settings.m_correlateFullPreamble) {
m_correlationScale = 3.0;
} else {
m_correlationScale = 2.0;
}
if ((m_settings.m_correlationThreshold != settings.m_correlationThreshold) || force)
{
m_correlationThresholdLinear = CalcDb::powerFromdB(settings.m_correlationThreshold);
m_correlationThresholdLinear /= m_correlationScale;
qDebug() << "m_correlationThresholdLinear: " << m_correlationThresholdLinear;
}
if (settings.m_correlateFullPreamble)
{
m_correlationOnesScale = 1.0f / settings.m_samplesPerBit;
m_correlationZerosScale = 2.0 * 1.0f / settings.m_samplesPerBit; // As 2x more 0s than 1s
}
else
{
m_correlationOnesScale = 1.0f / settings.m_samplesPerBit;
m_correlationZerosScale = 3.0 * 1.0f / settings.m_samplesPerBit; // As 3x more 0s than 1s
}
m_settings = settings;
delete message;
}

View File

@ -74,8 +74,7 @@ private:
ADSBDemodSink *m_sink;
ADSBDemodStats m_demodStats;
Real m_correlationThresholdLinear;
Real m_correlationZerosScale;
Real m_correlationOnesScale;
Real m_correlationScale;
crcadsb m_crc; //!< Have as member to avoid recomputing LUT
};

View File

@ -116,7 +116,8 @@ The table displays the decoded ADS-B data for each aircraft along side data avai
* Owner - The owner of the aircraft. (DB)
* Updated - The local time at which the last ADS-B message was received.
* RX Frames - A count of the number of ADS-B frames received from this aircraft.
* Correlation - Displays the minimun, average and maximum of the preamable correlation in dB for each recevied frame. These values can be used to help select a threshold setting.
* Correlation - Displays the minimun, average and maximum of the preamable correlation in dB for each recevied frame. These values can be used to help select a threshold setting. This correlation value is the ratio between the presence and absence of the signal corresponding to the "ones" and the "zeros" of the sync word adjusted by the bits ratio. It can be interpreted as a SNR estimation.
* RSSI - This Received Signal Strength Indicator is based on the signal power during correlation estimation. This is the power sum during the expected presence of the signal i.e. the "ones" of the sync word.
If an ADS-B frame has not been received from an aircraft for 60 seconds, the aircraft is removed from the table and map. This timeout can be adjusted in the Display Settings dialog.