diff options
| author | Keith Packard <keithp@keithp.com> | 2009-09-06 20:26:17 -0700 | 
|---|---|---|
| committer | Keith Packard <keithp@keithp.com> | 2009-09-06 20:26:17 -0700 | 
| commit | 932f1539b38567e565fd484171c13539b1467308 (patch) | |
| tree | 485485df3cef45614c861da39b987bedb0aec190 | |
| parent | 9177f5f4e9d832558ddd9ab227c4511f6201e7e5 (diff) | |
Color plots, integrate only flight portion of data.
Telemetry files have piles of pad data which shouldn't be integrated
into the velocity data as it tends to generate huge values from the
noise of the sensor.
Also make the data lines colored to keep them visually distinct from
the rest of the plot image.
Signed-off-by: Keith Packard <keithp@keithp.com>
| -rw-r--r-- | ao-tools/ao-postflight/ao-postflight.1 | 22 | ||||
| -rw-r--r-- | ao-tools/ao-postflight/ao-postflight.c | 118 | ||||
| -rw-r--r-- | ao-tools/lib/cc-analyse.c | 14 | ||||
| -rw-r--r-- | ao-tools/lib/cc-integrate.c | 21 | ||||
| -rw-r--r-- | ao-tools/lib/cc-period.c | 26 | ||||
| -rw-r--r-- | ao-tools/lib/cc-process.c | 20 | ||||
| -rw-r--r-- | ao-tools/lib/cc.h | 12 | 
7 files changed, 180 insertions, 53 deletions
| diff --git a/ao-tools/ao-postflight/ao-postflight.1 b/ao-tools/ao-postflight/ao-postflight.1 index ac1c18a4..eca4bb34 100644 --- a/ao-tools/ao-postflight/ao-postflight.1 +++ b/ao-tools/ao-postflight/ao-postflight.1 @@ -23,15 +23,29 @@ ao-postflight \- Analyse a flight log (either telemetry or eeprom)  .B "ao-postflight"  [\-s <summary-file>]  [\--summary=<summary-file>] -[\-d <detail-file] +[\-d <detail-file>]  [\--detail=<detail-file>] +[\-r <raw-file>] +[\--raw=<raw-file>]  [\-p <plot-file>]  [\--plot=<plot-file>]  {flight.eeprom|flight.telem}  .SH DESCRIPTION  .I ao-postflight -reads the specified flight log and produces a summary of the flight on -stdout or to the specified file along with an optional .svg format -plot and detailed table of time/height/speed/accel. +reads the specified flight log and produces several different kinds of +output. +.IP Summary +By default, summary information is shown on stdout. With the --summary +option, it can be redirected to a file. +.IP Detail +When requested with the --detail option, a filtered version of the +flight position, speed and acceleration are written to the specified +file. +.IP Raw +The --raw option writes the unfiltered, but converted acceleration +and height data to the specified file. +.IP Plot +The --plot option writes plots of height, speed and acceleration to +the specified file in .svg format  .SH AUTHOR  Keith Packard diff --git a/ao-tools/ao-postflight/ao-postflight.c b/ao-tools/ao-postflight/ao-postflight.c index 4ca39c24..ded2f3c2 100644 --- a/ao-tools/ao-postflight/ao-postflight.c +++ b/ao-tools/ao-postflight/ao-postflight.c @@ -39,9 +39,19 @@ static const char *state_names[] = {  	"invalid"  }; +static int plot_colors[3][3] = { +	{ 0, 0x90, 0 },	/* height */ +	{ 0xa0, 0, 0 },	/* speed */ +	{ 0, 0, 0xc0 },	/* accel */ +}; + +#define PLOT_HEIGHT	0 +#define PLOT_SPEED	1 +#define PLOT_ACCEL	2 +  static void  plot_perioddata(struct cc_perioddata *d, char *axis_label, char *plot_label, -		double min_time, double max_time) +		double min_time, double max_time, int plot_type)  {  	double	*times;  	double	ymin, ymax; @@ -60,11 +70,58 @@ plot_perioddata(struct cc_perioddata *d, char *axis_label, char *plot_label,  	ymax_i = cc_perioddata_max(d, min_time, max_time);  	ymin = d->data[ymin_i];  	ymax = d->data[ymax_i]; +	plscol0(1, 0, 0, 0); +	plscol0(2, plot_colors[plot_type][0],  plot_colors[plot_type][1],  plot_colors[plot_type][2]); +	plcol0(1);  	plenv(times[0], times[stop-start],  	      ymin, ymax, 0, 2); -	plcol0(1);  	pllab("Time", axis_label, plot_label); +	plcol0(2);  	plline(stop - start + 1, times, d->data + start); +	free(times); +} + +static void +plot_timedata(struct cc_timedata *d, char *axis_label, char *plot_label, +		double min_time, double max_time) +{ +	double	*times; +	double	*values; +	double	ymin, ymax; +	int	ymin_i, ymax_i; +	int	i; +	int	start = -1, stop = -1; +	double	start_time = 0, stop_time = 0; +	int	num; + +	for (i = 0; i < d->num; i++) { +		if (start < 0 && d->data[i].time >= min_time) { +			start_time = d->data[i].time; +			start = i; +		} +		if (d->data[i].time <= max_time) { +			stop_time = d->data[i].time; +			stop = i; +		} +	} + +	times = calloc(stop - start + 1, sizeof (double)); +	values = calloc(stop - start + 1, sizeof (double)); + +	ymin_i = cc_timedata_min(d, min_time, max_time); +	ymax_i = cc_timedata_max(d, min_time, max_time); +	ymin = d->data[ymin_i].value; +	ymax = d->data[ymax_i].value; +	plcol0(1); +	pllab("Time", axis_label, plot_label); +	for (i = start; i <= stop; i++) { +		times[i-start] = (d->data[i].time - start_time)/100.0; +		values[i-start] = d->data[i].value; +	} +	plenv(times[0], times[stop-start], ymin, ymax, 0, 2); +	plline(stop - start + 1, times, values); +	free(times); +	free(values);  }  static struct cc_perioddata * @@ -102,7 +159,7 @@ merge_data(struct cc_perioddata *first, struct cc_perioddata *last, double split  }  static void -analyse_flight(struct cc_flightraw *f, FILE *summary_file, FILE *detail_file, char *plot_name) +analyse_flight(struct cc_flightraw *f, FILE *summary_file, FILE *detail_file, FILE *raw_file, char *plot_name)  {  	double	height;  	double	accel; @@ -241,6 +298,17 @@ analyse_flight(struct cc_flightraw *f, FILE *summary_file, FILE *detail_file, ch  			       time, pos, speed, accel);  		}  	} +	if (raw_file) { +		fprintf(raw_file, "%9s %9s %9s\n", +		       "time", "height", "accel"); +		for (i = 0; i < cooked->pres.num; i++) { +			double time = cooked->pres.data[i].time; +			double pres = cooked->pres.data[i].value; +			double accel = cooked->accel.data[i].value; +			fprintf(raw_file, "%9.2f %9.2f %9.2f %9.2f\n", +				time, pres, accel); +		} +	}  	if (cooked && plot_name) {  		struct cc_perioddata	*speed;  		plsdev("svgcairo"); @@ -252,12 +320,12 @@ analyse_flight(struct cc_flightraw *f, FILE *summary_file, FILE *detail_file, ch  		plstar(2, 3);  		speed = merge_data(&cooked->accel_speed, &cooked->pres_speed, apogee); -		plot_perioddata(&cooked->pres_pos, "meters", "Height", -1e10, 1e10); -		plot_perioddata(&cooked->pres_pos, "meters", "Height", boost_start, apogee); -		plot_perioddata(speed, "meters/second", "Speed", -1e10, 1e10); -		plot_perioddata(speed, "meters/second", "Speed", boost_start, apogee); -		plot_perioddata(&cooked->accel_accel, "meters/second²", "Acceleration", -1e10, 1e10); -		plot_perioddata(&cooked->accel_accel, "meters/second²", "Acceleration", boost_start, apogee); +		plot_perioddata(&cooked->pres_pos, "meters", "Height", -1e10, 1e10, PLOT_HEIGHT); +		plot_perioddata(&cooked->pres_pos, "meters", "Height to Apogee", boost_start, apogee, PLOT_HEIGHT); +		plot_perioddata(speed, "meters/second", "Speed", -1e10, 1e10, PLOT_SPEED); +		plot_perioddata(speed, "meters/second", "Speed to Apogee", boost_start, apogee, PLOT_SPEED); +		plot_perioddata(&cooked->accel_accel, "meters/second²", "Acceleration", -1e10, 1e10, PLOT_ACCEL); +		plot_perioddata(&cooked->accel_accel, "meters/second²", "Acceleration to Apogee", boost_start, apogee, PLOT_ACCEL);  		free(speed->data);  		free(speed);  		plend(); @@ -270,12 +338,18 @@ static const struct option options[] = {  	{ .name = "summary", .has_arg = 1, .val = 's' },  	{ .name = "detail", .has_arg = 1, .val = 'd' },  	{ .name = "plot", .has_arg = 1, .val = 'p' }, +	{ .name = "raw", .has_arg = 1, .val = 'r' },  	{ 0, 0, 0, 0},  };  static void usage(char *program)  { -	fprintf(stderr, "usage: %s [--summary=<summary-file>] [-s <summary-file>] [--detail=<detail-file] [-d <detail-file>] [--plot=<plot-file> -p <plot-file>] {flight-log} ...\n", program); +	fprintf(stderr, "usage: %s\n" +		"\t[--summary=<summary-file>] [-s <summary-file>]\n" +		"\t[--detail=<detail-file] [-d <detail-file>]\n" +		"\t[--raw=<raw-file> -r <raw-file]\n" +		"\t[--plot=<plot-file> -p <plot-file>]\n" +		"\t{flight-log} ...\n", program);  	exit(1);  } @@ -283,18 +357,21 @@ int  main (int argc, char **argv)  {  	FILE			*file; -	FILE			*summary_file; -	FILE			*detail_file; +	FILE			*summary_file = NULL; +	FILE			*detail_file = NULL; +	FILE			*raw_file = NULL;  	int			i;  	int			ret = 0;  	struct cc_flightraw	*raw;  	int			c;  	int			serial;  	char			*s; -	char			*summary_name = NULL, *detail_name = NULL; +	char			*summary_name = NULL; +	char			*detail_name = NULL; +	char			*raw_name = NULL;  	char			*plot_name = NULL; -	while ((c = getopt_long(argc, argv, "s:d:p:", options, NULL)) != -1) { +	while ((c = getopt_long(argc, argv, "s:d:p:r:", options, NULL)) != -1) {  		switch (c) {  		case 's':  			summary_name = optarg; @@ -305,13 +382,15 @@ main (int argc, char **argv)  		case 'p':  			plot_name = optarg;  			break; +		case 'r': +			raw_name = optarg; +			break;  		default:  			usage(argv[0]);  			break;  		}  	}  	summary_file = stdout; -	detail_file = NULL;  	if (summary_name) {  		summary_file = fopen(summary_name, "w");  		if (!summary_file) { @@ -330,6 +409,13 @@ main (int argc, char **argv)  			}  		}  	} +	if (raw_name) { +		raw_file = fopen (raw_name, "w"); +		if (!raw_file) { +			perror(raw_name); +			exit(1); +		} +	}  	for (i = optind; i < argc; i++) {  		file = fopen(argv[i], "r");  		if (!file) { @@ -350,7 +436,7 @@ main (int argc, char **argv)  		}  		if (!raw->serial)  			raw->serial = serial; -		analyse_flight(raw, summary_file, detail_file, plot_name); +		analyse_flight(raw, summary_file, detail_file, raw_file, plot_name);  		cc_flightraw_free(raw);  	}  	return ret; diff --git a/ao-tools/lib/cc-analyse.c b/ao-tools/lib/cc-analyse.c index cdb16f02..27c416a6 100644 --- a/ao-tools/lib/cc-analyse.c +++ b/ao-tools/lib/cc-analyse.c @@ -18,6 +18,20 @@  #include "cc.h"  #include <math.h> +void +cc_timedata_limits(struct cc_timedata *d, double min_time, double max_time, int *start, int *stop) +{ +	int	i; + +	*start = -1; +	for (i = 0; i < d->num; i++) { +		if (*start < 0 && min_time <= d->data[i].time) +			*start = i; +		if (d->data[i].time <= max_time) +			*stop = i; +	} +} +  int  cc_timedata_min(struct cc_timedata *d, double min_time, double max_time)  { diff --git a/ao-tools/lib/cc-integrate.c b/ao-tools/lib/cc-integrate.c index f9793dcd..ba50761b 100644 --- a/ao-tools/lib/cc-integrate.c +++ b/ao-tools/lib/cc-integrate.c @@ -37,24 +37,27 @@ cc_timedata_convert(struct cc_timedata *d, double (*f)(double v, double a), doub  }  struct cc_timedata * -cc_timedata_integrate(struct cc_timedata *d) +cc_timedata_integrate(struct cc_timedata *d, double min_time, double max_time)  {  	struct cc_timedata	*i; -	int			n; +	int			n, m; +	int			start, stop; +	cc_timedata_limits(d, min_time, max_time, &start, &stop);  	i = calloc (1, sizeof (struct cc_timedata)); -	i->num = d->num; -	i->size = d->num; +	i->num = stop - start + 1; +	i->size = i->num;  	i->data = calloc (i->size, sizeof (struct cc_timedataelt)); -	i->time_offset = d->time_offset; -	for (n = 0; n < d->num; n++) { -		i->data[n].time = d->data[n].time; +	i->time_offset = d->data[start].time; +	for (n = 0; n < i->num; n++) { +		m = n + start; +		i->data[n].time = d->data[m].time;  		if (n == 0) {  			i->data[n].value = 0;  		} else {  			i->data[n].value = i->data[n-1].value + -				(d->data[n].value + d->data[n-1].value) / 2 * -				((d->data[n].time - d->data[n-1].time) / 100.0); +				(d->data[m].value + d->data[m-1].value) / 2 * +				((d->data[m].time - d->data[m-1].time) / 100.0);  		}  	}  	return i; diff --git a/ao-tools/lib/cc-period.c b/ao-tools/lib/cc-period.c index c74cf9dc..2a4e5952 100644 --- a/ao-tools/lib/cc-period.c +++ b/ao-tools/lib/cc-period.c @@ -17,35 +17,27 @@  #include "cc.h"  #include <stdlib.h> +#include <math.h>  struct cc_perioddata *  cc_period_make(struct cc_timedata *td, double start_time, double stop_time)  {  	int			len = stop_time - start_time + 1;  	struct cc_perioddata	*pd; -	int			i; -	double			prev_time; -	double			next_time; -	double			interval; +	int			i, j; +	double			t;  	pd = calloc(1, sizeof (struct cc_perioddata));  	pd->start = start_time;  	pd->step = 1;  	pd->num = len;  	pd->data = calloc(len, sizeof(double)); -	prev_time = start_time; -	for (i = 0; i < td->num; i++) { -		if (start_time <= td->data[i].time && td->data[i].time <= stop_time) { -			int	pos = td->data[i].time - start_time; - -			if (i < td->num - 1 && td->data[i+1].time < stop_time) -				next_time = (td->data[i].time + td->data[i+1].time) / 2.0; -			else -				next_time = stop_time; -			interval = next_time - prev_time; -			pd->data[pos] = td->data[i].value * interval; -			prev_time = next_time; -		} +	j = 0; +	for (i = 0; i < pd->num; i++) { +		t = start_time + i * pd->step; +		while (j < td->num - 1 && fabs(t - td->data[j].time) > fabs(t - td->data[j+1].time)) +			j++; +		pd->data[i] = td->data[j].value;  	}  	return pd;  } diff --git a/ao-tools/lib/cc-process.c b/ao-tools/lib/cc-process.c index 469ad2f2..5c1acc6b 100644 --- a/ao-tools/lib/cc-process.c +++ b/ao-tools/lib/cc-process.c @@ -33,8 +33,6 @@ cook_timed(struct cc_timedata *td, struct cc_perioddata *pd,  	free (filtered);  	free (unfiltered->data);  	free (unfiltered); -	free (td->data); -	free (td);  }  static double @@ -93,11 +91,15 @@ cc_flight_cook(struct cc_flightraw *raw)  	} else {  		flight_stop = raw->accel.data[raw->accel.num-1].time;  	} +	cooked->flight_start = flight_start; +	cooked->flight_stop = flight_stop;  	/* Integrate the accelerometer data to get speed and position */  	accel = cc_timedata_convert(&raw->accel, cc_accelerometer_to_acceleration, raw->ground_accel); -	accel_speed = cc_timedata_integrate(accel); -	accel_pos = cc_timedata_integrate(accel_speed); +	cooked->accel = *accel; +	free(accel); +	accel_speed = cc_timedata_integrate(&cooked->accel, flight_start - 10, flight_stop); +	accel_pos = cc_timedata_integrate(accel_speed, flight_start - 10, flight_stop);  #define ACCEL_OMEGA_PASS	(2 * M_PI * 5 / 100)  #define ACCEL_OMEGA_STOP	(2 * M_PI * 8 / 100) @@ -105,20 +107,24 @@ cc_flight_cook(struct cc_flightraw *raw)  #define BARO_OMEGA_STOP		(2 * M_PI * 1 / 100)  #define FILTER_ERROR		(1e-8) -	cook_timed(accel, &cooked->accel_accel, +	cook_timed(&cooked->accel, &cooked->accel_accel,  		   flight_start, flight_stop,  		   ACCEL_OMEGA_PASS, ACCEL_OMEGA_STOP, FILTER_ERROR);  	cook_timed(accel_speed, &cooked->accel_speed,  		   flight_start, flight_stop,  		   ACCEL_OMEGA_PASS, ACCEL_OMEGA_STOP, FILTER_ERROR); +	free(accel_speed->data); free(accel_speed);  	cook_timed(accel_pos, &cooked->accel_pos,  		   flight_start, flight_stop,  		   ACCEL_OMEGA_PASS, ACCEL_OMEGA_STOP, FILTER_ERROR); +	free(accel_pos->data); free(accel_pos);  	/* Filter the pressure data */  	pres = cc_timedata_convert(&raw->pres, barometer_to_altitude,  				   cc_barometer_to_altitude(raw->ground_pres)); -	cook_timed(pres, &cooked->pres_pos, +	cooked->pres = *pres; +	free(pres); +	cook_timed(&cooked->pres, &cooked->pres_pos,  		   flight_start, flight_stop,  		   BARO_OMEGA_PASS, BARO_OMEGA_STOP, FILTER_ERROR);  	/* differentiate twice to get to acceleration */ @@ -154,5 +160,7 @@ cc_flightcooked_free(struct cc_flightcooked *cooked)  	if_free(cooked->gps_lon.data);  	if_free(cooked->gps_alt.data);  	if_free(cooked->state.data); +	if_free(cooked->accel.data); +	if_free(cooked->pres.data);  	free(cooked);  } diff --git a/ao-tools/lib/cc.h b/ao-tools/lib/cc.h index 4e9aadc4..01226958 100644 --- a/ao-tools/lib/cc.h +++ b/ao-tools/lib/cc.h @@ -142,6 +142,9 @@ void  cc_flightraw_free(struct cc_flightraw *raw);  struct cc_flightcooked { +	double			flight_start; +	double			flight_stop; +  	struct cc_perioddata	accel_accel;  	struct cc_perioddata	accel_speed;  	struct cc_perioddata	accel_pos; @@ -151,6 +154,10 @@ struct cc_flightcooked {  	struct cc_perioddata	gps_lat;  	struct cc_perioddata	gps_lon;  	struct cc_perioddata	gps_alt; + +	/* unfiltered, but converted */ +	struct cc_timedata	pres; +	struct cc_timedata	accel;  	struct cc_timedata	state;  }; @@ -262,6 +269,9 @@ cc_great_circle (double start_lat, double start_lon,  		 double end_lat, double end_lon,  		 double *dist, double *bearing); +void +cc_timedata_limits(struct cc_timedata *d, double min_time, double max_time, int *start, int *stop); +  int  cc_timedata_min(struct cc_timedata *d, double min_time, double max_time); @@ -314,7 +324,7 @@ struct cc_timedata *  cc_timedata_convert(struct cc_timedata *d, double (*f)(double v, double a), double a);  struct cc_timedata * -cc_timedata_integrate(struct cc_timedata *d); +cc_timedata_integrate(struct cc_timedata *d, double min_time, double max_time);  struct cc_perioddata *  cc_perioddata_differentiate(struct cc_perioddata *i); | 
