X-Git-Url: https://git.gag.com/?p=fw%2Faltos;a=blobdiff_plain;f=altoslib%2FAltosState.java;h=7a64f8a188182704c5aa6fbd01e17fb627eef5e5;hp=e874a498b0ed066aa02387afcab22fd54fe88b92;hb=e64b1bc108bd75bcd6271631e48abde84af4631f;hpb=4de934c283a839fcbb246b36aa15362f3cf8629c diff --git a/altoslib/AltosState.java b/altoslib/AltosState.java index e874a498..7a64f8a1 100644 --- a/altoslib/AltosState.java +++ b/altoslib/AltosState.java @@ -3,7 +3,8 @@ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of @@ -19,10 +20,9 @@ * Track flight state from telemetry or eeprom data stream */ -package org.altusmetrum.altoslib_1; +package org.altusmetrum.altoslib_13; -public class AltosState implements Cloneable { - public AltosRecord record; +public class AltosState extends AltosDataListener { public static final int set_position = 1; public static final int set_gps = 2; @@ -30,41 +30,40 @@ public class AltosState implements Cloneable { public int set; - static final double ascent_filter_len = 0.1; - static final double descent_filter_len = 2.0; + static final double filter_len = 2.0; + static final double ascent_filter_len = 0.5; + static final double descent_filter_len = 5.0; /* derived data */ public long received_time; - public double time; - public double prev_time; - public double time_change; - public int tick; - private int prev_tick; - public int boost_tick; + public int rssi; + public int status; class AltosValue { - private double value; - private double prev_value; + double value; + double prev_value; private double max_value; private double set_time; private double prev_set_time; - private double max_rate = 1000.0; + + boolean can_max() { return true; } void set(double new_value, double time) { - if (new_value != AltosRecord.MISSING) { + if (new_value != AltosLib.MISSING) { value = new_value; - if (max_value == AltosRecord.MISSING || value > max_value) { + if (can_max() && (max_value == AltosLib.MISSING || value > max_value)) max_value = value; - } set_time = time; } } void set_filtered(double new_value, double time) { - if (prev_value != AltosRecord.MISSING) - new_value = (prev_value * 15.0 + new_value) / 16.0; + if (prev_value != AltosLib.MISSING) { + double f = 1/Math.exp((time - prev_set_time) / filter_len); + new_value = f * new_value + (1-f) * prev_value; + } set(new_value, time); } @@ -81,25 +80,25 @@ public class AltosState implements Cloneable { } double change() { - if (value != AltosRecord.MISSING && prev_value != AltosRecord.MISSING) + if (value != AltosLib.MISSING && prev_value != AltosLib.MISSING) return value - prev_value; - return AltosRecord.MISSING; + return AltosLib.MISSING; } double rate() { double c = change(); double t = set_time - prev_set_time; - if (c != AltosRecord.MISSING && t != 0) + if (c != AltosLib.MISSING && t != 0) return c / t; - return AltosRecord.MISSING; + return AltosLib.MISSING; } double integrate() { - if (value == AltosRecord.MISSING) - return AltosRecord.MISSING; - if (prev_value == AltosRecord.MISSING) - return AltosRecord.MISSING; + if (value == AltosLib.MISSING) + return AltosLib.MISSING; + if (prev_value == AltosLib.MISSING) + return AltosLib.MISSING; return (value + prev_value) / 2 * (set_time - prev_set_time); } @@ -110,14 +109,14 @@ public class AltosState implements Cloneable { void set_derivative(AltosValue in) { double n = in.rate(); - - if (n == AltosRecord.MISSING) + + if (n == AltosLib.MISSING) return; double p = prev_value; double pt = prev_set_time; - if (p == AltosRecord.MISSING) { + if (p == AltosLib.MISSING) { p = 0; pt = in.time() - 0.01; } @@ -125,13 +124,15 @@ public class AltosState implements Cloneable { /* Clip changes to reduce noise */ double ddt = in.time() - pt; double ddv = (n - p) / ddt; - + + final double max = 100000; + /* 100gs */ - if (Math.abs(ddv) > 1000) { + if (Math.abs(ddv) > max) { if (n > p) - n = p + ddt * 1000; + n = p + ddt * max; else - n = p - ddt * 1000; + n = p - ddt * max; } double filter_len; @@ -150,9 +151,9 @@ public class AltosState implements Cloneable { void set_integral(AltosValue in) { double change = in.integrate(); - if (change != AltosRecord.MISSING) { + if (change != AltosLib.MISSING) { double prev = prev_value; - if (prev == AltosRecord.MISSING) + if (prev == AltosLib.MISSING) prev = 0; set(prev + change, in.time()); } @@ -166,58 +167,79 @@ public class AltosState implements Cloneable { max_value = old.max_value; } + void finish_update() { + prev_value = value; + prev_set_time = set_time; + } + AltosValue() { - value = AltosRecord.MISSING; - prev_value = AltosRecord.MISSING; - max_value = AltosRecord.MISSING; + value = AltosLib.MISSING; + prev_value = AltosLib.MISSING; + max_value = AltosLib.MISSING; } + } class AltosCValue { - AltosValue measured; - AltosValue computed; + + class AltosIValue extends AltosValue { + boolean can_max() { + return c_can_max(); + } + + AltosIValue() { + super(); + } + }; + + public AltosIValue measured; + public AltosIValue computed; + + boolean can_max() { return true; } + + boolean c_can_max() { return can_max(); } double value() { double v = measured.value(); - if (v != AltosRecord.MISSING) + if (v != AltosLib.MISSING) return v; return computed.value(); } boolean is_measured() { - return measured.value() != AltosRecord.MISSING; + return measured.value() != AltosLib.MISSING; } double max() { double m = measured.max(); - if (m != AltosRecord.MISSING) + if (m != AltosLib.MISSING) return m; return computed.max(); } double prev_value() { - if (measured.value != AltosRecord.MISSING && measured.prev_value != AltosRecord.MISSING) + if (measured.value != AltosLib.MISSING && measured.prev_value != AltosLib.MISSING) return measured.prev_value; return computed.prev_value; } AltosValue altos_value() { - if (measured.value() != AltosRecord.MISSING) + if (measured.value() != AltosLib.MISSING) return measured; return computed; } double change() { double c = measured.change(); - if (c == AltosRecord.MISSING) + if (c == AltosLib.MISSING) c = computed.change(); return c; } double rate() { double r = measured.rate(); - if (r == AltosRecord.MISSING) + if (r == AltosLib.MISSING) r = computed.rate(); return r; } @@ -241,40 +263,34 @@ public class AltosState implements Cloneable { void set_integral(AltosValue in) { computed.set_integral(in); } - + void set_integral(AltosCValue in) { set_integral(in.altos_value()); } - + void copy(AltosCValue old) { measured.copy(old.measured); computed.copy(old.computed); } - AltosCValue() { - measured = new AltosValue(); - computed = new AltosValue(); + void finish_update() { + measured.finish_update(); + computed.finish_update(); + } + + public AltosCValue() { + measured = new AltosIValue(); + computed = new AltosIValue(); } } - 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 int device_type; - public int config_major; - public int config_minor; - public int apogee_delay; - public int main_deploy; - public int flight_log_max; private double pressure_to_altitude(double p) { - if (p == AltosRecord.MISSING) - return AltosRecord.MISSING; + if (p == AltosLib.MISSING) + return AltosLib.MISSING; return AltosConvert.pressure_to_altitude(p); } @@ -288,20 +304,53 @@ public class AltosState implements Cloneable { ground_altitude.set_measured(a, time); } + class AltosGpsGroundAltitude extends AltosValue { + void set(double a, double t) { + super.set(a, t); + pad_alt = value(); + gps_altitude.set_gps_height(); + } + + void set_filtered(double a, double t) { + super.set_filtered(a, t); + pad_alt = value(); + gps_altitude.set_gps_height(); + } + + AltosGpsGroundAltitude() { + super(); + } + } + + private AltosGpsGroundAltitude gps_ground_altitude; + + public double gps_ground_altitude() { + return gps_ground_altitude.value(); + } + + public void set_gps_ground_altitude(double a) { + gps_ground_altitude.set(a, time); + } + class AltosGroundPressure extends AltosCValue { void set_filtered(double p, double time) { computed.set_filtered(p, time); - ground_altitude.set_computed(pressure_to_altitude(computed.value()), time); + if (!is_measured()) + ground_altitude.set_computed(pressure_to_altitude(computed.value()), time); } void set_measured(double p, double time) { super.set_measured(p, time); ground_altitude.set_computed(pressure_to_altitude(p), time); } + + AltosGroundPressure () { + super(); + } } private AltosGroundPressure ground_pressure; - + public double ground_pressure() { return ground_pressure.value(); } @@ -328,38 +377,118 @@ public class AltosState implements Cloneable { set_speed(measured); set |= set_position; } + + AltosAltitude() { + super(); + } } private AltosAltitude altitude; + class AltosGpsAltitude extends AltosValue { + + private void set_gps_height() { + double a = value(); + double g = gps_ground_altitude.value(); + + if (a != AltosLib.MISSING && g != AltosLib.MISSING) + gps_height = a - g; + else + gps_height = AltosLib.MISSING; + } + + void set(double a, double t) { + super.set(a, t); + set_gps_height(); + } + + AltosGpsAltitude() { + super(); + } + } + + private AltosGpsAltitude gps_altitude; + + private AltosValue gps_ground_speed; + private AltosValue gps_ascent_rate; + private AltosValue gps_course; + private AltosValue gps_speed; + public double altitude() { double a = altitude.value(); - if (a != AltosRecord.MISSING) + if (a != AltosLib.MISSING) return a; - if (gps != null) - return gps.alt; - return AltosRecord.MISSING; + return gps_altitude.value(); } public double max_altitude() { double a = altitude.max(); - if (a != AltosRecord.MISSING) + if (a != AltosLib.MISSING) return a; - return AltosRecord.MISSING; + return gps_altitude.max(); } public void set_altitude(double new_altitude) { + double old_altitude = altitude.value(); + if (old_altitude != AltosLib.MISSING) { + while (old_altitude - new_altitude > 32000) + new_altitude += 65536.0; + } altitude.set_measured(new_altitude, time); } + public double gps_altitude() { + return gps_altitude.value(); + } + + public double max_gps_altitude() { + return gps_altitude.max(); + } + + public void set_gps_altitude(double new_gps_altitude) { + gps_altitude.set(new_gps_altitude, time); + } + + public double gps_ground_speed() { + return gps_ground_speed.value(); + } + + public double max_gps_ground_speed() { + return gps_ground_speed.max(); + } + + public double gps_ascent_rate() { + return gps_ascent_rate.value(); + } + + public double max_gps_ascent_rate() { + return gps_ascent_rate.max(); + } + + public double gps_course() { + return gps_course.value(); + } + + public double gps_speed() { + return gps_speed.value(); + } + + public double max_gps_speed() { + return gps_speed.max(); + } + 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); } + + AltosPressure() { + super(); + } } private AltosPressure pressure; @@ -372,32 +501,65 @@ public class AltosState implements Cloneable { pressure.set(p, time); } - public double height() { - double k = kalman_height.value(); - if (k != AltosRecord.MISSING) - return k; + public void set_thrust(double N) { + } + public double baro_height() { double a = altitude(); double g = ground_altitude(); - if (a != AltosRecord.MISSING && g != AltosRecord.MISSING) + if (a != AltosLib.MISSING && g != AltosLib.MISSING) return a - g; - return AltosRecord.MISSING; + return AltosLib.MISSING; + } + + public double height() { + double k = kalman_height.value(); + if (k != AltosLib.MISSING) + return k; + + double b = baro_height(); + if (b != AltosLib.MISSING) + return b; + + return gps_height(); } public double max_height() { double k = kalman_height.max(); - if (k != AltosRecord.MISSING) + if (k != AltosLib.MISSING) return k; double a = altitude.max(); double g = ground_altitude(); - if (a != AltosRecord.MISSING && g != AltosRecord.MISSING) + if (a != AltosLib.MISSING && g != AltosLib.MISSING) + return a - g; + return max_gps_height(); + } + + public double gps_height() { + double a = gps_altitude(); + double g = gps_ground_altitude(); + + if (a != AltosLib.MISSING && g != AltosLib.MISSING) return a - g; - return AltosRecord.MISSING; + return AltosLib.MISSING; + } + + public double max_gps_height() { + double a = gps_altitude.max(); + double g = gps_ground_altitude(); + + if (a != AltosLib.MISSING && g != AltosLib.MISSING) + return a - g; + return AltosLib.MISSING; } class AltosSpeed extends AltosCValue { - + + boolean can_max() { + return state() < AltosLib.ao_flight_fast || state() == AltosLib.ao_flight_stateless; + } + void set_accel() { acceleration.set_derivative(this); } @@ -416,24 +578,55 @@ public class AltosState implements Cloneable { super.set_measured(new_value, time); set_accel(); } + + AltosSpeed() { + super(); + } } private AltosSpeed speed; public double speed() { - return speed.value(); + double v = kalman_speed.value(); + if (v != AltosLib.MISSING) + return v; + v = speed.value(); + if (v != AltosLib.MISSING) + return v; + v = gps_speed(); + if (v != AltosLib.MISSING) + return v; + return AltosLib.MISSING; } public double max_speed() { - return speed.max(); + double v = kalman_speed.max(); + if (v != AltosLib.MISSING) + return v; + v = speed.max(); + if (v != AltosLib.MISSING) + return v; + v = max_gps_speed(); + if (v != AltosLib.MISSING) + return v; + return AltosLib.MISSING; } class AltosAccel extends AltosCValue { + + boolean can_max() { + return state() < AltosLib.ao_flight_fast || state() == AltosLib.ao_flight_stateless; + } + void set_measured(double a, double time) { super.set_measured(a, time); if (ascent) speed.set_integral(this.measured); } + + AltosAccel() { + super(); + } } AltosAccel acceleration; @@ -446,9 +639,28 @@ public class AltosState implements Cloneable { return acceleration.max(); } + public AltosCValue orient; + + public void set_orient(double new_orient) { + orient.set_measured(new_orient, time); + } + + public double orient() { + return orient.value(); + } + + public double max_orient() { + return orient.max(); + } + public AltosValue kalman_height, kalman_speed, kalman_acceleration; public void set_kalman(double height, double speed, double acceleration) { + double old_height = kalman_height.value(); + if (old_height != AltosLib.MISSING) { + while (old_height - height > 32000) + height += 65536; + } kalman_height.set(height, time); kalman_speed.set(speed, time); kalman_acceleration.set(acceleration, time); @@ -460,16 +672,10 @@ public class AltosState implements Cloneable { public double apogee_voltage; public double main_voltage; - public double ignitor_voltage[]; + public double igniter_voltage[]; public AltosGPS gps; - public AltosGPS temp_gps; - public boolean temp_gps_clear_sats_pending; public boolean gps_pending; - public int gps_sequence; - - public AltosIMU imu; - public AltosMag mag; public static final int MIN_PAD_SAMPLES = 10; @@ -481,6 +687,7 @@ public class AltosState implements Cloneable { public AltosGreatCircle from_pad; public double elevation; /* from pad */ + public double distance; /* distance along ground */ public double range; /* total distance */ public double gps_height; @@ -490,20 +697,11 @@ public class AltosState implements Cloneable { public int speak_tick; public double speak_altitude; - public String callsign; - public String firmware_version; - - public double accel_plus_g; - public double accel_minus_g; - public double accel; public double ground_accel; - public double ground_accel_avg; - public int log_format; + public AltosCompanion companion; - public AltosMs5607 baro; - - public AltosRecordCompanion companion; + public int pyro_fired; public void set_npad(int npad) { this.npad = npad; @@ -514,29 +712,15 @@ public class AltosState implements Cloneable { } public void init() { - record = null; + super.init(); set = 0; received_time = System.currentTimeMillis(); - time = AltosRecord.MISSING; - time_change = AltosRecord.MISSING; - prev_time = AltosRecord.MISSING; - tick = AltosRecord.MISSING; - prev_tick = AltosRecord.MISSING; - boost_tick = AltosRecord.MISSING; - state = AltosLib.ao_flight_invalid; - flight = AltosRecord.MISSING; landed = false; boost = false; - rssi = AltosRecord.MISSING; + rssi = AltosLib.MISSING; status = 0; - device_type = AltosRecord.MISSING; - config_major = AltosRecord.MISSING; - config_minor = AltosRecord.MISSING; - apogee_delay = AltosRecord.MISSING; - main_deploy = AltosRecord.MISSING; - flight_log_max = AltosRecord.MISSING; ground_altitude = new AltosCValue(); ground_pressure = new AltosGroundPressure(); @@ -544,507 +728,336 @@ public class AltosState implements Cloneable { pressure = new AltosPressure(); speed = new AltosSpeed(); acceleration = new AltosAccel(); + orient = new AltosCValue(); - temperature = AltosRecord.MISSING; - battery_voltage = AltosRecord.MISSING; - pyro_voltage = AltosRecord.MISSING; - apogee_voltage = AltosRecord.MISSING; - main_voltage = AltosRecord.MISSING; - ignitor_voltage = null; + temperature = AltosLib.MISSING; + battery_voltage = AltosLib.MISSING; + pyro_voltage = AltosLib.MISSING; + apogee_voltage = AltosLib.MISSING; + main_voltage = AltosLib.MISSING; + igniter_voltage = null; kalman_height = new AltosValue(); kalman_speed = new AltosValue(); kalman_acceleration = new AltosValue(); gps = null; - temp_gps = null; - temp_gps_clear_sats_pending = false; - gps_sequence = 0; gps_pending = false; - imu = null; - mag = null; + last_imu_time = AltosLib.MISSING; + rotation = null; + + accel_ground_along = AltosLib.MISSING; + accel_ground_across = AltosLib.MISSING; + accel_ground_through = AltosLib.MISSING; + + accel_along = AltosLib.MISSING; + accel_across = AltosLib.MISSING; + accel_through = AltosLib.MISSING; + + gyro_roll = AltosLib.MISSING; + gyro_pitch = AltosLib.MISSING; + gyro_yaw = AltosLib.MISSING; + + mag_along = AltosLib.MISSING; + mag_across = AltosLib.MISSING; + mag_through = AltosLib.MISSING; set_npad(0); ngps = 0; from_pad = null; - elevation = AltosRecord.MISSING; - range = AltosRecord.MISSING; - gps_height = AltosRecord.MISSING; - - pad_lat = AltosRecord.MISSING; - pad_lon = AltosRecord.MISSING; - pad_alt = AltosRecord.MISSING; - - speak_tick = AltosRecord.MISSING; - speak_altitude = AltosRecord.MISSING; + elevation = AltosLib.MISSING; + distance = AltosLib.MISSING; + range = AltosLib.MISSING; + gps_height = AltosLib.MISSING; - callsign = null; + pad_lat = AltosLib.MISSING; + pad_lon = AltosLib.MISSING; + pad_alt = AltosLib.MISSING; - accel_plus_g = AltosRecord.MISSING; - accel_minus_g = AltosRecord.MISSING; - accel = AltosRecord.MISSING; + gps_altitude = new AltosGpsAltitude(); + gps_ground_altitude = new AltosGpsGroundAltitude(); + gps_ground_speed = new AltosValue(); + gps_speed = new AltosValue(); + gps_ascent_rate = new AltosValue(); + gps_course = new AltosValue(); - ground_accel = AltosRecord.MISSING; - ground_accel_avg = AltosRecord.MISSING; + speak_tick = AltosLib.MISSING; + speak_altitude = AltosLib.MISSING; - log_format = AltosRecord.MISSING; - serial = AltosRecord.MISSING; + ground_accel = AltosLib.MISSING; - baro = null; companion = null; - } - - void copy(AltosState old) { - record = null; + pyro_fired = 0; + } - if (old == null) { - init(); - return; - } + void finish_update() { + ground_altitude.finish_update(); + altitude.finish_update(); + pressure.finish_update(); + speed.finish_update(); + acceleration.finish_update(); + orient.finish_update(); - received_time = old.received_time; - time = old.time; - time_change = 0; - tick = old.tick; - prev_tick = old.tick; - boost_tick = old.boost_tick; - - state = old.state; - flight = old.flight; - landed = old.landed; - ascent = old.ascent; - boost = old.boost; - rssi = old.rssi; - status = old.status; - device_type = old.device_type; - config_major = old.config_major; - config_minor = old.config_minor; - apogee_delay = old.apogee_delay; - main_deploy = old.main_deploy; - flight_log_max = old.flight_log_max; - - set = 0; + kalman_height.finish_update(); + kalman_speed.finish_update(); + kalman_acceleration.finish_update(); + } - ground_altitude.copy(old.ground_altitude); - altitude.copy(old.altitude); - pressure.copy(old.pressure); - speed.copy(old.speed); - acceleration.copy(old.acceleration); - - battery_voltage = old.battery_voltage; - pyro_voltage = old.pyro_voltage; - temperature = old.temperature; - apogee_voltage = old.apogee_voltage; - main_voltage = old.main_voltage; - ignitor_voltage = old.ignitor_voltage; - - kalman_height.copy(old.kalman_height); - kalman_speed.copy(old.kalman_speed); - kalman_acceleration.copy(old.kalman_acceleration); - - if (old.gps != null) - gps = old.gps.clone(); - else - gps = null; - if (old.temp_gps != null) - temp_gps = old.temp_gps.clone(); - else - temp_gps = null; - temp_gps_clear_sats_pending = old.temp_gps_clear_sats_pending; - gps_sequence = old.gps_sequence; - gps_pending = old.gps_pending; - - if (old.imu != null) - imu = old.imu.clone(); - else - imu = null; - - if (old.mag != null) - mag = old.mag.clone(); - else - mag = null; - - npad = old.npad; - gps_waiting = old.gps_waiting; - gps_ready = old.gps_ready; - ngps = old.ngps; - - if (old.from_pad != null) - from_pad = old.from_pad.clone(); - else - from_pad = null; - - elevation = old.elevation; - range = old.range; - - gps_height = old.gps_height; - pad_lat = old.pad_lat; - pad_lon = old.pad_lon; - pad_alt = old.pad_alt; - - speak_tick = old.speak_tick; - speak_altitude = old.speak_altitude; - - callsign = old.callsign; - - accel_plus_g = old.accel_plus_g; - accel_minus_g = old.accel_minus_g; - accel = old.accel; - ground_accel = old.ground_accel; - ground_accel_avg = old.ground_accel_avg; - - log_format = old.log_format; - serial = old.serial; - - baro = old.baro; - companion = old.companion; - } - void update_time() { } void update_gps() { - elevation = 0; - range = -1; - gps_height = 0; + elevation = AltosLib.MISSING; + distance = AltosLib.MISSING; + range = AltosLib.MISSING; 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) { + if (state() == AltosLib.ao_flight_pad || state() == AltosLib.ao_flight_stateless) { set_npad(npad+1); - if (pad_lat != AltosRecord.MISSING) { + 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; - pad_alt = (pad_alt * 31 + gps.alt) / 32; + gps_ground_altitude.set_filtered(gps.alt, time); } } - if (pad_lat == AltosRecord.MISSING) { + if (pad_lat == AltosLib.MISSING) { pad_lat = gps.lat; pad_lon = gps.lon; - pad_alt = gps.alt; + gps_ground_altitude.set(gps.alt, time); } + gps_altitude.set(gps.alt, time); + if (gps.climb_rate != AltosLib.MISSING) + gps_ascent_rate.set(gps.climb_rate, time); + if (gps.ground_speed != AltosLib.MISSING) + gps_ground_speed.set(gps.ground_speed, time); + if (gps.climb_rate != AltosLib.MISSING && gps.ground_speed != AltosLib.MISSING) + gps_speed.set(Math.sqrt(gps.ground_speed * gps.ground_speed + + gps.climb_rate * gps.climb_rate), time); + if (gps.course != AltosLib.MISSING) + gps_course.set(gps.course, time); + } else if (state() == AltosLib.ao_flight_pad || state() == AltosLib.ao_flight_stateless) { + set_npad(0); } if (gps.lat != 0 && gps.lon != 0 && - pad_lat != AltosRecord.MISSING && - pad_lon != AltosRecord.MISSING) + pad_lat != AltosLib.MISSING && + pad_lon != AltosLib.MISSING) { double h = height(); - if (h == AltosRecord.MISSING) + if (h == AltosLib.MISSING) h = 0; from_pad = new AltosGreatCircle(pad_lat, pad_lon, 0, gps.lat, gps.lon, h); elevation = from_pad.elevation; + distance = from_pad.distance; range = from_pad.range; - gps_height = gps.alt - pad_alt; } } - public void set_tick(int new_tick) { - if (new_tick != AltosRecord.MISSING) { - if (prev_tick != AltosRecord.MISSING) { - while (new_tick < prev_tick - 32767) { - new_tick += 65536; - } - } - tick = new_tick; - time = tick / 100.0; - } + public String state_name() { + return AltosLib.state_name(state()); } - public void set_boost_tick(int boost_tick) { - if (boost_tick != AltosRecord.MISSING) - this.boost_tick = boost_tick; + public void set_state(int state) { + super.set_state(state); + ascent = (AltosLib.ao_flight_boost <= state() && + state() <= AltosLib.ao_flight_coast); + boost = (AltosLib.ao_flight_boost == state()); } - public String state_name() { - return AltosLib.state_name(state); + public int rssi() { + if (rssi == AltosLib.MISSING) + return 0; + return rssi; } - 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 void set_rssi(int rssi, int status) { + if (rssi != AltosLib.MISSING) { + this.rssi = rssi; + this.status = status; } - } - public void set_device_type(int device_type) { - this.device_type = device_type; + public void set_received_time(long ms) { + received_time = ms; } - public void set_config(int major, int minor, int apogee_delay, int main_deploy, int flight_log_max) { - config_major = major; - config_minor = minor; - this.apogee_delay = apogee_delay; - this.main_deploy = main_deploy; - this.flight_log_max = flight_log_max; + public void set_gps(AltosGPS gps) { + super.set_gps(gps); + if (gps != null) { + this.gps = gps; + update_gps(); + set |= set_gps; + } } - public void set_callsign(String callsign) { - this.callsign = callsign; + public AltosRotation rotation; + + public double accel_ground_along, accel_ground_across, accel_ground_through; + + void update_pad_rotation() { + if (cal_data().pad_orientation != AltosLib.MISSING && accel_ground_along != AltosLib.MISSING) { + rotation = new AltosRotation(AltosIMU.convert_accel(accel_ground_across - cal_data().accel_zero_across), + AltosIMU.convert_accel(accel_ground_through - cal_data().accel_zero_through), + AltosIMU.convert_accel(accel_ground_along - cal_data().accel_zero_along), + cal_data().pad_orientation); + orient.set_computed(rotation.tilt(), time); + } } - public void set_firmware_version(String version) { - firmware_version = version; + public void set_accel_ground(double ground_along, double ground_across, double ground_through) { + accel_ground_along = ground_along; + accel_ground_across = ground_across; + accel_ground_through = ground_through; + update_pad_rotation(); } - public void set_flight(int flight) { + public double last_imu_time; - /* When the flight changes, reset the state */ - if (flight != AltosRecord.MISSING) { - if (this.flight != AltosRecord.MISSING && - this.flight != flight) { - init(); - } - this.flight = flight; - } - } + private void update_orient() { + if (last_imu_time != AltosLib.MISSING) { + double t = time - last_imu_time; - 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(); + if (t > 0 && gyro_pitch != AltosLib.MISSING && rotation != null) { + double pitch = AltosConvert.degrees_to_radians(gyro_pitch) * t; + double yaw = AltosConvert.degrees_to_radians(gyro_yaw) * t; + double roll = AltosConvert.degrees_to_radians(gyro_roll) * t; + + rotation.rotate(pitch, yaw, roll); + orient.set_computed(rotation.tilt(), time); } - this.serial = serial; } + last_imu_time = time; } - public int rssi() { - if (rssi == AltosRecord.MISSING) - return 0; - return rssi; - } + private double gyro_roll, gyro_pitch, gyro_yaw; - public void set_rssi(int rssi, int status) { - if (rssi != AltosRecord.MISSING) { - this.rssi = rssi; - this.status = status; - } + public void set_gyro(double roll, double pitch, double yaw) { + gyro_roll = roll; + gyro_pitch = pitch; + gyro_yaw = yaw; + update_orient(); } - public void set_received_time(long ms) { - received_time = ms; + private double accel_along, accel_across, accel_through; + + public void set_accel(double along, double across, double through) { + accel_along = along; + accel_across = across; + accel_through = through; + update_orient(); } - public void set_gps(AltosGPS gps, int sequence) { - if (gps != null) { - this.gps = gps.clone(); - gps_sequence = sequence; - update_gps(); - set |= set_gps; - } + public double accel_along() { + return accel_along; } - public void make_baro() { - if (baro == null) - baro = new AltosMs5607(); + public double accel_across() { + return accel_across; } - public void set_ms5607(int pres, int temp) { - if (baro != null) { - baro.set(pres, temp); + public double accel_through() { + return accel_through; + } - set_pressure(baro.pa); - set_temperature(baro.cc / 100.0); - } + public double gyro_roll() { + return gyro_roll; } - public void make_companion (int nchannels) { - if (companion == null) - companion = new AltosRecordCompanion(nchannels); + public double gyro_pitch() { + return gyro_pitch; } - public void set_companion(AltosRecordCompanion companion) { - this.companion = companion; + public double gyro_yaw() { + return gyro_yaw; } - void update_accel() { - double ground = ground_accel; + private double mag_along, mag_across, mag_through; - if (ground == AltosRecord.MISSING) - ground = ground_accel_avg; - if (accel == AltosRecord.MISSING) - return; - if (ground == AltosRecord.MISSING) - return; - if (accel_plus_g == AltosRecord.MISSING) - return; - if (accel_minus_g == AltosRecord.MISSING) - return; + public void set_mag(double along, double across, double through) { + mag_along = along; + mag_across = across; + mag_through = through; + } - double counts_per_g = (accel_minus_g - accel_plus_g) / 2.0; - double counts_per_mss = counts_per_g / 9.80665; - acceleration.set_computed((ground - accel) / counts_per_mss, time); + public double mag_along() { + return mag_along; } - 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; - this.accel_minus_g = accel_minus_g; - update_accel(); - } + public double mag_across() { + return mag_across; } - public void set_ground_accel(double ground_accel) { - if (ground_accel != AltosRecord.MISSING) { - this.ground_accel = ground_accel; - update_accel(); - } + public double mag_through() { + return mag_through; } - public void set_accel(double accel) { - if (accel != AltosRecord.MISSING) { - this.accel = accel; - if (state == AltosLib.ao_flight_pad) { - if (ground_accel_avg == AltosRecord.MISSING) - ground_accel_avg = accel; - else - ground_accel_avg = (ground_accel_avg * 7 + accel) / 8; - } + public void set_companion(AltosCompanion companion) { + this.companion = companion; + } + + public void set_acceleration(double acceleration) { + if (acceleration != AltosLib.MISSING) { + this.acceleration.set_measured(acceleration, time); + set |= set_data; } - update_accel(); } public void set_temperature(double temperature) { - if (temperature != AltosRecord.MISSING) { + if (temperature != AltosLib.MISSING) { this.temperature = temperature; set |= set_data; } } public void set_battery_voltage(double battery_voltage) { - if (battery_voltage != AltosRecord.MISSING) { + if (battery_voltage != AltosLib.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 != AltosLib.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 != AltosLib.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 != AltosLib.MISSING) { this.main_voltage = main_voltage; set |= set_data; } } - public void set_ignitor_voltage(double[] voltage) { - this.ignitor_voltage = voltage; + public void set_igniter_voltage(double[] voltage) { + this.igniter_voltage = voltage; } - 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 void set_pyro_fired(int fired) { + this.pyro_fired = fired; } - public AltosGPS make_temp_gps(boolean sats) { - if (temp_gps == null) { - temp_gps = new AltosGPS(gps); - } - gps_pending = true; - if (!sats) - temp_gps_clear_sats_pending = true; - else if (temp_gps_clear_sats_pending) { - temp_gps.cc_gps_sat = null; - temp_gps_clear_sats_pending = false; - } - return temp_gps; - } - - public void set_temp_gps() { - set_gps(temp_gps, gps_sequence + 1); - gps_pending = false; - temp_gps = null; - } - - public AltosState clone() { - AltosState s = new AltosState(); - s.copy(this); - return s; - } - - - public void init (AltosRecord cur, AltosState prev_state) { - - System.out.printf ("init\n"); - if (cur == null) - cur = new AltosRecord(); - - record = cur; - - /* Discard previous state if it was for a different board */ - if (prev_state != null && prev_state.serial != cur.serial) - prev_state = null; - - copy(prev_state); - - set_ground_altitude(cur.ground_altitude()); - set_altitude(cur.altitude()); - - set_kalman(cur.kalman_height, cur.kalman_speed, cur.kalman_acceleration); - - received_time = System.currentTimeMillis(); - - set_temperature(cur.temperature()); - set_apogee_voltage(cur.drogue_voltage()); - set_main_voltage(cur.main_voltage()); - set_battery_voltage(cur.battery_voltage()); - - set_pressure(cur.pressure()); - - set_tick(cur.tick); - set_state(cur.state); - - set_accel_g (cur.accel_minus_g, cur.accel_plus_g); - set_ground_accel(cur.ground_accel); - set_accel (cur.accel); - - if (cur.gps_sequence != gps_sequence) - set_gps(cur.gps, cur.gps_sequence); - - } - - public AltosState(AltosRecord cur) { - init(cur, null); - } - - public AltosState (AltosRecord cur, AltosState prev) { - init(cur, prev); + public AltosState() { + init(); } - - public AltosState () { + public AltosState (AltosCalData cal_data) { + super(cal_data); init(); } }