diff options
| -rw-r--r-- | altosui/Altos.java | 13 | ||||
| -rw-r--r-- | altosui/AltosFlightStats.java | 95 | ||||
| -rw-r--r-- | altosui/AltosFlightStatsTable.java | 104 | ||||
| -rw-r--r-- | altosui/AltosGraph.java | 1 | ||||
| -rw-r--r-- | altosui/AltosGraphTime.java | 1 | ||||
| -rw-r--r-- | altosui/AltosGraphUI.java | 36 | ||||
| -rw-r--r-- | altosui/AltosState.java | 3 | ||||
| -rw-r--r-- | altosui/Makefile.am | 2 | 
8 files changed, 242 insertions, 13 deletions
| diff --git a/altosui/Altos.java b/altosui/Altos.java index b257ad7b..d90c4183 100644 --- a/altosui/Altos.java +++ b/altosui/Altos.java @@ -142,6 +142,19 @@ public class Altos {  		"invalid",  	}; +	static String[] state_to_string_capital = { +		"Startup", +		"Idle", +		"Pad", +		"Boost", +		"Fast", +		"Coast", +		"Drogue", +		"Main", +		"Landed", +		"Invalid", +	}; +  	static public int state(String state) {  		if (!map_initialized)  			initialize_map(); diff --git a/altosui/AltosFlightStats.java b/altosui/AltosFlightStats.java new file mode 100644 index 00000000..e38142f0 --- /dev/null +++ b/altosui/AltosFlightStats.java @@ -0,0 +1,95 @@ +/* + * 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 altosui; + +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; +import javax.swing.filechooser.FileNameExtensionFilter; +import javax.swing.table.*; +import java.io.*; +import java.util.*; +import java.text.*; +import java.util.prefs.*; +import java.util.concurrent.*; + +public class AltosFlightStats { +	double		max_height; +	double		max_speed; +	double		max_acceleration; +	double[]	state_speed = new double[Altos.ao_flight_invalid + 1]; +	double[]	state_baro_speed = new double[Altos.ao_flight_invalid + 1]; +	double[]	state_accel = new double[Altos.ao_flight_invalid + 1]; +	int[]		state_count = new int[Altos.ao_flight_invalid + 1]; +	double[]	state_start = new double[Altos.ao_flight_invalid + 1]; +	double[]	state_end = new double[Altos.ao_flight_invalid + 1]; + +	public AltosFlightStats(AltosFlightReader reader) throws InterruptedException, IOException { +		AltosState	state = null; +		AltosState	new_state = null; +		double		boost_time = -1; +		double		start_time; + +		for (;;) { +			try { +				AltosRecord	record = reader.read(); +				if (record == null) +					break; +				new_state = new AltosState(record, state); +				if (state == null) { +					start_time = new_state.time; +				} +				state = new_state; +				if (0 <= state.state && state.state < Altos.ao_flight_invalid) { +					if (boost_time == -1 && state.state >= Altos.ao_flight_boost) +						boost_time = state.time; +					state_accel[state.state] += state.acceleration; +					state_speed[state.state] += state.speed; +					state_baro_speed[state.state] += state.baro_speed; +					state_count[state.state]++; +					if (state_start[state.state] == 0.0) +						state_start[state.state] = state.time; +					if (state_end[state.state] < state.time) +						state_end[state.state] = state.time; +					max_height = state.max_height; +					max_speed = state.max_speed; +					max_acceleration = state.max_acceleration; +				} +			} catch (ParseException pp) { +				System.out.printf("Parse error: %d \"%s\"\n", pp.getErrorOffset(), pp.getMessage()); +			} catch (AltosCRCException ce) { + +			} +		} +		for (int s = Altos.ao_flight_startup; s <= Altos.ao_flight_landed; s++) { +			if (state_count[s] > 0) { +				state_speed[s] /= state_count[s]; +				state_baro_speed[s] /= state_count[s]; +				state_accel[s] /= state_count[s]; +			} +		} +	} + +	public AltosFlightStats(AltosRecordIterable iterable, String filename) throws InterruptedException, IOException { +		this(new AltosReplayReader(iterable.iterator(), filename)); +	} + +	public AltosFlightStats(AltosRecordIterable iterable) throws InterruptedException, IOException { +		this(iterable, ""); +	} +} diff --git a/altosui/AltosFlightStatsTable.java b/altosui/AltosFlightStatsTable.java new file mode 100644 index 00000000..8676d306 --- /dev/null +++ b/altosui/AltosFlightStatsTable.java @@ -0,0 +1,104 @@ +/* + * 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 altosui; + +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; +import javax.swing.filechooser.FileNameExtensionFilter; +import javax.swing.table.*; +import java.io.*; +import java.util.*; +import java.text.*; +import java.util.prefs.*; +import java.util.concurrent.*; + +public class AltosFlightStatsTable extends JComponent { +	GridBagLayout	layout; + +	class FlightStat { +		JLabel		label; +		JTextField	value; + +		public FlightStat(GridBagLayout layout, int y, String label_text, String ... values) { +			GridBagConstraints	c = new GridBagConstraints(); +			c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad); +			c.weighty = 1; + +			label = new JLabel(label_text); +			label.setFont(Altos.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); + +			for (int j = 0; j < values.length; j++) { +				value = new JTextField(values[j]); +				value.setFont(Altos.value_font); +				value.setHorizontalAlignment(SwingConstants.RIGHT); +				c.gridx = j+1; c.gridy = y; +				c.anchor = GridBagConstraints.EAST; +				c.fill = GridBagConstraints.BOTH; +				c.weightx = 1; +				layout.setConstraints(value, c); +				add(value); +			} +		} + +	} + +	public AltosFlightStatsTable(AltosFlightStats stats) { +		layout = new GridBagLayout(); + +		setLayout(layout); +		int y = 0; +		new FlightStat(layout, y++, "Maximum height", +			       String.format("%5.0f m", stats.max_height), +			       String.format("%5.0f ft", stats.max_height * 100 / 2.54 / 12)); +		new FlightStat(layout, y++, "Maximum speed", +			       String.format("%5.0f m/s", stats.max_speed), +			       String.format("%5.0f ft/s", stats.max_speed * 100 / 2.54 / 12), +			       String.format("Mach %5.3f", stats.max_speed / 343.0)); +		new FlightStat(layout, y++, "Maximum acceleration", +			       String.format("%5.0f m/s²", stats.max_acceleration), +			       String.format("%5.0f ft/s²", stats.max_acceleration * 100 / 2.54 /12), +			       String.format("%5.2f G", stats.max_acceleration / 9.80665)); +		new FlightStat(layout, y++, "Average boost acceleration", +			       String.format("%5.0f m/s²", stats.state_accel[Altos.ao_flight_boost]), +			       String.format("%5.0f ft/s²", stats.state_accel[Altos.ao_flight_boost] * 100 / 2.54 /12), +			       String.format("%5.2f G", stats.state_accel[Altos.ao_flight_boost] / 9.80665)); +		new FlightStat(layout, y++, "Drogue descent rate", +			       String.format("%5.0f m/s", stats.state_baro_speed[Altos.ao_flight_drogue]), +			       String.format("%5.0f ft/s", stats.state_baro_speed[Altos.ao_flight_drogue] * 100 / 2.54 / 12)); +		new FlightStat(layout, y++, "Main descent rate", +			       String.format("%5.0f m/s", stats.state_baro_speed[Altos.ao_flight_main]), +			       String.format("%5.0f ft/s", stats.state_baro_speed[Altos.ao_flight_main] * 100 / 2.54 / 12)); +		for (int s = Altos.ao_flight_boost; s <= Altos.ao_flight_main; s++) { +			new FlightStat(layout, y++, String.format("%s time", Altos.state_to_string_capital[s]), +				       String.format("%6.2f s", stats.state_end[s] - stats.state_start[s])); +		} +		new FlightStat(layout, y++, "Flight Time", +			       String.format("%6.2f s", stats.state_end[Altos.ao_flight_main] - +					     stats.state_start[Altos.ao_flight_boost])); +		 +	} +	 +}
\ No newline at end of file diff --git a/altosui/AltosGraph.java b/altosui/AltosGraph.java index 58c27979..fbcefd61 100644 --- a/altosui/AltosGraph.java +++ b/altosui/AltosGraph.java @@ -13,6 +13,7 @@ abstract class AltosGraph {      public String filename;      public abstract void addData(AltosDataPoint d);      public abstract JFreeChart createChart(); +    public String title;      public void toPNG() throws java.io.IOException { toPNG(300, 500); }      public void toPNG(int width, int height)          throws java.io.IOException diff --git a/altosui/AltosGraphTime.java b/altosui/AltosGraphTime.java index a5451280..ada6ef13 100644 --- a/altosui/AltosGraphTime.java +++ b/altosui/AltosGraphTime.java @@ -132,7 +132,6 @@ class AltosGraphTime extends AltosGraph {      private Integer serial = null;      private Integer flight = null;  -    private String title;      private ArrayList<Element> elements;      private HashMap<String,Integer> axes;      private HashMap<Element,Integer> datasets; diff --git a/altosui/AltosGraphUI.java b/altosui/AltosGraphUI.java index a27aa37f..16b0fd48 100644 --- a/altosui/AltosGraphUI.java +++ b/altosui/AltosGraphUI.java @@ -7,8 +7,11 @@ package altosui;  import java.io.*;  import java.util.ArrayList; -import javax.swing.JFrame; -import java.awt.Color; +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; +import javax.swing.filechooser.FileNameExtensionFilter; +import javax.swing.table.*;  import org.jfree.chart.ChartPanel;  import org.jfree.chart.ChartUtilities; @@ -19,6 +22,8 @@ import org.jfree.ui.RefineryUtilities;  public class AltosGraphUI extends JFrame   { +    JTabbedPane	pane; +      static final private Color red = new Color(194,31,31);      static final private Color green = new Color(31,194,31);      static final private Color blue = new Color(31,31,194); @@ -173,7 +178,7 @@ public class AltosGraphUI extends JFrame          }      } -	public AltosGraphUI(AltosRecordIterable records) { +    public AltosGraphUI(AltosRecordIterable records) throws InterruptedException, IOException {  		super("Altos Graph");  		AltosDataPointReader reader = new AltosDataPointReader (records); @@ -181,25 +186,32 @@ public class AltosGraphUI extends JFrame  			return;  		if (reader.has_accel) -			init(reader, 0); +		    init(reader, records, 0);  		else -			init(reader, 1); +		    init(reader, records, 1);  	} -    public AltosGraphUI(AltosDataPointReader data, int which) -    { -        super("Altos Graph"); -        init(data, which); -    } +//    public AltosGraphUI(AltosDataPointReader data, int which) +    //  { +//        super("Altos Graph"); +//        init(data, which); +//    } + +    private void init(AltosDataPointReader data, AltosRecordIterable records, int which) throws InterruptedException, IOException { +	pane = new JTabbedPane(); -    private void init(AltosDataPointReader data, int which) {          AltosGraph graph = createGraph(data, which);          JFreeChart chart = graph.createChart();          ChartPanel chartPanel = new ChartPanel(chart);          chartPanel.setMouseWheelEnabled(true);          chartPanel.setPreferredSize(new java.awt.Dimension(800, 500)); -        setContentPane(chartPanel); +        pane.add(graph.title, chartPanel); + +	AltosFlightStatsTable stats = new AltosFlightStatsTable(new AltosFlightStats(records)); +	pane.add("Flight Statistics", stats); + +	setContentPane (pane);          pack(); diff --git a/altosui/AltosState.java b/altosui/AltosState.java index d374aed8..1ac816d5 100644 --- a/altosui/AltosState.java +++ b/altosui/AltosState.java @@ -28,6 +28,7 @@ public class AltosState {  	long  	report_time; +	double	time;  	double	time_change;  	int	tick; @@ -130,6 +131,8 @@ public class AltosState {  			time_change = 0;  		} +		time = tick / 100.0; +  		if (state == Altos.ao_flight_pad || state == Altos.ao_flight_idle) {  			/* Track consecutive 'good' gps reports, waiting for 10 of them */ diff --git a/altosui/Makefile.am b/altosui/Makefile.am index a11e2c7f..3bc68cdb 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -51,6 +51,8 @@ altosui_JAVA = \  	AltosFlightDisplay.java \  	AltosFlightInfoTableModel.java \  	AltosFlightReader.java \ +	AltosFlightStats.java \ +	AltosFlightStatsTable.java \  	AltosFlightStatus.java \  	AltosFlightUI.java \  	AltosFrequency.java \ | 
