X-Git-Url: https://git.gag.com/?p=fw%2Faltos;a=blobdiff_plain;f=micropeak%2FMicroData.java;h=96053ac55ca712c8e8c45f12441eff8ed5779c7d;hp=473af44bc691da619c51deef5988039717d0582f;hb=HEAD;hpb=8d1d8d2a3c129cdbd55427bcda0f26715b02f1ee diff --git a/micropeak/MicroData.java b/micropeak/MicroData.java index 473af44b..4a53482c 100644 --- a/micropeak/MicroData.java +++ b/micropeak/MicroData.java @@ -3,7 +3,8 @@ * * 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. + * 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 @@ -20,59 +21,38 @@ package org.altusmetrum.micropeak; import java.lang.*; import java.io.*; import java.util.*; -import org.altusmetrum.altoslib_1.*; - -class MicroIterator implements Iterator { - int i; - MicroData data; - - public boolean hasNext() { - return i < data.pressures.length; - } - - public MicroDataPoint next() { - return new MicroDataPoint(data, i++); - } - - public MicroIterator (MicroData data) { - this.data = data; - i = 0; - } - - public void remove() { - } -} - -class MicroIterable implements Iterable { - - MicroData data; - - public Iterator iterator() { - return new MicroIterator(data); - } - - public MicroIterable(MicroData data) { - this.data = data; - } -} +import org.altusmetrum.altoslib_14.*; +import org.altusmetrum.altosuilib_14.*; public class MicroData { public int ground_pressure; public int min_pressure; - public int[] pressures; + + AltosUIFlightSeries flight_series; + AltosFlightStats flight_stats; + AltosCalData cal_data; + private double time_step; - private double ground_altitude; private ArrayList bytes; + public int nsamples; + public int log_id; String name; - + String unique_id; + + public static final int LOG_ID_MICROPEAK = 0; + public static final int LOG_ID_MICROKITE = 1; + public static final int LOG_ID_MICROPEAK2 = 2; + + public static final double CLOCK_MP1 = 0.096; + public static final double CLOCK_MP2 = 0.1; - class FileEndedException extends Exception { + public class FileEndedException extends Exception { } - class NonHexcharException extends Exception { + public class NonHexcharException extends Exception { } - class InvalidCrcException extends Exception { + public class InvalidCrcException extends Exception { } private int getc(InputStream f) throws IOException, FileEndedException { @@ -133,16 +113,12 @@ public class MicroData { return h; } - private boolean find_header(InputStream f) throws IOException { - try { - for (;;) { - if (get_nonwhite(f) == 'M' && get_nonwhite(f) == 'P') - return true; - } - } catch (FileEndedException fe) { - return false; + private boolean find_header(InputStream f) throws IOException, FileEndedException { + for (;;) { + if (get_nonwhite(f) == 'M' && get_nonwhite(f) == 'P') + return true; } - } + } private int get_32(InputStream f) throws IOException, FileEndedException, NonHexcharException { int v = 0; @@ -160,12 +136,29 @@ public class MicroData { return v; } + private String get_line(InputStream f) throws IOException, FileEndedException, NonHexcharException { + int c; + StringBuffer line = new StringBuffer(); + + do { + c = f.read(); + } while (Character.isWhitespace(c)); + + do { + line.append((char) c); + c = f.read(); + } while (!Character.isWhitespace(c)); + return new String(line); + } + private int swap16(int i) { return ((i << 8) & 0xff00) | ((i >> 8) & 0xff); } public boolean crc_valid; + public boolean log_empty; + int mix_in (int high, int low) { return high - (high & 0xffff) + low; } @@ -174,61 +167,45 @@ public class MicroData { return Math.abs (target - a) < Math.abs(target - b); } - public double altitude(int i) { - return AltosConvert.pressure_to_altitude(pressures[i]); - } - - public Iterable points() { - return new MicroIterable(this); + public double altitude(double time) { + if (flight_series.altitude_series == null) + return 0.0; + return flight_series.altitude_series.value(time); } - int fact(int n) { - if (n == 0) - return 1; - return n * fact(n-1); + public double altitude(int i) { + return altitude(time(i)); } - int choose(int n, int k) { - return fact(n) / (fact(k) * fact(n-k)); + public String name() { + return name; } + public double pressure(int i) { + if (flight_series.pressure_series == null) + return 0.0; - public double avg_altitude(int center, int dist) { - int start = center - dist; - int stop = center + dist; - - if (start < 0) - start = 0; - if (stop >= pressures.length) - stop = pressures.length - 1; - - double sum = 0; - double div = 0; - - int n = dist * 2; - - for (int i = start; i <= stop; i++) { - int k = i - (center - dist); - int c = choose (n, k); - - sum += c * pressures[i]; - div += c; - } + return flight_series.pressure_series.value(time(i)); + } - double pres = sum / div; + public double height(double time) { + if (flight_series.height_series == null) + return 0.0; - double alt = AltosConvert.pressure_to_altitude(pres); - return alt; + return flight_series.height_series.value(time); } - public double pressure(int i) { - return pressures[i]; + public double height(int i) { + return height(time(i)); } - public double height(int i) { - return altitude(i) - ground_altitude; + public int length() { + if (flight_series.pressure_series == null) + return 0; + return flight_series.pressure_series.size(); } + /* Use the recorded apogee pressure for stats so that it agrees with the device */ public double apogee_pressure() { return min_pressure; } @@ -238,31 +215,27 @@ public class MicroData { } public double apogee_height() { - return apogee_altitude() - ground_altitude; + return apogee_altitude() - cal_data.ground_altitude; } - static final int speed_avg = 3; - static final int accel_avg = 5; - - private double avg_speed(int center, int dist) { - if (center == 0) - return 0; - - double ai = avg_altitude(center, dist); - double aj = avg_altitude(center - 1, dist); - double s = (ai - aj) / time_step; - - return s; + public double speed(double time) { + if (flight_series.speed_series == null) + return 0.0; + return flight_series.speed_series.value(time); } public double speed(int i) { - return avg_speed(i, speed_avg); + return speed(time(i)); + } + + public double acceleration(double time) { + if (flight_series.accel_series == null) + return 0.0; + return flight_series.accel_series.value(time); } public double acceleration(int i) { - if (i == 0) - return 0; - return (avg_speed(i, accel_avg) - avg_speed(i-1, accel_avg)) / time_step; + return acceleration(time(i)); } public double time(int i) { @@ -275,21 +248,36 @@ public class MicroData { f.write('\n'); } + public boolean is_empty() { + boolean empty = true; + for (int c : bytes) { + if (!Character.isWhitespace(c) && c != 'f') + empty = false; + } + return empty; + } + public void export (Writer f) throws IOException { PrintWriter pw = new PrintWriter(f); pw.printf(" Time, Press(Pa), Height(m), Height(f), Speed(m/s), Speed(mph), Speed(mach), Accel(m/s²), Accel(ft/s²), Accel(g)\n"); - for (MicroDataPoint point : points()) { + + for (AltosTimeValue ptv : flight_series.pressure_series) { + + double height = height(ptv.time); + double speed = speed(ptv.time); + double accel = acceleration(ptv.time); + pw.printf("%6.3f,%10.0f,%10.1f,%10.1f,%11.2f,%11.2f,%12.4f,%12.2f,%13.2f,%10.4f\n", - point.time, - point.pressure, - point.height, - AltosConvert.meters_to_feet(point.height), - point.speed, - AltosConvert.meters_to_mph(point.speed), - AltosConvert.meters_to_mach(point.speed), - point.accel, - AltosConvert.meters_to_feet(point.accel), - AltosConvert.meters_to_g(point.accel)); + ptv.time, + ptv.value, + height, + AltosConvert.meters_to_feet(height), + speed, + AltosConvert.meters_to_mph(speed), + AltosConvert.meters_to_mach(speed), + accel, + AltosConvert.meters_to_feet(accel), + AltosConvert.meters_to_g(accel)); } } @@ -297,21 +285,58 @@ public class MicroData { this.name = name; } - public MicroData (InputStream f, String name) throws IOException, InterruptedException { + public MicroData() { + ground_pressure = 101000; + min_pressure = 101000; + cal_data = new AltosCalData(); + flight_series = new AltosUIFlightSeries(cal_data); + } + + public MicroData (InputStream f, String name) throws IOException, InterruptedException, NonHexcharException, FileEndedException { this.name = name; bytes = new ArrayList(); + + cal_data = new AltosCalData(); + flight_series = new AltosUIFlightSeries(cal_data); + if (!find_header(f)) throw new IOException("No MicroPeak data header found"); try { file_crc = 0xffff; ground_pressure = get_32(f); min_pressure = get_32(f); - int nsamples = get_16(f); - pressures = new int[nsamples + 1]; + nsamples = get_16(f); + + log_id = nsamples >> 12; + nsamples &= 0xfff; + if (log_id == LOG_ID_MICROPEAK2) { + int nsamples_high = get_16(f); + nsamples |= (nsamples_high << 12); + } + + cal_data.set_ground_pressure(ground_pressure); + + switch (log_id) { + case LOG_ID_MICROPEAK: + time_step = 2 * CLOCK_MP1; + break; + case LOG_ID_MICROKITE: + time_step = 200 * CLOCK_MP1; + break; + case LOG_ID_MICROPEAK2: + time_step = CLOCK_MP2; + break; + default: + throw new IOException(String.format("Unknown device type: %d", log_id)); + } + cal_data.set_ticks_per_sec(1/time_step); + cal_data.set_tick(0); + cal_data.set_boost_tick(); - ground_altitude = AltosConvert.pressure_to_altitude(ground_pressure); int cur = ground_pressure; - pressures[0] = cur; + cal_data.set_tick(0); + flight_series.set_time(cal_data.time()); + flight_series.set_pressure(cur); for (int i = 0; i < nsamples; i++) { int k = get_16(f); int same = mix_in(cur, k); @@ -329,28 +354,55 @@ public class MicroData { else cur = down; } - - pressures[i+1] = cur; + + cal_data.set_tick(i+1); + flight_series.set_time(cal_data.time()); + flight_series.set_pressure(cur); } int current_crc = swap16(~file_crc & 0xffff); int crc = get_16(f); - crc_valid = crc == current_crc; + crc_valid = (crc == current_crc); + + if (!crc_valid && is_empty()) { + crc_valid = true; + nsamples = 0; + } + + if (log_id == LOG_ID_MICROPEAK2) { + unique_id = get_line(f); + } + + flight_series.finish(); + + /* Build states */ + + flight_series.set_time(0); + flight_series.set_state(AltosLib.ao_flight_boost); + + if (flight_series.speed_series != null && flight_series.speed_series.max() != null) { + flight_series.set_time(flight_series.speed_series.max().time); + flight_series.set_state(AltosLib.ao_flight_coast); + } + + flight_series.set_time(flight_series.height_series.max().time); + flight_series.set_state(AltosLib.ao_flight_drogue); + + cal_data.set_tick(nsamples); + flight_series.set_time(cal_data.time()); + flight_series.set_state(AltosLib.ao_flight_landed); + + flight_series.set_min_pressure(min_pressure); + + flight_series.finish(); + + flight_stats = new AltosFlightStats(flight_series); + - time_step = 0.192; } catch (FileEndedException fe) { throw new IOException("File Ended Unexpectedly"); - } catch (NonHexcharException ne) { - throw new IOException("Non hexadecimal character found"); } } - public MicroData() { - ground_pressure = 101000; - min_pressure = 101000; - pressures = new int[1]; - pressures[0] = 101000; - } - }