X-Git-Url: https://git.gag.com/?p=fw%2Faltos;a=blobdiff_plain;f=altoslib%2FAltosFlightSeries.java;h=32bd6c5ef63f6aae98d0fef1fb0141f45efc7fcd;hp=6f4f7bb1e89c5960a5744df84ca1ba49cc7c273e;hb=eaf2ee0f498b519d64e1664a2b8c66c52ac1497c;hpb=fd738d47bbc46d36698350d5450abe1125d990a3;ds=sidebyside diff --git a/altoslib/AltosFlightSeries.java b/altoslib/AltosFlightSeries.java index 6f4f7bb1..32bd6c5e 100644 --- a/altoslib/AltosFlightSeries.java +++ b/altoslib/AltosFlightSeries.java @@ -12,7 +12,7 @@ * General Public License for more details. */ -package org.altusmetrum.altoslib_11; +package org.altusmetrum.altoslib_13; import java.util.*; @@ -20,6 +20,9 @@ public class AltosFlightSeries extends AltosDataListener { public ArrayList series = new ArrayList(); + public double speed_filter_width = 4.0; + public double accel_filter_width = 1.0; + public int[] indices() { int[] indices = new int[series.size()]; for (int i = 0; i < indices.length; i++) @@ -86,6 +89,14 @@ public class AltosFlightSeries extends AltosDataListener { return AltosLib.MISSING; } + public double value(String name, double time) { + for (AltosTimeSeries s : series) { + if (s.label.equals(name)) + return s.value(time); + } + return AltosLib.MISSING; + } + public double value_before(String name, double time) { for (AltosTimeSeries s : series) { if (s.label.equals(name)) @@ -107,6 +118,12 @@ public class AltosFlightSeries extends AltosDataListener { } public void add_series(AltosTimeSeries s) { + for (int e = 0; e < series.size(); e++) { + if (s.compareTo(series.get(e)) < 0){ + series.add(e, s); + return; + } + } series.add(s); } @@ -127,50 +144,97 @@ public class AltosFlightSeries extends AltosDataListener { return false; } - AltosTimeSeries state_series; + public 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, 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); } - AltosTimeSeries accel_series; + public AltosTimeSeries accel_series; + public boolean accel_computed; public static final String accel_name = "Accel"; + public AltosTimeSeries vert_accel_series; + + public static final String vert_accel_name = "Vertical Accel"; + public void set_acceleration(double acceleration) { - if (accel_series == null) { + if (acceleration == AltosLib.MISSING) + return; + if (accel_series == null) 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(accel_name, AltosConvert.accel); - speed_series.differentiate(temp_series); - accel_series = add_series(accel_name, AltosConvert.accel); - temp_series.filter(accel_series, 0.25); + 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) { } - AltosTimeSeries rssi_series; + 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"; - AltosTimeSeries status_series; + public AltosTimeSeries status_series; public static final String status_name = "Radio Status"; @@ -183,59 +247,101 @@ public class AltosFlightSeries extends AltosDataListener { status_series.add(time(), status); } - AltosTimeSeries pressure_series; + public AltosTimeSeries pressure_series; public static final String pressure_name = "Pressure"; - AltosTimeSeries altitude_series; + public AltosTimeSeries altitude_series; public static final String altitude_name = "Altitude"; - AltosTimeSeries height_series; + public AltosTimeSeries height_series; + + public double max_height = AltosLib.MISSING; + + public void set_min_pressure(double pa) { + double ground_altitude = cal_data().ground_altitude; + if (ground_altitude != AltosLib.MISSING) + max_height = AltosConvert.pressure_to_altitude(pa) - + ground_altitude; + } public static final String height_name = "Height"; public void set_pressure(double pa) { + if (pa == AltosLib.MISSING) + return; + if (pressure_series == null) pressure_series = add_series(pressure_name, AltosConvert.pressure); pressure_series.add(time(), pa); if (altitude_series == null) altitude_series = add_series(altitude_name, AltosConvert.height); + if (cal_data().ground_pressure == AltosLib.MISSING) + cal_data().set_ground_pressure(pa); + double altitude = AltosConvert.pressure_to_altitude(pa); altitude_series.add(time(), altitude); } private void compute_height() { - double ground_altitude = cal_data.ground_altitude; - if (height_series == null && ground_altitude != AltosLib.MISSING) { + double ground_altitude = cal_data().ground_altitude; + if (height_series == null && ground_altitude != AltosLib.MISSING && altitude_series != null) { height_series = add_series(height_name, AltosConvert.height); for (AltosTimeValue alt : altitude_series) height_series.add(alt.time, alt.value - ground_altitude); } + + if (gps_height == null && cal_data().gps_pad != null && cal_data().gps_pad.alt != AltosLib.MISSING && gps_altitude != null) { + double gps_ground_altitude = cal_data().gps_pad.alt; + gps_height = add_series(gps_height_name, AltosConvert.height); + for (AltosTimeValue gps_alt : gps_altitude) + gps_height.add(gps_alt.time, gps_alt.value - gps_ground_altitude); + } } - AltosTimeSeries speed_series; + public AltosTimeSeries speed_series; 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(speed_name, AltosConvert.speed); - altitude_series.differentiate(temp_series); + 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.filter(alt_speed_series, 10.0); + 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); + + for (AltosTimeValue a : accel_series) { + double orient = orient_series.value(a.time); + double a_abs = a.value + AltosConvert.gravity; + double v_a = a_abs * Math.cos(AltosConvert.degrees_to_radians(orient)) - AltosConvert.gravity; + + vert_accel_series.add(a.time, v_a); + } + } + AltosTimeSeries temp_series = make_series(speed_name, AltosConvert.speed); - accel_series.integrate(temp_series); + + if (vert_accel_series != null) + vert_accel_series.integrate(temp_series); + else + accel_series.integrate(temp_series); accel_speed_series = make_series(speed_name, AltosConvert.speed); temp_series.filter(accel_speed_series, 0.1); @@ -252,29 +358,71 @@ 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; } - AltosTimeSeries kalman_height_series, kalman_speed_series, kalman_accel_series; + public AltosTimeSeries orient_series; + + public static final String orient_name = "Tilt Angle"; + + private void compute_orient() { + + if (orient_series != null) + return; + + if (accel_ground_across == AltosLib.MISSING) + return; + + if (cal_data().pad_orientation == AltosLib.MISSING) + return; + + if (cal_data().accel_zero_across == AltosLib.MISSING) + return; + + AltosRotation 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); + double prev_time = ground_time; + + orient_series = add_series(orient_name, AltosConvert.orient); + orient_series.add(ground_time, rotation.tilt()); + + for (AltosTimeValue roll_v : gyro_roll) { + double time = roll_v.time; + double dt = time - prev_time; + + if (dt > 0) { + double roll = AltosConvert.degrees_to_radians(roll_v.value) * dt; + double pitch = AltosConvert.degrees_to_radians(gyro_pitch.value(time)) * dt; + double yaw = AltosConvert.degrees_to_radians(gyro_yaw.value(time)) * dt; + + rotation.rotate(pitch, yaw, roll); + orient_series.add(time, rotation.tilt()); + } + prev_time = time; + } + } + + public AltosTimeSeries kalman_height_series, kalman_speed_series, kalman_accel_series; public static final String kalman_height_name = "Kalman Height"; public static final String kalman_speed_name = "Kalman Speed"; @@ -291,7 +439,7 @@ public class AltosFlightSeries extends AltosDataListener { kalman_accel_series.add(time(), acceleration); } - AltosTimeSeries thrust_series; + public AltosTimeSeries thrust_series; public static final String thrust_name = "Thrust"; @@ -301,7 +449,7 @@ public class AltosFlightSeries extends AltosDataListener { thrust_series.add(time(), N); } - AltosTimeSeries temperature_series; + public AltosTimeSeries temperature_series; public static final String temperature_name = "Temperature"; @@ -311,7 +459,7 @@ public class AltosFlightSeries extends AltosDataListener { temperature_series.add(time(), deg_c); } - AltosTimeSeries battery_voltage_series; + public AltosTimeSeries battery_voltage_series; public static final String battery_voltage_name = "Battery Voltage"; @@ -323,7 +471,7 @@ public class AltosFlightSeries extends AltosDataListener { battery_voltage_series.add(time(), volts); } - AltosTimeSeries apogee_voltage_series; + public AltosTimeSeries apogee_voltage_series; public static final String apogee_voltage_name = "Apogee Voltage"; @@ -335,7 +483,7 @@ public class AltosFlightSeries extends AltosDataListener { apogee_voltage_series.add(time(), volts); } - AltosTimeSeries main_voltage_series; + public AltosTimeSeries main_voltage_series; public static final String main_voltage_name = "Main Voltage"; @@ -350,24 +498,35 @@ public class AltosFlightSeries extends AltosDataListener { public ArrayList 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; - } - - AltosTimeSeries sats_in_view; - AltosTimeSeries sats_in_soln; - AltosTimeSeries gps_altitude; - AltosTimeSeries gps_height; - AltosTimeSeries gps_ground_speed; - AltosTimeSeries gps_ascent_rate; - AltosTimeSeries gps_course; - AltosTimeSeries gps_speed; - AltosTimeSeries gps_pdop, gps_vdop, gps_hdop; + 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; + public AltosTimeSeries sats_in_soln; + public AltosTimeSeries gps_altitude; + public AltosTimeSeries gps_height; + public AltosTimeSeries gps_ground_speed; + public AltosTimeSeries gps_ascent_rate; + public AltosTimeSeries gps_course; + public AltosTimeSeries gps_speed; + public AltosTimeSeries gps_pdop, gps_vdop, gps_hdop; public static final String sats_in_view_name = "Satellites in view"; public static final String sats_in_soln_name = "Satellites in solution"; @@ -382,6 +541,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(); gps_series.add(new AltosGPSTimeValue(time(), gps)); @@ -391,38 +551,47 @@ public class AltosFlightSeries extends AltosDataListener { } sats_in_soln.add(time(), gps.nsat); if (gps.pdop != AltosLib.MISSING) { - if (gps_pdop == null) { + if (gps_pdop == null) gps_pdop = add_series(gps_pdop_name, null); - gps_hdop = add_series(gps_hdop_name, null); - gps_vdop = add_series(gps_vdop_name, null); - } gps_pdop.add(time(), gps.pdop); + } + if (gps.hdop != AltosLib.MISSING) { + if (gps_hdop == null) + gps_hdop = add_series(gps_hdop_name, null); gps_hdop.add(time(), gps.hdop); + } + if (gps.vdop != AltosLib.MISSING) { + if (gps_vdop == null) + gps_vdop = add_series(gps_vdop_name, null); gps_vdop.add(time(), gps.vdop); } if (gps.locked) { - if (gps_altitude == null) { - gps_altitude = add_series(gps_altitude_name, AltosConvert.height); - gps_height = add_series(gps_height_name, AltosConvert.height); - gps_ground_speed = add_series(gps_ground_speed_name, AltosConvert.speed); - gps_ascent_rate = add_series(gps_ascent_rate_name, AltosConvert.speed); - gps_course = add_series(gps_course_name, null); - gps_speed = add_series(gps_speed_name, null); - } if (gps.alt != AltosLib.MISSING) { + if (gps_altitude == null) + gps_altitude = add_series(gps_altitude_name, AltosConvert.height); gps_altitude.add(time(), gps.alt); - if (cal_data.gps_pad != null) - gps_height.add(time(), gps.alt - cal_data.gps_pad.alt); } - if (gps.ground_speed != AltosLib.MISSING) + if (gps.ground_speed != AltosLib.MISSING) { + if (gps_ground_speed == null) + gps_ground_speed = add_series(gps_ground_speed_name, AltosConvert.speed); gps_ground_speed.add(time(), gps.ground_speed); - if (gps.climb_rate != AltosLib.MISSING) + } + if (gps.climb_rate != AltosLib.MISSING) { + if (gps_ascent_rate == null) + gps_ascent_rate = add_series(gps_ascent_rate_name, AltosConvert.speed); gps_ascent_rate.add(time(), gps.climb_rate); - if (gps.course != AltosLib.MISSING) + } + if (gps.course != AltosLib.MISSING) { + if (gps_course == null) + gps_course = add_series(gps_course_name, null); gps_course.add(time(), gps.course); - if (gps.ground_speed != AltosLib.MISSING && gps.climb_rate != AltosLib.MISSING) + } + if (gps.ground_speed != AltosLib.MISSING && gps.climb_rate != AltosLib.MISSING) { + if (gps_speed == null) + gps_speed = add_series(gps_speed_name, null); gps_speed.add(time(), Math.sqrt(gps.ground_speed * gps.ground_speed + gps.climb_rate * gps.climb_rate)); + } } if (gps.cc_gps_sat != null) { if (sats_in_view == null) @@ -435,19 +604,19 @@ public class AltosFlightSeries extends AltosDataListener { public static final String accel_across_name = "Accel Across"; public static final String accel_through_name = "Accel Through"; - AltosTimeSeries accel_along, accel_across, accel_through; + public AltosTimeSeries accel_along, accel_across, accel_through; public static final String gyro_roll_name = "Roll Rate"; public static final String gyro_pitch_name = "Pitch Rate"; public static final String gyro_yaw_name = "Yaw Rate"; - AltosTimeSeries gyro_roll, gyro_pitch, gyro_yaw; + public AltosTimeSeries gyro_roll, gyro_pitch, gyro_yaw; public static final String mag_along_name = "Magnetic Field Along"; public static final String mag_across_name = "Magnetic Field Across"; public static final String mag_through_name = "Magnetic Field Through"; - AltosTimeSeries mag_along, mag_across, mag_through; + public AltosTimeSeries mag_along, mag_across, mag_through; public void set_accel(double along, double across, double through) { if (accel_along == null) { @@ -460,7 +629,17 @@ public class AltosFlightSeries extends AltosDataListener { accel_through.add(time(), through); } + private double accel_ground_along = AltosLib.MISSING; + private double accel_ground_across = AltosLib.MISSING; + private double accel_ground_through = AltosLib.MISSING; + + private double ground_time; + public void set_accel_ground(double along, double across, double through) { + accel_ground_along = along; + accel_ground_across = across; + accel_ground_through = through; + ground_time = time(); } public void set_gyro(double roll, double pitch, double yaw) { @@ -485,10 +664,6 @@ public class AltosFlightSeries extends AltosDataListener { mag_through.add(time(), through); } - public static final String orient_name = "Tilt Angle"; - - AltosTimeSeries orient_series; - public void set_orient(double orient) { if (orient_series == null) orient_series = add_series(orient_name, AltosConvert.orient); @@ -497,7 +672,7 @@ public class AltosFlightSeries extends AltosDataListener { public static final String pyro_voltage_name = "Pyro Voltage"; - AltosTimeSeries pyro_voltage; + public AltosTimeSeries pyro_voltage; public void set_pyro_voltage(double volts) { if (pyro_voltage == null) @@ -523,12 +698,12 @@ public class AltosFlightSeries extends AltosDataListener { return igniter_voltage_names[channel]; } - AltosTimeSeries[] igniter_voltage; + public AltosTimeSeries[] igniter_voltage; 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) { @@ -545,7 +720,7 @@ public class AltosFlightSeries extends AltosDataListener { public static final String pyro_fired_name = "Pyro Channel State"; - AltosTimeSeries pyro_fired_series; + public AltosTimeSeries pyro_fired_series; int last_pyro_mask; @@ -565,8 +740,19 @@ public class AltosFlightSeries extends AltosDataListener { } public void finish() { - compute_speed(); - compute_accel(); + compute_orient(); + 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(); }