Better handling of zero time-step data

pull/21/head
Mark Jessop 2020-07-18 16:56:02 +09:30
rodzic 9fe136bbdf
commit 8c284eaa31
3 zmienionych plików z 57 dodań i 17 usunięć

Wyświetl plik

@ -105,7 +105,11 @@ class GenericTrack(object):
_time_delta = (self.track_history[-1][0] - self.track_history[-2][0]).total_seconds()
_altitude_delta = self.track_history[-1][3] - self.track_history[-2][3]
return _altitude_delta/_time_delta
if _time_delta == 0:
logging.warning("Zero time-step encountered in ascent rate calculation - are multiple receivers reporting telemetry simultaneously?")
return 0.0
else:
return _altitude_delta/_time_delta
else:
@ -115,7 +119,12 @@ class GenericTrack(object):
for _i in range(-1*(_num_samples-1), 0):
_time_delta = (self.track_history[_i][0] - self.track_history[_i-1][0]).total_seconds()
_altitude_delta = self.track_history[_i][3] - self.track_history[_i-1][3]
_asc_rates.append(_altitude_delta/_time_delta)
try:
_asc_rates.append(_altitude_delta/_time_delta)
except ZeroDivisionError:
logging.warning("Zero time-step encountered in ascent rate calculation - are multiple receivers reporting telemetry simultaneously?")
continue
return np.mean(_asc_rates)
@ -142,7 +151,11 @@ class GenericTrack(object):
_pos_info = position_info((_pos_1[1],_pos_1[2],_pos_1[3]), (_pos_2[1],_pos_2[2],_pos_2[3]))
_speed = _pos_info['great_circle_distance']/_time_delta
try:
_speed = _pos_info['great_circle_distance']/_time_delta
except ZeroDivisionError:
logging.warning("Zero time-step encountered in speed calculation - are multiple receivers reporting telemetry simultaneously?")
return 0.0
return _speed

Wyświetl plik

@ -607,7 +607,12 @@ def udp_listener_summary_callback(data):
output['alt'] = float(data['altitude'])
output['callsign'] = data['callsign']
logging.info("Horus UDP Data: %.5f, %.5f, %.1f" % (output['lat'], output['lon'], output['alt']))
if 'time' in data.keys():
_time = data['time']
else:
_time = "??:??:??"
logging.info("Horus UDP Data: %s, %s, %.5f, %.5f, %.1f" % (output['callsign'], _time, output['lat'], output['lon'], output['alt']))
# Process the 'short time' value if we have been provided it.
if 'time' in data.keys():

Wyświetl plik

@ -36,8 +36,12 @@ def read_file(filename):
return _output
def stringify_entry(entry):
""" Convert a balloon telemetry entry to a string """
_out = "%s,%.6f,%.6f,%d\n" % (entry['time'], entry['lat'], entry['lon'], entry['alt'])
return _out
def extract_data(log_entries):
def extract_data(log_entries, csv_dump=None):
""" Step through the log entries, and extract:
- Car position telemetry
- Balloon positions
@ -49,6 +53,9 @@ def extract_data(log_entries):
# We might have more than one balloon though, so we use a dictionary, with one entry per callsign.
_telemetry = {}
if csv_dump is not None:
csv_out = open(csv_dump, 'w')
for _entry in log_entries:
if _entry['log_type'] == "CAR POSITION":
@ -63,6 +70,9 @@ def extract_data(log_entries):
_telemetry[_call]['telemetry'].append(_entry)
if csv_dump is not None:
csv_out.write(stringify_entry(_entry))
elif _entry['log_type'] == "PREDICTION":
# Extract the callsign.
_call = _entry['callsign']
@ -76,6 +86,10 @@ def extract_data(log_entries):
for _call in _telemetry:
logging.info("Callsign %s: Extracted %d telemetry positions, %d predictions." % (_call, len(_telemetry[_call]['telemetry']), len(_telemetry[_call]['predictions'])))
if csv_dump is not None:
csv_out.close()
return (_car, _telemetry)
@ -124,7 +138,7 @@ def flight_stats(telemetry, ascent_threshold = 3.0, descent_threshold=-5.0, lan
_stats['positions'].append([_position['time'], _position['lat'], _position['lon'], _position['alt']])
_state = _track.add_telemetry(_position)
print(_state)
#print(_state)
if _state == None:
continue
@ -167,6 +181,7 @@ def flight_stats(telemetry, ascent_threshold = 3.0, descent_threshold=-5.0, lan
_stats['burst_position'][2],
_stats['burst_position'][3]
))
logging.info("Average ascent rate: %.2f" % np.mean(_stats['raw_ascent_rates']))
if _mean_asc_rate < descent_threshold:
_flight_segment = "DESCENT"
@ -183,7 +198,7 @@ def flight_stats(telemetry, ascent_threshold = 3.0, descent_threshold=-5.0, lan
_flight_segment = "LANDED"
return _stats
print(_flight_segment)
#print(_flight_segment)
return _stats
@ -216,7 +231,7 @@ def calculate_predictor_error(predictions, landing_time, lat, lon, alt):
_pos_info = position_info(_landing, _predict_landing)
logging.info("Prediction %s: Altitude %d, Predicted Landing: %.4f, %.4f Prediction Error: %.1f km, %s" % (
logging.debug("Prediction %s: Altitude %d, Predicted Landing: %.4f, %.4f Prediction Error: %.1f km, %s" % (
_predict_time,
int(_predict_altitude),
_predict['pred_landing'][0],
@ -269,7 +284,7 @@ def calculate_abort_error(predictions, landing_time, lat, lon, alt):
_pos_info = position_info(_landing, _predict_landing)
logging.info("Abort Prediction %s: Altitude %d, Predicted Landing: %.4f, %.4f Prediction Error: %.1f km, %s" % (
logging.debug("Abort Prediction %s: Altitude %d, Predicted Landing: %.4f, %.4f Prediction Error: %.1f km, %s" % (
_predict_time,
int(_predict_altitude),
_predict['abort_landing'][0],
@ -353,7 +368,7 @@ def plot_predictor_error(flight_stats, predictor_errors, abort_predictor_errors=
plt.grid()
def plot_wind_trace(stats, title="", gfs_file=None, landing=None):
def plot_wind_trace(stats, title="", gfs_file=None, landing=None, ascent=True):
""" Plot the wind trace for the descent part of the flight """
_altitude = stats['altitudes']
@ -363,10 +378,16 @@ def plot_wind_trace(stats, title="", gfs_file=None, landing=None):
# Find peak altitude
_peak_idx = np.argmax(_altitude)
# Only use descent data
_altitude = np.array(_altitude[_peak_idx:])
_speed = np.array(_speed[_peak_idx:])
_heading = np.array(_heading[_peak_idx:])
if ascent:
# Only use descent data
_altitude = np.array(_altitude[:_peak_idx])
_speed = np.array(_speed[:_peak_idx])
_heading = np.array(_heading[:_peak_idx])
else:
# Only use descent data
_altitude = np.array(_altitude[_peak_idx:])
_speed = np.array(_speed[_peak_idx:])
_heading = np.array(_heading[_peak_idx:])
if gfs_file is not None:
# Read in supplied GFS file.
@ -390,7 +411,7 @@ def plot_wind_trace(stats, title="", gfs_file=None, landing=None):
plt.ylabel("Altitude (m)")
plt.xlabel("Absolute Speed (m/s)")
plt.title("Descent Wind Speed - " + title)
plt.title("Wind Speed - " + title)
plt.grid()
plt.legend()
@ -403,7 +424,7 @@ def plot_wind_trace(stats, title="", gfs_file=None, landing=None):
plt.ylabel("Altitude (m)")
plt.xlabel("Wind Heading (Degrees True)")
plt.title("Descent Wind Heading - " + title)
plt.title("Wind Heading - " + title)
plt.grid()
plt.legend()
@ -419,6 +440,7 @@ if __name__ == "__main__":
parser.add_argument("--landing-lon", type=float, default=None, help="Override Landing Longitude")
parser.add_argument("--wind-trace", action="store_true", default=False, help="Plot wind trace.")
parser.add_argument("--gfs-file", type=str, default=None, help="Overlay GFS data on wind trace.")
parser.add_argument("--csv-dump", type=str, default=None, help="Dump telemetry to CSV file.")
args = parser.parse_args()
# Configure logging
@ -432,7 +454,7 @@ if __name__ == "__main__":
_log_entries = read_file(args.filename)
_car, _telemetry = extract_data(_log_entries)
_car, _telemetry = extract_data(_log_entries, csv_dump=args.csv_dump)
for _call in _telemetry:
logging.info("Processing Callsign: %s" % _call)