Merge pull request #1023 from DB8LE/testing

Filter telemetry in real-time
testing
Mark Jessop 2025-10-19 09:10:27 +10:30 zatwierdzone przez GitHub
commit c962fea247
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: B5690EEEBB952194
5 zmienionych plików z 76 dodań i 0 usunięć

Wyświetl plik

@ -269,6 +269,8 @@ def start_decoder(freq, sonde_type, continuous=False):
exporter=exporter_functions,
timeout=_timeout,
telem_filter=telemetry_filter,
enable_realtime_filter=config["enable_realtime_filter"],
max_velocity=config["max_velocity"],
rs92_ephemeris=rs92_ephemeris,
rs41_drift_tweak=config["rs41_drift_tweak"],
experimental_decoder=config["experimental_decoders"][_exp_sonde_type],

Wyświetl plik

@ -96,6 +96,8 @@ def read_auto_rx_config(filename, no_sdr_test=False):
"min_radius_km": 0,
"radius_temporary_block": False,
# "sonde_time_threshold": 3, # Commented out to ensure warning message is shown.
"enable_realtime_filter": True,
"max_velocity": 300,
# Habitat Settings
"habitat_uploader_callsign": "SONDE_AUTO_RX",
"habitat_uploader_antenna": "1/4-wave",
@ -783,6 +785,17 @@ def read_auto_rx_config(filename, no_sdr_test=False):
)
auto_rx_config["ozi_host"] = "<broadcast>"
auto_rx_config["payload_summary_host"] = "<broadcast>"
# Real time filtering
try:
auto_rx_config["enable_realtime_filter"] = config.getboolean("filtering", "enable_realtime_filter")
auto_rx_config["max_velocity"] = config.getboolean("filtering", "max_velocity")
except:
logging.warning(
"Config - MIssing enable_realtime_filter or max_velocity option, using default (enabled, 300m/s)"
)
auto_rx_config["enable_realtime_filter"] = True
auto_rx_config["max_velocity"] = 300
# If we are being called as part of a unit test, just return the config now.
if no_sdr_test:

Wyświetl plik

@ -148,6 +148,8 @@ class SondeDecoder(object):
exporter=None,
timeout=180,
telem_filter=None,
enable_realtime_filter=True,
max_velocity=300,
rs92_ephemeris=None,
rs41_drift_tweak=False,
experimental_decoder=False,
@ -216,6 +218,8 @@ class SondeDecoder(object):
self.save_decode_iq = save_decode_iq
self.telem_filter = telem_filter
self.enable_realtime_filter = enable_realtime_filter
self.max_velocity = max_velocity
self.timeout = timeout
self.rs92_ephemeris = rs92_ephemeris
self.rs41_drift_tweak = rs41_drift_tweak
@ -224,6 +228,9 @@ class SondeDecoder(object):
self.raw_file = None
self.wideband_sondes = wideband_sondes
# Last decoded position of this sonde
self.last_positions = {}
# Raw hex filename
if self.save_raw_hex:
_outfilename = f"{datetime.datetime.now(datetime.timezone.utc).strftime('%Y%m%d-%H%M%S')}_{self.sonde_type}_{int(self.sonde_freq)}.raw"
@ -1929,6 +1936,40 @@ class SondeDecoder(object):
self.decoder_running = False
return False
# Run telemetry from DFM sondes through real-time filter
if self.enable_realtime_filter and (_telemetry["model"].startswith("DFM")):
# If sonde has already been received, calculate velocity
velocity = 0
if _telemetry["callsign"] in self.last_positions.keys():
_last_position = self.last_positions[_telemetry["callsign"]]
distance = position_info(
(_last_position[0], _last_position[1], 0),
(_telemetry["latitude"], _telemetry["longitude"], 0)
)["great_circle_distance"] # distance is in metres
time_diff = time.time() - _last_position[2] # seconds
velocity = distance / time_diff # m/s
# Check if velocity is higher than allowed maximum
if velocity > self.max_velocity:
_telem_ok = False
# Reset last position to prevent an endless chain of rejecting telemetry
del self.last_positions[_telemetry["callsign"]]
else:
# Check passed, update last position and continue processing
self.last_positions[_telemetry["callsign"]] = (
_telemetry["latitude"],
_telemetry["longitude"],
time.time()
)
# Garbage collect last_positions list
for serial, position in self.last_positions.items():
# If last position packet was more than 3 hours ago, delete it from list
if time.time()-position[2] > 3*60*60:
del self.last_positions[serial]
# If the telemetry is OK, send to the exporter functions (if we have any).
if self.exporters is None:

Wyświetl plik

@ -645,3 +645,13 @@ radius_temporary_block = False
# This helps catch glitches around 00Z UTC from iMet & LMS6 sondes, and bad CRC checks from
# DFM sondes.
sonde_time_threshold = 3
# Wether to perform real-time velocity filtering
# This filter calculates the velocity between the previous decoded telemetry frame and
# newly received frames, and discards them if it is faster than the velocity configured below.
# This helps discard the frame with invalid GPS data that DFM sondes transmit once per flight.
enable_realtime_filter = True
# Maximum velocity in metres per second for sondes to be discarded in the real-time filter
max_velocity = 300

Wyświetl plik

@ -644,3 +644,13 @@ radius_temporary_block = False
# This helps catch glitches around 00Z UTC from iMet & LMS6 sondes, and bad CRC checks from
# DFM sondes.
sonde_time_threshold = 3
# Wether to perform real-time velocity filtering
# This filter calculates the velocity between the previous decoded telemetry frame and
# newly received frames, and discards them if it is faster than the velocity configured below.
# This helps discard the frame with invalid GPS data that DFM sondes transmit once per flight.
enable_realtime_filter = True
# Maximum velocity in metres per second for sondes to be discarded in the real-time filter
max_velocity = 300