2 // Copyright (c) 2010 Anthony Towns
8 import java.util.ArrayList;
12 import org.altusmetrum.AltosLib.*;
14 import org.jfree.chart.ChartPanel;
15 import org.jfree.chart.JFreeChart;
16 import org.jfree.ui.RefineryUtilities;
18 public class AltosGraphUI extends AltosFrame
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);
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));
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) {
44 if (d.state() < Altos.ao_flight_drogue && d.has_accel()) {
45 speed = d.accel_speed();
47 speed = d.baro_speed();
49 if (speed != AltosRecord.MISSING)
50 series.add(time, AltosConvert.speed.value(speed));
54 AltosGraphTime.Element acceleration =
55 new AltosGraphTime.TimeSeries(String.format("Acceleration (%s)",
56 AltosConvert.accel.show_units()),
57 "Axial Acceleration", blue)
59 public void gotTimeData(double time, AltosDataPoint d) {
60 double acceleration = d.acceleration();
61 if (acceleration != AltosRecord.MISSING)
62 series.add(time, AltosConvert.accel.value(acceleration));
66 AltosGraphTime.Element temperature =
67 new AltosGraphTime.TimeSeries("Temperature (\u00B0C)",
68 "Board temperature", red)
70 public void gotTimeData(double time, AltosDataPoint d) {
71 double temp = d.temperature();
72 if (temp != AltosRecord.MISSING)
73 series.add(time, d.temperature());
77 AltosGraphTime.Element drogue_voltage =
78 new AltosGraphTime.TimeSeries("Voltage (V)", "Drogue Continuity", yellow)
80 public void gotTimeData(double time, AltosDataPoint d) {
81 double v = d.drogue_voltage();
82 if (v != AltosRecord.MISSING)
87 AltosGraphTime.Element main_voltage =
88 new AltosGraphTime.TimeSeries("Voltage (V)", "Main Continuity", magenta)
90 public void gotTimeData(double time, AltosDataPoint d) {
91 double v = d.main_voltage();
92 if (v != AltosRecord.MISSING)
97 AltosGraphTime.Element e_pad = new AltosGraphTime.StateMarker(Altos.ao_flight_pad, "Pad");
98 AltosGraphTime.Element e_boost = new AltosGraphTime.StateMarker(Altos.ao_flight_boost, "Boost");
99 AltosGraphTime.Element e_fast = new AltosGraphTime.StateMarker(Altos.ao_flight_fast, "Fast");
100 AltosGraphTime.Element e_coast = new AltosGraphTime.StateMarker(Altos.ao_flight_coast, "Coast");
101 AltosGraphTime.Element e_drogue = new AltosGraphTime.StateMarker(Altos.ao_flight_drogue, "Drogue");
102 AltosGraphTime.Element e_main = new AltosGraphTime.StateMarker(Altos.ao_flight_main, "Main");
103 AltosGraphTime.Element e_landed = new AltosGraphTime.StateMarker(Altos.ao_flight_landed, "Landed");
105 protected AltosGraphTime myAltosGraphTime(String suffix) {
106 return (new AltosGraphTime("Overall " + suffix))
110 .addElement(e_drogue)
112 .addElement(e_landed);
115 public ArrayList<AltosGraph> graphs() {
116 ArrayList<AltosGraph> graphs = new ArrayList<AltosGraph>();
118 graphs.add( myAltosGraphTime("Summary")
121 .addElement(acceleration) );
123 graphs.add( myAltosGraphTime("Summary")
127 graphs.add( myAltosGraphTime("Altitude")
128 .addElement(height) );
130 graphs.add( myAltosGraphTime("Speed")
131 .addElement(speed) );
133 graphs.add( myAltosGraphTime("Acceleration")
134 .addElement(acceleration) );
136 graphs.add( myAltosGraphTime("Temperature")
137 .addElement(temperature) );
139 graphs.add( myAltosGraphTime("Continuity")
140 .addElement(drogue_voltage)
141 .addElement(main_voltage) );
147 static private class AscentGraphs extends OverallGraphs {
148 protected AltosGraphTime myAltosGraphTime(String suffix) {
149 return (new AltosGraphTime("Ascent " + suffix) {
150 public void addData(AltosDataPoint d) {
151 int state = d.state();
152 if (Altos.ao_flight_boost <= state && state <= Altos.ao_flight_coast) {
156 }).addElement(e_boost)
158 .addElement(e_coast);
162 static private class DescentGraphs extends OverallGraphs {
163 protected AltosGraphTime myAltosGraphTime(String suffix) {
164 return (new AltosGraphTime("Descent " + suffix) {
165 public void addData(AltosDataPoint d) {
166 int state = d.state();
167 if (Altos.ao_flight_drogue <= state && state <= Altos.ao_flight_main) {
171 }).addElement(e_drogue)
173 // ((XYGraph)graph[8]).ymin = new Double(-50);
177 public AltosGraphUI(AltosRecordIterable records, String name) throws InterruptedException, IOException {
178 super(String.format("Altos Graph %s", name));
180 AltosDataPointReader reader = new AltosDataPointReader (records);
184 if (reader.has_accel)
185 init(reader, records, 0);
187 init(reader, records, 1);
190 // public AltosGraphUI(AltosDataPointReader data, int which)
192 // super("Altos Graph");
193 // init(data, which);
196 private void init(AltosDataPointReader data, AltosRecordIterable records, int which) throws InterruptedException, IOException {
197 pane = new JTabbedPane();
199 AltosGraph graph = createGraph(data, which);
201 JFreeChart chart = graph.createChart();
202 ChartPanel chartPanel = new ChartPanel(chart);
203 chartPanel.setMouseWheelEnabled(true);
204 chartPanel.setPreferredSize(new java.awt.Dimension(800, 500));
205 pane.add(graph.title, chartPanel);
207 AltosFlightStatsTable stats = new AltosFlightStatsTable(new AltosFlightStats(records));
208 pane.add("Flight Statistics", stats);
210 setContentPane (pane);
214 RefineryUtilities.centerFrameOnScreen(this);
216 setDefaultCloseOperation(DISPOSE_ON_CLOSE);
220 private static AltosGraph createGraph(Iterable<AltosDataPoint> data,
223 return createGraphsWhich(data, which).get(0);
226 private static ArrayList<AltosGraph> createGraphs(
227 Iterable<AltosDataPoint> data)
229 return createGraphsWhich(data, -1);
232 private static ArrayList<AltosGraph> createGraphsWhich(
233 Iterable<AltosDataPoint> data, int which)
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());
241 if (which >= graph.size()) {
244 AltosGraph g = graph.get(which);
245 graph = new ArrayList<AltosGraph>();
249 for (AltosDataPoint dp : data) {
250 for (AltosGraph g : graph) {
263 --------------------------------------------------------
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)
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
276 set term png tiny size 700,700 enhanced
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"
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"
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"