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