dump1090-fa/tools/df-correction-arrays.py

49 lines
1.6 KiB
Python
Raw Permalink Normal View History

Overhaul of message scoring & error correction. Major changes: Try to error-correct all messages that potentially could be DF11/17/18 even if the original DF value is different. This allows messages with correctable damage in the first 5 bits to be correctable. Track recently-seen DF18 addresses separately to DF17 addresses. DF18 does not imply Mode S support, so we don't want to treat it like a known Mode S emitter, but once we've heard some DF18 for an aircraft we can be more confident about future DF18 messages for the same address. Rework the scoring system so it's just a big enum that lists all the possible outcomes in the order that we want. This makes the relative ordering of different messages clearer, and makes it easier to move messages above/below the accept thresholds as needed. Don't accept 2-bit-error-corrected messages that are from aircraft we have not previously seen. This greatly reduces the number of garbage messages when using 2-bit error correction. Overall results are: * more CPU required for decoding (approx 30% increase in my tests) as we're doing a lot more speculative CRC-checking work * no significant change to message rates with error correction off * about 5% more 1-bit-corrected DF17 decodes, with a disproportionate increase in those messages contributing to successful position decodes / unique aircraft counts * _fewer_ decodes with 2-bit correction (versus old code with 2-bit correction), but the message quality is substantially improved, the rate of garbage decodes / phantom aircraft is greatly reduced sample stats: 1-bit correction, old code: 141158 total usable messages 137852 accepted with correct CRC 3306 accepted with 1-bit error repaired 27446 DF17 messages 51 unique aircraft tracks 1-bit correction, new code: 141296 total usable messages 137854 accepted with correct CRC 3442 accepted with 1-bit error repaired 27528 DF17 messages 55 unique aircraft tracks 2-bit correction, old code: 142656 total usable messages 137809 accepted with correct CRC 3283 accepted with 1-bit error repaired 1564 accepted with 2-bit error repaired 28803 DF17 messages 349 unique aircraft tracks (<- note that most of these are garbage) 2-bit correction, new code: 142426 total usable messages 137822 accepted with correct CRC 3420 accepted with 1-bit error repaired 1184 accepted with 2-bit error repaired 28666 DF17 messages 55 unique aircraft tracks
2021-02-09 11:43:38 +00:00
#!/usr/bin/env python3
# For each error-correction level (0, 1, or 2-bit errors)
# generate the set of possible DF values that could possibly be
# corrected to DF11/17/18/19 messages, expressed as a bitset.
def popcount(x):
return bin(x).count('1')
# is the Hamming distance between 'df' and a valid long-message DF no more than `max_errors`?
def correctable_long(df, max_errors):
if popcount(df ^ 17) <= max_errors: return True
if popcount(df ^ 18) <= max_errors: return True
#if popcount(df ^ 19) <= max_errors: return True
return False
# is the Hamming distance between 'df' and a valid short-message DF no more than `max_errors`?
def correctable_short(df, max_errors):
if popcount(df ^ 11) <= max_errors: return True
return False
# Generate a bitset value where bit N is set if predicate(N) is True
def bitset(predicate):
result = 0
for i in range(32):
if predicate(i):
result |= 1 << i
return result
shorts = [
bitset(lambda x: correctable_short(x,0)),
bitset(lambda x: correctable_short(x,1)),
bitset(lambda x: correctable_short(x,1)) # deliberately not 2
]
longs = [
bitset(lambda x: correctable_long(x,0)),
bitset(lambda x: correctable_long(x,1)),
bitset(lambda x: correctable_long(x,2))
]
print('static const uint32_t df_correctable_short[MODES_MAX_BITERRORS + 1] = {')
print(' ' + ', '.join(f'0x{i:08x}' for i in shorts))
print('};')
print('static const uint32_t df_correctable_long[MODES_MAX_BITERRORS + 1] = {')
print(' ' + ', '.join(f'0x{i:08x}' for i in longs))
print('};')