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