2 // Copyright (c) 2010 Anthony Towns
8 import java.util.ArrayList;
12 import org.altusmetrum.AltosLib.*;
13 import org.altusmetrum.altosuilib.*;
15 import org.jfree.chart.ChartPanel;
16 import org.jfree.chart.JFreeChart;
17 import org.jfree.ui.RefineryUtilities;
19 public class AltosGraphUI extends AltosUIFrame
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);
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));
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));
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));
59 AltosGraphTime.Element acceleration =
60 new AltosGraphTime.TimeSeries("Acceleration",
61 AltosConvert.accel.show_units(),
62 "Axial Acceleration", blue)
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));
71 AltosGraphTime.Element temperature =
72 new AltosGraphTime.TimeSeries("Temperature", "\u00B0C",
73 "Board temperature", red)
75 public void gotTimeData(double time, AltosDataPoint d) {
76 double temp = d.temperature();
77 if (temp != AltosRecord.MISSING)
78 series.add(time, d.temperature());
82 AltosGraphTime.Element drogue_voltage =
83 new AltosGraphTime.TimeSeries("Voltage", "(V)", "Drogue Continuity", yellow)
85 public void gotTimeData(double time, AltosDataPoint d) {
86 double v = d.drogue_voltage();
87 if (v != AltosRecord.MISSING)
92 AltosGraphTime.Element main_voltage =
93 new AltosGraphTime.TimeSeries("Voltage", "(V)", "Main Continuity", magenta)
95 public void gotTimeData(double time, AltosDataPoint d) {
96 double v = d.main_voltage();
97 if (v != AltosRecord.MISSING)
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");
110 protected AltosGraphTime myAltosGraphTime(String suffix) {
111 return (new AltosGraphTime("Overall " + suffix))
115 .addElement(e_drogue)
117 .addElement(e_landed);
120 public ArrayList<AltosGraph> graphs() {
121 ArrayList<AltosGraph> graphs = new ArrayList<AltosGraph>();
123 graphs.add( myAltosGraphTime("Summary")
125 .addElement(gps_height)
127 .addElement(acceleration) );
129 graphs.add( myAltosGraphTime("Summary")
133 graphs.add( myAltosGraphTime("Altitude")
134 .addElement(height) );
136 graphs.add( myAltosGraphTime("Speed")
137 .addElement(speed) );
139 graphs.add( myAltosGraphTime("Acceleration")
140 .addElement(acceleration) );
142 graphs.add( myAltosGraphTime("Temperature")
143 .addElement(temperature) );
145 graphs.add( myAltosGraphTime("Continuity")
146 .addElement(drogue_voltage)
147 .addElement(main_voltage) );
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) {
163 }).addElement(e_boost)
165 .addElement(e_coast);
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) {
180 }).addElement(e_drogue)
182 // ((XYGraph)graph[8]).ymin = new Double(-50);
187 public AltosGraphUI(AltosRecordIterable records, String name) throws InterruptedException, IOException {
188 super(String.format("Altos Graph %s", name));
190 AltosDataPointReader reader = new AltosDataPointReader (records);
192 if (reader.has_accel)
193 init(reader, records, 0);
195 init(reader, records, 1);
198 // public AltosGraphUI(AltosDataPointReader data, int which)
200 // super("Altos Graph");
201 // init(data, which);
204 private void init(AltosDataPointReader data, AltosRecordIterable records, int which) throws InterruptedException, IOException {
205 pane = new JTabbedPane();
207 AltosGraph graph = createGraph(data, which);
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);
215 AltosFlightStatsTable stats = new AltosFlightStatsTable(new AltosFlightStats(records));
216 pane.add("Flight Statistics", stats);
218 setContentPane (pane);
222 RefineryUtilities.centerFrameOnScreen(this);
224 setDefaultCloseOperation(DISPOSE_ON_CLOSE);
228 private static AltosGraph createGraph(Iterable<AltosDataPoint> data,
231 return createGraphsWhich(data, which).get(0);
235 private static ArrayList<AltosGraph> createGraphs(
236 Iterable<AltosDataPoint> data)
238 return createGraphsWhich(data, -1);
242 private static ArrayList<AltosGraph> createGraphsWhich(
243 Iterable<AltosDataPoint> data, int which)
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());
251 if (which >= graph.size()) {
254 AltosGraph g = graph.get(which);
255 graph = new ArrayList<AltosGraph>();
259 for (AltosDataPoint dp : data) {
260 for (AltosGraph g : graph) {
273 --------------------------------------------------------
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)
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
286 set term png tiny size 700,700 enhanced
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"
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"
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"