--- /dev/null
+
+// Copyright (c) 2010 Anthony Towns
+// GPL v2 or later
+
+package altosui;
+
+import java.lang.UnsupportedOperationException;
+import java.util.HashMap;
+import java.util.NoSuchElementException;
+import java.util.Iterator;
+import java.io.*;
+import com.csvreader.CsvReader;
+
+import altosui.AltosDataPoint;
+
+class AltosCsvReader implements Iterable<AltosDataPoint>
+{
+ public CsvReader csv;
+ public AltosDataPoint next = null;
+
+ static protected String [] headers = "version serial flight call time rssi state state_name acceleration pressure altitude height accel_speed baro_speed temperature battery_voltage drogue_voltage main_voltage connected locked nsat latitude longitude altitude year month day hour minute second pad_dist pad_range pad_az pad_el".split(" ");
+
+ AltosCsvReader(Reader stream) {
+ csv = new CsvReader(stream);
+ csv.setComment('#');
+ csv.setUseComments(true);
+ csv.setHeaders(headers);
+ }
+ AltosCsvReader(String filename) throws FileNotFoundException {
+ csv = new CsvReader(filename);
+ csv.setComment('#');
+ csv.setUseComments(true);
+ csv.setHeaders(headers);
+ }
+
+ public Iterator<AltosDataPoint> iterator() {
+ return new Iterator<AltosDataPoint>() {
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+ public boolean hasNext() {
+ if (next == null) {
+ try {
+ if (csv.readRecord()) {
+ next = new CsvRow();
+ } else {
+ close();
+ return false;
+ }
+ } catch (IOException e) {
+ close();
+ return false;
+ }
+ }
+ return true;
+ }
+ public AltosDataPoint next() {
+ if (!hasNext())
+ throw new NoSuchElementException();
+ AltosDataPoint res = next;
+ next = null;
+ return res;
+ }
+ };
+ }
+
+ public void close() {
+ csv.close();
+ }
+
+ private class CsvRow extends HashMap<String,String>
+ implements AltosDataPoint
+ {
+ CsvRow() throws IOException {
+ for (int i = 0; i < headers.length; i++) {
+ this.put(headers[i], csv.get(headers[i]).trim());
+ }
+ }
+
+ private int intField(String name) {
+ return Integer.parseInt(get(name).trim());
+ }
+ private double doubleField(String name) {
+ return Double.valueOf(get(name)).doubleValue();
+ }
+ private String stringField(String name) {
+ return get(name);
+ }
+
+ public int version() { return intField("version"); }
+ public int serial() { return intField("serial"); }
+ public int flight() { return intField("flight"); }
+ public String callsign() { return stringField("call"); }
+ public double time() { return doubleField("time"); }
+ public double rssi() { return doubleField("rssi"); }
+
+ public int state() { return intField("state"); }
+ public String state_name() { return stringField("state_name"); }
+
+ public double acceleration() { return doubleField("acceleration"); }
+ public double pressure() { return doubleField("pressure"); }
+ public double altitude() { return doubleField("altitude"); }
+ public double height() { return doubleField("height"); }
+ public double accel_speed() { return doubleField("accel_speed"); }
+ public double baro_speed() { return doubleField("baro_speed"); }
+ public double temperature() { return doubleField("temperature"); }
+ public double battery_voltage() {
+ return doubleField("battery_voltage");
+ }
+ public double drogue_voltage() { return doubleField("drogue_voltage"); }
+ public double main_voltage() { return doubleField("main_voltage"); }
+ }
+}
--- /dev/null
+
+// Copyright (c) 2010 Anthony Towns
+// GPL v2 or later
+
+package altosui;
+
+interface AltosDataPoint {
+ int version();
+ int serial();
+ int flight();
+ String callsign();
+ double time();
+ double rssi();
+
+ int state();
+ String state_name();
+
+ double acceleration();
+ double pressure();
+ double altitude();
+ double height();
+ double accel_speed();
+ double baro_speed();
+ double temperature();
+ double battery_voltage();
+ double drogue_voltage();
+ double main_voltage();
+}
+
--- /dev/null
+
+// Copyright (c) 2010 Anthony Towns
+// GPL v2 or later
+
+package altosui;
+
+import java.io.*;
+
+import org.jfree.chart.JFreeChart;
+import org.jfree.chart.ChartUtilities;
+
+import altosui.AltosDataPoint;
+
+abstract class AltosGraph {
+ public String filename;
+ public abstract void addData(AltosDataPoint d);
+ public abstract JFreeChart createChart();
+ public void toPNG() throws java.io.IOException { toPNG(300, 500); }
+ public void toPNG(int width, int height)
+ throws java.io.IOException
+ {
+ File pngout = new File(filename);
+ JFreeChart chart = createChart();
+ ChartUtilities.saveChartAsPNG(pngout, chart, width, height);
+ System.out.println("Created " + filename);
+ }
+}
--- /dev/null
+/*
+ * Copyright © 2010 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package altosui;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import javax.swing.filechooser.FileNameExtensionFilter;
+import javax.swing.table.*;
+import java.io.*;
+import java.util.*;
+import java.text.*;
+import java.util.prefs.*;
+
+import altosui.AltosPreferences;
+import altosui.AltosReader;
+import altosui.AltosCsvReader;
+import altosui.AltosEepromReader;
+import altosui.AltosTelemetryReader;
+
+public class AltosGraphDataChooser extends JFileChooser {
+ JFrame frame;
+ String filename;
+ File file;
+
+ public String filename() {
+ return filename;
+ }
+
+ public File file() {
+ return file;
+ }
+
+ public Iterable<AltosDataPoint> runDialog() {
+ int ret;
+
+ ret = showOpenDialog(frame);
+ if (ret == APPROVE_OPTION) {
+ file = getSelectedFile();
+ if (file == null)
+ return null;
+ filename = file.getName();
+ try {
+ return new AltosCsvReader(new FileReader(file));
+ } catch (FileNotFoundException fe) {
+ JOptionPane.showMessageDialog(frame,
+ filename,
+ "Cannot open file",
+ JOptionPane.ERROR_MESSAGE);
+ }
+ }
+ return null;
+ }
+
+ public AltosGraphDataChooser(JFrame in_frame) {
+ frame = in_frame;
+ setDialogTitle("Select Flight Record File");
+ setFileFilter(new FileNameExtensionFilter("Flight data file",
+ "csv"));
+ setCurrentDirectory(AltosPreferences.logdir());
+ }
+}
--- /dev/null
+
+// Copyright (c) 2010 Anthony Towns
+// GPL v2 or later
+
+package altosui;
+
+import java.awt.Color;
+import java.util.ArrayList;
+import java.util.HashMap;
+
+import org.jfree.chart.ChartUtilities;
+import org.jfree.chart.JFreeChart;
+import org.jfree.chart.axis.AxisLocation;
+import org.jfree.chart.axis.NumberAxis;
+import org.jfree.chart.labels.StandardXYToolTipGenerator;
+import org.jfree.chart.plot.PlotOrientation;
+import org.jfree.chart.plot.XYPlot;
+import org.jfree.chart.plot.ValueMarker;
+import org.jfree.chart.renderer.xy.StandardXYItemRenderer;
+import org.jfree.chart.renderer.xy.XYItemRenderer;
+import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
+import org.jfree.data.xy.XYSeries;
+import org.jfree.data.xy.XYSeriesCollection;
+import org.jfree.ui.RectangleAnchor;
+import org.jfree.ui.TextAnchor;
+
+import altosui.AltosDataPoint;
+import altosui.AltosGraph;
+
+class AltosGraphTime extends AltosGraph {
+ static interface Element {
+ void attachGraph(AltosGraphTime g);
+ void gotTimeData(double time, AltosDataPoint d);
+ void addToPlot(AltosGraphTime g, XYPlot plot);
+ }
+
+ static class TimeAxis implements Element {
+ private int axis;
+ private Color color;
+ private String label;
+ private AxisLocation locn;
+ private double min_y = Double.NaN;
+
+ public TimeAxis(int axis, String label, Color color, AxisLocation locn)
+ {
+ this.axis = axis;
+ this.color = color;
+ this.label = label;
+ this.locn = locn;
+ }
+
+ public void setLowerBound(double min_y) {
+ this.min_y = min_y;
+ }
+
+ public void attachGraph(AltosGraphTime g) { return; }
+ public void gotTimeData(double time, AltosDataPoint d) { return; }
+
+ public void addToPlot(AltosGraphTime g, XYPlot plot) {
+ NumberAxis numAxis = new NumberAxis(label);
+ if (!Double.isNaN(min_y))
+ numAxis.setLowerBound(min_y);
+ plot.setRangeAxis(axis, numAxis);
+ plot.setRangeAxisLocation(axis, locn);
+ numAxis.setLabelPaint(color);
+ numAxis.setTickLabelPaint(color);
+ numAxis.setAutoRangeIncludesZero(false);
+ }
+ }
+
+ abstract static class TimeSeries implements Element {
+ protected XYSeries series;
+ private String axisName;
+ private Color color;
+
+ public TimeSeries(String axisName, String label, Color color) {
+ this.series = new XYSeries(label);
+ this.axisName = axisName;
+ this.color = color;
+ }
+
+ public void attachGraph(AltosGraphTime g) {
+ g.setAxis(this, axisName, color);
+ }
+ abstract public void gotTimeData(double time, AltosDataPoint d);
+
+ public void addToPlot(AltosGraphTime g, XYPlot plot) {
+ XYSeriesCollection dataset = new XYSeriesCollection();
+ dataset.addSeries(this.series);
+
+ XYItemRenderer renderer = new StandardXYItemRenderer();
+ renderer.setSeriesPaint(0, color);
+
+ int dataNum = g.getDataNum(this);
+ int axisNum = g.getAxisNum(this);
+
+ plot.setDataset(dataNum, dataset);
+ plot.mapDatasetToRangeAxis(dataNum, axisNum);
+ plot.setRenderer(dataNum, renderer);
+ }
+ }
+
+ static class StateMarker implements Element {
+ private double val = Double.NaN;
+ private String name;
+ private int state;
+
+ StateMarker(int state, String name) {
+ this.state = state;
+ this.name = name;
+ }
+
+ public void attachGraph(AltosGraphTime g) { return; }
+ public void gotTimeData(double time, AltosDataPoint d) {
+ if (Double.isNaN(val) || time < val) {
+ if (d.state() == state) {
+ val = time;
+ }
+ }
+ }
+
+ public void addToPlot(AltosGraphTime g, XYPlot plot) {
+ if (Double.isNaN(val))
+ return;
+
+ ValueMarker m = new ValueMarker(val);
+ m.setLabel(name);
+ m.setLabelAnchor(RectangleAnchor.TOP_RIGHT);
+ m.setLabelTextAnchor(TextAnchor.TOP_LEFT);
+ plot.addDomainMarker(m);
+ }
+ }
+
+ private String title;
+ private ArrayList<Element> elements;
+ private HashMap<String,Integer> axes;
+ private HashMap<Element,Integer> datasets;
+ private ArrayList<Integer> datasetAxis;
+
+ public AltosGraphTime(String title) {
+ this.filename = title.toLowerCase().replaceAll("[^a-z0-9]","_")+".png";
+ this.title = title;
+ this.elements = new ArrayList<Element>();
+ this.axes = new HashMap<String,Integer>();
+ this.datasets = new HashMap<Element,Integer>();
+ this.datasetAxis = new ArrayList<Integer>();
+ }
+
+ public AltosGraphTime addElement(Element e) {
+ e.attachGraph(this);
+ elements.add(e);
+ return this;
+ }
+
+ public void setAxis(Element ds, String axisName, Color color) {
+ Integer axisNum = axes.get(axisName);
+ int dsNum = datasetAxis.size();
+ if (axisNum == null) {
+ axisNum = newAxis(axisName, color);
+ }
+ datasets.put(ds, dsNum);
+ datasetAxis.add(axisNum);
+ }
+
+ public int getAxisNum(Element ds) {
+ return datasetAxis.get( datasets.get(ds) ).intValue();
+ }
+ public int getDataNum(Element ds) {
+ return datasets.get(ds).intValue();
+ }
+
+ private Integer newAxis(String name, Color color) {
+ int cnt = axes.size();
+ AxisLocation locn = AxisLocation.BOTTOM_OR_LEFT;
+ if (cnt > 0) {
+ locn = AxisLocation.TOP_OR_RIGHT;
+ }
+ Integer res = new Integer(cnt);
+ axes.put(name, res);
+ this.addElement(new TimeAxis(cnt, name, color, locn));
+ return res;
+ }
+
+ public void addData(AltosDataPoint d) {
+ double time = d.time();
+ for (Element e : elements) {
+ e.gotTimeData(time, d);
+ }
+ }
+
+ public JFreeChart createChart() {
+ NumberAxis xAxis = new NumberAxis("Time (s)");
+ xAxis.setAutoRangeIncludesZero(false);
+ XYItemRenderer renderer = new XYLineAndShapeRenderer(true, false);
+ XYPlot plot = new XYPlot();
+ plot.setDomainAxis(xAxis);
+ plot.setRenderer(renderer);
+ plot.setOrientation(PlotOrientation.VERTICAL);
+
+ renderer.setBaseToolTipGenerator(new StandardXYToolTipGenerator());
+ JFreeChart chart = new JFreeChart(title, JFreeChart.DEFAULT_TITLE_FONT,
+ plot, true);
+ ChartUtilities.applyCurrentTheme(chart);
+
+ plot.setDomainPannable(true);
+ plot.setRangePannable(true);
+
+ for (Element e : elements) {
+ e.addToPlot(this, plot);
+ }
+
+ return chart;
+ }
+
+ public void toPNG() throws java.io.IOException {
+ if (axes.size() > 1) {
+ toPNG(800, 500);
+ } else {
+ toPNG(300, 500);
+ }
+ }
+}
--- /dev/null
+
+// Copyright (c) 2010 Anthony Towns
+// GPL v2 or later
+
+package altosui;
+
+import java.io.*;
+import java.util.ArrayList;
+
+import javax.swing.JFrame;
+import java.awt.Color;
+
+import org.jfree.chart.ChartPanel;
+import org.jfree.chart.ChartUtilities;
+import org.jfree.chart.JFreeChart;
+import org.jfree.chart.axis.AxisLocation;
+import org.jfree.ui.ApplicationFrame;
+import org.jfree.ui.RefineryUtilities;
+
+import altosui.AltosCsvReader;
+import altosui.AltosDataPoint;
+import altosui.AltosGraphTime;
+
+public class AltosGraphUI extends JFrame
+{
+ static final private Color red = new Color(194,31,31);
+ static final private Color green = new Color(31,194,31);
+ static final private Color blue = new Color(31,31,194);
+ static final private Color black = new Color(31,31,31);
+
+ static private class OverallGraphs {
+ AltosGraphTime.Element height =
+ new AltosGraphTime.TimeSeries("Height (m)", "Height (AGL)", red) {
+ public void gotTimeData(double time, AltosDataPoint d) {
+ series.add(time, d.height());
+ }
+ };
+
+ AltosGraphTime.Element speed =
+ new AltosGraphTime.TimeSeries("Speed (m/s)", "Vertical Speed", green) {
+ public void gotTimeData(double time, AltosDataPoint d) {
+ if (d.state() < 4) {
+ series.add(time, d.accel_speed());
+ } else {
+ series.add(time, d.baro_speed());
+ }
+ }
+ };
+
+ AltosGraphTime.Element acceleration =
+ new AltosGraphTime.TimeSeries("Acceleration (m/s\u00B2)",
+ "Axial Acceleration", blue)
+ {
+ public void gotTimeData(double time, AltosDataPoint d) {
+ series.add(time, d.acceleration());
+ }
+ };
+
+ AltosGraphTime.Element temperature =
+ new AltosGraphTime.TimeSeries("Temperature (\u00B0C)",
+ "Board temperature", red)
+ {
+ public void gotTimeData(double time, AltosDataPoint d) {
+ series.add(time, d.temperature());
+ }
+ };
+
+ AltosGraphTime.Element drogue_voltage =
+ new AltosGraphTime.TimeSeries("Voltage (V)", "Drogue Continuity", blue)
+ {
+ public void gotTimeData(double time, AltosDataPoint d) {
+ series.add(time, d.drogue_voltage());
+ }
+ };
+
+ AltosGraphTime.Element main_voltage =
+ new AltosGraphTime.TimeSeries("Voltage (V)", "Main Continuity", green)
+ {
+ public void gotTimeData(double time, AltosDataPoint d) {
+ series.add(time, d.main_voltage());
+ }
+ };
+
+ AltosGraphTime.Element e_pad = new AltosGraphTime.StateMarker(2, "Pad");
+ AltosGraphTime.Element e_boost = new AltosGraphTime.StateMarker(3, "Boost");
+ AltosGraphTime.Element e_fast = new AltosGraphTime.StateMarker(4, "Fast");
+ AltosGraphTime.Element e_coast = new AltosGraphTime.StateMarker(5, "Coast");
+ AltosGraphTime.Element e_drogue = new AltosGraphTime.StateMarker(6, "Drogue");
+ AltosGraphTime.Element e_main = new AltosGraphTime.StateMarker(7, "Main");
+ AltosGraphTime.Element e_landed = new AltosGraphTime.StateMarker(8, "Landed");
+
+ protected AltosGraphTime myAltosGraphTime(String suffix) {
+ return (new AltosGraphTime("Overall " + suffix))
+ .addElement(e_boost)
+ .addElement(e_drogue)
+ .addElement(e_main)
+ .addElement(e_landed);
+ }
+
+ public ArrayList<AltosGraph> graphs() {
+ ArrayList<AltosGraph> graphs = new ArrayList<AltosGraph>();
+
+ graphs.add( myAltosGraphTime("Summary")
+ .addElement(height)
+ .addElement(speed)
+ .addElement(acceleration) );
+
+ graphs.add( myAltosGraphTime("Altitude")
+ .addElement(height) );
+
+ graphs.add( myAltosGraphTime("Speed")
+ .addElement(speed) );
+
+ graphs.add( myAltosGraphTime("Acceleration")
+ .addElement(acceleration) );
+
+ graphs.add( myAltosGraphTime("Temperature")
+ .addElement(temperature) );
+
+ graphs.add( myAltosGraphTime("Continuity")
+ .addElement(drogue_voltage)
+ .addElement(main_voltage) );
+
+ return graphs;
+ }
+ }
+
+ static private class AscentGraphs extends OverallGraphs {
+ protected AltosGraphTime myAltosGraphTime(String suffix) {
+ return (new AltosGraphTime("Ascent " + suffix) {
+ public void addData(AltosDataPoint d) {
+ int state = d.state();
+ if (3 <= state && state <= 5) {
+ super.addData(d);
+ }
+ }
+ }).addElement(e_boost)
+ .addElement(e_fast)
+ .addElement(e_coast);
+ }
+ }
+
+ static private class DescentGraphs extends OverallGraphs {
+ protected AltosGraphTime myAltosGraphTime(String suffix) {
+ return (new AltosGraphTime("Descent " + suffix) {
+ public void addData(AltosDataPoint d) {
+ int state = d.state();
+ if (6 <= state && state <= 7) {
+ super.addData(d);
+ }
+ }
+ }).addElement(e_drogue)
+ .addElement(e_main);
+ // ((XYGraph)graph[8]).ymin = new Double(-50);
+ }
+ }
+
+ public AltosGraphUI(JFrame frame)
+ {
+ super("Altos Graph");
+
+ AltosGraphDataChooser chooser;
+ chooser = new AltosGraphDataChooser(frame);
+ Iterable<AltosDataPoint> reader = chooser.runDialog();
+ if (reader == null)
+ return;
+
+ init(reader, 0);
+ }
+
+ public AltosGraphUI(Iterable<AltosDataPoint> data, int which)
+ {
+ super("Altos Graph");
+ init(data, which);
+ }
+
+ private void init(Iterable<AltosDataPoint> data, int which) {
+ AltosGraph graph = createGraph(data, which);
+
+ JFreeChart chart = graph.createChart();
+ ChartPanel chartPanel = new ChartPanel(chart);
+ chartPanel.setMouseWheelEnabled(true);
+ chartPanel.setPreferredSize(new java.awt.Dimension(800, 500));
+ setContentPane(chartPanel);
+
+ pack();
+
+ RefineryUtilities.centerFrameOnScreen(this);
+
+ setDefaultCloseOperation(DISPOSE_ON_CLOSE);
+ setVisible(true);
+ }
+
+ private static AltosGraph createGraph(Iterable<AltosDataPoint> data,
+ int which)
+ {
+ return createGraphsWhich(data, which).get(0);
+ }
+
+ private static ArrayList<AltosGraph> createGraphs(
+ Iterable<AltosDataPoint> data)
+ {
+ return createGraphsWhich(data, -1);
+ }
+
+ private static ArrayList<AltosGraph> createGraphsWhich(
+ Iterable<AltosDataPoint> data, int which)
+ {
+ ArrayList<AltosGraph> graph = new ArrayList<AltosGraph>();
+ graph.addAll((new OverallGraphs()).graphs());
+ graph.addAll((new AscentGraphs()).graphs());
+ graph.addAll((new DescentGraphs()).graphs());
+
+ if (which > 0) {
+ if (which >= graph.size()) {
+ which = 0;
+ }
+ AltosGraph g = graph.get(which);
+ graph = new ArrayList<AltosGraph>();
+ graph.add(g);
+ }
+
+ for (AltosDataPoint dp : data) {
+ for (AltosGraph g : graph) {
+ g.addData(dp);
+ }
+ }
+
+ return graph;
+ }
+
+ public static void main(String[] args)
+ throws java.io.FileNotFoundException, java.io.IOException
+ {
+ if (args.length < 1 || 2 < args.length)
+ {
+ System.out.println("Please specify telemetry csv");
+ return;
+ }
+
+ AltosCsvReader csv = new AltosCsvReader(args[0]);
+ if (args.length == 1) {
+ for (AltosGraph g : createGraphs(csv)) {
+ g.toPNG();
+ }
+ } else {
+ int which = Integer.parseInt(args[1].trim());
+ AltosGraphUI demo = new AltosGraphUI(csv, which);
+ }
+ }
+}
+
+/* gnuplot bits...
+ *
+300x400
+
+--------------------------------------------------------
+TOO HARD! :)
+
+"ascent-gps-accuracy.png" "Vertical error margin to apogee - GPS v Baro (m)"
+ 5:($7 < 6 ? $24-$11 : 1/0)
+"descent-gps-accuracy.png" "Vertical error margin during descent - GPS v Baro (m)"
+ 5:($7 < 6 ? 1/0 : $24-$11)
+
+set output "overall-gps-accuracy.png"
+set ylabel "distance above sea level (m)"
+plot "telemetry.csv" using 5:11 with lines ti "baro altitude" axis x1y1, \
+ "telemetry.csv" using 5:24 with lines ti "gps altitude" axis x1y1
+
+set term png tiny size 700,700 enhanced
+set xlabel "m"
+set ylabel "m"
+set polar
+set grid polar
+set rrange[*:*]
+set angles degrees
+
+set output "overall-gps-path.png"
+#:30 with yerrorlines
+plot "telemetry.csv" using (90-$33):($7 == 2 ? $31 : 1/0) with lines ti "pad", \
+ "telemetry.csv" using (90-$33):($7 == 3 ? $31 : 1/0) with lines ti "boost", \
+ "telemetry.csv" using (90-$33):($7 == 4 ? $31 : 1/0) with lines ti "fast", \
+ "telemetry.csv" using (90-$33):($7 == 5 ? $31 : 1/0) with lines ti "coast", \
+ "telemetry.csv" using (90-$33):($7 == 6 ? $31 : 1/0) with lines ti "drogue", \
+ "telemetry.csv" using (90-$33):($7 == 7 ? $31 : 1/0) with lines ti "main", \
+ "telemetry.csv" using (90-$33):($7 == 8 ? $31 : 1/0) with lines ti "landed"
+
+set output "ascent-gps-path.png"
+plot "telemetry.csv" using (90-$33):($7 == 2 ? $31 : 1/0):30 with lines ti "pad", \
+ "telemetry.csv" using (90-$33):($7 == 3 ? $31 : 1/0):20 with lines ti "boost", \
+ "telemetry.csv" using (90-$33):($7 == 4 ? $31 : 1/0):10 with lines ti "fast", \
+ "telemetry.csv" using (90-$33):($7 == 5 ? $31 : 1/0):5 with lines ti "coast"
+
+set output "descent-gps-path.png"
+plot "telemetry.csv" using (90-$33):($7 == 6 ? $31 : 1/0) with lines ti "drogue", \
+ "telemetry.csv" using (90-$33):($7 == 7 ? $31 : 1/0) with lines ti "main", \
+ "telemetry.csv" using (90-$33):($7 == 8 ? $31 : 1/0) with lines ti "landed"
+
+ */
+
+
new AltosCSVUI(AltosUI.this);
}
+ /* Load a flight log CSV file and display a pretty graph.
+ */
+
+ private void GraphData() {
+ new AltosGraphUI(AltosUI.this);
+ }
+
/* Create the AltosUI menus
*/
private void createMenu() {
});
menu.add(item);
+ item = new JMenuItem("Graph Data",KeyEvent.VK_F);
+ item.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ GraphData();
+ }
+ });
+ menu.add(item);
+
item = new JMenuItem("Quit",KeyEvent.VK_Q);
item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q,
ActionEvent.CTRL_MASK));
altosui.setVisible(true);
}
}
-}
\ No newline at end of file
+}