public ArrayList<AltosTimeSeries> series = new ArrayList<AltosTimeSeries>();
public double speed_filter_width = 4.0;
- public double accel_filter_width = 4.0;
+ public double accel_filter_width = 1.0;
public int[] indices() {
int[] indices = new int[series.size()];
}
public AltosTimeSeries accel_series;
+ public boolean accel_computed;
public static final String accel_name = "Accel";
accel_series = add_series(accel_name, AltosConvert.accel);
accel_series.add(time(), acceleration);
+ accel_computed = false;
}
- private void compute_accel() {
- if (accel_series != null)
- return;
+ private AltosTimeSeries compute_accel() {
+ AltosTimeSeries new_accel_series = null;
if (speed_series != null) {
- AltosTimeSeries temp_series = make_series(speed_name, AltosConvert.speed);
- speed_series.filter(temp_series, accel_filter_width);
- accel_series = add_series(accel_name, AltosConvert.accel);
- temp_series.differentiate(accel_series);
+ AltosTimeSeries temp_series;
+ if (accel_filter_width > 0) {
+ temp_series = make_series(speed_name, AltosConvert.speed);
+ speed_series.filter(temp_series, accel_filter_width);
+ } else
+ temp_series = speed_series;
+
+ new_accel_series = make_series(accel_name, AltosConvert.accel);
+ temp_series.differentiate(new_accel_series);
+ }
+ return new_accel_series;
+ }
+
+ public void set_filter(double speed_filter, double accel_filter) {
+ this.speed_filter_width = speed_filter;
+ this.accel_filter_width = accel_filter;
+
+ AltosTimeSeries new_speed_series = compute_speed();
+
+ if (new_speed_series != null) {
+ speed_series.erase_values();
+ for (AltosTimeValue tv : new_speed_series)
+ speed_series.add(tv);
+ }
+ if (accel_computed) {
+ AltosTimeSeries new_accel_series = compute_accel();
+ if (new_accel_series != null) {
+ accel_series.erase_values();
+ for (AltosTimeValue tv : new_accel_series)
+ accel_series.add(tv);
+ }
}
}
public static final String speed_name = "Speed";
- private void compute_speed() {
- if (speed_series != null)
- return;
-
+ private AltosTimeSeries compute_speed() {
+ AltosTimeSeries new_speed_series = null;
AltosTimeSeries alt_speed_series = null;
AltosTimeSeries accel_speed_series = null;
if (altitude_series != null) {
- AltosTimeSeries temp_series = make_series(altitude_name, AltosConvert.height);
- altitude_series.filter(temp_series, speed_filter_width);
+ AltosTimeSeries temp_series;
+
+ if (speed_filter_width > 0) {
+ temp_series = make_series(speed_name, AltosConvert.height);
+ altitude_series.filter(temp_series, speed_filter_width);
+ } else
+ temp_series = altitude_series;
alt_speed_series = make_series(speed_name, AltosConvert.speed);
temp_series.differentiate(alt_speed_series);
}
- if (accel_series != null) {
+ if (accel_series != null && !accel_computed) {
if (orient_series != null) {
vert_accel_series = add_series(vert_accel_name, AltosConvert.accel);
}
}
if (apogee_time == AltosLib.MISSING) {
- speed_series = alt_speed_series;
+ new_speed_series = alt_speed_series;
} else {
- speed_series = make_series(speed_name, AltosConvert.speed);
+ new_speed_series = make_series(speed_name, AltosConvert.speed);
for (AltosTimeValue d : accel_speed_series) {
if (d.time <= apogee_time)
- speed_series.add(d);
+ new_speed_series.add(d);
}
for (AltosTimeValue d : alt_speed_series) {
if (d.time > apogee_time)
- speed_series.add(d);
+ new_speed_series.add(d);
}
}
} else if (alt_speed_series != null) {
- speed_series = alt_speed_series;
+ new_speed_series = alt_speed_series;
} else if (accel_speed_series != null) {
- speed_series = accel_speed_series;
+ new_speed_series = accel_speed_series;
}
- if (speed_series != null)
- add_series(speed_series);
+ return new_speed_series;
}
public AltosTimeSeries orient_series;
public void finish() {
compute_orient();
- compute_speed();
- compute_accel();
+ if (speed_series == null) {
+ speed_series = compute_speed();
+ if (speed_series != null)
+ add_series(speed_series);
+ }
+ if (accel_series == null) {
+ accel_series = compute_accel();
+ if (accel_series != null) {
+ add_series(accel_series);
+ accel_computed = true;
+ }
+ }
compute_height();
}
public String label;
public AltosUnits units;
ArrayList<AltosTimeValue> values;
+ boolean data_changed;
public int compareTo(AltosTimeSeries other) {
return label.compareTo(other.label);
}
public void add(AltosTimeValue tv) {
+ data_changed = true;
values.add(tv);
}
+ public void erase_values() {
+ data_changed = true;
+ this.values = new ArrayList<AltosTimeValue>();
+ }
+
+ public void clear_changed() {
+ data_changed = false;
+ }
+
+// public boolean changed() {
+// return data_changed;
+// }
+
public void add(double time, double value) {
add(new AltosTimeValue(time, value));
}
}
- private double filter_coeff(double dist, double width) {
- double ratio = dist / (width / 2);
+ private static double i0(double x) {
+ double ds = 1, d = 0, s = 0;
- return Math.cos(ratio * Math.PI / 2);
+ do {
+ d += 2;
+ ds = ds * (x * x) / (d * d);
+ s += ds;
+ } while (ds - 0.2e-8 * s > 0);
+ return s;
+ }
+
+ private static double kaiser(double n, double m, double beta) {
+ double alpha = m / 2;
+ double t = (n - alpha) / alpha;
+
+ if (t > 1)
+ t = 1;
+ double k = i0 (beta * Math.sqrt (1 - t*t)) / i0(beta);
+ return k;
+ }
+
+ private double filter_coeff(double dist, double width) {
+ return kaiser(dist + width/2.0, width, 2 * Math.PI);
}
public AltosTimeSeries filter(AltosTimeSeries f, double width) {
+
double half_width = width/2;
+ int half_point = values.size() / 2;
for (int i = 0; i < values.size(); i++) {
double center_time = values.get(i).time;
double left_time = center_time - half_width;
AltosEepromList.java \
AltosEepromLog.java \
AltosFile.java \
+ AltosFilterListener.java \
AltosFlash.java \
AltosFlashListener.java \
AltosDataListener.java \
import org.jfree.chart.JFreeChart;
import org.jfree.ui.RefineryUtilities;
-public class AltosGraphUI extends AltosUIFrame implements AltosFontListener, AltosUnitsListener
+public class AltosGraphUI extends AltosUIFrame implements AltosFontListener, AltosUnitsListener, AltosFilterListener
{
JTabbedPane pane;
AltosGraph graph;
enable.units_changed(imperial_units);
}
+ AltosUIFlightSeries flight_series;
+
+ public void filter_changed(double speed_filter, double accel_filter) {
+ flight_series.set_filter(speed_filter, accel_filter);
+ graph.filter_changed();
+ stats = new AltosFlightStats(flight_series);
+ statsTable.filter_changed(stats);
+ }
+
+ public double speed_filter() {
+ return flight_series.speed_filter_width;
+ }
+
+ public double accel_filter() {
+ return flight_series.accel_filter_width;
+ }
+
AltosGraphUI(AltosRecordSet set, File file) throws InterruptedException, IOException {
super(file.getName());
AltosCalData cal_data = set.cal_data();
pane = new JTabbedPane();
- enable = new AltosUIEnable();
+ flight_series = new AltosUIFlightSeries(cal_data);
- AltosUIFlightSeries flight_series = new AltosUIFlightSeries(cal_data);
+ enable = new AltosUIEnable(this);
set.capture_series(flight_series);
value[i].setFont(AltosUILib.value_font);
}
+ public void set(String ... values) {
+ for (int j = 0; j < values.length; j++)
+ value[j].setText(values[j]);
+ }
+
public FlightStat(GridBagLayout layout, int y, String label_text, String ... values) {
GridBagConstraints c = new GridBagConstraints();
c.insets = new Insets(AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad, AltosUILib.tab_elt_pad);
return String.format("%s %4d° %9.6f'", h, deg, min);
}
+ private FlightStat max_height_stat;
+ private FlightStat max_speed_stat;
+ private FlightStat max_accel_stat;
+ private FlightStat boost_accel_stat;
+ private FlightStat drogue_descent_stat;
+ private FlightStat main_descent_stat;
+
+ public void set_values(AltosFlightStats stats) {
+ if (max_height_stat != null && stats.max_height != AltosLib.MISSING) {
+ max_height_stat.set(String.format("%6.1f m", stats.max_height),
+ String.format("%5.0f ft", AltosConvert.meters_to_feet(stats.max_height)));
+ }
+ if (max_speed_stat != null && stats.max_speed != AltosLib.MISSING) {
+ max_speed_stat.set(String.format("%6.1f m/s", stats.max_speed),
+ String.format("%5.0f fps", AltosConvert.mps_to_fps(stats.max_speed)),
+ String.format("Mach %4.1f", AltosConvert.meters_to_mach(stats.max_speed)));
+ }
+ if (max_accel_stat != null && stats.max_acceleration != AltosLib.MISSING) {
+ max_accel_stat.set(String.format("%6.1f m/s²", stats.max_acceleration),
+ String.format("%5.0f ft/s²", AltosConvert.meters_to_feet(stats.max_acceleration)),
+ String.format("%6.2f G", AltosConvert.meters_to_g(stats.max_acceleration)));
+ }
+ if (boost_accel_stat != null && stats.state_accel[AltosLib.ao_flight_boost] != AltosLib.MISSING) {
+ boost_accel_stat.set(String.format("%6.1f m/s²", stats.state_accel[AltosLib.ao_flight_boost]),
+ String.format("%5.0f ft/s²", AltosConvert.meters_to_feet(stats.state_accel[AltosLib.ao_flight_boost])),
+ String.format("%6.2f G", AltosConvert.meters_to_g(stats.state_accel[AltosLib.ao_flight_boost])));
+ }
+ if (drogue_descent_stat != null && stats.state_speed[AltosLib.ao_flight_drogue] != AltosLib.MISSING) {
+ drogue_descent_stat.set(String.format("%6.1f m/s", -stats.state_speed[AltosLib.ao_flight_drogue]),
+ String.format("%5.0f ft/s", -AltosConvert.meters_to_feet(stats.state_speed[AltosLib.ao_flight_drogue])));
+ }
+ if (main_descent_stat != null && stats.state_speed[AltosLib.ao_flight_main] != AltosLib.MISSING) {
+ main_descent_stat.set(String.format("%6.1f m/s", -stats.state_speed[AltosLib.ao_flight_main]),
+ String.format("%5.0f ft/s", -AltosConvert.meters_to_feet(stats.state_speed[AltosLib.ao_flight_main])));
+ }
+ }
+
public void set_stats(AltosFlightStats stats) {
int y = 0;
if (stats.serial != AltosLib.MISSING) {
String.format("%02d:%02d:%02d UTC", stats.hour, stats.minute, stats.second));
}
if (stats.max_height != AltosLib.MISSING) {
- new FlightStat(layout, y++, "Maximum height",
- String.format("%6.1f m", stats.max_height),
- String.format("%5.0f ft", AltosConvert.meters_to_feet(stats.max_height)));
+ max_height_stat = new FlightStat(layout, y++, "Maximum height",
+ String.format("%6.1f m", stats.max_height),
+ String.format("%5.0f ft", AltosConvert.meters_to_feet(stats.max_height)));
}
if (stats.max_gps_height != AltosLib.MISSING) {
new FlightStat(layout, y++, "Maximum GPS height",
String.format("%5.0f ft", AltosConvert.meters_to_feet(stats.max_gps_height)));
}
if (stats.max_speed != AltosLib.MISSING) {
- new FlightStat(layout, y++, "Maximum speed",
- String.format("%6.1f m/s", stats.max_speed),
- String.format("%5.0f fps", AltosConvert.mps_to_fps(stats.max_speed)),
- String.format("Mach %4.1f", AltosConvert.meters_to_mach(stats.max_speed)));
+ max_speed_stat = new FlightStat(layout, y++, "Maximum speed",
+ String.format("%6.1f m/s", stats.max_speed),
+ String.format("%5.0f fps", AltosConvert.mps_to_fps(stats.max_speed)),
+ String.format("Mach %4.1f", AltosConvert.meters_to_mach(stats.max_speed)));
}
if (stats.max_acceleration != AltosLib.MISSING)
- new FlightStat(layout, y++, "Maximum boost acceleration",
- String.format("%6.1f m/s²", stats.max_acceleration),
- String.format("%5.0f ft/s²", AltosConvert.meters_to_feet(stats.max_acceleration)),
- String.format("%6.2f G", AltosConvert.meters_to_g(stats.max_acceleration)));
+ max_accel_stat = new FlightStat(layout, y++, "Maximum boost acceleration",
+ String.format("%6.1f m/s²", stats.max_acceleration),
+ String.format("%5.0f ft/s²", AltosConvert.meters_to_feet(stats.max_acceleration)),
+ String.format("%6.2f G", AltosConvert.meters_to_g(stats.max_acceleration)));
if (stats.state_accel[AltosLib.ao_flight_boost] != AltosLib.MISSING)
- new FlightStat(layout, y++, "Average boost acceleration",
- String.format("%6.1f m/s²", stats.state_accel[AltosLib.ao_flight_boost]),
- String.format("%5.0f ft/s²", AltosConvert.meters_to_feet(stats.state_accel[AltosLib.ao_flight_boost])),
- String.format("%6.2f G", AltosConvert.meters_to_g(stats.state_accel[AltosLib.ao_flight_boost])));
+ boost_accel_stat = new FlightStat(layout, y++, "Average boost acceleration",
+ String.format("%6.1f m/s²", stats.state_accel[AltosLib.ao_flight_boost]),
+ String.format("%5.0f ft/s²", AltosConvert.meters_to_feet(stats.state_accel[AltosLib.ao_flight_boost])),
+ String.format("%6.2f G", AltosConvert.meters_to_g(stats.state_accel[AltosLib.ao_flight_boost])));
if (stats.state_time[AltosLib.ao_flight_boost] != 0 || stats.state_time[AltosLib.ao_flight_fast] != 0 || stats.state_time[AltosLib.ao_flight_coast] != 0) {
double boost_time = stats.state_time[AltosLib.ao_flight_boost];
label = "Descent rate";
else
label = "Drogue descent rate";
- new FlightStat(layout, y++, label,
+ drogue_descent_stat = new FlightStat(layout, y++, label,
String.format("%6.1f m/s", -stats.state_speed[AltosLib.ao_flight_drogue]),
String.format("%5.0f ft/s", -AltosConvert.meters_to_feet(stats.state_speed[AltosLib.ao_flight_drogue])));
}
if (stats.state_speed[AltosLib.ao_flight_main] != AltosLib.MISSING)
- new FlightStat(layout, y++, "Main descent rate",
- String.format("%6.1f m/s", -stats.state_speed[AltosLib.ao_flight_main]),
- String.format("%5.0f ft/s", -AltosConvert.meters_to_feet(stats.state_speed[AltosLib.ao_flight_main])));
+ main_descent_stat = new FlightStat(layout, y++, "Main descent rate",
+ String.format("%6.1f m/s", -stats.state_speed[AltosLib.ao_flight_main]),
+ String.format("%5.0f ft/s", -AltosConvert.meters_to_feet(stats.state_speed[AltosLib.ao_flight_main])));
if (stats.state_time[AltosLib.ao_flight_drogue] != 0 || stats.state_time[AltosLib.ao_flight_main] != 0) {
double drogue_duration = stats.state_time[AltosLib.ao_flight_drogue];
double main_duration = stats.state_time[AltosLib.ao_flight_main];
AltosUIPreferences.unregister_font_listener(this);
}
+ public void filter_changed(AltosFlightStats stats) {
+ set_values(stats);
+ }
+
public AltosFlightStatsTable() {
layout = new GridBagLayout();
AltosUIAxis gyro_axis, orient_axis, mag_axis;
AltosUIAxis course_axis, dop_axis, tick_axis;
- if (stats.serial != AltosLib.MISSING && stats.product != null && stats.flight != AltosLib.MISSING)
+ if (stats != null && stats.serial != AltosLib.MISSING && stats.product != null && stats.flight != AltosLib.MISSING)
setName(String.format("%s %d flight %d\n", stats.product, stats.serial, stats.flight));
height_axis = newAxis("Height", AltosConvert.height, height_color);
return flight_series.series(cal_data);
}
- public void set_filter(double filter) {
- System.out.printf("filter set to %f\n", filter);
- flight_series.set_filter(filter, filter);
- units_changed(false);
- }
-
public void set_data(AltosFlightStats stats, AltosUIFlightSeries flight_series) {
set_series(setup(stats, flight_series));
}
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
+import javax.swing.event.*;
import java.io.*;
import java.util.concurrent.*;
import java.util.*;
import org.jfree.data.xy.*;
import org.jfree.data.*;
-public class AltosUIEnable extends Container {
+public class AltosUIEnable extends Container implements ChangeListener {
Insets il, ir;
int y;
int x;
JCheckBox imperial_units;
+ JLabel speed_filter_label;
+ JSlider speed_filter;
+ JLabel accel_filter_label;
+ JSlider accel_filter;
+ AltosFilterListener filter_listener;
static final int max_rows = 14;
}
}
+ LinkedList<GraphElement> elements = new LinkedList<GraphElement>();
+
public void add(String name, AltosUIGrapher grapher, boolean enabled) {
GraphElement e = new GraphElement(name, grapher, enabled);
GridBagConstraints c = new GridBagConstraints();
+ elements.add(e);
+
/* Add element */
c = new GridBagConstraints();
c.gridx = x; c.gridy = y;
}
}
+ public void stateChanged(ChangeEvent e) {
+ JSlider filter = (JSlider) e.getSource();
+ if (!filter.getValueIsAdjusting()) {
+ double speed_value = (int) speed_filter.getValue() / 1000.0;
+ double accel_value = (int) accel_filter.getValue() / 1000.0;
+ if (filter_listener != null) {
+ filter_listener.filter_changed(speed_value, accel_value);
+ }
+ }
+ }
+
public void add_units() {
/* Imperial units setting */
c.anchor = GridBagConstraints.LINE_START;
c.insets = il;
add(imperial_units, c);
+
+ speed_filter_label = new JLabel("Speed Filter(ms)");
+ c = new GridBagConstraints();
+ c.gridx = 0; c.gridy = 1001;
+ c.fill = GridBagConstraints.NONE;
+ c.anchor = GridBagConstraints.LINE_START;
+ c.insets = il;
+ add(speed_filter_label, c);
+
+ speed_filter = new JSlider(JSlider.HORIZONTAL, 0, 10000, (int) (filter_listener.speed_filter() * 1000.0));
+ Hashtable<Integer,JLabel> label_table = new Hashtable<Integer,JLabel>();
+ for (int i = 0; i <= 10000; i += 5000) {
+ label_table.put(new Integer(i), new JLabel(String.format("%d", i)));
+ }
+ speed_filter.setPaintTicks(true);
+ speed_filter.setMajorTickSpacing(1000);
+ speed_filter.setMinorTickSpacing(250);
+ speed_filter.setLabelTable(label_table);
+ speed_filter.setPaintTrack(false);
+ speed_filter.setSnapToTicks(true);
+ speed_filter.setPaintLabels(true);
+ speed_filter.addChangeListener(this);
+
+ c = new GridBagConstraints();
+ c.gridx = 1; c.gridy = 1001;
+ c.gridwidth = 1000; c.gridheight = 1;
+ c.fill = GridBagConstraints.BOTH;
+ c.anchor = GridBagConstraints.LINE_START;
+ c.insets = il;
+ add(speed_filter, c);
+
+ accel_filter_label = new JLabel("Acceleration Filter(ms)");
+ c = new GridBagConstraints();
+ c.gridx = 0; c.gridy = 1002;
+ c.fill = GridBagConstraints.NONE;
+ c.anchor = GridBagConstraints.LINE_START;
+ c.insets = il;
+ add(accel_filter_label, c);
+
+ accel_filter = new JSlider(JSlider.HORIZONTAL, 0, 10000, (int) (filter_listener.accel_filter() * 1000.0));
+ accel_filter.setPaintTicks(true);
+ accel_filter.setMajorTickSpacing(1000);
+ accel_filter.setMinorTickSpacing(250);
+ accel_filter.setLabelTable(label_table);
+ accel_filter.setPaintTrack(false);
+ accel_filter.setSnapToTicks(true);
+ accel_filter.setPaintLabels(true);
+ accel_filter.addChangeListener(this);
+
+ c = new GridBagConstraints();
+ c.gridx = 1; c.gridy = 1002;
+ c.gridwidth = 1000; c.gridheight = 1;
+ c.fill = GridBagConstraints.BOTH;
+ c.anchor = GridBagConstraints.LINE_START;
+ c.insets = il;
+ add(accel_filter, c);
}
- public AltosUIEnable() {
+ public AltosUIEnable(AltosFilterListener filter_listener) {
+ this.filter_listener = filter_listener;
il = new Insets(4,4,4,4);
ir = new Insets(4,4,4,4);
x = 0;
s.set_units();
}
+ public void filter_changed() {
+ units_changed(false);
+ }
+
public void setName (String name) {
chart.setTitle(name);
}
public void fireSeriesChanged() {
}
- void set_data() {
+ public void set_data() {
if (marker) {
if (markers != null) {
for (ValueMarker marker : markers)
}
xy_series.setNotify(true);
}
+ clear_changed();
}
public void set_units() {
import org.altusmetrum.altoslib_12.*;
import org.altusmetrum.altosuilib_12.*;
-public class MicroPeak extends MicroFrame implements ActionListener, ItemListener {
+public class MicroPeak extends MicroFrame implements ActionListener, ItemListener, AltosFilterListener {
File filename;
AltosGraph graph;
Preferences();
}
+ public void filter_changed(double speed_filter, double accel_filter) {
+ data.flight_series.set_filter(speed_filter, accel_filter);
+ graph.filter_changed();
+ data.flight_stats = new AltosFlightStats(data.flight_series);
+ statsTable.filter_changed(data.flight_stats);
+ }
+
+ public double speed_filter() {
+ if (data != null && data.flight_series != null)
+ return data.flight_series.speed_filter_width;
+ return 4.0;
+ }
+
+ public double accel_filter() {
+ if (data != null && data.flight_series != null)
+ return data.flight_series.accel_filter_width;
+ return 1.0;
+ }
+
public MicroPeak() {
++number_of_windows;
}
});
- enable = new AltosUIEnable();
+ enable = new AltosUIEnable(this);
graph = new AltosGraph(enable);
statsTable = new AltosFlightStatsTable();
import org.jfree.chart.JFreeChart;
import org.jfree.ui.RefineryUtilities;
-public class TeleGPSGraphUI extends AltosUIFrame implements AltosFontListener, AltosUnitsListener
+public class TeleGPSGraphUI extends AltosUIFrame implements AltosFontListener, AltosUnitsListener, AltosFilterListener
{
JTabbedPane pane;
AltosGraph graph;
enable.units_changed(imperial_units);
}
+ AltosUIFlightSeries flight_series;
+
+ public void filter_changed(double speed_filter, double accel_filter) {
+ flight_series.set_filter(speed_filter, accel_filter);
+ graph.filter_changed();
+ stats = new AltosFlightStats(flight_series);
+ statsTable.filter_changed(stats);
+ }
+
+ public double speed_filter() {
+ return flight_series.speed_filter_width;
+ }
+
+ public double accel_filter() {
+ return flight_series.accel_filter_width;
+ }
+
TeleGPSGraphUI(AltosRecordSet set, File file) throws InterruptedException, IOException {
super(file.getName());
AltosCalData cal_data = set.cal_data();
- AltosUIFlightSeries flight_series = new AltosUIFlightSeries(cal_data);
+ flight_series = new AltosUIFlightSeries(cal_data);
set.capture_series(flight_series);
flight_series.finish();
pane = new JTabbedPane();
- enable = new AltosUIEnable();
+ graph = new AltosGraph(enable, stats, flight_series);
+
stats = new AltosFlightStats(flight_series);
- graph = new AltosGraph(enable, stats, flight_series);
+ enable = new AltosUIEnable(this);
statsTable = new AltosFlightStatsTable(stats);