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