From c46e832b28820d7c5be4efaacbbd7c0607927fe5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 5 Sep 2009 22:03:31 -0700 Subject: Add simple post-flight analysis tool (ao-postflight) This tool reads either an eeprom or telem log file and displays some rudimentary data (max accel/alt for each flight stage). Signed-off-by: Keith Packard --- ao-tools/lib/cc-logfile.c | 218 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 218 insertions(+) create mode 100644 ao-tools/lib/cc-logfile.c (limited to 'ao-tools/lib/cc-logfile.c') diff --git a/ao-tools/lib/cc-logfile.c b/ao-tools/lib/cc-logfile.c new file mode 100644 index 00000000..444ff089 --- /dev/null +++ b/ao-tools/lib/cc-logfile.c @@ -0,0 +1,218 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "cc.h" +#include +#include + +static int +timedata_add(struct cc_timedata *data, double time, double value) +{ + struct cc_timedataelt *newdata; + int newsize; + if (data->size == data->num) { + if (data->size == 0) + newdata = malloc((newsize = 256) * sizeof (struct cc_timedataelt)); + else + newdata = realloc (data->data, (newsize = data->size * 2) + * sizeof (struct cc_timedataelt)); + if (!newdata) + return 0; + data->size = newsize; + data->data = newdata; + } + if (data->num && data->data[data->num-1].time > time) + time += 65536; + data->data[data->num].time = time; + data->data[data->num].value = value; + data->num++; + return 1; +} + +static void +timedata_free(struct cc_timedata *data) +{ + if (data->data) + free(data->data); +} + +static int +gpsdata_add(struct cc_gpsdata *data, struct cc_gpselt *elt) +{ + struct cc_gpselt *newdata; + int newsize; + if (data->size == data->num) { + if (data->size == 0) + newdata = malloc((newsize = 256) * sizeof (struct cc_gpselt)); + else + newdata = realloc (data->data, (newsize = data->size * 2) + * sizeof (struct cc_gpselt)); + if (!newdata) + return 0; + data->size = newsize; + data->data = newdata; + } + data->data[data->num] = *elt; + data->num++; + return 1; +} + +static void +gpsdata_free(struct cc_gpsdata *data) +{ + if (data->data) + free(data->data); +} + +#define AO_LOG_FLIGHT 'F' +#define AO_LOG_SENSOR 'A' +#define AO_LOG_TEMP_VOLT 'T' +#define AO_LOG_DEPLOY 'D' +#define AO_LOG_STATE 'S' +#define AO_LOG_GPS_TIME 'G' +#define AO_LOG_GPS_LAT 'N' +#define AO_LOG_GPS_LON 'W' +#define AO_LOG_GPS_ALT 'H' +#define AO_LOG_GPS_SAT 'V' + +#define AO_LOG_POS_NONE (~0UL) + +static int +read_eeprom(const char *line, struct cc_flightraw *f, double *ground_pres, int *ground_pres_count) +{ + char type; + int tick; + int a, b; + struct cc_gpselt gps; + int serial; + + if (sscanf(line, "serial-number %u", &serial) == 1) { + f->serial = serial; + return 1; + } + if (sscanf(line, "%c %x %x %x", &type, &tick, &a, &b) != 4) + return 0; + switch (type) { + case AO_LOG_FLIGHT: + f->ground_accel = a; + f->ground_pres = 0; + f->flight = b; + *ground_pres = 0; + *ground_pres_count = 0; + break; + case AO_LOG_SENSOR: + timedata_add(&f->accel, tick, a); + timedata_add(&f->pres, tick, b); + if (*ground_pres_count < 20) { + *ground_pres += b; + (*ground_pres_count)++; + if (*ground_pres_count >= 20) + f->ground_pres = *ground_pres / *ground_pres_count; + } + break; + case AO_LOG_TEMP_VOLT: + timedata_add(&f->temp, tick, a); + timedata_add(&f->volt, tick, b); + break; + case AO_LOG_DEPLOY: + timedata_add(&f->drogue, tick, a); + timedata_add(&f->main, tick, b); + break; + case AO_LOG_STATE: + timedata_add(&f->state, tick, a); + break; + case AO_LOG_GPS_TIME: + gps.time = tick; + break; + case AO_LOG_GPS_LAT: + gps.lat = ((int32_t) (a + (b << 16))) / 10000000.0; + break; + case AO_LOG_GPS_LON: + gps.lon = ((int32_t) (a + (b << 16))) / 10000000.0; + break; + case AO_LOG_GPS_ALT: + gps.alt = ((int32_t) (a + (b << 16))); + gpsdata_add(&f->gps, &gps); + break; + case AO_LOG_GPS_SAT: + break; + default: + return 0; + } + return 1; +} + +static int +read_telem(const char *line, struct cc_flightraw *f) +{ + struct cc_telem telem; + struct cc_gpselt gps; + if (!cc_telem_parse(line, &telem)) + return 0; + f->ground_accel = telem.ground_accel; + f->ground_pres = telem.ground_pres; + f->flight = 0; + timedata_add(&f->accel, telem.tick, telem.flight_accel); + timedata_add(&f->pres, telem.tick, telem.flight_pres); + timedata_add(&f->temp, telem.tick, telem.temp); + timedata_add(&f->volt, telem.tick, telem.batt); + timedata_add(&f->drogue, telem.tick, telem.drogue); + timedata_add(&f->main, telem.tick, telem.main); + if (telem.gps.gps_locked) { + gps.time = telem.tick; + gps.lat = telem.gps.lat; + gps.lon = telem.gps.lon; + gps.alt = telem.gps.alt; + gpsdata_add(&f->gps, &gps); + } + return 1; +} + +struct cc_flightraw * +cc_log_read(FILE *file) +{ + struct cc_flightraw *f; + char line[8192]; + double ground_pres; + int ground_pres_count; + + f = calloc(1, sizeof (struct cc_flightraw)); + if (!f) + return NULL; + while (fgets(line, sizeof (line), file)) { + if (read_eeprom(line, f, &ground_pres, &ground_pres_count)) + continue; + if (read_telem(line, f)) + continue; + fprintf (stderr, "invalid line: %s", line); + } + return f; +} + +void +cc_flightraw_free(struct cc_flightraw *raw) +{ + timedata_free(&raw->accel); + timedata_free(&raw->pres); + timedata_free(&raw->temp); + timedata_free(&raw->volt); + timedata_free(&raw->main); + timedata_free(&raw->drogue); + timedata_free(&raw->state); + gpsdata_free(&raw->gps); + free(raw); +} -- cgit v1.2.3 From 6d018ab933832e2d80bb1564c339d9fb18b57be2 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 5 Sep 2009 22:45:49 -0700 Subject: Handle vageries of .telem files in ao-postflight Telem files have multiple entries of the same state, and sometimes long gaps between recordings. Deal with this as best as possible. Signed-off-by: Keith Packard --- ao-tools/ao-postflight/ao-postflight.c | 60 +++++++++++++++++++++------------- ao-tools/lib/cc-analyse.c | 8 ++--- ao-tools/lib/cc-logfile.c | 35 +++++++++++++++++++- ao-tools/lib/cc.h | 3 +- 4 files changed, 77 insertions(+), 29 deletions(-) (limited to 'ao-tools/lib/cc-logfile.c') diff --git a/ao-tools/ao-postflight/ao-postflight.c b/ao-tools/ao-postflight/ao-postflight.c index f0e2c2ae..9371f351 100644 --- a/ao-tools/ao-postflight/ao-postflight.c +++ b/ao-tools/ao-postflight/ao-postflight.c @@ -81,43 +81,57 @@ analyse_flight(struct cc_flightraw *f) pres_i = cc_timedata_min(&f->pres, f->pres.data[0].time, f->pres.data[f->pres.num-1].time); - min_pres = f->pres.data[pres_i].value; - height = cc_barometer_to_altitude(min_pres) - - cc_barometer_to_altitude(f->ground_pres); - printf ("Max height: %9.2fm %9.2fft %9.2fs\n", - height, height * 100 / 2.54 / 12, - (f->pres.data[pres_i].time - boost_start) / 100.0); + if (pres_i) + { + min_pres = f->pres.data[pres_i].value; + height = cc_barometer_to_altitude(min_pres) - + cc_barometer_to_altitude(f->ground_pres); + printf ("Max height: %9.2fm %9.2fft %9.2fs\n", + height, height * 100 / 2.54 / 12, + (f->pres.data[pres_i].time - boost_start) / 100.0); + } accel_i = cc_timedata_min(&f->accel, boost_start, boost_stop); - accel = cc_accelerometer_to_acceleration(f->accel.data[accel_i].value, - f->ground_accel); - printf ("Max accel: %9.2fm/s² %9.2fg %9.2fs\n", - accel, accel / 9.80665, - (f->accel.data[accel_i].time - boost_start) / 100.0); + if (accel_i) + { + accel = cc_accelerometer_to_acceleration(f->accel.data[accel_i].value, + f->ground_accel); + printf ("Max accel: %9.2fm/s² %9.2fg %9.2fs\n", + accel, accel / 9.80665, + (f->accel.data[accel_i].time - boost_start) / 100.0); + } for (i = 0; i < f->state.num; i++) { state = f->state.data[i].value; state_start = f->state.data[i].time; + while (i < f->state.num - 1 && f->state.data[i+1].value == state) + i++; if (i < f->state.num - 1) - state_stop = f->state.data[i+1].time; + state_stop = f->state.data[i + 1].time; else state_stop = f->accel.data[f->accel.num-1].time; printf("State: %s\n", state_names[state]); printf("\tStart: %9.2fs\n", (state_start - boost_start) / 100.0); printf("\tDuration: %9.2fs\n", (state_stop - state_start) / 100.0); accel_i = cc_timedata_min(&f->accel, state_start, state_stop); - accel = cc_accelerometer_to_acceleration(f->accel.data[accel_i].value, - f->ground_accel); - printf("\tMax accel: %9.2fm/s² %9.2fg %9.2fs\n", - accel, accel / 9.80665, - (f->accel.data[accel_i].time - boost_start) / 100.0); + if (accel_i >= 0) + { + accel = cc_accelerometer_to_acceleration(f->accel.data[accel_i].value, + f->ground_accel); + printf("\tMax accel: %9.2fm/s² %9.2fg %9.2fs\n", + accel, accel / 9.80665, + (f->accel.data[accel_i].time - boost_start) / 100.0); + } pres_i = cc_timedata_min(&f->pres, state_start, state_stop); - min_pres = f->pres.data[pres_i].value; - height = cc_barometer_to_altitude(min_pres) - - cc_barometer_to_altitude(f->ground_pres); - printf ("\tMax height: %9.2fm %9.2fft %9.2fs\n", - height, height * 100 / 2.54 / 12, - (f->pres.data[pres_i].time - boost_start) / 100.0); + if (pres_i >= 0) + { + min_pres = f->pres.data[pres_i].value; + height = cc_barometer_to_altitude(min_pres) - + cc_barometer_to_altitude(f->ground_pres); + printf ("\tMax height: %9.2fm %9.2fft %9.2fs\n", + height, height * 100 / 2.54 / 12, + (f->pres.data[pres_i].time - boost_start) / 100.0); + } } } diff --git a/ao-tools/lib/cc-analyse.c b/ao-tools/lib/cc-analyse.c index 6fd36cdc..fc8a8417 100644 --- a/ao-tools/lib/cc-analyse.c +++ b/ao-tools/lib/cc-analyse.c @@ -22,11 +22,11 @@ cc_timedata_min(struct cc_timedata *d, double min_time, double max_time) { int i; int set = 0; - int min_i; + int min_i = -1; double min; if (d->num == 0) - return 0; + return -1; for (i = 0; i < d->num; i++) if (min_time <= d->data[i].time && d->data[i].time <= max_time) if (!set || d->data[i].value < min) { @@ -42,11 +42,11 @@ cc_timedata_max(struct cc_timedata *d, double min_time, double max_time) { int i; double max; - int max_i; + int max_i = -1; int set = 0; if (d->num == 0) - return 0; + return -1; for (i = 0; i < d->num; i++) if (min_time <= d->data[i].time && d->data[i].time <= max_time) if (!set || d->data[i].value > max) { diff --git a/ao-tools/lib/cc-logfile.c b/ao-tools/lib/cc-logfile.c index 444ff089..4abf7eb6 100644 --- a/ao-tools/lib/cc-logfile.c +++ b/ao-tools/lib/cc-logfile.c @@ -18,6 +18,7 @@ #include "cc.h" #include #include +#include static int timedata_add(struct cc_timedata *data, double time, double value) @@ -35,8 +36,11 @@ timedata_add(struct cc_timedata *data, double time, double value) data->size = newsize; data->data = newdata; } - if (data->num && data->data[data->num-1].time > time) + time += data->time_offset; + if (data->num && data->data[data->num-1].time > time) { + data->time_offset += 65536; time += 65536; + } data->data[data->num].time = time; data->data[data->num].value = value; data->num++; @@ -66,6 +70,11 @@ gpsdata_add(struct cc_gpsdata *data, struct cc_gpselt *elt) data->size = newsize; data->data = newdata; } + elt->time += data->time_offset; + if (data->num && data->data[data->num-1].time > elt->time) { + data->time_offset += 65536; + elt->time += 65536; + } data->data[data->num] = *elt; data->num++; return 1; @@ -156,6 +165,29 @@ read_eeprom(const char *line, struct cc_flightraw *f, double *ground_pres, int * return 1; } +static const char *state_names[] = { + "startup", + "idle", + "pad", + "boost", + "fast", + "coast", + "drogue", + "main", + "landed", + "invalid" +}; + +static enum ao_flight_state +state_name_to_state(char *state_name) +{ + enum ao_flight_state state; + for (state = ao_flight_startup; state < ao_flight_invalid; state++) + if (!strcmp(state_names[state], state_name)) + return state; + return ao_flight_invalid; +} + static int read_telem(const char *line, struct cc_flightraw *f) { @@ -172,6 +204,7 @@ read_telem(const char *line, struct cc_flightraw *f) timedata_add(&f->volt, telem.tick, telem.batt); timedata_add(&f->drogue, telem.tick, telem.drogue); timedata_add(&f->main, telem.tick, telem.main); + timedata_add(&f->state, telem.tick, state_name_to_state(telem.state)); if (telem.gps.gps_locked) { gps.time = telem.tick; gps.lat = telem.gps.lat; diff --git a/ao-tools/lib/cc.h b/ao-tools/lib/cc.h index 3975cf1b..57f80b8d 100644 --- a/ao-tools/lib/cc.h +++ b/ao-tools/lib/cc.h @@ -75,6 +75,7 @@ struct cc_timedata { int num; int size; struct cc_timedataelt *data; + double time_offset; }; @@ -92,8 +93,8 @@ struct cc_gpselt { struct cc_gpsdata { int num; int size; - double time_offset; struct cc_gpselt *data; + double time_offset; }; /* -- cgit v1.2.3