mirror of
https://github.com/f4exb/sdrangel.git
synced 2024-11-25 17:28:50 -05:00
ADS-B: reworked correlation threshold. Added RSSI. Corrected latitude negative shift. Implements #696
This commit is contained in:
parent
fffac68b7f
commit
9024d3f6fa
@ -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);
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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>
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
};
|
||||
|
||||
|
@ -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.
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user