summaryrefslogtreecommitdiff
path: root/altoslib
diff options
context:
space:
mode:
Diffstat (limited to 'altoslib')
-rw-r--r--altoslib/AltosCSV.java87
-rw-r--r--altoslib/AltosCalData.java49
-rw-r--r--altoslib/AltosDataListener.java51
-rw-r--r--altoslib/AltosEeprom.java1
-rw-r--r--altoslib/AltosEepromDownload.java43
-rw-r--r--altoslib/AltosEepromList.java4
-rw-r--r--altoslib/AltosEepromLog.java18
-rw-r--r--altoslib/AltosEepromMonitor.java6
-rw-r--r--altoslib/AltosEepromRecord.java33
-rw-r--r--altoslib/AltosEepromRecordFull.java12
-rw-r--r--altoslib/AltosEepromRecordMega.java7
-rw-r--r--altoslib/AltosEepromRecordMetrum.java6
-rw-r--r--altoslib/AltosEepromRecordSet.java9
-rw-r--r--altoslib/AltosFile.java17
-rw-r--r--altoslib/AltosFilterListener.java22
-rw-r--r--altoslib/AltosFlightListener.java162
-rw-r--r--altoslib/AltosFlightSeries.java145
-rw-r--r--altoslib/AltosFlightStats.java7
-rw-r--r--altoslib/AltosIMU.java6
-rw-r--r--altoslib/AltosIdleMonitor.java17
-rw-r--r--altoslib/AltosKML.java297
-rw-r--r--altoslib/AltosLib.java7
-rw-r--r--altoslib/AltosLink.java63
-rw-r--r--altoslib/AltosReplayReader.java4
-rw-r--r--altoslib/AltosState.java35
-rw-r--r--altoslib/AltosTelemetry.java12
-rw-r--r--altoslib/AltosTelemetryConfiguration.java2
-rw-r--r--altoslib/AltosTelemetryFile.java2
-rw-r--r--altoslib/AltosTelemetryLocation.java7
-rw-r--r--altoslib/AltosTelemetryMegaData.java4
-rw-r--r--altoslib/AltosTelemetryReader.java8
-rw-r--r--altoslib/AltosTelemetrySatellite.java3
-rw-r--r--altoslib/AltosTimeSeries.java42
-rw-r--r--altoslib/Makefile.am1
34 files changed, 743 insertions, 446 deletions
diff --git a/altoslib/AltosCSV.java b/altoslib/AltosCSV.java
index f55b4785..a8de23f0 100644
--- a/altoslib/AltosCSV.java
+++ b/altoslib/AltosCSV.java
@@ -29,9 +29,11 @@ public class AltosCSV implements AltosWriter {
int boost_tick;
boolean has_basic;
+ boolean has_radio;
boolean has_battery;
boolean has_flight_state;
boolean has_advanced;
+ boolean has_igniter;
boolean has_gps;
boolean has_gps_sat;
boolean has_companion;
@@ -39,7 +41,7 @@ public class AltosCSV implements AltosWriter {
AltosFlightSeries series;
int[] indices;
- static final int ALTOS_CSV_VERSION = 5;
+ static final int ALTOS_CSV_VERSION = 6;
/* Version 4 format:
*
@@ -49,7 +51,8 @@ public class AltosCSV implements AltosWriter {
* flight number
* callsign
* time (seconds since boost)
- * clock (tick count / 100)
+ *
+ * Radio info (if available)
* rssi
* link quality
*
@@ -81,6 +84,14 @@ public class AltosCSV implements AltosWriter {
* mag_x (g)
* mag_y (g)
* mag_z (g)
+ * tilt (d)
+ *
+ * Extra igniter voltages (if available)
+ * pyro (V)
+ * igniter_a (V)
+ * igniter_b (V)
+ * igniter_c (V)
+ * igniter_d (V)
*
* GPS data (if available)
* connected (1/0)
@@ -115,13 +126,26 @@ public class AltosCSV implements AltosWriter {
*/
void write_general_header() {
- out.printf("version,serial,flight,call,time,clock,rssi,lqi");
+ out.printf("version,serial,flight,call,time");
}
double time() {
return series.time(indices);
}
+ void write_general() {
+ out.printf("%s, %d, %d, %s, %8.2f",
+ ALTOS_CSV_VERSION,
+ series.cal_data().serial,
+ series.cal_data().flight,
+ series.cal_data().callsign,
+ time());
+ }
+
+ void write_radio_header() {
+ out.printf("rssi,lqi");
+ }
+
int rssi() {
return (int) series.value(AltosFlightSeries.rssi_name, indices);
}
@@ -130,12 +154,8 @@ public class AltosCSV implements AltosWriter {
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, series.cal_data().serial,
- series.cal_data().flight, series.cal_data().callsign,
- time, time,
+ void write_radio() {
+ out.printf("%4d, %3d",
rssi(), status() & 0x7f);
}
@@ -149,7 +169,7 @@ public class AltosCSV implements AltosWriter {
void write_flight() {
int state = state();
- out.printf("%d,%8s", state, AltosLib.state_name(state));
+ out.printf("%2d,%8s", state, AltosLib.state_name(state));
}
void write_basic_header() {
@@ -189,7 +209,7 @@ public class AltosCSV implements AltosWriter {
}
void write_advanced_header() {
- out.printf("accel_x,accel_y,accel_z,gyro_x,gyro_y,gyro_z,mag_x,mag_y,mag_z");
+ out.printf("accel_x,accel_y,accel_z,gyro_x,gyro_y,gyro_z,mag_x,mag_y,mag_z,tilt");
}
double accel_along() { return series.value(AltosFlightSeries.accel_along_name, indices); }
@@ -204,11 +224,30 @@ public class AltosCSV implements AltosWriter {
double mag_across() { return series.value(AltosFlightSeries.mag_across_name, indices); }
double mag_through() { return series.value(AltosFlightSeries.mag_through_name, indices); }
+ double tilt() { return series.value(AltosFlightSeries.orient_name, indices); }
+
void write_advanced() {
- out.printf("%7.2f,%7.2f,%7.2f,%7.2f,%7.2f,%7.2f,%7.2f,%7.2f,%7.2f",
+ out.printf("%7.2f,%7.2f,%7.2f,%7.2f,%7.2f,%7.2f,%7.2f,%7.2f,%7.2f,%7.2f",
accel_along(), accel_across(), accel_through(),
gyro_roll(), gyro_pitch(), gyro_yaw(),
- mag_along(), mag_across(), mag_through());
+ mag_along(), mag_across(), mag_through(),
+ tilt());
+ }
+
+ void write_igniter_header() {
+ out.printf("pyro");
+ for (int i = 0; i < series.igniter_voltage.length; i++)
+ out.printf(",%s", AltosLib.igniter_short_name(i));
+ }
+
+ double pyro() { return series.value(AltosFlightSeries.pyro_voltage_name, indices); }
+
+ double igniter_value(int channel) { return series.value(series.igniter_voltage_name(channel), indices); }
+
+ void write_igniter() {
+ out.printf("%5.2f", pyro());
+ for (int i = 0; i < series.igniter_voltage.length; i++)
+ out.printf(",%5.2f", igniter_value(i));
}
void write_gps_header() {
@@ -306,6 +345,10 @@ public class AltosCSV implements AltosWriter {
void write_header() {
out.printf("#"); write_general_header();
+ if (has_radio) {
+ out.printf(",");
+ write_radio_header();
+ }
if (has_flight_state) {
out.printf(",");
write_flight_header();
@@ -322,6 +365,10 @@ public class AltosCSV implements AltosWriter {
out.printf(",");
write_advanced_header();
}
+ if (has_igniter) {
+ out.printf(",");
+ write_igniter_header();
+ }
if (has_gps) {
out.printf(",");
write_gps_header();
@@ -339,6 +386,10 @@ public class AltosCSV implements AltosWriter {
void write_one() {
write_general();
+ if (has_radio) {
+ out.printf(",");
+ write_radio();
+ }
if (has_flight_state) {
out.printf(",");
write_flight();
@@ -355,6 +406,10 @@ public class AltosCSV implements AltosWriter {
out.printf(",");
write_advanced();
}
+ if (has_igniter) {
+ out.printf(",");
+ write_igniter();
+ }
if (has_gps) {
out.printf(",");
write_gps();
@@ -395,14 +450,18 @@ public class AltosCSV implements AltosWriter {
series.finish();
+ has_radio = false;
has_flight_state = false;
has_basic = false;
has_battery = false;
has_advanced = false;
+ has_igniter = false;
has_gps = false;
has_gps_sat = false;
has_companion = false;
+ if (series.has_series(AltosFlightSeries.rssi_name))
+ has_radio = 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))
@@ -411,6 +470,8 @@ public class AltosCSV implements AltosWriter {
has_battery = true;
if (series.has_series(AltosFlightSeries.accel_across_name))
has_advanced = true;
+ if (series.has_series(AltosFlightSeries.pyro_voltage_name))
+ has_igniter = true;
if (series.gps_series != null)
has_gps = true;
diff --git a/altoslib/AltosCalData.java b/altoslib/AltosCalData.java
index 6258c1a8..03e2cbd7 100644
--- a/altoslib/AltosCalData.java
+++ b/altoslib/AltosCalData.java
@@ -72,6 +72,13 @@ public class AltosCalData {
}
}
+ public int log_format = AltosLib.MISSING;
+
+ public void set_log_format(int log_format) {
+ if (log_format != AltosLib.MISSING)
+ this.log_format = log_format;
+ }
+
public int config_major = AltosLib.MISSING;
public int config_minor = AltosLib.MISSING;
public int flight_log_max = AltosLib.MISSING;
@@ -192,7 +199,6 @@ public class AltosCalData {
tick = AltosLib.MISSING;
prev_tick = AltosLib.MISSING;
temp_gps = null;
- prev_gps = null;
temp_gps_sat_tick = AltosLib.MISSING;
accel = AltosLib.MISSING;
}
@@ -235,13 +241,19 @@ public class AltosCalData {
public AltosGPS gps_pad = null;
+ public AltosGPS prev_gps = null;
+
public double gps_pad_altitude = AltosLib.MISSING;
- public void set_gps(AltosGPS gps) {
- if ((state != AltosLib.MISSING && state < AltosLib.ao_flight_boost) || gps_pad == null)
- gps_pad = gps;
- if (gps_pad_altitude == AltosLib.MISSING && gps.alt != AltosLib.MISSING)
- gps_pad_altitude = gps.alt;
+ public void set_cal_gps(AltosGPS gps) {
+ if (gps.locked && gps.nsat >= 4) {
+ if ((state != AltosLib.MISSING && state < AltosLib.ao_flight_boost) || gps_pad == null)
+ gps_pad = gps;
+ if (gps_pad_altitude == AltosLib.MISSING && gps.alt != AltosLib.MISSING)
+ gps_pad_altitude = gps.alt;
+ }
+ temp_gps = null;
+ prev_gps = gps;
}
/*
@@ -249,33 +261,24 @@ public class AltosCalData {
* object and then deliver the result atomically to the listener
*/
AltosGPS temp_gps = null;
- AltosGPS prev_gps = null;
int temp_gps_sat_tick = AltosLib.MISSING;
- public AltosGPS temp_gps() {
+ public AltosGPS temp_cal_gps() {
return temp_gps;
}
- public void reset_temp_gps() {
- if (temp_gps != null) {
- if (temp_gps.locked && temp_gps.nsat >= 4)
- set_gps(temp_gps);
- prev_gps = temp_gps;
- temp_gps = null;
- }
+ public void reset_temp_cal_gps() {
+ if (temp_gps != null)
+ set_cal_gps(temp_gps);
}
- public boolean gps_pending() {
+ public boolean cal_gps_pending() {
return temp_gps != null;
}
- public AltosGPS make_temp_gps(int tick, boolean sats) {
- if (temp_gps == null) {
- if (prev_gps != null)
- temp_gps = prev_gps.clone();
- else
- temp_gps = new AltosGPS();
- }
+ public AltosGPS make_temp_cal_gps(int tick, boolean sats) {
+ if (temp_gps == null)
+ temp_gps = new AltosGPS(prev_gps);
if (sats) {
if (tick != temp_gps_sat_tick)
temp_gps.cc_gps_sat = null;
diff --git a/altoslib/AltosDataListener.java b/altoslib/AltosDataListener.java
index be6d840f..9a1e1465 100644
--- a/altoslib/AltosDataListener.java
+++ b/altoslib/AltosDataListener.java
@@ -19,10 +19,16 @@ public abstract class AltosDataListener {
private AltosCalData cal_data = null;
public double time = AltosLib.MISSING;
- public int state = AltosLib.MISSING;
public double frequency = AltosLib.MISSING;
+ public int raw_tick = AltosLib.MISSING;
+
+ public int tick() {
+ return raw_tick;
+ }
+
public void set_tick(int tick) {
+ raw_tick = tick;
cal_data.set_tick(tick);
set_time(cal_data.time());
}
@@ -42,14 +48,34 @@ public abstract class AltosDataListener {
cal_data().set_serial(serial);
}
+ public void set_device_type(int device_type) {
+ cal_data().set_device_type(device_type);
+ switch (device_type) {
+ case AltosLib.product_telegps:
+ set_state(AltosLib.ao_flight_stateless);
+ break;
+ }
+ }
+
+ public void set_log_format(int log_format) {
+ cal_data().set_log_format(log_format);
+ switch (log_format) {
+ case AltosLib.AO_LOG_FORMAT_TELEGPS:
+ set_state(AltosLib.ao_flight_stateless);
+ break;
+ }
+ }
+
public double time() {
return time;
}
public void set_state(int state) {
cal_data().set_state(state);
- if (state != AltosLib.MISSING)
- this.state = state;
+ }
+
+ public int state() {
+ return cal_data().state;
}
public void set_flight(int flight) {
@@ -64,6 +90,12 @@ public abstract class AltosDataListener {
public void finish() {
}
+ public void init() {
+ set_state(AltosLib.ao_flight_invalid);
+ time = AltosLib.MISSING;
+ frequency = AltosLib.MISSING;
+ }
+
public abstract void set_rssi(int rssi, int status);
public abstract void set_received_time(long received_time);
@@ -79,7 +111,18 @@ public abstract class AltosDataListener {
public abstract void set_apogee_voltage(double volts);
public abstract void set_main_voltage(double volts);
- public abstract void set_gps(AltosGPS gps);
+ public void set_gps(AltosGPS gps) {
+ AltosCalData cal_data = cal_data();
+ cal_data.set_cal_gps(gps);
+ }
+
+ public AltosGPS make_temp_gps(boolean sats) {
+ return cal_data().make_temp_cal_gps(tick(), sats);
+ }
+
+ public AltosGPS temp_gps() {
+ return cal_data().temp_cal_gps();
+ }
public abstract void set_orient(double orient);
public abstract void set_gyro(double roll, double pitch, double yaw);
diff --git a/altoslib/AltosEeprom.java b/altoslib/AltosEeprom.java
index ad7bf881..124bd478 100644
--- a/altoslib/AltosEeprom.java
+++ b/altoslib/AltosEeprom.java
@@ -22,6 +22,7 @@ public class AltosEeprom {
private AltosJson config;
ArrayList<Byte> data;
private AltosConfigData config_data;
+ int errors = 0;
/*
* Public accessor APIs
diff --git a/altoslib/AltosEepromDownload.java b/altoslib/AltosEepromDownload.java
index 33f0dd17..547b523f 100644
--- a/altoslib/AltosEepromDownload.java
+++ b/altoslib/AltosEepromDownload.java
@@ -40,6 +40,7 @@ class AltosEepromNameData extends AltosDataListener {
public void set_main_voltage(double volts) { }
public void set_gps(AltosGPS gps) {
+ super.set_gps(gps);
if (gps != null &&
gps.year != AltosLib.MISSING &&
gps.month != AltosLib.MISSING &&
@@ -199,25 +200,47 @@ public class AltosEepromDownload implements Runnable {
AltosFile f = MakeFile(flights.config_data.serial, log.flight, name_data);
- monitor.set_filename(f.toString());
+ log.set_file(f);
- FileWriter w = new FileWriter(f);
+ boolean do_write = true;
- eeprom.write(w);
- w.close();
+ if (f.exists())
+ do_write = monitor.check_overwrite(f);
+
+ if (do_write) {
+ FileWriter w = new FileWriter(f);
+
+ eeprom.write(w);
+ w.close();
+ }
+
+ if (eeprom.errors != 0)
+ throw new ParseException(String.format("%d CRC Errors", eeprom.errors), 0);
+ }
+
+ static String label(int flight) {
+ if (flight < 0)
+ return "Corrupt";
+ else
+ return "Flight";
+ }
+
+ static int flight(int flight) {
+ if (flight < 0)
+ return -flight;
+ return flight;
}
public void run () {
boolean success = false;
try {
- boolean failed = false;
if (remote)
link.start_remote();
for (AltosEepromLog log : flights) {
parse_errors = null;
- if (log.selected) {
+ if (log.download_selected) {
monitor.reset();
try {
CaptureLog(log);
@@ -225,16 +248,16 @@ public class AltosEepromDownload implements Runnable {
LogError(e.getMessage());
}
}
+ success = true;
if (parse_errors != null) {
- failed = true;
- monitor.show_message(String.format("Flight %d download error. Valid log data saved\n%s",
- log.flight,
+ monitor.show_message(String.format("%s %d download error. Valid log data saved\n%s",
+ label(log.flight),
+ flight(log.flight),
parse_errors),
link.name,
AltosEepromMonitor.WARNING_MESSAGE);
}
}
- success = !failed;
} catch (IOException ee) {
monitor.show_message(ee.getLocalizedMessage(),
link.name,
diff --git a/altoslib/AltosEepromList.java b/altoslib/AltosEepromList.java
index 55d47e20..c55bcaaa 100644
--- a/altoslib/AltosEepromList.java
+++ b/altoslib/AltosEepromList.java
@@ -87,7 +87,7 @@ public class AltosEepromList extends ArrayList<AltosEepromLog> {
start = AltosParse.parse_hex(tokens[3]);
if (tokens[4].equals("end"))
end = AltosParse.parse_hex(tokens[5]);
- if (flight > 0 && start >= 0 && end > 0)
+ if (flight != 0 && start >= 0 && end > 0)
flights.add(new AltosEepromFlight(flight, start, end));
} catch (ParseException pe) { System.out.printf("Parse error %s\n", pe.toString()); }
}
@@ -115,4 +115,4 @@ public class AltosEepromList extends ArrayList<AltosEepromLog> {
link.flush_output();
}
}
-} \ No newline at end of file
+}
diff --git a/altoslib/AltosEepromLog.java b/altoslib/AltosEepromLog.java
index 8d1f3fc4..ba722b89 100644
--- a/altoslib/AltosEepromLog.java
+++ b/altoslib/AltosEepromLog.java
@@ -18,6 +18,7 @@
package org.altusmetrum.altoslib_12;
+import java.io.*;
import java.text.*;
import java.util.concurrent.*;
@@ -32,7 +33,15 @@ public class AltosEepromLog {
public int start_block;
public int end_block;
- public boolean selected;
+ public boolean download_selected;
+ public boolean delete_selected;
+ public boolean graph_selected;
+
+ public File file;
+
+ public void set_file(File file) {
+ this.file = file;
+ }
public AltosEepromLog(AltosConfigData config_data,
AltosLink link,
@@ -50,8 +59,11 @@ public class AltosEepromLog {
serial = config_data.serial;
/*
- * Select all flights for download
+ * Select all flights for download and graph, but not
+ * for delete
*/
- selected = true;
+ download_selected = true;
+ delete_selected = false;
+ graph_selected = true;
}
}
diff --git a/altoslib/AltosEepromMonitor.java b/altoslib/AltosEepromMonitor.java
index a99ec687..11144a3a 100644
--- a/altoslib/AltosEepromMonitor.java
+++ b/altoslib/AltosEepromMonitor.java
@@ -18,6 +18,8 @@
package org.altusmetrum.altoslib_12;
+import java.io.*;
+
public interface AltosEepromMonitor {
public void set_block(int in_block);
@@ -28,8 +30,6 @@ public interface AltosEepromMonitor {
public void set_flight(int in_flight);
- public void set_filename(String in_file);
-
public void set_thread(Thread eeprom_thread);
final static int INFO_MESSAGE = 0;
@@ -38,6 +38,8 @@ public interface AltosEepromMonitor {
public void show_message(String message, String title, int message_type);
+ public Boolean check_overwrite(File file);
+
public void start();
public void done(boolean success);
diff --git a/altoslib/AltosEepromRecord.java b/altoslib/AltosEepromRecord.java
index 094584fe..43e8ea4d 100644
--- a/altoslib/AltosEepromRecord.java
+++ b/altoslib/AltosEepromRecord.java
@@ -50,8 +50,22 @@ public abstract class AltosEepromRecord implements Comparable<AltosEepromRecord>
return data8(i) | (data8(i+1) << 8) | (data8(i+2) << 16) | (data8(i+3) << 24);
}
+ public boolean empty(int s) {
+ for (int i = 0; i < length; i++)
+ if (eeprom.data8(s + i) != 0xff)
+ return false;
+ return true;
+ }
+
public boolean valid(int s) {
- return AltosConvert.checksum(eeprom.data, s, length) == 0;
+ int ck = AltosConvert.checksum(eeprom.data, s, length);
+
+ if (ck != 0) {
+ ++eeprom.errors;
+ System.out.printf("invalid checksum 0x%x at 0x%x\n", ck, s);
+ return false;
+ }
+ return true;
}
public boolean valid() {
@@ -83,18 +97,16 @@ public abstract class AltosEepromRecord implements Comparable<AltosEepromRecord>
/* AltosDataProvider */
public void provide_data(AltosDataListener listener, AltosCalData cal_data) {
- cal_data.set_tick(tick());
+ listener.set_tick(tick());
if (cmd() == AltosLib.AO_LOG_FLIGHT)
cal_data.set_boost_tick();
listener.set_time(cal_data.time());
/* Flush any pending GPS changes */
if (!AltosLib.is_gps_cmd(cmd())) {
- AltosGPS gps = cal_data.temp_gps();
- if (gps != null) {
+ AltosGPS gps = listener.temp_gps();
+ if (gps != null)
listener.set_gps(gps);
- cal_data.reset_temp_gps();
- }
}
}
@@ -102,25 +114,18 @@ public abstract class AltosEepromRecord implements Comparable<AltosEepromRecord>
int s = start + length;
while (s + length <= eeprom.data.size()) {
- if (valid(s))
+ if (!empty(s) && valid(s))
return s;
s += length;
}
return -1;
}
- public boolean hasNext() {
- return next_start() >= 0;
- }
-
public abstract AltosEepromRecord next();
public AltosEepromRecord(AltosEeprom eeprom, int start, int length) {
this.eeprom = eeprom;
this.start = start;
this.length = length;
-
- while (start + length < eeprom.data.size() && !valid())
- start += length;
}
}
diff --git a/altoslib/AltosEepromRecordFull.java b/altoslib/AltosEepromRecordFull.java
index 32df9578..7e92d353 100644
--- a/altoslib/AltosEepromRecordFull.java
+++ b/altoslib/AltosEepromRecordFull.java
@@ -53,7 +53,7 @@ public class AltosEepromRecordFull extends AltosEepromRecord {
listener.set_state(data16(0));
break;
case AltosLib.AO_LOG_GPS_TIME:
- gps = cal_data.make_temp_gps(tick(),false);
+ gps = listener.make_temp_gps(false);
gps.hour = data8(0);
gps.minute = data8(1);
@@ -67,29 +67,29 @@ public class AltosEepromRecordFull extends AltosEepromRecord {
AltosLib.AO_GPS_NUM_SAT_SHIFT;
break;
case AltosLib.AO_LOG_GPS_LAT:
- gps = cal_data.make_temp_gps(tick(),false);
+ gps = listener.make_temp_gps(false);
int lat32 = data32(0);
gps.lat = (double) lat32 / 1e7;
break;
case AltosLib.AO_LOG_GPS_LON:
- gps = cal_data.make_temp_gps(tick(),false);
+ gps = listener.make_temp_gps(false);
int lon32 = data32(0);
gps.lon = (double) lon32 / 1e7;
break;
case AltosLib.AO_LOG_GPS_ALT:
- gps = cal_data.make_temp_gps(tick(),false);
+ gps = listener.make_temp_gps(false);
gps.alt = data16(0);
break;
case AltosLib.AO_LOG_GPS_SAT:
- gps = cal_data.make_temp_gps(tick(),true);
+ gps = listener.make_temp_gps(true);
int svid = data16(0);
int c_n0 = data16(2);
gps.add_sat(svid, c_n0);
break;
case AltosLib.AO_LOG_GPS_DATE:
- gps = cal_data.make_temp_gps(tick(),false);
+ gps = listener.make_temp_gps(false);
gps.year = data8(0) + 2000;
gps.month = data8(1);
gps.day = data8(2);
diff --git a/altoslib/AltosEepromRecordMega.java b/altoslib/AltosEepromRecordMega.java
index ad3e23fd..86343fe0 100644
--- a/altoslib/AltosEepromRecordMega.java
+++ b/altoslib/AltosEepromRecordMega.java
@@ -31,6 +31,7 @@ public class AltosEepromRecordMega extends AltosEepromRecord {
private int ground_roll() {
switch (log_format) {
case AltosLib.AO_LOG_FORMAT_TELEMEGA:
+ case AltosLib.AO_LOG_FORMAT_TELEMEGA_3:
return data32(16);
case AltosLib.AO_LOG_FORMAT_TELEMEGA_OLD:
return data16(14);
@@ -41,6 +42,7 @@ public class AltosEepromRecordMega extends AltosEepromRecord {
private int ground_pitch() {
switch (log_format) {
case AltosLib.AO_LOG_FORMAT_TELEMEGA:
+ case AltosLib.AO_LOG_FORMAT_TELEMEGA_3:
return data32(20);
case AltosLib.AO_LOG_FORMAT_TELEMEGA_OLD:
return data16(16);
@@ -51,6 +53,7 @@ public class AltosEepromRecordMega extends AltosEepromRecord {
private int ground_yaw() {
switch (log_format) {
case AltosLib.AO_LOG_FORMAT_TELEMEGA:
+ case AltosLib.AO_LOG_FORMAT_TELEMEGA_3:
return data32(24);
case AltosLib.AO_LOG_FORMAT_TELEMEGA_OLD:
return data16(18);
@@ -188,7 +191,7 @@ public class AltosEepromRecordMega extends AltosEepromRecord {
listener.set_pyro_fired(pyro());
break;
case AltosLib.AO_LOG_GPS_TIME:
- gps = cal_data.make_temp_gps(tick(), false);
+ gps = listener.make_temp_gps(false);
gps.lat = latitude() / 1e7;
gps.lon = longitude() / 1e7;
@@ -231,7 +234,7 @@ public class AltosEepromRecordMega extends AltosEepromRecord {
}
break;
case AltosLib.AO_LOG_GPS_SAT:
- gps = cal_data.make_temp_gps(tick(), true);
+ gps = listener.make_temp_gps(true);
int n = nsat();
if (n > max_sat)
diff --git a/altoslib/AltosEepromRecordMetrum.java b/altoslib/AltosEepromRecordMetrum.java
index 3da50544..888a06cc 100644
--- a/altoslib/AltosEepromRecordMetrum.java
+++ b/altoslib/AltosEepromRecordMetrum.java
@@ -91,7 +91,7 @@ public class AltosEepromRecordMetrum extends AltosEepromRecord {
listener.set_main_voltage(AltosConvert.mega_pyro_voltage(sense_m()));
break;
case AltosLib.AO_LOG_GPS_POS:
- gps = cal_data.make_temp_gps(tick(), false);
+ gps = listener.make_temp_gps(false);
gps.lat = latitude() / 1e7;
gps.lon = longitude() / 1e7;
if (config_data().altitude_32())
@@ -100,7 +100,7 @@ public class AltosEepromRecordMetrum extends AltosEepromRecord {
gps.alt = altitude_low();
break;
case AltosLib.AO_LOG_GPS_TIME:
- gps = cal_data.make_temp_gps(tick(), false);
+ gps = listener.make_temp_gps(false);
gps.hour = hour();
gps.minute = minute();
@@ -119,7 +119,7 @@ public class AltosEepromRecordMetrum extends AltosEepromRecord {
gps.pdop = pdop() / 10.0;
break;
case AltosLib.AO_LOG_GPS_SAT:
- gps = cal_data.make_temp_gps(tick(), true);
+ gps = listener.make_temp_gps(true);
int n = nsat();
for (int i = 0; i < n; i++)
diff --git a/altoslib/AltosEepromRecordSet.java b/altoslib/AltosEepromRecordSet.java
index 48e90c05..36075931 100644
--- a/altoslib/AltosEepromRecordSet.java
+++ b/altoslib/AltosEepromRecordSet.java
@@ -44,6 +44,8 @@ public class AltosEepromRecordSet implements AltosRecordSet {
AltosCalData cal_data = cal_data();
cal_data.reset();
+ listener.set_log_format(config_data().log_format);
+
for (AltosEepromRecord record : ordered) {
record.provide_data(listener, cal_data);
}
@@ -67,6 +69,7 @@ public class AltosEepromRecordSet implements AltosRecordSet {
case AltosLib.AO_LOG_FORMAT_TELEMETRY:
case AltosLib.AO_LOG_FORMAT_TELESCIENCE:
case AltosLib.AO_LOG_FORMAT_TELEMEGA:
+ case AltosLib.AO_LOG_FORMAT_TELEMEGA_3:
case AltosLib.AO_LOG_FORMAT_TELEMEGA_OLD:
record = new AltosEepromRecordMega(eeprom);
break;
@@ -95,7 +98,7 @@ public class AltosEepromRecordSet implements AltosRecordSet {
int tick = 0;
boolean first = true;
- for (;;) {
+ do {
int t = record.tick();
if (first) {
@@ -108,10 +111,8 @@ public class AltosEepromRecordSet implements AltosRecordSet {
}
record.wide_tick = tick;
ordered.add(record);
- if (!record.hasNext())
- break;
record = record.next();
- }
+ } while (record != null);
}
public AltosEepromRecordSet(InputStream input) throws IOException {
diff --git a/altoslib/AltosFile.java b/altoslib/AltosFile.java
index 69f779c1..6f98b87a 100644
--- a/altoslib/AltosFile.java
+++ b/altoslib/AltosFile.java
@@ -36,10 +36,23 @@ public class AltosFile extends File {
return String.format("-via-%04d", receiver);
}
+ static private String label(int flight) {
+ if (flight < 0)
+ return "corrupt";
+ else
+ return "flight";
+ }
+
+ static private int flight(int flight) {
+ if (flight < 0)
+ return -flight;
+ return flight;
+ }
+
public AltosFile(int year, int month, int day, int serial, int flight, int receiver, String extension) {
super (AltosPreferences.logdir(),
- String.format("%04d-%02d-%02d-serial-%s-flight-%s%s.%s",
- year, month, day, number(serial), number(flight), receiver(receiver), extension));
+ String.format("%04d-%02d-%02d-serial-%s-%s-%s%s.%s",
+ year, month, day, number(serial), label(flight), number(flight(flight)), receiver(receiver), extension));
}
public AltosFile(int year, int month, int day, int serial, int flight, String extension) {
diff --git a/altoslib/AltosFilterListener.java b/altoslib/AltosFilterListener.java
new file mode 100644
index 00000000..fe91100a
--- /dev/null
+++ b/altoslib/AltosFilterListener.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright © 2017 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, 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_12;
+
+public interface AltosFilterListener {
+ void filter_changed(double speed_filter, double accel_filter);
+
+ double speed_filter();
+ double accel_filter();
+}
diff --git a/altoslib/AltosFlightListener.java b/altoslib/AltosFlightListener.java
deleted file mode 100644
index d61831a9..00000000
--- a/altoslib/AltosFlightListener.java
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * Copyright © 2017 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, 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_12;
-
-public abstract class AltosFlightListener {
-
- public int flight;
- public int serial;
- public int tick;
- public int boost_tick;
- public int state;
-
- public double accel_plus_g;
- public double accel_minus_g;
- public double accel;
-
- 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) {
- if (boost_tick != AltosLib.MISSING)
- this.boost_tick = boost_tick;
- }
-
- public void set_tick(int tick) {
- if (tick != AltosLib.MISSING)
- this.tick = tick;
- }
-
- public double time() {
- if (tick == AltosLib.MISSING)
- return AltosLib.MISSING;
- if (boost_tick != AltosLib.MISSING)
- return (tick - boost_tick) / 100.0;
- else
- return tick / 100.0;
- }
-
- public double boost_time() {
- if (boost_tick == AltosLib.MISSING)
- return AltosLib.MISSING;
- 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 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)
- this.flight = flight;
- }
- public int flight() {
- return flight;
- }
-
- 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);
-
- public abstract void set_temperature(double deg_c);
- public abstract void set_battery_voltage(double volts);
-
- public abstract void set_apogee_voltage(double volts);
- public abstract void set_main_voltage(double volts);
-
- public void set_temp_gps() {
- temp_gps = null;
- }
-
- public boolean gps_pending() {
- return temp_gps != null;
- }
-
- public AltosGPS make_temp_gps(boolean sats) {
- if (temp_gps == null) {
- temp_gps = new AltosGPS();
- }
- if (sats) {
- if (tick != temp_gps_sat_tick)
- temp_gps.cc_gps_sat = null;
- temp_gps_sat_tick = tick;
- }
- return temp_gps;
- }
-
- public 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 check_imu_wrap(AltosIMU imu);
- public abstract void set_imu(AltosIMU imu);
- public abstract void set_mag(AltosMag mag);
- public abstract void set_pyro_voltage(double volts);
- public abstract void set_igniter_voltage(double[] voltage);
- public abstract void set_pyro_fired(int pyro_mask);
-
- 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 57f1a491..d130d3ad 100644
--- a/altoslib/AltosFlightSeries.java
+++ b/altoslib/AltosFlightSeries.java
@@ -21,7 +21,7 @@ public class AltosFlightSeries extends AltosDataListener {
public ArrayList<AltosTimeSeries> series = new ArrayList<AltosTimeSeries>();
public double speed_filter_width = 4.0;
- public double accel_filter_width = 4.0;
+ public double accel_filter_width = 1.0;
public int[] indices() {
int[] indices = new int[series.size()];
@@ -150,18 +150,17 @@ public class AltosFlightSeries extends AltosDataListener {
public void set_state(int state) {
- if (state == AltosLib.ao_flight_pad)
- return;
-
- if (state_series == null)
- state_series = add_series(state_name, AltosConvert.state_name);
- else if (this.state == state)
- return;
- this.state = state;
- state_series.add(time(), state);
+ if (state != AltosLib.ao_flight_pad && state != AltosLib.MISSING && state != AltosLib.ao_flight_stateless) {
+ if (state_series == null)
+ state_series = add_series(state_name, AltosConvert.state_name);
+ if (this.state() != state)
+ state_series.add(time(), state);
+ }
+ super.set_state(state);
}
public AltosTimeSeries accel_series;
+ public boolean accel_computed;
public static final String accel_name = "Accel";
@@ -176,23 +175,61 @@ public class AltosFlightSeries extends AltosDataListener {
accel_series = add_series(accel_name, AltosConvert.accel);
accel_series.add(time(), acceleration);
+ accel_computed = false;
}
- private void compute_accel() {
- if (accel_series != null)
- return;
+ private AltosTimeSeries compute_accel() {
+ AltosTimeSeries new_accel_series = null;
if (speed_series != null) {
- AltosTimeSeries temp_series = make_series(speed_name, AltosConvert.speed);
- speed_series.filter(temp_series, accel_filter_width);
- accel_series = add_series(accel_name, AltosConvert.accel);
- temp_series.differentiate(accel_series);
+ AltosTimeSeries temp_series;
+ if (accel_filter_width > 0) {
+ temp_series = make_series(speed_name, AltosConvert.speed);
+ speed_series.filter(temp_series, accel_filter_width);
+ } else
+ temp_series = speed_series;
+
+ new_accel_series = make_series(accel_name, AltosConvert.accel);
+ temp_series.differentiate(new_accel_series);
+ }
+ return new_accel_series;
+ }
+
+ public void set_filter(double speed_filter, double accel_filter) {
+ this.speed_filter_width = speed_filter;
+ this.accel_filter_width = accel_filter;
+
+ AltosTimeSeries new_speed_series = compute_speed();
+
+ if (new_speed_series != null) {
+ speed_series.erase_values();
+ for (AltosTimeValue tv : new_speed_series)
+ speed_series.add(tv);
+ }
+ if (accel_computed) {
+ AltosTimeSeries new_accel_series = compute_accel();
+ if (new_accel_series != null) {
+ accel_series.erase_values();
+ for (AltosTimeValue tv : new_accel_series)
+ accel_series.add(tv);
+ }
}
}
public void set_received_time(long received_time) {
}
+ public AltosTimeSeries tick_series;
+
+ public static final String tick_name = "Tick";
+
+ public void set_tick(int tick) {
+ super.set_tick(tick);
+ if (tick_series == null)
+ tick_series = add_series(tick_name, null);
+ tick_series.add(time(), tick);
+ }
+
public AltosTimeSeries rssi_series;
public static final String rssi_name = "RSSI";
@@ -259,21 +296,24 @@ public class AltosFlightSeries extends AltosDataListener {
public static final String speed_name = "Speed";
- private void compute_speed() {
- if (speed_series != null)
- return;
-
+ private AltosTimeSeries compute_speed() {
+ AltosTimeSeries new_speed_series = null;
AltosTimeSeries alt_speed_series = null;
AltosTimeSeries accel_speed_series = null;
if (altitude_series != null) {
- AltosTimeSeries temp_series = make_series(altitude_name, AltosConvert.height);
- altitude_series.filter(temp_series, speed_filter_width);
+ AltosTimeSeries temp_series;
+
+ if (speed_filter_width > 0) {
+ temp_series = make_series(speed_name, AltosConvert.height);
+ altitude_series.filter(temp_series, speed_filter_width);
+ } else
+ temp_series = altitude_series;
alt_speed_series = make_series(speed_name, AltosConvert.speed);
temp_series.differentiate(alt_speed_series);
}
- if (accel_series != null) {
+ if (accel_series != null && !accel_computed) {
if (orient_series != null) {
vert_accel_series = add_series(vert_accel_name, AltosConvert.accel);
@@ -309,26 +349,25 @@ public class AltosFlightSeries extends AltosDataListener {
}
}
if (apogee_time == AltosLib.MISSING) {
- speed_series = alt_speed_series;
+ new_speed_series = alt_speed_series;
} else {
- speed_series = make_series(speed_name, AltosConvert.speed);
+ new_speed_series = make_series(speed_name, AltosConvert.speed);
for (AltosTimeValue d : accel_speed_series) {
if (d.time <= apogee_time)
- speed_series.add(d);
+ new_speed_series.add(d);
}
for (AltosTimeValue d : alt_speed_series) {
if (d.time > apogee_time)
- speed_series.add(d);
+ new_speed_series.add(d);
}
}
} else if (alt_speed_series != null) {
- speed_series = alt_speed_series;
+ new_speed_series = alt_speed_series;
} else if (accel_speed_series != null) {
- speed_series = accel_speed_series;
+ new_speed_series = accel_speed_series;
}
- if (speed_series != null)
- add_series(speed_series);
+ return new_speed_series;
}
public AltosTimeSeries orient_series;
@@ -450,13 +489,24 @@ public class AltosFlightSeries extends AltosDataListener {
public ArrayList<AltosGPSTimeValue> gps_series;
public AltosGPS gps_before(double time) {
- AltosGPS gps = null;
- for (AltosGPSTimeValue gtv : gps_series)
- if (gtv.time <= time)
- gps = gtv.gps;
- else
- break;
- return gps;
+ AltosGPSTimeValue nearest = null;
+ for (AltosGPSTimeValue gtv : gps_series) {
+ if (nearest == null)
+ nearest = gtv;
+ else {
+ if (gtv.time <= time) {
+ if (nearest.time <= time && gtv.time > nearest.time)
+ nearest = gtv;
+ } else {
+ if (nearest.time > time && gtv.time < nearest.time)
+ nearest = gtv;
+ }
+ }
+ }
+ if (nearest != null)
+ return nearest.gps;
+ else
+ return null;
}
public AltosTimeSeries sats_in_view;
@@ -482,6 +532,7 @@ public class AltosFlightSeries extends AltosDataListener {
public static final String gps_hdop_name = "GPS Horizontal Dilution of Precision";
public void set_gps(AltosGPS gps) {
+ super.set_gps(gps);
if (gps_series == null)
gps_series = new ArrayList<AltosGPSTimeValue>();
gps_series.add(new AltosGPSTimeValue(time(), gps));
@@ -643,7 +694,7 @@ public class AltosFlightSeries extends AltosDataListener {
public void set_igniter_voltage(double[] voltage) {
int channels = voltage.length;
if (igniter_voltage == null || igniter_voltage.length <= channels) {
- AltosTimeSeries[] new_igniter_voltage = new AltosTimeSeries[channels + 1];
+ AltosTimeSeries[] new_igniter_voltage = new AltosTimeSeries[channels];
int i = 0;
if (igniter_voltage != null) {
@@ -681,8 +732,18 @@ public class AltosFlightSeries extends AltosDataListener {
public void finish() {
compute_orient();
- compute_speed();
- compute_accel();
+ if (speed_series == null) {
+ speed_series = compute_speed();
+ if (speed_series != null)
+ add_series(speed_series);
+ }
+ if (accel_series == null) {
+ accel_series = compute_accel();
+ if (accel_series != null) {
+ add_series(accel_series);
+ accel_computed = true;
+ }
+ }
compute_height();
}
diff --git a/altoslib/AltosFlightStats.java b/altoslib/AltosFlightStats.java
index ea1a9675..6bb83581 100644
--- a/altoslib/AltosFlightStats.java
+++ b/altoslib/AltosFlightStats.java
@@ -27,6 +27,8 @@ public class AltosFlightStats {
public double max_acceleration;
public double[] state_speed = new double[AltosLib.ao_flight_invalid + 1];
public double[] state_enter_speed = new double[AltosLib.ao_flight_invalid + 1];
+ public double[] state_enter_height = new double[AltosLib.ao_flight_invalid + 1];
+ public double[] state_enter_gps_height = new double[AltosLib.ao_flight_invalid + 1];
public double[] state_accel = new double[AltosLib.ao_flight_invalid + 1];
public double[] state_time = new double[AltosLib.ao_flight_invalid + 1];
public String product;
@@ -134,6 +136,11 @@ public class AltosFlightStats {
if (0 <= state && state <= AltosLib.ao_flight_invalid && delta_time > 0) {
if (state_enter_speed[state] == AltosLib.MISSING)
state_enter_speed[state] = series.speed_series.value(start_time);
+ if (state_enter_height[state] == AltosLib.MISSING)
+ state_enter_height[state] = series.height_series.value(start_time);
+ if (state_enter_gps_height[state] == AltosLib.MISSING)
+ if (series.gps_height != null)
+ state_enter_gps_height[state] = series.gps_height.value(start_time);
speeds[state].value += series.speed_series.average(start_time, end_time) * delta_time;
speeds[state].time += delta_time;
accels[state].value += series.accel_series.average(start_time, end_time) * delta_time;
diff --git a/altoslib/AltosIMU.java b/altoslib/AltosIMU.java
index dee28a92..ba6f1a82 100644
--- a/altoslib/AltosIMU.java
+++ b/altoslib/AltosIMU.java
@@ -83,9 +83,9 @@ public class AltosIMU implements Cloneable {
listener.set_gyro(cal_data.gyro_roll(imu.gyro_y),
cal_data.gyro_pitch(imu.gyro_x),
cal_data.gyro_yaw(imu.gyro_z));
- listener.set_accel_ground(cal_data.accel_along(imu.accel_y),
- cal_data.accel_across(imu.accel_x),
- cal_data.accel_through(imu.accel_z));
+ listener.set_accel_ground(imu.accel_y,
+ imu.accel_x,
+ imu.accel_z);
}
} catch (TimeoutException te) {
}
diff --git a/altoslib/AltosIdleMonitor.java b/altoslib/AltosIdleMonitor.java
index fc5d4cc8..834d9aa5 100644
--- a/altoslib/AltosIdleMonitor.java
+++ b/altoslib/AltosIdleMonitor.java
@@ -33,6 +33,7 @@ public class AltosIdleMonitor extends Thread {
double frequency;
String callsign;
+ AltosState state;
AltosListenerState listener_state;
AltosConfigData config_data;
AltosGPS gps;
@@ -52,20 +53,23 @@ public class AltosIdleMonitor extends Thread {
return link.reply_abort;
}
- boolean provide_data(AltosDataListener listener) throws InterruptedException, TimeoutException, AltosUnknownProduct {
+ boolean provide_data() throws InterruptedException, TimeoutException, AltosUnknownProduct {
boolean worked = false;
boolean aborted = false;
try {
start_link();
- fetch.provide_data(listener);
+ link.config_data();
+ if (state == null)
+ state = new AltosState(new AltosCalData(link.config_data()));
+ fetch.provide_data(state);
if (!link.has_error && !link.reply_abort)
worked = true;
} finally {
aborted = stop_link();
if (worked) {
if (remote)
- listener.set_rssi(link.rssi(), 0);
+ state.set_rssi(link.rssi(), 0);
listener_state.battery = link.monitor_battery();
}
}
@@ -92,14 +96,11 @@ public class AltosIdleMonitor extends Thread {
}
public void run() {
- AltosState state = null;
+ state = null;
try {
for (;;) {
try {
- link.config_data();
- if (state == null)
- state = new AltosState(new AltosCalData(link.config_data()));
- provide_data(state);
+ provide_data();
listener.update(state, listener_state);
} catch (TimeoutException te) {
} catch (AltosUnknownProduct ae) {
diff --git a/altoslib/AltosKML.java b/altoslib/AltosKML.java
index 587b845b..d5248a17 100644
--- a/altoslib/AltosKML.java
+++ b/altoslib/AltosKML.java
@@ -38,16 +38,18 @@ public class AltosKML implements AltosWriter {
int flight_state = -1;
AltosGPS prev = null;
double gps_start_altitude = AltosLib.MISSING;
+ AltosFlightSeries series;
AltosFlightStats stats;
+ AltosCalData cal_data;
static final String[] kml_state_colors = {
"FF000000", // startup
"FF000000", // idle
"FF000000", // pad
"FF0000FF", // boost
+ "FF8040FF", // coast
"FF4080FF", // fast
- "FF00FFFF", // coast
- "FFFF0000", // drogue
+ "FF00FFFF", // drogue
"FF00FF00", // main
"FF000000", // landed
"FFFFFFFF", // invalid
@@ -60,85 +62,169 @@ public class AltosKML implements AltosWriter {
return kml_state_colors[state];
}
+ static final String[] kml_style_colors = {
+ "FF0000FF", // baro
+ "FFFF0000", // gps
+ };
+
+ static String style_color(int style) {
+ if (style < 0 || kml_style_colors.length <= style)
+ return kml_style_colors[0];
+ return kml_style_colors[style];
+ }
+
static final String kml_header_start =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<kml xmlns=\"http://www.opengis.net/kml/2.2\">\n" +
"<Document>\n" +
" <name>AO Flight#%d S/N: %03d</name>\n" +
- " <description>\n";
+ " <Snippet maxLines=\"8\">\n";
+
static final String kml_header_end =
- " </description>\n" +
- " <open>0</open>\n";
-
- static final String kml_style_start =
- " <Style id=\"ao-flightstate-%s\">\n" +
- " <LineStyle><color>%s</color><width>4</width></LineStyle>\n" +
- " <BalloonStyle>\n" +
- " <text>\n";
-
- static final String kml_style_end =
- " </text>\n" +
- " </BalloonStyle>\n" +
- " </Style>\n";
-
- static final String kml_placemark_start =
- " <Placemark>\n" +
- " <name>%s</name>\n" +
- " <styleUrl>#ao-flightstate-%s</styleUrl>\n" +
- " <LineString>\n" +
- " <tessellate>1</tessellate>\n" +
- " <altitudeMode>absolute</altitudeMode>\n" +
- " <coordinates>\n";
+ " </Snippet>\n" +
+ " <open>1</open>\n";
+
+ static final String kml_folder_start =
+ " <Folder>\n" +
+ " <name>%s</name>\n";
+
+ static final String kml_path_style_start =
+ " <Style id=\"ao-style-%s\">\n" +
+ " <LineStyle><color>%s</color><width>8</width></LineStyle>\n" +
+ " <BalloonStyle>\n" +
+ " <text>\n";
+
+ static final String kml_path_style_end =
+ " </text>\n" +
+ " </BalloonStyle>\n" +
+ " </Style>\n";
+
+ static final String kml_point_style_start =
+ " <Style id=\"ao-style-%s\">\n" +
+ " <LabelStyle><color>%s</color></LabelStyle>\n" +
+ " <IconStyle><color>%s</color></IconStyle>\n" +
+ " <BalloonStyle>\n" +
+ " <text>\n";
+
+ static final String kml_point_style_end =
+ " </text>\n" +
+ " </BalloonStyle>\n" +
+ " </Style>\n";
+
+ static final String kml_path_start =
+ " <Placemark>\n" +
+ " <name>%s</name>\n" +
+ " <styleUrl>#ao-style-%s</styleUrl>\n" +
+ " <LineString>\n" +
+ " <tessellate>1</tessellate>\n" +
+ " <altitudeMode>absolute</altitudeMode>\n" +
+ " <coordinates>\n";
static final String kml_coord_fmt =
- " %.7f,%.7f,%.7f <!-- alt %12.7f time %12.7f sats %d -->\n";
+ " %.7f,%.7f,%.7f <!-- alt %12.7f time %12.7f sats %d -->\n";
- static final String kml_placemark_end =
- " </coordinates>\n" +
- " </LineString>\n" +
- " </Placemark>\n";
+ static final String kml_path_end =
+ " </coordinates>\n" +
+ " </LineString>\n" +
+ " </Placemark>\n";
+
+ static final String kml_point_start =
+ " <Placemark>\n" +
+ " <name>%s</name>\n" +
+ " <styleUrl>#ao-style-%s</styleUrl>\n" +
+ " <Point>\n" +
+ " <tessellate>1</tessellate>\n" +
+ " <altitudeMode>absolute</altitudeMode>\n" +
+ " <coordinates>\n";
+
+ static final String kml_point_end =
+ " </coordinates>\n" +
+ " </Point>\n" +
+ " </Placemark>\n";
+
+ static final String kml_folder_end =
+ " </Folder>\n";
static final String kml_footer =
"</Document>\n" +
"</kml>\n";
- void start (AltosCalData cal_data) {
+ void start () {
AltosGPS gps = cal_data.gps_pad;
gps_start_altitude = cal_data.gps_pad_altitude;
out.printf(kml_header_start, cal_data.flight, cal_data.serial);
- out.printf("Date: %04d-%02d-%02d\n",
+ out.printf("Product: %s\n", stats.product);
+ out.printf("Firmware: %s\n", stats.firmware_version);
+ out.printf("Date: %04d-%02d-%02d\n",
gps.year, gps.month, gps.day);
- out.printf("Time: %2d:%02d:%02d\n",
+ out.printf("Time: %2d:%02d:%02d\n",
gps.hour, gps.minute, gps.second);
+ if (stats.max_height != AltosLib.MISSING)
+ out.printf("Max baro height: %s\n", AltosConvert.height.show(6, stats.max_height));
+ if (stats.max_gps_height != AltosLib.MISSING)
+ out.printf("Max GPS Height: %s\n", AltosConvert.height.show(6, stats.max_gps_height));
+ if (stats.max_speed != AltosLib.MISSING)
+ out.printf("Max speed: %s\n", AltosConvert.speed.show(6, stats.max_speed));
+ if (stats.max_acceleration != AltosLib.MISSING)
+ out.printf("Max accel: %s\n", AltosConvert.accel.show(6, stats.max_acceleration));
out.printf("%s", kml_header_end);
}
- boolean started = false;
+ void folder_start(String folder_name) {
+ out.printf(kml_folder_start, folder_name);
+ }
+
+ void folder_end() {
+ out.printf(kml_folder_end);
+ }
+
+ void path_style_start(String style, String color) {
+ out.printf(kml_path_style_start, style, color);
+ }
+
+ void path_style_end() {
+ out.printf(kml_path_style_end);
+ }
- 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("State: %s\n", state_name);
- out.printf("Time: %6.2f s\n", stats.state_time[state]);
- out.printf("Average speed: %s\n", AltosConvert.speed.show(6, stats.state_speed[state]));
- out.printf("Average accel: %s\n", AltosConvert.accel.show(6, stats.state_accel[state]));
- out.printf("%s", kml_style_end);
- out.printf(kml_placemark_start, state_name, state_name);
+ void point_style_start(String style, String color) {
+ out.printf(kml_point_style_start, style, color, color);
}
- void state_end() {
- out.printf("%s", kml_placemark_end);
+ void point_style_end() {
+ out.printf(kml_point_style_end);
}
- void coord(double time, AltosGPS gps, int state, double height) {
- double altitude;
+ void path_start(String name, String style) {
+ out.printf(kml_path_start, name, style);
+ }
+
+ void path_end() {
+ out.printf(kml_path_end);
+ }
+
+ void point_start(String name, String style) {
+ out.printf(kml_point_start, name, style);
+ }
+
+ void point_end() {
+ out.printf(kml_point_end);
+ }
+
+ boolean started = false;
+
+ private double baro_altitude(AltosFlightSeries series, double time) {
+ double height = series.value(AltosFlightSeries.height_name, time);
+
+ if (height == AltosLib.MISSING)
+ return AltosLib.MISSING;
+ if (cal_data.gps_pad_altitude == AltosLib.MISSING)
+ return AltosLib.MISSING;
- if (height != AltosLib.MISSING)
- altitude = height + gps_start_altitude;
- else
- altitude = gps.alt;
+ return height + cal_data.gps_pad_altitude;
+ }
+
+ void coord(double time, AltosGPS gps, double altitude) {
out.printf(kml_coord_fmt,
gps.lon, gps.lat,
altitude, (double) gps.alt,
@@ -150,48 +236,111 @@ public class AltosKML implements AltosWriter {
}
public void close() {
- if (prev != null) {
- state_end();
- end();
- prev = null;
- }
if (out != null) {
out.close();
out = null;
}
}
- public void write(AltosGPSTimeValue gtv, AltosCalData cal_data, int state, double height) {
- AltosGPS gps = gtv.gps;
+ public void write(AltosGPS gps, double alt)
+ {
+ if (gps == null)
+ return;
if (gps.lat == AltosLib.MISSING)
return;
if (gps.lon == AltosLib.MISSING)
return;
- if (state != flight_state) {
- flight_state = state;
- if (prev != null) {
- coord(gtv.time, gps, state, height);
- state_end();
- }
- state_start(state);
+ if (alt == AltosLib.MISSING) {
+ alt = cal_data.gps_pad_altitude;
+ if (alt == AltosLib.MISSING)
+ return;
}
- coord(0, gps, state, height);
+ coord(0, gps, alt);
prev = gps;
}
- private int state(AltosFlightSeries series, double time) {
- return (int) series.value_before(AltosFlightSeries.state_name, time);
- }
+ public void write_point(AltosTimeValue tv, boolean is_gps) {
+ int state = (int) tv.value;
+ String style_prefix = is_gps ? "gps-" : "baro-";
+ String state_name = AltosLib.state_name(state);
+ String state_label = AltosLib.state_name_capital(state);
+ String style_name = style_prefix + state_name;
+ String folder_name = is_gps ? "GPS" : "Baro";
+ String full_name = state_label + " (" + folder_name + ")";
+ AltosGPS gps = series.gps_before(tv.time);
+ double altitude = is_gps ? gps.alt : baro_altitude(series, tv.time);
- private double height(AltosFlightSeries series, double time) {
- return series.value(AltosFlightSeries.height_name, time);
+ point_style_start(style_name, state_color(state));
+ out.printf("%s\n", full_name);
+ switch (state) {
+ case AltosLib.ao_flight_boost:
+ out.printf("Max accel %s\n", AltosConvert.accel.show(6, stats.max_acceleration));
+ out.printf("Max speed %s\n", AltosConvert.speed.show(6, stats.max_speed));
+ break;
+ case AltosLib.ao_flight_coast:
+ case AltosLib.ao_flight_fast:
+ out.printf("Entry speed %s\n", AltosConvert.speed.show(6, stats.state_enter_speed[state]));
+ out.printf("Entry height %s\n", AltosConvert.height.show(6, altitude - cal_data.gps_pad_altitude));
+ break;
+ case AltosLib.ao_flight_drogue:
+ out.printf("Max height %s\n", AltosConvert.height.show(6, is_gps ? stats.max_gps_height : stats.max_height));
+ out.printf("Average descent rate %s\n", AltosConvert.speed.show(6, -stats.state_speed[state]));
+ break;
+ case AltosLib.ao_flight_main:
+ out.printf("Entry speed %s\n", AltosConvert.speed.show(6, -stats.state_enter_speed[state]));
+ out.printf("Entry height %s\n", AltosConvert.height.show(6, altitude - cal_data.gps_pad_altitude));
+ out.printf("Average descent rate %s\n", AltosConvert.speed.show(6, -stats.state_speed[state]));
+ break;
+ case AltosLib.ao_flight_landed:
+ out.printf("Landing speed %s\n", AltosConvert.speed.show(6, -stats.state_enter_speed[state]));
+ break;
+ }
+ point_style_end();
+ point_start(full_name, style_name);
+ gps = series.gps_before(tv.time);
+ write(gps, altitude);
+ point_end();
}
public void write(AltosFlightSeries series) {
+ this.series = series;
+ series.finish();
stats = new AltosFlightStats(series);
- start(series.cal_data());
+ cal_data = series.cal_data();
+ start();
+ if (series.height_series != null) {
+ folder_start("Barometric Altitude");
+ path_style_start("baro", style_color(0));
+ out.printf("Barometric Altitude\n");
+ out.printf("Max height: %s\n", AltosConvert.height.show(6, stats.max_height));
+ path_style_end();
+ path_start("Barometric Altitude", "baro");
+ for (AltosGPSTimeValue gtv : series.gps_series)
+ write(gtv.gps, baro_altitude(series, gtv.time));
+ path_end();
+ if (series.state_series != null) {
+ for (AltosTimeValue tv : series.state_series) {
+ write_point(tv, false);
+ }
+ }
+ folder_end();
+ }
+ folder_start("GPS Altitude");
+ path_style_start("gps", style_color(1));
+ out.printf("GPS Altitude");
+ out.printf("Max height: %s\n", AltosConvert.height.show(6, stats.max_gps_height));
+ path_style_end();
+ path_start("GPS Altitude", "gps");
for (AltosGPSTimeValue gtv : series.gps_series)
- write(gtv, series.cal_data(), state(series, gtv.time), height(series, gtv.time));
+ write(gtv.gps, gtv.gps.alt);
+ path_end();
+ if (series.state_series != null) {
+ for (AltosTimeValue tv : series.state_series) {
+ write_point(tv, true);
+ }
+ }
+ folder_end();
+ end();
}
public AltosKML(File in_name) throws FileNotFoundException {
diff --git a/altoslib/AltosLib.java b/altoslib/AltosLib.java
index d1063509..c25a6273 100644
--- a/altoslib/AltosLib.java
+++ b/altoslib/AltosLib.java
@@ -363,6 +363,7 @@ public class AltosLib {
public static final int AO_LOG_FORMAT_TELEMINI3 = 12;
public static final int AO_LOG_FORMAT_TELEFIRETWO = 13;
public static final int AO_LOG_FORMAT_EASYMINI2 = 14;
+ public static final int AO_LOG_FORMAT_TELEMEGA_3 = 15;
public static final int AO_LOG_FORMAT_NONE = 127;
public static boolean isspace(int c) {
@@ -587,7 +588,11 @@ public class AltosLib {
}
public static String igniter_name(int i) {
- return String.format("Ignitor %c", 'A' + i);
+ return String.format("Igniter %c", 'A' + i);
+ }
+
+ public static String igniter_short_name(int i) {
+ return String.format("igniter_%c", 'a' + i);
}
public static AltosRecordSet record_set(File file) throws FileNotFoundException, IOException {
diff --git a/altoslib/AltosLink.java b/altoslib/AltosLink.java
index 5413de9d..829a1a63 100644
--- a/altoslib/AltosLink.java
+++ b/altoslib/AltosLink.java
@@ -355,7 +355,8 @@ public abstract class AltosLink implements Runnable {
public int telemetry_rate = -1;
public double frequency;
public String callsign;
- AltosConfigData config_data;
+ private AltosConfigData config_data_local;
+ private AltosConfigData config_data_remote;
private Object config_data_lock = new Object();
@@ -390,7 +391,7 @@ public abstract class AltosLink implements Runnable {
public void set_radio_frequency(double in_frequency) throws InterruptedException, TimeoutException {
frequency = in_frequency;
- config_data();
+ AltosConfigData config_data = config_data();
set_radio_frequency(frequency,
config_data.radio_frequency > 0,
config_data.radio_setting > 0,
@@ -446,11 +447,24 @@ public abstract class AltosLink implements Runnable {
public AltosConfigData config_data() throws InterruptedException, TimeoutException {
synchronized(config_data_lock) {
- if (config_data == null) {
- printf("m 0\n");
- config_data = new AltosConfigData(this);
- if (monitor_mode)
- set_monitor(true);
+ AltosConfigData config_data;
+
+ if (remote) {
+ if (config_data_remote == null) {
+ printf("m 0\n");
+ config_data_remote = new AltosConfigData(this);
+ if (monitor_mode)
+ set_monitor(true);
+ }
+ config_data = config_data_remote;
+ } else {
+ if (config_data_local == null) {
+ printf("m 0\n");
+ config_data_local = new AltosConfigData(this);
+ if (monitor_mode)
+ set_monitor(true);
+ }
+ config_data = config_data_local;
}
return config_data;
}
@@ -551,14 +565,23 @@ public abstract class AltosLink implements Runnable {
}
public boolean has_monitor_battery() {
- return config_data.has_monitor_battery();
+ try {
+ return config_data().has_monitor_battery();
+ } catch (InterruptedException ie) {
+ return false;
+ } catch (TimeoutException te) {
+ return false;
+ }
}
public double monitor_battery() throws InterruptedException {
- int monitor_batt = AltosLib.MISSING;
+ double volts = AltosLib.MISSING;
- if (config_data.has_monitor_battery()) {
- try {
+ try {
+ AltosConfigData config_data = config_data();
+ int monitor_batt = AltosLib.MISSING;
+
+ if (config_data.has_monitor_battery()) {
String[] items = adc();
for (int i = 0; i < items.length;) {
if (items[i].equals("batt")) {
@@ -568,19 +591,17 @@ public abstract class AltosLink implements Runnable {
}
i++;
}
- } catch (TimeoutException te) {
}
- }
- if (monitor_batt == AltosLib.MISSING)
- return AltosLib.MISSING;
+ if (monitor_batt != AltosLib.MISSING) {
+ if (config_data.product.startsWith("TeleBT-v3") || config_data.product.startsWith("TeleBT-v4")) {
+ volts = AltosConvert.tele_bt_3_battery(monitor_batt);
+ } else {
+ volts = AltosConvert.cc_battery_to_voltage(monitor_batt);
+ }
+ }
- double volts = AltosLib.MISSING;
- if (config_data.product.startsWith("TeleBT-v3") || config_data.product.startsWith("TeleBT-v4")) {
- volts = AltosConvert.tele_bt_3_battery(monitor_batt);
- } else {
- volts = AltosConvert.cc_battery_to_voltage(monitor_batt);
+ } catch (TimeoutException te) {
}
-
return volts;
}
diff --git a/altoslib/AltosReplayReader.java b/altoslib/AltosReplayReader.java
index 24b425b7..fab28cac 100644
--- a/altoslib/AltosReplayReader.java
+++ b/altoslib/AltosReplayReader.java
@@ -31,7 +31,7 @@ class AltosReplay extends AltosDataListener implements Runnable {
AltosState state;
AltosRecordSet record_set;
double last_time = AltosLib.MISSING;
- Semaphore semaphore = new Semaphore(1);;
+ Semaphore semaphore = new Semaphore(1);
boolean done = false;
public void set_time(double time) {
@@ -70,7 +70,7 @@ class AltosReplay extends AltosDataListener implements Runnable {
public void set_apogee_voltage(double volts) { state.set_apogee_voltage(volts); }
public void set_main_voltage(double volts) { state.set_main_voltage(volts); }
- public void set_gps(AltosGPS gps) { state.set_gps(gps); }
+ public void set_gps(AltosGPS gps) { super.set_gps(gps); state.set_gps(gps); }
public void set_orient(double orient) { state.set_orient(orient); }
public void set_gyro(double roll, double pitch, double yaw) { state.set_gyro(roll, pitch, yaw); }
diff --git a/altoslib/AltosState.java b/altoslib/AltosState.java
index 39ab10da..68097faf 100644
--- a/altoslib/AltosState.java
+++ b/altoslib/AltosState.java
@@ -480,7 +480,7 @@ public class AltosState extends AltosDataListener {
class AltosPressure extends AltosValue {
void set(double p, double time) {
super.set(p, time);
- if (state == AltosLib.ao_flight_pad)
+ if (state() == AltosLib.ao_flight_pad)
ground_pressure.set_filtered(p, time);
double a = pressure_to_altitude(p);
altitude.set_computed(a, time);
@@ -557,7 +557,7 @@ public class AltosState extends AltosDataListener {
class AltosSpeed extends AltosCValue {
boolean can_max() {
- return state < AltosLib.ao_flight_fast || state == AltosLib.ao_flight_stateless;
+ return state() < AltosLib.ao_flight_fast || state() == AltosLib.ao_flight_stateless;
}
void set_accel() {
@@ -615,7 +615,7 @@ public class AltosState extends AltosDataListener {
class AltosAccel extends AltosCValue {
boolean can_max() {
- return state < AltosLib.ao_flight_fast || state == AltosLib.ao_flight_stateless;
+ return state() < AltosLib.ao_flight_fast || state() == AltosLib.ao_flight_stateless;
}
void set_measured(double a, double time) {
@@ -712,11 +712,11 @@ public class AltosState extends AltosDataListener {
}
public void init() {
+ super.init();
+
set = 0;
received_time = System.currentTimeMillis();
- time = AltosLib.MISSING;
- state = AltosLib.ao_flight_invalid;
landed = false;
boost = false;
rssi = AltosLib.MISSING;
@@ -819,9 +819,9 @@ public class AltosState extends AltosDataListener {
if (gps.locked && gps.nsat >= 4) {
/* Track consecutive 'good' gps reports, waiting for 10 of them */
- if (state == AltosLib.ao_flight_pad || state == AltosLib.ao_flight_stateless) {
+ if (state() == AltosLib.ao_flight_pad || state() == AltosLib.ao_flight_stateless) {
set_npad(npad+1);
- if (pad_lat != AltosLib.MISSING && (npad < 10 || state == AltosLib.ao_flight_pad)) {
+ if (pad_lat != AltosLib.MISSING && (npad < 10 || state() == AltosLib.ao_flight_pad)) {
pad_lat = (pad_lat * 31 + gps.lat) / 32;
pad_lon = (pad_lon * 31 + gps.lon) / 32;
gps_ground_altitude.set_filtered(gps.alt, time);
@@ -859,24 +859,14 @@ public class AltosState extends AltosDataListener {
}
public String state_name() {
- return AltosLib.state_name(state);
+ return AltosLib.state_name(state());
}
public void set_state(int state) {
- if (state != AltosLib.ao_flight_invalid) {
- this.state = state;
- ascent = (AltosLib.ao_flight_boost <= state &&
- state <= AltosLib.ao_flight_coast);
- boost = (AltosLib.ao_flight_boost == state);
- }
- }
-
- public int state() {
- return state;
- }
-
- private void re_init() {
- init();
+ super.set_state(state);
+ ascent = (AltosLib.ao_flight_boost <= state() &&
+ state() <= AltosLib.ao_flight_coast);
+ boost = (AltosLib.ao_flight_boost == state());
}
public int rssi() {
@@ -897,6 +887,7 @@ public class AltosState extends AltosDataListener {
}
public void set_gps(AltosGPS gps) {
+ super.set_gps(gps);
if (gps != null) {
this.gps = gps;
update_gps();
diff --git a/altoslib/AltosTelemetry.java b/altoslib/AltosTelemetry.java
index f17e1171..a374519d 100644
--- a/altoslib/AltosTelemetry.java
+++ b/altoslib/AltosTelemetry.java
@@ -28,8 +28,11 @@ public abstract class AltosTelemetry implements AltosDataProvider {
int[] bytes;
/* All telemetry packets have these fields */
- public int rssi() { return AltosConvert.telem_to_rssi(AltosLib.int8(bytes, bytes.length - 3)); }
- public int status() { return AltosLib.uint8(bytes, bytes.length - 2); }
+ static public int rssi(int[] bytes) { return AltosConvert.telem_to_rssi(AltosLib.int8(bytes, bytes.length - 3)); }
+ static public int status(int[] bytes) { return AltosLib.uint8(bytes, bytes.length - 2); }
+
+ public int rssi() { return rssi(bytes); }
+ public int status() { return status(bytes); }
/* All telemetry packets report these fields in some form */
public abstract int serial();
@@ -51,7 +54,7 @@ public abstract class AltosTelemetry implements AltosDataProvider {
public void provide_data(AltosDataListener listener) {
listener.set_serial(serial());
- if (listener.state == AltosLib.ao_flight_invalid)
+ if (listener.state() == AltosLib.ao_flight_invalid)
listener.set_state(AltosLib.ao_flight_startup);
if (frequency != AltosLib.MISSING)
listener.set_frequency(frequency);
@@ -96,6 +99,9 @@ public abstract class AltosTelemetry implements AltosDataProvider {
if (!cksum(bytes))
throw new ParseException(String.format("invalid line \"%s\"", hex), 0);
+ if ((status(bytes) & PKT_APPEND_STATUS_1_CRC_OK) == 0)
+ throw new AltosCRCException(rssi(bytes));
+
/* length, data ..., rssi, status, checksum -- 4 bytes extra */
switch (bytes.length) {
case AltosLib.ao_telemetry_standard_len + 4:
diff --git a/altoslib/AltosTelemetryConfiguration.java b/altoslib/AltosTelemetryConfiguration.java
index ea307442..c8026a83 100644
--- a/altoslib/AltosTelemetryConfiguration.java
+++ b/altoslib/AltosTelemetryConfiguration.java
@@ -40,7 +40,7 @@ public class AltosTelemetryConfiguration extends AltosTelemetryStandard {
AltosCalData cal_data = listener.cal_data();
- cal_data.set_device_type(device_type());
+ listener.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)
diff --git a/altoslib/AltosTelemetryFile.java b/altoslib/AltosTelemetryFile.java
index 135b0284..e51455f8 100644
--- a/altoslib/AltosTelemetryFile.java
+++ b/altoslib/AltosTelemetryFile.java
@@ -128,7 +128,7 @@ public class AltosTelemetryFile implements AltosRecordSet {
/* Try to pick up at least one pre-boost value */
if (cal_data.time() >= -2)
telem.provide_data(listener);
- if (listener.state == AltosLib.ao_flight_landed)
+ if (listener.state() == AltosLib.ao_flight_landed)
break;
}
listener.finish();
diff --git a/altoslib/AltosTelemetryLocation.java b/altoslib/AltosTelemetryLocation.java
index f4366e33..e2925a58 100644
--- a/altoslib/AltosTelemetryLocation.java
+++ b/altoslib/AltosTelemetryLocation.java
@@ -54,7 +54,7 @@ public class AltosTelemetryLocation extends AltosTelemetryStandard {
AltosCalData cal_data = listener.cal_data();
- AltosGPS gps = cal_data.make_temp_gps(tick(), false);
+ AltosGPS gps = listener.make_temp_gps(false);
int flags = flags();
gps.nsat = flags & 0xf;
@@ -77,12 +77,7 @@ public class AltosTelemetryLocation extends AltosTelemetryStandard {
gps.ground_speed = ground_speed() * 1.0e-2;
gps.course = course() * 2;
gps.climb_rate = climb_rate() * 1.0e-2;
-
- if (gps.nsat >= 4)
- cal_data.set_gps(gps);
}
listener.set_gps(gps);
- cal_data.set_gps(gps);
- cal_data.reset_temp_gps();
}
}
diff --git a/altoslib/AltosTelemetryMegaData.java b/altoslib/AltosTelemetryMegaData.java
index 7ef9c637..f5961c8c 100644
--- a/altoslib/AltosTelemetryMegaData.java
+++ b/altoslib/AltosTelemetryMegaData.java
@@ -24,7 +24,9 @@ public class AltosTelemetryMegaData extends AltosTelemetryStandard {
int v_batt() { return int16(6); }
int v_pyro() { return int16(8); }
- int sense(int i) { int v = uint8(10+i); return v << 4 | v >> 8; }
+
+ /* pyro sense values are sent in 8 bits, expand to 12 bits */
+ int sense(int i) { int v = uint8(10+i); return (v << 4) | (v >> 4); }
int ground_pres() { return int32(16); }
int ground_accel() { return int16(20); }
diff --git a/altoslib/AltosTelemetryReader.java b/altoslib/AltosTelemetryReader.java
index 26fe4f26..8fb61a4f 100644
--- a/altoslib/AltosTelemetryReader.java
+++ b/altoslib/AltosTelemetryReader.java
@@ -41,19 +41,15 @@ public class AltosTelemetryReader extends AltosFlightReader {
throw new IOException("IO error");
} while (!link.get_monitor());
AltosTelemetry telem = AltosTelemetry.parse(l.line);
- if (state == null) {
- System.out.printf("Make state\n");
+ if (state == null)
state = new AltosState(cal_data());
- }
telem.provide_data(state);
return state;
}
public AltosCalData cal_data() {
- if (cal_data == null) {
- System.out.printf("Make cal data\n");
+ if (cal_data == null)
cal_data = new AltosCalData();
- }
return cal_data;
}
diff --git a/altoslib/AltosTelemetrySatellite.java b/altoslib/AltosTelemetrySatellite.java
index 60bc4a51..0965df9f 100644
--- a/altoslib/AltosTelemetrySatellite.java
+++ b/altoslib/AltosTelemetrySatellite.java
@@ -49,10 +49,9 @@ public class AltosTelemetrySatellite extends AltosTelemetryStandard {
AltosCalData cal_data = listener.cal_data();
- AltosGPS gps = cal_data.make_temp_gps(tick(), true);
+ AltosGPS gps = listener.make_temp_gps(true);
gps.cc_gps_sat = sats();
listener.set_gps(gps);
- cal_data.reset_temp_gps();
}
}
diff --git a/altoslib/AltosTimeSeries.java b/altoslib/AltosTimeSeries.java
index 9f3b4d80..c6a780a3 100644
--- a/altoslib/AltosTimeSeries.java
+++ b/altoslib/AltosTimeSeries.java
@@ -20,15 +20,30 @@ public class AltosTimeSeries implements Iterable<AltosTimeValue>, Comparable<Alt
public String label;
public AltosUnits units;
ArrayList<AltosTimeValue> values;
+ boolean data_changed;
public int compareTo(AltosTimeSeries other) {
return label.compareTo(other.label);
}
public void add(AltosTimeValue tv) {
+ data_changed = true;
values.add(tv);
}
+ public void erase_values() {
+ data_changed = true;
+ this.values = new ArrayList<AltosTimeValue>();
+ }
+
+ public void clear_changed() {
+ data_changed = false;
+ }
+
+// public boolean changed() {
+// return data_changed;
+// }
+
public void add(double time, double value) {
add(new AltosTimeValue(time, value));
}
@@ -264,14 +279,35 @@ public class AltosTimeSeries implements Iterable<AltosTimeValue>, Comparable<Alt
}
- private double filter_coeff(double dist, double width) {
- double ratio = dist / (width / 2);
+ private static double i0(double x) {
+ double ds = 1, d = 0, s = 0;
- return Math.cos(ratio * Math.PI / 2);
+ do {
+ d += 2;
+ ds = ds * (x * x) / (d * d);
+ s += ds;
+ } while (ds - 0.2e-8 * s > 0);
+ return s;
+ }
+
+ private static double kaiser(double n, double m, double beta) {
+ double alpha = m / 2;
+ double t = (n - alpha) / alpha;
+
+ if (t > 1 || t < -1)
+ t = 1;
+ double k = i0 (beta * Math.sqrt (1 - t*t)) / i0(beta);
+ return k;
+ }
+
+ private double filter_coeff(double dist, double width) {
+ return kaiser(dist + width/2.0, width, 2 * Math.PI);
}
public AltosTimeSeries filter(AltosTimeSeries f, double width) {
+
double half_width = width/2;
+ int half_point = values.size() / 2;
for (int i = 0; i < values.size(); i++) {
double center_time = values.get(i).time;
double left_time = center_time - half_width;
diff --git a/altoslib/Makefile.am b/altoslib/Makefile.am
index 08af9496..2a1cb8e4 100644
--- a/altoslib/Makefile.am
+++ b/altoslib/Makefile.am
@@ -55,6 +55,7 @@ altoslib_JAVA = \
AltosEepromList.java \
AltosEepromLog.java \
AltosFile.java \
+ AltosFilterListener.java \
AltosFlash.java \
AltosFlashListener.java \
AltosDataListener.java \