diff options
Diffstat (limited to 'altoslib')
-rw-r--r-- | altoslib/AltosConvert.java | 6 | ||||
-rw-r--r-- | altoslib/AltosEepromFile.java | 64 | ||||
-rw-r--r-- | altoslib/AltosEepromHeader.java | 13 | ||||
-rw-r--r-- | altoslib/AltosEepromHeaderIterable.java | 2 | ||||
-rw-r--r-- | altoslib/AltosEepromIterable.java | 72 | ||||
-rw-r--r-- | altoslib/AltosEepromMini.java | 17 | ||||
-rw-r--r-- | altoslib/AltosEepromMiniIterable.java | 2 | ||||
-rw-r--r-- | altoslib/AltosEepromTM.java | 249 | ||||
-rw-r--r-- | altoslib/AltosFlightReader.java | 2 | ||||
-rw-r--r-- | altoslib/AltosGPS.java | 10 | ||||
-rw-r--r-- | altoslib/AltosIMU.java | 1 | ||||
-rw-r--r-- | altoslib/AltosLib.java | 4 | ||||
-rw-r--r-- | altoslib/AltosRecord.java | 8 | ||||
-rw-r--r-- | altoslib/AltosReplayReader.java | 6 | ||||
-rw-r--r-- | altoslib/AltosState.java | 425 | ||||
-rw-r--r-- | altoslib/AltosStateIterable.java | 29 | ||||
-rw-r--r-- | altoslib/AltosTelemetryReader.java | 6 | ||||
-rw-r--r-- | altoslib/Makefile.am | 3 |
18 files changed, 594 insertions, 325 deletions
diff --git a/altoslib/AltosConvert.java b/altoslib/AltosConvert.java index 8cd478e2..a1e2cdca 100644 --- a/altoslib/AltosConvert.java +++ b/altoslib/AltosConvert.java @@ -190,6 +190,12 @@ public class AltosConvert { return ignite / 32767 * 15.0; } + public static double + barometer_to_pressure(double count) + { + return ((count / 16.0) / 2047.0 + 0.095) / 0.009 * 1000.0; + } + public static double radio_to_frequency(int freq, int setting, int cal, int channel) { double f; diff --git a/altoslib/AltosEepromFile.java b/altoslib/AltosEepromFile.java index 48d2543c..bcc7171e 100644 --- a/altoslib/AltosEepromFile.java +++ b/altoslib/AltosEepromFile.java @@ -21,11 +21,47 @@ import java.io.*; import java.util.*; import java.text.*; -public class AltosEepromFile { +class AltosEepromIterator implements Iterator<AltosState> { + AltosState state; + Iterator<AltosEeprom> body; + AltosEeprom next; + boolean seen; + + public boolean hasNext() { + return !seen || body.hasNext(); + } + + public AltosState next() { + if (seen) { + AltosState n = state.clone(); + AltosEeprom e = body.next(); + + e.update_state(n); + state = n; + } + seen = true; + return state; + } + + public void remove () { + } + + public AltosEepromIterator(AltosState start, Iterator<AltosEeprom> body) { + this.state = start; + this.body = body; + this.seen = false; + } +} + +public class AltosEepromFile extends AltosStateIterable { AltosEepromIterable headers; AltosEepromIterable body; + public void write_comments(PrintStream out) { + headers.write(out); + } + public void write(PrintStream out) { headers.write(out); body.write(out); @@ -38,14 +74,38 @@ public class AltosEepromFile { switch (state.log_format) { case AltosLib.AO_LOG_FORMAT_FULL: + body = new AltosEepromIterable(AltosEepromTM.read(input)); + break; case AltosLib.AO_LOG_FORMAT_TINY: case AltosLib.AO_LOG_FORMAT_TELEMETRY: case AltosLib.AO_LOG_FORMAT_TELESCIENCE: case AltosLib.AO_LOG_FORMAT_TELEMEGA: break; - case AltosLib.AO_LOG_FORMAT_MINI: + case AltosLib.AO_LOG_FORMAT_TELEMINI: + case AltosLib.AO_LOG_FORMAT_EASYMINI: body = new AltosEepromIterable(AltosEepromMini.read(input)); break; } } + + int boost_tick (AltosState start) { + AltosState state = start.clone(); + for (AltosEeprom eeprom : body) { + eeprom.update_state(state); + if (state.state >= AltosLib.ao_flight_boost) + return state.tick; + } + return 0; + } + + public Iterator<AltosState> iterator() { + + AltosState state = headers.state(); + Iterator<AltosEeprom> i = body.iterator(); + + while (i.hasNext() && !state.valid()) + i.next().update_state(state); + state.set_boost_tick(boost_tick(state)); + return new AltosEepromIterator(state, i); + } }
\ No newline at end of file diff --git a/altoslib/AltosEepromHeader.java b/altoslib/AltosEepromHeader.java index b2343dc6..a06f05ed 100644 --- a/altoslib/AltosEepromHeader.java +++ b/altoslib/AltosEepromHeader.java @@ -43,8 +43,7 @@ public class AltosEepromHeader extends AltosEeprom { state.callsign = data; break; case AltosLib.AO_LOG_ACCEL_CAL: - state.accel_plus_g = config_a; - state.accel_minus_g = config_b; + state.set_accel_g(config_a, config_b); break; case AltosLib.AO_LOG_RADIO_CAL: break; @@ -56,30 +55,38 @@ public class AltosEepromHeader extends AltosEeprom { state.log_format = config_a; break; case AltosLib.AO_LOG_SERIAL_NUMBER: - state.serial = config_a; + state.set_serial(config_a); break; case AltosLib.AO_LOG_BARO_RESERVED: + state.make_baro(); state.baro.reserved = config_a; break; case AltosLib.AO_LOG_BARO_SENS: + state.make_baro(); state.baro.sens = config_a; break; case AltosLib.AO_LOG_BARO_OFF: + state.make_baro(); state.baro.off = config_a; break; case AltosLib.AO_LOG_BARO_TCS: + state.make_baro(); state.baro.tcs = config_a; break; case AltosLib.AO_LOG_BARO_TCO: + state.make_baro(); state.baro.tco = config_a; break; case AltosLib.AO_LOG_BARO_TREF: + state.make_baro(); state.baro.tref = config_a; break; case AltosLib.AO_LOG_BARO_TEMPSENS: + state.make_baro(); state.baro.tempsens = config_a; break; case AltosLib.AO_LOG_BARO_CRC: + state.make_baro(); state.baro.crc = config_a; break; case AltosLib.AO_LOG_SOFTWARE_VERSION: diff --git a/altoslib/AltosEepromHeaderIterable.java b/altoslib/AltosEepromHeaderIterable.java index fe9e05d9..01953f0e 100644 --- a/altoslib/AltosEepromHeaderIterable.java +++ b/altoslib/AltosEepromHeaderIterable.java @@ -29,7 +29,7 @@ public class AltosEepromHeaderIterable implements Iterable<AltosEepromHeader> { } public AltosState state() { - AltosState state = new AltosState(null); + AltosState state = new AltosState(); for (AltosEepromHeader header : headers) header.update_state(state); diff --git a/altoslib/AltosEepromIterable.java b/altoslib/AltosEepromIterable.java index 470a7a8a..8e6a2313 100644 --- a/altoslib/AltosEepromIterable.java +++ b/altoslib/AltosEepromIterable.java @@ -21,6 +21,74 @@ import java.io.*; import java.util.*; import java.text.*; +class AltosEepromOrdered implements Comparable<AltosEepromOrdered> { + AltosEeprom eeprom; + int index; + int tick; + + int cmdi() { + if (eeprom.cmd == AltosLib.AO_LOG_FLIGHT) + return 0; + return 1; + } + + public int compareTo(AltosEepromOrdered o) { + int cmd_diff = cmdi() - o.cmdi(); + + if (cmd_diff != 0) + return cmd_diff; + + int tick_diff = tick - o.tick; + + if (tick_diff != 0) + return tick_diff; + return index - o.index; + } + + AltosEepromOrdered (AltosEeprom eeprom, int index, int tick) { + this.eeprom = eeprom; + this.index = index; + this.tick = tick; + } +} + +class AltosEepromOrderedIterator implements Iterator<AltosEeprom> { + TreeSet<AltosEepromOrdered> olist; + Iterator<AltosEepromOrdered> oiterator; + + public AltosEepromOrderedIterator(Iterable<AltosEeprom> eeproms) { + olist = new TreeSet<AltosEepromOrdered>(); + + int tick = 0; + int index = 0; + boolean first = true; + + for (AltosEeprom e : eeproms) { + int t = e.tick; + if (first) + tick = t; + else { + while (t < tick - 32767) + t += 65536; + tick = t; + } + olist.add(new AltosEepromOrdered(e, index++, tick)); + } + oiterator = olist.iterator(); + } + + public boolean hasNext() { + return oiterator.hasNext(); + } + + public AltosEeprom next() { + return oiterator.next().eeprom; + } + + public void remove () { + } +} + public class AltosEepromIterable implements Iterable<AltosEeprom> { public LinkedList<AltosEeprom> eeproms; @@ -30,7 +98,7 @@ public class AltosEepromIterable implements Iterable<AltosEeprom> { } public AltosState state() { - AltosState state = new AltosState(null); + AltosState state = new AltosState(); for (AltosEeprom header : eeproms) header.update_state(state); @@ -44,6 +112,6 @@ public class AltosEepromIterable implements Iterable<AltosEeprom> { public Iterator<AltosEeprom> iterator() { if (eeproms == null) eeproms = new LinkedList<AltosEeprom>(); - return eeproms.iterator(); + return new AltosEepromOrderedIterator(eeproms); } }
\ No newline at end of file diff --git a/altoslib/AltosEepromMini.java b/altoslib/AltosEepromMini.java index ced87680..1e0ff1b9 100644 --- a/altoslib/AltosEepromMini.java +++ b/altoslib/AltosEepromMini.java @@ -55,13 +55,30 @@ public class AltosEepromMini extends AltosEeprom { public int sense_m() { return data16(8); } public int v_batt() { return data16(10); } + double voltage(AltosState state, int sensor) { + double supply; + + if (state.log_format == AltosLib.AO_LOG_FORMAT_EASYMINI) + supply = 3.0; + else + supply = 3.3; + return sensor / 32767.0 * supply * 127/27; + } + public void update_state(AltosState state) { switch (cmd) { case AltosLib.AO_LOG_FLIGHT: + state.set_flight(flight()); + state.set_ground_pressure(ground_pres()); break; case AltosLib.AO_LOG_STATE: + state.set_state(state()); break; case AltosLib.AO_LOG_SENSOR: + state.set_ms5607(pres(), temp()); + state.set_apogee_voltage(voltage(state, sense_a())); + state.set_main_voltage(voltage(state, sense_m())); + state.set_battery_voltage(voltage(state, v_batt())); break; } } diff --git a/altoslib/AltosEepromMiniIterable.java b/altoslib/AltosEepromMiniIterable.java index 1f221187..495495eb 100644 --- a/altoslib/AltosEepromMiniIterable.java +++ b/altoslib/AltosEepromMiniIterable.java @@ -21,7 +21,7 @@ import java.io.*; import java.util.*; import java.text.*; -public class AltosEepromMiniIterable extends AltosRecordIterable { +public class AltosEepromMiniIterable implements Iterable<AltosEepromMini> { static final int seen_flight = 1; static final int seen_sensor = 2; diff --git a/altoslib/AltosEepromTM.java b/altoslib/AltosEepromTM.java index fc7ec321..6945468b 100644 --- a/altoslib/AltosEepromTM.java +++ b/altoslib/AltosEepromTM.java @@ -17,134 +17,119 @@ package org.altusmetrum.altoslib_1; +import java.io.*; +import java.util.*; import java.text.*; -public class AltosEepromTM implements AltosStateUpdate { +public class AltosEepromTM extends AltosEeprom { public int cmd; public int tick; public int a; public int b; - public String data; public boolean tick_valid; public static final int record_length = 8; + static double + thermometer_to_temperature(double thermo) + { + return (thermo - 19791.268) / 32728.0 * 1.25 / 0.00247; + } + + public void write(PrintStream out) { + out.printf("%c %4x %4x %4x\n", cmd, tick, a, b); + } + public void update_state(AltosState state) { - state.set_tick(tick); + AltosGPS gps; + + /* Flush any pending GPS 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; + } + } + switch (cmd) { case AltosLib.AO_LOG_FLIGHT: - state.ground_accel = a; - state.flight = b; + state.set_state(AltosLib.ao_flight_pad); + state.set_ground_accel(a); + state.set_flight(b); state.set_boost_tick(tick); - state.time = 0; break; case AltosLib.AO_LOG_SENSOR: - state.set_telemetrum(a, b); + state.set_tick(tick); + state.set_accel(a); + double pressure = AltosConvert.barometer_to_pressure(b); + state.set_pressure(pressure); break; case AltosLib.AO_LOG_PRESSURE: - state.set_telemetrum(AltosState.MISSING, b); + state.set_tick(tick); + state.set_pressure(AltosConvert.barometer_to_pressure(b)); break; case AltosLib.AO_LOG_TEMP_VOLT: -/* - - record.temp = a; - record.batt = b; - eeprom_state.seen |= AltosRecord.seen_temp_volt; -*/ + state.set_tick(tick); + state.set_temperature(thermometer_to_temperature(a)); + state.set_battery_voltage(AltosConvert.cc_battery_to_voltage(b)); break; case AltosLib.AO_LOG_DEPLOY: -/* - record.drogue = a; - record.main = b; - eeprom_state.seen |= AltosRecord.seen_deploy; - has_ignite = true; -*/ + state.set_tick(tick); + state.set_apogee_voltage(AltosConvert.cc_ignitor_to_voltage(a)); + state.set_main_voltage(AltosConvert.cc_ignitor_to_voltage(b)); break; case AltosLib.AO_LOG_STATE: - state.state = a; - break; -// case AltosLib.AO_LOG_GPS_TIME: -// eeprom_state.gps_tick = record.tick; -// eeprom_state.seen |= AltosRecord.seen_gps_time; -// AltosGPS old = state.gps; -// AltosGPS gps = new AltosGPS(); -// -// /* GPS date doesn't get repeated through the file */ -// if (old != null) { -// gps.year = old.year; -// gps.month = old.month; -// gps.day = old.day; -// } -// gps.hour = (a & 0xff); -// gps.minute = (a >> 8); -// gps.second = (b & 0xff); -// -// int flags = (b >> 8); -// gps.connected = (flags & AltosLib.AO_GPS_RUNNING) != 0; -// gps.locked = (flags & AltosLib.AO_GPS_VALID) != 0; -// gps.nsat = (flags & AltosLib.AO_GPS_NUM_SAT_MASK) >> -// AltosLib.AO_GPS_NUM_SAT_SHIFT; -// state.temp_gps = gps; -// break; -// case AltosLib.AO_LOG_GPS_LAT: -// int lat32 = a | (b << 16); -// if (state.temp_gps == null) -// state.temp_gps = new AltosGPS(); -// state.temp_gps.lat = (double) lat32 / 1e7; -// break; -// case AltosLib.AO_LOG_GPS_LON: -// int lon32 = a | (b << 16); -// if (state.temp_gps == null) -// state.temp_gps = new AltosGPS(); -// state.temp_gps.lon = (double) lon32 / 1e7; -// break; -// case AltosLib.AO_LOG_GPS_ALT: -// if (state.temp_gps == null) -// state.temp_gps = new AltosGPS(); -// state.temp_gps.alt = a; -// break; -// case AltosLib.AO_LOG_GPS_SAT: -// if (record.tick == eeprom_state.gps_tick) { -// int svid = a; -// int c_n0 = b >> 8; -// if (record.gps == null) -// record.gps = new AltosGPS(); -// record.gps.add_sat(svid, c_n0); -// } -// break; -// case AltosLib.AO_LOG_GPS_DATE: -// if (record.gps == null) -// record.gps = new AltosGPS(); -// record.gps.year = (a & 0xff) + 2000; -// record.gps.month = a >> 8; -// record.gps.day = b & 0xff; -// break; - - case AltosLib.AO_LOG_CONFIG_VERSION: - break; - case AltosLib.AO_LOG_MAIN_DEPLOY: - break; - case AltosLib.AO_LOG_APOGEE_DELAY: - break; - case AltosLib.AO_LOG_RADIO_CHANNEL: - break; - case AltosLib.AO_LOG_CALLSIGN: - state.callsign = data; + state.set_tick(tick); + state.set_state(a); break; - case AltosLib.AO_LOG_ACCEL_CAL: - state.accel_plus_g = a; - state.accel_minus_g = b; + case AltosLib.AO_LOG_GPS_TIME: + gps = state.make_temp_gps(); + + gps.hour = (a & 0xff); + gps.minute = (a >> 8); + gps.second = (b & 0xff); + + int flags = (b >> 8); + + gps.connected = (flags & AltosLib.AO_GPS_RUNNING) != 0; + gps.locked = (flags & AltosLib.AO_GPS_VALID) != 0; + gps.nsat = (flags & AltosLib.AO_GPS_NUM_SAT_MASK) >> + AltosLib.AO_GPS_NUM_SAT_SHIFT; break; - case AltosLib.AO_LOG_RADIO_CAL: + case AltosLib.AO_LOG_GPS_LAT: + gps = state.make_temp_gps(); + + int lat32 = a | (b << 16); + gps.lat = (double) lat32 / 1e7; break; - case AltosLib.AO_LOG_MANUFACTURER: + case AltosLib.AO_LOG_GPS_LON: + gps = state.make_temp_gps(); + + int lon32 = a | (b << 16); + gps.lon = (double) lon32 / 1e7; break; - case AltosLib.AO_LOG_PRODUCT: + case AltosLib.AO_LOG_GPS_ALT: + gps = state.make_temp_gps(); + gps.alt = a; break; - case AltosLib.AO_LOG_SERIAL_NUMBER: - state.serial = a; + case AltosLib.AO_LOG_GPS_SAT: + gps = state.make_temp_gps(); + int svid = a; + int c_n0 = b >> 8; + gps.add_sat(svid, c_n0); break; - case AltosLib.AO_LOG_SOFTWARE_VERSION: + case AltosLib.AO_LOG_GPS_DATE: + gps = state.make_temp_gps(); + gps.year = (a & 0xff) + 2000; + gps.month = a >> 8; + gps.day = b & 0xff; break; } } @@ -166,8 +151,6 @@ public class AltosEepromTM implements AltosStateUpdate { tick = chunk.data16(start + 2); a = chunk.data16(start + 4); b = chunk.data16(start + 6); - - data = null; } public AltosEepromTM (String line) { @@ -175,10 +158,8 @@ public class AltosEepromTM implements AltosStateUpdate { tick = 0; a = 0; b = 0; - data = null; if (line == null) { cmd = AltosLib.AO_LOG_INVALID; - data = ""; } else { try { String[] tokens = line.split("\\s+"); @@ -186,7 +167,6 @@ public class AltosEepromTM implements AltosStateUpdate { if (tokens[0].length() == 1) { if (tokens.length != 4) { cmd = AltosLib.AO_LOG_INVALID; - data = line; } else { cmd = tokens[0].codePointAt(0); tick = Integer.parseInt(tokens[1],16); @@ -194,53 +174,11 @@ public class AltosEepromTM implements AltosStateUpdate { a = Integer.parseInt(tokens[2],16); b = Integer.parseInt(tokens[3],16); } - } else if (tokens[0].equals("Config") && tokens[1].equals("version:")) { - cmd = AltosLib.AO_LOG_CONFIG_VERSION; - data = tokens[2]; - } else if (tokens[0].equals("Main") && tokens[1].equals("deploy:")) { - cmd = AltosLib.AO_LOG_MAIN_DEPLOY; - a = Integer.parseInt(tokens[2]); - } else if (tokens[0].equals("Apogee") && tokens[1].equals("delay:")) { - cmd = AltosLib.AO_LOG_APOGEE_DELAY; - a = Integer.parseInt(tokens[2]); - } else if (tokens[0].equals("Radio") && tokens[1].equals("channel:")) { - cmd = AltosLib.AO_LOG_RADIO_CHANNEL; - a = Integer.parseInt(tokens[2]); - } else if (tokens[0].equals("Callsign:")) { - cmd = AltosLib.AO_LOG_CALLSIGN; - data = tokens[1].replaceAll("\"",""); - } else if (tokens[0].equals("Accel") && tokens[1].equals("cal")) { - cmd = AltosLib.AO_LOG_ACCEL_CAL; - a = Integer.parseInt(tokens[3]); - b = Integer.parseInt(tokens[5]); - } else if (tokens[0].equals("Radio") && tokens[1].equals("cal:")) { - cmd = AltosLib.AO_LOG_RADIO_CAL; - a = Integer.parseInt(tokens[2]); - } else if (tokens[0].equals("Max") && tokens[1].equals("flight") && tokens[2].equals("log:")) { - cmd = AltosLib.AO_LOG_MAX_FLIGHT_LOG; - a = Integer.parseInt(tokens[3]); - } else if (tokens[0].equals("manufacturer")) { - cmd = AltosLib.AO_LOG_MANUFACTURER; - data = tokens[1]; - } else if (tokens[0].equals("product")) { - cmd = AltosLib.AO_LOG_PRODUCT; - data = tokens[1]; - } else if (tokens[0].equals("serial-number")) { - cmd = AltosLib.AO_LOG_SERIAL_NUMBER; - a = Integer.parseInt(tokens[1]); - } else if (tokens[0].equals("log-format")) { - cmd = AltosLib.AO_LOG_LOG_FORMAT; - a = Integer.parseInt(tokens[1]); - } else if (tokens[0].equals("software-version")) { - cmd = AltosLib.AO_LOG_SOFTWARE_VERSION; - data = tokens[1]; } else { cmd = AltosLib.AO_LOG_INVALID; - data = line; } } catch (NumberFormatException ne) { -v cmd = AltosLib.AO_LOG_INVALID; - data = line; + cmd = AltosLib.AO_LOG_INVALID; } } } @@ -252,4 +190,23 @@ v cmd = AltosLib.AO_LOG_INVALID; a = in_a; b = in_b; } + + static public LinkedList<AltosEeprom> read(FileInputStream input) { + LinkedList<AltosEeprom> tms = new LinkedList<AltosEeprom>(); + + for (;;) { + try { + String line = AltosLib.gets(input); + if (line == null) + break; + AltosEepromTM tm = new AltosEepromTM(line); + tms.add(tm); + } catch (IOException ie) { + break; + } + } + + return tms; + } + } diff --git a/altoslib/AltosFlightReader.java b/altoslib/AltosFlightReader.java index 34526658..5a415274 100644 --- a/altoslib/AltosFlightReader.java +++ b/altoslib/AltosFlightReader.java @@ -28,7 +28,7 @@ public class AltosFlightReader { public void init() { } - public AltosRecord read() throws InterruptedException, ParseException, AltosCRCException, IOException { return null; } + public AltosState read() throws InterruptedException, ParseException, AltosCRCException, IOException { return null; } public void close(boolean interrupted) { } diff --git a/altoslib/AltosGPS.java b/altoslib/AltosGPS.java index f7929a4c..eb384e4d 100644 --- a/altoslib/AltosGPS.java +++ b/altoslib/AltosGPS.java @@ -28,7 +28,7 @@ public class AltosGPS implements Cloneable { public boolean connected; public double lat; /* degrees (+N -S) */ public double lon; /* degrees (+E -W) */ - public int alt; /* m */ + public double alt; /* m */ public int year; public int month; public int day; @@ -222,7 +222,7 @@ public class AltosGPS implements Cloneable { g.nsat = nsat; g.locked = locked; g.connected = connected; - g.lat = lat; g./* degrees (+N -S) */ + g.lat = lat; /* degrees (+N -S) */ g.lon = lon; /* degrees (+E -W) */ g.alt = alt; /* m */ g.year = year; @@ -242,11 +242,11 @@ public class AltosGPS implements Cloneable { if (cc_gps_sat != null) { g.cc_gps_sat = new AltosGPSSat[cc_gps_sat.length]; for (int i = 0; i < cc_gps_sat.length; i++) { - g.cc_gps_sat[i] = new AltosGPSSat(); - g.cc_gps_sat[i].svid = cc_gps_sat[i].svid; - g.cc_gps_sat[i].c_n0 = cc_gps_sat[i].c_n0; + g.cc_gps_sat[i] = new AltosGPSSat(cc_gps_sat[i].svid, + cc_gps_sat[i].c_n0); } } + return g; } public AltosGPS(AltosGPS old) { diff --git a/altoslib/AltosIMU.java b/altoslib/AltosIMU.java index 46df35bf..c5ebbb16 100644 --- a/altoslib/AltosIMU.java +++ b/altoslib/AltosIMU.java @@ -37,5 +37,6 @@ public class AltosIMU implements Cloneable { n.gyro_y = gyro_y; n.gyro_z = gyro_z; return n; + } }
\ No newline at end of file diff --git a/altoslib/AltosLib.java b/altoslib/AltosLib.java index d60ef492..4ca8ad9d 100644 --- a/altoslib/AltosLib.java +++ b/altoslib/AltosLib.java @@ -218,7 +218,9 @@ public class AltosLib { public static final int AO_LOG_FORMAT_TELEMETRY = 3; public static final int AO_LOG_FORMAT_TELESCIENCE = 4; public static final int AO_LOG_FORMAT_TELEMEGA = 5; - public static final int AO_LOG_FORMAT_MINI = 6; + public static final int AO_LOG_FORMAT_EASYMINI = 6; + public static final int AO_LOG_FORMAT_TELEMETRUM = 7; + public static final int AO_LOG_FORMAT_TELEMINI = 8; public static final int AO_LOG_FORMAT_NONE = 127; public static boolean isspace(int c) { diff --git a/altoslib/AltosRecord.java b/altoslib/AltosRecord.java index 5e4ed927..0c8e1db9 100644 --- a/altoslib/AltosRecord.java +++ b/altoslib/AltosRecord.java @@ -56,6 +56,10 @@ public class AltosRecord implements Comparable <AltosRecord>, Cloneable { public int flight_log_max; public String firmware_version; + public double accel_plus_g, accel_minus_g; + public double ground_accel; + public double accel; + public AltosRecordCompanion companion; /* Telemetry sources have these values recorded from the flight computer */ @@ -167,5 +171,9 @@ public class AltosRecord implements Comparable <AltosRecord>, Cloneable { kalman_acceleration = MISSING; kalman_speed = MISSING; kalman_height = MISSING; + + accel_plus_g = MISSING; + accel_minus_g = MISSING; + } } diff --git a/altoslib/AltosReplayReader.java b/altoslib/AltosReplayReader.java index a7e30370..0c14dee4 100644 --- a/altoslib/AltosReplayReader.java +++ b/altoslib/AltosReplayReader.java @@ -25,10 +25,10 @@ import java.util.*; */ public class AltosReplayReader extends AltosFlightReader { - Iterator<AltosRecord> iterator; + Iterator<AltosState> iterator; File file; - public AltosRecord read() { + public AltosState read() { if (iterator.hasNext()) return iterator.next(); return null; @@ -45,7 +45,7 @@ public class AltosReplayReader extends AltosFlightReader { public File backing_file() { return file; } - public AltosReplayReader(Iterator<AltosRecord> in_iterator, File in_file) { + public AltosReplayReader(Iterator<AltosState> in_iterator, File in_file) { iterator = in_iterator; file = in_file; name = file.getName(); diff --git a/altoslib/AltosState.java b/altoslib/AltosState.java index b40b744f..daf06c19 100644 --- a/altoslib/AltosState.java +++ b/altoslib/AltosState.java @@ -22,22 +22,35 @@ package org.altusmetrum.altoslib_1; public class AltosState implements Cloneable { - public AltosRecord data; + public AltosRecord record; + + public static final int set_position = 1; + public static final int set_gps = 2; + public static final int set_data = 4; + + public int set; /* derived data */ public long report_time; public double time; + public double prev_time; public double time_change; public int tick; + public int boost_tick; public int state; + public int flight; + public int serial; public boolean landed; public boolean ascent; /* going up? */ public boolean boost; /* under power */ + public int rssi; + public int status; public double ground_altitude; + public double ground_pressure; public double altitude; public double height; public double pressure; @@ -60,6 +73,8 @@ public class AltosState implements Cloneable { public double kalman_height, kalman_speed, kalman_acceleration; public AltosGPS gps; + public AltosGPS temp_gps; + public boolean gps_pending; public int gps_sequence; public AltosIMU imu; @@ -91,10 +106,11 @@ public class AltosState implements Cloneable { public double ground_accel; public int log_format; - public int serial; public AltosMs5607 baro; + public AltosRecordCompanion companion; + public double speed() { return speed; } @@ -112,17 +128,25 @@ public class AltosState implements Cloneable { } public void init() { - data = new AltosRecord(); + record = null; + + set = 0; report_time = System.currentTimeMillis(); time = AltosRecord.MISSING; time_change = AltosRecord.MISSING; + prev_time = AltosRecord.MISSING; tick = AltosRecord.MISSING; + boost_tick = AltosRecord.MISSING; state = AltosLib.ao_flight_invalid; + flight = AltosRecord.MISSING; landed = false; boost = false; + rssi = AltosRecord.MISSING; + status = 0; ground_altitude = AltosRecord.MISSING; + ground_pressure = AltosRecord.MISSING; altitude = AltosRecord.MISSING; height = AltosRecord.MISSING; pressure = AltosRecord.MISSING; @@ -138,21 +162,20 @@ public class AltosState implements Cloneable { apogee_voltage = AltosRecord.MISSING; main_voltage = AltosRecord.MISSING; - - accel_speed = AltosRecord.MISSING; - baro_speed = AltosRecord.MISSING; + speed = AltosRecord.MISSING; kalman_height = AltosRecord.MISSING; kalman_speed = AltosRecord.MISSING; kalman_acceleration = AltosRecord.MISSING; - max_baro_speed = 0; - max_accel_speed = 0; + max_speed = 0; max_height = 0; max_acceleration = 0; gps = null; + temp_gps = null; gps_sequence = 0; + gps_pending = false; imu = null; mag = null; @@ -165,7 +188,7 @@ public class AltosState implements Cloneable { range = AltosRecord.MISSING; gps_height = AltosRecord.MISSING; - pat_lat = AltosRecord.MISSING; + pad_lat = AltosRecord.MISSING; pad_lon = AltosRecord.MISSING; pad_alt = AltosRecord.MISSING; @@ -176,15 +199,18 @@ public class AltosState implements Cloneable { accel_plus_g = AltosRecord.MISSING; accel_minus_g = AltosRecord.MISSING; + accel = AltosRecord.MISSING; + ground_accel = AltosRecord.MISSING; log_format = AltosRecord.MISSING; serial = AltosRecord.MISSING; baro = null; + companion = null; } void copy(AltosState old) { - data = null; + record = null; if (old == null) { init(); @@ -193,13 +219,19 @@ public class AltosState implements Cloneable { report_time = old.report_time; time = old.time; - time_change = old.time_change; + time_change = 0; 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; + + set = 0; ground_altitude = old.ground_altitude; altitude = old.altitude; @@ -211,17 +243,16 @@ public class AltosState implements Cloneable { temperature = old.temperature; apogee_voltage = old.apogee_voltage; main_voltage = old.main_voltage; - accel_speed = old.accel_speed; - baro_speed = old.baro_speed; + speed = old.speed; prev_height = old.height; prev_speed = old.speed; prev_acceleration = old.acceleration; + prev_time = old.time; max_height = old.max_height; max_acceleration = old.max_acceleration; - max_accel_speed = old.max_accel_speed; - max_baro_speed = old.max_baro_speed; + max_speed = old.max_speed; kalman_height = old.kalman_height; kalman_speed = old.kalman_speed; @@ -231,7 +262,12 @@ public class AltosState implements Cloneable { gps = old.gps.clone(); else gps = null; + if (old.temp_gps != null) + temp_gps = old.temp_gps.clone(); + else + temp_gps = null; gps_sequence = old.gps_sequence; + gps_pending = old.gps_pending; if (old.imu != null) imu = old.imu.clone(); @@ -268,14 +304,14 @@ public class AltosState implements Cloneable { accel_plus_g = old.accel_plus_g; accel_minus_g = old.accel_minus_g; + accel = old.accel; + ground_accel = old.ground_accel; + log_format = old.log_format; serial = old.serial; baro = old.baro; - } - - double ground_altitude() { - + companion = old.companion; } double altitude() { @@ -289,8 +325,12 @@ public class AltosState implements Cloneable { void update_vertical_pos() { double alt = altitude(); - if (state == AltosLib.ao_flight_pad) { - + + if (state == AltosLib.ao_flight_pad && alt != AltosRecord.MISSING && ground_pressure == AltosRecord.MISSING) { + if (ground_altitude == AltosRecord.MISSING) + ground_altitude = alt; + else + ground_altitude = (ground_altitude * 7 + alt) / 8; } if (kalman_height != AltosRecord.MISSING) @@ -300,6 +340,9 @@ public class AltosState implements Cloneable { else height = AltosRecord.MISSING; + if (height != AltosRecord.MISSING && height > max_height) + max_height = height; + update_speed(); } @@ -348,12 +391,14 @@ public class AltosState implements Cloneable { } } } + if (boost && speed != AltosRecord.MISSING && speed > max_speed) + max_speed = speed; } void update_accel() { if (accel == AltosRecord.MISSING) return; - if (ground_Accel == AltosRecord.MISSING) + if (ground_accel == AltosRecord.MISSING) return; if (accel_plus_g == AltosRecord.MISSING) return; @@ -364,9 +409,60 @@ public class AltosState implements Cloneable { double counts_per_mss = counts_per_g / 9.80665; acceleration = (ground_accel - accel) / counts_per_mss; + + /* Only look at accelerometer data under boost */ + if (boost && acceleration != AltosRecord.MISSING && (max_acceleration == AltosRecord.MISSING || acceleration > max_acceleration)) + max_acceleration = acceleration; update_speed(); } + void update_time() { + if (tick != AltosRecord.MISSING) { + time = tick / 100.0; + if (prev_time != AltosRecord.MISSING) + time_change = time - prev_time; + } + } + + void update_gps() { + elevation = 0; + range = -1; + gps_height = 0; + + if (gps == null) + return; + + if (gps.locked && gps.nsat >= 4) { + /* Track consecutive 'good' gps reports, waiting for 10 of them */ + if (state == AltosLib.ao_flight_pad) { + set_npad(npad+1); + if (pad_lat != AltosRecord.MISSING) { + pad_lat = (pad_lat * 31 + gps.lat) / 32; + pad_lon = (pad_lon * 31 + gps.lon) / 32; + pad_alt = (pad_alt * 31 + gps.alt) / 32; + } + } + if (pad_lat == AltosRecord.MISSING) { + pad_lat = gps.lat; + pad_lon = gps.lon; + pad_alt = gps.alt; + } + } + if (gps.lat != 0 && gps.lon != 0 && + pad_lat != AltosRecord.MISSING && + pad_lon != AltosRecord.MISSING) + { + double h = height; + + if (h == AltosRecord.MISSING) + h = 0; + from_pad = new AltosGreatCircle(pad_lat, pad_lon, 0, gps.lat, gps.lon, h); + elevation = from_pad.elevation; + range = from_pad.range; + gps_height = gps.alt - pad_alt; + } + } + public void set_tick(int tick) { if (tick != AltosRecord.MISSING) { if (this.tick != AltosRecord.MISSING) { @@ -380,6 +476,15 @@ public class AltosState implements Cloneable { } } + public void set_boost_tick(int boost_tick) { + if (boost_tick != AltosRecord.MISSING) + this.boost_tick = boost_tick; + } + + public String state_name() { + return AltosLib.state_name(state); + } + public void set_state(int state) { if (state != AltosLib.ao_flight_invalid) { this.state = state; @@ -390,10 +495,47 @@ public class AltosState implements Cloneable { } + public void set_flight(int flight) { + + /* When the flight changes, reset the state */ + if (flight != AltosRecord.MISSING) { + if (this.flight != AltosRecord.MISSING && + this.flight != flight) { + init(); + } + this.flight = flight; + } + } + + public void set_serial(int serial) { + /* When the serial changes, reset the state */ + if (serial != AltosRecord.MISSING) { + if (this.serial != AltosRecord.MISSING && + this.serial != serial) { + init(); + } + this.serial = serial; + } + } + + public int rssi() { + if (rssi == AltosRecord.MISSING) + return 0; + return rssi; + } + + public void set_rssi(int rssi, int status) { + if (rssi != AltosRecord.MISSING) { + this.rssi = rssi; + this.status = status; + } + } + public void set_altitude(double altitude) { if (altitude != AltosRecord.MISSING) { this.altitude = altitude; update_vertical_pos(); + set |= set_position; } } @@ -404,11 +546,24 @@ public class AltosState implements Cloneable { } } + public void set_ground_pressure (double pressure) { + if (pressure != AltosRecord.MISSING) { + this.ground_pressure = pressure; + set_ground_altitude(AltosConvert.pressure_to_altitude(pressure)); + update_vertical_pos(); + } + } + public void set_gps(AltosGPS gps, int sequence) { if (gps != null) { + System.out.printf ("gps date: %d-%d-%d time %d:%d:%d\n", + gps.year, gps.month, gps.day, + gps.hour, gps.minute, gps.second); this.gps = gps.clone(); gps_sequence = sequence; + update_gps(); update_vertical_pos(); + set |= set_gps; } } @@ -417,7 +572,6 @@ public class AltosState implements Cloneable { kalman_height = height; kalman_speed = speed; kalman_acceleration = acceleration; - baro_speed = accel_speed = speed; update_vertical_pos(); } } @@ -429,6 +583,29 @@ public class AltosState implements Cloneable { } } + public void make_baro() { + if (baro == null) + baro = new AltosMs5607(); + } + + 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 make_companion (int nchannels) { + if (companion == null) + companion = new AltosRecordCompanion(nchannels); + } + + public void set_companion(AltosRecordCompanion companion) { + this.companion = companion; + } + public void set_accel_g(double accel_plus_g, double accel_minus_g) { if (accel_plus_g != AltosRecord.MISSING) { this.accel_plus_g = accel_plus_g; @@ -451,36 +628,77 @@ public class AltosState implements Cloneable { } public void set_temperature(double temperature) { - if (temperature != AltosRecord.MISSING) + if (temperature != AltosRecord.MISSING) { this.temperature = temperature; + set |= set_data; + } } public void set_battery_voltage(double battery_voltage) { - if (battery_voltage != AltosRecord.MISSING) + if (battery_voltage != AltosRecord.MISSING) { this.battery_voltage = battery_voltage; + set |= set_data; + } } public void set_pyro_voltage(double pyro_voltage) { - if (pyro_voltage != AltosRecord.MISSING) + if (pyro_voltage != AltosRecord.MISSING) { this.pyro_voltage = pyro_voltage; + set |= set_data; + } } public void set_apogee_voltage(double apogee_voltage) { - if (apogee_voltage != AltosRecord.MISSING) + if (apogee_voltage != AltosRecord.MISSING) { this.apogee_voltage = apogee_voltage; + set |= set_data; + } } public void set_main_voltage(double main_voltage) { - if (main_voltage != AltosRecord.MISSING) + if (main_voltage != AltosRecord.MISSING) { this.main_voltage = main_voltage; + set |= set_data; + } + } + + + public double time_since_boost() { + if (tick == AltosRecord.MISSING) + return 0.0; + + if (boost_tick != AltosRecord.MISSING) { + return (tick - boost_tick) / 100.0; + } + return tick / 100.0; + } + + public boolean valid() { + return tick != AltosRecord.MISSING && serial != AltosRecord.MISSING; + } + + public AltosGPS make_temp_gps() { + if (temp_gps == null) { + temp_gps = new AltosGPS(gps); + temp_gps.cc_gps_sat = null; + } + gps_pending = true; + return temp_gps; + } + + public void set_temp_gps() { + set_gps(temp_gps, gps_sequence + 1); + gps_pending = false; + temp_gps = null; } public void init (AltosRecord cur, AltosState prev_state) { + System.out.printf ("init\n"); if (cur == null) cur = new AltosRecord(); - data = cur; + record = cur; /* Discard previous state if it was for a different board */ if (prev_state != null && prev_state.serial != cur.serial) @@ -488,146 +706,35 @@ public class AltosState implements Cloneable { copy(prev_state); - set_ground_altitude(data.ground_altitude()); - set_altitude(data.altitude()); + set_ground_altitude(cur.ground_altitude()); + set_altitude(cur.altitude()); - set_kalman(data.kalman_height, data.kalman_speed, data.kalman_acceleration); + set_kalman(cur.kalman_height, cur.kalman_speed, cur.kalman_acceleration); report_time = System.currentTimeMillis(); - set_temperature(data.temperature()); - set_apogee_voltage(data.drogue_voltage()); - set_main_voltage(data.main_voltage()); - set_battery_voltage(data.battery_voltage()); - - set_pressure(data.pressure()); - - set_tick(data.tick); - set_state(data.state); + set_temperature(cur.temperature()); + set_apogee_voltage(cur.drogue_voltage()); + set_main_voltage(cur.main_voltage()); + set_battery_voltage(cur.battery_voltage()); - set_accel_g (data.accel_minus_g, data.accel_plus_g); - set_ground_accel(data.ground_accel); - set_accel (data.accel); + set_pressure(cur.pressure()); - set_gps(data.gps, data.gps_sequence); + set_tick(cur.tick); + set_state(cur.state); - if (prev_state != null) { + set_accel_g (cur.accel_minus_g, cur.accel_plus_g); + set_ground_accel(cur.ground_accel); + set_accel (cur.accel); - if (data.kalman_speed != AltosRecord.MISSING) { - baro_speed = accel_speed = data.kalman_speed; - } else { - /* compute barometric speed */ - - double height_change = height - prev_state.height; - - double prev_baro_speed = prev_state.baro_speed; - if (prev_baro_speed == AltosRecord.MISSING) - prev_baro_speed = 0; - - if (time_change > 0) - baro_speed = (prev_baro_speed * 3 + (height_change / time_change)) / 4.0; - else - baro_speed = prev_state.baro_speed; + if (cur.gps_sequence != gps_sequence) + set_gps(cur.gps, cur.gps_sequence); - double prev_accel_speed = prev_state.accel_speed; - - if (prev_accel_speed == AltosRecord.MISSING) - prev_accel_speed = 0; - - if (acceleration == AltosRecord.MISSING) { - /* Fill in mising acceleration value */ - accel_speed = baro_speed; - - if (time_change > 0 && accel_speed != AltosRecord.MISSING) - acceleration = (accel_speed - prev_accel_speed) / time_change; - else - acceleration = prev_state.acceleration; - } else { - /* compute accelerometer speed */ - accel_speed = prev_accel_speed + acceleration * time_change; - } - } - } else { - npad = 0; - ngps = 0; - gps = null; - gps_sequence = 0; - baro_speed = AltosRecord.MISSING; - accel_speed = AltosRecord.MISSING; - pad_alt = AltosRecord.MISSING; - max_baro_speed = 0; - max_accel_speed = 0; - max_height = 0; - max_acceleration = 0; - time_change = 0; - baro = new AltosMs5607(); - callsign = ""; - accel_plus_g = AltosRecord.MISSING; - accel_minus_g = AltosRecord.MISSING; - log_format = AltosRecord.MISSING; - serial = AltosRecord.MISSING; - } - - time = tick / 100.0; - - if (data.gps != null && data.gps_sequence != gps_sequence && (state < AltosLib.ao_flight_boost)) { - - /* Track consecutive 'good' gps reports, waiting for 10 of them */ - if (data.gps != null && data.gps.locked && data.gps.nsat >= 4) - set_npad(npad+1); - else - set_npad(0); - - /* Average GPS data while on the pad */ - if (data.gps != null && data.gps.locked && data.gps.nsat >= 4) { - if (ngps > 1 && state == AltosLib.ao_flight_pad) { - /* filter pad position */ - pad_lat = (pad_lat * 31.0 + data.gps.lat) / 32.0; - pad_lon = (pad_lon * 31.0 + data.gps.lon) / 32.0; - pad_alt = (pad_alt * 31.0 + data.gps.alt) / 32.0; - } else { - pad_lat = data.gps.lat; - pad_lon = data.gps.lon; - pad_alt = data.gps.alt; - } - ngps++; - } - } else { - if (ngps == 0 && ground_altitude != AltosRecord.MISSING) - pad_alt = ground_altitude; - } - - gps_sequence = data.gps_sequence; - - /* Only look at accelerometer data under boost */ - if (boost && acceleration != AltosRecord.MISSING && (max_acceleration == AltosRecord.MISSING || acceleration > max_acceleration)) - max_acceleration = acceleration; - if (boost && accel_speed != AltosRecord.MISSING && accel_speed > max_accel_speed) - max_accel_speed = accel_speed; - if (boost && baro_speed != AltosRecord.MISSING && baro_speed > max_baro_speed) - max_baro_speed = baro_speed; - - if (height != AltosRecord.MISSING && height > max_height) - max_height = height; - elevation = 0; - range = -1; - gps_height = 0; - if (data.gps != null) { - gps = data.gps; - if (ngps > 0 && gps.locked) { - double h = height; - - if (h == AltosRecord.MISSING) h = 0; - from_pad = new AltosGreatCircle(pad_lat, pad_lon, 0, gps.lat, gps.lon, h); - elevation = from_pad.elevation; - range = from_pad.range; - gps_height = gps.alt - pad_alt; - } - } } public AltosState clone() { - AltosState s = new AltosState(data, this); + AltosState s = new AltosState(); + s.copy(this); return s; } @@ -638,4 +745,8 @@ public class AltosState implements Cloneable { public AltosState (AltosRecord cur, AltosState prev) { init(cur, prev); } + + public AltosState () { + init(); + } } diff --git a/altoslib/AltosStateIterable.java b/altoslib/AltosStateIterable.java new file mode 100644 index 00000000..db4a2568 --- /dev/null +++ b/altoslib/AltosStateIterable.java @@ -0,0 +1,29 @@ +/* + * Copyright © 2013 Keith Packard <keithp@keithp.com> + * + * 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_1; + +import java.io.*; +import java.util.*; + +public abstract class AltosStateIterable implements Iterable<AltosState> { + + public void write_comments (PrintStream out) { + } + + public abstract void write(PrintStream out); +} diff --git a/altoslib/AltosTelemetryReader.java b/altoslib/AltosTelemetryReader.java index b4293c73..3915927c 100644 --- a/altoslib/AltosTelemetryReader.java +++ b/altoslib/AltosTelemetryReader.java @@ -27,16 +27,18 @@ public class AltosTelemetryReader extends AltosFlightReader { AltosRecord previous; double frequency; int telemetry; + AltosState state = null; LinkedBlockingQueue<AltosLine> telem; - public AltosRecord read() throws InterruptedException, ParseException, AltosCRCException, IOException { + public AltosState read() throws InterruptedException, ParseException, AltosCRCException, IOException { AltosLine l = telem.take(); if (l.line == null) throw new IOException("IO error"); AltosRecord next = AltosTelemetry.parse(l.line, previous); previous = next; - return next; + state = new AltosState (next, state); + return state; } public void flush() { diff --git a/altoslib/Makefile.am b/altoslib/Makefile.am index 8a41b90c..bbcca906 100644 --- a/altoslib/Makefile.am +++ b/altoslib/Makefile.am @@ -20,6 +20,7 @@ altoslib_JAVA = \ AltosEeprom.java \ AltosEepromChunk.java \ AltosEepromFile.java \ + AltosEepromTM.java \ AltosEepromHeader.java \ AltosEepromIterable.java \ AltosEepromLog.java \ @@ -28,7 +29,6 @@ altoslib_JAVA = \ AltosEepromRecord.java \ AltosEepromTeleScience.java \ AltosEepromMini.java \ - AltosEepromMiniIterable.java \ AltosEepromOldIterable.java \ AltosFile.java \ AltosFlash.java \ @@ -69,6 +69,7 @@ altoslib_JAVA = \ AltosSensorMM.java \ AltosSensorTM.java \ AltosState.java \ + AltosStateIterable.java \ AltosStateUpdate.java \ AltosTelemetry.java \ AltosTelemetryIterable.java \ |