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