From f26cfe417c6977cf1e7e75a4f050e25f64d41859 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 25 May 2017 17:24:14 -0700 Subject: [PATCH] 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 +++ ...tateUpdate.java => AltosDataProvider.java} | 4 +- 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/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 +- 65 files changed, 2070 insertions(+), 1375 deletions(-) create mode 100644 altoslib/AltosCalData.java create mode 100644 altoslib/AltosDataListener.java rename altoslib/{AltosStateUpdate.java => AltosDataProvider.java} (83%) create mode 100644 altoslib/AltosGPSTimeValue.java create mode 100644 altoslib/AltosPresTemp.java create mode 100644 altoslib/AltosStateName.java create mode 100644 altoslib/AltosTelemetryRecordSet.java 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/AltosStateUpdate.java b/altoslib/AltosDataProvider.java similarity index 83% rename from altoslib/AltosStateUpdate.java rename to altoslib/AltosDataProvider.java index e9698cba..e55071cf 100644 --- a/altoslib/AltosStateUpdate.java +++ b/altoslib/AltosDataProvider.java @@ -18,6 +18,6 @@ package org.altusmetrum.altoslib_11; -public interface AltosStateUpdate { - public void update_state(AltosState state) throws InterruptedException, AltosUnknownProduct; +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/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 \ -- 2.30.2