diff options
| author | Keith Packard <keithp@keithp.com> | 2012-12-31 14:17:26 -0800 | 
|---|---|---|
| committer | Keith Packard <keithp@keithp.com> | 2012-12-31 14:17:26 -0800 | 
| commit | 2bd6aca54fc465995d6985c8799cd0d016c9a543 (patch) | |
| tree | 86837459a95308ae286d2b8bae4d9e0e20e6d37f | |
| parent | 56a1210a7b04a3623d19ec282f26fecc79c126dd (diff) | |
micropeak: Add flight stats pane
Shows graph or stats in alternate panes
Signed-off-by: Keith Packard <keithp@keithp.com>
| -rw-r--r-- | altosuilib/AltosUILib.java | 18 | ||||
| -rw-r--r-- | micropeak/Makefile.am | 2 | ||||
| -rw-r--r-- | micropeak/MicroData.java | 100 | ||||
| -rw-r--r-- | micropeak/MicroPeak.java | 15 | ||||
| -rw-r--r-- | micropeak/MicroStats.java | 184 | ||||
| -rw-r--r-- | micropeak/MicroStatsTable.java | 138 | 
6 files changed, 445 insertions, 12 deletions
| diff --git a/altosuilib/AltosUILib.java b/altosuilib/AltosUILib.java index 717678ba..5d5f9aaa 100644 --- a/altosuilib/AltosUILib.java +++ b/altosuilib/AltosUILib.java @@ -24,17 +24,17 @@ import org.altusmetrum.AltosLib.*;  public class AltosUILib extends AltosLib { -	static final int tab_elt_pad = 5; +	public static final int tab_elt_pad = 5; -	static Font label_font; -	static Font value_font; -	static Font status_font; -	static Font table_label_font; -	static Font table_value_font; +	public static Font label_font; +	public static Font value_font; +	public static Font status_font; +	public static Font table_label_font; +	public static Font table_value_font; -	final static int font_size_small = 1; -	final static int font_size_medium = 2; -	final static int font_size_large = 3; +	final public static int font_size_small = 1; +	final public static int font_size_medium = 2; +	final public static int font_size_large = 3;  	static void set_fonts(int size) {  		int	brief_size; diff --git a/micropeak/Makefile.am b/micropeak/Makefile.am index fde981a6..e0de690c 100644 --- a/micropeak/Makefile.am +++ b/micropeak/Makefile.am @@ -13,6 +13,8 @@ micropeak_JAVA= \  	MicroFrame.java \  	MicroGraph.java \  	MicroSerial.java \ +	MicroStats.java \ +	MicroStatsTable.java \  	MicroFileChooser.java \  	MicroUSB.java diff --git a/micropeak/MicroData.java b/micropeak/MicroData.java index 783ae40f..ec9b83d8 100644 --- a/micropeak/MicroData.java +++ b/micropeak/MicroData.java @@ -22,6 +22,87 @@ import java.io.*;  import java.util.*;  import org.altusmetrum.AltosLib.*; +abstract class MicroIterator implements Iterator<Double> { +	int		i; +	MicroData	data; + +	public boolean hasNext() { +		return i < data.pressures.length; +	} + +	public MicroIterator (MicroData data) { +		this.data = data; +		i = 0; +	} + +	public void remove() { +	} +} + +class MicroHeightIterator extends MicroIterator { +	public Double next() { +		return data.height(i++); +	} + +	public MicroHeightIterator(MicroData data) { +		super(data); +	} +} + +class MicroHeightIterable implements Iterable<Double> { +	MicroData	data; + +	public Iterator<Double> iterator() { +		return new MicroHeightIterator(data); +	} + +	public MicroHeightIterable(MicroData data) { +		this.data = data; +	} +} + +class MicroSpeedIterator extends MicroIterator { +	public Double next() { +		return data.speed(i++); +	} +	public MicroSpeedIterator(MicroData data) { +		super(data); +	} +} + +class MicroSpeedIterable implements Iterable<Double> { +	MicroData	data; + +	public Iterator<Double> iterator() { +		return new MicroSpeedIterator(data); +	} + +	public MicroSpeedIterable(MicroData data) { +		this.data = data; +	} +} + +class MicroAccelIterator extends MicroIterator { +	public Double next() { +		return data.acceleration(i++); +	} +	public MicroAccelIterator(MicroData data) { +		super(data); +	} +} + +class MicroAccelIterable implements Iterable<Double> { +	MicroData	data; + +	public Iterator<Double> iterator() { +		return new MicroAccelIterator(data); +	} + +	public MicroAccelIterable(MicroData data) { +		this.data = data; +	} +} +  public class MicroData {  	public int		ground_pressure;  	public int		min_pressure; @@ -143,6 +224,18 @@ public class MicroData {  		return AltosConvert.pressure_to_altitude(pressures[i]);  	} +	public Iterable<Double> heights() { +		return new MicroHeightIterable(this); +	} + +	public Iterable<Double> speeds() { +		return new MicroSpeedIterable(this); +	} + +	public Iterable<Double> accels() { +		return new MicroAccelIterable(this); +	} +  	int fact(int n) {  		if (n == 0)  			return 1; @@ -266,5 +359,12 @@ public class MicroData {  			throw new IOException();  		}  	} + +	public MicroData() { +		ground_pressure = 101000; +		min_pressure = 101000; +		pressures = new int[1]; +		pressures[0] = 101000; +	}  } diff --git a/micropeak/MicroPeak.java b/micropeak/MicroPeak.java index 463238c8..c69f7167 100644 --- a/micropeak/MicroPeak.java +++ b/micropeak/MicroPeak.java @@ -30,13 +30,16 @@ public class MicroPeak extends MicroFrame implements ActionListener, ItemListene  	File		filename;  	MicroGraph	graph; +	MicroStatsTable	stats;  	MicroData	data; -	Container	pane; +	Container	container; +	JTabbedPane	pane;  	private void RunFile(InputStream input) {  		try {  			data = new MicroData(input);  			graph.setData(data); +			stats.setData(data);  		} catch (IOException ioe) {  		}  		try { @@ -90,7 +93,8 @@ public class MicroPeak extends MicroFrame implements ActionListener, ItemListene  		AltosUIPreferences.set_component(this); -		pane = getContentPane(); +		container = getContentPane(); +		pane = new JTabbedPane();  		setTitle("MicroPeak"); @@ -129,9 +133,14 @@ public class MicroPeak extends MicroFrame implements ActionListener, ItemListene  		});  		graph = new MicroGraph(); -		pane.add(graph.panel); +		stats = new MicroStatsTable(); +		pane.add(graph.panel, "Graph"); +		pane.add(stats, "Statistics");  		pane.doLayout();  		pane.validate(); +		container.add(pane); +		container.doLayout(); +		container.validate();  		doLayout();  		validate();  		Insets i = getInsets(); diff --git a/micropeak/MicroStats.java b/micropeak/MicroStats.java new file mode 100644 index 00000000..6ae8a2b2 --- /dev/null +++ b/micropeak/MicroStats.java @@ -0,0 +1,184 @@ +/* + * Copyright © 2011 Keith Packard <keithp@keithp.com> + * + * 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. + */ + +package org.altusmetrum.micropeak; + +import java.io.*; +import org.altusmetrum.AltosLib.*; +import org.altusmetrum.altosuilib.*; + +public class MicroStats { +	double		coast_height; +	double		coast_time; + +	double		apogee_height; +	double		apogee_time; + +	double		landed_height; +	double		landed_time; + +	double		max_speed; +	double		max_accel; + +	MicroData	data; + +	void find_landing() { +		landed_height = 0; + +		int t = 0; +		for (double height : data.heights()) { +			landed_height = height; +			t++; +		} +		landed_time = data.time(t); + +		t = 0; +		boolean above = false; +		for (double height : data.heights()) { +			if (height > landed_height + 10) { +				above = true; +			} else { +				if (above && height < landed_height + 2) { +					above = false; +					landed_time = data.time(t); +				} +			} +			t++; +		} +	} + +	void find_apogee() { +		apogee_height = 0; +		apogee_time = 0; +		 +		int t = 0; +		for (double height : data.heights()) { +			if (height > apogee_height) { +				apogee_height = height; +				apogee_time = data.time(t); +			} +			t++; +		} +	} + +	void find_coast() { +		coast_height = 0; +		coast_time = 0; + +		int t = 0; +		for (double accel : data.accels()) { +			if (accel < -9.8) +				break; +			t++; +		} +		coast_time = data.time(t); + +		int coast_t = t; +		t = 0; +		for (double height : data.heights()) { +			if (t >= coast_t) { +				coast_height = height; +				break; +			} +			t++; +		} +	} + +	void find_max_speed() { +		max_speed = 0; +		int	t = 0; +		for (double speed : data.speeds()) { +			if (data.time(t) > apogee_time) +				break; +			if (speed > max_speed) +				max_speed = speed; +			t++; +		} +	} + +	void find_max_accel() { +		max_accel = 0; + +		int t = 0; +		for (double accel : data.accels()) { +			if (data.time(t) > apogee_time) +				break; +			if (accel > max_accel) +				max_accel = accel; +			t++; +		} +	} + +	double boost_duration() { +		return coast_time; +	} + +	double boost_height() { +		return coast_height; +	} + +	double	boost_speed() { +		return coast_height / coast_time; +	} + +	double boost_accel() { +		return boost_speed() / boost_duration(); +	} + +	double coast_duration() { +		return apogee_time - coast_time; +	} + +	double coast_height() { +		return apogee_height - coast_height; +	} + +	double coast_speed() { +		return coast_height() / coast_duration(); +	} + +	double coast_accel() { +		return coast_speed() / coast_duration(); +	} + +	double descent_duration() { +		return landed_time - apogee_time; +	} + +	double descent_height() { +		return apogee_height - landed_height; +	} + +	double descent_speed() { +		return descent_height() / descent_duration(); +	} + +	public MicroStats(MicroData data) { + +		this.data = data; + +		find_coast(); +		find_apogee(); +		find_landing(); +		find_max_speed(); +		find_max_accel(); +	} + +	public MicroStats() { +		this(new MicroData()); +	} +} diff --git a/micropeak/MicroStatsTable.java b/micropeak/MicroStatsTable.java new file mode 100644 index 00000000..f373e25d --- /dev/null +++ b/micropeak/MicroStatsTable.java @@ -0,0 +1,138 @@ +/* + * Copyright © 2011 Keith Packard <keithp@keithp.com> + * + * 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. + */ + +package org.altusmetrum.micropeak; + +import java.awt.*; +import javax.swing.*; +import org.altusmetrum.AltosLib.*; +import org.altusmetrum.altosuilib.*; + +public class MicroStatsTable extends JComponent { +	GridBagLayout	layout; + +	class MicroStat { +		JLabel		label; +		JTextField[]	texts; + +		public void set_values(String ... values) { +			for (int j = 0; j < values.length; j++) { +				texts[j].setText(values[j]); +			} +		} + +		public MicroStat(GridBagLayout layout, int y, String label_text, String ... values) { +			GridBagConstraints	c = new GridBagConstraints(); +			c.insets = new Insets(AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad); +			c.weighty = 1; + +			label = new JLabel(label_text); +			label.setFont(AltosUILib.label_font); +			label.setHorizontalAlignment(SwingConstants.LEFT); +			c.gridx = 0; c.gridy = y; +			c.anchor = GridBagConstraints.WEST; +			c.fill = GridBagConstraints.VERTICAL; +			c.weightx = 0; +			layout.setConstraints(label, c); +			add(label); + +			texts = new JTextField[values.length]; +			for (int j = 0; j < values.length; j++) { +				JTextField value = new JTextField(values[j]); +				value.setFont(AltosUILib.value_font); +				value.setHorizontalAlignment(SwingConstants.RIGHT); +				texts[j] = value; +				c.gridx = j+1; c.gridy = y; +				c.anchor = GridBagConstraints.EAST; +				c.fill = GridBagConstraints.BOTH; +				c.weightx = 1; +				layout.setConstraints(value, c); +				add(value); +			} +		} +	} + +	MicroStat	max_height, max_speed; +	MicroStat	max_accel, avg_accel; +	MicroStat	boost_duration; +	MicroStat	coast_duration; +	MicroStat	descent_speed; +	MicroStat	descent_duration; +	MicroStat	flight_time; +	 +	public void setStats(MicroStats stats) { +		max_height.set_values(String.format("%5.0f m", stats.apogee_height), +				      String.format("%5.0f ft", AltosConvert.meters_to_feet(stats.apogee_height))); +		max_speed.set_values(String.format("%5.0f m/s", stats.max_speed), +				     String.format("%5.0f mph", AltosConvert.meters_to_mph(stats.max_speed)), +				     String.format("Mach %4.1f", AltosConvert.meters_to_mach(stats.max_speed))); +		max_accel.set_values(String.format("%5.0f m/s²", stats.max_accel), +				     String.format("%5.0f ft/s²", AltosConvert.meters_to_feet(stats.max_accel)), +				     String.format("%5.0f G", AltosConvert.meters_to_g(stats.max_accel))); +		avg_accel.set_values(String.format("%5.0f m/s²", stats.boost_accel(), +						   String.format("%5.0f ft/s²", AltosConvert.meters_to_feet(stats.boost_accel())), +						   String.format("%5.0f G", AltosConvert.meters_to_g(stats.boost_accel())))); +		boost_duration.set_values(String.format("%6.1f s", stats.boost_duration())); +		coast_duration.set_values(String.format("%6.1f s", stats.coast_duration())); +		descent_speed.set_values(String.format("%5.0f m/s", stats.descent_speed()), +					 String.format("%5.0f ft/s", AltosConvert.meters_to_feet(stats.descent_speed()))); +		descent_duration.set_values(String.format("%6.1f s", stats.descent_duration())); +		flight_time.set_values(String.format("%6.1f s", stats.landed_time)); +	} + +	public void setData(MicroData data) { +		setStats(new MicroStats(data)); +	} + +	public MicroStatsTable(MicroStats stats) { +		layout = new GridBagLayout(); + +		setLayout(layout); +		int y = 0; +		max_height = new MicroStat(layout, y++, "Maximum height", +					   String.format("%5.0f m", stats.apogee_height), +					   String.format("%5.0f ft", AltosConvert.meters_to_feet(stats.apogee_height))); +		max_speed = new MicroStat(layout, y++, "Maximum speed", +					  String.format("%5.0f m/s", stats.max_speed), +					  String.format("%5.0f mph", AltosConvert.meters_to_mph(stats.max_speed)), +					  String.format("Mach %4.1f", AltosConvert.meters_to_mach(stats.max_speed))); +		max_accel = new MicroStat(layout, y++, "Maximum boost acceleration", +					  String.format("%5.0f m/s²", stats.max_accel), +					  String.format("%5.0f ft/s²", AltosConvert.meters_to_feet(stats.max_accel)), +					  String.format("%5.0f G", AltosConvert.meters_to_g(stats.max_accel))); +		avg_accel = new MicroStat(layout, y++, "Average boost acceleration", +					  String.format("%5.0f m/s²", stats.boost_accel(), +							String.format("%5.0f ft/s²", AltosConvert.meters_to_feet(stats.boost_accel())), +							String.format("%5.0f G", AltosConvert.meters_to_g(stats.boost_accel())))); +		boost_duration = new MicroStat(layout, y++, "Boost duration", +					       String.format("%6.0f s", stats.boost_duration())); +		coast_duration = new MicroStat(layout, y++, "Coast duration", +					       String.format("%6.1f s", stats.coast_duration())); +		descent_speed = new MicroStat(layout, y++, "Descent rate", +					      String.format("%5.0f m/s", stats.descent_speed()), +					      String.format("%5.0f ft/s", AltosConvert.meters_to_feet(stats.descent_speed()))); +		descent_duration = new MicroStat(layout, y++, "Descent duration", +						 String.format("%6.1f s", stats.descent_duration())); +		flight_time = new MicroStat(layout, y++, "Flight Time", +					    String.format("%6.0f s", stats.landed_time)); +	} + +	public MicroStatsTable() { +		this(new MicroStats()); +	} +	 +}
\ No newline at end of file | 
