diff options
| author | Keith Packard <keithp@keithp.com> | 2017-06-27 23:36:05 -0700 | 
|---|---|---|
| committer | Keith Packard <keithp@keithp.com> | 2017-06-27 23:36:05 -0700 | 
| commit | 46ff12a88136d3c274610255a918870aff9328cd (patch) | |
| tree | 0fac5fbe7cf34a695c6278c34e3b97ce73fdaa62 | |
| parent | 13abb6739ae9be5a8733724c5d9b3f714f32bea4 (diff) | |
altoslib: Deal with multiple motors in flight stats
Combine boost/fast/coast sections when computing ascent stats.
Signed-off-by: Keith Packard <keithp@keithp.com>
| -rw-r--r-- | altoslib/AltosFlightStats.java | 90 | ||||
| -rw-r--r-- | altoslib/AltosTimeSeries.java | 41 | ||||
| -rw-r--r-- | altosuilib/AltosFlightStatsTable.java | 18 | 
3 files changed, 86 insertions, 63 deletions
diff --git a/altoslib/AltosFlightStats.java b/altoslib/AltosFlightStats.java index 2b6530c8..7159cc35 100644 --- a/altoslib/AltosFlightStats.java +++ b/altoslib/AltosFlightStats.java @@ -27,8 +27,7 @@ public class AltosFlightStats {  	public double		max_acceleration;  	public double[]		state_speed = new double[AltosLib.ao_flight_invalid + 1];  	public double[]		state_accel = new double[AltosLib.ao_flight_invalid + 1]; -	public double[]		state_start = new double[AltosLib.ao_flight_invalid + 1]; -	public double[]		state_end = new double[AltosLib.ao_flight_invalid + 1]; +	public double[]		state_time = new double[AltosLib.ao_flight_invalid + 1];  	public String		product;  	public String		firmware_version;  	public int		serial; @@ -126,6 +125,28 @@ public class AltosFlightStats {  		return boost_time;  	} +	private void add_times(AltosFlightSeries series, int state, double start_time, double end_time) { +		double delta_time = end_time - start_time; +		if (0 <= state && state <= AltosLib.ao_flight_invalid && delta_time > 0) { +			speeds[state].value += series.speed_series.average(start_time, end_time) * delta_time; +			speeds[state].time += delta_time; +			accels[state].value += series.accel_series.average(start_time, end_time) * delta_time; +			accels[state].time += delta_time; +			state_time[state] += delta_time; + +			if (state == AltosLib.ao_flight_boost) { +				AltosTimeValue tv_speed = series.speed_series.max(start_time, end_time); +				if (tv_speed != null && (max_speed == AltosLib.MISSING || tv_speed.value > max_speed)) +					max_speed = tv_speed.value; +				AltosTimeValue tv_accel = series.accel_series.max(start_time, end_time); +				if (tv_accel != null && (max_acceleration == AltosLib.MISSING || tv_accel.value > max_acceleration)) +					max_acceleration = tv_accel.value; +			} +		} +	} + +	AltosTimeValue[]	speeds = new AltosTimeValue[AltosLib.ao_flight_invalid + 1]; +	AltosTimeValue[]	accels = new AltosTimeValue[AltosLib.ao_flight_invalid + 1];  	public AltosFlightStats(AltosFlightSeries series) {  		AltosCalData	cal_data = series.cal_data(); @@ -140,12 +161,12 @@ public class AltosFlightStats {  			boolean fixed_landed = false;  			for (AltosTimeValue state : series.state_series) {  				if ((int) state.value == AltosLib.ao_flight_boost) -					if (boost_time != AltosLib.MISSING) { +					if (boost_time != AltosLib.MISSING && !fixed_boost) {  						state.time = boost_time;  						fixed_boost = true;  					}  				if ((int) state.value == AltosLib.ao_flight_landed) -					if (landed_time != AltosLib.MISSING) { +					if (landed_time != AltosLib.MISSING && !fixed_landed) {  						state.time = landed_time;  						fixed_landed = true;  					} @@ -166,32 +187,33 @@ public class AltosFlightStats {  		has_mag = false;  		has_orient = false; -		for (int s = 0; s < AltosLib.ao_flight_invalid + 1; s++) -			state_speed[s] = state_accel[s] = state_start[s] = state_end[s] = AltosLib.MISSING; +		for (int s = 0; s < AltosLib.ao_flight_invalid + 1; s++) { +			state_speed[s] = AltosLib.MISSING; +			state_accel[s] = AltosLib.MISSING; +			state_time[s] = 0; +			speeds[s] = new AltosTimeValue(0, 0); +			accels[s] = new AltosTimeValue(0, 0); +		} + +		max_speed = AltosLib.MISSING; +		max_acceleration = AltosLib.MISSING;  		if (series.state_series != null) { +			AltosTimeValue prev = null;  			for (AltosTimeValue state : series.state_series) { -				int s = (int) state.value; - -				if (s < AltosLib.ao_flight_startup && AltosLib.ao_flight_landed < s) -					continue; - -				if (s == AltosLib.ao_flight_boost) -					state_start[s] = boost_time; -				else -					state_start[s] = series.state_series.time_of(s); - -				if (s == AltosLib.ao_flight_main) -					state_end[s] = landed_time; -				else -					state_end[s] = series.state_series.time_of(s+1); - -				if (series.speed_series != null) -					state_speed[s] = series.speed_series.average(state_start[s], state_end[s]); - -				if (series.accel_series != null) -					state_accel[s] = series.accel_series.average(state_start[s], state_end[s]); +				if (prev != null) +					add_times(series, (int) prev.value, prev.time, state.time); +				prev = state;  			} +			if (prev != null) +				add_times(series, (int) prev.value, prev.time, series.accel_series.last().time); +		} + +		for (int s = 0; s <= AltosLib.ao_flight_invalid; s++) { +			if (speeds[s].time > 0) +				state_speed[s] = speeds[s].value / speeds[s].time; +			if (accels[s].time > 0) +				state_accel[s] = accels[s].value / accels[s].time;  		}  		product = cal_data.product; @@ -229,22 +251,6 @@ public class AltosFlightStats {  		max_height = AltosLib.MISSING;  		if (series.height_series != null)  			max_height = series.height_series.max().value; -		max_speed = AltosLib.MISSING; -		if (series.speed_series != null) { -			AltosTimeValue tv = series.speed_series.max(state_start[AltosLib.ao_flight_boost], state_start[AltosLib.ao_flight_drogue]); -			if (tv == null) -				tv = series.speed_series.max(); -			if (tv != null) -				max_speed = tv.value; -		} -		max_acceleration = AltosLib.MISSING; -		if (series.accel_series != null) { -			AltosTimeValue tv = series.accel_series.max(state_start[AltosLib.ao_flight_boost], state_start[AltosLib.ao_flight_drogue]); -			if (tv == null) -				tv = series.accel_series.max(); -			if (tv != null) -				max_acceleration = tv.value; -		}  		max_gps_height = AltosLib.MISSING;  		if (series.gps_height != null) {  			AltosTimeValue tv = series.gps_height.max(); diff --git a/altoslib/AltosTimeSeries.java b/altoslib/AltosTimeSeries.java index b5d831be..b3c432fc 100644 --- a/altoslib/AltosTimeSeries.java +++ b/altoslib/AltosTimeSeries.java @@ -150,30 +150,47 @@ public class AltosTimeSeries implements Iterable<AltosTimeValue>, Comparable<Alt  		return min;  	} +	public AltosTimeValue first() { +		return values.get(0); +	} + +	public AltosTimeValue last() { +		return values.get(values.size() - 1); +	} +  	public double average() { -		double total = 0; -		int count = 0; +		double total_value = 0; +		double total_time = 0; +		AltosTimeValue prev = null;  		for (AltosTimeValue tv : values) { -			total += tv.value; -			count++; +			if (prev != null) { +				total_value += (tv.value + prev.value) / 2 * (tv.time - prev.time); +				total_time += (tv.time - prev.time); +			} +			prev = tv;  		} -		if (count == 0) +		if (total_time == 0)  			return AltosLib.MISSING; -		return total / count; +		return total_value / total_time;  	}  	public double average(double start_time, double end_time) { -		double total = 0; -		int count = 0; +		double total_value = 0; +		double total_time = 0; +		AltosTimeValue prev = null;  		for (AltosTimeValue tv : values) {  			if (start_time <= tv.time && tv.time <= end_time) { -				total += tv.value; -				count++; +				if (prev != null) { +					total_value += (tv.value + prev.value) / 2 * (tv.time - start_time); +					total_time += (tv.time - start_time); +				} +				start_time = tv.time;  			} +			prev = tv;  		} -		if (count == 0) +		if (total_time == 0)  			return AltosLib.MISSING; -		return total / count; +		return total_value / total_time;  	}  	public AltosTimeSeries integrate(AltosTimeSeries integral) { diff --git a/altosuilib/AltosFlightStatsTable.java b/altosuilib/AltosFlightStatsTable.java index 7e3be1ea..415c0244 100644 --- a/altosuilib/AltosFlightStatsTable.java +++ b/altosuilib/AltosFlightStatsTable.java @@ -138,11 +138,11 @@ public class AltosFlightStatsTable extends JComponent implements AltosFontListen  				       String.format("%6.1f m/s²", stats.state_accel[AltosLib.ao_flight_boost]),  				       String.format("%5.0f ft/s²", AltosConvert.meters_to_feet(stats.state_accel[AltosLib.ao_flight_boost])),  				       String.format("%6.2f G", AltosConvert.meters_to_g(stats.state_accel[AltosLib.ao_flight_boost]))); -		if (stats.state_start[AltosLib.ao_flight_boost] < stats.state_end[AltosLib.ao_flight_coast]) { +		if (stats.state_time[AltosLib.ao_flight_boost] != 0 || stats.state_time[AltosLib.ao_flight_fast] != 0 || stats.state_time[AltosLib.ao_flight_coast] != 0) { -			double	boost_time = stats.state_end[AltosLib.ao_flight_boost] - stats.state_start[AltosLib.ao_flight_boost]; -			double	fast_time = stats.state_end[AltosLib.ao_flight_fast] - stats.state_start[AltosLib.ao_flight_fast]; -			double	coast_time = stats.state_end[AltosLib.ao_flight_coast] - stats.state_start[AltosLib.ao_flight_coast]; +			double	boost_time = stats.state_time[AltosLib.ao_flight_boost]; +			double	fast_time = stats.state_time[AltosLib.ao_flight_fast]; +			double	coast_time = stats.state_time[AltosLib.ao_flight_coast];  			if (fast_time > 0) {  				new FlightStat(layout, y++, "Ascent time", @@ -175,10 +175,10 @@ public class AltosFlightStatsTable extends JComponent implements AltosFontListen  			new FlightStat(layout, y++, "Main descent rate",  				       String.format("%6.1f m/s", -stats.state_speed[AltosLib.ao_flight_main]),  				       String.format("%5.0f ft/s", -AltosConvert.meters_to_feet(stats.state_speed[AltosLib.ao_flight_main]))); -		if (stats.state_start[AltosLib.ao_flight_drogue] < stats.state_end[AltosLib.ao_flight_main]) { -			double	drogue_duration = stats.state_end[AltosLib.ao_flight_drogue] - stats.state_start[AltosLib.ao_flight_drogue]; -			double	main_duration = stats.landed_time - stats.state_start[AltosLib.ao_flight_main]; -			double	duration = stats.landed_time - stats.state_start[AltosLib.ao_flight_drogue]; +		if (stats.state_time[AltosLib.ao_flight_drogue] != 0 || stats.state_time[AltosLib.ao_flight_main] != 0) { +			double	drogue_duration = stats.state_time[AltosLib.ao_flight_drogue]; +			double	main_duration = stats.state_time[AltosLib.ao_flight_main]; +			double	duration = drogue_duration + main_duration;  			if (drogue_duration > 0 && main_duration > 0) {  				new FlightStat(layout, y++, "Descent time", @@ -191,7 +191,7 @@ public class AltosFlightStatsTable extends JComponent implements AltosFontListen  					       String.format("%6.1f s", duration));  			}  		} -		if (stats.state_start[AltosLib.ao_flight_boost] < stats.state_start[AltosLib.ao_flight_landed]) +		if (stats.landed_time > stats.boost_time)  			new FlightStat(layout, y++, "Flight time",  				       String.format("%6.1f s", stats.landed_time - stats.boost_time));  		if (stats.has_gps && stats.pad_lat != AltosLib.MISSING) {  | 
