Add experimental decoders.

pull/164/head
Mark Jessop 2019-04-26 18:25:48 +09:30
rodzic 26b7b8ccc0
commit 1ba539650b
3 zmienionych plików z 152 dodań i 6 usunięć

Wyświetl plik

@ -201,7 +201,13 @@ class SondeDecoder(object):
raise TypeError("Supplied exporter has incorrect type.")
# Generate the decoder command.
self.decoder_command = self.generate_decoder_command()
if self.experimental_decoder:
self.decoder_command = self.generate_decoder_command_experimental()
# TODO: Split the experimental decoder subprocess into two processed, and
# split out the status data from fsk_demod so we can use it.
else:
self.decoder_command = self.generate_decoder_command()
if self.decoder_command is None:
self.log_error("Could not generate decoder command. Not starting decoder.")
@ -217,14 +223,150 @@ class SondeDecoder(object):
def generate_decoder_command(self):
""" Generate the shell command which runs the relevant radiosonde decoder.
""" Generate the shell command which runs the relevant radiosonde decoder - Standard decoders.
This is where support for new sonde types can be added.s
Returns:
str/None: The shell command which will be run in the decoder thread, or none if a valid decoder could not be found.
"""
# Common options to rtl_fm
# Add a -T option if bias is enabled
bias_option = "-T " if self.bias else ""
# Add a gain parameter if we have been provided one.
if self.gain != -1:
gain_param = '-g %.1f ' % self.gain
else:
gain_param = ''
if self.sonde_type == "RS41":
# RS41 Decoder command.
# rtl_fm -p 0 -g -1 -M fm -F9 -s 15k -f 405500000 | sox -t raw -r 15k -e s -b 16 -c 1 - -r 48000 -b 8 -t wav - lowpass 2600 2>/dev/null | ./rs41ecc --crc --ecc --ptu
# Note: Have removed a 'highpass 20' filter from the sox line, will need to re-evaluate if adding that is useful in the future.
decode_cmd = "%s %s-p %d -d %s %s-M fm -F9 -s 15k -f %d 2>/dev/null | " % (self.sdr_fm, bias_option, int(self.ppm), str(self.device_idx), gain_param, self.sonde_freq)
# If selected by the user, we can add a highpass filter into the sox command. This helps handle up to about 5ppm of receiver drift
# before performance becomes significantly degraded. By default this is off, as it is not required with TCXO RTLSDRs, and actually
# slightly degrades performance.
if self.rs41_drift_tweak:
_highpass = "highpass 20 "
else:
_highpass = ""
decode_cmd += "sox -t raw -r 15k -e s -b 16 -c 1 - -r 48000 -b 8 -t wav - %slowpass 2600 2>/dev/null | " % _highpass
# Add in tee command to save audio to disk if debugging is enabled.
if self.save_decode_audio:
decode_cmd += " tee decode_%s.wav |" % str(self.device_idx)
decode_cmd += "./rs41mod --ptu --json 2>/dev/null"
elif self.sonde_type == "RS92":
# Decoding a RS92 requires either an ephemeris or an almanac file.
# If we have been supplied an ephemeris file, we will attempt to use it, otherwise
# we will try and download one.
if self.rs92_ephemeris == None:
# If no ephemeris data defined, attempt to download it.
# get_ephemeris will either return the saved file name, or None.
self.rs92_ephemeris = get_ephemeris(destination="ephemeris.dat")
# If ephemeris is still None, then we failed to download the ephemeris data.
# Try and grab the almanac data instead
if self.rs92_ephemeris == None:
self.log_error("Could not obtain ephemeris data, trying to download an almanac.")
almanac = get_almanac(destination="almanac.txt")
if almanac == None:
# We probably don't have an internet connection. Bomb out, since we can't do much with the sonde telemetry without an almanac!
self.log_error("Could not obtain GPS ephemeris or almanac data.")
return None
else:
_rs92_gps_data = "-a almanac.txt --gpsepoch 2" # Note - This will need to be updated in... 19 years.
else:
_rs92_gps_data = "-e ephemeris.dat"
else:
_rs92_gps_data = "-e %s" % self.rs92_ephemeris
# Adjust the receive bandwidth based on the band the scanning is occuring in.
if self.sonde_freq < 1000e6:
# 400-406 MHz sondes - use a 12 kHz FM demod bandwidth.
_rx_bw = 12000
else:
# 1680 MHz sondes - use a 28 kHz FM demod bandwidth.
# NOTE: This is a first-pass of this bandwidth, and may need to be optimized.
_rx_bw = 28000
# Now construct the decoder command.
# rtl_fm -p 0 -g 26.0 -M fm -F9 -s 12k -f 400500000 | sox -t raw -r 12k -e s -b 16 -c 1 - -r 48000 -b 8 -t wav - highpass 20 lowpass 2500 2>/dev/null | ./rs92ecc -vx -v --crc --ecc --vel -e ephemeris.dat
decode_cmd = "%s %s-p %d -d %s %s-M fm -F9 -s %d -f %d 2>/dev/null |" % (self.sdr_fm, bias_option, int(self.ppm), str(self.device_idx), gain_param, _rx_bw, self.sonde_freq)
decode_cmd += "sox -t raw -r %d -e s -b 16 -c 1 - -r 48000 -b 8 -t wav - lowpass 2500 highpass 20 2>/dev/null |" % _rx_bw
# Add in tee command to save audio to disk if debugging is enabled.
if self.save_decode_audio:
decode_cmd += " tee decode_%s.wav |" % str(self.device_idx)
decode_cmd += "./rs92mod -vx -v --crc --ecc --vel --json %s 2>/dev/null" % _rs92_gps_data
elif self.sonde_type == "DFM":
# DFM06/DFM09 Sondes.
# As of 2019-02-10, dfm09ecc auto-detects if the signal is inverted,
# so we don't need to specify an invert flag.
# 2019-02-27: Added the --dist flag, which should reduce bad positions a bit.
# Note: Have removed a 'highpass 20' filter from the sox line, will need to re-evaluate if adding that is useful in the future.
decode_cmd = "%s %s-p %d -d %s %s-M fm -F9 -s 15k -f %d 2>/dev/null |" % (self.sdr_fm, bias_option, int(self.ppm), str(self.device_idx), gain_param, self.sonde_freq)
decode_cmd += "sox -t raw -r 15k -e s -b 16 -c 1 - -r 48000 -b 8 -t wav - highpass 20 lowpass 2000 2>/dev/null |"
# Add in tee command to save audio to disk if debugging is enabled.
if self.save_decode_audio:
decode_cmd += " tee decode_%s.wav |" % str(self.device_idx)
# DFM decoder
decode_cmd += "./dfm09ecc -vv --ecc --json --dist --auto 2>/dev/null"
elif self.sonde_type == "M10":
# M10 Sondes
decode_cmd = "%s %s-p %d -d %s %s-M fm -F9 -s 22k -f %d 2>/dev/null |" % (self.sdr_fm, bias_option, int(self.ppm), str(self.device_idx), gain_param, self.sonde_freq)
decode_cmd += "sox -t raw -r 22k -e s -b 16 -c 1 - -r 48000 -b 8 -t wav - highpass 20 2>/dev/null |"
# Add in tee command to save audio to disk if debugging is enabled.
if self.save_decode_audio:
decode_cmd += " tee decode_%s.wav |" % str(self.device_idx)
# M10 decoder
decode_cmd += "./m10 -b -b2 2>/dev/null"
elif self.sonde_type == "iMet":
# iMet-4 Sondes
decode_cmd = "%s %s-p %d -d %s %s-M fm -F9 -s 15k -f %d 2>/dev/null |" % (self.sdr_fm, bias_option, int(self.ppm), str(self.device_idx), gain_param, self.sonde_freq)
decode_cmd += "sox -t raw -r 15k -e s -b 16 -c 1 - -r 48000 -b 8 -t wav - highpass 20 2>/dev/null |"
# Add in tee command to save audio to disk if debugging is enabled.
if self.save_decode_audio:
decode_cmd += " tee decode_%s.wav |" % str(self.device_idx)
# iMet-4 (IMET1RS) decoder
decode_cmd += "./imet1rs_dft --json 2>/dev/null"
else:
return None
return decode_cmd
def generate_decoder_command_experimental(self):
""" Generate the shell command which runs the relevant radiosonde decoder - Experimental Decoders
Returns:
str/None: The shell command which will be run in the decoder thread, or none if a valid decoder could not be found.
"""
self.log_info("Using experimental decoder chain.")
# Common options to rtl_fm
# Add a -T option if bias is enabled
@ -286,12 +428,13 @@ class SondeDecoder(object):
if self.sonde_freq > 1000e6:
# Use a higher IQ rate for 1680 MHz sondes, at the expensive of some CPU usage.
# Use a higher IQ rate for 1680 MHz sondes, at the expense of some CPU usage.
_sdr_rate = 96000
else:
# On 400 MHz, use 48 khz - RS92s dont drift far enough to need any more than this.
_sdr_rate = 48000
_output_rate = 48000
_baud_rate = 4800
_offset = 0.25 # Place the sonde frequency in the centre of the passband.
_lower = int(0.025 * _sdr_rate) # Limit the frequency estimation window to not include the passband edges.
@ -305,7 +448,7 @@ class SondeDecoder(object):
decode_cmd += " tee decode_IQ_%s.bin |" % str(self.device_idx)
decode_cmd += "./fsk_demod --cs16 -b %d -u %d --stats=%d 2 %d %d - - 2>stats.txt " % (_lower, _upper, _stats_rate, _sdr_rate, _baud_rate)
decode_cmd += "| python ./test/bit_to_samples.py %d %d | sox -t raw -r %d -e unsigned-integer -b 8 -c 1 - -r %d -b 8 -t wav - 2>/dev/null|" % (_sdr_rate, _baud_rate, _sdr_rate, _sdr_rate)
decode_cmd += "| python ./test/bit_to_samples.py %d %d | sox -t raw -r %d -e unsigned-integer -b 8 -c 1 - -r %d -b 8 -t wav - 2>/dev/null|" % (_output_rate, _baud_rate, _output_rate, _output_rate)
# Add in tee command to save audio to disk if debugging is enabled.
if self.save_decode_audio:
@ -344,6 +487,8 @@ class SondeDecoder(object):
elif self.sonde_type == "M10":
# M10 Sondes
# These have a 'weird' baud rate, and as fsk_demod requires the input sample rate to be an integer multiple of the baud rate,
# our required sample rate is correspondingly weird!
_sdr_rate = 48080
_baud_rate = 9616
_offset = 0.25 # Place the sonde frequency in the centre of the passband.
@ -382,7 +527,6 @@ class SondeDecoder(object):
decode_cmd += "./imet1rs_dft --json 2>/dev/null"
else:
# Should never get here.
return None
return decode_cmd

Wyświetl plik

@ -289,4 +289,5 @@ void M10GtopParser::printFrame() {
"Gtop", frame, getSerialNumber().c_str(), getdxlSerialNumber().c_str(), getYear(), getMonth(), getDay(), getHours(), getMinutes(), getSeconds(), getLatitude(), getLongitude(),
getAltitude(), getHorizontalSpeed(), getDirection(), getVerticalSpeed()/*, getTemperature()*/, correctCRC);
}
fflush(stdout);
}

Wyświetl plik

@ -469,6 +469,7 @@ void M10TrimbleParser::printFrame() {
auxstr.c_str(), getSatellites(), getLatitude(), getLongitude(),
getAltitude(), getHorizontalSpeed(), getDirection(), getVerticalSpeed(), getTemperature(), getBatteryLevel(), correctCRC);
}
fflush(stdout);
}
/*