Provide basic flight stats alongside the flight graph.
Signed-off-by: Keith Packard <keithp@keithp.com>
"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();
--- /dev/null
+/*
+ * 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, "");
+ }
+}
--- /dev/null
+/*
+ * 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
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
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;
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;
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);
}
}
- public AltosGraphUI(AltosRecordIterable records) {
+ public AltosGraphUI(AltosRecordIterable records) throws InterruptedException, IOException {
super("Altos Graph");
AltosDataPointReader reader = new AltosDataPointReader (records);
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();
long report_time;
+ double time;
double time_change;
int tick;
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 */
AltosFlightDisplay.java \
AltosFlightInfoTableModel.java \
AltosFlightReader.java \
+ AltosFlightStats.java \
+ AltosFlightStatsTable.java \
AltosFlightStatus.java \
AltosFlightUI.java \
AltosFrequency.java \