From a9aa2d3558c77eb444223eaa747c75916bc7bac1 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 11 May 2017 12:14:41 -0600 Subject: altoslib: include TimeSeries code in build --- altoslib/Makefile.am | 3 +++ 1 file changed, 3 insertions(+) (limited to 'altoslib/Makefile.am') diff --git a/altoslib/Makefile.am b/altoslib/Makefile.am index b93d1f88..20b82849 100644 --- a/altoslib/Makefile.am +++ b/altoslib/Makefile.am @@ -119,6 +119,9 @@ altoslib_JAVA = \ AltosTelemetrySensor.java \ AltosTelemetrySatellite.java \ AltosTelemetryStandard.java \ + AltosTime.java \ + AltosTimeSeries.java \ + AltosTimeValue.java \ AltosUnitsListener.java \ AltosUnknownProduct.java \ AltosMs5607.java \ -- cgit v1.2.3 From 258808d296aeadaf150fa9b07e9c99a6bf1ca7c8 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 11 May 2017 17:14:51 -0700 Subject: altoslib: Create new abstraction underneath AltosState for recording values Provides a way for the graph API to see raw data values, instead of those cooked by AltosState. Signed-off-by: Keith Packard --- altoslib/AltosConfigData.java | 10 +- altoslib/AltosConvert.java | 2 + altoslib/AltosEepromFile.java | 6 +- altoslib/AltosEepromRecord.java | 11 +- altoslib/AltosEepromRecordFireTwo.java | 2 +- altoslib/AltosEepromRecordFull.java | 5 +- altoslib/AltosEepromRecordGps.java | 6 +- altoslib/AltosEepromRecordMega.java | 8 +- altoslib/AltosEepromRecordMetrum.java | 6 +- altoslib/AltosEepromRecordMini.java | 2 +- altoslib/AltosEepromRecordSet.java | 9 +- altoslib/AltosEepromRecordTiny.java | 2 +- altoslib/AltosFlightListener.java | 117 ++++++++++++++++ altoslib/AltosFlightSeries.java | 249 +++++++++++++++++++++++++++++++++ altoslib/AltosRecordSet.java | 21 +++ altoslib/AltosRotationRate.java | 38 +++++ altoslib/AltosState.java | 26 +--- altoslib/AltosTimeSeries.java | 56 ++++++++ altoslib/Makefile.am | 4 + 19 files changed, 534 insertions(+), 46 deletions(-) create mode 100644 altoslib/AltosFlightListener.java create mode 100644 altoslib/AltosFlightSeries.java create mode 100644 altoslib/AltosRecordSet.java create mode 100644 altoslib/AltosRotationRate.java (limited to 'altoslib/Makefile.am') diff --git a/altoslib/AltosConfigData.java b/altoslib/AltosConfigData.java index 23ab1e11..05fc2031 100644 --- a/altoslib/AltosConfigData.java +++ b/altoslib/AltosConfigData.java @@ -214,6 +214,10 @@ public class AltosConfigData implements Iterable { return r; } + public boolean altitude_32() { + return altitude_32 == 1; + } + public int compare_version(String other) { int[] me = parse_version(version); int[] them = parse_version(other); @@ -438,11 +442,11 @@ public class AltosConfigData implements Iterable { if (frequency > 0) { radio_frequency = (int) Math.floor (freq * 1000 + 0.5); - radio_channel = -1; + radio_channel = AltosLib.MISSING; } else if (setting > 0) { radio_setting =AltosConvert.radio_frequency_to_setting(freq, radio_calibration); - radio_channel = -1; + radio_channel = AltosLib.MISSING; } else { radio_channel = AltosConvert.radio_frequency_to_channel(freq); } @@ -453,7 +457,7 @@ public class AltosConfigData implements Iterable { int setting = radio_setting; if (radio_frequency < 0 && channel < 0 && setting < 0) - return -1; + return AltosLib.MISSING; if (channel < 0) channel = 0; diff --git a/altoslib/AltosConvert.java b/altoslib/AltosConvert.java index 3489a609..a3343a4f 100644 --- a/altoslib/AltosConvert.java +++ b/altoslib/AltosConvert.java @@ -408,6 +408,8 @@ public class AltosConvert { public static AltosLongitude longitude = new AltosLongitude(); + public static AltosRotationRate rotation_rate = new AltosRotationRate(); + public static String show_gs(String format, double a) { a = meters_to_g(a); format = format.concat(" g"); diff --git a/altoslib/AltosEepromFile.java b/altoslib/AltosEepromFile.java index 4606e780..7f629913 100644 --- a/altoslib/AltosEepromFile.java +++ b/altoslib/AltosEepromFile.java @@ -22,7 +22,7 @@ import java.io.*; import java.util.*; import java.text.*; -public class AltosEepromFile extends AltosStateIterable { +public class AltosEepromFile extends AltosStateIterable implements AltosRecordSet { AltosEepromRecordSet set; @@ -44,4 +44,8 @@ public class AltosEepromFile extends AltosStateIterable { public Iterator iterator() { return set.iterator(); } + + public void capture_series(AltosFlightSeries series) { + set.capture_series(series); + } } diff --git a/altoslib/AltosEepromRecord.java b/altoslib/AltosEepromRecord.java index c0edb952..1f6ade66 100644 --- a/altoslib/AltosEepromRecord.java +++ b/altoslib/AltosEepromRecord.java @@ -14,7 +14,6 @@ package org.altusmetrum.altoslib_11; - public abstract class AltosEepromRecord implements Comparable { AltosEepromNew eeprom; @@ -65,6 +64,10 @@ public abstract class AltosEepromRecord implements Comparable return 1; } + public AltosConfigData config_data() { + return eeprom.config_data(); + } + public int compareTo(AltosEepromRecord o) { int cmd_diff = cmdi() - o.cmdi(); @@ -78,11 +81,11 @@ public abstract class AltosEepromRecord implements Comparable return start - o.start; } - public void update_state(AltosState state) { + public void update_state(AltosFlightListener listen) { if (cmd() == AltosLib.AO_LOG_FLIGHT) - state.set_boost_tick(tick()); + listen.set_boost_tick(tick()); else - state.set_tick(tick()); + listen.set_tick(tick()); } public int next_start() { diff --git a/altoslib/AltosEepromRecordFireTwo.java b/altoslib/AltosEepromRecordFireTwo.java index 8c03cd56..a430bd97 100644 --- a/altoslib/AltosEepromRecordFireTwo.java +++ b/altoslib/AltosEepromRecordFireTwo.java @@ -68,7 +68,7 @@ public class AltosEepromRecordFireTwo extends AltosEepromRecord { return AltosConvert.lb_to_n(v * 298 * 9.807); } - public void update_state(AltosState state) { + public void update_state(AltosFlightListener state) { super.update_state(state); switch (cmd()) { diff --git a/altoslib/AltosEepromRecordFull.java b/altoslib/AltosEepromRecordFull.java index fbb8fbd9..0fdfa5e7 100644 --- a/altoslib/AltosEepromRecordFull.java +++ b/altoslib/AltosEepromRecordFull.java @@ -21,12 +21,13 @@ public class AltosEepromRecordFull extends AltosEepromRecord { public static final int two_g_default = 16294 - 15758; - public void update_state(AltosState state) { + public void update_state(AltosFlightListener state) { + super.update_state(state); AltosGPS gps; /* Flush any pending GPS changes */ - if (state.gps_pending) { + if (state.gps_pending()) { switch (cmd()) { case AltosLib.AO_LOG_GPS_LAT: case AltosLib.AO_LOG_GPS_LON: diff --git a/altoslib/AltosEepromRecordGps.java b/altoslib/AltosEepromRecordGps.java index 1312d3ec..4f30692e 100644 --- a/altoslib/AltosEepromRecordGps.java +++ b/altoslib/AltosEepromRecordGps.java @@ -71,13 +71,13 @@ public class AltosEepromRecordGps extends AltosEepromRecord { return start - o.start; } - public void update_state(AltosState state) { + public void update_state(AltosFlightListener state) { super.update_state(state); AltosGPS gps; /* Flush any pending RecordGps changes */ - if (state.gps_pending) { + if (state.gps_pending()) { switch (cmd()) { case AltosLib.AO_LOG_GPS_LAT: case AltosLib.AO_LOG_GPS_LON: @@ -93,7 +93,7 @@ public class AltosEepromRecordGps extends AltosEepromRecord { switch (cmd()) { case AltosLib.AO_LOG_FLIGHT: - if (state.flight == AltosLib.MISSING) { + if (state.flight() == AltosLib.MISSING) { state.set_boost_tick(tick()); state.set_flight(flight()); } diff --git a/altoslib/AltosEepromRecordMega.java b/altoslib/AltosEepromRecordMega.java index 1c6d1aee..3c5f60b3 100644 --- a/altoslib/AltosEepromRecordMega.java +++ b/altoslib/AltosEepromRecordMega.java @@ -109,12 +109,12 @@ public class AltosEepromRecordMega extends AltosEepromRecord { private int svid(int n) { return data8(2 + n * 2); } private int c_n(int n) { return data8(2 + n * 2 + 1); } - public void update_state(AltosState state) { + public void update_state(AltosFlightListener state) { super.update_state(state); AltosGPS gps; /* Flush any pending GPS changes */ - if (state.gps_pending) { + if (state.gps_pending()) { switch (cmd()) { case AltosLib.AO_LOG_GPS_LAT: case AltosLib.AO_LOG_GPS_LON: @@ -186,7 +186,7 @@ public class AltosEepromRecordMega extends AltosEepromRecord { gps.lat = latitude() / 1e7; gps.lon = longitude() / 1e7; - if (state.altitude_32()) + if (config_data().altitude_32()) gps.alt = (altitude_low() & 0xffff) | (altitude_high() << 16); else gps.alt = altitude_low(); @@ -208,7 +208,7 @@ public class AltosEepromRecordMega extends AltosEepromRecord { gps.ground_speed = ground_speed() * 1.0e-2; gps.course = course() * 2; gps.climb_rate = climb_rate() * 1.0e-2; - if (state.compare_version("1.4.9") >= 0) { + if (config_data().compare_version("1.4.9") >= 0) { gps.pdop = pdop() / 10.0; gps.hdop = hdop() / 10.0; gps.vdop = vdop() / 10.0; diff --git a/altoslib/AltosEepromRecordMetrum.java b/altoslib/AltosEepromRecordMetrum.java index c11b6aac..6d516ebb 100644 --- a/altoslib/AltosEepromRecordMetrum.java +++ b/altoslib/AltosEepromRecordMetrum.java @@ -65,13 +65,13 @@ public class AltosEepromRecordMetrum extends AltosEepromRecord { public int svid(int n) { return data8(2 + n * 2); } public int c_n(int n) { return data8(2 + n * 2 + 1); } - public void update_state(AltosState state) { + public void update_state(AltosFlightListener state) { super.update_state(state); AltosGPS gps; /* Flush any pending GPS changes */ - if (state.gps_pending) { + if (state.gps_pending()) { switch (cmd()) { case AltosLib.AO_LOG_GPS_POS: case AltosLib.AO_LOG_GPS_LAT: @@ -111,7 +111,7 @@ public class AltosEepromRecordMetrum extends AltosEepromRecord { gps = state.make_temp_gps(false); gps.lat = latitude() / 1e7; gps.lon = longitude() / 1e7; - if (state.altitude_32()) + if (config_data().altitude_32()) gps.alt = (altitude_low() & 0xffff) | (altitude_high() << 16); else gps.alt = altitude_low(); diff --git a/altoslib/AltosEepromRecordMini.java b/altoslib/AltosEepromRecordMini.java index f0fc61ad..dedf4bda 100644 --- a/altoslib/AltosEepromRecordMini.java +++ b/altoslib/AltosEepromRecordMini.java @@ -62,7 +62,7 @@ public class AltosEepromRecordMini extends AltosEepromRecord { return -1; } - public void update_state(AltosState state) { + public void update_state(AltosFlightListener state) { super.update_state(state); switch (cmd()) { diff --git a/altoslib/AltosEepromRecordSet.java b/altoslib/AltosEepromRecordSet.java index 911b90b9..653a1305 100644 --- a/altoslib/AltosEepromRecordSet.java +++ b/altoslib/AltosEepromRecordSet.java @@ -17,7 +17,7 @@ package org.altusmetrum.altoslib_11; import java.io.*; import java.util.*; -public class AltosEepromRecordSet implements Iterable { +public class AltosEepromRecordSet implements Iterable, AltosRecordSet { AltosEepromNew eeprom; TreeSet ordered; AltosState start_state; @@ -52,6 +52,13 @@ public class AltosEepromRecordSet implements Iterable { return new RecordIterator(); } + public void capture_series(AltosFlightSeries series) { + series.set_config_data(eeprom.config_data()); + for (AltosEepromRecord record : ordered) { + record.update_state(series); + } + } + public AltosEepromRecordSet(AltosEepromNew eeprom) { this.eeprom = eeprom; diff --git a/altoslib/AltosEepromRecordTiny.java b/altoslib/AltosEepromRecordTiny.java index fda6ddff..e70f8cdc 100644 --- a/altoslib/AltosEepromRecordTiny.java +++ b/altoslib/AltosEepromRecordTiny.java @@ -50,7 +50,7 @@ public class AltosEepromRecordTiny extends AltosEepromRecord { return tick; } - public void update_state(AltosState state) { + public void update_state(AltosFlightListener state) { int value = data16(-header_length); state.set_tick(tick()); diff --git a/altoslib/AltosFlightListener.java b/altoslib/AltosFlightListener.java new file mode 100644 index 00000000..ff5e4c3d --- /dev/null +++ b/altoslib/AltosFlightListener.java @@ -0,0 +1,117 @@ +/* + * Copyright © 2017 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, either version 2 of the License, or + * (at your option) any later version. + * + * 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. + */ + +package org.altusmetrum.altoslib_11; + +public abstract class AltosFlightListener { + + int flight; + + public int tick; + int boost_tick; + + AltosGPS temp_gps; + int temp_gps_sat_tick; + + /* AltosEepromRecord */ + public void set_boost_tick(int boost_tick) { + if (boost_tick != AltosLib.MISSING) + this.boost_tick = boost_tick; + } + + public void set_tick(int tick) { + if (tick != AltosLib.MISSING) + this.tick = tick; + } + + public double time() { + if (tick == AltosLib.MISSING) + return AltosLib.MISSING; + return tick / 100.0; + } + + public double boost_time() { + if (boost_tick == AltosLib.MISSING) + return AltosLib.MISSING; + return boost_tick / 100.0; + } + + /* AltosEepromRecordFull */ + + public abstract void set_state(int state); + public abstract void set_ground_accel(double ground_accel); + public void set_flight(int flight) { + if (flight != AltosLib.MISSING) + this.flight = flight; + } + public int flight() { + return flight; + } + + public abstract void set_accel(double accel); + public abstract void set_accel_g(double accel_plus_g, double accel_minus_g); + public abstract void set_pressure(double pa); + + public abstract void set_temperature(double deg_c); + public abstract void set_battery_voltage(double volts); + + public abstract void set_apogee_voltage(double volts); + public abstract void set_main_voltage(double volts); + + public void set_temp_gps() { + temp_gps = null; + } + + public boolean gps_pending() { + return temp_gps != null; + } + + public AltosGPS make_temp_gps(boolean sats) { + if (temp_gps == null) { + temp_gps = new AltosGPS(); + } + if (sats) { + if (tick != temp_gps_sat_tick) + temp_gps.cc_gps_sat = null; + temp_gps_sat_tick = tick; + } + return temp_gps; + } + + public abstract void set_ground_pressure(double ground_pressure); + public abstract void set_accel_ground(double along, double across, double through); + public abstract void set_gyro_zero(double roll, double pitch, double yaw); + public abstract void set_ms5607(int pres_val, int temp_val); + public abstract void check_imu_wrap(AltosIMU imu); + public abstract void set_imu(AltosIMU imu); + public abstract void set_mag(AltosMag mag); + public abstract void set_pyro_voltage(double volts); + public abstract void set_ignitor_voltage(double[] voltage); + public abstract void set_pyro_fired(int pyro_mask); + + public void copy(AltosFlightListener old) { + flight = old.flight; + tick = old.tick; + boost_tick = old.boost_tick; + temp_gps = old.temp_gps; + temp_gps_sat_tick = old.temp_gps_sat_tick; + } + + public void init() { + flight = AltosLib.MISSING; + tick = AltosLib.MISSING; + boost_tick = AltosLib.MISSING; + temp_gps_sat_tick = AltosLib.MISSING; + } +} diff --git a/altoslib/AltosFlightSeries.java b/altoslib/AltosFlightSeries.java new file mode 100644 index 00000000..752aa48b --- /dev/null +++ b/altoslib/AltosFlightSeries.java @@ -0,0 +1,249 @@ +/* + * Copyright © 2017 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, either version 2 of the License, or + * (at your option) any later version. + * + * 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. + */ + +package org.altusmetrum.altoslib_11; + +import java.util.*; + +public class AltosFlightSeries extends AltosFlightListener { + + int flight; + + int tick; + int boost_tick; + + AltosGPS temp_gps; + int temp_gps_sat_tick; + + AltosMs5607 ms5607; + + public ArrayList series; + + /* AltosEepromRecord */ + public void set_boost_tick(int boost_tick) { + if (boost_tick != AltosLib.MISSING) + this.boost_tick = boost_tick; + } + + public void set_tick(int tick) { + if (tick != AltosLib.MISSING) + this.tick = tick; + } + + public double time() { + if (tick == AltosLib.MISSING) + return AltosLib.MISSING; + return tick / 100.0; + } + + public double boost_time() { + if (boost_tick == AltosLib.MISSING) + return AltosLib.MISSING; + return boost_tick / 100.0; + } + + public AltosTimeSeries make_series(String label, AltosUnits units) { + return new AltosTimeSeries(label, units); + } + + public AltosTimeSeries add_series(String label, AltosUnits units) { + System.out.printf("add series %s\n", label); + AltosTimeSeries s = make_series(label, units); + series.add(s); + return s; + } + + /* AltosEepromRecordFull */ + + AltosTimeSeries state_series; + + public static final String state_name = "State"; + + public void set_state(int state) { + if (state_series == null) + state_series = add_series(state_name, null); + state_series.add(time(), state); + } + + public void set_flight(int flight) { + if (flight != AltosLib.MISSING) + this.flight = flight; + } + public int flight() { + return flight; + } + + AltosTimeSeries accel_series; + + double accel_plus_g, accel_minus_g; + + public static final String accel_name = "Accel"; + + public void set_accel(double accel) { + if (accel_series == null) + accel_series = add_series(accel_name, AltosConvert.accel); + double counts_per_g = (accel_minus_g - accel_plus_g) / 2.0; + double counts_per_mss = counts_per_g / 9.80665; + double mss = (accel_plus_g - accel) / counts_per_mss; + + accel_series.add(time(), mss); + } + + + public void set_accel_g(double accel_plus_g, double accel_minus_g) { + this.accel_plus_g = accel_plus_g; + this.accel_minus_g = accel_minus_g; + } + + public void set_config_data(AltosConfigData config_data) { +// if (config_data.callsign != null) +// set_callsign(config_data.callsign); + if (config_data.accel_cal_plus != AltosLib.MISSING && + config_data.accel_cal_minus != AltosLib.MISSING) + set_accel_g(config_data.accel_cal_plus, config_data.accel_cal_minus); +// if (config_data.product != null) +// set_product(config_data.product); +// if (config_data.log_format != AltosLib.MISSING) +// set_log_format(config_data.log_format); +// if (config_data.serial != AltosLib.MISSING) +// set_serial(config_data.serial); + AltosMs5607 ms5607 = new AltosMs5607(config_data); + if (ms5607.valid_config()) + this.ms5607 = ms5607; + } + + public void set_ground_accel(double ground_accel) { + } + + AltosTimeSeries pressure_series; + + public static final String pressure_name = "Pressure"; + + public void set_pressure(double pa) { + if (pressure_series == null) + pressure_series = add_series(pressure_name, AltosConvert.pressure); + pressure_series.add(time(), pa); + } + + public void set_temperature(double deg_c) { + } + + public void set_battery_voltage(double volts) { + } + + public void set_apogee_voltage(double volts) { + } + + public void set_main_voltage(double volts) { + } + + AltosTimeSeries sats_in_view; + AltosTimeSeries sats_in_soln; + AltosTimeSeries gps_altitude; + AltosTimeSeries gps_ground_speed; + AltosTimeSeries gps_ascent_rate; + AltosTimeSeries gps_course; + AltosTimeSeries gps_speed; + + public static final String sats_in_view_name = "Satellites in view"; + public static final String sats_in_soln_name = "Satellites in solution"; + public static final String gps_altitude_name = "GPS Altitude"; + + public void set_temp_gps() { + if (sats_in_view == null) { + sats_in_view = add_series("Satellites in view", null); + sats_in_soln = add_series("Satellites in solution", null); + gps_altitude = add_series("GPS Altitude", AltosConvert.height); + gps_ground_speed = add_series("GPS Ground Speed", AltosConvert.speed); + gps_ascent_rate = add_series("GPS Ascent Rate", AltosConvert.speed); + gps_course = add_series("GPS Course", null); + gps_speed = add_series("GPS Speed", null); + } + + /* XXX capture GPS data */ + super.set_temp_gps(); + } + + public boolean gps_pending() { + return temp_gps != null; + } + + public AltosGPS make_temp_gps(boolean sats) { + if (temp_gps == null) { + temp_gps = new AltosGPS(); + } + if (sats) { + if (tick != temp_gps_sat_tick) + temp_gps.cc_gps_sat = null; + temp_gps_sat_tick = tick; + } + return temp_gps; + } + + public void set_ground_pressure(double ground_pressure) { + } + + public void set_accel_ground(double along, double across, double through) { + } + + public void set_gyro_zero(double roll, double pitch, double yaw) { + } + + public void set_ms5607(int pres_val, int temp_val) { + if (ms5607 != null) { + ms5607.set(pres_val, temp_val); + + set_pressure(ms5607.pa); + set_temperature(ms5607.cc / 100.0); + } + } + + public void check_imu_wrap(AltosIMU imu) { + } + + public void set_imu(AltosIMU imu) { + } + + public void set_mag(AltosMag mag) { + } + + public void set_pyro_voltage(double volts) { + } + + public void set_ignitor_voltage(double[] voltage) { + } + + public void set_pyro_fired(int pyro_mask) { + } + + public void init() { + flight = AltosLib.MISSING; + tick = AltosLib.MISSING; + boost_tick = AltosLib.MISSING; + temp_gps_sat_tick = AltosLib.MISSING; + series = new ArrayList(); + } + + public void copy(AltosFlightSeries old) { + super.copy(old); + } + + public AltosTimeSeries[] series() { + return series.toArray(new AltosTimeSeries[0]); + } + + public AltosFlightSeries() { + init(); + } +} diff --git a/altoslib/AltosRecordSet.java b/altoslib/AltosRecordSet.java new file mode 100644 index 00000000..8a472336 --- /dev/null +++ b/altoslib/AltosRecordSet.java @@ -0,0 +1,21 @@ +/* + * Copyright © 2017 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, either version 2 of the License, or + * (at your option) any later version. + * + * 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. + */ + +package org.altusmetrum.altoslib_11; + +import java.util.*; + +public interface AltosRecordSet { + public void capture_series(AltosFlightSeries series); +} diff --git a/altoslib/AltosRotationRate.java b/altoslib/AltosRotationRate.java new file mode 100644 index 00000000..c3f26f46 --- /dev/null +++ b/altoslib/AltosRotationRate.java @@ -0,0 +1,38 @@ +/* + * Copyright © 2017 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, either version 2 of the License, or + * (at your option) any later version. + * + * 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. + */ + +package org.altusmetrum.altoslib_11; + +public class AltosRotationRate extends AltosUnits { + + public double value(double p, boolean imperial_units) { + return p; + } + + public double inverse(double p, boolean imperial_units) { + return p; + } + + public String show_units(boolean imperial_units) { + return "°/sec"; + } + + public String say_units(boolean imperial_units) { + return "degrees per second"; + } + + public int show_fraction(int width, boolean imperial_units) { + return 1; + } +} diff --git a/altoslib/AltosState.java b/altoslib/AltosState.java index 8c3f93f0..6aa77139 100644 --- a/altoslib/AltosState.java +++ b/altoslib/AltosState.java @@ -24,7 +24,7 @@ package org.altusmetrum.altoslib_11; import java.io.*; -public class AltosState implements Cloneable { +public class AltosState extends AltosFlightListener implements Cloneable { public static final int set_position = 1; public static final int set_gps = 2; @@ -43,9 +43,7 @@ public class AltosState implements Cloneable { public double time; public double prev_time; public double time_change; - public int tick; private int prev_tick; - public int boost_tick; class AltosValue { double value; @@ -870,6 +868,8 @@ public class AltosState implements Cloneable { return; } + super.copy(old); + received_time = old.received_time; time = old.time; time_change = old.time_change; @@ -1071,11 +1071,6 @@ public class AltosState implements Cloneable { } } - public void set_boost_tick(int boost_tick) { - if (boost_tick != AltosLib.MISSING) - this.boost_tick = boost_tick; - } - public String state_name() { return AltosLib.state_name(state); } @@ -1502,23 +1497,10 @@ public class AltosState implements Cloneable { return tick != AltosLib.MISSING && serial != AltosLib.MISSING; } - public AltosGPS make_temp_gps(boolean sats) { - if (temp_gps == null) { - temp_gps = new AltosGPS(gps); - } - gps_pending = true; - if (sats) { - if (tick != temp_gps_sat_tick) - temp_gps.cc_gps_sat = null; - temp_gps_sat_tick = tick; - } - return temp_gps; - } - public void set_temp_gps() { set_gps(temp_gps, gps_sequence + 1); gps_pending = false; - temp_gps = null; + super.set_temp_gps(); } public void set_config_data(AltosConfigData config_data) { diff --git a/altoslib/AltosTimeSeries.java b/altoslib/AltosTimeSeries.java index 53c0076f..0ea7b356 100644 --- a/altoslib/AltosTimeSeries.java +++ b/altoslib/AltosTimeSeries.java @@ -29,6 +29,62 @@ public class AltosTimeSeries implements Iterable { return values.iterator(); } + public void integrate(AltosTimeSeries integral) { + double y = 0.0; + double x = 0.0; + boolean start = true; + + for (AltosTimeValue v : values) { + if (start) { + y = 0.0; + x = v.x; + start = false; + } else { + y += v.y * (v.x - x); + x = v.x; + } + integral.add(x, y); + } + } + + public void differentiate(AltosTimeSeries diff) { + double y = 0.0; + double x = 0.0; + boolean start = true; + + for (AltosTimeValue v: values) { + if (start) { + y = 0.0; + x = v.x; + start = false; + } else { + double dx = v.x - x; + double dy = v.y - y; + + x = v.x; + y = v.y; + if (dx != 0) + diff.add(x, dy); + } + } + } + + private int find_left(int i, double dt) { + int j; + double t = values.get(i).x - dt; + for (j = i; j > 0; j--) { + if (values.get(j).x < t) + break; + } + return j; + + } + + public void filter(AltosTimeSeries out, double width) { + for (int i = 0; i < values.size(); i++) { + } + } + public AltosTimeSeries(String label, AltosUnits units) { this.label = label; this.units = units; diff --git a/altoslib/Makefile.am b/altoslib/Makefile.am index 20b82849..1b37215c 100644 --- a/altoslib/Makefile.am +++ b/altoslib/Makefile.am @@ -35,6 +35,7 @@ altoslib_JAVA = \ AltosCSV.java \ AltosDebug.java \ AltosEepromNew.java \ + AltosRecordSet.java \ AltosEepromRecord.java \ AltosEepromRecordFull.java \ AltosEepromRecordTiny.java \ @@ -54,6 +55,8 @@ altoslib_JAVA = \ AltosFile.java \ AltosFlash.java \ AltosFlashListener.java \ + AltosFlightListener.java \ + AltosFlightSeries.java \ AltosFlightReader.java \ AltosFlightStats.java \ AltosForce.java \ @@ -138,6 +141,7 @@ altoslib_JAVA = \ AltosLocation.java \ AltosLatitude.java \ AltosLongitude.java \ + AltosRotationRate.java \ AltosPyro.java \ AltosWriter.java \ AltosQuaternion.java \ -- cgit v1.2.3 From f26cfe417c6977cf1e7e75a4f050e25f64d41859 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 25 May 2017 17:24:14 -0700 Subject: altoslib: Do data analysis on raw values rather than AltosState Use AltosFlightSeries instead of a sequence of AltosState records when processing saved data. This provides a better way of doing filtering and plotting. Signed-off-by: Keith Packard --- altoslib/AltosCSV.java | 186 +++++++----- altoslib/AltosCalData.java | 348 +++++++++++++++++++++ altoslib/AltosConfigData.java | 43 +-- altoslib/AltosConvert.java | 42 ++- altoslib/AltosDataListener.java | 69 +++++ altoslib/AltosDataProvider.java | 23 ++ altoslib/AltosEeprom.java | 10 +- altoslib/AltosEepromDownload.java | 66 +++- altoslib/AltosEepromFile.java | 16 +- altoslib/AltosEepromNew.java | 4 - altoslib/AltosEepromRecord.java | 9 +- altoslib/AltosEepromRecordFireTwo.java | 14 +- altoslib/AltosEepromRecordFull.java | 47 +-- altoslib/AltosEepromRecordGps.java | 30 +- altoslib/AltosEepromRecordMega.java | 92 +++--- altoslib/AltosEepromRecordMetrum.java | 38 +-- altoslib/AltosEepromRecordMini.java | 20 +- altoslib/AltosEepromRecordSet.java | 50 ++- altoslib/AltosEepromRecordTiny.java | 16 +- altoslib/AltosFile.java | 4 +- altoslib/AltosFlightListener.java | 62 +++- altoslib/AltosFlightSeries.java | 418 ++++++++++++++++++------- altoslib/AltosFlightStats.java | 129 ++++---- altoslib/AltosGPS.java | 12 +- altoslib/AltosGPSTimeValue.java | 28 ++ altoslib/AltosIMU.java | 14 +- altoslib/AltosIdleFetch.java | 60 ++-- altoslib/AltosIdleMonitor.java | 13 +- altoslib/AltosIdleReader.java | 9 +- altoslib/AltosKML.java | 73 +++-- altoslib/AltosLib.java | 10 + altoslib/AltosLog.java | 29 +- altoslib/AltosMag.java | 6 +- altoslib/AltosMap.java | 28 +- altoslib/AltosMma655x.java | 8 +- altoslib/AltosMs5607.java | 174 ++++------- altoslib/AltosPreferences.java | 6 +- altoslib/AltosPresTemp.java | 25 ++ altoslib/AltosRecordSet.java | 3 +- altoslib/AltosSensorTM.java | 14 +- altoslib/AltosState.java | 489 +++++------------------------- altoslib/AltosStateName.java | 32 ++ altoslib/AltosStateUpdate.java | 23 -- altoslib/AltosTelemetry.java | 40 +-- altoslib/AltosTelemetryCompanion.java | 6 +- altoslib/AltosTelemetryConfiguration.java | 18 +- altoslib/AltosTelemetryFile.java | 136 ++++++--- altoslib/AltosTelemetryLegacy.java | 34 ++- altoslib/AltosTelemetryLocation.java | 12 +- altoslib/AltosTelemetryMegaData.java | 26 +- altoslib/AltosTelemetryMegaSensor.java | 45 ++- altoslib/AltosTelemetryMetrumData.java | 8 +- altoslib/AltosTelemetryMetrumSensor.java | 22 +- altoslib/AltosTelemetryMini2.java | 21 +- altoslib/AltosTelemetryMini3.java | 22 +- altoslib/AltosTelemetryRaw.java | 4 +- altoslib/AltosTelemetryReader.java | 12 +- altoslib/AltosTelemetryRecordSet.java | 97 ++++++ altoslib/AltosTelemetrySatellite.java | 8 +- altoslib/AltosTelemetrySensor.java | 28 +- altoslib/AltosTelemetryStandard.java | 4 +- altoslib/AltosTimeSeries.java | 124 ++++++-- altoslib/AltosTimeValue.java | 9 +- altoslib/AltosUnits.java | 8 + altoslib/AltosWriter.java | 2 +- altoslib/Makefile.am | 9 +- 66 files changed, 2091 insertions(+), 1396 deletions(-) create mode 100644 altoslib/AltosCalData.java create mode 100644 altoslib/AltosDataListener.java create mode 100644 altoslib/AltosDataProvider.java create mode 100644 altoslib/AltosGPSTimeValue.java create mode 100644 altoslib/AltosPresTemp.java create mode 100644 altoslib/AltosStateName.java delete mode 100644 altoslib/AltosStateUpdate.java create mode 100644 altoslib/AltosTelemetryRecordSet.java (limited to 'altoslib/Makefile.am') diff --git a/altoslib/AltosCSV.java b/altoslib/AltosCSV.java index b5199456..0cfe4c94 100644 --- a/altoslib/AltosCSV.java +++ b/altoslib/AltosCSV.java @@ -27,16 +27,17 @@ public class AltosCSV implements AltosWriter { boolean header_written; boolean seen_boost; int boost_tick; - LinkedList pad_states; - AltosState state; - static boolean has_basic; - static boolean has_battery; - static boolean has_flight_state; - static boolean has_advanced; - static boolean has_gps; - static boolean has_gps_sat; - static boolean has_companion; + boolean has_basic; + boolean has_battery; + boolean has_flight_state; + boolean has_advanced; + boolean has_gps; + boolean has_gps_sat; + boolean has_companion; + + AltosFlightSeries series; + int[] indices; static final int ALTOS_CSV_VERSION = 5; @@ -117,63 +118,97 @@ public class AltosCSV implements AltosWriter { out.printf("version,serial,flight,call,time,clock,rssi,lqi"); } - void write_general(AltosState state) { + double time() { + return series.time(indices); + } + + int rssi() { + return (int) series.value(AltosFlightSeries.rssi_name, indices); + } + + int status() { + return (int) series.value(AltosFlightSeries.status_name, indices); + } + + void write_general() { + double time = time(); out.printf("%s, %d, %d, %s, %8.2f, %8.2f, %4d, %3d", - ALTOS_CSV_VERSION, state.serial, state.flight, state.callsign, - (double) state.time_since_boost(), (double) state.tick / 100.0, - state.rssi, - state.status & 0x7f); + ALTOS_CSV_VERSION, series.cal_data.serial, + series.cal_data.flight, series.cal_data.callsign, + time, time, + rssi(), status() & 0x7f); } void write_flight_header() { out.printf("state,state_name"); } - void write_flight(AltosState state) { - out.printf("%d,%8s", state.state(), state.state_name()); + int state() { + return (int) series.value(AltosFlightSeries.state_name, indices); + } + + void write_flight() { + int state = state(); + out.printf("%d,%8s", state, AltosLib.state_name(state)); } void write_basic_header() { out.printf("acceleration,pressure,altitude,height,accel_speed,baro_speed,temperature,drogue_voltage,main_voltage"); } - void write_basic(AltosState state) { + double acceleration() { return series.value(AltosFlightSeries.accel_name, indices); } + double pressure() { return series.value(AltosFlightSeries.pressure_name, indices); } + double altitude() { return series.value(AltosFlightSeries.altitude_name, indices); } + double height() { return series.value(AltosFlightSeries.height_name, indices); } + double speed() { return series.value(AltosFlightSeries.speed_name, indices); } + double temperature() { return series.value(AltosFlightSeries.temperature_name, indices); } + double apogee_voltage() { return series.value(AltosFlightSeries.apogee_voltage_name, indices); } + double main_voltage() { return series.value(AltosFlightSeries.main_voltage_name, indices); } + + void write_basic() { out.printf("%8.2f,%10.2f,%8.2f,%8.2f,%8.2f,%8.2f,%5.1f,%5.2f,%5.2f", - state.acceleration(), - state.pressure(), - state.altitude(), - state.height(), - state.speed(), - state.speed(), - state.temperature, - state.apogee_voltage, - state.main_voltage); + acceleration(), + pressure(), + altitude(), + height(), + speed(), + speed(), + temperature(), + apogee_voltage(), + main_voltage()); } void write_battery_header() { out.printf("battery_voltage"); } - void write_battery(AltosState state) { - out.printf("%5.2f", state.battery_voltage); + double battery_voltage() { return series.value(AltosFlightSeries.battery_voltage_name, indices); } + + void write_battery() { + out.printf("%5.2f", battery_voltage()); } void write_advanced_header() { out.printf("accel_x,accel_y,accel_z,gyro_x,gyro_y,gyro_z,mag_x,mag_y,mag_z"); } - void write_advanced(AltosState state) { + void write_advanced() { +/* out.printf("%7.2f,%7.2f,%7.2f,%7.2f,%7.2f,%7.2f,%7.2f,%7.2f,%7.2f", state.accel_along(), state.accel_across(), state.accel_through(), state.gyro_roll(), state.gyro_pitch(), state.gyro_yaw(), state.mag_along(), state.mag_across(), state.mag_through()); +*/ } void write_gps_header() { +/* out.printf("connected,locked,nsat,latitude,longitude,altitude,year,month,day,hour,minute,second,pad_dist,pad_range,pad_az,pad_el,pdop,hdop,vdop"); +*/ } - void write_gps(AltosState state) { + void write_gps() { +/* AltosGPS gps = state.gps; if (gps == null) gps = new AltosGPS(); @@ -202,6 +237,7 @@ public class AltosCSV implements AltosWriter { gps.pdop, gps.hdop, gps.vdop); +*/ } void write_gps_sat_header() { @@ -212,7 +248,8 @@ public class AltosCSV implements AltosWriter { } } - void write_gps_sat(AltosState state) { + void write_gps_sat() { +/* AltosGPS gps = state.gps; for(int i = 1; i <= 32; i++) { int c_n0 = 0; @@ -227,6 +264,7 @@ public class AltosCSV implements AltosWriter { if (i != 32) out.printf(","); } +*/ } void write_companion_header() { @@ -235,7 +273,8 @@ public class AltosCSV implements AltosWriter { out.printf(",companion_%02d", i); } - void write_companion(AltosState state) { + void write_companion() { +/* AltosCompanion companion = state.companion; int channels_written = 0; @@ -252,6 +291,7 @@ public class AltosCSV implements AltosWriter { } for (; channels_written < 12; channels_written++) out.printf(",0"); +*/ } void write_header() { @@ -287,63 +327,47 @@ public class AltosCSV implements AltosWriter { out.printf ("\n"); } - void write_one(AltosState state) { - write_general(state); + void write_one() { + write_general(); if (has_flight_state) { out.printf(","); - write_flight(state); + write_flight(); } if (has_basic) { out.printf(","); - write_basic(state); + write_basic(); } if (has_battery) { out.printf(","); - write_battery(state); + write_battery(); } if (has_advanced) { out.printf(","); - write_advanced(state); + write_advanced(); } if (has_gps) { out.printf(","); - write_gps(state); + write_gps(); } if (has_gps_sat) { out.printf(","); - write_gps_sat(state); + write_gps_sat(); } if (has_companion) { out.printf(","); - write_companion(state); + write_companion(); } out.printf ("\n"); } - private void flush_pad() { - while (!pad_states.isEmpty()) { - write_one (pad_states.remove()); - } - } - - private void write(AltosState state) { - if (state.state() == AltosLib.ao_flight_startup) + private void write() { + if (state() == AltosLib.ao_flight_startup) return; if (!header_written) { write_header(); header_written = true; } - if (!seen_boost) { - if (state.state() >= AltosLib.ao_flight_boost) { - seen_boost = true; - boost_tick = state.tick; - flush_pad(); - } - } - if (seen_boost) - write_one(state); - else - pad_states.add(state); + write_one(); } private PrintStream out() { @@ -351,15 +375,15 @@ public class AltosCSV implements AltosWriter { } public void close() { - if (!pad_states.isEmpty()) { - boost_tick = pad_states.element().tick; - flush_pad(); - } out.close(); } - public void write(AltosStateIterable states) { - states.write_comments(out()); + public void write(AltosFlightSeries series) { +// series.write_comments(out()); + + this.series = series; + + series.fill_in(); has_flight_state = false; has_basic = false; @@ -368,15 +392,16 @@ public class AltosCSV implements AltosWriter { has_gps = false; has_gps_sat = false; has_companion = false; - for (AltosState state : states) { - if (state.state() != AltosLib.ao_flight_stateless && state.state() != AltosLib.ao_flight_invalid && state.state() != AltosLib.ao_flight_startup) - has_flight_state = true; - if (state.acceleration() != AltosLib.MISSING || state.pressure() != AltosLib.MISSING) - has_basic = true; - if (state.battery_voltage != AltosLib.MISSING) - has_battery = true; - if (state.accel_across() != AltosLib.MISSING) - has_advanced = true; + + if (series.has_series(AltosFlightSeries.state_name)) + has_flight_state = true; + if (series.has_series(AltosFlightSeries.accel_name) || series.has_series(AltosFlightSeries.pressure_name)) + has_basic = true; + if (series.has_series(AltosFlightSeries.battery_voltage_name)) + has_battery = true; + if (series.has_series(AltosFlightSeries.accel_across_name)) + has_advanced = true; +/* if (state.gps != null) { has_gps = true; if (state.gps.cc_gps_sat != null) @@ -385,14 +410,19 @@ public class AltosCSV implements AltosWriter { if (state.companion != null) has_companion = true; } - for (AltosState state : states) - write(state); +*/ + indices = series.indices(); + + for (;;) { + write(); + if (!series.step_indices(indices)) + break; + } } public AltosCSV(PrintStream in_out, File in_name) { name = in_name; out = in_out; - pad_states = new LinkedList(); } public AltosCSV(File in_name) throws FileNotFoundException { diff --git a/altoslib/AltosCalData.java b/altoslib/AltosCalData.java new file mode 100644 index 00000000..58d34abe --- /dev/null +++ b/altoslib/AltosCalData.java @@ -0,0 +1,348 @@ +/* + * Copyright © 2017 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, either version 2 of the License, or + * (at your option) any later version. + * + * 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. + */ + +package org.altusmetrum.altoslib_11; + +/* + * Calibration and other data needed to construct 'real' values from various data + * sources. + */ + +public class AltosCalData { + public int flight = AltosLib.MISSING; + + public void set_flight(int flight) { + if (flight != AltosLib.MISSING) + this.flight = flight; + } + + public String callsign = null; + + public void set_callsign(String callsign) { + if (callsign != null) + this.callsign = callsign; + } + + public String firmware_version = null; + + public void set_firmware_version(String firmware_version) { + if (firmware_version != null) + this.firmware_version = firmware_version; + } + + public String product = null; + + public void set_product(String product) { + if (product != null) + this.product = product; + } + + public int serial = AltosLib.MISSING; + + public void set_serial(int serial) { + if (serial != AltosLib.MISSING) + this.serial = serial; + } + + public int receiver_serial = AltosLib.MISSING; + + public void set_receiver_serial(int receiver_serial) { + if (receiver_serial != AltosLib.MISSING) + this.receiver_serial = receiver_serial; + } + + public int device_type = AltosLib.MISSING; + + public void set_device_type(int device_type) { + if (device_type != AltosLib.MISSING) + this.device_type = device_type; + } + + public int config_major = AltosLib.MISSING; + public int config_minor = AltosLib.MISSING; + public int flight_log_max = AltosLib.MISSING; + + public void set_config(int major, int minor, int log_max) { + if (major != AltosLib.MISSING) + config_major = major; + if (minor != AltosLib.MISSING) + config_minor = minor; + if (log_max != AltosLib.MISSING) + flight_log_max = log_max; + } + + public double apogee_delay = AltosLib.MISSING; + public double main_deploy = AltosLib.MISSING; + + public void set_flight_params(double apogee_delay, double main_deploy) { + if (apogee_delay != AltosLib.MISSING) + this.apogee_delay = apogee_delay; + if (main_deploy != AltosLib.MISSING) + this.main_deploy = main_deploy; + } + + public double accel_plus_g = AltosLib.MISSING; + public double accel_minus_g = AltosLib.MISSING; + public double ground_accel = AltosLib.MISSING; + + public void set_accel_plus_minus(double plus, double minus) { + if (plus != AltosLib.MISSING && minus != AltosLib.MISSING) { + accel_plus_g = plus; + accel_minus_g = minus; + } + } + + public void set_ground_accel(double ground_accel) { + if (ground_accel != AltosLib.MISSING) + this.ground_accel = ground_accel; + } + + /* Raw acceleration value */ + public double accel = AltosLib.MISSING; + + public void set_accel(double accel) { + this.accel = accel; + } + + public boolean mma655x_inverted = false; + + public void set_mma655x_inverted(boolean inverted) { + mma655x_inverted = inverted; + } + + public int pad_orientation = AltosLib.MISSING; + + public void set_pad_orientation(int orientation) { + if (orientation != AltosLib.MISSING) + pad_orientation = orientation; + } + + /* Compute acceleration */ + public double acceleration(double sensor) { + return AltosConvert.acceleration_from_sensor(sensor, accel_plus_g, accel_minus_g, ground_accel); + } + + public AltosMs5607 ms5607 = null; + + public void set_ms5607(AltosMs5607 ms5607) { + this.ms5607 = ms5607; + } + + public double ground_pressure = AltosLib.MISSING; + public double ground_altitude = AltosLib.MISSING; + + public void set_ground_pressure(double ground_pressure) { + if (ground_pressure != AltosLib.MISSING) { + this.ground_pressure = ground_pressure; + this.ground_altitude = AltosConvert.pressure_to_altitude(ground_pressure); + } + } + + public void set_ground_altitude(double ground_altitude) { + if (ground_altitude != AltosLib.MISSING) + this.ground_altitude = ground_altitude; + } + + /* Compute pressure */ + + public AltosPresTemp pressure_ms5607(int raw_pres, int raw_temp) { + if (ms5607 == null) + return new AltosPresTemp(AltosLib.MISSING, AltosLib.MISSING); + return ms5607.pres_temp(raw_pres, raw_temp); + } + + public int tick = AltosLib.MISSING; + private int prev_tick = AltosLib.MISSING; + + public void set_tick(int tick) { + if (tick != AltosLib.MISSING) { + if (prev_tick != AltosLib.MISSING) { + while (tick < prev_tick - 1000) { + tick += 65536; + } + } + this.tick = tick; + } + } + + public int boost_tick = AltosLib.MISSING; + + public void set_boost_tick() { + boost_tick = tick; + } + + public double time() { + if (tick == AltosLib.MISSING) + return AltosLib.MISSING; + if (boost_tick == AltosLib.MISSING) + return AltosLib.MISSING; + return (tick - boost_tick) / 100.0; + } + + public double boost_time() { + if (boost_tick == AltosLib.MISSING) + return AltosLib.MISSING; + return boost_tick / 100.0; + } + + public int state = AltosLib.MISSING; + + public void set_state(int state) { + if (state >= AltosLib.ao_flight_boost && boost_tick == AltosLib.MISSING) + set_boost_tick(); + this.state = state; + } + + public double gps_ground_altitude = AltosLib.MISSING; + + public void set_gps_altitude(double altitude) { + if ((state != AltosLib.MISSING && state < AltosLib.ao_flight_boost) || + gps_ground_altitude == AltosLib.MISSING) + gps_ground_altitude = altitude; + } + + /* + * While receiving GPS data, we construct a temporary GPS state + * object and then deliver the result atomically to the listener + */ + AltosGPS temp_gps = null; + int temp_gps_sat_tick = AltosLib.MISSING; + + public AltosGPS temp_gps() { + return temp_gps; + } + + public void reset_temp_gps() { + if (temp_gps != null) { + if (temp_gps.locked && temp_gps.nsat >= 4) + set_gps_altitude(temp_gps.alt); + } + temp_gps = null; + } + + public boolean gps_pending() { + return temp_gps != null; + } + + public AltosGPS make_temp_gps(int tick, boolean sats) { + if (temp_gps == null) { + temp_gps = new AltosGPS(); + } + if (sats) { + if (tick != temp_gps_sat_tick) + temp_gps.cc_gps_sat = null; + temp_gps_sat_tick = tick; + } + return temp_gps; + } + + public double accel_zero_along, accel_zero_across, accel_zero_through; + + public void set_accel_zero(double zero_along, double zero_across, double zero_through) { + if (zero_along != AltosLib.MISSING) { + accel_zero_along = zero_along; + accel_zero_across = zero_across; + accel_zero_through = zero_through; + } + } + + public double accel_along(double counts) { + return AltosIMU.convert_accel(counts - accel_zero_along); + } + + public double accel_across(double counts) { + return AltosIMU.convert_accel(counts - accel_zero_across); + } + + public double accel_through(double counts) { + return AltosIMU.convert_accel(counts - accel_zero_through); + } + + public double gyro_zero_roll, gyro_zero_pitch, gyro_zero_yaw; + + public void set_gyro_zero(double roll, double pitch, double yaw) { + if (roll != AltosLib.MISSING) { + gyro_zero_roll = roll; + gyro_zero_pitch = pitch; + gyro_zero_yaw = yaw; + } + } + + public double gyro_roll(double counts) { + if (gyro_zero_roll == AltosLib.MISSING || counts == AltosLib.MISSING) + return AltosLib.MISSING; + return AltosIMU.convert_gyro(counts - gyro_zero_roll); + } + + public double gyro_pitch(double counts) { + if (gyro_zero_pitch == AltosLib.MISSING || counts == AltosLib.MISSING) + return AltosLib.MISSING; + return AltosIMU.convert_gyro(counts - gyro_zero_pitch); + } + + public double gyro_yaw(double counts) { + if (gyro_zero_yaw == AltosLib.MISSING || counts == AltosLib.MISSING) + return AltosLib.MISSING; + return AltosIMU.convert_gyro(counts - gyro_zero_yaw); + } + + private double gyro_zero_overflow(double first) { + double v = first / 128.0; + if (v < 0) + v = Math.ceil(v); + else + v = Math.floor(v); + return v * 128.0; + } + + public void check_imu_wrap(double roll, double pitch, double yaw) { + gyro_zero_roll += gyro_zero_overflow(roll); + gyro_zero_pitch += gyro_zero_overflow(pitch); + gyro_zero_yaw += gyro_zero_overflow(yaw); + } + + public double mag_along(double along) { + if (along == AltosLib.MISSING) + return AltosLib.MISSING; + return AltosMag.convert_gauss(along); + } + + public double mag_across(double across) { + if (across == AltosLib.MISSING) + return AltosLib.MISSING; + return AltosMag.convert_gauss(across); + } + + public double mag_through(double through) { + if (through == AltosLib.MISSING) + return AltosLib.MISSING; + return AltosMag.convert_gauss(through); + } + + public AltosCalData() { + } + + public AltosCalData(AltosConfigData config_data) { + set_serial(config_data.serial); + set_flight(config_data.flight); + set_callsign(config_data.callsign); + set_accel_plus_minus(config_data.accel_cal_plus, config_data.accel_cal_minus); + set_ms5607(config_data.ms5607); + try { + set_mma655x_inverted(config_data.mma655x_inverted()); + } catch (AltosUnknownProduct up) { + } + set_pad_orientation(config_data.pad_orientation); + } +} diff --git a/altoslib/AltosConfigData.java b/altoslib/AltosConfigData.java index 05fc2031..1972ca0f 100644 --- a/altoslib/AltosConfigData.java +++ b/altoslib/AltosConfigData.java @@ -22,7 +22,7 @@ import java.util.*; import java.text.*; import java.util.concurrent.*; -public class AltosConfigData implements Iterable { +public class AltosConfigData { /* Version information */ public String manufacturer; @@ -34,9 +34,6 @@ public class AltosConfigData implements Iterable { public String version; public int altitude_32; - /* Strings returned */ - public LinkedList __lines; - /* Config information */ /* HAS_FLIGHT*/ public int main_deploy; @@ -96,14 +93,13 @@ public class AltosConfigData implements Iterable { public int accel_zero_along, accel_zero_across, accel_zero_through; /* ms5607 data */ - public int ms5607_reserved; - public int ms5607_sens; - public int ms5607_off; - public int ms5607_tcs; - public int ms5607_tco; - public int ms5607_tref; - public int ms5607_tempsens; - public int ms5607_crc; + AltosMs5607 ms5607; + + public AltosMs5607 ms5607() { + if (ms5607 == null) + ms5607 = new AltosMs5607(); + return ms5607; + } public static String get_string(String line, String label) throws ParseException { if (line.startsWith(label)) { @@ -142,10 +138,6 @@ public class AltosConfigData implements Iterable { throw new ParseException("mismatch", 0); } - public Iterator iterator() { - return __lines.iterator(); - } - public int log_space() { if (log_space > 0) return log_space; @@ -237,8 +229,6 @@ public class AltosConfigData implements Iterable { } public void reset() { - __lines = new LinkedList(); - manufacturer = null; product = null; serial = AltosLib.MISSING; @@ -293,7 +283,6 @@ public class AltosConfigData implements Iterable { } public void parse_line(String line) { - __lines.add(line); /* Version replies */ try { manufacturer = get_string(line, "manufacturer"); } catch (Exception e) {} try { product = get_string(line, "product"); } catch (Exception e) {} @@ -306,14 +295,14 @@ public class AltosConfigData implements Iterable { /* Version also contains MS5607 info, which we ignore here */ - try { ms5607_reserved = get_int(line, "ms5607 reserved:"); } catch (Exception e) {} - try { ms5607_sens = get_int(line, "ms5607 sens:"); } catch (Exception e) {} - try { ms5607_off = get_int(line, "ms5607 off:"); } catch (Exception e) {} - try { ms5607_tcs = get_int(line, "ms5607 tcs:"); } catch (Exception e) {} - try { ms5607_tco = get_int(line, "ms5607 tco:"); } catch (Exception e) {} - try { ms5607_tref = get_int(line, "ms5607 tref:"); } catch (Exception e) {} - try { ms5607_tempsens = get_int(line, "ms5607 tempsens:"); } catch (Exception e) {} - try { ms5607_crc = get_int(line, "ms5607 crc:"); } catch (Exception e) {} + try { ms5607().reserved = get_int(line, "ms5607 reserved:"); } catch (Exception e) {} + try { ms5607().sens = get_int(line, "ms5607 sens:"); } catch (Exception e) {} + try { ms5607().off = get_int(line, "ms5607 off:"); } catch (Exception e) {} + try { ms5607().tcs = get_int(line, "ms5607 tcs:"); } catch (Exception e) {} + try { ms5607().tco = get_int(line, "ms5607 tco:"); } catch (Exception e) {} + try { ms5607().tref = get_int(line, "ms5607 tref:"); } catch (Exception e) {} + try { ms5607().tempsens = get_int(line, "ms5607 tempsens:"); } catch (Exception e) {} + try { ms5607().crc = get_int(line, "ms5607 crc:"); } catch (Exception e) {} /* Config show replies */ diff --git a/altoslib/AltosConvert.java b/altoslib/AltosConvert.java index a3343a4f..95c1a99f 100644 --- a/altoslib/AltosConvert.java +++ b/altoslib/AltosConvert.java @@ -24,6 +24,9 @@ package org.altusmetrum.altoslib_11; import java.util.*; public class AltosConvert { + + public static final double gravity = 9.80665; + /* * Pressure Sensor Model, version 1.1 * @@ -44,20 +47,20 @@ public class AltosConvert { * in Joules/(kilogram-Kelvin). */ - public static final double GRAVITATIONAL_ACCELERATION = -9.80665; - public static final double AIR_GAS_CONSTANT = 287.053; - public static final double NUMBER_OF_LAYERS = 7; - public static final double MAXIMUM_ALTITUDE = 84852.0; - public static final double MINIMUM_PRESSURE = 0.3734; - public static final double LAYER0_BASE_TEMPERATURE = 288.15; - public static final double LAYER0_BASE_PRESSURE = 101325; + private static final double GRAVITATIONAL_ACCELERATION = -gravity; + private static final double AIR_GAS_CONSTANT = 287.053; + private static final double NUMBER_OF_LAYERS = 7; + private static final double MAXIMUM_ALTITUDE = 84852.0; + private static final double MINIMUM_PRESSURE = 0.3734; + private static final double LAYER0_BASE_TEMPERATURE = 288.15; + private static final double LAYER0_BASE_PRESSURE = 101325; /* lapse rate and base altitude for each layer in the atmosphere */ - public static final double[] lapse_rate = { + private static final double[] lapse_rate = { -0.0065, 0.0, 0.001, 0.0028, 0.0, -0.0028, -0.002 }; - public static final int[] base_altitude = { + private static final int[] base_altitude = { 0, 11000, 20000, 32000, 47000, 51000, 71000 }; @@ -307,6 +310,10 @@ public class AltosConvert { return 434.550 + channel * 0.100; } + public static int telem_to_rssi(int telem) { + return telem / 2 - 74; + } + public static int[] ParseHex(String line) { String[] tokens = line.split("\\s+"); int[] array = new int[tokens.length]; @@ -384,6 +391,21 @@ public class AltosConvert { return lb / 0.22480894; } + public static double acceleration_from_sensor(double sensor, double plus_g, double minus_g, double ground) { + if (sensor == AltosLib.MISSING) + return AltosLib.MISSING; + + if (plus_g == AltosLib.MISSING || minus_g == AltosLib.MISSING) + return AltosLib.MISSING; + + if (ground == AltosLib.MISSING) + ground = plus_g; + + double counts_per_g = (plus_g - minus_g) / 2.0; + double counts_per_mss = counts_per_g / gravity; + return (sensor - ground) / counts_per_mss; + } + public static boolean imperial_units = false; public static AltosDistance distance = new AltosDistance(); @@ -410,6 +432,8 @@ public class AltosConvert { public static AltosRotationRate rotation_rate = new AltosRotationRate(); + public static AltosStateName state_name = new AltosStateName(); + public static String show_gs(String format, double a) { a = meters_to_g(a); format = format.concat(" g"); diff --git a/altoslib/AltosDataListener.java b/altoslib/AltosDataListener.java new file mode 100644 index 00000000..b644e817 --- /dev/null +++ b/altoslib/AltosDataListener.java @@ -0,0 +1,69 @@ +/* + * Copyright © 2017 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, either version 2 of the License, or + * (at your option) any later version. + * + * 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. + */ + +package org.altusmetrum.altoslib_11; + +public abstract class AltosDataListener { + + public AltosCalData cal_data; + + public double time = AltosLib.MISSING; + + public void set_time(double time) { + if (time != AltosLib.MISSING) + this.time = time; + } + + public double time() { + return time; + } + + public int state = AltosLib.MISSING; + + public void set_state(int state) { + if (state != AltosLib.MISSING) + this.state = state; + } + + public abstract void set_rssi(int rssi, int status); + public abstract void set_received_time(long received_time); + + public abstract void set_acceleration(double accel); + public abstract void set_pressure(double pa); + public abstract void set_thrust(double N); + + public abstract void set_kalman(double height, double speed, double accel); + + public abstract void set_temperature(double deg_c); + public abstract void set_battery_voltage(double volts); + + public abstract void set_apogee_voltage(double volts); + public abstract void set_main_voltage(double volts); + + public abstract void set_gps(AltosGPS gps); + + public abstract void set_orient(double orient); + public abstract void set_gyro(double roll, double pitch, double yaw); + public abstract void set_accel_ground(double along, double across, double through); + public abstract void set_accel(double along, double across, double through); + public abstract void set_mag(double along, double across, double through); + public abstract void set_pyro_voltage(double volts); + public abstract void set_ignitor_voltage(double[] voltage); + public abstract void set_pyro_fired(int pyro_mask); + public abstract void set_companion(AltosCompanion companion); + + public AltosDataListener(AltosCalData cal_data) { + this.cal_data = cal_data; + } +} diff --git a/altoslib/AltosDataProvider.java b/altoslib/AltosDataProvider.java new file mode 100644 index 00000000..e55071cf --- /dev/null +++ b/altoslib/AltosDataProvider.java @@ -0,0 +1,23 @@ +/* + * Copyright © 2013 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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 org.altusmetrum.altoslib_11; + +public interface AltosDataProvider { + public void provide_data(AltosDataListener listener, AltosCalData cal_data) throws InterruptedException, AltosUnknownProduct; +} diff --git a/altoslib/AltosEeprom.java b/altoslib/AltosEeprom.java index 6ed14d3a..dec7dd57 100644 --- a/altoslib/AltosEeprom.java +++ b/altoslib/AltosEeprom.java @@ -22,7 +22,7 @@ import java.io.*; import java.util.*; import java.text.*; -public abstract class AltosEeprom implements AltosStateUpdate { +public abstract class AltosEeprom implements AltosDataProvider { public int cmd; public int tick; public int data8[]; @@ -52,11 +52,11 @@ public abstract class AltosEeprom implements AltosStateUpdate { public abstract int record_length(); - public void update_state(AltosState state) { + public void provide_data(AltosDataListener listener, AltosCalData cal_data) { + cal_data.set_tick(tick); if (cmd == AltosLib.AO_LOG_FLIGHT) - state.set_boost_tick(tick); - else - state.set_tick(tick); + cal_data.set_boost_tick(); + listener.set_time(cal_data.time()); } public void write(PrintStream out) { diff --git a/altoslib/AltosEepromDownload.java b/altoslib/AltosEepromDownload.java index 74912ed4..4e641b85 100644 --- a/altoslib/AltosEepromDownload.java +++ b/altoslib/AltosEepromDownload.java @@ -23,6 +23,53 @@ import java.util.*; import java.text.*; import java.util.concurrent.*; +class AltosEepromNameData extends AltosDataListener { + AltosGPS gps = null; + + public void set_rssi(int rssi, int status) { } + public void set_received_time(long received_time) { } + + public void set_acceleration(double accel) { } + public void set_pressure(double pa) { } + public void set_thrust(double N) { } + + public void set_temperature(double deg_c) { } + public void set_battery_voltage(double volts) { } + + public void set_apogee_voltage(double volts) { } + public void set_main_voltage(double volts) { } + + public void set_gps(AltosGPS gps) { + if (gps != null && + gps.year != AltosLib.MISSING && + gps.month != AltosLib.MISSING && + gps.day != AltosLib.MISSING) { + this.gps = gps; + } + } + + public boolean done() { + if (gps == null) + return false; + return true; + } + + public void set_gyro(double roll, double pitch, double yaw) { } + public void set_accel_ground(double along, double across, double through) { } + public void set_accel(double along, double across, double through) { } + public void set_mag(double along, double across, double through) { } + public void set_pyro_voltage(double volts) { } + public void set_ignitor_voltage(double[] voltage) { } + public void set_pyro_fired(int pyro_mask) { } + public void set_companion(AltosCompanion companion) { } + public void set_kalman(double height, double speed, double acceleration) { } + public void set_orient(double new_orient) { } + + public AltosEepromNameData(AltosCalData cal_data) { + super(cal_data); + } +} + public class AltosEepromDownload implements Runnable { AltosLink link; @@ -45,11 +92,11 @@ public class AltosEepromDownload implements Runnable { gps.day != AltosLib.MISSING; } - private AltosFile MakeFile(int serial, int flight, AltosState state) throws IOException { + private AltosFile MakeFile(int serial, int flight, AltosEepromNameData name_data) throws IOException { AltosFile eeprom_name; - if (has_gps_date(state)) { - AltosGPS gps = state.gps; + if (name_data.gps != null) { + AltosGPS gps = name_data.gps; eeprom_name = new AltosFile(gps.year, gps.month, gps.day, serial, flight, "eeprom"); } else @@ -141,17 +188,16 @@ public class AltosEepromDownload implements Runnable { * doesn't need to work; we'll still save the data using * a less accurate name. */ - AltosEepromRecordSet set = new AltosEepromRecordSet(eeprom); - - AltosState state = new AltosState(); + AltosEepromRecordSet set = new AltosEepromRecordSet(eeprom); + AltosEepromNameData name_data = new AltosEepromNameData(set.cal_data()); - for (AltosState s : set) { - state = s; - if (state.gps != null) + for (AltosEepromRecord record : set.ordered) { + record.provide_data(name_data, set.cal_data()); + if (name_data.done()) break; } - AltosFile f = MakeFile(flights.config_data.serial, log.flight, state); + AltosFile f = MakeFile(flights.config_data.serial, log.flight, name_data); monitor.set_filename(f.toString()); diff --git a/altoslib/AltosEepromFile.java b/altoslib/AltosEepromFile.java index 7f629913..df19877b 100644 --- a/altoslib/AltosEepromFile.java +++ b/altoslib/AltosEepromFile.java @@ -22,14 +22,10 @@ import java.io.*; import java.util.*; import java.text.*; -public class AltosEepromFile extends AltosStateIterable implements AltosRecordSet { +public class AltosEepromFile implements AltosRecordSet { AltosEepromRecordSet set; - public AltosConfigData config_data() { - return set.eeprom.config_data(); - } - public void write_comments(PrintStream out) { } @@ -41,11 +37,15 @@ public class AltosEepromFile extends AltosStateIterable implements AltosRecordSe set = new AltosEepromRecordSet(input); } - public Iterator iterator() { - return set.iterator(); + public AltosConfigData config_data() { + return set.config_data(); + } + + public AltosCalData cal_data() { + return set.cal_data(); } - public void capture_series(AltosFlightSeries series) { + public void capture_series(AltosDataListener series) { set.capture_series(series); } } diff --git a/altoslib/AltosEepromNew.java b/altoslib/AltosEepromNew.java index 4e3ee416..5220f3a0 100644 --- a/altoslib/AltosEepromNew.java +++ b/altoslib/AltosEepromNew.java @@ -70,10 +70,6 @@ public class AltosEepromNew { return config_data; } - public void reset_config_data() { - config_data = null; - } - private void write_config(Writer w) throws IOException { config.write(w, 0, true); w.append('\n'); diff --git a/altoslib/AltosEepromRecord.java b/altoslib/AltosEepromRecord.java index 1f6ade66..08f7ebca 100644 --- a/altoslib/AltosEepromRecord.java +++ b/altoslib/AltosEepromRecord.java @@ -81,11 +81,12 @@ public abstract class AltosEepromRecord implements Comparable return start - o.start; } - public void update_state(AltosFlightListener listen) { + /* AltosDataProvider */ + public void provide_data(AltosDataListener listener, AltosCalData cal_data) { + cal_data.set_tick(tick()); if (cmd() == AltosLib.AO_LOG_FLIGHT) - listen.set_boost_tick(tick()); - else - listen.set_tick(tick()); + cal_data.set_boost_tick(); + listener.set_time(cal_data.time()); } public int next_start() { diff --git a/altoslib/AltosEepromRecordFireTwo.java b/altoslib/AltosEepromRecordFireTwo.java index bfdd6cf8..713d0bb7 100644 --- a/altoslib/AltosEepromRecordFireTwo.java +++ b/altoslib/AltosEepromRecordFireTwo.java @@ -68,21 +68,19 @@ public class AltosEepromRecordFireTwo extends AltosEepromRecord { return AltosConvert.lb_to_n(v * 298 * 9.807); } - public void update_state(AltosFlightListener state) { - super.update_state(state); + public void provide_data(AltosDataListener listener, AltosCalData cal_data) { + super.provide_data(listener, cal_data); switch (cmd()) { case AltosLib.AO_LOG_FLIGHT: - state.set_flight(flight()); - state.set_ground_pressure(0.0); - state.set_accel_g(0, -1); + cal_data.set_flight(flight()); break; case AltosLib.AO_LOG_STATE: - state.set_state(state()); + listener.set_state(state()); break; case AltosLib.AO_LOG_SENSOR: - state.set_pressure(adc_to_pa(pres())); - state.set_thrust(adc_to_n(thrust())); + listener.set_pressure(adc_to_pa(pres())); + listener.set_thrust(adc_to_n(thrust())); break; } } diff --git a/altoslib/AltosEepromRecordFull.java b/altoslib/AltosEepromRecordFull.java index 0fdfa5e7..ea81eb3d 100644 --- a/altoslib/AltosEepromRecordFull.java +++ b/altoslib/AltosEepromRecordFull.java @@ -21,13 +21,13 @@ public class AltosEepromRecordFull extends AltosEepromRecord { public static final int two_g_default = 16294 - 15758; - public void update_state(AltosFlightListener state) { + public void provide_data(AltosDataListener listener, AltosCalData cal_data) { - super.update_state(state); + super.provide_data(listener, cal_data); AltosGPS gps; /* Flush any pending GPS changes */ - if (state.gps_pending()) { + if (cal_data.gps_pending()) { switch (cmd()) { case AltosLib.AO_LOG_GPS_LAT: case AltosLib.AO_LOG_GPS_LON: @@ -36,39 +36,40 @@ public class AltosEepromRecordFull extends AltosEepromRecord { case AltosLib.AO_LOG_GPS_DATE: break; default: - state.set_temp_gps(); + listener.set_gps(cal_data.temp_gps()); + cal_data.reset_temp_gps(); break; } } switch (cmd()) { case AltosLib.AO_LOG_FLIGHT: - state.set_state(AltosLib.ao_flight_pad); - state.set_ground_accel(data16(0)); - state.set_flight(data16(2)); - if (state.accel_plus_g == AltosLib.MISSING) - state.set_accel_g(data16(0), data16(0) + two_g_default); + listener.set_state(AltosLib.ao_flight_pad); + cal_data.set_ground_accel(data16(0)); + cal_data.set_flight(data16(2)); + if (cal_data.accel_plus_g == AltosLib.MISSING) + cal_data.set_accel_plus_minus(data16(0), data16(0) + two_g_default); break; case AltosLib.AO_LOG_SENSOR: - state.set_accel(data16(0)); - state.set_pressure(AltosConvert.barometer_to_pressure(data16(2))); + listener.set_acceleration(cal_data.acceleration(data16(0))); + listener.set_pressure(AltosConvert.barometer_to_pressure(data16(2))); break; case AltosLib.AO_LOG_PRESSURE: - state.set_pressure(AltosConvert.barometer_to_pressure(data16(2))); + listener.set_pressure(AltosConvert.barometer_to_pressure(data16(2))); break; case AltosLib.AO_LOG_TEMP_VOLT: - state.set_temperature(AltosConvert.thermometer_to_temperature(data16(0))); - state.set_battery_voltage(AltosConvert.cc_battery_to_voltage(data16(2))); + listener.set_temperature(AltosConvert.thermometer_to_temperature(data16(0))); + listener.set_battery_voltage(AltosConvert.cc_battery_to_voltage(data16(2))); break; case AltosLib.AO_LOG_DEPLOY: - state.set_apogee_voltage(AltosConvert.cc_ignitor_to_voltage(data16(0))); - state.set_main_voltage(AltosConvert.cc_ignitor_to_voltage(data16(2))); + listener.set_apogee_voltage(AltosConvert.cc_ignitor_to_voltage(data16(0))); + listener.set_main_voltage(AltosConvert.cc_ignitor_to_voltage(data16(2))); break; case AltosLib.AO_LOG_STATE: - state.set_state(data16(0)); + listener.set_state(data16(0)); break; case AltosLib.AO_LOG_GPS_TIME: - gps = state.make_temp_gps(false); + gps = cal_data.make_temp_gps(tick(),false); gps.hour = data8(0); gps.minute = data8(1); @@ -82,29 +83,29 @@ public class AltosEepromRecordFull extends AltosEepromRecord { AltosLib.AO_GPS_NUM_SAT_SHIFT; break; case AltosLib.AO_LOG_GPS_LAT: - gps = state.make_temp_gps(false); + gps = cal_data.make_temp_gps(tick(),false); int lat32 = data32(0); gps.lat = (double) lat32 / 1e7; break; case AltosLib.AO_LOG_GPS_LON: - gps = state.make_temp_gps(false); + gps = cal_data.make_temp_gps(tick(),false); int lon32 = data32(0); gps.lon = (double) lon32 / 1e7; break; case AltosLib.AO_LOG_GPS_ALT: - gps = state.make_temp_gps(false); + gps = cal_data.make_temp_gps(tick(),false); gps.alt = data16(0); break; case AltosLib.AO_LOG_GPS_SAT: - gps = state.make_temp_gps(true); + gps = cal_data.make_temp_gps(tick(),true); int svid = data16(0); int c_n0 = data16(3); gps.add_sat(svid, c_n0); break; case AltosLib.AO_LOG_GPS_DATE: - gps = state.make_temp_gps(false); + gps = cal_data.make_temp_gps(tick(),false); gps.year = data8(0) + 2000; gps.month = data8(1); gps.day = data8(2); diff --git a/altoslib/AltosEepromRecordGps.java b/altoslib/AltosEepromRecordGps.java index 4f30692e..a992abff 100644 --- a/altoslib/AltosEepromRecordGps.java +++ b/altoslib/AltosEepromRecordGps.java @@ -71,36 +71,19 @@ public class AltosEepromRecordGps extends AltosEepromRecord { return start - o.start; } - public void update_state(AltosFlightListener state) { - super.update_state(state); - - AltosGPS gps; - - /* Flush any pending RecordGps changes */ - if (state.gps_pending()) { - switch (cmd()) { - case AltosLib.AO_LOG_GPS_LAT: - case AltosLib.AO_LOG_GPS_LON: - case AltosLib.AO_LOG_GPS_ALT: - case AltosLib.AO_LOG_GPS_SAT: - case AltosLib.AO_LOG_GPS_DATE: - break; - default: - state.set_temp_gps(); - break; - } - } + public void provide_data(AltosDataListener listener, AltosCalData cal_data) { + super.provide_data(listener, cal_data); switch (cmd()) { case AltosLib.AO_LOG_FLIGHT: - if (state.flight() == AltosLib.MISSING) { - state.set_boost_tick(tick()); - state.set_flight(flight()); + if (cal_data.flight == AltosLib.MISSING) { + cal_data.set_boost_tick(); + cal_data.set_flight(flight()); } /* no place to log start lat/lon yet */ break; case AltosLib.AO_LOG_GPS_TIME: - gps = state.make_temp_gps(false); + AltosGPS gps = new AltosGPS(); gps.lat = latitude() / 1e7; gps.lon = longitude() / 1e7; if (eeprom.config_data().altitude_32 == 1) @@ -140,6 +123,7 @@ public class AltosEepromRecordGps extends AltosEepromRecord { if (gps.vdop < 0.8) gps.vdop += 2.56; } + listener.set_gps(gps); break; } } diff --git a/altoslib/AltosEepromRecordMega.java b/altoslib/AltosEepromRecordMega.java index 3c5f60b3..371810ab 100644 --- a/altoslib/AltosEepromRecordMega.java +++ b/altoslib/AltosEepromRecordMega.java @@ -109,12 +109,13 @@ public class AltosEepromRecordMega extends AltosEepromRecord { private int svid(int n) { return data8(2 + n * 2); } private int c_n(int n) { return data8(2 + n * 2 + 1); } - public void update_state(AltosFlightListener state) { - super.update_state(state); + public void provide_data(AltosDataListener listener, AltosCalData cal_data) { + super.provide_data(listener, cal_data); + AltosGPS gps; /* Flush any pending GPS changes */ - if (state.gps_pending()) { + if (cal_data.gps_pending()) { switch (cmd()) { case AltosLib.AO_LOG_GPS_LAT: case AltosLib.AO_LOG_GPS_LON: @@ -123,66 +124,85 @@ public class AltosEepromRecordMega extends AltosEepromRecord { case AltosLib.AO_LOG_GPS_DATE: break; default: - state.set_temp_gps(); + listener.set_gps(cal_data.temp_gps()); + cal_data.reset_temp_gps(); break; } } switch (cmd()) { case AltosLib.AO_LOG_FLIGHT: - state.set_flight(flight()); - state.set_ground_accel(ground_accel()); - state.set_ground_pressure(ground_pres()); - state.set_accel_ground(ground_accel_along(), - ground_accel_across(), - ground_accel_through()); - state.set_gyro_zero(ground_roll() / 512.0, - ground_pitch() / 512.0, - ground_yaw() / 512.0); + cal_data.set_flight(flight()); + cal_data.set_ground_accel(ground_accel()); + cal_data.set_ground_pressure(ground_pres()); + listener.set_accel_ground(ground_accel_along(), + ground_accel_across(), + ground_accel_through()); + cal_data.set_gyro_zero(ground_roll() / 512.0, + ground_pitch() / 512.0, + ground_yaw() / 512.0); break; case AltosLib.AO_LOG_STATE: - state.set_state(state()); + listener.set_state(state()); break; case AltosLib.AO_LOG_SENSOR: - state.set_ms5607(pres(), temp()); - - AltosIMU imu = new AltosIMU(accel_y(), /* along */ - accel_x(), /* across */ - accel_z(), /* through */ - gyro_y(), /* roll */ - gyro_x(), /* pitch */ - gyro_z()); /* yaw */ + AltosConfigData config_data = eeprom.config_data(); + AltosPresTemp pt = config_data.ms5607().pres_temp(pres(), temp());; + listener.set_pressure(pt.pres); + listener.set_temperature(pt.temp); + + int accel_along = accel_y(); + int accel_across = accel_x(); + int accel_through = accel_z(); + int gyro_roll = gyro_y(); + int gyro_pitch = gyro_x(); + int gyro_yaw = gyro_z(); + + int mag_along = mag_x(); + int mag_across = mag_y(); + int mag_through = mag_z(); if (log_format == AltosLib.AO_LOG_FORMAT_TELEMEGA_OLD) - state.check_imu_wrap(imu); + cal_data.check_imu_wrap(gyro_roll, gyro_pitch, gyro_yaw); + + listener.set_accel(cal_data.accel_along(accel_along), + cal_data.accel_across(accel_across), + cal_data.accel_through(accel_through)); + listener.set_gyro(cal_data.gyro_roll(gyro_roll), + cal_data.gyro_pitch(gyro_pitch), + cal_data.gyro_yaw(gyro_yaw)); - state.set_imu(imu); + listener.set_mag(cal_data.mag_along(mag_along), + cal_data.mag_across(mag_across), + cal_data.mag_through(mag_through)); - state.set_mag(new AltosMag(mag_x(), - mag_y(), - mag_z())); - state.set_accel(accel()); + double acceleration = AltosConvert.acceleration_from_sensor( + accel(), + config_data.accel_cal_plus, + config_data.accel_cal_minus, + AltosLib.MISSING); + listener.set_acceleration(acceleration); break; case AltosLib.AO_LOG_TEMP_VOLT: - state.set_battery_voltage(AltosConvert.mega_battery_voltage(v_batt())); - state.set_pyro_voltage(AltosConvert.mega_pyro_voltage(v_pbatt())); + listener.set_battery_voltage(AltosConvert.mega_battery_voltage(v_batt())); + listener.set_pyro_voltage(AltosConvert.mega_pyro_voltage(v_pbatt())); int nsense = nsense(); - state.set_apogee_voltage(AltosConvert.mega_pyro_voltage(sense(nsense-2))); - state.set_main_voltage(AltosConvert.mega_pyro_voltage(sense(nsense-1))); + listener.set_apogee_voltage(AltosConvert.mega_pyro_voltage(sense(nsense-2))); + listener.set_main_voltage(AltosConvert.mega_pyro_voltage(sense(nsense-1))); double voltages[] = new double[nsense-2]; for (int i = 0; i < nsense-2; i++) voltages[i] = AltosConvert.mega_pyro_voltage(sense(i)); - state.set_ignitor_voltage(voltages); - state.set_pyro_fired(pyro()); + listener.set_ignitor_voltage(voltages); + listener.set_pyro_fired(pyro()); break; case AltosLib.AO_LOG_GPS_TIME: - gps = state.make_temp_gps(false); + gps = cal_data.make_temp_gps(tick(), false); gps.lat = latitude() / 1e7; gps.lon = longitude() / 1e7; @@ -225,7 +245,7 @@ public class AltosEepromRecordMega extends AltosEepromRecord { } break; case AltosLib.AO_LOG_GPS_SAT: - gps = state.make_temp_gps(true); + gps = cal_data.make_temp_gps(tick(), true); int n = nsat(); if (n > max_sat) diff --git a/altoslib/AltosEepromRecordMetrum.java b/altoslib/AltosEepromRecordMetrum.java index 6d516ebb..97a1103d 100644 --- a/altoslib/AltosEepromRecordMetrum.java +++ b/altoslib/AltosEepromRecordMetrum.java @@ -65,13 +65,13 @@ public class AltosEepromRecordMetrum extends AltosEepromRecord { public int svid(int n) { return data8(2 + n * 2); } public int c_n(int n) { return data8(2 + n * 2 + 1); } - public void update_state(AltosFlightListener state) { - super.update_state(state); + public void provide_data(AltosDataListener listener, AltosCalData cal_data) { + super.provide_data(listener, cal_data); AltosGPS gps; /* Flush any pending GPS changes */ - if (state.gps_pending()) { + if (cal_data.gps_pending()) { switch (cmd()) { case AltosLib.AO_LOG_GPS_POS: case AltosLib.AO_LOG_GPS_LAT: @@ -81,34 +81,34 @@ public class AltosEepromRecordMetrum extends AltosEepromRecord { case AltosLib.AO_LOG_GPS_DATE: break; default: - state.set_temp_gps(); + listener.set_gps(cal_data.temp_gps()); + cal_data.reset_temp_gps(); break; } } switch (cmd()) { case AltosLib.AO_LOG_FLIGHT: - state.set_flight(flight()); - state.set_ground_accel(ground_accel()); - state.set_ground_pressure(ground_pres()); + cal_data.set_flight(flight()); + cal_data.set_ground_accel(ground_accel()); + cal_data.set_ground_pressure(ground_pres()); break; case AltosLib.AO_LOG_STATE: - state.set_state(state()); + listener.set_state(state()); break; case AltosLib.AO_LOG_SENSOR: - state.set_ms5607(pres(), temp()); - state.set_accel(accel()); - + AltosPresTemp pt = eeprom.config_data().ms5607().pres_temp(pres(), temp()); + listener.set_pressure(pt.pres); + listener.set_temperature(pt.temp); + listener.set_acceleration(cal_data.acceleration(accel())); break; case AltosLib.AO_LOG_TEMP_VOLT: - state.set_battery_voltage(AltosConvert.mega_battery_voltage(v_batt())); - - state.set_apogee_voltage(AltosConvert.mega_pyro_voltage(sense_a())); - state.set_main_voltage(AltosConvert.mega_pyro_voltage(sense_m())); - + listener.set_battery_voltage(AltosConvert.mega_battery_voltage(v_batt())); + listener.set_apogee_voltage(AltosConvert.mega_pyro_voltage(sense_a())); + listener.set_main_voltage(AltosConvert.mega_pyro_voltage(sense_m())); break; case AltosLib.AO_LOG_GPS_POS: - gps = state.make_temp_gps(false); + gps = cal_data.make_temp_gps(tick(), false); gps.lat = latitude() / 1e7; gps.lon = longitude() / 1e7; if (config_data().altitude_32()) @@ -117,7 +117,7 @@ public class AltosEepromRecordMetrum extends AltosEepromRecord { gps.alt = altitude_low(); break; case AltosLib.AO_LOG_GPS_TIME: - gps = state.make_temp_gps(false); + gps = cal_data.make_temp_gps(tick(), false); gps.hour = hour(); gps.minute = minute(); @@ -136,7 +136,7 @@ public class AltosEepromRecordMetrum extends AltosEepromRecord { gps.pdop = pdop() / 10.0; break; case AltosLib.AO_LOG_GPS_SAT: - gps = state.make_temp_gps(true); + gps = cal_data.make_temp_gps(tick(), true); int n = nsat(); for (int i = 0; i < n; i++) diff --git a/altoslib/AltosEepromRecordMini.java b/altoslib/AltosEepromRecordMini.java index dedf4bda..4b3a564e 100644 --- a/altoslib/AltosEepromRecordMini.java +++ b/altoslib/AltosEepromRecordMini.java @@ -62,22 +62,24 @@ public class AltosEepromRecordMini extends AltosEepromRecord { return -1; } - public void update_state(AltosFlightListener state) { - super.update_state(state); + public void provide_data(AltosDataListener listener, AltosCalData cal_data) { + super.provide_data(listener, cal_data); switch (cmd()) { case AltosLib.AO_LOG_FLIGHT: - state.set_flight(flight()); - state.set_ground_pressure(ground_pres()); + cal_data.set_flight(flight()); + cal_data.set_ground_pressure(ground_pres()); break; case AltosLib.AO_LOG_STATE: - state.set_state(state()); + listener.set_state(state()); break; case AltosLib.AO_LOG_SENSOR: - state.set_ms5607(pres(), temp()); - state.set_apogee_voltage(pyro_voltage(sense_a())); - state.set_main_voltage(pyro_voltage(sense_m())); - state.set_battery_voltage(battery_voltage(v_batt())); + AltosPresTemp pt = eeprom.config_data().ms5607().pres_temp(pres(), temp()); + listener.set_pressure(pt.pres); + listener.set_temperature(pt.temp); + listener.set_apogee_voltage(pyro_voltage(sense_a())); + listener.set_main_voltage(pyro_voltage(sense_m())); + listener.set_battery_voltage(battery_voltage(v_batt())); break; } } diff --git a/altoslib/AltosEepromRecordSet.java b/altoslib/AltosEepromRecordSet.java index 653a1305..69159cdf 100644 --- a/altoslib/AltosEepromRecordSet.java +++ b/altoslib/AltosEepromRecordSet.java @@ -17,45 +17,32 @@ package org.altusmetrum.altoslib_11; import java.io.*; import java.util.*; -public class AltosEepromRecordSet implements Iterable, AltosRecordSet { +public class AltosEepromRecordSet implements AltosRecordSet { AltosEepromNew eeprom; TreeSet ordered; - AltosState start_state; + AltosCalData cal_data; - class RecordIterator implements Iterator { - Iterator riterator; - AltosState state; - boolean started; - - public boolean hasNext() { - return state == null || riterator.hasNext(); - } + public AltosConfigData config_data() { + return eeprom.config_data(); + } - public AltosState next() { - if (state == null) - state = start_state.clone(); - else { - state = state.clone(); - AltosEepromRecord r = riterator.next(); - r.update_state(state); + public AltosCalData cal_data() { + if (cal_data == null) { + cal_data = new AltosCalData(config_data()); + for (AltosEepromRecord record : ordered) { + if (record.cmd() == AltosLib.AO_LOG_FLIGHT) { + cal_data.set_tick(record.tick()); + cal_data.set_boost_tick(); + } } - return state; - } - - public RecordIterator() { - riterator = ordered.iterator(); - state = null; } + return cal_data; } - public Iterator iterator() { - return new RecordIterator(); - } - - public void capture_series(AltosFlightSeries series) { - series.set_config_data(eeprom.config_data()); + public void capture_series(AltosDataListener listener) { + AltosCalData cal_data = cal_data(); for (AltosEepromRecord record : ordered) { - record.update_state(series); + record.provide_data(listener, cal_data); } } @@ -103,9 +90,6 @@ public class AltosEepromRecordSet implements Iterable, AltosRecordSe int tick = 0; boolean first = true; - start_state = new AltosState(); - start_state.set_config_data(record.eeprom.config_data()); - for (;;) { int t = record.tick(); diff --git a/altoslib/AltosEepromRecordTiny.java b/altoslib/AltosEepromRecordTiny.java index e70f8cdc..705fbd9e 100644 --- a/altoslib/AltosEepromRecordTiny.java +++ b/altoslib/AltosEepromRecordTiny.java @@ -14,7 +14,7 @@ package org.altusmetrum.altoslib_11; -public class AltosEepromRecordTiny extends AltosEepromRecord { +public class AltosEepromRecordTiny extends AltosEepromRecord implements AltosDataProvider { public static final int record_length = 2; private int value() { @@ -50,21 +50,21 @@ public class AltosEepromRecordTiny extends AltosEepromRecord { return tick; } - public void update_state(AltosFlightListener state) { + public void provide_data(AltosDataListener listener, AltosCalData cal_data) { int value = data16(-header_length); - state.set_tick(tick()); + cal_data.set_tick(tick()); switch (cmd()) { case AltosLib.AO_LOG_FLIGHT: - state.set_state(AltosLib.ao_flight_pad); - state.set_flight(value); - state.set_boost_tick(0); + listener.set_state(AltosLib.ao_flight_pad); + cal_data.set_flight(value); + cal_data.set_boost_tick(); break; case AltosLib.AO_LOG_STATE: - state.set_state(value & 0x7fff); + listener.set_state(value & 0x7fff); break; case AltosLib.AO_LOG_SENSOR: - state.set_pressure(AltosConvert.barometer_to_pressure(value)); + listener.set_pressure(AltosConvert.barometer_to_pressure(value)); break; } } diff --git a/altoslib/AltosFile.java b/altoslib/AltosFile.java index ef75762a..691e70b4 100644 --- a/altoslib/AltosFile.java +++ b/altoslib/AltosFile.java @@ -66,7 +66,7 @@ public class AltosFile extends File { extension); } - public AltosFile(AltosState state) { - this(state.serial, state.flight, state.receiver_serial, "telem"); + public AltosFile(AltosCalData cal_data) { + this(cal_data.serial, cal_data.flight, cal_data.receiver_serial, "telem"); } } diff --git a/altoslib/AltosFlightListener.java b/altoslib/AltosFlightListener.java index f7705165..5b478ed0 100644 --- a/altoslib/AltosFlightListener.java +++ b/altoslib/AltosFlightListener.java @@ -16,13 +16,22 @@ package org.altusmetrum.altoslib_11; public abstract class AltosFlightListener { - int flight; + public int flight; + public int serial; + public int tick; + public int boost_tick; + public int state; - public int tick; - int boost_tick; + public double accel_plus_g; + public double accel_minus_g; + public double accel; - AltosGPS temp_gps; - int temp_gps_sat_tick; + public double ground_pressure; + public double ground_altitude; + + AltosGPS temp_gps; + int temp_gps_sat_tick; + int gps_sequence; /* AltosEepromRecord */ public void set_boost_tick(int boost_tick) { @@ -38,7 +47,10 @@ public abstract class AltosFlightListener { public double time() { if (tick == AltosLib.MISSING) return AltosLib.MISSING; - return tick / 100.0; + if (boost_tick != AltosLib.MISSING) + return (tick - boost_tick) / 100.0; + else + return tick / 100.0; } public double boost_time() { @@ -47,9 +59,23 @@ public abstract class AltosFlightListener { return boost_tick / 100.0; } + public abstract void set_rssi(int rssi, int status); + public abstract void set_received_time(long received_time); + /* AltosEepromRecordFull */ - public abstract void set_state(int state); + public void set_serial(int serial) { + if (serial != AltosLib.MISSING) + this.serial = serial; + } + + public void set_state(int state) { + if (state != AltosLib.MISSING) + this.state = state; + } + + public int state() { return state; } + public abstract void set_ground_accel(double ground_accel); public void set_flight(int flight) { if (flight != AltosLib.MISSING) @@ -60,6 +86,7 @@ public abstract class AltosFlightListener { } public abstract void set_accel(double accel); + public abstract void set_acceleration(double accel); public abstract void set_accel_g(double accel_plus_g, double accel_minus_g); public abstract void set_pressure(double pa); public abstract void set_thrust(double N); @@ -90,10 +117,15 @@ public abstract class AltosFlightListener { return temp_gps; } - public abstract void set_ground_pressure(double ground_pressure); + public void set_ground_pressure(double ground_pressure) { + if (ground_pressure != AltosLib.MISSING) { + this.ground_pressure = ground_pressure; + this.ground_altitude = AltosConvert.pressure_to_altitude(ground_pressure); + } + } + public abstract void set_accel_ground(double along, double across, double through); public abstract void set_gyro_zero(double roll, double pitch, double yaw); - public abstract void set_ms5607(int pres_val, int temp_val); public abstract void check_imu_wrap(AltosIMU imu); public abstract void set_imu(AltosIMU imu); public abstract void set_mag(AltosMag mag); @@ -103,16 +135,28 @@ public abstract class AltosFlightListener { public void copy(AltosFlightListener old) { flight = old.flight; + serial = old.serial; tick = old.tick; boost_tick = old.boost_tick; + accel_plus_g = old.accel_plus_g; + accel_minus_g = old.accel_minus_g; + ground_pressure = old.ground_pressure; + ground_altitude = old.ground_altitude; temp_gps = old.temp_gps; temp_gps_sat_tick = old.temp_gps_sat_tick; } public void init() { flight = AltosLib.MISSING; + serial = AltosLib.MISSING; tick = AltosLib.MISSING; boost_tick = AltosLib.MISSING; + accel_plus_g = AltosLib.MISSING; + accel_minus_g = AltosLib.MISSING; + accel = AltosLib.MISSING; + ground_pressure = AltosLib.MISSING; + ground_altitude = AltosLib.MISSING; + temp_gps = null; temp_gps_sat_tick = AltosLib.MISSING; } } diff --git a/altoslib/AltosFlightSeries.java b/altoslib/AltosFlightSeries.java index 0e260fb4..b7434a5c 100644 --- a/altoslib/AltosFlightSeries.java +++ b/altoslib/AltosFlightSeries.java @@ -16,124 +16,261 @@ package org.altusmetrum.altoslib_11; import java.util.*; -public class AltosFlightSeries extends AltosFlightListener { +public class AltosFlightSeries extends AltosDataListener { - int flight; + public ArrayList series; - int tick; - int boost_tick; + public int[] indices() { + int[] indices = new int[series.size()]; + for (int i = 0; i < indices.length; i++) + indices[i] = 0; + return indices; + } - AltosGPS temp_gps; - int temp_gps_sat_tick; + private double time(int id, int index) { + AltosTimeSeries s = series.get(id); + if (index < s.values.size()) + return s.values.get(index).time; + return Double.POSITIVE_INFINITY; + } - AltosMs5607 ms5607; + public boolean step_indices(int[] indices) { + double min_next = time(0, indices[0]+1); - public ArrayList series; + for (int i = 1; i < indices.length; i++) { + double next = time(i, indices[i]+1); + if (next < min_next) + min_next = next; + } - /* AltosEepromRecord */ - public void set_boost_tick(int boost_tick) { - if (boost_tick != AltosLib.MISSING) - this.boost_tick = boost_tick; - } + if (min_next == Double.POSITIVE_INFINITY) + return false; - public void set_tick(int tick) { - if (tick != AltosLib.MISSING) - this.tick = tick; + for (int i = 0; i < indices.length; i++) { + double t = time(i, indices[i] + 1); + + if (t <= min_next) + indices[i]++; + } + return true; } - public double time() { - if (tick == AltosLib.MISSING) - return AltosLib.MISSING; - return tick / 100.0; + public double time(int[] indices) { + double max = time(0, indices[0]); + + for (int i = 1; i < indices.length; i++) { + double t = time(i, indices[i]); + if (t >= max) + max = t; + } + return max; } - public double boost_time() { - if (boost_tick == AltosLib.MISSING) - return AltosLib.MISSING; - return boost_tick / 100.0; + public double value(String name, int[] indices) { + for (int i = 0; i < indices.length; i++) { + AltosTimeSeries s = series.get(i); + if (s.label.equals(name)) + return s.values.get(indices[i]).value; + } + return AltosLib.MISSING; } public AltosTimeSeries make_series(String label, AltosUnits units) { return new AltosTimeSeries(label, units); } + public void add_series(AltosTimeSeries s) { + series.add(s); + } + public AltosTimeSeries add_series(String label, AltosUnits units) { - System.out.printf("add series %s\n", label); AltosTimeSeries s = make_series(label, units); - series.add(s); + add_series(s); return s; } - /* AltosEepromRecordFull */ + public void remove_series(AltosTimeSeries s) { + series.remove(s); + } + + public boolean has_series(String label) { + for (AltosTimeSeries s : series) + if (s.label.equals(label)) + return true; + return false; + } AltosTimeSeries state_series; public static final String state_name = "State"; public void set_state(int state) { + this.state = state; if (state_series == null) - state_series = add_series(state_name, null); + state_series = add_series(state_name, AltosConvert.state_name); + else if ((int) state_series.get(state_series.size()-1).value == state) + return; state_series.add(time(), state); } - public void set_flight(int flight) { - if (flight != AltosLib.MISSING) - this.flight = flight; - } - public int flight() { - return flight; - } - AltosTimeSeries accel_series; - double accel_plus_g, accel_minus_g; - public static final String accel_name = "Accel"; - public void set_accel(double accel) { - if (accel_series == null) + public void set_acceleration(double acceleration) { + if (accel_series == null) { + System.out.printf("set acceleration %g\n", acceleration); accel_series = add_series(accel_name, AltosConvert.accel); - double counts_per_g = (accel_minus_g - accel_plus_g) / 2.0; - double counts_per_mss = counts_per_g / 9.80665; - double mss = (accel_plus_g - accel) / counts_per_mss; - - accel_series.add(time(), mss); + } + accel_series.add(time(), acceleration); } + private void compute_accel() { + if (accel_series != null) + return; - public void set_accel_g(double accel_plus_g, double accel_minus_g) { - this.accel_plus_g = accel_plus_g; - this.accel_minus_g = accel_minus_g; + if (speed_series != null) { + AltosTimeSeries temp_series = make_series(accel_name, AltosConvert.accel); + speed_series.differentiate(temp_series); + accel_series = add_series(accel_name, AltosConvert.accel); + temp_series.filter(accel_series, 0.25); + } } - public void set_config_data(AltosConfigData config_data) { -// if (config_data.callsign != null) -// set_callsign(config_data.callsign); - if (config_data.accel_cal_plus != AltosLib.MISSING && - config_data.accel_cal_minus != AltosLib.MISSING) - set_accel_g(config_data.accel_cal_plus, config_data.accel_cal_minus); -// if (config_data.product != null) -// set_product(config_data.product); -// if (config_data.log_format != AltosLib.MISSING) -// set_log_format(config_data.log_format); -// if (config_data.serial != AltosLib.MISSING) -// set_serial(config_data.serial); - AltosMs5607 ms5607 = new AltosMs5607(config_data); - if (ms5607.valid_config()) - this.ms5607 = ms5607; + public void set_received_time(long received_time) { } - public void set_ground_accel(double ground_accel) { + AltosTimeSeries rssi_series; + + public static final String rssi_name = "RSSI"; + + AltosTimeSeries status_series; + + public static final String status_name = "Status"; + + public void set_rssi(int rssi, int status) { + if (rssi_series == null) + rssi_series = add_series(rssi_name, null); + rssi_series.add(time(), rssi); + if (status_series == null) + status_series = add_series(status_name, null); + status_series.add(time(), status); } AltosTimeSeries pressure_series; public static final String pressure_name = "Pressure"; + AltosTimeSeries altitude_series; + + public static final String altitude_name = "Altitude"; + + AltosTimeSeries height_series; + + public static final String height_name = "Height"; + public void set_pressure(double pa) { if (pressure_series == null) pressure_series = add_series(pressure_name, AltosConvert.pressure); pressure_series.add(time(), pa); + if (altitude_series == null) + altitude_series = add_series(altitude_name, AltosConvert.height); + + double altitude = AltosConvert.pressure_to_altitude(pa); + altitude_series.add(time(), altitude); + } + + private void compute_height(double ground_altitude) { + if (height_series == null) { + height_series = add_series(height_name, AltosConvert.height); + for (AltosTimeValue alt : altitude_series) + height_series.add(alt.time, alt.value - ground_altitude); + } + } + + AltosTimeSeries speed_series; + + public static final String speed_name = "Speed"; + + private void compute_speed() { + if (speed_series != null) { + System.out.printf("speed series already made\n"); + return; + } + + AltosTimeSeries alt_speed_series = null; + AltosTimeSeries accel_speed_series = null; + + if (altitude_series != null) { + AltosTimeSeries temp_series = make_series(speed_name, AltosConvert.speed); + altitude_series.differentiate(temp_series); + + alt_speed_series = make_series(speed_name, AltosConvert.speed); + temp_series.filter(alt_speed_series, 10.0); + } else { + System.out.printf("no altitude series\n"); + } + if (accel_series != null) { + AltosTimeSeries temp_series = make_series(speed_name, AltosConvert.speed); + accel_series.integrate(temp_series); + + accel_speed_series = make_series(speed_name, AltosConvert.speed); + temp_series.filter(accel_speed_series, 0.1); + } else { + System.out.printf("no accel series\n"); + } + + if (alt_speed_series != null && accel_speed_series != null) { + double apogee_time = AltosLib.MISSING; + if (state_series != null) { + for (AltosTimeValue d : state_series) { + if (d.value >= AltosLib.ao_flight_drogue){ + apogee_time = d.time; + break; + } + } + } + if (apogee_time == AltosLib.MISSING) { + speed_series = alt_speed_series; + } else { + speed_series = make_series(speed_name, AltosConvert.speed); + for (AltosTimeValue d : accel_speed_series) { + if (d.time <= apogee_time) + speed_series.add(d); + } + for (AltosTimeValue d : alt_speed_series) { + if (d.time > apogee_time) + speed_series.add(d); + } + + } + } else if (alt_speed_series != null) { + speed_series = alt_speed_series; + } else if (accel_speed_series != null) { + speed_series = accel_speed_series; + } + if (speed_series != null) { + add_series(speed_series); + System.out.printf("speed series for %s set to %s\n", this.toString(), speed_series.toString()); + } else + System.out.printf("didn't manage to make speed series\n"); + } + + AltosTimeSeries kalman_height_series, kalman_speed_series, kalman_accel_series; + + public static final String kalman_height_name = "Kalman Height"; + public static final String kalman_speed_name = "Kalman Speed"; + public static final String kalman_accel_name = "Kalman Accel"; + + public void set_kalman(double height, double speed, double acceleration) { + if (kalman_height_series == null) { + kalman_height_series = add_series(kalman_height_name, AltosConvert.height); + kalman_speed_series = add_series(kalman_speed_name, AltosConvert.speed); + kalman_accel_series = add_series(kalman_accel_name, AltosConvert.accel); + } + kalman_height_series.add(time(), height); + kalman_speed_series.add(time(), speed); + kalman_accel_series.add(time(), acceleration); } AltosTimeSeries thrust_series; @@ -146,114 +283,159 @@ public class AltosFlightSeries extends AltosFlightListener { thrust_series.add(time(), N); } + AltosTimeSeries temperature_series; + + public static final String temperature_name = "Temperature"; + public void set_temperature(double deg_c) { + if (temperature_series == null) + temperature_series = add_series(temperature_name, AltosConvert.temperature); + temperature_series.add(time(), deg_c); } - public void set_battery_voltage(double volts) { + AltosTimeSeries battery_voltage_series; + + public static final String battery_voltage_name = "Battery Voltage"; + + public void set_battery_voltage(double volts) { + if (volts == AltosLib.MISSING) + return; + if (battery_voltage_series == null) + battery_voltage_series = add_series(battery_voltage_name, AltosConvert.voltage); + battery_voltage_series.add(time(), volts); } - public void set_apogee_voltage(double volts) { + AltosTimeSeries apogee_voltage_series; + + public static final String apogee_voltage_name = "Apogee Voltage"; + + public void set_apogee_voltage(double volts) { + if (volts == AltosLib.MISSING) + return; + if (apogee_voltage_series == null) + apogee_voltage_series = add_series(apogee_voltage_name, AltosConvert.voltage); + apogee_voltage_series.add(time(), volts); } - public void set_main_voltage(double volts) { + AltosTimeSeries main_voltage_series; + + public static final String main_voltage_name = "Main Voltage"; + + public void set_main_voltage(double volts) { + if (volts == AltosLib.MISSING) + return; + if (main_voltage_series == null) + main_voltage_series = add_series(main_voltage_name, AltosConvert.voltage); + main_voltage_series.add(time(), volts); } AltosTimeSeries sats_in_view; AltosTimeSeries sats_in_soln; AltosTimeSeries gps_altitude; + AltosTimeSeries gps_height; AltosTimeSeries gps_ground_speed; AltosTimeSeries gps_ascent_rate; AltosTimeSeries gps_course; AltosTimeSeries gps_speed; + public ArrayList gps_series; + public static final String sats_in_view_name = "Satellites in view"; public static final String sats_in_soln_name = "Satellites in solution"; public static final String gps_altitude_name = "GPS Altitude"; + public static final String gps_height_name = "GPS Height"; + public static final String gps_ground_speed_name = "GPS Ground Speed"; + public static final String gps_ascent_rate_name = "GPS Ascent Rate"; + public static final String gps_course_name = "GPS Course"; + public static final String gps_speed_name = "GPS Speed"; - public void set_temp_gps() { - if (sats_in_view == null) { - sats_in_view = add_series("Satellites in view", null); - sats_in_soln = add_series("Satellites in solution", null); - gps_altitude = add_series("GPS Altitude", AltosConvert.height); - gps_ground_speed = add_series("GPS Ground Speed", AltosConvert.speed); - gps_ascent_rate = add_series("GPS Ascent Rate", AltosConvert.speed); - gps_course = add_series("GPS Course", null); - gps_speed = add_series("GPS Speed", null); - } - - /* XXX capture GPS data */ - super.set_temp_gps(); - } - - public boolean gps_pending() { - return temp_gps != null; - } + public void set_gps(AltosGPS gps) { + if (gps_series == null) + gps_series = new ArrayList(); + gps_series.add(new AltosGPSTimeValue(time(), gps)); - public AltosGPS make_temp_gps(boolean sats) { - if (temp_gps == null) { - temp_gps = new AltosGPS(); + if (sats_in_view == null) { + sats_in_view = add_series(sats_in_view_name, null); + sats_in_soln = add_series(sats_in_soln_name, null); + gps_altitude = add_series(gps_altitude_name, AltosConvert.height); + gps_height = add_series(gps_height_name, AltosConvert.height); + gps_ground_speed = add_series(gps_ground_speed_name, AltosConvert.speed); + gps_ascent_rate = add_series(gps_ascent_rate_name, AltosConvert.speed); + gps_course = add_series(gps_course_name, null); + gps_speed = add_series(gps_speed_name, null); } - if (sats) { - if (tick != temp_gps_sat_tick) - temp_gps.cc_gps_sat = null; - temp_gps_sat_tick = tick; + if (gps.cc_gps_sat != null) + sats_in_view.add(time(), gps.cc_gps_sat.length); + if (gps.locked) { + sats_in_soln.add(time(), gps.nsat); + if (gps.alt != AltosLib.MISSING) { + gps_altitude.add(time(), gps.alt); + if (cal_data.gps_ground_altitude != AltosLib.MISSING) + gps_height.add(time(), gps.alt - cal_data.gps_ground_altitude); + } + if (gps.ground_speed != AltosLib.MISSING) + gps_ground_speed.add(time(), gps.ground_speed); + if (gps.climb_rate != AltosLib.MISSING) + gps_ascent_rate.add(time(), gps.climb_rate); + if (gps.course != AltosLib.MISSING) + gps_course.add(time(), gps.course); + if (gps.ground_speed != AltosLib.MISSING && gps.climb_rate != AltosLib.MISSING) + gps_speed.add(time(), Math.sqrt(gps.ground_speed * gps.ground_speed + + gps.climb_rate * gps.climb_rate)); } - return temp_gps; } - public void set_ground_pressure(double ground_pressure) { + public static final String accel_across_name = "Accel Across"; + public static final String accel_along_name = "Accel Along"; + public static final String accel_through_name = "Accel Through"; + + public void set_accel(double along, double across, double through) { } public void set_accel_ground(double along, double across, double through) { } - public void set_gyro_zero(double roll, double pitch, double yaw) { + public void set_gyro(double roll, double pitch, double yaw) { } - public void set_ms5607(int pres_val, int temp_val) { - if (ms5607 != null) { - ms5607.set(pres_val, temp_val); - - set_pressure(ms5607.pa); - set_temperature(ms5607.cc / 100.0); - } + public void set_mag(double along, double across, double through) { } - public void check_imu_wrap(AltosIMU imu) { - } + public void set_orient(double new_orient) { } - public void set_imu(AltosIMU imu) { + public void set_pyro_voltage(double volts) { } - public void set_mag(AltosMag mag) { + public void set_ignitor_voltage(double[] voltage) { } - public void set_pyro_voltage(double volts) { + public void set_pyro_fired(int pyro_mask) { } - public void set_ignitor_voltage(double[] voltage) { + public void set_companion(AltosCompanion companion) { } - public void set_pyro_fired(int pyro_mask) { + public void fill_in() { + System.out.printf("fill in %s\n", this.toString()); + compute_speed(); + compute_accel(); + if (cal_data.ground_altitude != AltosLib.MISSING) + compute_height(cal_data.ground_altitude); } public void init() { - flight = AltosLib.MISSING; - tick = AltosLib.MISSING; - boost_tick = AltosLib.MISSING; - temp_gps_sat_tick = AltosLib.MISSING; + time = AltosLib.MISSING; series = new ArrayList(); } - public void copy(AltosFlightSeries old) { - super.copy(old); - } - public AltosTimeSeries[] series() { + fill_in(); return series.toArray(new AltosTimeSeries[0]); } - public AltosFlightSeries() { + public AltosFlightSeries(AltosCalData cal_data) { + super(cal_data); + System.out.printf("new flight series %s\n", this.toString()); init(); } } diff --git a/altoslib/AltosFlightStats.java b/altoslib/AltosFlightStats.java index 98f13dac..7179351e 100644 --- a/altoslib/AltosFlightStats.java +++ b/altoslib/AltosFlightStats.java @@ -48,63 +48,74 @@ public class AltosFlightStats { public boolean has_orient; public int num_ignitor; - double landed_time(AltosStateIterable states) { - AltosState state = null; + double landed_time(AltosFlightSeries series) { + double landed_state_time = AltosLib.MISSING; - for (AltosState s : states) { - state = s; - if (state.state() == AltosLib.ao_flight_landed) + for (AltosTimeValue state : series.state_series) { + if (state.value == AltosLib.ao_flight_landed) { + landed_state_time = state.time; break; + } } - if (state == null) + if (landed_state_time == AltosLib.MISSING) return AltosLib.MISSING; - double landed_height = state.height(); + double landed_height = AltosLib.MISSING; + for (AltosTimeValue height : series.height_series) { + if (height.time >= landed_state_time) { + landed_height = height.value; + break; + } + } - state = null; + if (landed_height == AltosLib.MISSING) + return AltosLib.MISSING; boolean above = true; double landed_time = AltosLib.MISSING; - for (AltosState s : states) { - state = s; - - if (state.height() > landed_height + 10) { + for (AltosTimeValue height : series.height_series) { + if (height.value > landed_height + 10) { above = true; } else { - if (above && Math.abs(state.height() - landed_height) < 2) { + if (above && Math.abs(height.value - landed_height) < 2) { above = false; - landed_time = state.time; + landed_time = height.time; } } } return landed_time; } - double boost_time(AltosStateIterable states) { - double boost_time = AltosLib.MISSING; - AltosState state = null; + double boost_time(AltosFlightSeries series) { + double boost_time = AltosLib.MISSING; + double boost_state_time = AltosLib.MISSING; - for (AltosState s : states) { - state = s; - if (state.acceleration() < 1) - boost_time = state.time; - if (state.state() >= AltosLib.ao_flight_boost && state.state() <= AltosLib.ao_flight_landed) + for (AltosTimeValue state : series.state_series) { + if (state.value >= AltosLib.ao_flight_boost && state.value <= AltosLib.ao_flight_landed) { + boost_state_time = state.time; + break; + } + } + for (AltosTimeValue accel : series.accel_series) { + if (accel.value < 1) + boost_time = accel.time; + if (boost_state_time != AltosLib.MISSING && accel.time >= boost_state_time) break; } - if (state == null) - return AltosLib.MISSING; - return boost_time; } - public AltosFlightStats(AltosStateIterable states) throws InterruptedException, IOException { - double boost_time = boost_time(states); + public AltosFlightStats(AltosFlightSeries series) throws InterruptedException, IOException { + AltosCalData cal_data = series.cal_data; + double boost_time = boost_time(series); double end_time = 0; - double landed_time = landed_time(states); + double landed_time = landed_time(series); + + System.out.printf("flight stats %s\n", series.toString()); year = month = day = AltosLib.MISSING; hour = minute = second = AltosLib.MISSING; @@ -126,22 +137,44 @@ public class AltosFlightStats { state_accel[s] = 0.0; } + serial = cal_data.serial; + flight = cal_data.flight; + + has_battery = series.battery_voltage_series != null; + has_flight_adc = series.main_voltage_series != null; + has_rssi = series.rssi_series != null; + has_flight_data = series.pressure_series != null; + + if (series.gps_series != null) { + AltosGPS gps = series.gps_series.get(0).gps; + + year = gps.year; + month = gps.month; + day = gps.day; + hour = gps.hour; + minute = gps.minute; + second = gps.second; + } + + max_height = AltosLib.MISSING; + if (series.height_series != null) + max_height = series.height_series.max(); + max_speed = AltosLib.MISSING; + if (series.speed_series != null) + max_speed = series.speed_series.max(); + else + System.out.printf("missing speed series\n"); + max_acceleration = AltosLib.MISSING; + if (series.accel_series != null) + max_acceleration = series.accel_series.max(); + max_gps_height = AltosLib.MISSING; + if (series.gps_height != null) + max_gps_height = series.gps_height.max(); + +/* for (AltosState state : states) { - if (serial == AltosLib.MISSING && state.serial != AltosLib.MISSING) - serial = state.serial; - if (flight == AltosLib.MISSING && state.flight != AltosLib.MISSING) - flight = state.flight; - if (state.battery_voltage != AltosLib.MISSING) - has_battery = true; - if (state.main_voltage != AltosLib.MISSING) - has_flight_adc = true; - if (state.rssi != AltosLib.MISSING) - has_rssi = true; end_time = state.time; - if (state.pressure() != AltosLib.MISSING) - has_flight_data = true; - int state_id = state.state(); if (boost_time != AltosLib.MISSING && state.time >= boost_time && state_id < AltosLib.ao_flight_boost) { state_id = AltosLib.ao_flight_boost; @@ -150,19 +183,6 @@ public class AltosFlightStats { state_id = AltosLib.ao_flight_landed; } - if (state.gps != null && state.gps.locked) { - year = state.gps.year; - month = state.gps.month; - day = state.gps.day; - hour = state.gps.hour; - minute = state.gps.minute; - second = state.gps.second; - } - max_height = state.max_height(); - max_speed = state.max_speed(); - max_acceleration = state.max_acceleration(); - max_gps_height = state.max_gps_height(); - if (0 <= state_id && state_id < AltosLib.ao_flight_invalid) { double acceleration = state.acceleration(); double speed = state.speed(); @@ -198,6 +218,7 @@ public class AltosFlightStats { if (state.ignitor_voltage != null && state.ignitor_voltage.length > num_ignitor) num_ignitor = state.ignitor_voltage.length; } +*/ for (int s = AltosLib.ao_flight_startup; s <= AltosLib.ao_flight_landed; s++) { if (state_count[s] > 0) { state_speed[s] /= state_count[s]; diff --git a/altoslib/AltosGPS.java b/altoslib/AltosGPS.java index 0b30ed45..a730957b 100644 --- a/altoslib/AltosGPS.java +++ b/altoslib/AltosGPS.java @@ -383,17 +383,13 @@ public class AltosGPS implements Cloneable { } } - static public void update_state(AltosState state, AltosLink link, AltosConfigData config_data) throws InterruptedException { + static public void provide_data(AltosDataListener listener, AltosLink link, AltosCalData cal_data) throws InterruptedException { try { - AltosGPS gps = new AltosGPS(link, config_data); - - if (gps != null) { - state.set_gps(gps, state.gps_sequence++); - return; - } + AltosGPS gps = new AltosGPS(link, link.config_data()); + if (gps != null) + listener.set_gps(gps); } catch (TimeoutException te) { } - state.set_gps(null, 0); } public AltosGPS (AltosLink link, AltosConfigData config_data) throws TimeoutException, InterruptedException { diff --git a/altoslib/AltosGPSTimeValue.java b/altoslib/AltosGPSTimeValue.java new file mode 100644 index 00000000..0a534373 --- /dev/null +++ b/altoslib/AltosGPSTimeValue.java @@ -0,0 +1,28 @@ +/* + * Copyright © 2017 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 org.altusmetrum.altoslib_11; + +public class AltosGPSTimeValue { + public double time; + public AltosGPS gps; + + public AltosGPSTimeValue(double time, AltosGPS gps) { + this.time = time; + this.gps = gps; + } +} diff --git a/altoslib/AltosIMU.java b/altoslib/AltosIMU.java index f6cadf1d..20a2a413 100644 --- a/altoslib/AltosIMU.java +++ b/altoslib/AltosIMU.java @@ -33,7 +33,7 @@ public class AltosIMU implements Cloneable { public static final double counts_per_g = 2048.0; public static double convert_accel(double counts) { - return counts / counts_per_g * (-AltosConvert.GRAVITATIONAL_ACCELERATION); + return counts / counts_per_g * AltosConvert.gravity; } public static final double counts_per_degsec = 16.4; @@ -72,12 +72,18 @@ public class AltosIMU implements Cloneable { return n; } - static public void update_state(AltosState state, AltosLink link, AltosConfigData config_data) throws InterruptedException { + static public void provide_data(AltosDataListener listener, AltosLink link, AltosCalData cal_data) throws InterruptedException { try { AltosIMU imu = new AltosIMU(link); - if (imu != null) - state.set_imu(imu); + if (imu != null) { + listener.set_accel(cal_data.accel_along(imu.accel_along), + cal_data.accel_across(imu.accel_across), + cal_data.accel_through(imu.accel_through)); + listener.set_gyro(cal_data.gyro_roll(imu.gyro_roll), + cal_data.gyro_pitch(imu.gyro_pitch), + cal_data.gyro_yaw(imu.gyro_yaw)); + } } catch (TimeoutException te) { } } diff --git a/altoslib/AltosIdleFetch.java b/altoslib/AltosIdleFetch.java index 73717e17..43eb980a 100644 --- a/altoslib/AltosIdleFetch.java +++ b/altoslib/AltosIdleFetch.java @@ -30,7 +30,6 @@ class AltosIdler { static final int idle_gps = 0; static final int idle_imu = 1; static final int idle_mag = 2; - static final int idle_ms5607 = 3; static final int idle_mma655x = 4; @@ -42,49 +41,44 @@ class AltosIdler { static final int idle_sensor_tgps = 15; static final int idle_sensor_tmini3 = 16; - public void update_state(AltosState state, AltosLink link, AltosConfigData config_data) throws InterruptedException, TimeoutException, AltosUnknownProduct { + public void provide_data(AltosDataListener listener, AltosLink link, AltosCalData cal_data) throws InterruptedException, TimeoutException, AltosUnknownProduct { for (int idler : idlers) { - AltosIdle idle = null; switch (idler) { case idle_gps: - AltosGPS.update_state(state, link, config_data); + AltosGPS.provide_data(listener, link, cal_data); break; case idle_imu: - AltosIMU.update_state(state, link, config_data); + AltosIMU.provide_data(listener, link, cal_data); break; case idle_mag: - AltosMag.update_state(state, link, config_data); - break; - case idle_ms5607: - AltosMs5607.update_state(state, link, config_data); + AltosMag.provide_data(listener, link, cal_data); break; case idle_mma655x: - AltosMma655x.update_state(state, link, config_data); + AltosMma655x.provide_data(listener, link, cal_data); break; - case idle_sensor_tm: - AltosSensorTM.update_state(state, link, config_data); +/* case idle_sensor_tm: + AltosSensorTM.provide_data(listener, link, cal_data); break; case idle_sensor_metrum: - AltosSensorMetrum.update_state(state, link, config_data); + AltosSensorMetrum.provide_data(listener, link, cal_data); break; case idle_sensor_mega: - AltosSensorMega.update_state(state, link, config_data); + AltosSensorMega.provide_data(listener, link, cal_data); break; case idle_sensor_emini: - AltosSensorEMini.update_state(state, link, config_data); + AltosSensorEMini.provide_data(listener, link, cal_data); break; case idle_sensor_tmini2: - AltosSensorTMini2.update_state(state, link, config_data); + AltosSensorTMini2.provide_data(listener, link, cal_data); break; case idle_sensor_tgps: - AltosSensorTGPS.update_state(state, link, config_data); + AltosSensorTGPS.provide_data(listener, link, cal_data); break; case idle_sensor_tmini3: - AltosSensorTMini3.update_state(state, link, config_data); + AltosSensorTMini3.provide_data(listener, link, cal_data); break; +*/ } - if (idle != null) - idle.update_state(state); } } @@ -99,23 +93,20 @@ class AltosIdler { } -public class AltosIdleFetch implements AltosStateUpdate { +public class AltosIdleFetch implements AltosDataProvider { static final AltosIdler[] idlers = { new AltosIdler("EasyMini", - AltosIdler.idle_ms5607, AltosIdler.idle_sensor_emini), new AltosIdler("TeleMini-v1", AltosIdler.idle_sensor_tm), new AltosIdler("TeleMini-v2", - AltosIdler.idle_ms5607, AltosIdler.idle_sensor_tmini2), new AltosIdler("TeleMini-v3", - AltosIdler.idle_ms5607, AltosIdler.idle_sensor_tmini3), new AltosIdler("TeleMetrum-v1", @@ -124,16 +115,16 @@ public class AltosIdleFetch implements AltosStateUpdate { new AltosIdler("TeleMetrum-v2", AltosIdler.idle_gps, - AltosIdler.idle_ms5607, AltosIdler.idle_mma655x, + AltosIdler.idle_mma655x, AltosIdler.idle_sensor_metrum), new AltosIdler("TeleMega", AltosIdler.idle_gps, - AltosIdler.idle_ms5607, AltosIdler.idle_mma655x, + AltosIdler.idle_mma655x, AltosIdler.idle_imu, AltosIdler.idle_mag, AltosIdler.idle_sensor_mega), new AltosIdler("EasyMega", - AltosIdler.idle_ms5607, AltosIdler.idle_mma655x, + AltosIdler.idle_mma655x, AltosIdler.idle_imu, AltosIdler.idle_mag, AltosIdler.idle_sensor_mega), new AltosIdler("TeleGPS", @@ -143,29 +134,22 @@ public class AltosIdleFetch implements AltosStateUpdate { AltosLink link; - public void update_state(AltosState state) throws InterruptedException, AltosUnknownProduct { + public void provide_data(AltosDataListener listener, AltosCalData cal_data) throws InterruptedException, AltosUnknownProduct { try { boolean matched = false; /* Fetch config data from remote */ AltosConfigData config_data = new AltosConfigData(link); - state.set_state(AltosLib.ao_flight_stateless); - state.set_serial(config_data.serial); - state.set_callsign(config_data.callsign); - state.set_ground_accel(config_data.accel_cal_plus); - state.set_accel_g(config_data.accel_cal_plus, config_data.accel_cal_minus); - state.set_product(config_data.product); - state.set_firmware_version(config_data.version); - state.set_log_space(config_data.log_space); + listener.set_state(AltosLib.ao_flight_stateless); for (AltosIdler idler : idlers) { if (idler.matches(config_data)) { - idler.update_state(state, link, config_data); + idler.provide_data(listener, link, cal_data); matched = true; break; } } if (!matched) throw new AltosUnknownProduct(config_data.product); - state.set_received_time(System.currentTimeMillis()); + listener.set_received_time(System.currentTimeMillis()); } catch (TimeoutException te) { } diff --git a/altoslib/AltosIdleMonitor.java b/altoslib/AltosIdleMonitor.java index c374b601..3d73dce6 100644 --- a/altoslib/AltosIdleMonitor.java +++ b/altoslib/AltosIdleMonitor.java @@ -52,20 +52,21 @@ public class AltosIdleMonitor extends Thread { return link.reply_abort; } - boolean update_state(AltosState state) throws InterruptedException, TimeoutException, AltosUnknownProduct { + boolean provide_data(AltosDataListener listener) throws InterruptedException, TimeoutException, AltosUnknownProduct { boolean worked = false; boolean aborted = false; + AltosCalData cal_data = new AltosCalData(link.config_data()); try { start_link(); - fetch.update_state(state); + fetch.provide_data(listener, cal_data); if (!link.has_error && !link.reply_abort) worked = true; } finally { aborted = stop_link(); if (worked) { if (remote) - state.set_rssi(link.rssi(), 0); + listener.set_rssi(link.rssi(), 0); listener_state.battery = link.monitor_battery(); } } @@ -92,12 +93,14 @@ public class AltosIdleMonitor extends Thread { } public void run() { - AltosState state = new AltosState(); + AltosState state = null; try { for (;;) { try { link.config_data(); - update_state(state); + if (state == null) + state = new AltosState(new AltosCalData(link.config_data())); + provide_data(state); listener.update(state, listener_state); } catch (TimeoutException te) { } catch (AltosUnknownProduct ae) { diff --git a/altoslib/AltosIdleReader.java b/altoslib/AltosIdleReader.java index 5903c968..49d0cf61 100644 --- a/altoslib/AltosIdleReader.java +++ b/altoslib/AltosIdleReader.java @@ -48,11 +48,6 @@ public class AltosIdleReader extends AltosFlightReader { boolean worked = false; boolean aborted = false; - if (state == null) - state = new AltosState(); - else - state = state.clone(); - long delay = next_millis - System.currentTimeMillis(); if (delay > 0) @@ -61,7 +56,9 @@ public class AltosIdleReader extends AltosFlightReader { try { try { start_link(); - fetch.update_state(state); + if (state == null) + state = new AltosState(new AltosCalData(link.config_data())); + fetch.provide_data(state, state.cal_data); if (!link.has_error && !link.reply_abort) worked = true; } catch (TimeoutException te) { diff --git a/altoslib/AltosKML.java b/altoslib/AltosKML.java index 25108bf9..61e83daa 100644 --- a/altoslib/AltosKML.java +++ b/altoslib/AltosKML.java @@ -36,7 +36,7 @@ public class AltosKML implements AltosWriter { File name; PrintWriter out; int flight_state = -1; - AltosState prev = null; + AltosGPS prev = null; double gps_start_altitude; static final String[] kml_state_colors = { @@ -101,42 +101,43 @@ public class AltosKML implements AltosWriter { "\n" + "\n"; - void start (AltosState record) { + void start (int state) { +/* out.printf(kml_header_start, record.flight, record.serial); out.printf("Date: %04d-%02d-%02d\n", record.gps.year, record.gps.month, record.gps.day); out.printf("Time: %2d:%02d:%02d\n", record.gps.hour, record.gps.minute, record.gps.second); out.printf("%s", kml_header_end); +*/ } boolean started = false; - void state_start(AltosState state) { - String state_name = AltosLib.state_name(state.state()); - String state_color = state_color(state.state()); + void state_start(int state) { + String state_name = AltosLib.state_name(state); + String state_color = state_color(state); out.printf(kml_style_start, state_name, state_color); out.printf("\tState: %s\n", state_name); out.printf("%s", kml_style_end); out.printf(kml_placemark_start, state_name, state_name); } - void state_end(AltosState state) { + void state_end() { out.printf("%s", kml_placemark_end); } - void coord(AltosState state) { - AltosGPS gps = state.gps; + void coord(double time, AltosGPS gps, int state, double height) { double altitude; - if (state.height() != AltosLib.MISSING) - altitude = state.height() + gps_start_altitude; + if (height != AltosLib.MISSING) + altitude = height + gps_start_altitude; else altitude = gps.alt; out.printf(kml_coord_fmt, gps.lon, gps.lat, altitude, (double) gps.alt, - state.time, gps.nsat); + time, gps.nsat); } void end() { @@ -145,7 +146,7 @@ public class AltosKML implements AltosWriter { public void close() { if (prev != null) { - state_end(prev); + state_end(); end(); prev = null; } @@ -155,12 +156,7 @@ public class AltosKML implements AltosWriter { } } - public void write(AltosState state) { - AltosGPS gps = state.gps; - - if (gps == null) - return; - + public void write(AltosGPS gps, int state, double height) { if (gps.lat == AltosLib.MISSING) return; if (gps.lon == AltosLib.MISSING) @@ -170,24 +166,41 @@ public class AltosKML implements AltosWriter { started = true; gps_start_altitude = gps.alt; } - if (prev != null && prev.gps_sequence == state.gps_sequence) - return; - if (state.state() != flight_state) { - flight_state = state.state(); + if (state != flight_state) { + flight_state = state; if (prev != null) { - coord(state); - state_end(prev); +// coord(gps, state, height); + state_end(); } state_start(state); } - coord(state); - prev = state; +// coord(0, gps, state, height); + prev = gps; + } + + private int state(AltosFlightSeries series, double time) { + int s = AltosLib.MISSING; + for (AltosTimeValue state : series.state_series) { + if (state.time > time) + break; + s = (int) state.value; + } + return s; + } + + private double height(AltosFlightSeries series, double time) { + double h = AltosLib.MISSING; + for (AltosTimeValue height : series.height_series) { + if (height.time > time) + break; + h = height.value; + } + return h; } - public void write(AltosStateIterable states) { - for (AltosState state : states) { - if ((state.set & AltosState.set_gps) != 0) - write(state); + public void write(AltosFlightSeries series) { + for (AltosGPSTimeValue gps : series.gps_series) { + write(gps.gps, state(series, gps.time), height(series, gps.time)); } } diff --git a/altoslib/AltosLib.java b/altoslib/AltosLib.java index a3f164d4..2137d1d7 100644 --- a/altoslib/AltosLib.java +++ b/altoslib/AltosLib.java @@ -162,6 +162,16 @@ public class AltosLib { return product_any; } + public static boolean has_9dof(int device_type) { + return device_type == product_telemega || device_type == product_easymega; + } + + public static boolean has_gps(int device_type) { + return device_type == product_telemetrum || + device_type == product_telemega || + device_type == product_telegps; + } + /* Bluetooth "identifier" (bluetooth sucks) */ public final static String bt_product_telebt = "TeleBT"; diff --git a/altoslib/AltosLog.java b/altoslib/AltosLog.java index 6d873d78..d57749a1 100644 --- a/altoslib/AltosLog.java +++ b/altoslib/AltosLog.java @@ -61,8 +61,8 @@ public class AltosLog implements Runnable { return file; } - boolean open (AltosState state) throws IOException, InterruptedException { - AltosFile a = new AltosFile(state); + boolean open (AltosCalData cal_data) throws IOException, InterruptedException { + AltosFile a = new AltosFile(cal_data); log_file = new FileWriter(a, true); if (log_file != null) { @@ -80,24 +80,31 @@ public class AltosLog implements Runnable { public void run () { try { - AltosState state = new AltosState(); AltosConfigData receiver_config = link.config_data(); - state.set_receiver_serial(receiver_config.serial); + AltosCalData cal_data = new AltosCalData(); + AltosState state = null; + cal_data.set_receiver_serial(receiver_config.serial); for (;;) { AltosLine line = input_queue.take(); if (line.line == null) continue; try { AltosTelemetry telem = AltosTelemetry.parse(line.line); - state = state.clone(); - telem.update_state(state); - if (state.serial != serial || state.flight != flight || log_file == null) + if (state == null) + state = new AltosState(cal_data); + telem.provide_data(state, cal_data); + + if (cal_data.serial != serial || + cal_data.flight != flight || + log_file == null) { close_log_file(); - serial = state.serial; - flight = state.flight; - if (state.serial != AltosLib.MISSING && state.flight != AltosLib.MISSING) - open(state); + serial = cal_data.serial; + flight = cal_data.flight; + state = null; + if (cal_data.serial != AltosLib.MISSING && + cal_data.flight != AltosLib.MISSING) + open(cal_data); } } catch (ParseException pe) { } catch (AltosCRCException ce) { diff --git a/altoslib/AltosMag.java b/altoslib/AltosMag.java index e89ec0de..523a31a5 100644 --- a/altoslib/AltosMag.java +++ b/altoslib/AltosMag.java @@ -72,12 +72,14 @@ public class AltosMag implements Cloneable { this.through = through; } - static public void update_state(AltosState state, AltosLink link, AltosConfigData config_data) throws InterruptedException { + static public void provide_data(AltosDataListener listener, AltosLink link, AltosCalData cal_data) throws InterruptedException { try { AltosMag mag = new AltosMag(link); if (mag != null) - state.set_mag(mag); + listener.set_mag(cal_data.mag_along(mag.along), + cal_data.mag_across(mag.across), + cal_data.mag_through(mag.through)); } catch (TimeoutException te) { } } diff --git a/altoslib/AltosMap.java b/altoslib/AltosMap.java index e3c4a6a7..203a23b5 100644 --- a/altoslib/AltosMap.java +++ b/altoslib/AltosMap.java @@ -220,11 +220,11 @@ public class AltosMap implements AltosMapTileListener, AltosMapStoreListener { return false; } - public void show(AltosState state, AltosListenerState listener_state) { + public void show(AltosGPS gps, int state) { - /* If insufficient gps data, nothing to update + /* + * If insufficient gps data, nothing to update */ - AltosGPS gps = state.gps; if (gps == null) return; @@ -232,23 +232,23 @@ public class AltosMap implements AltosMapTileListener, AltosMapStoreListener { if (!gps.locked && gps.nsat < 4) return; - switch (state.state()) { + switch (state) { case AltosLib.ao_flight_boost: if (!have_boost) { - add_mark(gps.lat, gps.lon, state.state()); + add_mark(gps.lat, gps.lon, state); have_boost = true; } break; case AltosLib.ao_flight_landed: if (!have_landed) { - add_mark(gps.lat, gps.lon, state.state()); + add_mark(gps.lat, gps.lon, state); have_landed = true; } break; } if (path != null) { - AltosMapRectangle damage = path.add(gps.lat, gps.lon, state.state()); + AltosMapRectangle damage = path.add(gps.lat, gps.lon, state); if (damage != null) repaint(damage, AltosMapPath.stroke_width); @@ -259,6 +259,10 @@ public class AltosMap implements AltosMapTileListener, AltosMapStoreListener { maybe_centre(gps.lat, gps.lon); } + public void show(AltosState state, AltosListenerState listener_state) { + show(state.gps, state.state()); + } + public void centre(AltosLatLon lat_lon) { centre = lat_lon; set_transform(); @@ -268,10 +272,14 @@ public class AltosMap implements AltosMapTileListener, AltosMapStoreListener { centre(new AltosLatLon(lat, lon)); } - public void centre(AltosState state) { - if (!state.gps.locked && state.gps.nsat < 4) + public void centre(AltosGPS gps) { + if (!gps.locked && gps.nsat < 4) return; - centre(state.gps.lat, state.gps.lon); + centre(gps.lat, gps.lon); + } + + public void centre(AltosState state) { + centre(state.gps); } public void maybe_centre(double lat, double lon) { diff --git a/altoslib/AltosMma655x.java b/altoslib/AltosMma655x.java index 503eb5fd..2aadfc2e 100644 --- a/altoslib/AltosMma655x.java +++ b/altoslib/AltosMma655x.java @@ -46,17 +46,17 @@ public class AltosMma655x implements Cloneable { return n; } - static public void update_state(AltosState state, AltosLink link, AltosConfigData config_data) throws InterruptedException, AltosUnknownProduct { + static public void provide_data(AltosDataListener listener, AltosLink link, AltosCalData cal_data) throws InterruptedException, AltosUnknownProduct { try { AltosMma655x mma655x = new AltosMma655x(link); if (mma655x != null) { int accel = mma655x.accel; - if (config_data.mma655x_inverted()) + if (cal_data.mma655x_inverted) accel = 4095 - accel; - if (config_data.pad_orientation == 1) + if (cal_data.pad_orientation == 1) accel = 4095 - accel; - state.set_accel(accel); + listener.set_acceleration(cal_data.acceleration(accel)); } } catch (TimeoutException te) { } catch (NumberFormatException ne) { diff --git a/altoslib/AltosMs5607.java b/altoslib/AltosMs5607.java index c598d01e..bb6ce4c2 100644 --- a/altoslib/AltosMs5607.java +++ b/altoslib/AltosMs5607.java @@ -22,28 +22,36 @@ import java.util.concurrent.*; import java.io.*; public class AltosMs5607 { - public int reserved; - public int sens; - public int off; - public int tcs; - public int tco; - public int tref; - public int tempsens; - public int crc; - - public int raw_pres; - public int raw_temp; - public int pa; - public int cc; - - static final boolean ms5611 = false; - - void convert() { + public int reserved = AltosLib.MISSING; + public int sens = AltosLib.MISSING; + public int off = AltosLib.MISSING; + public int tcs = AltosLib.MISSING; + public int tco = AltosLib.MISSING; + public int tref = AltosLib.MISSING; + public int tempsens = AltosLib.MISSING; + public int crc = AltosLib.MISSING; + private boolean ms5611 = false; + + public boolean valid_config() { + return reserved != AltosLib.MISSING && + sens != AltosLib.MISSING && + off != AltosLib.MISSING && + tcs != AltosLib.MISSING && + tco != AltosLib.MISSING && + tref != AltosLib.MISSING && + tempsens != AltosLib.MISSING && + crc != AltosLib.MISSING; + } + + public AltosPresTemp pres_temp(int raw_pres, int raw_temp) { int dT; - int TEMP; - long OFF; - long SENS; - //int P; + int TEMP; + long OFF; + long SENS; + int P; + + if (raw_pres == AltosLib.MISSING || raw_temp == AltosLib.MISSING) + return new AltosPresTemp(AltosLib.MISSING, AltosLib.MISSING); dT = raw_temp - ((int) tref << 8); @@ -75,111 +83,61 @@ public class AltosMs5607 { SENS -= SENS2; } - pa = (int) (((((long) raw_pres * SENS) >> 21) - OFF) >> 15); - cc = TEMP; - } + P = (int) (((((long) raw_pres * SENS) >> 21) - OFF) >> 15); - public int set(int in_pres, int in_temp) { - raw_pres = in_pres; - raw_temp = in_temp; - convert(); - return pa; + return new AltosPresTemp(P, TEMP / 100.0); } - public boolean parse_line(String line) { - String[] items = line.split("\\s+"); - if (line.startsWith("Pressure:")) { - if (items.length >= 2) { - raw_pres = Integer.parseInt(items[1]); - } - } else if (line.startsWith("Temperature:")) { - if (items.length >= 2) - raw_temp = Integer.parseInt(items[1]); - } else if (line.startsWith("ms5607 reserved:")) { - if (items.length >= 3) - reserved = Integer.parseInt(items[2]); - } else if (line.startsWith("ms5607 sens:")) { - if (items.length >= 3) { - sens = Integer.parseInt(items[2]); - } - } else if (line.startsWith("ms5607 off:")) { - if (items.length >= 3) - off = Integer.parseInt(items[2]); - } else if (line.startsWith("ms5607 tcs:")) { - if (items.length >= 3) - tcs = Integer.parseInt(items[2]); - } else if (line.startsWith("ms5607 tco:")) { - if (items.length >= 3) - tco = Integer.parseInt(items[2]); - } else if (line.startsWith("ms5607 tref:")) { - if (items.length >= 3) - tref = Integer.parseInt(items[2]); - } else if (line.startsWith("ms5607 tempsens:")) { - if (items.length >= 3) - tempsens = Integer.parseInt(items[2]); - } else if (line.startsWith("ms5607 crc:")) { - if (items.length >= 3) - crc = Integer.parseInt(items[2]); - } else if (line.startsWith("Altitude:")) { - return false; - } - return true; - } + public AltosPresTemp pres_temp(AltosLink link) throws InterruptedException, TimeoutException { + int raw_pres = AltosLib.MISSING; + int raw_temp = AltosLib.MISSING; + boolean done = false; - static public void update_state(AltosState state, AltosLink link, AltosConfigData config_data) throws InterruptedException { - try { - AltosMs5607 ms5607 = new AltosMs5607(link, config_data); + link.printf("B\n"); + while (!done) { + String line = link.get_reply_no_dialog(5000); + if (line == null) + throw new TimeoutException(); - if (ms5607 != null) { - state.set_ms5607(ms5607); - return; + String[] items = line.split("\\s+"); + if (line.startsWith("Pressure:")) { + if (items.length >= 2) { + raw_pres = Integer.parseInt(items[1]); + } + } else if (line.startsWith("Temperature:")) { + if (items.length >= 2) + raw_temp = Integer.parseInt(items[1]); + } else if (line.startsWith("Altitude:")) { + done = true; } - } catch (TimeoutException te) { } + return pres_temp(raw_pres, raw_temp); } - public boolean valid_config() { - return reserved != AltosLib.MISSING && - sens != AltosLib.MISSING && - off != AltosLib.MISSING && - tcs != AltosLib.MISSING && - tco != AltosLib.MISSING && - tref != AltosLib.MISSING && - tempsens != AltosLib.MISSING && - crc != AltosLib.MISSING; + public AltosMs5607(boolean ms5611) { + this.ms5611 = ms5611; } public AltosMs5607() { - raw_pres = AltosLib.MISSING; - raw_temp = AltosLib.MISSING; - pa = AltosLib.MISSING; - cc = AltosLib.MISSING; + this(false); + } + + public AltosMs5607(AltosMs5607 old) { + reserved = old.reserved; + sens = old.sens; + off = old.off; + tcs = old.tcs; + tco = old.tco; + tref = old.tref; + tempsens = old.tempsens; + crc = old.crc; } public AltosMs5607(AltosConfigData config_data) { - this(); - reserved = config_data.ms5607_reserved; - sens = config_data.ms5607_sens; - off = config_data.ms5607_off; - tcs = config_data.ms5607_tcs; - tco = config_data.ms5607_tco; - tref = config_data.ms5607_tref; - tempsens = config_data.ms5607_tempsens; - crc = config_data.ms5607_crc; + this(config_data.ms5607()); } public AltosMs5607 (AltosLink link, AltosConfigData config_data) throws InterruptedException, TimeoutException { this(config_data); - link.printf("B\n"); - for (;;) { - String line = link.get_reply_no_dialog(5000); - if (line == null) { - throw new TimeoutException(); - } - if (!parse_line(line)) { - break; - } - } - convert(); } } diff --git a/altoslib/AltosPreferences.java b/altoslib/AltosPreferences.java index 35d44631..f446d4dd 100644 --- a/altoslib/AltosPreferences.java +++ b/altoslib/AltosPreferences.java @@ -363,11 +363,11 @@ public class AltosPreferences { } } - public static void set_state(AltosState state) { + public static void set_state(AltosState state, int serial) { synchronized(backend) { - backend.putJson(String.format(statePreferenceFormat, state.serial), new AltosJson(state)); - backend.putInt(statePreferenceLatest, state.serial); + backend.putJson(String.format(statePreferenceFormat, serial), new AltosJson(state)); + backend.putInt(statePreferenceLatest, serial); flush_preferences(); } } diff --git a/altoslib/AltosPresTemp.java b/altoslib/AltosPresTemp.java new file mode 100644 index 00000000..d0787033 --- /dev/null +++ b/altoslib/AltosPresTemp.java @@ -0,0 +1,25 @@ +/* + * Copyright © 2017 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, either version 2 of the License, or + * (at your option) any later version. + * + * 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. + */ + +package org.altusmetrum.altoslib_11; + +public class AltosPresTemp { + double pres = AltosLib.MISSING; + double temp = AltosLib.MISSING; + + public AltosPresTemp(double pres, double temp) { + this.pres = pres; + this.temp = temp; + } +} diff --git a/altoslib/AltosRecordSet.java b/altoslib/AltosRecordSet.java index 8a472336..3c6ae575 100644 --- a/altoslib/AltosRecordSet.java +++ b/altoslib/AltosRecordSet.java @@ -17,5 +17,6 @@ package org.altusmetrum.altoslib_11; import java.util.*; public interface AltosRecordSet { - public void capture_series(AltosFlightSeries series); + public AltosCalData cal_data(); + public void capture_series(AltosDataListener listener); } diff --git a/altoslib/AltosSensorTM.java b/altoslib/AltosSensorTM.java index 5d1b1b7f..7d7becfb 100644 --- a/altoslib/AltosSensorTM.java +++ b/altoslib/AltosSensorTM.java @@ -29,18 +29,18 @@ public class AltosSensorTM { public int drogue; public int main; - static public void update_state(AltosState state, AltosLink link, AltosConfigData config_data) throws InterruptedException { + static public void provide_data(AltosDataListener listener, AltosLink link, AltosCalData cal_data) throws InterruptedException { try { AltosSensorTM sensor_tm = new AltosSensorTM(link); if (sensor_tm == null) return; - state.set_accel(sensor_tm.accel); - state.set_pressure(AltosConvert.barometer_to_pressure(sensor_tm.pres)); - state.set_temperature(AltosConvert.thermometer_to_temperature(sensor_tm.temp)); - state.set_battery_voltage(AltosConvert.cc_battery_to_voltage(sensor_tm.batt)); - state.set_apogee_voltage(AltosConvert.cc_ignitor_to_voltage(sensor_tm.drogue)); - state.set_main_voltage(AltosConvert.cc_ignitor_to_voltage(sensor_tm.main)); + listener.set_acceleration(cal_data.acceleration((sensor_tm.accel))); + listener.set_pressure(AltosConvert.barometer_to_pressure(sensor_tm.pres)); + listener.set_temperature(AltosConvert.thermometer_to_temperature(sensor_tm.temp)); + listener.set_battery_voltage(AltosConvert.cc_battery_to_voltage(sensor_tm.batt)); + listener.set_apogee_voltage(AltosConvert.cc_ignitor_to_voltage(sensor_tm.drogue)); + listener.set_main_voltage(AltosConvert.cc_ignitor_to_voltage(sensor_tm.main)); } catch (TimeoutException te) { } diff --git a/altoslib/AltosState.java b/altoslib/AltosState.java index 846bda42..f46b12ea 100644 --- a/altoslib/AltosState.java +++ b/altoslib/AltosState.java @@ -24,7 +24,7 @@ package org.altusmetrum.altoslib_11; import java.io.*; -public class AltosState extends AltosFlightListener implements Cloneable { +public class AltosState extends AltosDataListener { public static final int set_position = 1; public static final int set_gps = 2; @@ -40,10 +40,12 @@ public class AltosState extends AltosFlightListener implements Cloneable { public long received_time; + public int rssi; + public int status; + public double time; public double prev_time; public double time_change; - private int prev_tick; class AltosValue { double value; @@ -289,16 +291,11 @@ public class AltosState extends AltosFlightListener implements Cloneable { } private int state; - public int flight; - public int serial; public int altitude_32; public int receiver_serial; public boolean landed; public boolean ascent; /* going up? */ public boolean boost; /* under power */ - public int rssi; - public int status; - public int device_type; public int config_major; public int config_minor; public int apogee_delay; @@ -446,6 +443,11 @@ public class AltosState extends AltosFlightListener implements Cloneable { } public void set_altitude(double new_altitude) { + double old_altitude = altitude.value(); + if (old_altitude != AltosLib.MISSING) { + while (old_altitude - new_altitude > 32000) + new_altitude += 65536.0; + } altitude.set_measured(new_altitude, time); } @@ -684,6 +686,11 @@ public class AltosState extends AltosFlightListener implements Cloneable { public AltosValue kalman_height, kalman_speed, kalman_acceleration; public void set_kalman(double height, double speed, double acceleration) { + double old_height = kalman_height.value(); + if (old_height != AltosLib.MISSING) { + while (old_height - height > 32000) + height += 65536; + } kalman_height.set(height, time); kalman_speed.set(speed, time); kalman_acceleration.set(acceleration, time); @@ -701,7 +708,6 @@ public class AltosState extends AltosFlightListener implements Cloneable { public AltosGPS temp_gps; public int temp_gps_sat_tick; public boolean gps_pending; - public int gps_sequence; public AltosIMU imu; public AltosMag mag; @@ -728,11 +734,7 @@ public class AltosState extends AltosFlightListener implements Cloneable { public String callsign; public String firmware_version; - public double accel_plus_g; - public double accel_minus_g; - public double accel; public double ground_accel; - public double ground_accel_avg; public int log_format; public int log_space; @@ -759,16 +761,11 @@ public class AltosState extends AltosFlightListener implements Cloneable { time = AltosLib.MISSING; time_change = AltosLib.MISSING; prev_time = AltosLib.MISSING; - tick = AltosLib.MISSING; - prev_tick = AltosLib.MISSING; - boost_tick = AltosLib.MISSING; state = AltosLib.ao_flight_invalid; - flight = AltosLib.MISSING; landed = false; boost = false; rssi = AltosLib.MISSING; status = 0; - device_type = AltosLib.MISSING; config_major = AltosLib.MISSING; config_minor = AltosLib.MISSING; apogee_delay = AltosLib.MISSING; @@ -798,7 +795,6 @@ public class AltosState extends AltosFlightListener implements Cloneable { gps = null; temp_gps = null; temp_gps_sat_tick = 0; - gps_sequence = 0; gps_pending = false; imu = null; @@ -817,10 +813,6 @@ public class AltosState extends AltosFlightListener implements Cloneable { pad_orientation = AltosLib.MISSING; - gyro_zero_roll = AltosLib.MISSING; - gyro_zero_pitch = AltosLib.MISSING; - gyro_zero_yaw = AltosLib.MISSING; - set_npad(0); ngps = 0; @@ -846,17 +838,11 @@ public class AltosState extends AltosFlightListener implements Cloneable { callsign = null; firmware_version = null; - accel_plus_g = AltosLib.MISSING; - accel_minus_g = AltosLib.MISSING; - accel = AltosLib.MISSING; - ground_accel = AltosLib.MISSING; - ground_accel_avg = AltosLib.MISSING; log_format = AltosLib.MISSING; log_space = AltosLib.MISSING; product = null; - serial = AltosLib.MISSING; receiver_serial = AltosLib.MISSING; altitude_32 = AltosLib.MISSING; @@ -867,8 +853,6 @@ public class AltosState extends AltosFlightListener implements Cloneable { } void finish_update() { - prev_tick = tick; - ground_altitude.finish_update(); altitude.finish_update(); pressure.finish_update(); @@ -881,153 +865,6 @@ public class AltosState extends AltosFlightListener implements Cloneable { kalman_acceleration.finish_update(); } - void copy(AltosState old) { - - if (old == null) { - init(); - return; - } - - super.copy(old); - - received_time = old.received_time; - time = old.time; - time_change = old.time_change; - prev_time = old.time; - - tick = old.tick; - prev_tick = old.tick; - boost_tick = old.boost_tick; - - state = old.state; - flight = old.flight; - landed = old.landed; - ascent = old.ascent; - boost = old.boost; - rssi = old.rssi; - status = old.status; - device_type = old.device_type; - config_major = old.config_major; - config_minor = old.config_minor; - apogee_delay = old.apogee_delay; - main_deploy = old.main_deploy; - flight_log_max = old.flight_log_max; - - set = 0; - - ground_pressure.copy(old.ground_pressure); - ground_altitude.copy(old.ground_altitude); - altitude.copy(old.altitude); - pressure.copy(old.pressure); - speed.copy(old.speed); - acceleration.copy(old.acceleration); - orient.copy(old.orient); - - battery_voltage = old.battery_voltage; - pyro_voltage = old.pyro_voltage; - temperature = old.temperature; - apogee_voltage = old.apogee_voltage; - main_voltage = old.main_voltage; - ignitor_voltage = old.ignitor_voltage; - - kalman_height.copy(old.kalman_height); - kalman_speed.copy(old.kalman_speed); - kalman_acceleration.copy(old.kalman_acceleration); - - if (old.gps != null) - gps = old.gps.clone(); - else - gps = null; - if (old.temp_gps != null) - temp_gps = old.temp_gps.clone(); - else - temp_gps = null; - temp_gps_sat_tick = old.temp_gps_sat_tick; - gps_sequence = old.gps_sequence; - gps_pending = old.gps_pending; - - if (old.imu != null) - imu = old.imu.clone(); - else - imu = null; - last_imu_time = old.last_imu_time; - - if (old.rotation != null) - rotation = new AltosRotation (old.rotation); - - if (old.ground_rotation != null) { - ground_rotation = new AltosRotation(old.ground_rotation); - } - - accel_zero_along = old.accel_zero_along; - accel_zero_across = old.accel_zero_across; - accel_zero_through = old.accel_zero_through; - - accel_ground_along = old.accel_ground_along; - accel_ground_across = old.accel_ground_across; - accel_ground_through = old.accel_ground_through; - pad_orientation = old.pad_orientation; - - gyro_zero_roll = old.gyro_zero_roll; - gyro_zero_pitch = old.gyro_zero_pitch; - gyro_zero_yaw = old.gyro_zero_yaw; - - if (old.mag != null) - mag = old.mag.clone(); - else - mag = null; - - npad = old.npad; - gps_waiting = old.gps_waiting; - gps_ready = old.gps_ready; - ngps = old.ngps; - - if (old.from_pad != null) - from_pad = old.from_pad.clone(); - else - from_pad = null; - - elevation = old.elevation; - range = old.range; - - gps_height = old.gps_height; - - gps_altitude.copy(old.gps_altitude); - gps_ground_altitude.copy(old.gps_ground_altitude); - gps_ground_speed.copy(old.gps_ground_speed); - gps_ascent_rate.copy(old.gps_ascent_rate); - gps_course.copy(old.gps_course); - gps_speed.copy(old.gps_speed); - - pad_lat = old.pad_lat; - pad_lon = old.pad_lon; - pad_alt = old.pad_alt; - - speak_tick = old.speak_tick; - speak_altitude = old.speak_altitude; - - callsign = old.callsign; - firmware_version = old.firmware_version; - - accel_plus_g = old.accel_plus_g; - accel_minus_g = old.accel_minus_g; - accel = old.accel; - ground_accel = old.ground_accel; - ground_accel_avg = old.ground_accel_avg; - - log_format = old.log_format; - log_space = old.log_space; - product = old.product; - serial = old.serial; - receiver_serial = old.receiver_serial; - altitude_32 = old.altitude_32; - - baro = old.baro; - companion = old.companion; - - pyro_fired = old.pyro_fired; - } - void update_time() { } @@ -1078,19 +915,6 @@ public class AltosState extends AltosFlightListener implements Cloneable { } } - public void set_tick(int new_tick) { - if (new_tick != AltosLib.MISSING) { - if (prev_tick != AltosLib.MISSING) { - while (new_tick < prev_tick - 1000) { - new_tick += 65536; - } - } - tick = new_tick; - time = tick / 100.0; - time_change = time - prev_time; - } - } - public String state_name() { return AltosLib.state_name(state); } @@ -1112,15 +936,6 @@ public class AltosState extends AltosFlightListener implements Cloneable { return state; } - public void set_device_type(int device_type) { - this.device_type = device_type; - switch (device_type) { - case AltosLib.product_telegps: - this.state = AltosLib.ao_flight_stateless; - break; - } - } - public void set_log_format(int log_format) { this.log_format = log_format; switch (log_format) { @@ -1160,40 +975,38 @@ public class AltosState extends AltosFlightListener implements Cloneable { } private void re_init() { - int bt = boost_tick; int rs = receiver_serial; init(); - boost_tick = bt; receiver_serial = rs; } - public void set_flight(int flight) { - - /* When the flight changes, reset the state */ - if (flight != AltosLib.MISSING) { - if (this.flight != AltosLib.MISSING && - this.flight != flight) { - re_init(); - } - this.flight = flight; - } - } - - public void set_serial(int serial) { - /* When the serial changes, reset the state */ - if (serial != AltosLib.MISSING) { - if (this.serial != AltosLib.MISSING && - this.serial != serial) { - re_init(); - } - this.serial = serial; - } - } - - public void set_receiver_serial(int serial) { - if (serial != AltosLib.MISSING) - receiver_serial = serial; - } +// public void set_flight(int flight) { +// +// /* When the flight changes, reset the state */ +// if (flight != AltosLib.MISSING) { +// if (this.flight != AltosLib.MISSING && +// this.flight != flight) { +// re_init(); +// } +// this.flight = flight; +// } +// } +// +// public void set_serial(int serial) { +// /* When the serial changes, reset the state */ +// if (serial != AltosLib.MISSING) { +// if (this.serial != AltosLib.MISSING && +// this.serial != serial) { +// re_init(); +// } +// this.serial = serial; +// } +// } +// +// public void set_receiver_serial(int serial) { +// if (serial != AltosLib.MISSING) +// receiver_serial = serial; +// } public boolean altitude_32() { return altitude_32 == 1; @@ -1221,10 +1034,9 @@ public class AltosState extends AltosFlightListener implements Cloneable { received_time = ms; } - public void set_gps(AltosGPS gps, int sequence) { + public void set_gps(AltosGPS gps) { if (gps != null) { - this.gps = gps.clone(); - gps_sequence = sequence; + this.gps = gps; update_gps(); set |= set_gps; } @@ -1273,18 +1085,6 @@ public class AltosState extends AltosFlightListener implements Cloneable { update_pad_rotation(); } - public double gyro_zero_roll; - public double gyro_zero_pitch; - public double gyro_zero_yaw; - - public void set_gyro_zero(double roll, double pitch, double yaw) { - if (roll != AltosLib.MISSING) { - gyro_zero_roll = roll; - gyro_zero_pitch = pitch; - gyro_zero_yaw = yaw; - } - } - public double last_imu_time; private double radians(double degrees) { @@ -1309,77 +1109,58 @@ public class AltosState extends AltosFlightListener implements Cloneable { last_imu_time = time; } - public void set_imu(AltosIMU imu) { - if (imu != null) - imu = imu.clone(); - this.imu = imu; + private double gyro_roll, gyro_pitch, gyro_yaw; + + public void set_gyro(double roll, double pitch, double yaw) { + gyro_roll = roll; + gyro_pitch = roll; + gyro_roll = roll; update_orient(); } - private double gyro_zero_overflow(double first) { - double v = first / 128.0; - if (v < 0) - v = Math.ceil(v); - else - v = Math.floor(v); - return v * 128.0; - } + private double accel_along, accel_across, accel_through; - public void check_imu_wrap(AltosIMU imu) { - if (this.imu == null) { - gyro_zero_roll += gyro_zero_overflow(imu.gyro_roll); - gyro_zero_pitch += gyro_zero_overflow(imu.gyro_pitch); - gyro_zero_yaw += gyro_zero_overflow(imu.gyro_yaw); - } + public void set_accel(double along, double across, double through) { + accel_along = along; + accel_across = across; + accel_through = through; + update_orient(); } public double accel_along() { - if (imu != null && accel_zero_along != AltosLib.MISSING) - return AltosIMU.convert_accel(imu.accel_along - accel_zero_along); - return AltosLib.MISSING; + return accel_along; } public double accel_across() { - if (imu != null && accel_zero_across != AltosLib.MISSING) - return AltosIMU.convert_accel(imu.accel_across - accel_zero_across); - return AltosLib.MISSING; + return accel_across; } public double accel_through() { - if (imu != null && accel_zero_through != AltosLib.MISSING) - return AltosIMU.convert_accel(imu.accel_through - accel_zero_through); - return AltosLib.MISSING; + return accel_through; } public double gyro_roll() { - if (imu != null && gyro_zero_roll != AltosLib.MISSING) { - return AltosIMU.convert_gyro(imu.gyro_roll - gyro_zero_roll); - } - return AltosLib.MISSING; + return gyro_roll; } public double gyro_pitch() { - if (imu != null && gyro_zero_pitch != AltosLib.MISSING) { - return AltosIMU.convert_gyro(imu.gyro_pitch - gyro_zero_pitch); - } - return AltosLib.MISSING; + return gyro_pitch; } public double gyro_yaw() { - if (imu != null && gyro_zero_yaw != AltosLib.MISSING) { - return AltosIMU.convert_gyro(imu.gyro_yaw - gyro_zero_yaw); - } - return AltosLib.MISSING; + return gyro_yaw; } - public void set_mag(AltosMag mag) { - this.mag = mag.clone(); + private double mag_along, mag_across, mag_through; + + public void set_mag(double along, double across, double through) { + mag_along = along; + mag_across = across; + mag_through = through; } public double mag_along() { - if (mag != null) - return AltosMag.convert_gauss(mag.along); - return AltosLib.MISSING; + return mag_along; } public double mag_across() { @@ -1394,71 +1175,15 @@ public class AltosState extends AltosFlightListener implements Cloneable { return AltosLib.MISSING; } - public AltosMs5607 make_baro() { - if (baro == null) - baro = new AltosMs5607(); - return baro; - } - - public void set_ms5607(AltosMs5607 ms5607) { - baro = ms5607; - - if (baro != null && baro.pa != AltosLib.MISSING && baro.cc != AltosLib.MISSING) { - set_pressure(baro.pa); - set_temperature(baro.cc / 100.0); - } - } - - public void set_ms5607(int pres, int temp) { - if (baro != null) { - baro.set(pres, temp); - - set_pressure(baro.pa); - set_temperature(baro.cc / 100.0); - } - } - public void set_companion(AltosCompanion companion) { this.companion = companion; } - void update_accel() { - if (accel == AltosLib.MISSING) - return; - if (accel_plus_g == AltosLib.MISSING) - return; - if (accel_minus_g == AltosLib.MISSING) - return; - - double counts_per_g = (accel_minus_g - accel_plus_g) / 2.0; - double counts_per_mss = counts_per_g / 9.80665; - acceleration.set_measured((accel_plus_g - accel) / counts_per_mss, time); - } - - public void set_accel_g(double accel_plus_g, double accel_minus_g) { - if (accel_plus_g != AltosLib.MISSING) { - this.accel_plus_g = accel_plus_g; - this.accel_minus_g = accel_minus_g; - update_accel(); - } - } - - public void set_ground_accel(double ground_accel) { - if (ground_accel != AltosLib.MISSING) - this.ground_accel = ground_accel; - } - - public void set_accel(double accel) { - if (accel != AltosLib.MISSING) { - this.accel = accel; - if (state == AltosLib.ao_flight_pad) { - if (ground_accel_avg == AltosLib.MISSING) - ground_accel_avg = accel; - else - ground_accel_avg = (ground_accel_avg * 7 + accel) / 8; - } + public void set_acceleration(double acceleration) { + if (acceleration != AltosLib.MISSING) { + this.acceleration.set_measured(acceleration, time); + set |= set_data; } - update_accel(); } public void set_temperature(double temperature) { @@ -1504,74 +1229,8 @@ public class AltosState extends AltosFlightListener implements Cloneable { this.pyro_fired = fired; } - public double time_since_boost() { - if (tick == AltosLib.MISSING) - return 0.0; - - if (boost_tick == AltosLib.MISSING) - return tick / 100.0; - return (tick - boost_tick) / 100.0; - } - - public boolean valid() { - return tick != AltosLib.MISSING && serial != AltosLib.MISSING; - } - - public void set_temp_gps() { - set_gps(temp_gps, gps_sequence + 1); - gps_pending = false; - super.set_temp_gps(); - } - - public void set_config_data(AltosConfigData config_data) { - if (config_data.callsign != null) - set_callsign(config_data.callsign); - if (config_data.accel_cal_plus != AltosLib.MISSING && - config_data.accel_cal_minus != AltosLib.MISSING) - set_accel_g(config_data.accel_cal_plus, config_data.accel_cal_minus); - if (config_data.product != null) - set_product(config_data.product); - if (config_data.log_format != AltosLib.MISSING) - set_log_format(config_data.log_format); - if (config_data.serial != AltosLib.MISSING) - set_serial(config_data.serial); - AltosMs5607 ms5607 = new AltosMs5607(config_data); - if (ms5607.valid_config()) - set_ms5607(ms5607); - } - - public AltosState clone() { - AltosState s = new AltosState(); - s.copy(this); - - /* Code to test state save/restore. Enable only for that purpose - */ - if (false) { - AltosJson json = new AltosJson(this); - String onetrip = json.toPrettyString(); - AltosJson back = AltosJson.fromString(onetrip); - AltosState tripstate = (AltosState) back.make(this.getClass()); - AltosJson tripjson = new AltosJson(tripstate); - String twotrip = tripjson.toPrettyString(); - - if (!onetrip.equals(twotrip)) { - try { - FileWriter one_file = new FileWriter("one.json", true); - one_file.write(onetrip); - one_file.flush(); - FileWriter two_file = new FileWriter("two.json", true); - two_file.write(twotrip); - two_file.flush(); - } catch (Exception e) { - } - System.out.printf("json error\n"); - System.exit(1); - } - } - return s; - } - - public AltosState () { + public AltosState (AltosCalData cal_data) { + super(cal_data); init(); } } diff --git a/altoslib/AltosStateName.java b/altoslib/AltosStateName.java new file mode 100644 index 00000000..a3ac9261 --- /dev/null +++ b/altoslib/AltosStateName.java @@ -0,0 +1,32 @@ +/* + * Copyright © 2017 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, either version 2 of the License, or + * (at your option) any later version. + * + * 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. + */ + +package org.altusmetrum.altoslib_11; + +public class AltosStateName extends AltosUnits { + + public double value(double v, boolean imperial_units) { return v; } + + public double inverse(double v, boolean imperial_units) { return v; } + + public String string_value(double v, boolean imperial_units) { + return AltosLib.state_name((int) v); + } + + public String show_units(boolean imperial_units) { return "state"; } + + public String say_units(boolean imperial_units) { return "state"; } + + public int show_fraction(int width, boolean imperial_units) { return 0; } +} diff --git a/altoslib/AltosStateUpdate.java b/altoslib/AltosStateUpdate.java deleted file mode 100644 index e9698cba..00000000 --- a/altoslib/AltosStateUpdate.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright © 2013 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; either version 2 of the License, or - * (at your option) any later version. - * - * 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 org.altusmetrum.altoslib_11; - -public interface AltosStateUpdate { - public void update_state(AltosState state) throws InterruptedException, AltosUnknownProduct; -} diff --git a/altoslib/AltosTelemetry.java b/altoslib/AltosTelemetry.java index 5600e7be..b810ac83 100644 --- a/altoslib/AltosTelemetry.java +++ b/altoslib/AltosTelemetry.java @@ -24,7 +24,7 @@ import java.text.*; * Telemetry data contents */ -public abstract class AltosTelemetry implements AltosStateUpdate { +public abstract class AltosTelemetry implements AltosDataProvider { int[] bytes; /* All telemetry packets have these fields */ @@ -46,13 +46,14 @@ public abstract class AltosTelemetry implements AltosStateUpdate { return sum == bytes[bytes.length - 1]; } - public void update_state(AltosState state) { - state.set_serial(serial()); - if (state.state() == AltosLib.ao_flight_invalid) - state.set_state(AltosLib.ao_flight_startup); - state.set_tick(tick()); - state.set_rssi(rssi(), status()); - state.set_received_time(received_time); + public void provide_data(AltosDataListener listener, AltosCalData cal_data) { + cal_data.set_serial(serial()); + if (listener.state == AltosLib.ao_flight_invalid) + listener.set_state(AltosLib.ao_flight_startup); + cal_data.set_tick(tick()); + listener.set_time(cal_data.time()); + listener.set_rssi(rssi(), status()); + listener.set_received_time(received_time); } final static int PKT_APPEND_STATUS_1_CRC_OK = (1 << 7); @@ -108,29 +109,6 @@ public abstract class AltosTelemetry implements AltosStateUpdate { return telem; } - public static int extend_height(AltosState state, int height_16) { - double compare_height; - int height = height_16; - - if (state.gps != null && state.gps.alt != AltosLib.MISSING) { - compare_height = state.gps_height(); - } else { - compare_height = state.height(); - } - - if (compare_height != AltosLib.MISSING) { - int high_bits = (int) Math.floor (compare_height / 65536.0); - - height = (high_bits << 16) | (height_16 & 0xffff); - - if (Math.abs(height + 65536 - compare_height) < Math.abs(height - compare_height)) - height += 65536; - else if (Math.abs(height - 65536 - compare_height) < Math.abs(height - compare_height)) - height -= 65536; - } - return height; - } - public AltosTelemetry() { this.received_time = System.currentTimeMillis(); } diff --git a/altoslib/AltosTelemetryCompanion.java b/altoslib/AltosTelemetryCompanion.java index 2c05e245..f3283c32 100644 --- a/altoslib/AltosTelemetryCompanion.java +++ b/altoslib/AltosTelemetryCompanion.java @@ -49,8 +49,8 @@ public class AltosTelemetryCompanion extends AltosTelemetryStandard { super(bytes); } - public void update_state(AltosState state) { - super.update_state(state); - state.set_companion(companion()); + public void provide_data(AltosDataListener listener, AltosCalData cal_data) { + super.provide_data(listener, cal_data); + listener.set_companion(companion()); } } diff --git a/altoslib/AltosTelemetryConfiguration.java b/altoslib/AltosTelemetryConfiguration.java index d91a03fc..920c3187 100644 --- a/altoslib/AltosTelemetryConfiguration.java +++ b/altoslib/AltosTelemetryConfiguration.java @@ -35,17 +35,17 @@ public class AltosTelemetryConfiguration extends AltosTelemetryStandard { super(bytes); } - public void update_state(AltosState state) { - super.update_state(state); - state.set_device_type(device_type()); - state.set_flight(flight()); - state.set_config(config_major(), config_minor(), flight_log_max()); + public void provide_data(AltosDataListener listener, AltosCalData cal_data) { + super.provide_data(listener, cal_data); + cal_data.set_device_type(device_type()); + cal_data.set_flight(flight()); + cal_data.set_config(config_major(), config_minor(), flight_log_max()); if (device_type() == AltosLib.product_telegps) - state.set_battery_voltage(AltosConvert.tele_gps_voltage(v_batt())); + listener.set_battery_voltage(AltosConvert.tele_gps_voltage(v_batt())); else - state.set_flight_params(apogee_delay(), main_deploy()); + cal_data.set_flight_params(apogee_delay() / 100.0, main_deploy()); - state.set_callsign(callsign()); - state.set_firmware_version(version()); + cal_data.set_callsign(callsign()); + cal_data.set_firmware_version(version()); } } diff --git a/altoslib/AltosTelemetryFile.java b/altoslib/AltosTelemetryFile.java index 9c5f8dae..0b0e6a48 100644 --- a/altoslib/AltosTelemetryFile.java +++ b/altoslib/AltosTelemetryFile.java @@ -22,76 +22,112 @@ import java.io.*; import java.util.*; import java.text.*; -class AltosTelemetryIterator implements Iterator { - AltosState state; - Iterator telems; - AltosTelemetry next; - boolean seen; - - public boolean hasNext() { - return !seen || telems.hasNext(); +class AltosTelemetryNullListener extends AltosDataListener { + public void set_rssi(int rssi, int status) { } + public void set_received_time(long received_time) { } + + public void set_acceleration(double accel) { } + public void set_pressure(double pa) { } + public void set_thrust(double N) { } + + public void set_kalman(double height, double speed, double accel) { } + + public void set_temperature(double deg_c) { } + public void set_battery_voltage(double volts) { } + + public void set_apogee_voltage(double volts) { } + public void set_main_voltage(double volts) { } + + public void set_gps(AltosGPS gps) { } + + public void set_orient(double orient) { } + public void set_gyro(double roll, double pitch, double yaw) { } + public void set_accel_ground(double along, double across, double through) { } + public void set_accel(double along, double across, double through) { } + public void set_mag(double along, double across, double through) { } + public void set_pyro_voltage(double volts) { } + public void set_ignitor_voltage(double[] voltage) { } + public void set_pyro_fired(int pyro_mask) { } + public void set_companion(AltosCompanion companion) { } + + public boolean cal_data_complete() { + /* All telemetry packets */ + if (cal_data.serial == AltosLib.MISSING) + return false; + + if (cal_data.boost_tick == AltosLib.MISSING) + return false; + + /* + * TelemetryConfiguration: + * + * device_type, flight, config version, log max, + * flight params, callsign and version + */ + if (cal_data.device_type == AltosLib.MISSING) + return false; + + /* + * TelemetrySensor or TelemetryMegaData: + * + * ground_accel, accel+/-, ground pressure + */ + if (cal_data.ground_pressure == AltosLib.MISSING) + return false; + + /* + * TelemetryLocation + */ + if (AltosLib.has_gps(cal_data.device_type) && cal_data.gps_ground_altitude == AltosLib.MISSING) + return false; + + return true; } - public AltosState next() { - if (seen) { - AltosState n = state.clone(); - AltosTelemetry t = telems.next(); - - t.update_state(n); - state = n; - } - seen = true; - return state; - } - - public void remove () { - } - - public AltosTelemetryIterator(AltosState start, Iterator telems) { - this.state = start; - this.telems = telems; - this.seen = false; + public AltosTelemetryNullListener(AltosCalData cal_data) { + super(cal_data); } } -public class AltosTelemetryFile extends AltosStateIterable { +public class AltosTelemetryFile implements AltosRecordSet { AltosTelemetryIterable telems; - AltosState start; + AltosCalData cal_data; public void write_comments(PrintStream out) { } public void write(PrintStream out) { - } - public AltosTelemetryFile(FileInputStream input) { - telems = new AltosTelemetryIterable(input); - start = new AltosState(); - - /* Find boost tick */ - AltosState state = start.clone(); + /* Construct cal data by walking through the telemetry data until we've found everything available */ + public AltosCalData cal_data() { + if (cal_data == null) { + cal_data = new AltosCalData(); + AltosTelemetryNullListener l = new AltosTelemetryNullListener(cal_data); - for (AltosTelemetry telem : telems) { - telem.update_state(state); - state.finish_update(); - if (state.state() != AltosLib.ao_flight_invalid && state.state() >= AltosLib.ao_flight_boost) { - start.set_boost_tick(state.tick); - break; + for (AltosTelemetry telem : telems) { + telem.provide_data(l, cal_data); + if (l.cal_data_complete()) + break; } + System.out.printf("Telemetry boost tick %d\n", cal_data.boost_tick); } + return cal_data; } - public Iterator iterator() { - AltosState state = start.clone(); - Iterator i = telems.iterator(); + public void capture_series(AltosDataListener listener) { + AltosCalData cal_data = cal_data(); - while (i.hasNext() && !state.valid()) { - AltosTelemetry t = i.next(); - t.update_state(state); - state.finish_update(); + for (AltosTelemetry telem : telems) { + int tick = telem.tick(); + cal_data.set_tick(tick); + if (cal_data.time() >= -1) + telem.provide_data(listener, cal_data); } - return new AltosTelemetryIterator(state, i); + } + + public AltosTelemetryFile(FileInputStream input) { + telems = new AltosTelemetryIterable(input); } } diff --git a/altoslib/AltosTelemetryLegacy.java b/altoslib/AltosTelemetryLegacy.java index 2907f111..394d023c 100644 --- a/altoslib/AltosTelemetryLegacy.java +++ b/altoslib/AltosTelemetryLegacy.java @@ -548,23 +548,25 @@ public class AltosTelemetryLegacy extends AltosTelemetry { } } - public void update_state(AltosState state) { - state.set_tick(tick); - state.set_state(this.state); - state.set_flight(flight); - state.set_serial(serial); - state.set_rssi(rssi, status); - - state.set_pressure(AltosConvert.barometer_to_pressure(pres)); - state.set_accel_g(accel_plus_g, accel_minus_g); - state.set_accel(accel); + public void provide_data(AltosDataListener listener, AltosCalData cal_data) { + cal_data.set_tick(tick); + listener.set_time(cal_data.time()); + listener.set_state(this.state); + cal_data.set_state(this.state); + cal_data.set_flight(flight); + cal_data.set_serial(serial); + listener.set_rssi(rssi, status); + + listener.set_pressure(AltosConvert.barometer_to_pressure(pres)); + cal_data.set_accel_plus_minus(accel_plus_g, accel_minus_g); + listener.set_acceleration(cal_data.acceleration(accel)); if (kalman_height != AltosLib.MISSING) - state.set_kalman(kalman_height, kalman_speed, kalman_acceleration); - state.set_temperature(AltosConvert.thermometer_to_temperature(temp)); - state.set_battery_voltage(AltosConvert.cc_battery_to_voltage(batt)); - state.set_apogee_voltage(AltosConvert.cc_ignitor_to_voltage(apogee)); - state.set_main_voltage(AltosConvert.cc_ignitor_to_voltage(main)); + listener.set_kalman(kalman_height, kalman_speed, kalman_acceleration); + listener.set_temperature(AltosConvert.thermometer_to_temperature(temp)); + listener.set_battery_voltage(AltosConvert.cc_battery_to_voltage(batt)); + listener.set_apogee_voltage(AltosConvert.cc_ignitor_to_voltage(apogee)); + listener.set_main_voltage(AltosConvert.cc_ignitor_to_voltage(main)); if (gps != null) - state.set_gps(gps, gps_sequence); + listener.set_gps(gps); } } diff --git a/altoslib/AltosTelemetryLocation.java b/altoslib/AltosTelemetryLocation.java index 8ad23ab6..5eb727d6 100644 --- a/altoslib/AltosTelemetryLocation.java +++ b/altoslib/AltosTelemetryLocation.java @@ -49,9 +49,10 @@ public class AltosTelemetryLocation extends AltosTelemetryStandard { super(bytes); } - public void update_state(AltosState state) { - super.update_state(state); - AltosGPS gps = state.make_temp_gps(false); + public void provide_data(AltosDataListener listener, AltosCalData cal_data) { + super.provide_data(listener, cal_data); + + AltosGPS gps = new AltosGPS(); int flags = flags(); gps.nsat = flags & 0xf; @@ -74,7 +75,10 @@ public class AltosTelemetryLocation extends AltosTelemetryStandard { gps.pdop = pdop() / 10.0; gps.hdop = hdop() / 10.0; gps.vdop = vdop() / 10.0; + + if (gps.nsat >= 4) + cal_data.set_gps_altitude(gps.alt); } - state.set_temp_gps(); + listener.set_gps(gps); } } diff --git a/altoslib/AltosTelemetryMegaData.java b/altoslib/AltosTelemetryMegaData.java index 916f1e94..c0749e87 100644 --- a/altoslib/AltosTelemetryMegaData.java +++ b/altoslib/AltosTelemetryMegaData.java @@ -39,34 +39,34 @@ public class AltosTelemetryMegaData extends AltosTelemetryStandard { super(bytes); } - public void update_state(AltosState state) { - super.update_state(state); + public void provide_data(AltosDataListener listener, AltosCalData cal_data) { + super.provide_data(listener, cal_data); - state.set_state(state()); + listener.set_state(state()); + cal_data.set_state(state()); - state.set_battery_voltage(AltosConvert.mega_battery_voltage(v_batt())); - state.set_pyro_voltage(AltosConvert.mega_pyro_voltage(v_pyro())); + listener.set_battery_voltage(AltosConvert.mega_battery_voltage(v_batt())); + listener.set_pyro_voltage(AltosConvert.mega_pyro_voltage(v_pyro())); - state.set_apogee_voltage(AltosConvert.mega_pyro_voltage(sense(4))); - state.set_main_voltage(AltosConvert.mega_pyro_voltage(sense(5))); + listener.set_apogee_voltage(AltosConvert.mega_pyro_voltage(sense(4))); + listener.set_main_voltage(AltosConvert.mega_pyro_voltage(sense(5))); double voltages[] = new double[4]; for (int i = 0; i < 4; i++) voltages[i] = AltosConvert.mega_pyro_voltage(sense(i)); - state.set_ignitor_voltage(voltages); + listener.set_ignitor_voltage(voltages); - state.set_ground_accel(ground_accel()); - state.set_ground_pressure(ground_pres()); - state.set_accel_g(accel_plus_g(), accel_minus_g()); + cal_data.set_ground_accel(ground_accel()); + cal_data.set_ground_pressure(ground_pres()); + cal_data.set_accel_plus_minus(accel_plus_g(), accel_minus_g()); /* Fill in the high bits of height from recent GPS * data if available, otherwise guess using the * previous kalman height */ - state.set_kalman(extend_height(state, height_16()), - speed()/16.0, acceleration() / 16.0); + listener.set_kalman(height_16(), speed()/16.0, acceleration() / 16.0); } } diff --git a/altoslib/AltosTelemetryMegaSensor.java b/altoslib/AltosTelemetryMegaSensor.java index bf560e92..396bdb16 100644 --- a/altoslib/AltosTelemetryMegaSensor.java +++ b/altoslib/AltosTelemetryMegaSensor.java @@ -41,22 +41,41 @@ public class AltosTelemetryMegaSensor extends AltosTelemetryStandard { super(bytes); } - public void update_state(AltosState state) { - super.update_state(state); + public void provide_data(AltosDataListener listener, AltosCalData cal_data) { + super.provide_data(listener, cal_data); - state.set_accel(accel()); - state.set_pressure(pres()); - state.set_temperature(temp() / 100.0); + listener.set_acceleration(cal_data.acceleration(accel())); + listener.set_pressure(pres()); + listener.set_temperature(temp() / 100.0); - state.set_orient(orient()); + listener.set_orient(orient()); - state.set_imu(new AltosIMU(accel_y(), /* along */ - accel_x(), /* across */ - accel_z(), /* through */ - gyro_y(), /* along */ - gyro_x(), /* across */ - gyro_z())); /* through */ + /* XXX we have no calibration data for these values */ - state.set_mag(new AltosMag(mag_x(), mag_y(), mag_z())); + if (cal_data.accel_zero_along == AltosLib.MISSING) + cal_data.set_accel_zero(0, 0, 0); + if (cal_data.gyro_zero_roll == AltosLib.MISSING) + cal_data.set_gyro_zero(0, 0, 0); + + int accel_along = accel_y(); + int accel_across = accel_x(); + int accel_through = accel_z(); + int gyro_roll = gyro_y(); + int gyro_pitch = gyro_x(); + int gyro_yaw = gyro_z(); + + int mag_along = mag_x(); + int mag_across = mag_y(); + int mag_through = mag_z(); + + listener.set_accel(cal_data.accel_along(accel_along), + cal_data.accel_across(accel_across), + cal_data.accel_through(accel_through)); + listener.set_gyro(cal_data.gyro_roll(gyro_roll), + cal_data.gyro_pitch(gyro_pitch), + cal_data.gyro_yaw(gyro_yaw)); + listener.set_mag(cal_data.mag_along(mag_along), + cal_data.mag_across(mag_across), + cal_data.mag_through(mag_through)); } } diff --git a/altoslib/AltosTelemetryMetrumData.java b/altoslib/AltosTelemetryMetrumData.java index 7ba591ed..21c60c75 100644 --- a/altoslib/AltosTelemetryMetrumData.java +++ b/altoslib/AltosTelemetryMetrumData.java @@ -30,9 +30,9 @@ public class AltosTelemetryMetrumData extends AltosTelemetryStandard { super(bytes); } - public void update_state(AltosState state) { - state.set_ground_accel(ground_accel()); - state.set_accel_g(accel_plus_g(), accel_minus_g()); - state.set_ground_pressure(ground_pres()); + public void provide_data(AltosDataListener listener, AltosCalData cal_data) { + cal_data.set_ground_accel(ground_accel()); + cal_data.set_accel_plus_minus(accel_plus_g(), accel_minus_g()); + cal_data.set_ground_pressure(ground_pres()); } } diff --git a/altoslib/AltosTelemetryMetrumSensor.java b/altoslib/AltosTelemetryMetrumSensor.java index e666f4ec..e003c831 100644 --- a/altoslib/AltosTelemetryMetrumSensor.java +++ b/altoslib/AltosTelemetryMetrumSensor.java @@ -38,21 +38,21 @@ public class AltosTelemetryMetrumSensor extends AltosTelemetryStandard { super(bytes); } - public void update_state(AltosState state) { - super.update_state(state); + public void provide_data(AltosDataListener listener, AltosCalData cal_data) { + super.provide_data(listener, cal_data); - state.set_state(state()); + listener.set_state(state()); + cal_data.set_state(state()); - state.set_accel(accel()); - state.set_pressure(pres()); - state.set_temperature(temp()/100.0); + listener.set_acceleration(cal_data.acceleration(accel())); + listener.set_pressure(pres()); + listener.set_temperature(temp()/100.0); - state.set_kalman(extend_height(state, height_16()), - speed()/16.0, acceleration()/16.0); + listener.set_kalman(height_16(), speed()/16.0, acceleration()/16.0); - state.set_battery_voltage(AltosConvert.mega_battery_voltage(v_batt())); + listener.set_battery_voltage(AltosConvert.mega_battery_voltage(v_batt())); - state.set_apogee_voltage(AltosConvert.mega_pyro_voltage(sense_a())); - state.set_main_voltage(AltosConvert.mega_pyro_voltage(sense_m())); + listener.set_apogee_voltage(AltosConvert.mega_pyro_voltage(sense_a())); + listener.set_main_voltage(AltosConvert.mega_pyro_voltage(sense_m())); } } diff --git a/altoslib/AltosTelemetryMini2.java b/altoslib/AltosTelemetryMini2.java index bc151139..02d1c757 100644 --- a/altoslib/AltosTelemetryMini2.java +++ b/altoslib/AltosTelemetryMini2.java @@ -40,20 +40,21 @@ public class AltosTelemetryMini2 extends AltosTelemetryStandard { super(bytes); } - public void update_state(AltosState state) { - super.update_state(state); + public void provide_data(AltosDataListener listener, AltosCalData cal_data) { + super.provide_data(listener, cal_data); - state.set_state(state()); + listener.set_state(state()); + cal_data.set_state(state()); - state.set_battery_voltage(AltosConvert.tele_mini_2_voltage(v_batt())); - state.set_apogee_voltage(AltosConvert.tele_mini_2_voltage(sense_a())); - state.set_main_voltage(AltosConvert.tele_mini_2_voltage(sense_m())); + listener.set_battery_voltage(AltosConvert.tele_mini_2_voltage(v_batt())); + listener.set_apogee_voltage(AltosConvert.tele_mini_2_voltage(sense_a())); + listener.set_main_voltage(AltosConvert.tele_mini_2_voltage(sense_m())); - state.set_ground_pressure(ground_pres()); + cal_data.set_ground_pressure(ground_pres()); - state.set_pressure(pres()); - state.set_temperature(temp()/100.0); + listener.set_pressure(pres()); + listener.set_temperature(temp()/100.0); - state.set_kalman(height(), speed()/16.0, acceleration()/16.0); + listener.set_kalman(height(), speed()/16.0, acceleration()/16.0); } } diff --git a/altoslib/AltosTelemetryMini3.java b/altoslib/AltosTelemetryMini3.java index b8a507cc..1d627668 100644 --- a/altoslib/AltosTelemetryMini3.java +++ b/altoslib/AltosTelemetryMini3.java @@ -40,22 +40,22 @@ public class AltosTelemetryMini3 extends AltosTelemetryStandard { super(bytes); } - public void update_state(AltosState state) { - super.update_state(state); + public void provide_data(AltosDataListener listener, AltosCalData cal_data) { + super.provide_data(listener, cal_data); - state.set_state(state()); + cal_data.set_ground_pressure(ground_pres()); - state.set_battery_voltage(AltosConvert.tele_mini_3_battery_voltage(v_batt())); + listener.set_state(state()); + cal_data.set_state(state()); - state.set_apogee_voltage(AltosConvert.tele_mini_3_pyro_voltage(sense_a())); - state.set_main_voltage(AltosConvert.tele_mini_3_pyro_voltage(sense_m())); + listener.set_battery_voltage(AltosConvert.tele_mini_3_battery_voltage(v_batt())); - state.set_pressure(pres()); - state.set_temperature(temp()/100.0); + listener.set_apogee_voltage(AltosConvert.tele_mini_3_pyro_voltage(sense_a())); + listener.set_main_voltage(AltosConvert.tele_mini_3_pyro_voltage(sense_m())); - state.set_kalman(extend_height(state, height_16()), - speed()/16.0, acceleration()/16.0); + listener.set_pressure(pres()); + listener.set_temperature(temp()/100.0); - state.set_ground_pressure(ground_pres()); + listener.set_kalman(height_16(), speed()/16.0, acceleration()/16.0); } } diff --git a/altoslib/AltosTelemetryRaw.java b/altoslib/AltosTelemetryRaw.java index 12c4623b..a7d3a2ca 100644 --- a/altoslib/AltosTelemetryRaw.java +++ b/altoslib/AltosTelemetryRaw.java @@ -23,7 +23,7 @@ public class AltosTelemetryRaw extends AltosTelemetryStandard { super(bytes); } - public void update_state(AltosState state) { - super.update_state(state); + public void provide_data(AltosDataListener listener, AltosCalData cal_data) { + super.provide_data(listener, cal_data); } } diff --git a/altoslib/AltosTelemetryReader.java b/altoslib/AltosTelemetryReader.java index 6a93c2c3..96113613 100644 --- a/altoslib/AltosTelemetryReader.java +++ b/altoslib/AltosTelemetryReader.java @@ -28,7 +28,8 @@ public class AltosTelemetryReader extends AltosFlightReader { double frequency; int telemetry; int telemetry_rate; - AltosState state = null; + public AltosState state = null; + public AltosCalData cal_data = null; LinkedBlockingQueue telem; @@ -40,11 +41,11 @@ public class AltosTelemetryReader extends AltosFlightReader { throw new IOException("IO error"); } while (!link.get_monitor()); AltosTelemetry telem = AltosTelemetry.parse(l.line); + if (cal_data == null) + cal_data = new AltosCalData(); if (state == null) - state = new AltosState(); - else - state = state.clone(); - telem.update_state(state); + state = new AltosState(cal_data); + telem.provide_data(state, cal_data); return state; } @@ -55,6 +56,7 @@ public class AltosTelemetryReader extends AltosFlightReader { public void reset() { flush(); state = null; + cal_data = null; } public void close(boolean interrupted) { diff --git a/altoslib/AltosTelemetryRecordSet.java b/altoslib/AltosTelemetryRecordSet.java new file mode 100644 index 00000000..0cb95261 --- /dev/null +++ b/altoslib/AltosTelemetryRecordSet.java @@ -0,0 +1,97 @@ +/* + * Copyright © 2017 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, either version 2 of the License, or + * (at your option) any later version. + * + * 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. + */ + +package org.altusmetrum.altoslib_11; + +import java.io.*; +import java.util.*; + +public class AltosTelemetryRecordSet implements AltosRecordSet { + AltosTelemetry telemetry; + TreeSet ordered; + + public void capture_series(AltosDataListener series) { + for (AltosTelemetryRecord record : ordered) { + record.update_state(series); + } + } + + public AltosTelemetryRecordSet(AltosTelemetry telemetry) { + this.telemetry = telemetry; + + AltosTelemetryRecord record = null; + + switch (config_data.log_format) { + case AltosLib.AO_LOG_FORMAT_FULL: + record = new AltosTelemetryRecordFull(eeprom); + break; + case AltosLib.AO_LOG_FORMAT_TINY: + record = new AltosTelemetryRecordTiny(eeprom); + break; + case AltosLib.AO_LOG_FORMAT_TELEMETRY: + case AltosLib.AO_LOG_FORMAT_TELESCIENCE: + case AltosLib.AO_LOG_FORMAT_TELEMEGA: + case AltosLib.AO_LOG_FORMAT_TELEMEGA_OLD: + record = new AltosTelemetryRecordMega(eeprom); + break; + case AltosLib.AO_LOG_FORMAT_TELEMETRUM: + record = new AltosTelemetryRecordMetrum(eeprom); + break; + case AltosLib.AO_LOG_FORMAT_TELEMINI2: + case AltosLib.AO_LOG_FORMAT_TELEMINI3: + case AltosLib.AO_LOG_FORMAT_EASYMINI: + record = new AltosTelemetryRecordMini(eeprom); + break; + case AltosLib.AO_LOG_FORMAT_TELEGPS: + record = new AltosTelemetryRecordGps(eeprom); + break; + case AltosLib.AO_LOG_FORMAT_TELEFIRETWO: + record = new AltosTelemetryRecordFireTwo(eeprom); + break; + } + + if (record == null) { + System.out.printf("failed to parse log format %d\n", config_data.log_format); + return; + } + ordered = new TreeSet(); + int tick = 0; + boolean first = true; + + start_state = new AltosState(); + start_state.set_config_data(record.eeprom.config_data()); + + for (;;) { + int t = record.tick(); + + if (first) { + tick = t; + first = false; + } else { + while (t < tick - 32767) + t += 65536; + tick = t; + } + record.wide_tick = tick; + ordered.add(record); + if (!record.hasNext()) + break; + record = record.next(); + } + } + + public AltosTelemetryRecordSet(Reader input) throws IOException { + this(new AltosTelemetryNew(input)); + } +} diff --git a/altoslib/AltosTelemetrySatellite.java b/altoslib/AltosTelemetrySatellite.java index ce12d32d..72ddd964 100644 --- a/altoslib/AltosTelemetrySatellite.java +++ b/altoslib/AltosTelemetrySatellite.java @@ -44,12 +44,12 @@ public class AltosTelemetrySatellite extends AltosTelemetryStandard { super(bytes); } - public void update_state(AltosState state) { - super.update_state(state); + public void provide_data(AltosDataListener listener, AltosCalData cal_data) { + super.provide_data(listener, cal_data); - AltosGPS gps = state.make_temp_gps(true); + AltosGPS gps = new AltosGPS(); gps.cc_gps_sat = sats(); - state.set_temp_gps(); + listener.set_gps(gps); } } diff --git a/altoslib/AltosTelemetrySensor.java b/altoslib/AltosTelemetrySensor.java index b669b9e6..37589397 100644 --- a/altoslib/AltosTelemetrySensor.java +++ b/altoslib/AltosTelemetrySensor.java @@ -41,24 +41,26 @@ public class AltosTelemetrySensor extends AltosTelemetryStandard { super(bytes); } - public void update_state(AltosState state) { - super.update_state(state); + public void provide_data(AltosDataListener listener, AltosCalData cal_data) { + super.provide_data(listener, cal_data); + + listener.set_state(state()); + cal_data.set_state(state()); - state.set_state(state()); if (type() == packet_type_TM_sensor) { - state.set_ground_accel(ground_accel()); - state.set_accel_g(accel_plus_g(), accel_minus_g()); - state.set_accel(accel()); + cal_data.set_ground_accel(ground_accel()); + cal_data.set_accel_plus_minus(accel_plus_g(), accel_minus_g()); + listener.set_acceleration(cal_data.acceleration(accel())); } - state.set_ground_pressure(AltosConvert.barometer_to_pressure(ground_pres())); - state.set_pressure(AltosConvert.barometer_to_pressure(pres())); - state.set_temperature(AltosConvert.thermometer_to_temperature(temp())); - state.set_battery_voltage(AltosConvert.cc_battery_to_voltage(v_batt())); + cal_data.set_ground_pressure(AltosConvert.barometer_to_pressure(ground_pres())); + listener.set_pressure(AltosConvert.barometer_to_pressure(pres())); + listener.set_temperature(AltosConvert.thermometer_to_temperature(temp())); + listener.set_battery_voltage(AltosConvert.cc_battery_to_voltage(v_batt())); if (type() == packet_type_TM_sensor || type() == packet_type_Tm_sensor) { - state.set_apogee_voltage(AltosConvert.cc_ignitor_to_voltage(sense_d())); - state.set_main_voltage(AltosConvert.cc_ignitor_to_voltage(sense_m())); + listener.set_apogee_voltage(AltosConvert.cc_ignitor_to_voltage(sense_d())); + listener.set_main_voltage(AltosConvert.cc_ignitor_to_voltage(sense_m())); } - state.set_kalman(height_16(), speed()/16.0, acceleration()/16.0); + listener.set_kalman(height_16(), speed()/16.0, acceleration()/16.0); } } diff --git a/altoslib/AltosTelemetryStandard.java b/altoslib/AltosTelemetryStandard.java index 1718e4b7..4429c49a 100644 --- a/altoslib/AltosTelemetryStandard.java +++ b/altoslib/AltosTelemetryStandard.java @@ -104,7 +104,7 @@ public abstract class AltosTelemetryStandard extends AltosTelemetry { super(bytes); } - public void update_state(AltosState state) { - super.update_state(state); + public void provide_data(AltosDataListener listener, AltosCalData cal_data) { + super.provide_data(listener, cal_data); } } diff --git a/altoslib/AltosTimeSeries.java b/altoslib/AltosTimeSeries.java index 0ea7b356..1d3d9a6c 100644 --- a/altoslib/AltosTimeSeries.java +++ b/altoslib/AltosTimeSeries.java @@ -21,68 +21,142 @@ public class AltosTimeSeries implements Iterable { public AltosUnits units; List values; - public void add(double x, double y) { - values.add(new AltosTimeValue(x, y)); + public void add(AltosTimeValue tv) { + values.add(tv); + } + + public void add(double time, double value) { + add(new AltosTimeValue(time, value)); + } + + public AltosTimeValue get(int i) { + return values.get(i); + } + + public int size() { + return values.size(); } public Iterator iterator() { return values.iterator(); } - public void integrate(AltosTimeSeries integral) { - double y = 0.0; - double x = 0.0; + public double max() { + double max = AltosLib.MISSING; + for (AltosTimeValue tv : values) { + if (max == AltosLib.MISSING || tv.value > max) + max = tv.value; + } + return max; + } + + public double min() { + double min = AltosLib.MISSING; + for (AltosTimeValue tv : values) { + if (min == AltosLib.MISSING || tv.value < min) + min = tv.value; + } + return min; + } + + public AltosTimeSeries integrate(AltosTimeSeries integral) { + double value = 0.0; + double pvalue = 0.0; + double time = 0.0; boolean start = true; for (AltosTimeValue v : values) { if (start) { - y = 0.0; - x = v.x; + value = 0.0; start = false; } else { - y += v.y * (v.x - x); - x = v.x; + value += (pvalue + v.value) / 2.0 * (v.time - time); } - integral.add(x, y); + pvalue = v.value; + time = v.time; +// System.out.printf("%g %g %g\n", time, v.value, value); + integral.add(time, value); + } + return integral; } - public void differentiate(AltosTimeSeries diff) { - double y = 0.0; - double x = 0.0; + public AltosTimeSeries differentiate(AltosTimeSeries diff) { + double value = 0.0; + double time = 0.0; boolean start = true; for (AltosTimeValue v: values) { if (start) { - y = 0.0; - x = v.x; + value = v.value; + time = v.time; start = false; } else { - double dx = v.x - x; - double dy = v.y - y; + double dx = v.time - time; + double dy = v.value - value; - x = v.x; - y = v.y; if (dx != 0) - diff.add(x, dy); + diff.add(time, dy/dx); + + time = v.time; + value = v.value; } } + return diff; } private int find_left(int i, double dt) { int j; - double t = values.get(i).x - dt; - for (j = i; j > 0; j--) { - if (values.get(j).x < t) + double t = values.get(i).time - dt; + for (j = i; j >= 0; j--) { + if (values.get(j).time < t) + break; + } + return j + 1; + + } + + private int find_right(int i, double dt) { + int j; + double t = values.get(i).time + dt; + for (j = i; j < values.size(); j++) { + if (values.get(j).time > t) break; } - return j; + return j - 1; } - public void filter(AltosTimeSeries out, double width) { + private double filter_coeff(double dist, double width) { + double ratio = dist / (width / 2); + + return Math.cos(ratio * Math.PI / 2); + } + + public AltosTimeSeries filter(AltosTimeSeries f, double width) { + double half_width = width/2; for (int i = 0; i < values.size(); i++) { + double center_time = values.get(i).time; + double left_time = center_time - half_width; + double right_time = center_time + half_width; + double total_coeff = 0.0; + double total_value = 0.0; + + int left = find_left(i, half_width); + int right = find_right(i, half_width); + for (int j = left; j <= right; j++) { + double j_time = values.get(j).time; + + if (left_time <= j_time && j_time <= right_time) { + double coeff = filter_coeff(j_time - center_time, width); + total_coeff += coeff; + total_value += coeff * values.get(j).value; + } + } + if (total_coeff != 0.0) + f.add(center_time, total_value / total_coeff); } + return f; } public AltosTimeSeries(String label, AltosUnits units) { diff --git a/altoslib/AltosTimeValue.java b/altoslib/AltosTimeValue.java index 50212361..489050f2 100644 --- a/altoslib/AltosTimeValue.java +++ b/altoslib/AltosTimeValue.java @@ -18,10 +18,11 @@ package org.altusmetrum.altoslib_11; public class AltosTimeValue { - public double x, y; + public double time; + public double value; - public AltosTimeValue(double x, double y) { - this.x = x; - this.y = y; + public AltosTimeValue(double time, double value) { + this.time = time; + this.value = value; } } diff --git a/altoslib/AltosUnits.java b/altoslib/AltosUnits.java index 717a106a..7744cdb4 100644 --- a/altoslib/AltosUnits.java +++ b/altoslib/AltosUnits.java @@ -41,6 +41,10 @@ public abstract class AltosUnits { public abstract double inverse(double v, boolean imperial_units); + public String string_value(double v, boolean imperial_units) { + return new Double(value(v, imperial_units)).toString(); + } + public abstract String show_units(boolean imperial_units); public abstract String say_units(boolean imperial_units); @@ -113,6 +117,10 @@ public abstract class AltosUnits { return say_units(v, AltosConvert.imperial_units); } + public String string_value(double v) { + return string_value(v, AltosConvert.imperial_units); + } + /* Parsing functions. Use the first range of the type */ public String parse_units(boolean imperial_units) { return first_range(imperial_units).show_units; diff --git a/altoslib/AltosWriter.java b/altoslib/AltosWriter.java index 691dc4de..717f1a8f 100644 --- a/altoslib/AltosWriter.java +++ b/altoslib/AltosWriter.java @@ -20,7 +20,7 @@ package org.altusmetrum.altoslib_11; public interface AltosWriter { - public void write(AltosStateIterable states); + public void write(AltosFlightSeries series); public void close(); } diff --git a/altoslib/Makefile.am b/altoslib/Makefile.am index 1b37215c..fa0e8c1b 100644 --- a/altoslib/Makefile.am +++ b/altoslib/Makefile.am @@ -26,6 +26,7 @@ record_files = \ altoslib_JAVA = \ AltosLib.java \ + AltosCalData.java \ AltosCompanion.java \ AltosConfigData.java \ AltosConfigDataException.java \ @@ -55,13 +56,15 @@ altoslib_JAVA = \ AltosFile.java \ AltosFlash.java \ AltosFlashListener.java \ - AltosFlightListener.java \ + AltosDataListener.java \ + AltosDataProvider.java \ AltosFlightSeries.java \ AltosFlightReader.java \ AltosFlightStats.java \ AltosForce.java \ AltosFrequency.java \ AltosGPS.java \ + AltosGPSTimeValue.java \ AltosGPSSat.java \ AltosGreatCircle.java \ AltosHexfile.java \ @@ -85,6 +88,7 @@ altoslib_JAVA = \ AltosOrient.java \ AltosParse.java \ AltosPressure.java \ + AltosPresTemp.java \ AltosPreferences.java \ AltosPreferencesBackend.java \ AltosProgrammer.java \ @@ -101,8 +105,7 @@ altoslib_JAVA = \ AltosSensorMetrum.java \ AltosSensorTGPS.java \ AltosState.java \ - AltosStateIterable.java \ - AltosStateUpdate.java \ + AltosStateName.java \ AltosTelemetry.java \ AltosTelemetryConfiguration.java \ AltosTelemetryCompanion.java \ -- cgit v1.2.3 From 222158581887b5f9e8b9843d14321c313fa023fa Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 25 May 2017 22:36:05 -0700 Subject: altoslib/altosuilib/altosui: More work towards using AltosFlightSeries for analysis Graphing and CSV seem complete now; stats still missing lots of stuff. Signed-off-by: Keith Packard --- altoslib/AltosCSV.java | 68 ++++--- altoslib/AltosCalData.java | 11 +- altoslib/AltosConvert.java | 6 +- altoslib/AltosDataListener.java | 2 +- altoslib/AltosDistance.java | 2 +- altoslib/AltosEepromDownload.java | 2 +- altoslib/AltosEepromNew.java | 3 +- altoslib/AltosEepromRecord.java | 2 +- altoslib/AltosEepromRecordFull.java | 4 +- altoslib/AltosEepromRecordMega.java | 3 +- altoslib/AltosFlightListener.java | 2 +- altoslib/AltosFlightSeries.java | 211 +++++++++++++++++--- altoslib/AltosFlightStats.java | 6 +- altoslib/AltosLib.java | 2 +- altoslib/AltosMapLine.java | 32 +-- altoslib/AltosPyroName.java | 32 +++ altoslib/AltosSensorMega.java | 6 +- altoslib/AltosSensorTM.java | 4 +- altoslib/AltosState.java | 8 +- altoslib/AltosTelemetryFile.java | 4 +- altoslib/AltosTelemetryLegacy.java | 4 +- altoslib/AltosTelemetryLocation.java | 8 +- altoslib/AltosTelemetryMegaData.java | 2 +- altoslib/AltosTelemetrySensor.java | 4 +- altoslib/AltosTimeSeries.java | 65 +++++- altoslib/Makefile.am | 1 + altosui/AltosFlightUI.java | 22 +- altosui/AltosGraphUI.java | 9 +- altosui/AltosIdleMonitorUI.java | 24 +-- altosui/AltosIgnitor.java | 42 ++-- altosui/AltosUI.java | 2 +- altosuilib/AltosGraphNew.java | 377 +++++++++++------------------------ altosuilib/AltosUIFlightSeries.java | 15 +- altosuilib/AltosUITimeSeries.java | 15 +- 34 files changed, 555 insertions(+), 445 deletions(-) create mode 100644 altoslib/AltosPyroName.java (limited to 'altoslib/Makefile.am') diff --git a/altoslib/AltosCSV.java b/altoslib/AltosCSV.java index 0cfe4c94..38afdc64 100644 --- a/altoslib/AltosCSV.java +++ b/altoslib/AltosCSV.java @@ -192,31 +192,42 @@ public class AltosCSV implements AltosWriter { out.printf("accel_x,accel_y,accel_z,gyro_x,gyro_y,gyro_z,mag_x,mag_y,mag_z"); } + double accel_along() { return series.value(AltosFlightSeries.accel_along_name, indices); } + double accel_across() { return series.value(AltosFlightSeries.accel_across_name, indices); } + double accel_through() { return series.value(AltosFlightSeries.accel_through_name, indices); } + + double gyro_roll() { return series.value(AltosFlightSeries.gyro_roll_name, indices); } + double gyro_pitch() { return series.value(AltosFlightSeries.gyro_pitch_name, indices); } + double gyro_yaw() { return series.value(AltosFlightSeries.gyro_yaw_name, indices); } + + double mag_along() { return series.value(AltosFlightSeries.mag_along_name, indices); } + double mag_across() { return series.value(AltosFlightSeries.mag_across_name, indices); } + double mag_through() { return series.value(AltosFlightSeries.mag_through_name, indices); } + void write_advanced() { -/* out.printf("%7.2f,%7.2f,%7.2f,%7.2f,%7.2f,%7.2f,%7.2f,%7.2f,%7.2f", - state.accel_along(), state.accel_across(), state.accel_through(), - state.gyro_roll(), state.gyro_pitch(), state.gyro_yaw(), - state.mag_along(), state.mag_across(), state.mag_through()); -*/ + accel_along(), accel_across(), accel_through(), + gyro_roll(), gyro_pitch(), gyro_yaw(), + mag_along(), mag_across(), mag_through()); } void write_gps_header() { -/* out.printf("connected,locked,nsat,latitude,longitude,altitude,year,month,day,hour,minute,second,pad_dist,pad_range,pad_az,pad_el,pdop,hdop,vdop"); -*/ } void write_gps() { -/* - AltosGPS gps = state.gps; - if (gps == null) - gps = new AltosGPS(); + AltosGPS gps = series.gps_before(series.time(indices)); - AltosGreatCircle from_pad = state.from_pad; - if (from_pad == null) + AltosGreatCircle from_pad; + + if (series.cal_data.gps_pad != null && gps != null) + from_pad = new AltosGreatCircle(series.cal_data.gps_pad, gps); + else from_pad = new AltosGreatCircle(); + if (gps == null) + gps = new AltosGPS(); + out.printf("%2d,%2d,%3d,%12.7f,%12.7f,%8.1f,%5d,%3d,%3d,%3d,%3d,%3d,%9.0f,%9.0f,%4.0f,%4.0f,%6.1f,%6.1f,%6.1f", gps.connected?1:0, gps.locked?1:0, @@ -231,13 +242,12 @@ public class AltosCSV implements AltosWriter { gps.minute, gps.second, from_pad.distance, - state.range, + from_pad.range, from_pad.bearing, - state.elevation, + from_pad.elevation, gps.pdop, gps.hdop, gps.vdop); -*/ } void write_gps_sat_header() { @@ -249,8 +259,7 @@ public class AltosCSV implements AltosWriter { } void write_gps_sat() { -/* - AltosGPS gps = state.gps; + AltosGPS gps = series.gps_before(series.time(indices)); for(int i = 1; i <= 32; i++) { int c_n0 = 0; if (gps != null && gps.cc_gps_sat != null) { @@ -264,13 +273,14 @@ public class AltosCSV implements AltosWriter { if (i != 32) out.printf(","); } -*/ } void write_companion_header() { +/* out.printf("companion_id,companion_time,companion_update,companion_channels"); for (int i = 0; i < 12; i++) out.printf(",companion_%02d", i); +*/ } void write_companion() { @@ -401,16 +411,16 @@ public class AltosCSV implements AltosWriter { has_battery = true; if (series.has_series(AltosFlightSeries.accel_across_name)) has_advanced = true; -/* - if (state.gps != null) { - has_gps = true; - if (state.gps.cc_gps_sat != null) - has_gps_sat = true; - } - if (state.companion != null) - has_companion = true; - } -*/ + + if (series.gps_series != null) + has_gps = true; + if (series.sats_in_view != null) + has_gps_sat = true; + /* + if (state.companion != null) + has_companion = true; + */ + indices = series.indices(); for (;;) { diff --git a/altoslib/AltosCalData.java b/altoslib/AltosCalData.java index 58d34abe..3da0e400 100644 --- a/altoslib/AltosCalData.java +++ b/altoslib/AltosCalData.java @@ -204,12 +204,11 @@ public class AltosCalData { this.state = state; } - public double gps_ground_altitude = AltosLib.MISSING; + public AltosGPS gps_pad = null; - public void set_gps_altitude(double altitude) { - if ((state != AltosLib.MISSING && state < AltosLib.ao_flight_boost) || - gps_ground_altitude == AltosLib.MISSING) - gps_ground_altitude = altitude; + public void set_gps(AltosGPS gps) { + if ((state != AltosLib.MISSING && state < AltosLib.ao_flight_boost) || gps_pad == null) + gps_pad = gps; } /* @@ -226,7 +225,7 @@ public class AltosCalData { public void reset_temp_gps() { if (temp_gps != null) { if (temp_gps.locked && temp_gps.nsat >= 4) - set_gps_altitude(temp_gps.alt); + set_gps(temp_gps); } temp_gps = null; } diff --git a/altoslib/AltosConvert.java b/altoslib/AltosConvert.java index 95c1a99f..5b3ff391 100644 --- a/altoslib/AltosConvert.java +++ b/altoslib/AltosConvert.java @@ -191,7 +191,7 @@ public class AltosConvert { } public static double - cc_ignitor_to_voltage(double ignite) + cc_igniter_to_voltage(double ignite) { return ignite / 32767 * 15.0; } @@ -434,6 +434,10 @@ public class AltosConvert { public static AltosStateName state_name = new AltosStateName(); + public static AltosPyroName pyro_name = new AltosPyroName(); + + public static AltosUnits magnetic_field = null; + public static String show_gs(String format, double a) { a = meters_to_g(a); format = format.concat(" g"); diff --git a/altoslib/AltosDataListener.java b/altoslib/AltosDataListener.java index b644e817..4a6fe04d 100644 --- a/altoslib/AltosDataListener.java +++ b/altoslib/AltosDataListener.java @@ -59,7 +59,7 @@ public abstract class AltosDataListener { public abstract void set_accel(double along, double across, double through); public abstract void set_mag(double along, double across, double through); public abstract void set_pyro_voltage(double volts); - public abstract void set_ignitor_voltage(double[] voltage); + public abstract void set_igniter_voltage(double[] voltage); public abstract void set_pyro_fired(int pyro_mask); public abstract void set_companion(AltosCompanion companion); diff --git a/altoslib/AltosDistance.java b/altoslib/AltosDistance.java index 0239c5ce..5e1b3545 100644 --- a/altoslib/AltosDistance.java +++ b/altoslib/AltosDistance.java @@ -96,7 +96,7 @@ public class AltosDistance extends AltosUnits { } }; - range_imperial[1] = new AltosUnitsRange(AltosConvert.feet_to_meters(1000), + range_imperial[1] = new AltosUnitsRange(AltosConvert.feet_to_meters(5280), "mi", "miles") { double value(double v) { return AltosConvert.meters_to_miles(v); diff --git a/altoslib/AltosEepromDownload.java b/altoslib/AltosEepromDownload.java index 4e641b85..8a2053ec 100644 --- a/altoslib/AltosEepromDownload.java +++ b/altoslib/AltosEepromDownload.java @@ -59,7 +59,7 @@ class AltosEepromNameData extends AltosDataListener { public void set_accel(double along, double across, double through) { } public void set_mag(double along, double across, double through) { } public void set_pyro_voltage(double volts) { } - public void set_ignitor_voltage(double[] voltage) { } + public void set_igniter_voltage(double[] voltage) { } public void set_pyro_fired(int pyro_mask) { } public void set_companion(AltosCompanion companion) { } public void set_kalman(double height, double speed, double acceleration) { } diff --git a/altoslib/AltosEepromNew.java b/altoslib/AltosEepromNew.java index 5220f3a0..0da3df71 100644 --- a/altoslib/AltosEepromNew.java +++ b/altoslib/AltosEepromNew.java @@ -165,7 +165,8 @@ public class AltosEepromNew { int start = data.size(); if (config_data().log_format != AltosLib.AO_LOG_FORMAT_TINY) { - data.add((byte) tokens[0].codePointAt(0)); + byte cmd = (byte) tokens[0].codePointAt(0); + data.add(cmd); int time = AltosLib.fromhex(tokens[1]); diff --git a/altoslib/AltosEepromRecord.java b/altoslib/AltosEepromRecord.java index 08f7ebca..7dd37592 100644 --- a/altoslib/AltosEepromRecord.java +++ b/altoslib/AltosEepromRecord.java @@ -92,7 +92,7 @@ public abstract class AltosEepromRecord implements Comparable public int next_start() { int s = start + length; - while (s + length < eeprom.data.size()) { + while (s + length <= eeprom.data.size()) { if (valid(s)) return s; s += length; diff --git a/altoslib/AltosEepromRecordFull.java b/altoslib/AltosEepromRecordFull.java index ea81eb3d..b4968220 100644 --- a/altoslib/AltosEepromRecordFull.java +++ b/altoslib/AltosEepromRecordFull.java @@ -62,8 +62,8 @@ public class AltosEepromRecordFull extends AltosEepromRecord { listener.set_battery_voltage(AltosConvert.cc_battery_to_voltage(data16(2))); break; case AltosLib.AO_LOG_DEPLOY: - listener.set_apogee_voltage(AltosConvert.cc_ignitor_to_voltage(data16(0))); - listener.set_main_voltage(AltosConvert.cc_ignitor_to_voltage(data16(2))); + listener.set_apogee_voltage(AltosConvert.cc_igniter_to_voltage(data16(0))); + listener.set_main_voltage(AltosConvert.cc_igniter_to_voltage(data16(2))); break; case AltosLib.AO_LOG_STATE: listener.set_state(data16(0)); diff --git a/altoslib/AltosEepromRecordMega.java b/altoslib/AltosEepromRecordMega.java index 371810ab..d4a5a0b2 100644 --- a/altoslib/AltosEepromRecordMega.java +++ b/altoslib/AltosEepromRecordMega.java @@ -143,6 +143,7 @@ public class AltosEepromRecordMega extends AltosEepromRecord { ground_yaw() / 512.0); break; case AltosLib.AO_LOG_STATE: + System.out.printf("log state %s\n", AltosLib.state_name(state())); listener.set_state(state()); break; case AltosLib.AO_LOG_SENSOR: @@ -198,7 +199,7 @@ public class AltosEepromRecordMega extends AltosEepromRecord { for (int i = 0; i < nsense-2; i++) voltages[i] = AltosConvert.mega_pyro_voltage(sense(i)); - listener.set_ignitor_voltage(voltages); + listener.set_igniter_voltage(voltages); listener.set_pyro_fired(pyro()); break; case AltosLib.AO_LOG_GPS_TIME: diff --git a/altoslib/AltosFlightListener.java b/altoslib/AltosFlightListener.java index 5b478ed0..395d8f3f 100644 --- a/altoslib/AltosFlightListener.java +++ b/altoslib/AltosFlightListener.java @@ -130,7 +130,7 @@ public abstract class AltosFlightListener { public abstract void set_imu(AltosIMU imu); public abstract void set_mag(AltosMag mag); public abstract void set_pyro_voltage(double volts); - public abstract void set_ignitor_voltage(double[] voltage); + public abstract void set_igniter_voltage(double[] voltage); public abstract void set_pyro_fired(int pyro_mask); public void copy(AltosFlightListener old) { diff --git a/altoslib/AltosFlightSeries.java b/altoslib/AltosFlightSeries.java index b7434a5c..0eea34b7 100644 --- a/altoslib/AltosFlightSeries.java +++ b/altoslib/AltosFlightSeries.java @@ -23,12 +23,17 @@ public class AltosFlightSeries extends AltosDataListener { public int[] indices() { int[] indices = new int[series.size()]; for (int i = 0; i < indices.length; i++) - indices[i] = 0; + indices[i] = -1; + step_indices(indices); return indices; } private double time(int id, int index) { AltosTimeSeries s = series.get(id); + + if (index < 0) + return Double.NEGATIVE_INFINITY; + if (index < s.values.size()) return s.values.get(index).time; return Double.POSITIVE_INFINITY; @@ -69,8 +74,30 @@ public class AltosFlightSeries extends AltosDataListener { public double value(String name, int[] indices) { for (int i = 0; i < indices.length; i++) { AltosTimeSeries s = series.get(i); + if (s.label.equals(name)) { + int index = indices[i]; + if (index < 0) + index = 0; + if (index >= s.values.size()) + index = s.values.size() - 1; + return s.values.get(index).value; + } + } + return AltosLib.MISSING; + } + + public double value_before(String name, double time) { + for (AltosTimeSeries s : series) { if (s.label.equals(name)) - return s.values.get(indices[i]).value; + return s.value_before(time); + } + return AltosLib.MISSING; + } + + public double value_after(String name, double time) { + for (AltosTimeSeries s : series) { + if (s.label.equals(name)) + return s.value_after(time); } return AltosLib.MISSING; } @@ -105,11 +132,12 @@ public class AltosFlightSeries extends AltosDataListener { public static final String state_name = "State"; public void set_state(int state) { - this.state = state; if (state_series == null) state_series = add_series(state_name, AltosConvert.state_name); - else if ((int) state_series.get(state_series.size()-1).value == state) + else if (this.state == state) return; + System.out.printf("state %s\n", AltosLib.state_name(state)); + this.state = state; state_series.add(time(), state); } @@ -146,14 +174,14 @@ public class AltosFlightSeries extends AltosDataListener { AltosTimeSeries status_series; - public static final String status_name = "Status"; + public static final String status_name = "Radio Status"; public void set_rssi(int rssi, int status) { - if (rssi_series == null) + if (rssi_series == null) { rssi_series = add_series(rssi_name, null); - rssi_series.add(time(), rssi); - if (status_series == null) status_series = add_series(status_name, null); + } + rssi_series.add(time(), rssi); status_series.add(time(), status); } @@ -329,6 +357,18 @@ public class AltosFlightSeries extends AltosDataListener { main_voltage_series.add(time(), volts); } + public ArrayList gps_series; + + public AltosGPS gps_before(double time) { + AltosGPS gps = null; + for (AltosGPSTimeValue gtv : gps_series) + if (gtv.time <= time) + gps = gtv.gps; + else + break; + return gps; + } + AltosTimeSeries sats_in_view; AltosTimeSeries sats_in_soln; AltosTimeSeries gps_altitude; @@ -337,8 +377,7 @@ public class AltosFlightSeries extends AltosDataListener { AltosTimeSeries gps_ascent_rate; AltosTimeSeries gps_course; AltosTimeSeries gps_speed; - - public ArrayList gps_series; + AltosTimeSeries gps_pdop, gps_vdop, gps_hdop; public static final String sats_in_view_name = "Satellites in view"; public static final String sats_in_soln_name = "Satellites in solution"; @@ -348,30 +387,42 @@ public class AltosFlightSeries extends AltosDataListener { public static final String gps_ascent_rate_name = "GPS Ascent Rate"; public static final String gps_course_name = "GPS Course"; public static final String gps_speed_name = "GPS Speed"; + public static final String gps_pdop_name = "GPS Dilution of Precision"; + public static final String gps_vdop_name = "GPS Vertical Dilution of Precision"; + public static final String gps_hdop_name = "GPS Horizontal Dilution of Precision"; public void set_gps(AltosGPS gps) { if (gps_series == null) gps_series = new ArrayList(); gps_series.add(new AltosGPSTimeValue(time(), gps)); - if (sats_in_view == null) { - sats_in_view = add_series(sats_in_view_name, null); + if (sats_in_soln == null) { sats_in_soln = add_series(sats_in_soln_name, null); - gps_altitude = add_series(gps_altitude_name, AltosConvert.height); - gps_height = add_series(gps_height_name, AltosConvert.height); - gps_ground_speed = add_series(gps_ground_speed_name, AltosConvert.speed); - gps_ascent_rate = add_series(gps_ascent_rate_name, AltosConvert.speed); - gps_course = add_series(gps_course_name, null); - gps_speed = add_series(gps_speed_name, null); } - if (gps.cc_gps_sat != null) - sats_in_view.add(time(), gps.cc_gps_sat.length); + sats_in_soln.add(time(), gps.nsat); + if (gps.pdop != AltosLib.MISSING) { + if (gps_pdop == null) { + gps_pdop = add_series(gps_pdop_name, null); + gps_hdop = add_series(gps_hdop_name, null); + gps_vdop = add_series(gps_vdop_name, null); + } + gps_pdop.add(time(), gps.pdop); + gps_hdop.add(time(), gps.hdop); + gps_vdop.add(time(), gps.vdop); + } if (gps.locked) { - sats_in_soln.add(time(), gps.nsat); + if (gps_altitude == null) { + gps_altitude = add_series(gps_altitude_name, AltosConvert.height); + gps_height = add_series(gps_height_name, AltosConvert.height); + gps_ground_speed = add_series(gps_ground_speed_name, AltosConvert.speed); + gps_ascent_rate = add_series(gps_ascent_rate_name, AltosConvert.speed); + gps_course = add_series(gps_course_name, null); + gps_speed = add_series(gps_speed_name, null); + } if (gps.alt != AltosLib.MISSING) { gps_altitude.add(time(), gps.alt); - if (cal_data.gps_ground_altitude != AltosLib.MISSING) - gps_height.add(time(), gps.alt - cal_data.gps_ground_altitude); + if (cal_data.gps_pad != null) + gps_height.add(time(), gps.alt - cal_data.gps_pad.alt); } if (gps.ground_speed != AltosLib.MISSING) gps_ground_speed.add(time(), gps.ground_speed); @@ -383,33 +434,141 @@ public class AltosFlightSeries extends AltosDataListener { gps_speed.add(time(), Math.sqrt(gps.ground_speed * gps.ground_speed + gps.climb_rate * gps.climb_rate)); } + if (gps.cc_gps_sat != null) { + if (sats_in_view == null) + sats_in_view = add_series(sats_in_view_name, null); + sats_in_view.add(time(), gps.cc_gps_sat.length); + } } - public static final String accel_across_name = "Accel Across"; public static final String accel_along_name = "Accel Along"; + public static final String accel_across_name = "Accel Across"; public static final String accel_through_name = "Accel Through"; + AltosTimeSeries accel_along, accel_across, accel_through; + + public static final String gyro_roll_name = "Roll Rate"; + public static final String gyro_pitch_name = "Pitch Rate"; + public static final String gyro_yaw_name = "Yaw Rate"; + + AltosTimeSeries gyro_roll, gyro_pitch, gyro_yaw; + + public static final String mag_along_name = "Magnetic Field Along"; + public static final String mag_across_name = "Magnetic Field Across"; + public static final String mag_through_name = "Magnetic Field Through"; + + AltosTimeSeries mag_along, mag_across, mag_through; + public void set_accel(double along, double across, double through) { + if (accel_along == null) { + accel_along = add_series(accel_along_name, AltosConvert.accel); + accel_across = add_series(accel_across_name, AltosConvert.accel); + accel_through = add_series(accel_through_name, AltosConvert.accel); + } + accel_along.add(time(), along); + accel_across.add(time(), across); + accel_through.add(time(), through); } public void set_accel_ground(double along, double across, double through) { } public void set_gyro(double roll, double pitch, double yaw) { + if (gyro_roll == null) { + gyro_roll = add_series(gyro_roll_name, AltosConvert.rotation_rate); + gyro_pitch = add_series(gyro_pitch_name, AltosConvert.rotation_rate); + gyro_yaw = add_series(gyro_yaw_name, AltosConvert.rotation_rate); + } + gyro_roll.add(time(), roll); + gyro_pitch.add(time(), pitch); + gyro_yaw.add(time(), yaw); } public void set_mag(double along, double across, double through) { + if (mag_along == null) { + mag_along = add_series(mag_along_name, AltosConvert.magnetic_field); + mag_across = add_series(mag_across_name, AltosConvert.magnetic_field); + mag_through = add_series(mag_through_name, AltosConvert.magnetic_field); + } + mag_along.add(time(), along); + mag_across.add(time(), across); + mag_through.add(time(), through); } - public void set_orient(double new_orient) { } + public static final String orient_name = "Tilt Angle"; + + AltosTimeSeries orient_series; + + public void set_orient(double orient) { + if (orient_series == null) + orient_series = add_series(orient_name, AltosConvert.orient); + orient_series.add(time(), orient); + } + + public static final String pyro_voltage_name = "Pyro Voltage"; + + AltosTimeSeries pyro_voltage; public void set_pyro_voltage(double volts) { + if (pyro_voltage == null) + pyro_voltage = add_series(pyro_voltage_name, AltosConvert.voltage); + pyro_voltage.add(time(), volts); } - public void set_ignitor_voltage(double[] voltage) { + private static String[] igniter_voltage_names; + + public String igniter_voltage_name(int channel) { + if (igniter_voltage_names == null || igniter_voltage_names.length <= channel) { + String[] new_igniter_voltage_names = new String[channel + 1]; + int i = 0; + + if (igniter_voltage_names != null) { + for (; i < igniter_voltage_names.length; i++) + new_igniter_voltage_names[i] = igniter_voltage_names[i]; + } + for (; i < channel+1; i++) + new_igniter_voltage_names[i] = AltosLib.igniter_name(i); + igniter_voltage_names = new_igniter_voltage_names; + } + return igniter_voltage_names[channel]; + } + + AltosTimeSeries[] igniter_voltage; + + public void set_igniter_voltage(double[] voltage) { + int channels = voltage.length; + if (igniter_voltage == null || igniter_voltage.length <= channels) { + AltosTimeSeries[] new_igniter_voltage = new AltosTimeSeries[channels + 1]; + int i = 0; + + if (igniter_voltage != null) { + for (; i < igniter_voltage.length; i++) + new_igniter_voltage[i] = igniter_voltage[i]; + } + for (; i < channels; i++) + new_igniter_voltage[i] = add_series(igniter_voltage_name(i), AltosConvert.voltage); + igniter_voltage = new_igniter_voltage; + } + for (int channel = 0; channel < voltage.length; channel++) + igniter_voltage[channel].add(time(), voltage[channel]); } + public static final String pyro_fired_name = "Pyro Channel State"; + + AltosTimeSeries pyro_fired_series; + + int last_pyro_mask; + public void set_pyro_fired(int pyro_mask) { + if (pyro_fired_series == null) + pyro_fired_series = add_series(pyro_fired_name, AltosConvert.pyro_name); + for (int channel = 0; channel < 32; channel++) { + if ((last_pyro_mask & (1 << channel)) == 0 && + (pyro_mask & (1 << channel)) != 0) { + pyro_fired_series.add(time(), channel); + } + } + last_pyro_mask = pyro_mask; } public void set_companion(AltosCompanion companion) { diff --git a/altoslib/AltosFlightStats.java b/altoslib/AltosFlightStats.java index 7179351e..54d0dd63 100644 --- a/altoslib/AltosFlightStats.java +++ b/altoslib/AltosFlightStats.java @@ -46,7 +46,7 @@ public class AltosFlightStats { public boolean has_imu; public boolean has_mag; public boolean has_orient; - public int num_ignitor; + public int num_igniter; double landed_time(AltosFlightSeries series) { double landed_state_time = AltosLib.MISSING; @@ -215,8 +215,8 @@ public class AltosFlightStats { has_mag = true; if (state.orient() != AltosLib.MISSING) has_orient = true; - if (state.ignitor_voltage != null && state.ignitor_voltage.length > num_ignitor) - num_ignitor = state.ignitor_voltage.length; + if (state.igniter_voltage != null && state.igniter_voltage.length > num_igniter) + num_igniter = state.igniter_voltage.length; } */ for (int s = AltosLib.ao_flight_startup; s <= AltosLib.ao_flight_landed; s++) { diff --git a/altoslib/AltosLib.java b/altoslib/AltosLib.java index 2137d1d7..fb43ea20 100644 --- a/altoslib/AltosLib.java +++ b/altoslib/AltosLib.java @@ -571,7 +571,7 @@ public class AltosLib { } } - public static String ignitor_name(int i) { + public static String igniter_name(int i) { return String.format("Ignitor %c", 'A' + i); } } diff --git a/altoslib/AltosMapLine.java b/altoslib/AltosMapLine.java index c475f52d..cf09307e 100644 --- a/altoslib/AltosMapLine.java +++ b/altoslib/AltosMapLine.java @@ -44,39 +44,9 @@ public abstract class AltosMapLine { } public String line_dist() { - String format; AltosGreatCircle g = new AltosGreatCircle(start.lat, start.lon, end.lat, end.lon); - double distance = g.distance; - if (AltosConvert.imperial_units) { - distance = AltosConvert.meters_to_feet(distance); - if (distance < 1000) { - format = "%4.0fft"; - } else { - distance /= 5280; - if (distance < 10) - format = "%5.3fmi"; - else if (distance < 100) - format = "%5.2fmi"; - else if (distance < 1000) - format = "%5.1fmi"; - else - format = "%5.0fmi"; - } - } else { - if (distance < 1000) { - format = "%4.0fm"; - } else { - distance /= 1000; - if (distance < 100) - format = "%5.2fkm"; - else if (distance < 1000) - format = "%5.1fkm"; - else - format = "%5.0fkm"; - } - } - return String.format(format, distance); + return AltosConvert.distance.show(7, g.distance); } } diff --git a/altoslib/AltosPyroName.java b/altoslib/AltosPyroName.java new file mode 100644 index 00000000..18a31dd2 --- /dev/null +++ b/altoslib/AltosPyroName.java @@ -0,0 +1,32 @@ +/* + * Copyright © 2017 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, either version 2 of the License, or + * (at your option) any later version. + * + * 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. + */ + +package org.altusmetrum.altoslib_11; + +public class AltosPyroName extends AltosUnits { + + public double value(double v, boolean imperial_units) { return v; } + + public double inverse(double v, boolean imperial_units) { return v; } + + public String string_value(double v, boolean imperial_units) { + return AltosLib.igniter_name((int) v); + } + + public String show_units(boolean imperial_units) { return "state"; } + + public String say_units(boolean imperial_units) { return "state"; } + + public int show_fraction(int width, boolean imperial_units) { return 0; } +} diff --git a/altoslib/AltosSensorMega.java b/altoslib/AltosSensorMega.java index 63c7a0ce..82696038 100644 --- a/altoslib/AltosSensorMega.java +++ b/altoslib/AltosSensorMega.java @@ -97,10 +97,10 @@ class AltosSensorMega { state.set_apogee_voltage(AltosConvert.mega_pyro_voltage(sensor_mega.sense[4])); state.set_main_voltage(AltosConvert.mega_pyro_voltage(sensor_mega.sense[5])); - double[] ignitor_voltage = new double[4]; + double[] igniter_voltage = new double[4]; for (int i = 0; i < 4; i++) - ignitor_voltage[i] = AltosConvert.mega_pyro_voltage(sensor_mega.sense[i]); - state.set_ignitor_voltage(ignitor_voltage); + igniter_voltage[i] = AltosConvert.mega_pyro_voltage(sensor_mega.sense[i]); + state.set_igniter_voltage(igniter_voltage); } catch (TimeoutException te) { } diff --git a/altoslib/AltosSensorTM.java b/altoslib/AltosSensorTM.java index 7d7becfb..49f3986b 100644 --- a/altoslib/AltosSensorTM.java +++ b/altoslib/AltosSensorTM.java @@ -39,8 +39,8 @@ public class AltosSensorTM { listener.set_pressure(AltosConvert.barometer_to_pressure(sensor_tm.pres)); listener.set_temperature(AltosConvert.thermometer_to_temperature(sensor_tm.temp)); listener.set_battery_voltage(AltosConvert.cc_battery_to_voltage(sensor_tm.batt)); - listener.set_apogee_voltage(AltosConvert.cc_ignitor_to_voltage(sensor_tm.drogue)); - listener.set_main_voltage(AltosConvert.cc_ignitor_to_voltage(sensor_tm.main)); + listener.set_apogee_voltage(AltosConvert.cc_igniter_to_voltage(sensor_tm.drogue)); + listener.set_main_voltage(AltosConvert.cc_igniter_to_voltage(sensor_tm.main)); } catch (TimeoutException te) { } diff --git a/altoslib/AltosState.java b/altoslib/AltosState.java index f46b12ea..889aa9a3 100644 --- a/altoslib/AltosState.java +++ b/altoslib/AltosState.java @@ -702,7 +702,7 @@ public class AltosState extends AltosDataListener { public double apogee_voltage; public double main_voltage; - public double ignitor_voltage[]; + public double igniter_voltage[]; public AltosGPS gps; public AltosGPS temp_gps; @@ -786,7 +786,7 @@ public class AltosState extends AltosDataListener { pyro_voltage = AltosLib.MISSING; apogee_voltage = AltosLib.MISSING; main_voltage = AltosLib.MISSING; - ignitor_voltage = null; + igniter_voltage = null; kalman_height = new AltosValue(); kalman_speed = new AltosValue(); @@ -1221,8 +1221,8 @@ public class AltosState extends AltosDataListener { } } - public void set_ignitor_voltage(double[] voltage) { - this.ignitor_voltage = voltage; + public void set_igniter_voltage(double[] voltage) { + this.igniter_voltage = voltage; } public void set_pyro_fired(int fired) { diff --git a/altoslib/AltosTelemetryFile.java b/altoslib/AltosTelemetryFile.java index 0b0e6a48..c6462872 100644 --- a/altoslib/AltosTelemetryFile.java +++ b/altoslib/AltosTelemetryFile.java @@ -46,7 +46,7 @@ class AltosTelemetryNullListener extends AltosDataListener { public void set_accel(double along, double across, double through) { } public void set_mag(double along, double across, double through) { } public void set_pyro_voltage(double volts) { } - public void set_ignitor_voltage(double[] voltage) { } + public void set_igniter_voltage(double[] voltage) { } public void set_pyro_fired(int pyro_mask) { } public void set_companion(AltosCompanion companion) { } @@ -78,7 +78,7 @@ class AltosTelemetryNullListener extends AltosDataListener { /* * TelemetryLocation */ - if (AltosLib.has_gps(cal_data.device_type) && cal_data.gps_ground_altitude == AltosLib.MISSING) + if (AltosLib.has_gps(cal_data.device_type) && cal_data.gps_pad == null) return false; return true; diff --git a/altoslib/AltosTelemetryLegacy.java b/altoslib/AltosTelemetryLegacy.java index 394d023c..8a86417c 100644 --- a/altoslib/AltosTelemetryLegacy.java +++ b/altoslib/AltosTelemetryLegacy.java @@ -564,8 +564,8 @@ public class AltosTelemetryLegacy extends AltosTelemetry { listener.set_kalman(kalman_height, kalman_speed, kalman_acceleration); listener.set_temperature(AltosConvert.thermometer_to_temperature(temp)); listener.set_battery_voltage(AltosConvert.cc_battery_to_voltage(batt)); - listener.set_apogee_voltage(AltosConvert.cc_ignitor_to_voltage(apogee)); - listener.set_main_voltage(AltosConvert.cc_ignitor_to_voltage(main)); + listener.set_apogee_voltage(AltosConvert.cc_igniter_to_voltage(apogee)); + listener.set_main_voltage(AltosConvert.cc_igniter_to_voltage(main)); if (gps != null) listener.set_gps(gps); } diff --git a/altoslib/AltosTelemetryLocation.java b/altoslib/AltosTelemetryLocation.java index 5eb727d6..c7b7fa22 100644 --- a/altoslib/AltosTelemetryLocation.java +++ b/altoslib/AltosTelemetryLocation.java @@ -58,6 +58,9 @@ public class AltosTelemetryLocation extends AltosTelemetryStandard { gps.nsat = flags & 0xf; gps.locked = (flags & (1 << 4)) != 0; gps.connected = (flags & (1 << 5)) != 0; + gps.pdop = pdop() / 10.0; + gps.hdop = hdop() / 10.0; + gps.vdop = vdop() / 10.0; if (gps.locked) { gps.lat = latitude() * 1.0e-7; @@ -72,12 +75,9 @@ public class AltosTelemetryLocation extends AltosTelemetryStandard { gps.ground_speed = ground_speed() * 1.0e-2; gps.course = course() * 2; gps.climb_rate = climb_rate() * 1.0e-2; - gps.pdop = pdop() / 10.0; - gps.hdop = hdop() / 10.0; - gps.vdop = vdop() / 10.0; if (gps.nsat >= 4) - cal_data.set_gps_altitude(gps.alt); + cal_data.set_gps(gps); } listener.set_gps(gps); } diff --git a/altoslib/AltosTelemetryMegaData.java b/altoslib/AltosTelemetryMegaData.java index c0749e87..b648f300 100644 --- a/altoslib/AltosTelemetryMegaData.java +++ b/altoslib/AltosTelemetryMegaData.java @@ -55,7 +55,7 @@ public class AltosTelemetryMegaData extends AltosTelemetryStandard { for (int i = 0; i < 4; i++) voltages[i] = AltosConvert.mega_pyro_voltage(sense(i)); - listener.set_ignitor_voltage(voltages); + listener.set_igniter_voltage(voltages); cal_data.set_ground_accel(ground_accel()); cal_data.set_ground_pressure(ground_pres()); diff --git a/altoslib/AltosTelemetrySensor.java b/altoslib/AltosTelemetrySensor.java index 37589397..da253eea 100644 --- a/altoslib/AltosTelemetrySensor.java +++ b/altoslib/AltosTelemetrySensor.java @@ -57,8 +57,8 @@ public class AltosTelemetrySensor extends AltosTelemetryStandard { listener.set_temperature(AltosConvert.thermometer_to_temperature(temp())); listener.set_battery_voltage(AltosConvert.cc_battery_to_voltage(v_batt())); if (type() == packet_type_TM_sensor || type() == packet_type_Tm_sensor) { - listener.set_apogee_voltage(AltosConvert.cc_ignitor_to_voltage(sense_d())); - listener.set_main_voltage(AltosConvert.cc_ignitor_to_voltage(sense_m())); + listener.set_apogee_voltage(AltosConvert.cc_igniter_to_voltage(sense_d())); + listener.set_main_voltage(AltosConvert.cc_igniter_to_voltage(sense_m())); } listener.set_kalman(height_16(), speed()/16.0, acceleration()/16.0); diff --git a/altoslib/AltosTimeSeries.java b/altoslib/AltosTimeSeries.java index 1d3d9a6c..30b24d82 100644 --- a/altoslib/AltosTimeSeries.java +++ b/altoslib/AltosTimeSeries.java @@ -17,9 +17,9 @@ package org.altusmetrum.altoslib_11; import java.util.*; public class AltosTimeSeries implements Iterable { - public String label; - public AltosUnits units; - List values; + public String label; + public AltosUnits units; + ArrayList values; public void add(AltosTimeValue tv) { values.add(tv); @@ -33,6 +33,58 @@ public class AltosTimeSeries implements Iterable { return values.get(i); } + private double lerp(AltosTimeValue v0, AltosTimeValue v1, double t) { + /* degenerate case */ + if (v0.time == v1.time) + return (v0.value + v1.value) / 2; + + return (v0.value * (v1.time - t) + v1.value * (t - v0.time)) / v1.time - v0.time; + } + + private int after_index(double time) { + int lo = 0; + int hi = values.size() - 1; + + while (lo <= hi) { + int mid = (lo + hi) / 2; + + if (values.get(mid).time < time) + lo = mid + 1; + else + hi = mid - 1; + } + return lo; + } + + /* Compute a value for an arbitrary time */ + public double value(double time) { + int after = after_index(time); + if (after == 0) + return values.get(0).value; + if (after == values.size()) + return values.get(after - 1).value; + + return lerp(values.get(after-1), values.get(after), time); + } + + /* Find the value just before an arbitrary time */ + public double value_before(double time) { + int after = after_index(time); + + if (after == 0) + return values.get(0).value; + return values.get(after-1).value; + } + + /* Find the value just after an arbitrary time */ + public double value_after(double time) { + int after = after_index(time); + + if (after == values.size()) + return values.get(after-1).value; + return values.get(after).value; + } + public int size() { return values.size(); } @@ -144,11 +196,16 @@ public class AltosTimeSeries implements Iterable { int left = find_left(i, half_width); int right = find_right(i, half_width); + for (int j = left; j <= right; j++) { double j_time = values.get(j).time; if (left_time <= j_time && j_time <= right_time) { - double coeff = filter_coeff(j_time - center_time, width); + double j_left = j == left ? left_time : values.get(j-1).time; + double j_right = j == right ? right_time : values.get(j+1).time; + double interval = (j_right - j_left) / 2.0; + double coeff = filter_coeff(j_time - center_time, width) * interval; + total_coeff += coeff; total_value += coeff * values.get(j).value; } diff --git a/altoslib/Makefile.am b/altoslib/Makefile.am index fa0e8c1b..ffa92783 100644 --- a/altoslib/Makefile.am +++ b/altoslib/Makefile.am @@ -92,6 +92,7 @@ altoslib_JAVA = \ AltosPreferences.java \ AltosPreferencesBackend.java \ AltosProgrammer.java \ + AltosPyroName.java \ AltosReplayReader.java \ AltosRomconfig.java \ AltosSavedState.java \ diff --git a/altosui/AltosFlightUI.java b/altosui/AltosFlightUI.java index 3d33b6e5..eaf19256 100644 --- a/altosui/AltosFlightUI.java +++ b/altosui/AltosFlightUI.java @@ -36,7 +36,7 @@ public class AltosFlightUI extends AltosUIFrame implements AltosFlightDisplay { JTabbedPane pane; AltosPad pad; - AltosIgnitor ignitor; + AltosIgnitor igniter; AltosAscent ascent; AltosDescent descent; AltosLanded landed; @@ -45,7 +45,7 @@ public class AltosFlightUI extends AltosUIFrame implements AltosFlightDisplay { boolean has_map; boolean has_companion; boolean has_state; - boolean has_ignitor; + boolean has_igniter; private AltosFlightStatus flightStatus; private AltosInfoTable flightInfo; @@ -121,15 +121,15 @@ public class AltosFlightUI extends AltosUIFrame implements AltosFlightDisplay { cur_tab = tab; } - if (ignitor.should_show(state)) { - if (!has_ignitor) { - pane.add("Ignitor", ignitor); - has_ignitor = true; + if (igniter.should_show(state)) { + if (!has_igniter) { + pane.add("Ignitor", igniter); + has_igniter = true; } } else { - if (has_ignitor) { - pane.remove(ignitor); - has_ignitor = false; + if (has_igniter) { + pane.remove(igniter); + has_igniter = false; } } @@ -272,8 +272,8 @@ public class AltosFlightUI extends AltosUIFrame implements AltosFlightDisplay { displays.add(pad); pane.add("Status", pad); - ignitor = new AltosIgnitor(); - displays.add(ignitor); + igniter = new AltosIgnitor(); + displays.add(igniter); ascent = new AltosAscent(); displays.add(ascent); descent = new AltosDescent(); diff --git a/altosui/AltosGraphUI.java b/altosui/AltosGraphUI.java index 5314a3b6..a3107f2b 100644 --- a/altosui/AltosGraphUI.java +++ b/altosui/AltosGraphUI.java @@ -44,19 +44,26 @@ public class AltosGraphUI extends AltosUIFrame implements AltosFontListener, Alt void fill_map(AltosFlightSeries flight_series) { boolean any_gps = false; + AltosGPSTimeValue gtv_last = null; for (AltosGPSTimeValue gtv : flight_series.gps_series) { + gtv_last = gtv; AltosGPS gps = gtv.gps; if (gps != null && gps.locked && gps.nsat >= 4) { if (map == null) map = new AltosUIMap(); - map.show(gps, AltosLib.ao_flight_pad); + map.show(gps, (int) flight_series.value_before(AltosFlightSeries.state_name, gtv.time)); this.gps = gps; has_gps = true; } } + if (gtv_last != null) { + int state = (int) flight_series.value_after(AltosFlightSeries.state_name, gtv_last.time); + if (state == AltosLib.ao_flight_landed) + map.show(gtv_last.gps, state); + } } public void font_size_changed(int font_size) { diff --git a/altosui/AltosIdleMonitorUI.java b/altosui/AltosIdleMonitorUI.java index 4d5c3b2d..afa9b944 100644 --- a/altosui/AltosIdleMonitorUI.java +++ b/altosui/AltosIdleMonitorUI.java @@ -34,12 +34,12 @@ public class AltosIdleMonitorUI extends AltosUIFrame implements AltosFlightDispl AltosPad pad; AltosInfoTable flightInfo; AltosFlightStatus flightStatus; - AltosIgnitor ignitor; + AltosIgnitor igniter; AltosIdleMonitor thread; AltosUIMap sitemap; int serial; boolean remote; - boolean has_ignitor; + boolean has_igniter; boolean has_map; void stop_display() { @@ -75,15 +75,15 @@ public class AltosIdleMonitorUI extends AltosUIFrame implements AltosFlightDispl public void show(AltosState state, AltosListenerState listener_state) { status_update.saved_state = state; - if (ignitor.should_show(state)) { - if (!has_ignitor) { - pane.add("Ignitor", ignitor); - has_ignitor = true; + if (igniter.should_show(state)) { + if (!has_igniter) { + pane.add("Ignitor", igniter); + has_igniter = true; } } else { - if (has_ignitor) { - pane.remove(ignitor); - has_ignitor = false; + if (has_igniter) { + pane.remove(igniter); + has_igniter = false; } } if (state.gps != null && state.gps.connected) { @@ -102,8 +102,8 @@ public class AltosIdleMonitorUI extends AltosUIFrame implements AltosFlightDispl pad.show(state, listener_state); flightStatus.show(state, listener_state); flightInfo.show(state, listener_state); - if (has_ignitor) - ignitor.show(state, listener_state); + if (has_igniter) + igniter.show(state, listener_state); if (has_map) sitemap.show(state, listener_state); // } catch (Exception e) { @@ -274,7 +274,7 @@ public class AltosIdleMonitorUI extends AltosUIFrame implements AltosFlightDispl flightInfo = new AltosInfoTable(); pane.add("Table", new JScrollPane(flightInfo)); - ignitor = new AltosIgnitor(); + igniter = new AltosIgnitor(); sitemap = new AltosUIMap(); diff --git a/altosui/AltosIgnitor.java b/altosui/AltosIgnitor.java index fabf4320..09dcdf93 100644 --- a/altosui/AltosIgnitor.java +++ b/altosui/AltosIgnitor.java @@ -27,59 +27,59 @@ import org.altusmetrum.altosuilib_11.*; public class AltosIgnitor extends AltosUIFlightTab { public class Ignitor extends AltosUIUnitsIndicator { - int ignitor; + int igniter; public double value(AltosState state, int i) { - if (state.ignitor_voltage == null || - state.ignitor_voltage.length < ignitor) + if (state.igniter_voltage == null || + state.igniter_voltage.length < igniter) return AltosLib.MISSING; - return state.ignitor_voltage[ignitor]; + return state.igniter_voltage[igniter]; } public double good() { return AltosLib.ao_igniter_good; } public Ignitor (AltosUIFlightTab container, int y) { - super(container, y, AltosConvert.voltage, String.format ("%s Voltage", AltosLib.ignitor_name(y)), 1, true, 1); - ignitor = y; + super(container, y, AltosConvert.voltage, String.format ("%s Voltage", AltosLib.igniter_name(y)), 1, true, 1); + igniter = y; } } - Ignitor[] ignitors; + Ignitor[] igniters; public void show(AltosState state, AltosListenerState listener_state) { if (isShowing()) - make_ignitors(state); + make_igniters(state); super.show(state, listener_state); } public boolean should_show(AltosState state) { if (state == null) return false; - if (state.ignitor_voltage == null) + if (state.igniter_voltage == null) return false; - return state.ignitor_voltage.length > 0; + return state.igniter_voltage.length > 0; } - void make_ignitors(AltosState state) { - int n = (state == null || state.ignitor_voltage == null) ? 0 : state.ignitor_voltage.length; - int old_n = ignitors == null ? 0 : ignitors.length; + void make_igniters(AltosState state) { + int n = (state == null || state.igniter_voltage == null) ? 0 : state.igniter_voltage.length; + int old_n = igniters == null ? 0 : igniters.length; if (n != old_n) { - if (ignitors != null) { - for (int i = 0; i < ignitors.length; i++) { - remove(ignitors[i]); - ignitors[i].remove(this); - ignitors = null; + if (igniters != null) { + for (int i = 0; i < igniters.length; i++) { + remove(igniters[i]); + igniters[i].remove(this); + igniters = null; } } if (n > 0) { setVisible(true); - ignitors = new Ignitor[n]; + igniters = new Ignitor[n]; for (int i = 0; i < n; i++) { - ignitors[i] = new Ignitor(this, i); - add(ignitors[i]); + igniters[i] = new Ignitor(this, i); + add(igniters[i]); } } else setVisible(false); diff --git a/altosui/AltosUI.java b/altosui/AltosUI.java index a6e422e6..b0cff381 100644 --- a/altosui/AltosUI.java +++ b/altosui/AltosUI.java @@ -327,7 +327,7 @@ public class AltosUI extends AltosUIFrame { } private static AltosFlightSeries make_series(AltosRecordSet set) { - AltosFlightSeries series = new AltosFlightSeries(new AltosCalData()); + AltosFlightSeries series = new AltosFlightSeries(set.cal_data()); set.capture_series(series); return series; } diff --git a/altosuilib/AltosGraphNew.java b/altosuilib/AltosGraphNew.java index dc5b7e47..a9393f94 100644 --- a/altosuilib/AltosGraphNew.java +++ b/altosuilib/AltosGraphNew.java @@ -52,6 +52,8 @@ public class AltosGraphNew extends AltosUIGraphNew { static final private Color battery_voltage_color = new Color(194, 194, 31); static final private Color drogue_voltage_color = new Color(150, 150, 31); static final private Color main_voltage_color = new Color(100, 100, 31); + static final private Color igniter_voltage_color = new Color(80, 80, 31); + static final private Color igniter_marker_color = new Color(255, 0, 0); static final private Color gps_nsat_color = new Color (194, 31, 194); static final private Color gps_nsat_solution_color = new Color (194, 31, 194); static final private Color gps_nsat_view_color = new Color (150, 31, 150); @@ -65,25 +67,17 @@ public class AltosGraphNew extends AltosUIGraphNew { static final private Color temperature_color = new Color (31, 194, 194); static final private Color dbm_color = new Color(31, 100, 100); static final private Color state_color = new Color(0,0,0); - static final private Color accel_x_color = new Color(255, 0, 0); - static final private Color accel_y_color = new Color(0, 255, 0); - static final private Color accel_z_color = new Color(0, 0, 255); - static final private Color gyro_x_color = new Color(192, 0, 0); - static final private Color gyro_y_color = new Color(0, 192, 0); - static final private Color gyro_z_color = new Color(0, 0, 192); - static final private Color mag_x_color = new Color(128, 0, 0); - static final private Color mag_y_color = new Color(0, 128, 0); - static final private Color mag_z_color = new Color(0, 0, 128); + static final private Color accel_along_color = new Color(255, 0, 0); + static final private Color accel_across_color = new Color(0, 255, 0); + static final private Color accel_through_color = new Color(0, 0, 255); + static final private Color gyro_roll_color = new Color(192, 0, 0); + static final private Color gyro_pitch_color = new Color(0, 192, 0); + static final private Color gyro_yaw_color = new Color(0, 0, 192); + static final private Color mag_along_color = new Color(128, 0, 0); + static final private Color mag_across_color = new Color(0, 128, 0); + static final private Color mag_through_color = new Color(0, 0, 128); static final private Color orient_color = new Color(31, 31, 31); -// static AltosNsat nsat_units = new AltosNsat(); - static AltosUnits nsat_units = null; -// static AltosDbm dbm_units = new AltosDbm(); - static AltosUnits dbm_units = null; - static AltosOrient orient_units = new AltosOrient(); -// static AltosMagUnits mag_units = new AltosMagUnits(); - static AltosUnits mag_units = null; -// static AltosDopUnits dop_units = new AltosDopUnits(); static AltosUnits dop_units = null; AltosUIFlightSeries flight_series; @@ -102,15 +96,15 @@ public class AltosGraphNew extends AltosUIGraphNew { accel_axis = newAxis("Acceleration", AltosConvert.accel, accel_color); voltage_axis = newAxis("Voltage", AltosConvert.voltage, voltage_color); temperature_axis = newAxis("Temperature", AltosConvert.temperature, temperature_color, 0); - nsat_axis = newAxis("Satellites", nsat_units, gps_nsat_color, + nsat_axis = newAxis("Satellites", null, gps_nsat_color, AltosUIAxis.axis_include_zero | AltosUIAxis.axis_integer); - dbm_axis = newAxis("Signal Strength", dbm_units, dbm_color, 0); + dbm_axis = newAxis("Signal Strength", null, dbm_color, 0); distance_axis = newAxis("Distance", AltosConvert.distance, range_color); - gyro_axis = newAxis("Rotation Rate", AltosConvert.rotation_rate, gyro_z_color, 0); - orient_axis = newAxis("Tilt Angle", orient_units, orient_color, 0); - mag_axis = newAxis("Magnetic Field", mag_units, mag_x_color, 0); - course_axis = newAxis("Course", orient_units, gps_course_color, 0); + gyro_axis = newAxis("Rotation Rate", AltosConvert.rotation_rate, gyro_roll_color, 0); + orient_axis = newAxis("Tilt Angle", AltosConvert.orient, orient_color, 0); + mag_axis = newAxis("Magnetic Field", AltosConvert.magnetic_field, mag_along_color, 0); + course_axis = newAxis("Course", AltosConvert.orient, gps_course_color, 0); dop_axis = newAxis("Dilution of Precision", dop_units, gps_pdop_color, 0); flight_series.register_axis("default", @@ -121,7 +115,14 @@ public class AltosGraphNew extends AltosUIGraphNew { flight_series.register_marker(AltosUIFlightSeries.state_name, state_color, true, - plot); + plot, + true); + + flight_series.register_marker(AltosUIFlightSeries.pyro_fired_name, + igniter_marker_color, + true, + plot, + false); flight_series.register_axis(AltosUIFlightSeries.accel_name, accel_color, @@ -164,17 +165,50 @@ public class AltosGraphNew extends AltosUIGraphNew { height_axis); + flight_series.register_axis(AltosUIFlightSeries.temperature_name, + temperature_color, + false, + temperature_axis); + + flight_series.register_axis(AltosUIFlightSeries.battery_voltage_name, + battery_voltage_color, + false, + voltage_axis); + + flight_series.register_axis(AltosUIFlightSeries.apogee_voltage_name, + drogue_voltage_color, + false, + voltage_axis); + + flight_series.register_axis(AltosUIFlightSeries.main_voltage_name, + main_voltage_color, + false, + voltage_axis); + flight_series.register_axis(AltosUIFlightSeries.sats_in_view_name, gps_nsat_view_color, false, nsat_axis); - flight_series.register_axis(AltosUIFlightSeries.sats_in_soln_name, gps_nsat_solution_color, false, nsat_axis); + flight_series.register_axis(AltosUIFlightSeries.gps_pdop_name, + gps_pdop_color, + false, + dop_axis); + + flight_series.register_axis(AltosUIFlightSeries.gps_hdop_name, + gps_hdop_color, + false, + dop_axis); + + flight_series.register_axis(AltosUIFlightSeries.gps_vdop_name, + gps_vdop_color, + false, + dop_axis); flight_series.register_axis(AltosUIFlightSeries.gps_altitude_name, gps_height_color, @@ -191,13 +225,11 @@ public class AltosGraphNew extends AltosUIGraphNew { false, speed_axis); - flight_series.register_axis(AltosUIFlightSeries.gps_ascent_rate_name, gps_climb_rate_color, false, speed_axis); - flight_series.register_axis(AltosUIFlightSeries.gps_course_name, gps_course_color, false, @@ -208,246 +240,69 @@ public class AltosGraphNew extends AltosUIGraphNew { false, speed_axis); + flight_series.register_axis(AltosUIFlightSeries.accel_along_name, + accel_along_color, + false, + accel_axis); + + flight_series.register_axis(AltosUIFlightSeries.accel_across_name, + accel_across_color, + false, + accel_axis); + + flight_series.register_axis(AltosUIFlightSeries.accel_through_name, + accel_through_color, + false, + accel_axis); + + flight_series.register_axis(AltosUIFlightSeries.gyro_roll_name, + gyro_roll_color, + false, + gyro_axis); + + flight_series.register_axis(AltosUIFlightSeries.gyro_pitch_name, + gyro_pitch_color, + false, + gyro_axis); + + flight_series.register_axis(AltosUIFlightSeries.gyro_yaw_name, + gyro_yaw_color, + false, + gyro_axis); + + flight_series.register_axis(AltosUIFlightSeries.mag_along_name, + mag_along_color, + false, + mag_axis); + + flight_series.register_axis(AltosUIFlightSeries.mag_across_name, + mag_across_color, + false, + mag_axis); + + flight_series.register_axis(AltosUIFlightSeries.mag_through_name, + mag_through_color, + false, + mag_axis); + + flight_series.register_axis(AltosUIFlightSeries.orient_name, + orient_color, + false, + orient_axis); + + for (int channel = 0; channel < 26; channel++) { + flight_series.register_axis(flight_series.igniter_voltage_name(channel), + igniter_voltage_color, + false, + voltage_axis); + } + flight_series.register_axis(AltosUIFlightSeries.thrust_name, thrust_color, true, thrust_axis); -// addMarker("State", AltosGraphDataPoint.data_state, state_color); - return flight_series.series(cal_data); -/* - if (stats.has_flight_data) { - addSeries("Height", - AltosGraphDataPoint.data_height, - AltosConvert.height, - height_color, - true, - height_axis); - addSeries("Pressure", - AltosGraphDataPoint.data_pressure, - pressure_units, - pressure_color, - false, - pressure_axis); - addSeries("Thrust", - AltosGraphDataPoint.data_thrust, - thrust_units, - thrust_color, - false, - thrust_axis); - addSeries("Speed", - AltosGraphDataPoint.data_speed, - AltosConvert.speed, - speed_color, - true, - speed_axis); - addSeries("Acceleration", - AltosGraphDataPoint.data_accel, - AltosConvert.accel, - accel_color, - true, - accel_axis); - } - if (stats.has_gps) { - boolean enable_gps = false; - - if (!stats.has_flight_data) - enable_gps = true; - - addSeries("Range", - AltosGraphDataPoint.data_range, - AltosConvert.distance, - range_color, - false, - distance_axis); - addSeries("Distance", - AltosGraphDataPoint.data_distance, - AltosConvert.distance, - distance_color, - enable_gps, - distance_axis); - addSeries("GPS Height", - AltosGraphDataPoint.data_gps_height, - AltosConvert.height, - gps_height_color, - enable_gps, - height_axis); - addSeries("GPS Altitude", - AltosGraphDataPoint.data_gps_altitude, - AltosConvert.height, - gps_height_color, - false, - height_axis); - addSeries("GPS Satellites in Solution", - AltosGraphDataPoint.data_gps_nsat_solution, - nsat_units, - gps_nsat_solution_color, - false, - nsat_axis); - if (stats.has_gps_sats) { - addSeries("GPS Satellites in View", - AltosGraphDataPoint.data_gps_nsat_view, - nsat_units, - gps_nsat_view_color, - false, - nsat_axis); - } - if (stats.has_gps_detail) { - addSeries("GPS Course", - AltosGraphDataPoint.data_gps_course, - orient_units, - gps_course_color, - false, - course_axis); - addSeries("GPS Ground Speed", - AltosGraphDataPoint.data_gps_ground_speed, - AltosConvert.speed, - gps_ground_speed_color, - enable_gps, - speed_axis); - addSeries("GPS Climb Rate", - AltosGraphDataPoint.data_gps_climb_rate, - AltosConvert.speed, - gps_climb_rate_color, - enable_gps, - speed_axis); - } - addSeries("GPS Position DOP", - AltosGraphDataPoint.data_gps_pdop, - dop_units, - gps_pdop_color, - false, - dop_axis); - if (stats.has_gps_detail) { - addSeries("GPS Horizontal DOP", - AltosGraphDataPoint.data_gps_hdop, - dop_units, - gps_hdop_color, - false, - dop_axis); - addSeries("GPS Vertical DOP", - AltosGraphDataPoint.data_gps_vdop, - dop_units, - gps_vdop_color, - false, - dop_axis); - } - } - if (stats.has_rssi) - addSeries("Received Signal Strength", - AltosGraphDataPoint.data_rssi, - dbm_units, - dbm_color, - false, - dbm_axis); - - if (stats.has_battery) - addSeries("Battery Voltage", - AltosGraphDataPoint.data_battery_voltage, - voltage_units, - battery_voltage_color, - false, - voltage_axis); - - if (stats.has_flight_adc) { - addSeries("Temperature", - AltosGraphDataPoint.data_temperature, - AltosConvert.temperature, - temperature_color, - false, - temperature_axis); - addSeries("Drogue Voltage", - AltosGraphDataPoint.data_drogue_voltage, - voltage_units, - drogue_voltage_color, - false, - voltage_axis); - addSeries("Main Voltage", - AltosGraphDataPoint.data_main_voltage, - voltage_units, - main_voltage_color, - false, - voltage_axis); - } - - if (stats.has_imu) { - addSeries("Acceleration Along", - AltosGraphDataPoint.data_accel_along, - AltosConvert.accel, - accel_x_color, - false, - accel_axis); - addSeries("Acceleration Across", - AltosGraphDataPoint.data_accel_across, - AltosConvert.accel, - accel_y_color, - false, - accel_axis); - addSeries("Acceleration Through", - AltosGraphDataPoint.data_accel_through, - AltosConvert.accel, - accel_z_color, - false, - accel_axis); - addSeries("Roll Rate", - AltosGraphDataPoint.data_gyro_roll, - gyro_units, - gyro_x_color, - false, - gyro_axis); - addSeries("Pitch Rate", - AltosGraphDataPoint.data_gyro_pitch, - gyro_units, - gyro_y_color, - false, - gyro_axis); - addSeries("Yaw Rate", - AltosGraphDataPoint.data_gyro_yaw, - gyro_units, - gyro_z_color, - false, - gyro_axis); - } - if (stats.has_mag) { - addSeries("Magnetometer Along", - AltosGraphDataPoint.data_mag_along, - mag_units, - mag_x_color, - false, - mag_axis); - addSeries("Magnetometer Across", - AltosGraphDataPoint.data_mag_across, - mag_units, - mag_y_color, - false, - mag_axis); - addSeries("Magnetometer Through", - AltosGraphDataPoint.data_mag_through, - mag_units, - mag_z_color, - false, - mag_axis); - } - if (stats.has_orient) - addSeries("Tilt Angle", - AltosGraphDataPoint.data_orient, - orient_units, - orient_color, - false, - orient_axis); - if (stats.num_ignitor > 0) { - for (int i = 0; i < stats.num_ignitor; i++) - addSeries(AltosLib.ignitor_name(i), - AltosGraphDataPoint.data_ignitor_0 + i, - voltage_units, - main_voltage_color, - false, - voltage_axis); - for (int i = 0; i < stats.num_ignitor; i++) - addMarker(AltosLib.ignitor_name(i), AltosGraphDataPoint.data_ignitor_fired_0 + i, state_color); - } -*/ } public AltosGraphNew(AltosUIEnable enable, AltosFlightStats stats, AltosUIFlightSeries flight_series, AltosCalData cal_data) { diff --git a/altosuilib/AltosUIFlightSeries.java b/altosuilib/AltosUIFlightSeries.java index 1840761e..0bcc8a6e 100644 --- a/altosuilib/AltosUIFlightSeries.java +++ b/altosuilib/AltosUIFlightSeries.java @@ -33,15 +33,17 @@ class AltosUITimeSeriesAxis { Color color; boolean enabled; boolean marker; + boolean marker_top; AltosUIAxis axis; XYPlot plot; - public AltosUITimeSeriesAxis(Color color, boolean enabled, AltosUIAxis axis, XYPlot plot, boolean marker) { + public AltosUITimeSeriesAxis(Color color, boolean enabled, AltosUIAxis axis, XYPlot plot, boolean marker, boolean marker_top) { this.color = color; this.enabled = enabled; this.axis = axis; this.plot = plot; this.marker = marker; + this.marker_top = marker_top; } } @@ -57,7 +59,7 @@ public class AltosUIFlightSeries extends AltosFlightSeries { if (label.equals(ts.label) || (label.equals("default") && uts.color == null)) { if (axis.marker) - uts.set_marker(axis.color, axis.enabled, axis.plot); + uts.set_marker(axis.color, axis.enabled, axis.plot, axis.marker_top); else uts.set_axis(axis.color, axis.enabled, axis.axis); } @@ -72,6 +74,7 @@ public class AltosUIFlightSeries extends AltosFlightSeries { enabled, axis, null, + false, false); axes.put(label, tsa); fill_axes(label, tsa); @@ -80,12 +83,14 @@ public class AltosUIFlightSeries extends AltosFlightSeries { public void register_marker(String label, Color color, boolean enabled, - XYPlot plot) { + XYPlot plot, + boolean marker_top) { AltosUITimeSeriesAxis tsa = new AltosUITimeSeriesAxis(color, enabled, null, plot, - true); + true, + marker_top); axes.put(label, tsa); fill_axes(label, tsa); } @@ -100,7 +105,7 @@ public class AltosUIFlightSeries extends AltosFlightSeries { tsa = axes.get("default"); if (tsa != null) { if (tsa.marker) - time_series.set_marker(tsa.color, tsa.enabled, tsa.plot); + time_series.set_marker(tsa.color, tsa.enabled, tsa.plot, tsa.marker_top); else time_series.set_axis(tsa.color, tsa.enabled, tsa.axis); } diff --git a/altosuilib/AltosUITimeSeries.java b/altosuilib/AltosUITimeSeries.java index 0f5e35eb..7c48264e 100644 --- a/altosuilib/AltosUITimeSeries.java +++ b/altosuilib/AltosUITimeSeries.java @@ -47,6 +47,7 @@ public class AltosUITimeSeries extends AltosTimeSeries implements AltosUIGrapher boolean enable; AltosUIAxis axis; boolean marker; + boolean marker_top; XYItemRenderer renderer; XYPlot plot; AltosXYSeries xy_series; @@ -81,8 +82,13 @@ public class AltosUITimeSeries extends AltosTimeSeries implements AltosUIGrapher String s = units.string_value(v.value); ValueMarker marker = new ValueMarker(v.time); marker.setLabel(s); - marker.setLabelAnchor(RectangleAnchor.TOP_RIGHT); - marker.setLabelTextAnchor(TextAnchor.TOP_LEFT); + if (marker_top) { + marker.setLabelAnchor(RectangleAnchor.TOP_RIGHT); + marker.setLabelTextAnchor(TextAnchor.TOP_LEFT); + } else { + marker.setLabelAnchor(RectangleAnchor.BOTTOM_RIGHT); + marker.setLabelTextAnchor(TextAnchor.BOTTOM_LEFT); + } marker.setPaint(color); if (enable) plot.addDomainMarker(marker); @@ -91,12 +97,14 @@ public class AltosUITimeSeries extends AltosTimeSeries implements AltosUIGrapher } else { xy_series.clear(); + xy_series.setNotify(false); for (AltosTimeValue v : this) { double value = v.value; if (units != null) value = units.graph_value(value); xy_series.add(v.time, value); } + xy_series.setNotify(true); } } @@ -153,11 +161,12 @@ public class AltosUITimeSeries extends AltosTimeSeries implements AltosUIGrapher xy_series = new AltosXYSeries(label); } - public void set_marker(Color color, boolean enable, XYPlot plot) { + public void set_marker(Color color, boolean enable, XYPlot plot, boolean marker_top) { this.color = color; this.enable = enable; this.marker = true; this.plot = plot; + this.marker_top = marker_top; } public AltosUITimeSeries(String label, AltosUnits units) { -- cgit v1.2.3 From da914cd72411af8c36af05b13c11b9093c8a378c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 28 May 2017 14:00:15 -0700 Subject: altoslib: Create data file open helper in AltosLib Use InputStream everywhere, instead of Reader. Create private string input stream as java one is deprecated. Signed-off-by: Keith Packard --- altoslib/AltosEepromFile.java | 2 +- altoslib/AltosEepromNew.java | 67 ++++++++++++++++++++++-------------- altoslib/AltosEepromRecordSet.java | 2 +- altoslib/AltosJson.java | 10 +++--- altoslib/AltosLib.java | 24 +++++++++++++ altoslib/AltosStringInputStream.java | 61 ++++++++++++++++++++++++++++++++ altoslib/AltosTelemetryFile.java | 2 +- altoslib/AltosTelemetryIterable.java | 30 +++++++--------- altoslib/Makefile.am | 1 + altosui/AltosLanded.java | 4 +-- altosui/AltosUI.java | 52 ++++++++-------------------- altosuilib/AltosDataChooser.java | 16 +-------- telegps/TeleGPS.java | 19 +++------- 13 files changed, 169 insertions(+), 121 deletions(-) create mode 100644 altoslib/AltosStringInputStream.java (limited to 'altoslib/Makefile.am') diff --git a/altoslib/AltosEepromFile.java b/altoslib/AltosEepromFile.java index df19877b..463948b1 100644 --- a/altoslib/AltosEepromFile.java +++ b/altoslib/AltosEepromFile.java @@ -33,7 +33,7 @@ public class AltosEepromFile implements AltosRecordSet { out.printf("%s\n", set.eeprom.toString()); } - public AltosEepromFile(Reader input) throws IOException { + public AltosEepromFile(InputStream input) throws IOException { set = new AltosEepromRecordSet(input); } diff --git a/altoslib/AltosEepromNew.java b/altoslib/AltosEepromNew.java index 0da3df71..c373bff3 100644 --- a/altoslib/AltosEepromNew.java +++ b/altoslib/AltosEepromNew.java @@ -93,19 +93,34 @@ public class AltosEepromNew { w.append('\n'); } - private boolean read_config(Reader r) throws IOException { - config = AltosJson.fromReader(r); + private boolean read_config(InputStream stream) throws IOException { + config = AltosJson.fromInputStream(stream); if (config == null) return false; return true; } - private boolean read_data(Reader r) throws IOException { - BufferedReader br = new BufferedReader(r); - String s; + private String read_line(InputStream stream) throws IOException { + StringBuffer buffer = null; + int c; + + for (;;) { + c = stream.read(); + if (c == -1 && buffer == null) + return null; + if (buffer == null) + buffer = new StringBuffer(); + if (c == -1 || c == '\n') + return buffer.toString(); + buffer.append((char) c); + } + } + + private boolean read_data(InputStream stream) throws IOException { + String s; data = new ArrayList(); - while ((s = br.readLine()) != null) { + while ((s = read_line(stream)) != null) { String[] tokens = s.split("\\s+"); @@ -122,24 +137,24 @@ public class AltosEepromNew { return true; } - private boolean read_old_config(BufferedReader r) throws IOException { + private boolean read_old_config(InputStream stream) throws IOException { AltosConfigData cfg = new AltosConfigData(); for (;;) { boolean done = false; /* The data starts with an upper case F character followed by a space */ - r.mark(2); - int first = r.read(); + stream.mark(2); + int first = stream.read(); if (first == 'F') { - int second = r.read(); + int second = stream.read(); if (second == ' ') done = true; } - r.reset(); + stream.reset(); if (done) break; - String line = r.readLine(); + String line = read_line(stream); if (line == null) return false; cfg.parse_line(line); @@ -148,11 +163,11 @@ public class AltosEepromNew { return true; } - private boolean read_old_data(BufferedReader r) throws IOException { + private boolean read_old_data(InputStream stream) throws IOException { String line; data = new ArrayList(); - while ((line = r.readLine()) != null) { + while ((line = read_line(stream)) != null) { String[] tokens = line.split("\\s+"); /* Make sure there's at least a type and time */ @@ -207,22 +222,22 @@ public class AltosEepromNew { return true; } - private void read(Reader r) throws IOException { - BufferedReader br = new BufferedReader(r); + private void read(InputStream stream) throws IOException { + BufferedInputStream bis = new BufferedInputStream(stream); - br.mark(1); - int c = br.read(); - br.reset(); + bis.mark(1); + int c = bis.read(); + bis.reset(); if (c == '{') { - if (!read_config(br)) + if (!read_config(bis)) throw new IOException("failed to read config"); - if (!read_data(br)) + if (!read_data(bis)) throw new IOException("failed to read data"); } else { - if (!read_old_config(br)) + if (!read_old_config(bis)) throw new IOException("failed to read old config"); - if (!read_old_data(br)) + if (!read_old_data(bis)) throw new IOException("failed to read old data"); } } @@ -253,12 +268,12 @@ public class AltosEepromNew { /* * Constructors */ - public AltosEepromNew(Reader r) throws IOException { - read(r); + public AltosEepromNew(InputStream stream) throws IOException { + read(stream); } public AltosEepromNew(String s) throws IOException { - read(new StringReader(s)); + read(new AltosStringInputStream(s)); } public AltosEepromNew(AltosJson config, ArrayList data) { diff --git a/altoslib/AltosEepromRecordSet.java b/altoslib/AltosEepromRecordSet.java index 183cb9ae..0c60c1a5 100644 --- a/altoslib/AltosEepromRecordSet.java +++ b/altoslib/AltosEepromRecordSet.java @@ -110,7 +110,7 @@ public class AltosEepromRecordSet implements AltosRecordSet { } } - public AltosEepromRecordSet(Reader input) throws IOException { + public AltosEepromRecordSet(InputStream input) throws IOException { this(new AltosEepromNew(input)); } } diff --git a/altoslib/AltosJson.java b/altoslib/AltosJson.java index 9191be68..ce50b872 100644 --- a/altoslib/AltosJson.java +++ b/altoslib/AltosJson.java @@ -255,7 +255,7 @@ class JsonToken { * Lexer for json */ class JsonLexer extends JsonUtil { - Reader f; + InputStream f; int line; int ungot = -2; StringBuffer pending_token; @@ -445,12 +445,12 @@ class JsonLexer extends JsonUtil { } JsonLexer(String s) { - f = new StringReader(s); + f = new AltosStringInputStream(s); line = 1; token = null; } - JsonLexer(Reader f) { + JsonLexer(InputStream f) { this.f = f; line = 1; token = null; @@ -570,7 +570,7 @@ class JsonParse { lexer = new JsonLexer(s); } - JsonParse(Reader f) { + JsonParse(InputStream f) { lexer = new JsonLexer(f); } } @@ -670,7 +670,7 @@ public class AltosJson extends JsonUtil { } } - public static AltosJson fromReader(Reader f) { + public static AltosJson fromInputStream(InputStream f) { JsonParse parse = new JsonParse(f); try { return parse.parse(); diff --git a/altoslib/AltosLib.java b/altoslib/AltosLib.java index 355c7a27..6c1729df 100644 --- a/altoslib/AltosLib.java +++ b/altoslib/AltosLib.java @@ -588,4 +588,28 @@ public class AltosLib { public static String igniter_name(int i) { return String.format("Ignitor %c", 'A' + i); } + + public static AltosRecordSet record_set(File file) throws FileNotFoundException, IOException { + FileInputStream in; + in = new FileInputStream(file); + if (file.getName().endsWith("telem")) { + return new AltosTelemetryFile(in); + } else if (file.getName().endsWith("eeprom")) { + return new AltosEepromFile(in); + } else { + String name = file.getName(); + int dot = name.lastIndexOf('.'); + String extension; + + if (dot == -1) + throw new IOException(String.format("%s (Missing extension)", file.toString())); + else { + extension = name.substring(dot); + throw new IOException(String.format("%s (Invalid extension '%s')", + file.toString(), + extension)); + } + } + } + } diff --git a/altoslib/AltosStringInputStream.java b/altoslib/AltosStringInputStream.java new file mode 100644 index 00000000..d574db24 --- /dev/null +++ b/altoslib/AltosStringInputStream.java @@ -0,0 +1,61 @@ +/* + * Copyright © 2017 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, either version 2 of the License, or + * (at your option) any later version. + * + * 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. + */ + +package org.altusmetrum.altoslib_11; + +import java.util.*; +import java.io.*; + +public class AltosStringInputStream extends InputStream { + + String s; + int at; + int mark; + + public int available() { + return s.length() - at; + } + + public void mark(int read_limit) { + mark = at; + } + + public boolean markSupported() { + return true; + } + + public int read() { + if (at == s.length()) + return -1; + return (int) s.charAt(at++); + } + + public void reset() { + at = mark; + } + + public long skip(long n) throws IOException { + if (n < 0) n = 0; + + if (at + n > s.length()) + n = s.length() - at; + at += n; + return n; + } + + public AltosStringInputStream(String s) { + this.s = s; + this.at = 0; + } +} diff --git a/altoslib/AltosTelemetryFile.java b/altoslib/AltosTelemetryFile.java index 40b9c9bf..077ef9c6 100644 --- a/altoslib/AltosTelemetryFile.java +++ b/altoslib/AltosTelemetryFile.java @@ -129,7 +129,7 @@ public class AltosTelemetryFile implements AltosRecordSet { listener.finish(); } - public AltosTelemetryFile(FileInputStream input) { + public AltosTelemetryFile(FileInputStream input) throws IOException { telems = new AltosTelemetryIterable(input); } } diff --git a/altoslib/AltosTelemetryIterable.java b/altoslib/AltosTelemetryIterable.java index 402bbf4f..a752e24e 100644 --- a/altoslib/AltosTelemetryIterable.java +++ b/altoslib/AltosTelemetryIterable.java @@ -80,29 +80,25 @@ public class AltosTelemetryIterable implements Iterable { return new AltosTelemetryOrderedIterator(telems); } - public AltosTelemetryIterable (FileInputStream input) { + public AltosTelemetryIterable (FileInputStream input) throws IOException { telems = new TreeSet (); tick = 0; index = 0; - try { - for (;;) { - String line = AltosLib.gets(input); - if (line == null) { + for (;;) { + String line = AltosLib.gets(input); + if (line == null) { + break; + } + try { + AltosTelemetry telem = AltosTelemetry.parse(line); + if (telem == null) break; - } - try { - AltosTelemetry telem = AltosTelemetry.parse(line); - if (telem == null) - break; - add(telem); - } catch (ParseException pe) { - System.out.printf("parse exception %s\n", pe.getMessage()); - } catch (AltosCRCException ce) { - } + add(telem); + } catch (ParseException pe) { + System.out.printf("parse exception %s\n", pe.getMessage()); + } catch (AltosCRCException ce) { } - } catch (IOException io) { - System.out.printf("io exception\n"); } } } diff --git a/altoslib/Makefile.am b/altoslib/Makefile.am index ffa92783..1e26b724 100644 --- a/altoslib/Makefile.am +++ b/altoslib/Makefile.am @@ -107,6 +107,7 @@ altoslib_JAVA = \ AltosSensorTGPS.java \ AltosState.java \ AltosStateName.java \ + AltosStringInputStream.java \ AltosTelemetry.java \ AltosTelemetryConfiguration.java \ AltosTelemetryCompanion.java \ diff --git a/altosui/AltosLanded.java b/altosui/AltosLanded.java index a75d5a9f..de0d7425 100644 --- a/altosui/AltosLanded.java +++ b/altosui/AltosLanded.java @@ -124,10 +124,10 @@ public class AltosLanded extends AltosUIFlightTab implements ActionListener { String filename = file.getName(); try { AltosRecordSet record_set = null; + FileInputStream in = new FileInputStream(file); if (filename.endsWith("eeprom")) { - record_set = new AltosEepromRecordSet(new FileReader(file)); + record_set = new AltosEepromRecordSet(in); } else if (filename.endsWith("telem")) { - FileInputStream in = new FileInputStream(file); record_set = new AltosTelemetryFile(in); } else { throw new FileNotFoundException(filename); diff --git a/altosui/AltosUI.java b/altosui/AltosUI.java index b302b670..ac121512 100644 --- a/altosui/AltosUI.java +++ b/altosui/AltosUI.java @@ -372,21 +372,6 @@ public class AltosUI extends AltosUIFrame { } } - static AltosRecordSet open_logfile(File file) { - try { - if (file.getName().endsWith("telem")) - return new AltosTelemetryFile(new FileInputStream(file)); - else - return new AltosEepromFile(new FileReader(file)); - } catch (FileNotFoundException fe) { - System.out.printf("%s\n", fe.getMessage()); - return null; - } catch (IOException ie) { - System.out.printf("%s\n", ie.getMessage()); - return null; - } - } - static AltosWriter open_csv(File file) { try { return new AltosCSV(file); @@ -405,6 +390,18 @@ public class AltosUI extends AltosUIFrame { } } + static AltosRecordSet record_set(File input) { + try { + return AltosLib.record_set(input); + } catch (IOException ie) { + String message = ie.getMessage(); + if (message == null) + message = String.format("%s (I/O error)", input.toString()); + System.err.printf("%s\n", message); + } + return null; + } + static final int process_none = 0; static final int process_csv = 1; static final int process_kml = 2; @@ -413,7 +410,7 @@ public class AltosUI extends AltosUIFrame { static final int process_summary = 5; static boolean process_csv(File input) { - AltosRecordSet set = open_logfile(input); + AltosRecordSet set = record_set(input); if (set == null) return false; @@ -434,7 +431,7 @@ public class AltosUI extends AltosUIFrame { } static boolean process_kml(File input) { - AltosRecordSet set = open_logfile(input); + AltosRecordSet set = record_set(input); if (set == null) return false; @@ -455,27 +452,6 @@ public class AltosUI extends AltosUIFrame { } } - static AltosRecordSet record_set(File file) { - FileInputStream in; - if (file.getName().endsWith("telem")) { - try { - in = new FileInputStream(file); - return new AltosTelemetryFile(in); - } catch (Exception e) { - System.out.printf("Failed to open file '%s'\n", file); - } - } else { - - try { - AltosEepromFile f = new AltosEepromFile(new FileReader(file)); - return f; - } catch (Exception e) { - System.out.printf("Failed to open file '%s'\n", file); - } - } - return null; - } - static AltosReplayReader replay_file(File file) { AltosRecordSet set = record_set(file); if (set == null) diff --git a/altosuilib/AltosDataChooser.java b/altosuilib/AltosDataChooser.java index c6d53a31..c26d3673 100644 --- a/altosuilib/AltosDataChooser.java +++ b/altosuilib/AltosDataChooser.java @@ -44,22 +44,8 @@ public class AltosDataChooser extends JFileChooser { file = getSelectedFile(); if (file == null) return null; - filename = file.getName(); try { - if (filename.endsWith("eeprom")) { - FileReader in = new FileReader(file); - return new AltosEepromFile(in); - } else if (filename.endsWith("telem")) { - FileInputStream in = new FileInputStream(file); - return new AltosTelemetryFile(in); - } else { - throw new FileNotFoundException(); - } - } catch (FileNotFoundException fe) { - JOptionPane.showMessageDialog(frame, - fe.getMessage(), - "Cannot open file", - JOptionPane.ERROR_MESSAGE); + return AltosLib.record_set(file); } catch (IOException ie) { JOptionPane.showMessageDialog(frame, ie.getMessage(), diff --git a/telegps/TeleGPS.java b/telegps/TeleGPS.java index 5e500e02..e032726a 100644 --- a/telegps/TeleGPS.java +++ b/telegps/TeleGPS.java @@ -620,21 +620,10 @@ public class TeleGPS } static AltosRecordSet record_set(File file) { - FileInputStream in; - if (file.getName().endsWith("telem")) { - try { - in = new FileInputStream(file); - return new AltosTelemetryFile(in); - } catch (Exception e) { - System.out.printf("Failed to open file '%s'\n", file); - } - } else { - - try { - return new AltosEepromFile(new FileReader(file)); - } catch (Exception e) { - System.out.printf("Failed to open file '%s'\n", file); - } + try { + return AltosLib.record_set(file); + } catch (IOException ie) { + System.out.printf("%s\n", ie.getMessage()); } return null; } -- cgit v1.2.3 From 0e586ab3604bb695c36ae86c95f533197522fc65 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 13 Jun 2017 10:38:13 -0700 Subject: altoslib: Remove old AltosEeprom.java code No longer in use Signed-off-by: Keith Packard --- altoslib/AltosEeprom.java | 132 ---------------------------------------------- altoslib/Makefile.am | 1 - 2 files changed, 133 deletions(-) delete mode 100644 altoslib/AltosEeprom.java (limited to 'altoslib/Makefile.am') diff --git a/altoslib/AltosEeprom.java b/altoslib/AltosEeprom.java deleted file mode 100644 index dec7dd57..00000000 --- a/altoslib/AltosEeprom.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright © 2013 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; either version 2 of the License, or - * (at your option) any later version. - * - * 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 org.altusmetrum.altoslib_11; - -import java.io.*; -import java.util.*; -import java.text.*; - -public abstract class AltosEeprom implements AltosDataProvider { - public int cmd; - public int tick; - public int data8[]; - public boolean valid; - - public int data8(int i) { - return data8[i]; - } - - public int data16(int i) { - return ((data8[i] | (data8[i+1] << 8)) << 16) >> 16; - } - - public int data24(int i) { - return data8[i] | (data8[i+1] << 8) | (data8[i+2] << 16); - } - - public int data32(int i) { - return data8[i] | (data8[i+1] << 8) | (data8[i+2] << 16) | (data8[i+3] << 24); - } - - public boolean has_seconds() { return false; } - - public int seconds() { return 0; } - - public final static int header_length = 4; - - public abstract int record_length(); - - public void provide_data(AltosDataListener listener, AltosCalData cal_data) { - cal_data.set_tick(tick); - if (cmd == AltosLib.AO_LOG_FLIGHT) - cal_data.set_boost_tick(); - listener.set_time(cal_data.time()); - } - - public void write(PrintStream out) { - out.printf("%c %04x", cmd, tick); - if (data8 != null) { - for (int i = 0; i < data8.length; i++) - out.printf (" %02x", data8[i]); - } - out.printf ("\n"); - } - - public String string() { - String s; - - s = String.format("%c %04x", cmd, tick); - if (data8 != null) { - for (int i = 0; i < data8.length; i++) { - String d = String.format(" %02x", data8[i]); - s = s.concat(d); - } - } - s = s.concat("\n"); - return s; - } - - void parse_chunk(AltosEepromChunk chunk, int start) throws ParseException { - cmd = chunk.data(start); - - int data_length = record_length() - header_length; - - valid = !chunk.erased(start, record_length()); - if (valid) { - if (AltosConvert.checksum(chunk.data, start, record_length()) != 0) - throw new ParseException(String.format("invalid checksum at 0x%x", - chunk.address + start), 0); - } else { - cmd = AltosLib.AO_LOG_INVALID; - } - - tick = chunk.data16(start+2); - - data8 = new int[data_length]; - for (int i = 0; i < data_length; i++) - data8[i] = chunk.data(start + header_length + i); - } - - void parse_string(String line) { - valid = false; - tick = 0; - cmd = AltosLib.AO_LOG_INVALID; - - int data_length = record_length() - header_length; - - if (line == null) - return; - try { - String[] tokens = line.split("\\s+"); - - if (tokens[0].length() == 1) { - if (tokens.length == 2 + data_length) { - cmd = tokens[0].codePointAt(0); - tick = Integer.parseInt(tokens[1],16); - valid = true; - data8 = new int[data_length]; - - for (int i = 0; i < data_length; i++) - data8[i] = Integer.parseInt(tokens[2 + i],16); - } - } - } catch (NumberFormatException ne) { - } - } -} diff --git a/altoslib/Makefile.am b/altoslib/Makefile.am index 1e26b724..ce934b4f 100644 --- a/altoslib/Makefile.am +++ b/altoslib/Makefile.am @@ -46,7 +46,6 @@ altoslib_JAVA = \ AltosEepromRecordGps.java \ AltosEepromRecordFireTwo.java \ AltosEepromRecordSet.java \ - AltosEeprom.java \ AltosEepromChunk.java \ AltosEepromDownload.java \ AltosEepromMonitor.java \ -- cgit v1.2.3 From e4f1fa544f1cb21070c9d79c81ebae0fb71d77db Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 13 Jun 2017 10:46:03 -0700 Subject: altoslib: Rename AltosEepromNew to AltosEeprom Signed-off-by: Keith Packard --- altoslib/AltosEeprom.java | 291 +++++++++++++++++++++++++++++++++ altoslib/AltosEepromDownload.java | 2 +- altoslib/AltosEepromNew.java | 291 --------------------------------- altoslib/AltosEepromRecord.java | 4 +- altoslib/AltosEepromRecordFireTwo.java | 4 +- altoslib/AltosEepromRecordFull.java | 4 +- altoslib/AltosEepromRecordGps.java | 4 +- altoslib/AltosEepromRecordMega.java | 4 +- altoslib/AltosEepromRecordMetrum.java | 4 +- altoslib/AltosEepromRecordMini.java | 4 +- altoslib/AltosEepromRecordSet.java | 6 +- altoslib/AltosEepromRecordTiny.java | 4 +- altoslib/Makefile.am | 2 +- 13 files changed, 312 insertions(+), 312 deletions(-) create mode 100644 altoslib/AltosEeprom.java delete mode 100644 altoslib/AltosEepromNew.java (limited to 'altoslib/Makefile.am') diff --git a/altoslib/AltosEeprom.java b/altoslib/AltosEeprom.java new file mode 100644 index 00000000..2600e802 --- /dev/null +++ b/altoslib/AltosEeprom.java @@ -0,0 +1,291 @@ +/* + * Copyright © 2017 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, either version 2 of the License, or + * (at your option) any later version. + * + * 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. + */ + +package org.altusmetrum.altoslib_11; + +import java.util.*; +import java.io.*; + +public class AltosEeprom { + + private AltosJson config; + ArrayList data; + private AltosConfigData config_data; + + /* + * Public accessor APIs + */ + public int data8(int offset) { + return ((int) data.get(offset)) & 0xff; + } + + public int data16(int offset) { + return data8(offset) | (data8(offset+1) << 8); + } + + public int data24(int offset) { + return (data8(offset) | + (data8(offset+1) << 8) | + (data8(offset+2) << 16)); + } + + public int data32(int offset) { + return (data8(offset) | + (data8(offset+1) << 8) | + (data8(offset+2) << 16) | + (data8(offset+3) << 24)); + } + + public int size() { + return data.size(); + } + + public AltosConfigData config_data() { + if (config_data == null) { + config_data = (AltosConfigData) config.make(AltosConfigData.class); + if (config_data == null) + config_data = new AltosConfigData(); + + if (config_data.log_format == AltosLib.AO_LOG_FORMAT_UNKNOWN) { + config_data.log_format = AltosLib.AO_LOG_FORMAT_FULL; + if (config_data.product != null) { + if (config_data.product.startsWith("TeleMetrum")) + config_data.log_format = AltosLib.AO_LOG_FORMAT_FULL; + else if (config_data.product.startsWith("TeleMini")) + config_data.log_format = AltosLib.AO_LOG_FORMAT_TINY; + } + } + } + return config_data; + } + + private void write_config(Writer w) throws IOException { + config.write(w, 0, true); + w.append('\n'); + } + + /* + * Private I/O APIs + */ + private void write_data(Writer w) throws IOException { + PrintWriter pw = new PrintWriter(w); + + for (int i = 0; i < data.size(); i++) { + if (i > 0) { + if ((i & 0x1f) == 0) + pw.printf("\n"); + else + pw.printf(" "); + } + pw.printf("%02x", data.get(i)); + } + w.append('\n'); + } + + private boolean read_config(InputStream stream) throws IOException { + config = AltosJson.fromInputStream(stream); + if (config == null) + return false; + return true; + } + + private String read_line(InputStream stream) throws IOException { + StringBuffer buffer = null; + int c; + + for (;;) { + c = stream.read(); + if (c == -1 && buffer == null) + return null; + if (buffer == null) + buffer = new StringBuffer(); + if (c == -1 || c == '\n') + return buffer.toString(); + buffer.append((char) c); + } + } + + private boolean read_data(InputStream stream) throws IOException { + String s; + + data = new ArrayList(); + while ((s = read_line(stream)) != null) { + + String[] tokens = s.split("\\s+"); + + for (int i = 0; i < tokens.length; i++) { + if (tokens[i].length() > 0) { + try { + data.add((byte) AltosLib.fromhex(tokens[i])); + } catch (NumberFormatException e) { + throw new IOException(e.toString()); + } + } + } + } + return true; + } + + private boolean read_old_config(InputStream stream) throws IOException { + AltosConfigData cfg = new AltosConfigData(); + for (;;) { + boolean done = false; + + /* The data starts with an upper case F character followed by a space */ + stream.mark(2); + int first = stream.read(); + if (first == 'F') { + int second = stream.read(); + if (second == ' ') + done = true; + } + stream.reset(); + if (done) + break; + + String line = read_line(stream); + if (line == null) + return false; + cfg.parse_line(line); + } + config = new AltosJson(cfg); + return true; + } + + private boolean read_old_data(InputStream stream) throws IOException { + String line; + + data = new ArrayList(); + while ((line = read_line(stream)) != null) { + String[] tokens = line.split("\\s+"); + + /* Make sure there's at least a type and time */ + if (tokens.length < 2) + break; + + /* packet type */ + if (tokens[0].length() != 1) + break; + int start = data.size(); + + if (config_data().log_format != AltosLib.AO_LOG_FORMAT_TINY) { + byte cmd = (byte) tokens[0].codePointAt(0); + data.add(cmd); + + int time = AltosLib.fromhex(tokens[1]); + + data.add((byte) 0); + data.add((byte) (time & 0xff)); + data.add((byte) (time >> 8)); + } + if (tokens.length == 4) { + /* Handle ancient log files */ + if (config_data().log_format == AltosLib.AO_LOG_FORMAT_TINY) { + /* + * Ancient TeleMini log files stored "extra" data to pretend + * that it was a TeleMetrum device. Throw that away and + * just save the actual log data. + */ + int a = AltosLib.fromhex(tokens[2]); + int b = AltosLib.fromhex(tokens[3]); + if (a != 0) + b = 0x8000 | a; + data.add((byte) (b & 0xff)); + data.add((byte) ((b >> 8))); + } else { + for (int i = 2; i < tokens.length; i++) { + int v = AltosLib.fromhex(tokens[i]); + data.add((byte) (v & 0xff)); + data.add((byte) ((v >> 8))); + } + /* Re-compute the checksum byte */ + data.set(start + 1, (byte) (256 - AltosConvert.checksum(data, start, data.size() - start))); + } + } else { + for (int i = 2; i < tokens.length; i++) + data.add((byte) AltosLib.fromhex(tokens[i])); + /* Re-compute the checksum byte */ + data.set(start + 1, (byte) (256 - AltosConvert.checksum(data, start, data.size() - start))); + } + } + return true; + } + + private void read(InputStream stream) throws IOException { + BufferedInputStream bis = new BufferedInputStream(stream); + + bis.mark(1); + int c = bis.read(); + bis.reset(); + + if (c == '{') { + if (!read_config(bis)) + throw new IOException("failed to read config"); + if (!read_data(bis)) + throw new IOException("failed to read data"); + } else { + if (!read_old_config(bis)) + throw new IOException("failed to read old config"); + if (!read_old_data(bis)) + throw new IOException("failed to read old data"); + } + } + + /* + * Public APIs for I/O + */ + public void write(Writer w) throws IOException { + write_config(w); + write_data(w); + } + + public String toString() { + try { + Writer w = new StringWriter(); + + write(w); + return w.toString(); + } catch (Exception e) { + return null; + } + } + + public void print() throws IOException { + System.out.printf("%s", toString()); + } + + /* + * Constructors + */ + public AltosEeprom(InputStream stream) throws IOException { + read(stream); + } + + public AltosEeprom(String s) throws IOException { + read(new AltosStringInputStream(s)); + } + + public AltosEeprom(AltosJson config, ArrayList data) { + this.config = config; + this.data = data; + } + + public AltosEeprom(AltosConfigData config_data, ArrayList data) { + this.config = new AltosJson(config_data); + this.data = data; + } + + public AltosEeprom() { + } +} diff --git a/altoslib/AltosEepromDownload.java b/altoslib/AltosEepromDownload.java index 8a2053ec..961b32cd 100644 --- a/altoslib/AltosEepromDownload.java +++ b/altoslib/AltosEepromDownload.java @@ -181,7 +181,7 @@ public class AltosEepromDownload implements Runnable { } /* Construct our internal representation of the eeprom data */ - AltosEepromNew eeprom = new AltosEepromNew(flights.config_data, data); + AltosEeprom eeprom = new AltosEeprom(flights.config_data, data); /* Now see if we can't actually parse the resulting * file to generate a better filename. Note that this diff --git a/altoslib/AltosEepromNew.java b/altoslib/AltosEepromNew.java deleted file mode 100644 index c373bff3..00000000 --- a/altoslib/AltosEepromNew.java +++ /dev/null @@ -1,291 +0,0 @@ -/* - * Copyright © 2017 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, either version 2 of the License, or - * (at your option) any later version. - * - * 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. - */ - -package org.altusmetrum.altoslib_11; - -import java.util.*; -import java.io.*; - -public class AltosEepromNew { - - private AltosJson config; - ArrayList data; - private AltosConfigData config_data; - - /* - * Public accessor APIs - */ - public int data8(int offset) { - return ((int) data.get(offset)) & 0xff; - } - - public int data16(int offset) { - return data8(offset) | (data8(offset+1) << 8); - } - - public int data24(int offset) { - return (data8(offset) | - (data8(offset+1) << 8) | - (data8(offset+2) << 16)); - } - - public int data32(int offset) { - return (data8(offset) | - (data8(offset+1) << 8) | - (data8(offset+2) << 16) | - (data8(offset+3) << 24)); - } - - public int size() { - return data.size(); - } - - public AltosConfigData config_data() { - if (config_data == null) { - config_data = (AltosConfigData) config.make(AltosConfigData.class); - if (config_data == null) - config_data = new AltosConfigData(); - - if (config_data.log_format == AltosLib.AO_LOG_FORMAT_UNKNOWN) { - config_data.log_format = AltosLib.AO_LOG_FORMAT_FULL; - if (config_data.product != null) { - if (config_data.product.startsWith("TeleMetrum")) - config_data.log_format = AltosLib.AO_LOG_FORMAT_FULL; - else if (config_data.product.startsWith("TeleMini")) - config_data.log_format = AltosLib.AO_LOG_FORMAT_TINY; - } - } - } - return config_data; - } - - private void write_config(Writer w) throws IOException { - config.write(w, 0, true); - w.append('\n'); - } - - /* - * Private I/O APIs - */ - private void write_data(Writer w) throws IOException { - PrintWriter pw = new PrintWriter(w); - - for (int i = 0; i < data.size(); i++) { - if (i > 0) { - if ((i & 0x1f) == 0) - pw.printf("\n"); - else - pw.printf(" "); - } - pw.printf("%02x", data.get(i)); - } - w.append('\n'); - } - - private boolean read_config(InputStream stream) throws IOException { - config = AltosJson.fromInputStream(stream); - if (config == null) - return false; - return true; - } - - private String read_line(InputStream stream) throws IOException { - StringBuffer buffer = null; - int c; - - for (;;) { - c = stream.read(); - if (c == -1 && buffer == null) - return null; - if (buffer == null) - buffer = new StringBuffer(); - if (c == -1 || c == '\n') - return buffer.toString(); - buffer.append((char) c); - } - } - - private boolean read_data(InputStream stream) throws IOException { - String s; - - data = new ArrayList(); - while ((s = read_line(stream)) != null) { - - String[] tokens = s.split("\\s+"); - - for (int i = 0; i < tokens.length; i++) { - if (tokens[i].length() > 0) { - try { - data.add((byte) AltosLib.fromhex(tokens[i])); - } catch (NumberFormatException e) { - throw new IOException(e.toString()); - } - } - } - } - return true; - } - - private boolean read_old_config(InputStream stream) throws IOException { - AltosConfigData cfg = new AltosConfigData(); - for (;;) { - boolean done = false; - - /* The data starts with an upper case F character followed by a space */ - stream.mark(2); - int first = stream.read(); - if (first == 'F') { - int second = stream.read(); - if (second == ' ') - done = true; - } - stream.reset(); - if (done) - break; - - String line = read_line(stream); - if (line == null) - return false; - cfg.parse_line(line); - } - config = new AltosJson(cfg); - return true; - } - - private boolean read_old_data(InputStream stream) throws IOException { - String line; - - data = new ArrayList(); - while ((line = read_line(stream)) != null) { - String[] tokens = line.split("\\s+"); - - /* Make sure there's at least a type and time */ - if (tokens.length < 2) - break; - - /* packet type */ - if (tokens[0].length() != 1) - break; - int start = data.size(); - - if (config_data().log_format != AltosLib.AO_LOG_FORMAT_TINY) { - byte cmd = (byte) tokens[0].codePointAt(0); - data.add(cmd); - - int time = AltosLib.fromhex(tokens[1]); - - data.add((byte) 0); - data.add((byte) (time & 0xff)); - data.add((byte) (time >> 8)); - } - if (tokens.length == 4) { - /* Handle ancient log files */ - if (config_data().log_format == AltosLib.AO_LOG_FORMAT_TINY) { - /* - * Ancient TeleMini log files stored "extra" data to pretend - * that it was a TeleMetrum device. Throw that away and - * just save the actual log data. - */ - int a = AltosLib.fromhex(tokens[2]); - int b = AltosLib.fromhex(tokens[3]); - if (a != 0) - b = 0x8000 | a; - data.add((byte) (b & 0xff)); - data.add((byte) ((b >> 8))); - } else { - for (int i = 2; i < tokens.length; i++) { - int v = AltosLib.fromhex(tokens[i]); - data.add((byte) (v & 0xff)); - data.add((byte) ((v >> 8))); - } - /* Re-compute the checksum byte */ - data.set(start + 1, (byte) (256 - AltosConvert.checksum(data, start, data.size() - start))); - } - } else { - for (int i = 2; i < tokens.length; i++) - data.add((byte) AltosLib.fromhex(tokens[i])); - /* Re-compute the checksum byte */ - data.set(start + 1, (byte) (256 - AltosConvert.checksum(data, start, data.size() - start))); - } - } - return true; - } - - private void read(InputStream stream) throws IOException { - BufferedInputStream bis = new BufferedInputStream(stream); - - bis.mark(1); - int c = bis.read(); - bis.reset(); - - if (c == '{') { - if (!read_config(bis)) - throw new IOException("failed to read config"); - if (!read_data(bis)) - throw new IOException("failed to read data"); - } else { - if (!read_old_config(bis)) - throw new IOException("failed to read old config"); - if (!read_old_data(bis)) - throw new IOException("failed to read old data"); - } - } - - /* - * Public APIs for I/O - */ - public void write(Writer w) throws IOException { - write_config(w); - write_data(w); - } - - public String toString() { - try { - Writer w = new StringWriter(); - - write(w); - return w.toString(); - } catch (Exception e) { - return null; - } - } - - public void print() throws IOException { - System.out.printf("%s", toString()); - } - - /* - * Constructors - */ - public AltosEepromNew(InputStream stream) throws IOException { - read(stream); - } - - public AltosEepromNew(String s) throws IOException { - read(new AltosStringInputStream(s)); - } - - public AltosEepromNew(AltosJson config, ArrayList data) { - this.config = config; - this.data = data; - } - - public AltosEepromNew(AltosConfigData config_data, ArrayList data) { - this.config = new AltosJson(config_data); - this.data = data; - } - - public AltosEepromNew() { - } -} diff --git a/altoslib/AltosEepromRecord.java b/altoslib/AltosEepromRecord.java index 75fe5381..c479a621 100644 --- a/altoslib/AltosEepromRecord.java +++ b/altoslib/AltosEepromRecord.java @@ -16,7 +16,7 @@ package org.altusmetrum.altoslib_11; public abstract class AltosEepromRecord implements Comparable { - AltosEepromNew eeprom; + AltosEeprom eeprom; int wide_tick; @@ -115,7 +115,7 @@ public abstract class AltosEepromRecord implements Comparable public abstract AltosEepromRecord next(); - public AltosEepromRecord(AltosEepromNew eeprom, int start, int length) { + public AltosEepromRecord(AltosEeprom eeprom, int start, int length) { this.eeprom = eeprom; this.start = start; this.length = length; diff --git a/altoslib/AltosEepromRecordFireTwo.java b/altoslib/AltosEepromRecordFireTwo.java index 713d0bb7..48d480c5 100644 --- a/altoslib/AltosEepromRecordFireTwo.java +++ b/altoslib/AltosEepromRecordFireTwo.java @@ -92,11 +92,11 @@ public class AltosEepromRecordFireTwo extends AltosEepromRecord { return new AltosEepromRecordFireTwo(eeprom, s); } - public AltosEepromRecordFireTwo(AltosEepromNew eeprom, int start) { + public AltosEepromRecordFireTwo(AltosEeprom eeprom, int start) { super(eeprom, start, record_length); } - public AltosEepromRecordFireTwo(AltosEepromNew eeprom) { + public AltosEepromRecordFireTwo(AltosEeprom eeprom) { this(eeprom, 0); } } diff --git a/altoslib/AltosEepromRecordFull.java b/altoslib/AltosEepromRecordFull.java index c29da025..10ae0bef 100644 --- a/altoslib/AltosEepromRecordFull.java +++ b/altoslib/AltosEepromRecordFull.java @@ -104,11 +104,11 @@ public class AltosEepromRecordFull extends AltosEepromRecord { return new AltosEepromRecordFull(eeprom, s); } - public AltosEepromRecordFull(AltosEepromNew eeprom, int start) { + public AltosEepromRecordFull(AltosEeprom eeprom, int start) { super(eeprom, start, record_length); } - public AltosEepromRecordFull(AltosEepromNew eeprom) { + public AltosEepromRecordFull(AltosEeprom eeprom) { this(eeprom, 0); } } diff --git a/altoslib/AltosEepromRecordGps.java b/altoslib/AltosEepromRecordGps.java index a992abff..ee76d073 100644 --- a/altoslib/AltosEepromRecordGps.java +++ b/altoslib/AltosEepromRecordGps.java @@ -135,11 +135,11 @@ public class AltosEepromRecordGps extends AltosEepromRecord { return new AltosEepromRecordGps(eeprom, s); } - public AltosEepromRecordGps(AltosEepromNew eeprom, int start) { + public AltosEepromRecordGps(AltosEeprom eeprom, int start) { super(eeprom, start, record_length); } - public AltosEepromRecordGps(AltosEepromNew eeprom) { + public AltosEepromRecordGps(AltosEeprom eeprom) { this(eeprom, 0); } } diff --git a/altoslib/AltosEepromRecordMega.java b/altoslib/AltosEepromRecordMega.java index d0da1b7c..fdbbd6f7 100644 --- a/altoslib/AltosEepromRecordMega.java +++ b/altoslib/AltosEepromRecordMega.java @@ -249,12 +249,12 @@ public class AltosEepromRecordMega extends AltosEepromRecord { return new AltosEepromRecordMega(eeprom, s); } - public AltosEepromRecordMega(AltosEepromNew eeprom, int start) { + public AltosEepromRecordMega(AltosEeprom eeprom, int start) { super(eeprom, start, record_length); log_format = eeprom.config_data().log_format; } - public AltosEepromRecordMega(AltosEepromNew eeprom) { + public AltosEepromRecordMega(AltosEeprom eeprom) { this(eeprom, 0); } } diff --git a/altoslib/AltosEepromRecordMetrum.java b/altoslib/AltosEepromRecordMetrum.java index 248709b3..65d8f086 100644 --- a/altoslib/AltosEepromRecordMetrum.java +++ b/altoslib/AltosEepromRecordMetrum.java @@ -135,11 +135,11 @@ public class AltosEepromRecordMetrum extends AltosEepromRecord { return new AltosEepromRecordMetrum(eeprom, s); } - public AltosEepromRecordMetrum(AltosEepromNew eeprom, int start) { + public AltosEepromRecordMetrum(AltosEeprom eeprom, int start) { super(eeprom, start, record_length); } - public AltosEepromRecordMetrum(AltosEepromNew eeprom) { + public AltosEepromRecordMetrum(AltosEeprom eeprom) { this(eeprom, 0); } } diff --git a/altoslib/AltosEepromRecordMini.java b/altoslib/AltosEepromRecordMini.java index 22bd073a..787f4e0d 100644 --- a/altoslib/AltosEepromRecordMini.java +++ b/altoslib/AltosEepromRecordMini.java @@ -95,11 +95,11 @@ public class AltosEepromRecordMini extends AltosEepromRecord { return new AltosEepromRecordMini(eeprom, s); } - public AltosEepromRecordMini(AltosEepromNew eeprom, int start) { + public AltosEepromRecordMini(AltosEeprom eeprom, int start) { super(eeprom, start, record_length); } - public AltosEepromRecordMini(AltosEepromNew eeprom) { + public AltosEepromRecordMini(AltosEeprom eeprom) { this(eeprom, 0); } } diff --git a/altoslib/AltosEepromRecordSet.java b/altoslib/AltosEepromRecordSet.java index 1f10e677..df1aad9f 100644 --- a/altoslib/AltosEepromRecordSet.java +++ b/altoslib/AltosEepromRecordSet.java @@ -18,7 +18,7 @@ import java.io.*; import java.util.*; public class AltosEepromRecordSet implements AltosRecordSet { - AltosEepromNew eeprom; + AltosEeprom eeprom; TreeSet ordered; AltosCalData cal_data; @@ -50,7 +50,7 @@ public class AltosEepromRecordSet implements AltosRecordSet { listener.finish(); } - public AltosEepromRecordSet(AltosEepromNew eeprom) { + public AltosEepromRecordSet(AltosEeprom eeprom) { this.eeprom = eeprom; AltosConfigData config_data = eeprom.config_data(); @@ -115,6 +115,6 @@ public class AltosEepromRecordSet implements AltosRecordSet { } public AltosEepromRecordSet(InputStream input) throws IOException { - this(new AltosEepromNew(input)); + this(new AltosEeprom(input)); } } diff --git a/altoslib/AltosEepromRecordTiny.java b/altoslib/AltosEepromRecordTiny.java index 70960a2a..628e18c3 100644 --- a/altoslib/AltosEepromRecordTiny.java +++ b/altoslib/AltosEepromRecordTiny.java @@ -77,11 +77,11 @@ public class AltosEepromRecordTiny extends AltosEepromRecord implements AltosDat return new AltosEepromRecordTiny(eeprom, s); } - public AltosEepromRecordTiny(AltosEepromNew eeprom, int start) { + public AltosEepromRecordTiny(AltosEeprom eeprom, int start) { super(eeprom, start, record_length); } - public AltosEepromRecordTiny(AltosEepromNew eeprom) { + public AltosEepromRecordTiny(AltosEeprom eeprom) { this(eeprom, 0); } } diff --git a/altoslib/Makefile.am b/altoslib/Makefile.am index ce934b4f..11b5d562 100644 --- a/altoslib/Makefile.am +++ b/altoslib/Makefile.am @@ -35,7 +35,7 @@ altoslib_JAVA = \ AltosCRCException.java \ AltosCSV.java \ AltosDebug.java \ - AltosEepromNew.java \ + AltosEeprom.java \ AltosRecordSet.java \ AltosEepromRecord.java \ AltosEepromRecordFull.java \ -- cgit v1.2.3