From: Anthony Towns Date: Tue, 28 Sep 2010 02:55:47 +0000 (+1000) Subject: Merge branch 'master' of git://git.gag.com/fw/altos X-Git-Tag: debian/0.7.1+28+gd8a2f4c~6 X-Git-Url: https://git.gag.com/?p=fw%2Faltos;a=commitdiff_plain;h=e2b9f47a205348d38756c70e928a2a9183de6884;hp=803203197e51e71e9c77b3610047fd5bf9a56c56 Merge branch 'master' of git://git.gag.com/fw/altos --- diff --git a/ao-tools/altosui/AltosCsvReader.java b/ao-tools/altosui/AltosCsvReader.java new file mode 100644 index 00000000..600788f4 --- /dev/null +++ b/ao-tools/altosui/AltosCsvReader.java @@ -0,0 +1,113 @@ + +// 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 +{ + 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 iterator() { + return new Iterator() { + 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 + 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"); } + } +} diff --git a/ao-tools/altosui/AltosDataPoint.java b/ao-tools/altosui/AltosDataPoint.java new file mode 100644 index 00000000..66313e03 --- /dev/null +++ b/ao-tools/altosui/AltosDataPoint.java @@ -0,0 +1,29 @@ + +// 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(); +} + diff --git a/ao-tools/altosui/AltosGraph.java b/ao-tools/altosui/AltosGraph.java new file mode 100644 index 00000000..fa3b87c1 --- /dev/null +++ b/ao-tools/altosui/AltosGraph.java @@ -0,0 +1,27 @@ + +// 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); + } +} diff --git a/ao-tools/altosui/AltosGraphDataChooser.java b/ao-tools/altosui/AltosGraphDataChooser.java new file mode 100644 index 00000000..1bf28454 --- /dev/null +++ b/ao-tools/altosui/AltosGraphDataChooser.java @@ -0,0 +1,77 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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 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()); + } +} diff --git a/ao-tools/altosui/AltosGraphTime.java b/ao-tools/altosui/AltosGraphTime.java new file mode 100644 index 00000000..c0f99c59 --- /dev/null +++ b/ao-tools/altosui/AltosGraphTime.java @@ -0,0 +1,222 @@ + +// 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 elements; + private HashMap axes; + private HashMap datasets; + private ArrayList datasetAxis; + + public AltosGraphTime(String title) { + this.filename = title.toLowerCase().replaceAll("[^a-z0-9]","_")+".png"; + this.title = title; + this.elements = new ArrayList(); + this.axes = new HashMap(); + this.datasets = new HashMap(); + this.datasetAxis = new ArrayList(); + } + + 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); + } + } +} diff --git a/ao-tools/altosui/AltosGraphUI.java b/ao-tools/altosui/AltosGraphUI.java new file mode 100644 index 00000000..73f95023 --- /dev/null +++ b/ao-tools/altosui/AltosGraphUI.java @@ -0,0 +1,301 @@ + +// 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 graphs() { + ArrayList graphs = new ArrayList(); + + 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 reader = chooser.runDialog(); + if (reader == null) + return; + + init(reader, 0); + } + + public AltosGraphUI(Iterable data, int which) + { + super("Altos Graph"); + init(data, which); + } + + private void init(Iterable 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 data, + int which) + { + return createGraphsWhich(data, which).get(0); + } + + private static ArrayList createGraphs( + Iterable data) + { + return createGraphsWhich(data, -1); + } + + private static ArrayList createGraphsWhich( + Iterable data, int which) + { + ArrayList graph = new ArrayList(); + 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(); + 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" + + */ + + diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java index 29eda2ec..de0673a2 100644 --- a/ao-tools/altosui/AltosUI.java +++ b/ao-tools/altosui/AltosUI.java @@ -245,6 +245,13 @@ public class AltosUI extends JFrame { 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() { @@ -291,6 +298,14 @@ public class AltosUI extends JFrame { }); 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)); @@ -472,4 +487,4 @@ public class AltosUI extends JFrame { altosui.setVisible(true); } } -} \ No newline at end of file +} diff --git a/ao-tools/altosui/Makefile.am b/ao-tools/altosui/Makefile.am index 7070af22..ab8ca7d4 100644 --- a/ao-tools/altosui/Makefile.am +++ b/ao-tools/altosui/Makefile.am @@ -5,7 +5,7 @@ man_MANS=altosui.1 altoslibdir=$(libdir)/altos -CLASSPATH_ENV=mkdir -p $(JAVAROOT); CLASSPATH=".:classes:../libaltos:$(FREETTS)/*:/usr/share/java/*" +CLASSPATH_ENV=mkdir -p $(JAVAROOT); CLASSPATH=".:classes:../libaltos:$(JFREECHART)/*:$(FREETTS)/*:/usr/share/java/*" bin_SCRIPTS=altosui @@ -53,8 +53,19 @@ altosui_JAVA = \ AltosTelemetry.java \ AltosTelemetryIterable.java \ AltosUI.java \ + AltosCsvReader.java \ + AltosDataPoint.java \ + AltosGraph.java \ + AltosGraphTime.java \ + AltosGraphUI.java \ + AltosGraphDataChooser.java \ AltosVoice.java +JFREECHART_CLASS= \ + jfreechart.jar \ + jcommon.jar \ + csv.jar + FREETTS_CLASS= \ cmudict04.jar \ cmulex.jar \ @@ -87,7 +98,7 @@ LINUX_DIST=Altos-Linux-$(VERSION).tar.bz2 MACOSX_DIST=Altos-Mac-$(VERSION).zip WINDOWS_DIST=Altos-Windows-$(VERSION_DASH).exe -FAT_FILES=$(FATJAR) $(FREETTS_CLASS) +FAT_FILES=$(FATJAR) $(FREETTS_CLASS) $(JFREECHART_CLASS) LINUX_FILES=$(FAT_FILES) libaltos.so $(FIRMWARE) LINUX_EXTRA=altosui-fat @@ -102,7 +113,7 @@ all-local: classes/altosui $(JAR) altosui altosui-test clean-local: -rm -rf classes $(JAR) $(FATJAR) \ $(LINUX_DIST) $(MACOSX_DIST) windows $(WINDOWS_DIST) $(FREETTS_CLASS) \ - $(LIBALTOS) Manifest.txt Manifest-fat.txt altos-windows.log \ + $(JFREECHART_CLASS) $(LIBALTOS) Manifest.txt Manifest-fat.txt altos-windows.log \ altosui altosui-test macosx linux if FATINSTALL @@ -149,7 +160,7 @@ $(JAR): classaltosui.stamp Manifest.txt $(JAVA_ICON) -C classes altosui \ -C ../libaltos libaltosJNI -$(FATJAR): classaltosui.stamp Manifest-fat.txt $(FREETTS_CLASS) $(LIBALTOS) $(JAVA_ICON) +$(FATJAR): classaltosui.stamp Manifest-fat.txt $(FREETTS_CLASS) $(JFREECHART_CLASS) $(LIBALTOS) $(JAVA_ICON) jar cfm $@ Manifest-fat.txt \ -C $(top_srcdir)/icon altus-metrum-16x16.jpg \ -C classes altosui \ @@ -157,11 +168,11 @@ $(FATJAR): classaltosui.stamp Manifest-fat.txt $(FREETTS_CLASS) $(LIBALTOS) $(JA Manifest.txt: Makefile echo 'Main-Class: altosui.AltosUI' > $@ - echo "Class-Path: $(FREETTS)/freetts.jar" >> $@ + echo "Class-Path: $(FREETTS)/freetts.jar $(JFREECHART)/jfreechart.jar $(JFREECHAR)/jcommon.jar $(JFREECHART)/csv.jar" >> $@ Manifest-fat.txt: echo 'Main-Class: altosui.AltosUI' > $@ - echo "Class-Path: freetts.jar" >> $@ + echo "Class-Path: freetts.jar jfreechart.jar jcommon.jar csv.jar" >> $@ altosui: Makefile echo "#!/bin/sh" > $@