return r;
}
+ public boolean altitude_32() {
+ return altitude_32 == 1;
+ }
+
public int compare_version(String other) {
int[] me = parse_version(version);
int[] them = parse_version(other);
if (frequency > 0) {
radio_frequency = (int) Math.floor (freq * 1000 + 0.5);
- radio_channel = -1;
+ radio_channel = AltosLib.MISSING;
} else if (setting > 0) {
radio_setting =AltosConvert.radio_frequency_to_setting(freq,
radio_calibration);
- radio_channel = -1;
+ radio_channel = AltosLib.MISSING;
} else {
radio_channel = AltosConvert.radio_frequency_to_channel(freq);
}
int setting = radio_setting;
if (radio_frequency < 0 && channel < 0 && setting < 0)
- return -1;
+ return AltosLib.MISSING;
if (channel < 0)
channel = 0;
public static AltosLongitude longitude = new AltosLongitude();
+ public static AltosRotationRate rotation_rate = new AltosRotationRate();
+
public static String show_gs(String format, double a) {
a = meters_to_g(a);
format = format.concat(" g");
import java.util.*;
import java.text.*;
-public class AltosEepromFile extends AltosStateIterable {
+public class AltosEepromFile extends AltosStateIterable implements AltosRecordSet {
AltosEepromRecordSet set;
public Iterator<AltosState> iterator() {
return set.iterator();
}
+
+ public void capture_series(AltosFlightSeries series) {
+ set.capture_series(series);
+ }
}
package org.altusmetrum.altoslib_11;
-
public abstract class AltosEepromRecord implements Comparable<AltosEepromRecord> {
AltosEepromNew eeprom;
return 1;
}
+ public AltosConfigData config_data() {
+ return eeprom.config_data();
+ }
+
public int compareTo(AltosEepromRecord o) {
int cmd_diff = cmdi() - o.cmdi();
return start - o.start;
}
- public void update_state(AltosState state) {
+ public void update_state(AltosFlightListener listen) {
if (cmd() == AltosLib.AO_LOG_FLIGHT)
- state.set_boost_tick(tick());
+ listen.set_boost_tick(tick());
else
- state.set_tick(tick());
+ listen.set_tick(tick());
}
public int next_start() {
return AltosConvert.lb_to_n(v * 298 * 9.807);
}
- public void update_state(AltosState state) {
+ public void update_state(AltosFlightListener state) {
super.update_state(state);
switch (cmd()) {
public static final int two_g_default = 16294 - 15758;
- public void update_state(AltosState state) {
+ public void update_state(AltosFlightListener state) {
+
super.update_state(state);
AltosGPS gps;
/* Flush any pending GPS changes */
- if (state.gps_pending) {
+ if (state.gps_pending()) {
switch (cmd()) {
case AltosLib.AO_LOG_GPS_LAT:
case AltosLib.AO_LOG_GPS_LON:
return start - o.start;
}
- public void update_state(AltosState state) {
+ public void update_state(AltosFlightListener state) {
super.update_state(state);
AltosGPS gps;
/* Flush any pending RecordGps changes */
- if (state.gps_pending) {
+ if (state.gps_pending()) {
switch (cmd()) {
case AltosLib.AO_LOG_GPS_LAT:
case AltosLib.AO_LOG_GPS_LON:
switch (cmd()) {
case AltosLib.AO_LOG_FLIGHT:
- if (state.flight == AltosLib.MISSING) {
+ if (state.flight() == AltosLib.MISSING) {
state.set_boost_tick(tick());
state.set_flight(flight());
}
private int svid(int n) { return data8(2 + n * 2); }
private int c_n(int n) { return data8(2 + n * 2 + 1); }
- public void update_state(AltosState state) {
+ public void update_state(AltosFlightListener state) {
super.update_state(state);
AltosGPS gps;
/* Flush any pending GPS changes */
- if (state.gps_pending) {
+ if (state.gps_pending()) {
switch (cmd()) {
case AltosLib.AO_LOG_GPS_LAT:
case AltosLib.AO_LOG_GPS_LON:
gps.lat = latitude() / 1e7;
gps.lon = longitude() / 1e7;
- if (state.altitude_32())
+ if (config_data().altitude_32())
gps.alt = (altitude_low() & 0xffff) | (altitude_high() << 16);
else
gps.alt = altitude_low();
gps.ground_speed = ground_speed() * 1.0e-2;
gps.course = course() * 2;
gps.climb_rate = climb_rate() * 1.0e-2;
- if (state.compare_version("1.4.9") >= 0) {
+ if (config_data().compare_version("1.4.9") >= 0) {
gps.pdop = pdop() / 10.0;
gps.hdop = hdop() / 10.0;
gps.vdop = vdop() / 10.0;
public int svid(int n) { return data8(2 + n * 2); }
public int c_n(int n) { return data8(2 + n * 2 + 1); }
- public void update_state(AltosState state) {
+ public void update_state(AltosFlightListener state) {
super.update_state(state);
AltosGPS gps;
/* Flush any pending GPS changes */
- if (state.gps_pending) {
+ if (state.gps_pending()) {
switch (cmd()) {
case AltosLib.AO_LOG_GPS_POS:
case AltosLib.AO_LOG_GPS_LAT:
gps = state.make_temp_gps(false);
gps.lat = latitude() / 1e7;
gps.lon = longitude() / 1e7;
- if (state.altitude_32())
+ if (config_data().altitude_32())
gps.alt = (altitude_low() & 0xffff) | (altitude_high() << 16);
else
gps.alt = altitude_low();
return -1;
}
- public void update_state(AltosState state) {
+ public void update_state(AltosFlightListener state) {
super.update_state(state);
switch (cmd()) {
import java.io.*;
import java.util.*;
-public class AltosEepromRecordSet implements Iterable<AltosState> {
+public class AltosEepromRecordSet implements Iterable<AltosState>, AltosRecordSet {
AltosEepromNew eeprom;
TreeSet<AltosEepromRecord> ordered;
AltosState start_state;
return new RecordIterator();
}
+ public void capture_series(AltosFlightSeries series) {
+ series.set_config_data(eeprom.config_data());
+ for (AltosEepromRecord record : ordered) {
+ record.update_state(series);
+ }
+ }
+
public AltosEepromRecordSet(AltosEepromNew eeprom) {
this.eeprom = eeprom;
return tick;
}
- public void update_state(AltosState state) {
+ public void update_state(AltosFlightListener state) {
int value = data16(-header_length);
state.set_tick(tick());
--- /dev/null
+/*
+ * 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_11;
+
+public abstract class AltosFlightListener {
+
+ int flight;
+
+ public int tick;
+ int boost_tick;
+
+ AltosGPS temp_gps;
+ int temp_gps_sat_tick;
+
+ /* AltosEepromRecord */
+ public void set_boost_tick(int boost_tick) {
+ if (boost_tick != AltosLib.MISSING)
+ this.boost_tick = boost_tick;
+ }
+
+ public void set_tick(int tick) {
+ if (tick != AltosLib.MISSING)
+ this.tick = tick;
+ }
+
+ public double time() {
+ if (tick == AltosLib.MISSING)
+ return AltosLib.MISSING;
+ return tick / 100.0;
+ }
+
+ public double boost_time() {
+ if (boost_tick == AltosLib.MISSING)
+ return AltosLib.MISSING;
+ return boost_tick / 100.0;
+ }
+
+ /* AltosEepromRecordFull */
+
+ public abstract void set_state(int state);
+ public abstract void set_ground_accel(double ground_accel);
+ public void set_flight(int flight) {
+ if (flight != AltosLib.MISSING)
+ this.flight = flight;
+ }
+ public int flight() {
+ return flight;
+ }
+
+ public abstract void set_accel(double accel);
+ public abstract void set_accel_g(double accel_plus_g, double accel_minus_g);
+ public abstract void set_pressure(double pa);
+
+ public abstract void set_temperature(double deg_c);
+ public abstract void set_battery_voltage(double volts);
+
+ public abstract void set_apogee_voltage(double volts);
+ public abstract void set_main_voltage(double volts);
+
+ public void set_temp_gps() {
+ temp_gps = null;
+ }
+
+ public boolean gps_pending() {
+ return temp_gps != null;
+ }
+
+ public AltosGPS make_temp_gps(boolean sats) {
+ if (temp_gps == null) {
+ temp_gps = new AltosGPS();
+ }
+ if (sats) {
+ if (tick != temp_gps_sat_tick)
+ temp_gps.cc_gps_sat = null;
+ temp_gps_sat_tick = tick;
+ }
+ return temp_gps;
+ }
+
+ public abstract void set_ground_pressure(double ground_pressure);
+ public abstract void set_accel_ground(double along, double across, double through);
+ public abstract void set_gyro_zero(double roll, double pitch, double yaw);
+ public abstract void set_ms5607(int pres_val, int temp_val);
+ public abstract void check_imu_wrap(AltosIMU imu);
+ public abstract void set_imu(AltosIMU imu);
+ public abstract void set_mag(AltosMag mag);
+ public abstract void set_pyro_voltage(double volts);
+ public abstract void set_ignitor_voltage(double[] voltage);
+ public abstract void set_pyro_fired(int pyro_mask);
+
+ public void copy(AltosFlightListener old) {
+ flight = old.flight;
+ tick = old.tick;
+ boost_tick = old.boost_tick;
+ temp_gps = old.temp_gps;
+ temp_gps_sat_tick = old.temp_gps_sat_tick;
+ }
+
+ public void init() {
+ flight = AltosLib.MISSING;
+ tick = AltosLib.MISSING;
+ boost_tick = AltosLib.MISSING;
+ temp_gps_sat_tick = AltosLib.MISSING;
+ }
+}
--- /dev/null
+/*
+ * 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_11;
+
+import java.util.*;
+
+public class AltosFlightSeries extends AltosFlightListener {
+
+ int flight;
+
+ int tick;
+ int boost_tick;
+
+ AltosGPS temp_gps;
+ int temp_gps_sat_tick;
+
+ AltosMs5607 ms5607;
+
+ public ArrayList<AltosTimeSeries> series;
+
+ /* AltosEepromRecord */
+ public void set_boost_tick(int boost_tick) {
+ if (boost_tick != AltosLib.MISSING)
+ this.boost_tick = boost_tick;
+ }
+
+ public void set_tick(int tick) {
+ if (tick != AltosLib.MISSING)
+ this.tick = tick;
+ }
+
+ public double time() {
+ if (tick == AltosLib.MISSING)
+ return AltosLib.MISSING;
+ return tick / 100.0;
+ }
+
+ public double boost_time() {
+ if (boost_tick == AltosLib.MISSING)
+ return AltosLib.MISSING;
+ return boost_tick / 100.0;
+ }
+
+ public AltosTimeSeries make_series(String label, AltosUnits units) {
+ return new AltosTimeSeries(label, units);
+ }
+
+ public AltosTimeSeries add_series(String label, AltosUnits units) {
+ System.out.printf("add series %s\n", label);
+ AltosTimeSeries s = make_series(label, units);
+ series.add(s);
+ return s;
+ }
+
+ /* AltosEepromRecordFull */
+
+ AltosTimeSeries state_series;
+
+ public static final String state_name = "State";
+
+ public void set_state(int state) {
+ if (state_series == null)
+ state_series = add_series(state_name, null);
+ state_series.add(time(), state);
+ }
+
+ public void set_flight(int flight) {
+ if (flight != AltosLib.MISSING)
+ this.flight = flight;
+ }
+ public int flight() {
+ return flight;
+ }
+
+ AltosTimeSeries accel_series;
+
+ double accel_plus_g, accel_minus_g;
+
+ public static final String accel_name = "Accel";
+
+ public void set_accel(double accel) {
+ if (accel_series == null)
+ accel_series = add_series(accel_name, AltosConvert.accel);
+ double counts_per_g = (accel_minus_g - accel_plus_g) / 2.0;
+ double counts_per_mss = counts_per_g / 9.80665;
+ double mss = (accel_plus_g - accel) / counts_per_mss;
+
+ accel_series.add(time(), mss);
+ }
+
+
+ public void set_accel_g(double accel_plus_g, double accel_minus_g) {
+ this.accel_plus_g = accel_plus_g;
+ this.accel_minus_g = accel_minus_g;
+ }
+
+ public void set_config_data(AltosConfigData config_data) {
+// if (config_data.callsign != null)
+// set_callsign(config_data.callsign);
+ if (config_data.accel_cal_plus != AltosLib.MISSING &&
+ config_data.accel_cal_minus != AltosLib.MISSING)
+ set_accel_g(config_data.accel_cal_plus, config_data.accel_cal_minus);
+// if (config_data.product != null)
+// set_product(config_data.product);
+// if (config_data.log_format != AltosLib.MISSING)
+// set_log_format(config_data.log_format);
+// if (config_data.serial != AltosLib.MISSING)
+// set_serial(config_data.serial);
+ AltosMs5607 ms5607 = new AltosMs5607(config_data);
+ if (ms5607.valid_config())
+ this.ms5607 = ms5607;
+ }
+
+ public void set_ground_accel(double ground_accel) {
+ }
+
+ AltosTimeSeries pressure_series;
+
+ public static final String pressure_name = "Pressure";
+
+ public void set_pressure(double pa) {
+ if (pressure_series == null)
+ pressure_series = add_series(pressure_name, AltosConvert.pressure);
+ pressure_series.add(time(), pa);
+ }
+
+ public void set_temperature(double deg_c) {
+ }
+
+ public void set_battery_voltage(double volts) {
+ }
+
+ public void set_apogee_voltage(double volts) {
+ }
+
+ public void set_main_voltage(double volts) {
+ }
+
+ AltosTimeSeries sats_in_view;
+ AltosTimeSeries sats_in_soln;
+ AltosTimeSeries gps_altitude;
+ AltosTimeSeries gps_ground_speed;
+ AltosTimeSeries gps_ascent_rate;
+ AltosTimeSeries gps_course;
+ AltosTimeSeries gps_speed;
+
+ public static final String sats_in_view_name = "Satellites in view";
+ public static final String sats_in_soln_name = "Satellites in solution";
+ public static final String gps_altitude_name = "GPS Altitude";
+
+ public void set_temp_gps() {
+ if (sats_in_view == null) {
+ sats_in_view = add_series("Satellites in view", null);
+ sats_in_soln = add_series("Satellites in solution", null);
+ gps_altitude = add_series("GPS Altitude", AltosConvert.height);
+ gps_ground_speed = add_series("GPS Ground Speed", AltosConvert.speed);
+ gps_ascent_rate = add_series("GPS Ascent Rate", AltosConvert.speed);
+ gps_course = add_series("GPS Course", null);
+ gps_speed = add_series("GPS Speed", null);
+ }
+
+ /* XXX capture GPS data */
+ super.set_temp_gps();
+ }
+
+ public boolean gps_pending() {
+ return temp_gps != null;
+ }
+
+ public AltosGPS make_temp_gps(boolean sats) {
+ if (temp_gps == null) {
+ temp_gps = new AltosGPS();
+ }
+ if (sats) {
+ if (tick != temp_gps_sat_tick)
+ temp_gps.cc_gps_sat = null;
+ temp_gps_sat_tick = tick;
+ }
+ return temp_gps;
+ }
+
+ public void set_ground_pressure(double ground_pressure) {
+ }
+
+ public void set_accel_ground(double along, double across, double through) {
+ }
+
+ public void set_gyro_zero(double roll, double pitch, double yaw) {
+ }
+
+ public void set_ms5607(int pres_val, int temp_val) {
+ if (ms5607 != null) {
+ ms5607.set(pres_val, temp_val);
+
+ set_pressure(ms5607.pa);
+ set_temperature(ms5607.cc / 100.0);
+ }
+ }
+
+ public void check_imu_wrap(AltosIMU imu) {
+ }
+
+ public void set_imu(AltosIMU imu) {
+ }
+
+ public void set_mag(AltosMag mag) {
+ }
+
+ public void set_pyro_voltage(double volts) {
+ }
+
+ public void set_ignitor_voltage(double[] voltage) {
+ }
+
+ public void set_pyro_fired(int pyro_mask) {
+ }
+
+ public void init() {
+ flight = AltosLib.MISSING;
+ tick = AltosLib.MISSING;
+ boost_tick = AltosLib.MISSING;
+ temp_gps_sat_tick = AltosLib.MISSING;
+ series = new ArrayList<AltosTimeSeries>();
+ }
+
+ public void copy(AltosFlightSeries old) {
+ super.copy(old);
+ }
+
+ public AltosTimeSeries[] series() {
+ return series.toArray(new AltosTimeSeries[0]);
+ }
+
+ public AltosFlightSeries() {
+ init();
+ }
+}
--- /dev/null
+/*
+ * 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_11;
+
+import java.util.*;
+
+public interface AltosRecordSet {
+ public void capture_series(AltosFlightSeries series);
+}
--- /dev/null
+/*
+ * 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_11;
+
+public class AltosRotationRate extends AltosUnits {
+
+ public double value(double p, boolean imperial_units) {
+ return p;
+ }
+
+ public double inverse(double p, boolean imperial_units) {
+ return p;
+ }
+
+ public String show_units(boolean imperial_units) {
+ return "°/sec";
+ }
+
+ public String say_units(boolean imperial_units) {
+ return "degrees per second";
+ }
+
+ public int show_fraction(int width, boolean imperial_units) {
+ return 1;
+ }
+}
import java.io.*;
-public class AltosState implements Cloneable {
+public class AltosState extends AltosFlightListener implements Cloneable {
public static final int set_position = 1;
public static final int set_gps = 2;
public double time;
public double prev_time;
public double time_change;
- public int tick;
private int prev_tick;
- public int boost_tick;
class AltosValue {
double value;
return;
}
+ super.copy(old);
+
received_time = old.received_time;
time = old.time;
time_change = old.time_change;
}
}
- public void set_boost_tick(int boost_tick) {
- if (boost_tick != AltosLib.MISSING)
- this.boost_tick = boost_tick;
- }
-
public String state_name() {
return AltosLib.state_name(state);
}
return tick != AltosLib.MISSING && serial != AltosLib.MISSING;
}
- public AltosGPS make_temp_gps(boolean sats) {
- if (temp_gps == null) {
- temp_gps = new AltosGPS(gps);
- }
- gps_pending = true;
- if (sats) {
- if (tick != temp_gps_sat_tick)
- temp_gps.cc_gps_sat = null;
- temp_gps_sat_tick = tick;
- }
- return temp_gps;
- }
-
public void set_temp_gps() {
set_gps(temp_gps, gps_sequence + 1);
gps_pending = false;
- temp_gps = null;
+ super.set_temp_gps();
}
public void set_config_data(AltosConfigData config_data) {
return values.iterator();
}
+ public void integrate(AltosTimeSeries integral) {
+ double y = 0.0;
+ double x = 0.0;
+ boolean start = true;
+
+ for (AltosTimeValue v : values) {
+ if (start) {
+ y = 0.0;
+ x = v.x;
+ start = false;
+ } else {
+ y += v.y * (v.x - x);
+ x = v.x;
+ }
+ integral.add(x, y);
+ }
+ }
+
+ public void differentiate(AltosTimeSeries diff) {
+ double y = 0.0;
+ double x = 0.0;
+ boolean start = true;
+
+ for (AltosTimeValue v: values) {
+ if (start) {
+ y = 0.0;
+ x = v.x;
+ start = false;
+ } else {
+ double dx = v.x - x;
+ double dy = v.y - y;
+
+ x = v.x;
+ y = v.y;
+ if (dx != 0)
+ diff.add(x, dy);
+ }
+ }
+ }
+
+ private int find_left(int i, double dt) {
+ int j;
+ double t = values.get(i).x - dt;
+ for (j = i; j > 0; j--) {
+ if (values.get(j).x < t)
+ break;
+ }
+ return j;
+
+ }
+
+ public void filter(AltosTimeSeries out, double width) {
+ for (int i = 0; i < values.size(); i++) {
+ }
+ }
+
public AltosTimeSeries(String label, AltosUnits units) {
this.label = label;
this.units = units;
AltosCSV.java \
AltosDebug.java \
AltosEepromNew.java \
+ AltosRecordSet.java \
AltosEepromRecord.java \
AltosEepromRecordFull.java \
AltosEepromRecordTiny.java \
AltosFile.java \
AltosFlash.java \
AltosFlashListener.java \
+ AltosFlightListener.java \
+ AltosFlightSeries.java \
AltosFlightReader.java \
AltosFlightStats.java \
AltosForce.java \
AltosLocation.java \
AltosLatitude.java \
AltosLongitude.java \
+ AltosRotationRate.java \
AltosPyro.java \
AltosWriter.java \
AltosQuaternion.java \