* General Public License for more details.
*/
-package org.altusmetrum.altoslib_11;
+package org.altusmetrum.altoslib_14;
import java.util.*;
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()];
}
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);
}
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";
+ public AltosTimeSeries vert_accel_series;
+
+ public static final String vert_accel_name = "Vertical Accel";
+
public void set_acceleration(double acceleration) {
if (acceleration == AltosLib.MISSING)
return;
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";
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 (altitude_series == null)
altitude_series = add_series(altitude_name, AltosConvert.height);
- if (cal_data.ground_pressure == AltosLib.MISSING)
- cal_data.set_ground_pressure(pa);
+ 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 && 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 (height_series == null) {
+ double ground_altitude = cal_data().ground_altitude;
+ if (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);
+ } else if (speed_series != null) {
+ height_series = add_series(height_name, AltosConvert.height);
+ speed_series.integrate(height_series);
+ }
}
- 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;
+ 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);
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);
+
+ 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);
+
+ AltosTimeSeries clip_series = make_series(speed_name, AltosConvert.speed);
+
+ temp_series.clip(clip_series, 0, Double.POSITIVE_INFINITY);
accel_speed_series = make_series(speed_name, AltosConvert.speed);
- temp_series.filter(accel_speed_series, 0.1);
+ clip_series.filter(accel_speed_series, 0.1);
}
if (alt_speed_series != null && accel_speed_series != null) {
}
}
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;
+ }
+ return new_speed_series;
+ }
+
+ public AltosTimeSeries orient_series;
+ public AltosTimeSeries azimuth_series;
+
+ public static final String orient_name = "Tilt Angle";
+ public static final String azimuth_name = "Azimuth Angle";
+
+ private void compute_orient() {
+
+ if (orient_series != null)
+ return;
+
+ if (accel_ground_across == AltosLib.MISSING)
+ return;
+
+ AltosCalData cal_data = cal_data();
+
+ if (cal_data.pad_orientation == AltosLib.MISSING)
+ return;
+
+ if (cal_data.accel_zero_across == AltosLib.MISSING)
+ return;
+
+ if (cal_data.gyro_zero_roll == AltosLib.MISSING)
+ return;
+
+ AltosRotation rotation = new AltosRotation(accel_ground_across,
+ accel_ground_through,
+ accel_ground_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());
+
+ azimuth_series = add_series(azimuth_name, AltosConvert.orient);
+ azimuth_series.add(ground_time, rotation.azimuth());
+
+ 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());
+ azimuth_series.add(time, rotation.azimuth());
+ }
+ prev_time = time;
}
- if (speed_series != null)
- add_series(speed_series);
}
public AltosTimeSeries kalman_height_series, kalman_speed_series, kalman_accel_series;
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;
public static final String gps_vdop_name = "GPS Vertical Dilution of Precision";
public static final String gps_hdop_name = "GPS Horizontal Dilution of Precision";
- public void set_gps(AltosGPS gps) {
+ public void set_gps(AltosGPS gps, boolean new_location, boolean new_sats) {
+ super.set_gps(gps, new_location, new_sats);
+ AltosCalData cal_data = cal_data();
if (gps_series == null)
gps_series = new ArrayList<AltosGPSTimeValue>();
gps_series.add(new AltosGPSTimeValue(time(), gps));
- if (sats_in_soln == null) {
- sats_in_soln = add_series(sats_in_soln_name, null);
- }
- sats_in_soln.add(time(), gps.nsat);
- if (gps.pdop != AltosLib.MISSING) {
- if (gps_pdop == null)
- gps_pdop = add_series(gps_pdop_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.alt != AltosLib.MISSING) {
- if (gps_altitude == null)
- gps_altitude = add_series(gps_altitude_name, AltosConvert.height);
- gps_altitude.add(time(), gps.alt);
+ if (new_location) {
+ if (sats_in_soln == null) {
+ sats_in_soln = add_series(sats_in_soln_name, null);
}
- 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);
+ sats_in_soln.add(time(), gps.nsat);
+ if (gps.pdop != AltosLib.MISSING) {
+ if (gps_pdop == null)
+ gps_pdop = add_series(gps_pdop_name, null);
+ gps_pdop.add(time(), gps.pdop);
}
- 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.hdop != AltosLib.MISSING) {
+ if (gps_hdop == null)
+ gps_hdop = add_series(gps_hdop_name, null);
+ gps_hdop.add(time(), gps.hdop);
}
- 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.vdop != AltosLib.MISSING) {
+ if (gps_vdop == null)
+ gps_vdop = add_series(gps_vdop_name, null);
+ gps_vdop.add(time(), gps.vdop);
}
- 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.locked) {
+ 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 (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_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 == 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_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)
- sats_in_view = add_series(sats_in_view_name, null);
- sats_in_view.add(time(), gps.cc_gps_sat.length);
+ if (new_sats) {
+ if (gps.cc_gps_sat != null) {
+ if (sats_in_view == null)
+ sats_in_view = add_series(sats_in_view_name, null);
+ sats_in_view.add(time(), gps.cc_gps_sat.length);
+ }
}
}
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";
+ public static final String mag_total_name = "Magnetic Field Strength";
+ public static final String compass_name = "Compass";
- public AltosTimeSeries mag_along, mag_across, mag_through;
+ public AltosTimeSeries mag_along, mag_across, mag_through, mag_total, compass;
public void set_accel(double along, double across, double through) {
if (accel_along == null) {
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) {
mag_along = add_series(mag_along_name, AltosConvert.magnetic_field);
mag_across = add_series(mag_across_name, AltosConvert.magnetic_field);
mag_through = add_series(mag_through_name, AltosConvert.magnetic_field);
+ mag_total = add_series(mag_total_name, AltosConvert.magnetic_field);
+ compass = add_series(compass_name, AltosConvert.orient);
}
mag_along.add(time(), along);
mag_across.add(time(), across);
mag_through.add(time(), through);
+ mag_total.add(time(), Math.sqrt(along * along + across * across + through *through));
+ compass.add(time(), Math.atan2(across, through) * 180 / Math.PI);
}
- public static final String orient_name = "Tilt Angle";
-
- public AltosTimeSeries orient_series;
-
public void set_orient(double orient) {
if (orient_series == null)
orient_series = add_series(orient_name, AltosConvert.orient);
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) {
public void set_companion(AltosCompanion companion) {
}
+ public static final String motor_pressure_name = "Motor Pressure";
+
+ public AltosTimeSeries motor_pressure_series;
+
+ public void set_motor_pressure(double motor_pressure) {
+ if (motor_pressure_series == null)
+ motor_pressure_series = add_series(motor_pressure_name, AltosConvert.pressure);
+ motor_pressure_series.add(time(), motor_pressure);
+ }
+
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();
}