TeleStern/altoslib/AltosFlightStats.java

280 lines
8.8 KiB
Java

/*
* Copyright © 2011 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.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
package org.altusmetrum.altoslib_14;
import java.io.*;
public class AltosFlightStats {
public double max_height;
public double max_gps_height;
public double max_speed;
public double max_acceleration;
public double[] state_speed = new double[AltosLib.ao_flight_invalid + 1];
public double[] state_enter_speed = new double[AltosLib.ao_flight_invalid + 1];
public double[] state_enter_height = new double[AltosLib.ao_flight_invalid + 1];
public double[] state_enter_gps_height = new double[AltosLib.ao_flight_invalid + 1];
public double[] state_accel = new double[AltosLib.ao_flight_invalid + 1];
public double[] state_time = new double[AltosLib.ao_flight_invalid + 1];
public String product;
public String firmware_version;
public int serial;
public int flight;
public int year, month, day;
public int hour, minute, second;
public double boost_time;
public double landed_time;
public double lat, lon;
public double pad_lat, pad_lon;
public boolean has_flight_data;
public boolean has_gps;
public boolean has_gps_sats;
public boolean has_gps_detail;
public boolean has_flight_adc;
public boolean has_battery;
public boolean has_rssi;
public boolean has_imu;
public boolean has_mag;
public boolean has_orient;
public int num_igniter;
double landed_time(AltosFlightSeries series) {
double landed_state_time = AltosLib.MISSING;
double prev_state_time = AltosLib.MISSING;
if (series.state_series != null) {
for (AltosTimeValue state : series.state_series) {
if (state.value == AltosLib.ao_flight_landed) {
landed_state_time = state.time;
break;
} else {
prev_state_time = state.time;
}
}
}
if (landed_state_time == AltosLib.MISSING && series.height_series != null)
landed_state_time = series.height_series.get(series.height_series.size()-1).time;
double landed_height = AltosLib.MISSING;
if (series.height_series != null) {
for (AltosTimeValue height : series.height_series) {
landed_height = height.value;
if (height.time >= landed_state_time)
break;
}
}
if (landed_height == AltosLib.MISSING)
return AltosLib.MISSING;
boolean above = true;
double landed_time = AltosLib.MISSING;
if (series.height_series != null) {
for (AltosTimeValue height : series.height_series) {
if (height.value > landed_height + 10) {
above = true;
} else {
if (above && Math.abs(height.value - landed_height) < 2) {
above = false;
landed_time = height.time;
}
}
}
}
if (landed_time == AltosLib.MISSING || (prev_state_time != AltosLib.MISSING && landed_time < prev_state_time))
landed_time = landed_state_time;
return landed_time;
}
double boost_time(AltosFlightSeries series) {
double boost_time = AltosLib.MISSING;
double boost_state_time = AltosLib.MISSING;
if (series.state_series != null) {
for (AltosTimeValue state : series.state_series) {
if (state.value >= AltosLib.ao_flight_boost && state.value <= AltosLib.ao_flight_landed) {
boost_state_time = state.time;
break;
}
}
}
if (series.accel_series != null) {
for (AltosTimeValue accel : series.accel_series) {
if (accel.value < 1)
boost_time = accel.time;
if (boost_state_time != AltosLib.MISSING && accel.time >= boost_state_time)
break;
}
}
if (boost_time == AltosLib.MISSING)
boost_time = boost_state_time;
return boost_time;
}
private void add_times(AltosFlightSeries series, int state, double start_time, double end_time) {
double delta_time = end_time - start_time;
if (0 <= state && state <= AltosLib.ao_flight_invalid && delta_time > 0) {
if (state_enter_speed[state] == AltosLib.MISSING)
state_enter_speed[state] = series.speed_series.value(start_time);
if (state_enter_height[state] == AltosLib.MISSING)
state_enter_height[state] = series.height_series.value(start_time);
if (state_enter_gps_height[state] == AltosLib.MISSING)
if (series.gps_height != null)
state_enter_gps_height[state] = series.gps_height.value(start_time);
speeds[state].value += series.speed_series.average(start_time, end_time) * delta_time;
speeds[state].time += delta_time;
accels[state].value += series.accel_series.average(start_time, end_time) * delta_time;
accels[state].time += delta_time;
state_time[state] += delta_time;
if (state == AltosLib.ao_flight_boost) {
AltosTimeValue tv_speed = series.speed_series.max(start_time, end_time);
if (tv_speed != null && (max_speed == AltosLib.MISSING || tv_speed.value > max_speed))
max_speed = tv_speed.value;
AltosTimeValue tv_accel = series.accel_series.max(start_time, end_time);
if (tv_accel != null && (max_acceleration == AltosLib.MISSING || tv_accel.value > max_acceleration))
max_acceleration = tv_accel.value;
}
}
}
AltosTimeValue[] speeds = new AltosTimeValue[AltosLib.ao_flight_invalid + 1];
AltosTimeValue[] accels = new AltosTimeValue[AltosLib.ao_flight_invalid + 1];
public AltosFlightStats(AltosFlightSeries series) {
AltosCalData cal_data = series.cal_data();
series.finish();
boost_time = boost_time(series);
landed_time = landed_time(series);
if (series.state_series != null){
boolean fixed_boost = false;
boolean fixed_landed = false;
for (AltosTimeValue state : series.state_series) {
if ((int) state.value == AltosLib.ao_flight_boost)
if (boost_time != AltosLib.MISSING && !fixed_boost) {
state.time = boost_time;
fixed_boost = true;
}
if ((int) state.value == AltosLib.ao_flight_landed)
if (landed_time != AltosLib.MISSING && !fixed_landed) {
state.time = landed_time;
fixed_landed = true;
}
}
}
year = month = day = AltosLib.MISSING;
hour = minute = second = AltosLib.MISSING;
serial = flight = AltosLib.MISSING;
lat = lon = AltosLib.MISSING;
has_flight_data = false;
has_gps = false;
has_gps_sats = false;
has_flight_adc = false;
has_battery = false;
has_rssi = false;
has_imu = false;
has_mag = false;
has_orient = false;
for (int s = 0; s < AltosLib.ao_flight_invalid + 1; s++) {
state_speed[s] = AltosLib.MISSING;
state_enter_speed[s] = AltosLib.MISSING;
state_accel[s] = AltosLib.MISSING;
state_time[s] = 0;
speeds[s] = new AltosTimeValue(0, 0);
accels[s] = new AltosTimeValue(0, 0);
}
max_speed = AltosLib.MISSING;
max_acceleration = AltosLib.MISSING;
if (series.state_series != null) {
AltosTimeValue prev = null;
for (AltosTimeValue state : series.state_series) {
if (prev != null)
add_times(series, (int) prev.value, prev.time, state.time);
prev = state;
}
if (prev != null) {
AltosTimeValue last_accel = series.accel_series.last();
if (last_accel != null)
add_times(series, (int) prev.value, prev.time, last_accel.time);
}
}
for (int s = 0; s <= AltosLib.ao_flight_invalid; s++) {
if (speeds[s].time > 0)
state_speed[s] = speeds[s].value / speeds[s].time;
if (accels[s].time > 0)
state_accel[s] = accels[s].value / accels[s].time;
}
product = cal_data.product;
firmware_version = cal_data.firmware_version;
serial = cal_data.serial;
flight = cal_data.flight;
has_battery = series.battery_voltage_series != null;
has_flight_adc = series.main_voltage_series != null;
has_rssi = series.rssi_series != null;
has_flight_data = series.pressure_series != null;
AltosGPS gps = series.cal_data().gps_pad;
if (gps != null) {
year = gps.year;
month = gps.month;
day = gps.day;
hour = gps.hour;
minute = gps.minute;
second = gps.second;
has_gps = true;
lat = pad_lat = gps.lat;
lon = pad_lon = gps.lon;
if (series.gps_series != null) {
for (AltosGPSTimeValue gtv : series.gps_series) {
gps = gtv.gps;
if (gps.locked && gps.nsat >= 4) {
lat = gps.lat;
lon = gps.lon;
}
}
}
}
max_height = series.max_height;
if (max_height == AltosLib.MISSING && series.height_series != null)
max_height = series.height_series.max().value;
max_gps_height = AltosLib.MISSING;
if (series.gps_height != null) {
AltosTimeValue tv = series.gps_height.max();
if (tv != null)
max_gps_height = tv.value;
}
}
}