Add GPS height to the usual plot
[fw/altos] / altosui / AltosGraphUI.java
1
2 // Copyright (c) 2010 Anthony Towns
3 // GPL v2 or later
4
5 package altosui;
6
7 import java.io.*;
8 import java.util.ArrayList;
9
10 import java.awt.*;
11 import javax.swing.*;
12 import org.altusmetrum.AltosLib.*;
13 import org.altusmetrum.altosuilib.*;
14
15 import org.jfree.chart.ChartPanel;
16 import org.jfree.chart.JFreeChart;
17 import org.jfree.ui.RefineryUtilities;
18
19 public class AltosGraphUI extends AltosUIFrame 
20 {
21     JTabbedPane pane;
22
23     static final private Color red = new Color(194,31,31);
24     static final private Color green = new Color(31,194,31);
25     static final private Color blue = new Color(31,31,194);
26     //static final private Color black = new Color(31,31,31);
27     static final private Color yellow = new Color(194,194,31);
28     //static final private Color cyan = new Color(31,194,194);
29     static final private Color magenta = new Color(194,31,194);
30
31     static private class OverallGraphs {
32         AltosGraphTime.Element height = 
33                 new AltosGraphTime.TimeSeries("Height", AltosConvert.height.show_units(), "Height (AGL)", red) {
34                 public void gotTimeData(double time, AltosDataPoint d) {
35                         double  height = d.height();
36                         if (height != AltosRecord.MISSING)
37                                 series.add(time, AltosConvert.height.value(height));
38                 } 
39             };
40     
41         AltosGraphTime.Element gps_height = 
42                 new AltosGraphTime.TimeSeries("Height", AltosConvert.height.show_units(), "GPS Height (AGL)", magenta) {
43                 public void gotTimeData(double time, AltosDataPoint d) {
44                         double  height = d.gps_height();
45                         if (height != AltosRecord.MISSING)
46                                 series.add(time, AltosConvert.height.value(height));
47                 } 
48             };
49     
50         AltosGraphTime.Element speed =
51                 new AltosGraphTime.TimeSeries("Speed", AltosConvert.speed.show_units(), "Vertical Speed", green) { 
52                 public void gotTimeData(double time, AltosDataPoint d) {
53                     double      speed = d.speed();
54                     if (speed != AltosRecord.MISSING)
55                             series.add(time, AltosConvert.speed.value(speed));
56                 }
57             };
58     
59         AltosGraphTime.Element acceleration =
60                 new AltosGraphTime.TimeSeries("Acceleration",
61                                               AltosConvert.accel.show_units(),
62                                               "Axial Acceleration", blue)
63             {
64                 public void gotTimeData(double time, AltosDataPoint d) {
65                     double acceleration = d.acceleration();
66                     if (acceleration != AltosRecord.MISSING)
67                             series.add(time, AltosConvert.accel.value(acceleration));
68                 }
69             };
70     
71         AltosGraphTime.Element temperature =
72             new AltosGraphTime.TimeSeries("Temperature", "\u00B0C", 
73                                           "Board temperature", red) 
74             {
75                 public void gotTimeData(double time, AltosDataPoint d) {
76                     double temp = d.temperature();
77                     if (temp != AltosRecord.MISSING)
78                         series.add(time, d.temperature());
79                 }
80             };
81     
82         AltosGraphTime.Element drogue_voltage =
83             new AltosGraphTime.TimeSeries("Voltage", "(V)", "Drogue Continuity", yellow) 
84             {
85                 public void gotTimeData(double time, AltosDataPoint d) {
86                     double v = d.drogue_voltage();
87                     if (v != AltosRecord.MISSING)
88                         series.add(time, v);
89                 }
90             };
91     
92         AltosGraphTime.Element main_voltage =
93             new AltosGraphTime.TimeSeries("Voltage", "(V)", "Main Continuity", magenta) 
94             {
95                 public void gotTimeData(double time, AltosDataPoint d) {
96                     double v = d.main_voltage();
97                     if (v != AltosRecord.MISSING)
98                         series.add(time, v);
99                 }
100             };
101     
102         //AltosGraphTime.Element e_pad    = new AltosGraphTime.StateMarker(Altos.ao_flight_pad, "Pad");
103         AltosGraphTime.Element e_boost  = new AltosGraphTime.StateMarker(Altos.ao_flight_boost, "Boost");
104         AltosGraphTime.Element e_fast   = new AltosGraphTime.StateMarker(Altos.ao_flight_fast, "Fast");
105         AltosGraphTime.Element e_coast  = new AltosGraphTime.StateMarker(Altos.ao_flight_coast, "Coast");
106         AltosGraphTime.Element e_drogue = new AltosGraphTime.StateMarker(Altos.ao_flight_drogue, "Drogue");
107         AltosGraphTime.Element e_main   = new AltosGraphTime.StateMarker(Altos.ao_flight_main, "Main");
108         AltosGraphTime.Element e_landed = new AltosGraphTime.StateMarker(Altos.ao_flight_landed, "Landed");
109     
110         protected AltosGraphTime myAltosGraphTime(String suffix) {
111             return (new AltosGraphTime("Overall " + suffix))
112                 .addElement(e_boost)
113                 .addElement(e_fast)
114                 .addElement(e_coast)
115                 .addElement(e_drogue)
116                 .addElement(e_main)
117                 .addElement(e_landed);
118         }
119     
120         public ArrayList<AltosGraph> graphs() {
121             ArrayList<AltosGraph> graphs = new ArrayList<AltosGraph>();
122     
123             graphs.add( myAltosGraphTime("Summary")
124                         .addElement(height)
125                         .addElement(gps_height)
126                         .addElement(speed)
127                         .addElement(acceleration) );
128
129             graphs.add( myAltosGraphTime("Summary")
130                         .addElement(height)
131                         .addElement(speed));
132     
133             graphs.add( myAltosGraphTime("Altitude")
134                     .addElement(height) );
135     
136             graphs.add( myAltosGraphTime("Speed")
137                     .addElement(speed) );
138     
139             graphs.add( myAltosGraphTime("Acceleration")
140                         .addElement(acceleration) );
141     
142             graphs.add( myAltosGraphTime("Temperature")
143                     .addElement(temperature) );
144     
145             graphs.add( myAltosGraphTime("Continuity")
146                         .addElement(drogue_voltage)
147                         .addElement(main_voltage) );
148     
149             return graphs;
150         }
151     }
152
153     /*
154     static private class AscentGraphs extends OverallGraphs {
155         protected AltosGraphTime myAltosGraphTime(String suffix) {
156             return (new AltosGraphTime("Ascent " + suffix) {
157                 public void addData(AltosDataPoint d) {
158                     int state = d.state();
159                     if (Altos.ao_flight_boost <= state && state <= Altos.ao_flight_coast) {
160                         super.addData(d);
161                     }
162                 }
163             }).addElement(e_boost)
164               .addElement(e_fast)
165               .addElement(e_coast);
166         }
167     }
168     */
169
170     /*
171     static private class DescentGraphs extends OverallGraphs {
172         protected AltosGraphTime myAltosGraphTime(String suffix) {
173             return (new AltosGraphTime("Descent " + suffix) {
174                 public void addData(AltosDataPoint d) {
175                     int state = d.state();
176                     if (Altos.ao_flight_drogue <= state && state <= Altos.ao_flight_main) {
177                         super.addData(d);
178                     }
179                 }
180             }).addElement(e_drogue)
181               .addElement(e_main);
182             // ((XYGraph)graph[8]).ymin = new Double(-50);
183         }
184     }
185     */
186
187         public AltosGraphUI(AltosRecordIterable records, String name) throws InterruptedException, IOException {
188                 super(String.format("Altos Graph %s", name));
189
190                 AltosDataPointReader reader = new AltosDataPointReader (records);
191         
192                 if (reader.has_accel)
193                     init(reader, records, 0);
194                 else
195                     init(reader, records, 1);
196         }
197
198 //    public AltosGraphUI(AltosDataPointReader data, int which)
199     //  {
200 //        super("Altos Graph");
201 //        init(data, which);
202 //    }
203
204     private void init(AltosDataPointReader data, AltosRecordIterable records, int which) throws InterruptedException, IOException {
205         pane = new JTabbedPane();
206
207         AltosGraph graph = createGraph(data, which);
208
209         JFreeChart chart = graph.createChart();
210         ChartPanel chartPanel = new ChartPanel(chart);
211         chartPanel.setMouseWheelEnabled(true);
212         chartPanel.setPreferredSize(new java.awt.Dimension(800, 500));
213         pane.add(graph.title, chartPanel);
214
215         AltosFlightStatsTable stats = new AltosFlightStatsTable(new AltosFlightStats(records));
216         pane.add("Flight Statistics", stats);
217
218         setContentPane (pane);
219
220         pack();
221
222         RefineryUtilities.centerFrameOnScreen(this);
223
224         setDefaultCloseOperation(DISPOSE_ON_CLOSE);
225         setVisible(true);
226     }
227
228     private static AltosGraph createGraph(Iterable<AltosDataPoint> data,
229             int which)
230     {
231         return createGraphsWhich(data, which).get(0);
232     }
233
234     /*
235     private static ArrayList<AltosGraph> createGraphs(
236             Iterable<AltosDataPoint> data)
237     {
238         return createGraphsWhich(data, -1);
239     }
240     */
241
242     private static ArrayList<AltosGraph> createGraphsWhich(
243             Iterable<AltosDataPoint> data, int which)
244     {
245         ArrayList<AltosGraph> graph = new ArrayList<AltosGraph>();
246         graph.addAll((new OverallGraphs()).graphs());
247 //        graph.addAll((new AscentGraphs()).graphs());
248 //        graph.addAll((new DescentGraphs()).graphs());
249
250         if (which > 0) {
251             if (which >= graph.size()) {
252                 which = 0;
253             }
254             AltosGraph g = graph.get(which);
255             graph = new ArrayList<AltosGraph>();
256             graph.add(g);
257         }
258
259         for (AltosDataPoint dp : data) {
260             for (AltosGraph g : graph) {
261                 g.addData(dp);
262             }
263         }
264
265         return graph;
266     }
267 }
268
269 /* gnuplot bits...
270  *
271 300x400
272
273 --------------------------------------------------------
274 TOO HARD! :)
275
276 "ascent-gps-accuracy.png" "Vertical error margin to apogee - GPS v Baro (m)"
277     5:($7 < 6 ? $24-$11 : 1/0)
278 "descent-gps-accuracy.png" "Vertical error margin during descent - GPS v Baro (m)"
279     5:($7 < 6 ? 1/0 : $24-$11)
280
281 set output "overall-gps-accuracy.png"
282 set ylabel "distance above sea level (m)"
283 plot "telemetry.csv" using 5:11 with lines ti "baro altitude" axis x1y1, \
284     "telemetry.csv" using 5:24 with lines ti "gps altitude" axis x1y1
285
286 set term png tiny size 700,700 enhanced
287 set xlabel "m"
288 set ylabel "m"
289 set polar
290 set grid polar
291 set rrange[*:*]
292 set angles degrees
293
294 set output "overall-gps-path.png"
295 #:30 with yerrorlines
296 plot "telemetry.csv" using (90-$33):($7 == 2 ? $31 : 1/0) with lines ti "pad", \
297     "telemetry.csv" using (90-$33):($7 == 3 ? $31 : 1/0) with lines ti "boost", \
298     "telemetry.csv" using (90-$33):($7 == 4 ? $31 : 1/0) with lines ti "fast", \
299     "telemetry.csv" using (90-$33):($7 == 5 ? $31 : 1/0) with lines ti "coast", \
300     "telemetry.csv" using (90-$33):($7 == 6 ? $31 : 1/0) with lines ti "drogue", \
301     "telemetry.csv" using (90-$33):($7 == 7 ? $31 : 1/0) with lines ti "main", \
302     "telemetry.csv" using (90-$33):($7 == 8 ? $31 : 1/0) with lines ti "landed"
303
304 set output "ascent-gps-path.png"
305 plot "telemetry.csv" using (90-$33):($7 == 2 ? $31 : 1/0):30 with lines ti "pad", \
306     "telemetry.csv" using (90-$33):($7 == 3 ? $31 : 1/0):20 with lines ti "boost", \
307     "telemetry.csv" using (90-$33):($7 == 4 ? $31 : 1/0):10 with lines ti "fast", \
308     "telemetry.csv" using (90-$33):($7 == 5 ? $31 : 1/0):5 with lines ti "coast"
309
310 set output "descent-gps-path.png"
311 plot "telemetry.csv" using (90-$33):($7 == 6 ? $31 : 1/0) with lines ti "drogue", \
312     "telemetry.csv" using (90-$33):($7 == 7 ? $31 : 1/0) with lines ti "main", \
313     "telemetry.csv" using (90-$33):($7 == 8 ? $31 : 1/0) with lines ti "landed"
314
315  */
316
317