2 // Copyright (c) 2010 Anthony Towns
8 import java.util.ArrayList;
11 import java.awt.event.*;
13 import javax.swing.filechooser.FileNameExtensionFilter;
14 import javax.swing.table.*;
16 import org.jfree.chart.ChartPanel;
17 import org.jfree.chart.ChartUtilities;
18 import org.jfree.chart.JFreeChart;
19 import org.jfree.chart.axis.AxisLocation;
20 import org.jfree.ui.ApplicationFrame;
21 import org.jfree.ui.RefineryUtilities;
23 public class AltosGraphUI extends JFrame
27 static final private Color red = new Color(194,31,31);
28 static final private Color green = new Color(31,194,31);
29 static final private Color blue = new Color(31,31,194);
30 static final private Color black = new Color(31,31,31);
31 static final private Color yellow = new Color(194,194,31);
32 static final private Color cyan = new Color(31,194,194);
33 static final private Color magenta = new Color(194,31,194);
35 static private class OverallGraphs {
36 AltosGraphTime.Element height =
37 new AltosGraphTime.TimeSeries("Height (m)", "Height (AGL)", red) {
38 public void gotTimeData(double time, AltosDataPoint d) {
39 double height = d.height();
40 if (height != AltosRecord.MISSING)
41 series.add(time, d.height());
45 AltosGraphTime.Element speed =
46 new AltosGraphTime.TimeSeries("Speed (m/s)", "Vertical Speed", green) {
47 public void gotTimeData(double time, AltosDataPoint d) {
49 if (d.state() < Altos.ao_flight_drogue && d.has_accel()) {
50 speed = d.accel_speed();
52 speed = d.baro_speed();
54 if (speed != AltosRecord.MISSING)
55 series.add(time, speed);
59 AltosGraphTime.Element acceleration =
60 new AltosGraphTime.TimeSeries("Acceleration (m/s\u00B2)",
61 "Axial Acceleration", blue)
63 public void gotTimeData(double time, AltosDataPoint d) {
64 double acceleration = d.acceleration();
65 if (acceleration != AltosRecord.MISSING)
66 series.add(time, acceleration);
70 AltosGraphTime.Element temperature =
71 new AltosGraphTime.TimeSeries("Temperature (\u00B0C)",
72 "Board temperature", red)
74 public void gotTimeData(double time, AltosDataPoint d) {
75 double temp = d.temperature();
76 if (temp != AltosRecord.MISSING)
77 series.add(time, d.temperature());
81 AltosGraphTime.Element drogue_voltage =
82 new AltosGraphTime.TimeSeries("Voltage (V)", "Drogue Continuity", yellow)
84 public void gotTimeData(double time, AltosDataPoint d) {
85 double v = d.drogue_voltage();
86 if (v != AltosRecord.MISSING)
91 AltosGraphTime.Element main_voltage =
92 new AltosGraphTime.TimeSeries("Voltage (V)", "Main Continuity", magenta)
94 public void gotTimeData(double time, AltosDataPoint d) {
95 double v = d.main_voltage();
96 if (v != AltosRecord.MISSING)
101 AltosGraphTime.Element e_pad = new AltosGraphTime.StateMarker(Altos.ao_flight_pad, "Pad");
102 AltosGraphTime.Element e_boost = new AltosGraphTime.StateMarker(Altos.ao_flight_boost, "Boost");
103 AltosGraphTime.Element e_fast = new AltosGraphTime.StateMarker(Altos.ao_flight_fast, "Fast");
104 AltosGraphTime.Element e_coast = new AltosGraphTime.StateMarker(Altos.ao_flight_coast, "Coast");
105 AltosGraphTime.Element e_drogue = new AltosGraphTime.StateMarker(Altos.ao_flight_drogue, "Drogue");
106 AltosGraphTime.Element e_main = new AltosGraphTime.StateMarker(Altos.ao_flight_main, "Main");
107 AltosGraphTime.Element e_landed = new AltosGraphTime.StateMarker(Altos.ao_flight_landed, "Landed");
109 protected AltosGraphTime myAltosGraphTime(String suffix) {
110 return (new AltosGraphTime("Overall " + suffix))
112 .addElement(e_drogue)
114 .addElement(e_landed);
117 public ArrayList<AltosGraph> graphs() {
118 ArrayList<AltosGraph> graphs = new ArrayList<AltosGraph>();
120 graphs.add( myAltosGraphTime("Summary")
123 .addElement(acceleration)
124 .addElement(drogue_voltage)
125 .addElement(main_voltage) );
127 graphs.add( myAltosGraphTime("Summary")
131 graphs.add( myAltosGraphTime("Altitude")
132 .addElement(height) );
134 graphs.add( myAltosGraphTime("Speed")
135 .addElement(speed) );
137 graphs.add( myAltosGraphTime("Acceleration")
138 .addElement(acceleration) );
140 graphs.add( myAltosGraphTime("Temperature")
141 .addElement(temperature) );
143 graphs.add( myAltosGraphTime("Continuity")
144 .addElement(drogue_voltage)
145 .addElement(main_voltage) );
151 static private class AscentGraphs extends OverallGraphs {
152 protected AltosGraphTime myAltosGraphTime(String suffix) {
153 return (new AltosGraphTime("Ascent " + suffix) {
154 public void addData(AltosDataPoint d) {
155 int state = d.state();
156 if (Altos.ao_flight_boost <= state && state <= Altos.ao_flight_coast) {
160 }).addElement(e_boost)
162 .addElement(e_coast);
166 static private class DescentGraphs extends OverallGraphs {
167 protected AltosGraphTime myAltosGraphTime(String suffix) {
168 return (new AltosGraphTime("Descent " + suffix) {
169 public void addData(AltosDataPoint d) {
170 int state = d.state();
171 if (Altos.ao_flight_drogue <= state && state <= Altos.ao_flight_main) {
175 }).addElement(e_drogue)
177 // ((XYGraph)graph[8]).ymin = new Double(-50);
181 public AltosGraphUI(AltosRecordIterable records) throws InterruptedException, IOException {
182 super("Altos Graph");
184 AltosDataPointReader reader = new AltosDataPointReader (records);
188 if (reader.has_accel)
189 init(reader, records, 0);
191 init(reader, records, 1);
194 // public AltosGraphUI(AltosDataPointReader data, int which)
196 // super("Altos Graph");
197 // init(data, which);
200 private void init(AltosDataPointReader data, AltosRecordIterable records, int which) throws InterruptedException, IOException {
201 pane = new JTabbedPane();
203 AltosGraph graph = createGraph(data, which);
205 JFreeChart chart = graph.createChart();
206 ChartPanel chartPanel = new ChartPanel(chart);
207 chartPanel.setMouseWheelEnabled(true);
208 chartPanel.setPreferredSize(new java.awt.Dimension(800, 500));
209 pane.add(graph.title, chartPanel);
211 AltosFlightStatsTable stats = new AltosFlightStatsTable(new AltosFlightStats(records));
212 pane.add("Flight Statistics", stats);
214 setContentPane (pane);
218 RefineryUtilities.centerFrameOnScreen(this);
220 setDefaultCloseOperation(DISPOSE_ON_CLOSE);
224 private static AltosGraph createGraph(Iterable<AltosDataPoint> data,
227 return createGraphsWhich(data, which).get(0);
230 private static ArrayList<AltosGraph> createGraphs(
231 Iterable<AltosDataPoint> data)
233 return createGraphsWhich(data, -1);
236 private static ArrayList<AltosGraph> createGraphsWhich(
237 Iterable<AltosDataPoint> data, int which)
239 ArrayList<AltosGraph> graph = new ArrayList<AltosGraph>();
240 graph.addAll((new OverallGraphs()).graphs());
241 graph.addAll((new AscentGraphs()).graphs());
242 graph.addAll((new DescentGraphs()).graphs());
245 if (which >= graph.size()) {
248 AltosGraph g = graph.get(which);
249 graph = new ArrayList<AltosGraph>();
253 for (AltosDataPoint dp : data) {
254 for (AltosGraph g : graph) {
267 --------------------------------------------------------
270 "ascent-gps-accuracy.png" "Vertical error margin to apogee - GPS v Baro (m)"
271 5:($7 < 6 ? $24-$11 : 1/0)
272 "descent-gps-accuracy.png" "Vertical error margin during descent - GPS v Baro (m)"
273 5:($7 < 6 ? 1/0 : $24-$11)
275 set output "overall-gps-accuracy.png"
276 set ylabel "distance above sea level (m)"
277 plot "telemetry.csv" using 5:11 with lines ti "baro altitude" axis x1y1, \
278 "telemetry.csv" using 5:24 with lines ti "gps altitude" axis x1y1
280 set term png tiny size 700,700 enhanced
288 set output "overall-gps-path.png"
289 #:30 with yerrorlines
290 plot "telemetry.csv" using (90-$33):($7 == 2 ? $31 : 1/0) with lines ti "pad", \
291 "telemetry.csv" using (90-$33):($7 == 3 ? $31 : 1/0) with lines ti "boost", \
292 "telemetry.csv" using (90-$33):($7 == 4 ? $31 : 1/0) with lines ti "fast", \
293 "telemetry.csv" using (90-$33):($7 == 5 ? $31 : 1/0) with lines ti "coast", \
294 "telemetry.csv" using (90-$33):($7 == 6 ? $31 : 1/0) with lines ti "drogue", \
295 "telemetry.csv" using (90-$33):($7 == 7 ? $31 : 1/0) with lines ti "main", \
296 "telemetry.csv" using (90-$33):($7 == 8 ? $31 : 1/0) with lines ti "landed"
298 set output "ascent-gps-path.png"
299 plot "telemetry.csv" using (90-$33):($7 == 2 ? $31 : 1/0):30 with lines ti "pad", \
300 "telemetry.csv" using (90-$33):($7 == 3 ? $31 : 1/0):20 with lines ti "boost", \
301 "telemetry.csv" using (90-$33):($7 == 4 ? $31 : 1/0):10 with lines ti "fast", \
302 "telemetry.csv" using (90-$33):($7 == 5 ? $31 : 1/0):5 with lines ti "coast"
304 set output "descent-gps-path.png"
305 plot "telemetry.csv" using (90-$33):($7 == 6 ? $31 : 1/0) with lines ti "drogue", \
306 "telemetry.csv" using (90-$33):($7 == 7 ? $31 : 1/0) with lines ti "main", \
307 "telemetry.csv" using (90-$33):($7 == 8 ? $31 : 1/0) with lines ti "landed"