diff options
| author | Keith Packard <keithp@keithp.com> | 2017-05-25 17:24:14 -0700 | 
|---|---|---|
| committer | Keith Packard <keithp@keithp.com> | 2017-05-25 17:24:14 -0700 | 
| commit | f26cfe417c6977cf1e7e75a4f050e25f64d41859 (patch) | |
| tree | 2f19ca9c93c3246b3eeadafee250f9dd3ee222d6 | |
| parent | 7600116a191b3ac252a0f716d200d0e0b3500987 (diff) | |
altoslib: Do data analysis on raw values rather than AltosState
Use AltosFlightSeries instead of a sequence of AltosState records when
processing saved data. This provides a better way of doing filtering
and plotting.
Signed-off-by: Keith Packard <keithp@keithp.com>
65 files changed, 2070 insertions, 1375 deletions
| diff --git a/altoslib/AltosCSV.java b/altoslib/AltosCSV.java index b5199456..0cfe4c94 100644 --- a/altoslib/AltosCSV.java +++ b/altoslib/AltosCSV.java @@ -27,16 +27,17 @@ public class AltosCSV implements AltosWriter {  	boolean			header_written;  	boolean			seen_boost;  	int			boost_tick; -	LinkedList<AltosState>	pad_states; -	AltosState		state; -	static boolean		has_basic; -	static boolean		has_battery; -	static boolean		has_flight_state; -	static boolean		has_advanced; -	static boolean		has_gps; -	static boolean		has_gps_sat; -	static boolean		has_companion; +	boolean			has_basic; +	boolean			has_battery; +	boolean			has_flight_state; +	boolean			has_advanced; +	boolean			has_gps; +	boolean			has_gps_sat; +	boolean			has_companion; + +	AltosFlightSeries	series; +	int[]			indices;  	static final int ALTOS_CSV_VERSION = 5; @@ -117,63 +118,97 @@ public class AltosCSV implements AltosWriter {  		out.printf("version,serial,flight,call,time,clock,rssi,lqi");  	} -	void write_general(AltosState state) { +	double time() { +		return series.time(indices); +	} + +	int rssi() { +		return (int) series.value(AltosFlightSeries.rssi_name, indices); +	} + +	int status() { +		return (int) series.value(AltosFlightSeries.status_name, indices); +	} + +	void write_general() { +		double time = time();  		out.printf("%s, %d, %d, %s, %8.2f, %8.2f, %4d, %3d", -			   ALTOS_CSV_VERSION, state.serial, state.flight, state.callsign, -			   (double) state.time_since_boost(), (double) state.tick / 100.0, -			   state.rssi, -			   state.status & 0x7f); +			   ALTOS_CSV_VERSION, series.cal_data.serial, +			   series.cal_data.flight, series.cal_data.callsign, +			   time, time, +			   rssi(), status() & 0x7f);  	}  	void write_flight_header() {  		out.printf("state,state_name");  	} -	void write_flight(AltosState state) { -		out.printf("%d,%8s", state.state(), state.state_name()); +	int state() { +		return (int) series.value(AltosFlightSeries.state_name, indices); +	} + +	void write_flight() { +		int state = state(); +		out.printf("%d,%8s", state, AltosLib.state_name(state));  	}  	void write_basic_header() {  		out.printf("acceleration,pressure,altitude,height,accel_speed,baro_speed,temperature,drogue_voltage,main_voltage");  	} -	void write_basic(AltosState state) { +	double acceleration() { return series.value(AltosFlightSeries.accel_name, indices); } +	double pressure() { return series.value(AltosFlightSeries.pressure_name, indices); } +	double altitude() { return series.value(AltosFlightSeries.altitude_name, indices); } +	double height() { return series.value(AltosFlightSeries.height_name, indices); } +	double speed() { return series.value(AltosFlightSeries.speed_name, indices); } +	double temperature() { return series.value(AltosFlightSeries.temperature_name, indices); } +	double apogee_voltage() { return series.value(AltosFlightSeries.apogee_voltage_name, indices); } +	double main_voltage() { return series.value(AltosFlightSeries.main_voltage_name, indices); } + +	void write_basic() {  		out.printf("%8.2f,%10.2f,%8.2f,%8.2f,%8.2f,%8.2f,%5.1f,%5.2f,%5.2f", -			   state.acceleration(), -			   state.pressure(), -			   state.altitude(), -			   state.height(), -			   state.speed(), -			   state.speed(), -			   state.temperature, -			   state.apogee_voltage, -			   state.main_voltage); +			   acceleration(), +			   pressure(), +			   altitude(), +			   height(), +			   speed(), +			   speed(), +			   temperature(), +			   apogee_voltage(), +			   main_voltage());  	}  	void write_battery_header() {  		out.printf("battery_voltage");  	} -	void write_battery(AltosState state) { -		out.printf("%5.2f", state.battery_voltage); +	double battery_voltage() { return series.value(AltosFlightSeries.battery_voltage_name, indices); } + +	void write_battery() { +		out.printf("%5.2f", battery_voltage());  	}  	void write_advanced_header() {  		out.printf("accel_x,accel_y,accel_z,gyro_x,gyro_y,gyro_z,mag_x,mag_y,mag_z");  	} -	void write_advanced(AltosState state) { +	void write_advanced() { +/*  		out.printf("%7.2f,%7.2f,%7.2f,%7.2f,%7.2f,%7.2f,%7.2f,%7.2f,%7.2f",  			   state.accel_along(), state.accel_across(), state.accel_through(),  			   state.gyro_roll(), state.gyro_pitch(), state.gyro_yaw(),  			   state.mag_along(), state.mag_across(), state.mag_through()); +*/  	}  	void write_gps_header() { +/*  		out.printf("connected,locked,nsat,latitude,longitude,altitude,year,month,day,hour,minute,second,pad_dist,pad_range,pad_az,pad_el,pdop,hdop,vdop"); +*/  	} -	void write_gps(AltosState state) { +	void write_gps() { +/*  		AltosGPS	gps = state.gps;  		if (gps == null)  			gps = new AltosGPS(); @@ -202,6 +237,7 @@ public class AltosCSV implements AltosWriter {  			   gps.pdop,  			   gps.hdop,  			   gps.vdop); +*/  	}  	void write_gps_sat_header() { @@ -212,7 +248,8 @@ public class AltosCSV implements AltosWriter {  		}  	} -	void write_gps_sat(AltosState state) { +	void write_gps_sat() { +/*  		AltosGPS	gps = state.gps;  		for(int i = 1; i <= 32; i++) {  			int	c_n0 = 0; @@ -227,6 +264,7 @@ public class AltosCSV implements AltosWriter {  			if (i != 32)  				out.printf(",");  		} +*/  	}  	void write_companion_header() { @@ -235,7 +273,8 @@ public class AltosCSV implements AltosWriter {  			out.printf(",companion_%02d", i);  	} -	void write_companion(AltosState state) { +	void write_companion() { +/*  		AltosCompanion companion = state.companion;  		int	channels_written = 0; @@ -252,6 +291,7 @@ public class AltosCSV implements AltosWriter {  		}  		for (; channels_written < 12; channels_written++)  			out.printf(",0"); +*/  	}  	void write_header() { @@ -287,63 +327,47 @@ public class AltosCSV implements AltosWriter {  		out.printf ("\n");  	} -	void write_one(AltosState state) { -		write_general(state); +	void write_one() { +		write_general();  		if (has_flight_state) {  			out.printf(","); -			write_flight(state); +			write_flight();  		}  		if (has_basic) {  			out.printf(","); -			write_basic(state); +			write_basic();  		}  		if (has_battery) {  			out.printf(","); -			write_battery(state); +			write_battery();  		}  		if (has_advanced) {  			out.printf(","); -			write_advanced(state); +			write_advanced();  		}  		if (has_gps) {  			out.printf(","); -			write_gps(state); +			write_gps();  		}  		if (has_gps_sat) {  			out.printf(","); -			write_gps_sat(state); +			write_gps_sat();  		}  		if (has_companion) {  			out.printf(","); -			write_companion(state); +			write_companion();  		}  		out.printf ("\n");  	} -	private void flush_pad() { -		while (!pad_states.isEmpty()) { -			write_one (pad_states.remove()); -		} -	} - -	private void write(AltosState state) { -		if (state.state() == AltosLib.ao_flight_startup) +	private void write() { +		if (state() == AltosLib.ao_flight_startup)  			return;  		if (!header_written) {  			write_header();  			header_written = true;  		} -		if (!seen_boost) { -			if (state.state() >= AltosLib.ao_flight_boost) { -				seen_boost = true; -				boost_tick = state.tick; -				flush_pad(); -			} -		} -		if (seen_boost) -			write_one(state); -		else -			pad_states.add(state); +		write_one();  	}  	private PrintStream out() { @@ -351,15 +375,15 @@ public class AltosCSV implements AltosWriter {  	}  	public void close() { -		if (!pad_states.isEmpty()) { -			boost_tick = pad_states.element().tick; -			flush_pad(); -		}  		out.close();  	} -	public void write(AltosStateIterable states) { -		states.write_comments(out()); +	public void write(AltosFlightSeries series) { +//		series.write_comments(out()); + +		this.series = series; + +		series.fill_in();  		has_flight_state = false;  		has_basic = false; @@ -368,15 +392,16 @@ public class AltosCSV implements AltosWriter {  		has_gps = false;  		has_gps_sat = false;  		has_companion = false; -		for (AltosState state : states) { -			if (state.state() != AltosLib.ao_flight_stateless && state.state() != AltosLib.ao_flight_invalid && state.state() != AltosLib.ao_flight_startup) -				has_flight_state = true; -			if (state.acceleration() != AltosLib.MISSING || state.pressure() != AltosLib.MISSING) -				has_basic = true; -			if (state.battery_voltage != AltosLib.MISSING) -				has_battery = true; -			if (state.accel_across() != AltosLib.MISSING) -				has_advanced = true; + +		if (series.has_series(AltosFlightSeries.state_name)) +			has_flight_state = true; +		if (series.has_series(AltosFlightSeries.accel_name) || series.has_series(AltosFlightSeries.pressure_name)) +			has_basic = true; +		if (series.has_series(AltosFlightSeries.battery_voltage_name)) +			has_battery = true; +		if (series.has_series(AltosFlightSeries.accel_across_name)) +			has_advanced = true; +/*  			if (state.gps != null) {  				has_gps = true;  				if (state.gps.cc_gps_sat != null) @@ -385,14 +410,19 @@ public class AltosCSV implements AltosWriter {  			if (state.companion != null)  				has_companion = true;  		} -		for (AltosState state : states) -			write(state); +*/ +		indices = series.indices(); + +		for (;;) { +			write(); +			if (!series.step_indices(indices)) +				break; +		}  	}  	public AltosCSV(PrintStream in_out, File in_name) {  		name = in_name;  		out = in_out; -		pad_states = new LinkedList<AltosState>();  	}  	public AltosCSV(File in_name) throws FileNotFoundException { diff --git a/altoslib/AltosCalData.java b/altoslib/AltosCalData.java new file mode 100644 index 00000000..58d34abe --- /dev/null +++ b/altoslib/AltosCalData.java @@ -0,0 +1,348 @@ +/* + * 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; + +/* + * Calibration and other data needed to construct 'real' values from various data + * sources. + */ + +public class AltosCalData { +	public int		flight = AltosLib.MISSING; + +	public void set_flight(int flight) { +		if (flight != AltosLib.MISSING) +			this.flight = flight; +	} + +	public String		callsign = null; + +	public void set_callsign(String callsign) { +		if (callsign != null) +			this.callsign = callsign; +	} + +	public String		firmware_version = null; + +	public void set_firmware_version(String firmware_version) { +		if (firmware_version != null) +			this.firmware_version = firmware_version; +	} + +	public String		product = null; + +	public void set_product(String product) { +		if (product != null) +			this.product = product; +	} + +	public int		serial = AltosLib.MISSING; + +	public void set_serial(int serial) { +		if (serial != AltosLib.MISSING) +			this.serial = serial; +	} + +	public int		receiver_serial = AltosLib.MISSING; + +	public void set_receiver_serial(int receiver_serial) { +		if (receiver_serial != AltosLib.MISSING) +			this.receiver_serial = receiver_serial; +	} + +	public int		device_type = AltosLib.MISSING; + +	public void set_device_type(int device_type) { +		if (device_type != AltosLib.MISSING) +			this.device_type = device_type; +	} + +	public int		config_major = AltosLib.MISSING; +	public int		config_minor = AltosLib.MISSING; +	public int		flight_log_max = AltosLib.MISSING; + +	public void set_config(int major, int minor, int log_max) { +		if (major != AltosLib.MISSING) +			config_major = major; +		if (minor != AltosLib.MISSING) +			config_minor = minor; +		if (log_max != AltosLib.MISSING) +			flight_log_max = log_max; +	} + +	public double		apogee_delay = AltosLib.MISSING; +	public double		main_deploy = AltosLib.MISSING; + +	public void set_flight_params(double apogee_delay, double main_deploy) { +		if (apogee_delay != AltosLib.MISSING) +			this.apogee_delay = apogee_delay; +		if (main_deploy != AltosLib.MISSING) +			this.main_deploy = main_deploy; +	} + +	public double		accel_plus_g = AltosLib.MISSING; +	public double		accel_minus_g = AltosLib.MISSING; +	public double		ground_accel = AltosLib.MISSING; + +	public void set_accel_plus_minus(double plus, double minus) { +		if (plus != AltosLib.MISSING && minus != AltosLib.MISSING) { +			accel_plus_g = plus; +			accel_minus_g = minus; +		} +	} + +	public void set_ground_accel(double ground_accel) { +		if (ground_accel != AltosLib.MISSING) +			this.ground_accel = ground_accel; +	} + +	/* Raw acceleration value */ +	public double		accel = AltosLib.MISSING; + +	public void set_accel(double accel) { +		this.accel = accel; +	} + +	public boolean mma655x_inverted = false; + +	public void set_mma655x_inverted(boolean inverted) { +		mma655x_inverted = inverted; +	} + +	public int pad_orientation = AltosLib.MISSING; + +	public void set_pad_orientation(int orientation) { +		if (orientation != AltosLib.MISSING) +			pad_orientation = orientation; +	} + +	/* Compute acceleration */ +	public double acceleration(double sensor) { +		return AltosConvert.acceleration_from_sensor(sensor, accel_plus_g, accel_minus_g, ground_accel); +	} + +	public AltosMs5607	ms5607 = null; + +	public void set_ms5607(AltosMs5607 ms5607) { +		this.ms5607 = ms5607; +	} + +	public double		ground_pressure = AltosLib.MISSING; +	public double		ground_altitude = AltosLib.MISSING; + +	public void set_ground_pressure(double ground_pressure) { +		if (ground_pressure != AltosLib.MISSING) { +			this.ground_pressure = ground_pressure; +			this.ground_altitude = AltosConvert.pressure_to_altitude(ground_pressure); +		} +	} + +	public void set_ground_altitude(double ground_altitude) { +		if (ground_altitude != AltosLib.MISSING) +			this.ground_altitude = ground_altitude; +	} + +	/* Compute pressure */ + +	public AltosPresTemp pressure_ms5607(int raw_pres, int raw_temp) { +		if (ms5607 == null) +			return new AltosPresTemp(AltosLib.MISSING, AltosLib.MISSING); +		return ms5607.pres_temp(raw_pres, raw_temp); +	} + +	public int		tick = AltosLib.MISSING; +	private int		prev_tick = AltosLib.MISSING; + +	public void set_tick(int tick) { +		if (tick != AltosLib.MISSING) { +			if (prev_tick != AltosLib.MISSING) { +				while (tick < prev_tick - 1000) { +					tick += 65536; +				} +			} +			this.tick = tick; +		} +	} + +	public int		boost_tick = AltosLib.MISSING; + +	public void set_boost_tick() { +		boost_tick = tick; +	} + +	public double time() { +		if (tick == AltosLib.MISSING) +			return AltosLib.MISSING; +		if (boost_tick == AltosLib.MISSING) +			return AltosLib.MISSING; +		return (tick - boost_tick) / 100.0; +	} + +	public double boost_time() { +		if (boost_tick == AltosLib.MISSING) +			return AltosLib.MISSING; +		return boost_tick / 100.0; +	} + +	public int		state = AltosLib.MISSING; + +	public void set_state(int state) { +		if (state >= AltosLib.ao_flight_boost && boost_tick == AltosLib.MISSING) +			set_boost_tick(); +		this.state = state; +	} + +	public double		gps_ground_altitude = AltosLib.MISSING; + +	public void set_gps_altitude(double altitude) { +		if ((state != AltosLib.MISSING && state < AltosLib.ao_flight_boost) || +		    gps_ground_altitude == AltosLib.MISSING) +			gps_ground_altitude = altitude; +	} + +	/* +	 * While receiving GPS data, we construct a temporary GPS state +	 * object and then deliver the result atomically to the listener +	 */ +	AltosGPS		temp_gps = null; +	int			temp_gps_sat_tick = AltosLib.MISSING; + +	public AltosGPS temp_gps() { +		return temp_gps; +	} + +	public void reset_temp_gps() { +		if (temp_gps != null) { +			if (temp_gps.locked && temp_gps.nsat >= 4) +				set_gps_altitude(temp_gps.alt); +		} +		temp_gps = null; +	} + +	public boolean gps_pending() { +		return temp_gps != null; +	} + +	public AltosGPS make_temp_gps(int tick, 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 double	accel_zero_along, accel_zero_across, accel_zero_through; + +	public void set_accel_zero(double zero_along, double zero_across, double zero_through) { +		if (zero_along != AltosLib.MISSING) { +			accel_zero_along = zero_along; +			accel_zero_across = zero_across; +			accel_zero_through = zero_through; +		} +	} + +	public double accel_along(double counts) { +		return AltosIMU.convert_accel(counts - accel_zero_along); +	} + +	public double accel_across(double counts) { +		return AltosIMU.convert_accel(counts - accel_zero_across); +	} + +	public double accel_through(double counts) { +		return AltosIMU.convert_accel(counts - accel_zero_through); +	} + +	public double	gyro_zero_roll,	gyro_zero_pitch, gyro_zero_yaw; + +	public void set_gyro_zero(double roll, double pitch, double yaw) { +		if (roll != AltosLib.MISSING) { +			gyro_zero_roll = roll; +			gyro_zero_pitch = pitch; +			gyro_zero_yaw = yaw; +		} +	} + +	public double gyro_roll(double counts) { +		if (gyro_zero_roll == AltosLib.MISSING || counts == AltosLib.MISSING) +			return AltosLib.MISSING; +		return AltosIMU.convert_gyro(counts - gyro_zero_roll); +	} + +	public double gyro_pitch(double counts) { +		if (gyro_zero_pitch == AltosLib.MISSING || counts == AltosLib.MISSING) +			return AltosLib.MISSING; +		return AltosIMU.convert_gyro(counts - gyro_zero_pitch); +	} + +	public double gyro_yaw(double counts) { +		if (gyro_zero_yaw == AltosLib.MISSING || counts == AltosLib.MISSING) +			return AltosLib.MISSING; +		return AltosIMU.convert_gyro(counts - gyro_zero_yaw); +	} + +	private double gyro_zero_overflow(double first) { +		double v = first / 128.0; +		if (v < 0) +			v = Math.ceil(v); +		else +			v = Math.floor(v); +		return v * 128.0; +	} + +	public void check_imu_wrap(double roll, double pitch, double yaw) { +		gyro_zero_roll += gyro_zero_overflow(roll); +		gyro_zero_pitch += gyro_zero_overflow(pitch); +		gyro_zero_yaw += gyro_zero_overflow(yaw); +	} + +	public double mag_along(double along) { +		if (along == AltosLib.MISSING) +			return AltosLib.MISSING; +		return AltosMag.convert_gauss(along); +	} + +	public double mag_across(double across) { +		if (across == AltosLib.MISSING) +			return AltosLib.MISSING; +		return AltosMag.convert_gauss(across); +	} + +	public double mag_through(double through) { +		if (through == AltosLib.MISSING) +			return AltosLib.MISSING; +		return AltosMag.convert_gauss(through); +	} + +	public AltosCalData() { +	} + +	public AltosCalData(AltosConfigData config_data) { +		set_serial(config_data.serial); +		set_flight(config_data.flight); +		set_callsign(config_data.callsign); +		set_accel_plus_minus(config_data.accel_cal_plus, config_data.accel_cal_minus); +		set_ms5607(config_data.ms5607); +		try { +			set_mma655x_inverted(config_data.mma655x_inverted()); +		} catch (AltosUnknownProduct up) { +		} +		set_pad_orientation(config_data.pad_orientation); +	} +} diff --git a/altoslib/AltosConfigData.java b/altoslib/AltosConfigData.java index 05fc2031..1972ca0f 100644 --- a/altoslib/AltosConfigData.java +++ b/altoslib/AltosConfigData.java @@ -22,7 +22,7 @@ import java.util.*;  import java.text.*;  import java.util.concurrent.*; -public class AltosConfigData implements Iterable<String> { +public class AltosConfigData {  	/* Version information */  	public String	manufacturer; @@ -34,9 +34,6 @@ public class AltosConfigData implements Iterable<String> {  	public String	version;  	public int	altitude_32; -	/* Strings returned */ -	public LinkedList<String>	__lines; -  	/* Config information */  	/* HAS_FLIGHT*/  	public int	main_deploy; @@ -96,14 +93,13 @@ public class AltosConfigData implements Iterable<String> {  	public int	accel_zero_along, accel_zero_across, accel_zero_through;  	/* ms5607 data */ -	public int	ms5607_reserved; -	public int	ms5607_sens; -	public int	ms5607_off; -	public int	ms5607_tcs; -	public int	ms5607_tco; -	public int	ms5607_tref; -	public int	ms5607_tempsens; -	public int	ms5607_crc; +	AltosMs5607	ms5607; + +	public AltosMs5607 ms5607() { +		if (ms5607 == null) +			ms5607 = new AltosMs5607(); +		return ms5607; +	}  	public static String get_string(String line, String label) throws  ParseException {  		if (line.startsWith(label)) { @@ -142,10 +138,6 @@ public class AltosConfigData implements Iterable<String> {  		throw new ParseException("mismatch", 0);  	} -	public Iterator<String> iterator() { -		return __lines.iterator(); -	} -  	public int log_space() {  		if (log_space > 0)  			return log_space; @@ -237,8 +229,6 @@ public class AltosConfigData implements Iterable<String> {  	}  	public void reset() { -		__lines = new LinkedList<String>(); -  		manufacturer = null;  		product = null;  		serial = AltosLib.MISSING; @@ -293,7 +283,6 @@ public class AltosConfigData implements Iterable<String> {  	}  	public void parse_line(String line) { -		__lines.add(line);  		/* Version replies */  		try { manufacturer = get_string(line, "manufacturer"); } catch (Exception e) {}  		try { product = get_string(line, "product"); } catch (Exception e) {} @@ -306,14 +295,14 @@ public class AltosConfigData implements Iterable<String> {  		/* Version also contains MS5607 info, which we ignore here */ -		try { ms5607_reserved = get_int(line, "ms5607 reserved:"); } catch (Exception e) {} -		try { ms5607_sens = get_int(line, "ms5607 sens:"); } catch (Exception e) {} -		try { ms5607_off = get_int(line, "ms5607 off:"); } catch (Exception e) {} -		try { ms5607_tcs = get_int(line, "ms5607 tcs:"); } catch (Exception e) {} -		try { ms5607_tco = get_int(line, "ms5607 tco:"); } catch (Exception e) {} -		try { ms5607_tref = get_int(line, "ms5607 tref:"); } catch (Exception e) {} -		try { ms5607_tempsens = get_int(line, "ms5607 tempsens:"); } catch (Exception e) {} -		try { ms5607_crc = get_int(line, "ms5607 crc:"); } catch (Exception e) {} +		try { ms5607().reserved = get_int(line, "ms5607 reserved:"); } catch (Exception e) {} +		try { ms5607().sens = get_int(line, "ms5607 sens:"); } catch (Exception e) {} +		try { ms5607().off = get_int(line, "ms5607 off:"); } catch (Exception e) {} +		try { ms5607().tcs = get_int(line, "ms5607 tcs:"); } catch (Exception e) {} +		try { ms5607().tco = get_int(line, "ms5607 tco:"); } catch (Exception e) {} +		try { ms5607().tref = get_int(line, "ms5607 tref:"); } catch (Exception e) {} +		try { ms5607().tempsens = get_int(line, "ms5607 tempsens:"); } catch (Exception e) {} +		try { ms5607().crc = get_int(line, "ms5607 crc:"); } catch (Exception e) {}  		/* Config show replies */ diff --git a/altoslib/AltosConvert.java b/altoslib/AltosConvert.java index a3343a4f..95c1a99f 100644 --- a/altoslib/AltosConvert.java +++ b/altoslib/AltosConvert.java @@ -24,6 +24,9 @@ package org.altusmetrum.altoslib_11;  import java.util.*;  public class AltosConvert { + +	public static final double gravity = 9.80665; +  	/*  	 * Pressure Sensor Model, version 1.1  	 * @@ -44,20 +47,20 @@ public class AltosConvert {  	 *   in Joules/(kilogram-Kelvin).  	 */ -	public static final double GRAVITATIONAL_ACCELERATION = -9.80665; -	public static final double AIR_GAS_CONSTANT		= 287.053; -	public static final double NUMBER_OF_LAYERS		= 7; -	public static final double MAXIMUM_ALTITUDE		= 84852.0; -	public static final double MINIMUM_PRESSURE		= 0.3734; -	public static final double LAYER0_BASE_TEMPERATURE	= 288.15; -	public static final double LAYER0_BASE_PRESSURE	= 101325; +	private static final double GRAVITATIONAL_ACCELERATION = -gravity; +	private static final double AIR_GAS_CONSTANT		= 287.053; +	private static final double NUMBER_OF_LAYERS		= 7; +	private static final double MAXIMUM_ALTITUDE		= 84852.0; +	private static final double MINIMUM_PRESSURE		= 0.3734; +	private static final double LAYER0_BASE_TEMPERATURE	= 288.15; +	private static final double LAYER0_BASE_PRESSURE	= 101325;  	/* lapse rate and base altitude for each layer in the atmosphere */ -	public static final double[] lapse_rate = { +	private static final double[] lapse_rate = {  		-0.0065, 0.0, 0.001, 0.0028, 0.0, -0.0028, -0.002  	}; -	public static final int[] base_altitude = { +	private static final int[] base_altitude = {  		0, 11000, 20000, 32000, 47000, 51000, 71000  	}; @@ -307,6 +310,10 @@ public class AltosConvert {  		return 434.550 + channel * 0.100;  	} +	public static int telem_to_rssi(int telem) { +		return telem / 2 - 74; +	} +  	public static int[] ParseHex(String line) {  		String[] tokens = line.split("\\s+");  		int[] array = new int[tokens.length]; @@ -384,6 +391,21 @@ public class AltosConvert {  		return lb / 0.22480894;  	} +	public static double acceleration_from_sensor(double sensor, double plus_g, double minus_g, double ground) { +		if (sensor == AltosLib.MISSING) +			return AltosLib.MISSING; + +		if (plus_g == AltosLib.MISSING || minus_g == AltosLib.MISSING) +			return AltosLib.MISSING; + +		if (ground == AltosLib.MISSING) +			ground = plus_g; + +		double counts_per_g = (plus_g - minus_g) / 2.0; +		double counts_per_mss = counts_per_g / gravity; +		return (sensor - ground) / counts_per_mss; +	} +  	public static boolean imperial_units = false;  	public static AltosDistance distance = new AltosDistance(); @@ -410,6 +432,8 @@ public class AltosConvert {  	public static AltosRotationRate rotation_rate = new AltosRotationRate(); +	public static AltosStateName state_name = new AltosStateName(); +  	public static String show_gs(String format, double a) {  		a = meters_to_g(a);  		format = format.concat(" g"); diff --git a/altoslib/AltosDataListener.java b/altoslib/AltosDataListener.java new file mode 100644 index 00000000..b644e817 --- /dev/null +++ b/altoslib/AltosDataListener.java @@ -0,0 +1,69 @@ +/* + * 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 AltosDataListener { + +	public AltosCalData	cal_data; + +	public double	time = AltosLib.MISSING; + +	public void set_time(double time) { +		if (time != AltosLib.MISSING) +			this.time = time; +	} + +	public double time() { +		return time; +	} + +	public int	state = AltosLib.MISSING; + +	public void set_state(int state) { +		if (state != AltosLib.MISSING) +			this.state = state; +	} + +	public abstract void set_rssi(int rssi, int status); +	public abstract void set_received_time(long received_time); + +	public abstract void set_acceleration(double accel); +	public abstract void set_pressure(double pa); +	public abstract void set_thrust(double N); + +	public abstract void set_kalman(double height, double speed, double accel); + +	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 abstract void set_gps(AltosGPS gps); + +	public abstract void set_orient(double orient); +	public abstract void set_gyro(double roll, double pitch, double yaw); +	public abstract void set_accel_ground(double along, double across, double through); +	public abstract void set_accel(double along, double across, double through); +	public abstract void set_mag(double along, double across, double through); +	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 abstract void set_companion(AltosCompanion companion); + +	public AltosDataListener(AltosCalData cal_data) { +		this.cal_data = cal_data; +	} +} diff --git a/altoslib/AltosStateUpdate.java b/altoslib/AltosDataProvider.java index e9698cba..e55071cf 100644 --- a/altoslib/AltosStateUpdate.java +++ b/altoslib/AltosDataProvider.java @@ -18,6 +18,6 @@  package org.altusmetrum.altoslib_11; -public interface AltosStateUpdate { -	public void	update_state(AltosState state) throws InterruptedException, AltosUnknownProduct; +public interface AltosDataProvider { +	public void	provide_data(AltosDataListener listener, AltosCalData cal_data) throws InterruptedException, AltosUnknownProduct;  } diff --git a/altoslib/AltosEeprom.java b/altoslib/AltosEeprom.java index 6ed14d3a..dec7dd57 100644 --- a/altoslib/AltosEeprom.java +++ b/altoslib/AltosEeprom.java @@ -22,7 +22,7 @@ import java.io.*;  import java.util.*;  import java.text.*; -public abstract class AltosEeprom implements AltosStateUpdate { +public abstract class AltosEeprom implements AltosDataProvider {  	public int	cmd;  	public int	tick;  	public int	data8[]; @@ -52,11 +52,11 @@ public abstract class AltosEeprom implements AltosStateUpdate {  	public abstract int record_length(); -	public void update_state(AltosState state) { +	public void provide_data(AltosDataListener listener, AltosCalData cal_data) { +		cal_data.set_tick(tick);  		if (cmd == AltosLib.AO_LOG_FLIGHT) -			state.set_boost_tick(tick); -		else -			state.set_tick(tick); +			cal_data.set_boost_tick(); +		listener.set_time(cal_data.time());  	}  	public void write(PrintStream out) { diff --git a/altoslib/AltosEepromDownload.java b/altoslib/AltosEepromDownload.java index 74912ed4..4e641b85 100644 --- a/altoslib/AltosEepromDownload.java +++ b/altoslib/AltosEepromDownload.java @@ -23,6 +23,53 @@ import java.util.*;  import java.text.*;  import java.util.concurrent.*; +class AltosEepromNameData extends AltosDataListener { +	AltosGPS	gps = null; + +	public void set_rssi(int rssi, int status) { } +	public void set_received_time(long received_time) { } + +	public void set_acceleration(double accel) { } +	public void set_pressure(double pa) { } +	public void set_thrust(double N) { } + +	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) { } + +	public void set_gps(AltosGPS gps) { +		if (gps != null && +		    gps.year != AltosLib.MISSING && +		    gps.month != AltosLib.MISSING && +		    gps.day != AltosLib.MISSING) { +			this.gps = gps; +		} +	} + +	public boolean done() { +		if (gps == null) +			return false; +		return true; +	} + +	public void set_gyro(double roll, double pitch, double yaw) { } +	public void set_accel_ground(double along, double across, double through) { } +	public void set_accel(double along, double across, double through) { } +	public void set_mag(double along, double across, double through) { } +	public void set_pyro_voltage(double volts) { } +	public void set_ignitor_voltage(double[] voltage) { } +	public void set_pyro_fired(int pyro_mask) { } +	public void set_companion(AltosCompanion companion) { } +	public void set_kalman(double height, double speed, double acceleration) { } +	public void set_orient(double new_orient) { } + +	public AltosEepromNameData(AltosCalData cal_data) { +		super(cal_data); +	} +} +  public class AltosEepromDownload implements Runnable {  	AltosLink		link; @@ -45,11 +92,11 @@ public class AltosEepromDownload implements Runnable {  			gps.day != AltosLib.MISSING;  	} -	private AltosFile MakeFile(int serial, int flight, AltosState state) throws IOException { +	private AltosFile MakeFile(int serial, int flight, AltosEepromNameData name_data) throws IOException {  		AltosFile		eeprom_name; -		if (has_gps_date(state)) { -			AltosGPS		gps = state.gps; +		if (name_data.gps != null) { +			AltosGPS		gps = name_data.gps;  			eeprom_name = new AltosFile(gps.year, gps.month, gps.day,  						    serial, flight, "eeprom");  		} else @@ -141,17 +188,16 @@ public class AltosEepromDownload implements Runnable {  		 * doesn't need to work; we'll still save the data using  		 * a less accurate name.  		 */ -		AltosEepromRecordSet	set = new AltosEepromRecordSet(eeprom); - -		AltosState state = new AltosState(); +		AltosEepromRecordSet		set = new AltosEepromRecordSet(eeprom); +		AltosEepromNameData name_data = new AltosEepromNameData(set.cal_data()); -		for (AltosState s : set) { -			state = s; -			if (state.gps != null) +		for (AltosEepromRecord record : set.ordered) { +			record.provide_data(name_data, set.cal_data()); +			if (name_data.done())  				break;  		} -		AltosFile f = MakeFile(flights.config_data.serial, log.flight, state); +		AltosFile f = MakeFile(flights.config_data.serial, log.flight, name_data);  		monitor.set_filename(f.toString()); diff --git a/altoslib/AltosEepromFile.java b/altoslib/AltosEepromFile.java index 7f629913..df19877b 100644 --- a/altoslib/AltosEepromFile.java +++ b/altoslib/AltosEepromFile.java @@ -22,14 +22,10 @@ import java.io.*;  import java.util.*;  import java.text.*; -public class AltosEepromFile extends AltosStateIterable implements AltosRecordSet { +public class AltosEepromFile implements AltosRecordSet {  	AltosEepromRecordSet	set; -	public AltosConfigData config_data() { -		return set.eeprom.config_data(); -	} -  	public void write_comments(PrintStream out) {  	} @@ -41,11 +37,15 @@ public class AltosEepromFile extends AltosStateIterable implements AltosRecordSe  		set = new AltosEepromRecordSet(input);  	} -	public Iterator<AltosState> iterator() { -		return set.iterator(); +	public AltosConfigData config_data() { +		return set.config_data(); +	} + +	public AltosCalData cal_data() { +		return set.cal_data();  	} -	public void capture_series(AltosFlightSeries series) { +	public void capture_series(AltosDataListener series) {  		set.capture_series(series);  	}  } diff --git a/altoslib/AltosEepromNew.java b/altoslib/AltosEepromNew.java index 4e3ee416..5220f3a0 100644 --- a/altoslib/AltosEepromNew.java +++ b/altoslib/AltosEepromNew.java @@ -70,10 +70,6 @@ public class AltosEepromNew {  		return config_data;  	} -	public void reset_config_data() { -		config_data = null; -	} -  	private void write_config(Writer w) throws IOException {  		config.write(w, 0, true);  		w.append('\n'); diff --git a/altoslib/AltosEepromRecord.java b/altoslib/AltosEepromRecord.java index 1f6ade66..08f7ebca 100644 --- a/altoslib/AltosEepromRecord.java +++ b/altoslib/AltosEepromRecord.java @@ -81,11 +81,12 @@ public abstract class AltosEepromRecord implements Comparable<AltosEepromRecord>  		return start - o.start;  	} -	public void update_state(AltosFlightListener listen) { +	/* AltosDataProvider */ +	public void provide_data(AltosDataListener listener, AltosCalData cal_data) { +		cal_data.set_tick(tick());  		if (cmd() == AltosLib.AO_LOG_FLIGHT) -			listen.set_boost_tick(tick()); -		else -			listen.set_tick(tick()); +			cal_data.set_boost_tick(); +		listener.set_time(cal_data.time());  	}  	public int next_start() { diff --git a/altoslib/AltosEepromRecordFireTwo.java b/altoslib/AltosEepromRecordFireTwo.java index bfdd6cf8..713d0bb7 100644 --- a/altoslib/AltosEepromRecordFireTwo.java +++ b/altoslib/AltosEepromRecordFireTwo.java @@ -68,21 +68,19 @@ public class AltosEepromRecordFireTwo extends AltosEepromRecord {  		return AltosConvert.lb_to_n(v * 298 * 9.807);  	} -	public void update_state(AltosFlightListener state) { -		super.update_state(state); +	public void provide_data(AltosDataListener listener, AltosCalData cal_data) { +		super.provide_data(listener, cal_data);  		switch (cmd()) {  		case AltosLib.AO_LOG_FLIGHT: -			state.set_flight(flight()); -			state.set_ground_pressure(0.0); -			state.set_accel_g(0, -1); +			cal_data.set_flight(flight());  			break;  		case AltosLib.AO_LOG_STATE: -			state.set_state(state()); +			listener.set_state(state());  			break;  		case AltosLib.AO_LOG_SENSOR: -			state.set_pressure(adc_to_pa(pres())); -			state.set_thrust(adc_to_n(thrust())); +			listener.set_pressure(adc_to_pa(pres())); +			listener.set_thrust(adc_to_n(thrust()));  			break;  		}  	} diff --git a/altoslib/AltosEepromRecordFull.java b/altoslib/AltosEepromRecordFull.java index 0fdfa5e7..ea81eb3d 100644 --- a/altoslib/AltosEepromRecordFull.java +++ b/altoslib/AltosEepromRecordFull.java @@ -21,13 +21,13 @@ public class AltosEepromRecordFull extends AltosEepromRecord {  	public static final int two_g_default = 16294 - 15758; -	public void update_state(AltosFlightListener state) { +	public void provide_data(AltosDataListener listener, AltosCalData cal_data) { -		super.update_state(state); +		super.provide_data(listener, cal_data);  		AltosGPS	gps;  		/* Flush any pending GPS changes */ -		if (state.gps_pending()) { +		if (cal_data.gps_pending()) {  			switch (cmd()) {  			case AltosLib.AO_LOG_GPS_LAT:  			case AltosLib.AO_LOG_GPS_LON: @@ -36,39 +36,40 @@ public class AltosEepromRecordFull extends AltosEepromRecord {  			case AltosLib.AO_LOG_GPS_DATE:  				break;  			default: -				state.set_temp_gps(); +				listener.set_gps(cal_data.temp_gps()); +				cal_data.reset_temp_gps();  				break;  			}  		}  		switch (cmd()) {  		case AltosLib.AO_LOG_FLIGHT: -			state.set_state(AltosLib.ao_flight_pad); -			state.set_ground_accel(data16(0)); -			state.set_flight(data16(2)); -			if (state.accel_plus_g == AltosLib.MISSING) -				state.set_accel_g(data16(0), data16(0) + two_g_default); +			listener.set_state(AltosLib.ao_flight_pad); +			cal_data.set_ground_accel(data16(0)); +			cal_data.set_flight(data16(2)); +			if (cal_data.accel_plus_g == AltosLib.MISSING) +				cal_data.set_accel_plus_minus(data16(0), data16(0) + two_g_default);  			break;  		case AltosLib.AO_LOG_SENSOR: -			state.set_accel(data16(0)); -			state.set_pressure(AltosConvert.barometer_to_pressure(data16(2))); +			listener.set_acceleration(cal_data.acceleration(data16(0))); +			listener.set_pressure(AltosConvert.barometer_to_pressure(data16(2)));  			break;  		case AltosLib.AO_LOG_PRESSURE: -			state.set_pressure(AltosConvert.barometer_to_pressure(data16(2))); +			listener.set_pressure(AltosConvert.barometer_to_pressure(data16(2)));  			break;  		case AltosLib.AO_LOG_TEMP_VOLT: -			state.set_temperature(AltosConvert.thermometer_to_temperature(data16(0))); -			state.set_battery_voltage(AltosConvert.cc_battery_to_voltage(data16(2))); +			listener.set_temperature(AltosConvert.thermometer_to_temperature(data16(0))); +			listener.set_battery_voltage(AltosConvert.cc_battery_to_voltage(data16(2)));  			break;  		case AltosLib.AO_LOG_DEPLOY: -			state.set_apogee_voltage(AltosConvert.cc_ignitor_to_voltage(data16(0))); -			state.set_main_voltage(AltosConvert.cc_ignitor_to_voltage(data16(2))); +			listener.set_apogee_voltage(AltosConvert.cc_ignitor_to_voltage(data16(0))); +			listener.set_main_voltage(AltosConvert.cc_ignitor_to_voltage(data16(2)));  			break;  		case AltosLib.AO_LOG_STATE: -			state.set_state(data16(0)); +			listener.set_state(data16(0));  			break;  		case AltosLib.AO_LOG_GPS_TIME: -			gps = state.make_temp_gps(false); +			gps = cal_data.make_temp_gps(tick(),false);  			gps.hour = data8(0);  			gps.minute = data8(1); @@ -82,29 +83,29 @@ public class AltosEepromRecordFull extends AltosEepromRecord {  				AltosLib.AO_GPS_NUM_SAT_SHIFT;  			break;  		case AltosLib.AO_LOG_GPS_LAT: -			gps = state.make_temp_gps(false); +			gps = cal_data.make_temp_gps(tick(),false);  			int lat32 = data32(0);  			gps.lat = (double) lat32 / 1e7;  			break;  		case AltosLib.AO_LOG_GPS_LON: -			gps = state.make_temp_gps(false); +			gps = cal_data.make_temp_gps(tick(),false);  			int lon32 = data32(0);  			gps.lon = (double) lon32 / 1e7;  			break;  		case AltosLib.AO_LOG_GPS_ALT: -			gps = state.make_temp_gps(false); +			gps = cal_data.make_temp_gps(tick(),false);  			gps.alt = data16(0);  			break;  		case AltosLib.AO_LOG_GPS_SAT: -			gps = state.make_temp_gps(true); +			gps = cal_data.make_temp_gps(tick(),true);  			int svid = data16(0);  			int c_n0 = data16(3);  			gps.add_sat(svid, c_n0);  			break;  		case AltosLib.AO_LOG_GPS_DATE: -			gps = state.make_temp_gps(false); +			gps = cal_data.make_temp_gps(tick(),false);  			gps.year = data8(0) + 2000;  			gps.month = data8(1);  			gps.day = data8(2); diff --git a/altoslib/AltosEepromRecordGps.java b/altoslib/AltosEepromRecordGps.java index 4f30692e..a992abff 100644 --- a/altoslib/AltosEepromRecordGps.java +++ b/altoslib/AltosEepromRecordGps.java @@ -71,36 +71,19 @@ public class AltosEepromRecordGps extends AltosEepromRecord {  		return start - o.start;  	} -	public void update_state(AltosFlightListener state) { -		super.update_state(state); - -		AltosGPS	gps; - -		/* Flush any pending RecordGps changes */ -		if (state.gps_pending()) { -			switch (cmd()) { -			case AltosLib.AO_LOG_GPS_LAT: -			case AltosLib.AO_LOG_GPS_LON: -			case AltosLib.AO_LOG_GPS_ALT: -			case AltosLib.AO_LOG_GPS_SAT: -			case AltosLib.AO_LOG_GPS_DATE: -				break; -			default: -				state.set_temp_gps(); -				break; -			} -		} +	public void provide_data(AltosDataListener listener, AltosCalData cal_data) { +		super.provide_data(listener, cal_data);  		switch (cmd()) {  		case AltosLib.AO_LOG_FLIGHT: -			if (state.flight() == AltosLib.MISSING) { -				state.set_boost_tick(tick()); -				state.set_flight(flight()); +			if (cal_data.flight == AltosLib.MISSING) { +				cal_data.set_boost_tick(); +				cal_data.set_flight(flight());  			}  			/* no place to log start lat/lon yet */  			break;  		case AltosLib.AO_LOG_GPS_TIME: -			gps = state.make_temp_gps(false); +			AltosGPS gps = new AltosGPS();  			gps.lat = latitude() / 1e7;  			gps.lon = longitude() / 1e7;  			if (eeprom.config_data().altitude_32 == 1) @@ -140,6 +123,7 @@ public class AltosEepromRecordGps extends AltosEepromRecord {  				if (gps.vdop < 0.8)  					gps.vdop += 2.56;  			} +			listener.set_gps(gps);  			break;  		}  	} diff --git a/altoslib/AltosEepromRecordMega.java b/altoslib/AltosEepromRecordMega.java index 3c5f60b3..371810ab 100644 --- a/altoslib/AltosEepromRecordMega.java +++ b/altoslib/AltosEepromRecordMega.java @@ -109,12 +109,13 @@ public class AltosEepromRecordMega extends AltosEepromRecord {  	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(AltosFlightListener state) { -		super.update_state(state); +	public void provide_data(AltosDataListener listener, AltosCalData cal_data) { +		super.provide_data(listener, cal_data); +  		AltosGPS	gps;  		/* Flush any pending GPS changes */ -		if (state.gps_pending()) { +		if (cal_data.gps_pending()) {  			switch (cmd()) {  			case AltosLib.AO_LOG_GPS_LAT:  			case AltosLib.AO_LOG_GPS_LON: @@ -123,66 +124,85 @@ public class AltosEepromRecordMega extends AltosEepromRecord {  			case AltosLib.AO_LOG_GPS_DATE:  				break;  			default: -				state.set_temp_gps(); +				listener.set_gps(cal_data.temp_gps()); +				cal_data.reset_temp_gps();  				break;  			}  		}  		switch (cmd()) {  		case AltosLib.AO_LOG_FLIGHT: -			state.set_flight(flight()); -			state.set_ground_accel(ground_accel()); -			state.set_ground_pressure(ground_pres()); -			state.set_accel_ground(ground_accel_along(), -					       ground_accel_across(), -					       ground_accel_through()); -			state.set_gyro_zero(ground_roll() / 512.0, -					    ground_pitch() / 512.0, -					    ground_yaw() / 512.0); +			cal_data.set_flight(flight()); +			cal_data.set_ground_accel(ground_accel()); +			cal_data.set_ground_pressure(ground_pres()); +			listener.set_accel_ground(ground_accel_along(), +						  ground_accel_across(), +						  ground_accel_through()); +			cal_data.set_gyro_zero(ground_roll() / 512.0, +					       ground_pitch() / 512.0, +					       ground_yaw() / 512.0);  			break;  		case AltosLib.AO_LOG_STATE: -			state.set_state(state()); +			listener.set_state(state());  			break;  		case AltosLib.AO_LOG_SENSOR: -			state.set_ms5607(pres(), temp()); - -			AltosIMU	imu = new AltosIMU(accel_y(),	/* along */ -							   accel_x(),	/* across */ -							   accel_z(),	/* through */ -							   gyro_y(),	/* roll */ -							   gyro_x(),	/* pitch */ -							   gyro_z());	/* yaw */ +			AltosConfigData config_data = eeprom.config_data(); +			AltosPresTemp pt = config_data.ms5607().pres_temp(pres(), temp());; +			listener.set_pressure(pt.pres); +			listener.set_temperature(pt.temp); + +			int	accel_along = accel_y(); +			int	accel_across = accel_x(); +			int	accel_through = accel_z(); +			int	gyro_roll = gyro_y(); +			int	gyro_pitch = gyro_x(); +			int	gyro_yaw = gyro_z(); + +			int	mag_along = mag_x(); +			int	mag_across = mag_y(); +			int	mag_through = mag_z();  			if (log_format == AltosLib.AO_LOG_FORMAT_TELEMEGA_OLD) -				state.check_imu_wrap(imu); +				cal_data.check_imu_wrap(gyro_roll, gyro_pitch, gyro_yaw); + +			listener.set_accel(cal_data.accel_along(accel_along), +					   cal_data.accel_across(accel_across), +					   cal_data.accel_through(accel_through)); +			listener.set_gyro(cal_data.gyro_roll(gyro_roll), +					  cal_data.gyro_pitch(gyro_pitch), +					  cal_data.gyro_yaw(gyro_yaw)); -			state.set_imu(imu); +			listener.set_mag(cal_data.mag_along(mag_along), +					 cal_data.mag_across(mag_across), +					 cal_data.mag_through(mag_through)); -			state.set_mag(new AltosMag(mag_x(), -						   mag_y(), -						   mag_z())); -			state.set_accel(accel()); +			double acceleration = AltosConvert.acceleration_from_sensor( +				accel(), +				config_data.accel_cal_plus, +				config_data.accel_cal_minus, +				AltosLib.MISSING); +			listener.set_acceleration(acceleration);  			break;  		case AltosLib.AO_LOG_TEMP_VOLT: -			state.set_battery_voltage(AltosConvert.mega_battery_voltage(v_batt())); -			state.set_pyro_voltage(AltosConvert.mega_pyro_voltage(v_pbatt())); +			listener.set_battery_voltage(AltosConvert.mega_battery_voltage(v_batt())); +			listener.set_pyro_voltage(AltosConvert.mega_pyro_voltage(v_pbatt()));  			int nsense = nsense(); -			state.set_apogee_voltage(AltosConvert.mega_pyro_voltage(sense(nsense-2))); -			state.set_main_voltage(AltosConvert.mega_pyro_voltage(sense(nsense-1))); +			listener.set_apogee_voltage(AltosConvert.mega_pyro_voltage(sense(nsense-2))); +			listener.set_main_voltage(AltosConvert.mega_pyro_voltage(sense(nsense-1)));  			double voltages[] = new double[nsense-2];  			for (int i = 0; i < nsense-2; i++)  				voltages[i] = AltosConvert.mega_pyro_voltage(sense(i)); -			state.set_ignitor_voltage(voltages); -			state.set_pyro_fired(pyro()); +			listener.set_ignitor_voltage(voltages); +			listener.set_pyro_fired(pyro());  			break;  		case AltosLib.AO_LOG_GPS_TIME: -			gps = state.make_temp_gps(false); +			gps = cal_data.make_temp_gps(tick(), false);  			gps.lat = latitude() / 1e7;  			gps.lon = longitude() / 1e7; @@ -225,7 +245,7 @@ public class AltosEepromRecordMega extends AltosEepromRecord {  			}  			break;  		case AltosLib.AO_LOG_GPS_SAT: -			gps = state.make_temp_gps(true); +			gps = cal_data.make_temp_gps(tick(), true);  			int n = nsat();  			if (n > max_sat) diff --git a/altoslib/AltosEepromRecordMetrum.java b/altoslib/AltosEepromRecordMetrum.java index 6d516ebb..97a1103d 100644 --- a/altoslib/AltosEepromRecordMetrum.java +++ b/altoslib/AltosEepromRecordMetrum.java @@ -65,13 +65,13 @@ public class AltosEepromRecordMetrum extends AltosEepromRecord {  	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(AltosFlightListener state) { -		super.update_state(state); +	public void provide_data(AltosDataListener listener, AltosCalData cal_data) { +		super.provide_data(listener, cal_data);  		AltosGPS	gps;  		/* Flush any pending GPS changes */ -		if (state.gps_pending()) { +		if (cal_data.gps_pending()) {  			switch (cmd()) {  			case AltosLib.AO_LOG_GPS_POS:  			case AltosLib.AO_LOG_GPS_LAT: @@ -81,34 +81,34 @@ public class AltosEepromRecordMetrum extends AltosEepromRecord {  			case AltosLib.AO_LOG_GPS_DATE:  				break;  			default: -				state.set_temp_gps(); +				listener.set_gps(cal_data.temp_gps()); +				cal_data.reset_temp_gps();  				break;  			}  		}  		switch (cmd()) {  		case AltosLib.AO_LOG_FLIGHT: -			state.set_flight(flight()); -			state.set_ground_accel(ground_accel()); -			state.set_ground_pressure(ground_pres()); +			cal_data.set_flight(flight()); +			cal_data.set_ground_accel(ground_accel()); +			cal_data.set_ground_pressure(ground_pres());  			break;  		case AltosLib.AO_LOG_STATE: -			state.set_state(state()); +			listener.set_state(state());  			break;  		case AltosLib.AO_LOG_SENSOR: -			state.set_ms5607(pres(), temp()); -			state.set_accel(accel()); - +			AltosPresTemp pt = eeprom.config_data().ms5607().pres_temp(pres(), temp()); +			listener.set_pressure(pt.pres); +			listener.set_temperature(pt.temp); +			listener.set_acceleration(cal_data.acceleration(accel()));  			break;  		case AltosLib.AO_LOG_TEMP_VOLT: -			state.set_battery_voltage(AltosConvert.mega_battery_voltage(v_batt())); - -			state.set_apogee_voltage(AltosConvert.mega_pyro_voltage(sense_a())); -			state.set_main_voltage(AltosConvert.mega_pyro_voltage(sense_m())); - +			listener.set_battery_voltage(AltosConvert.mega_battery_voltage(v_batt())); +			listener.set_apogee_voltage(AltosConvert.mega_pyro_voltage(sense_a())); +			listener.set_main_voltage(AltosConvert.mega_pyro_voltage(sense_m()));  			break;  		case AltosLib.AO_LOG_GPS_POS: -			gps = state.make_temp_gps(false); +			gps = cal_data.make_temp_gps(tick(), false);  			gps.lat = latitude() / 1e7;  			gps.lon = longitude() / 1e7;  			if (config_data().altitude_32()) @@ -117,7 +117,7 @@ public class AltosEepromRecordMetrum extends AltosEepromRecord {  				gps.alt = altitude_low();  			break;  		case AltosLib.AO_LOG_GPS_TIME: -			gps = state.make_temp_gps(false); +			gps = cal_data.make_temp_gps(tick(), false);  			gps.hour = hour();  			gps.minute = minute(); @@ -136,7 +136,7 @@ public class AltosEepromRecordMetrum extends AltosEepromRecord {  			gps.pdop = pdop() / 10.0;  			break;  		case AltosLib.AO_LOG_GPS_SAT: -			gps = state.make_temp_gps(true); +			gps = cal_data.make_temp_gps(tick(), true);  			int n = nsat();  			for (int i = 0; i < n; i++) diff --git a/altoslib/AltosEepromRecordMini.java b/altoslib/AltosEepromRecordMini.java index dedf4bda..4b3a564e 100644 --- a/altoslib/AltosEepromRecordMini.java +++ b/altoslib/AltosEepromRecordMini.java @@ -62,22 +62,24 @@ public class AltosEepromRecordMini extends AltosEepromRecord {  		return -1;  	} -	public void update_state(AltosFlightListener state) { -		super.update_state(state); +	public void provide_data(AltosDataListener listener, AltosCalData cal_data) { +		super.provide_data(listener, cal_data);  		switch (cmd()) {  		case AltosLib.AO_LOG_FLIGHT: -			state.set_flight(flight()); -			state.set_ground_pressure(ground_pres()); +			cal_data.set_flight(flight()); +			cal_data.set_ground_pressure(ground_pres());  			break;  		case AltosLib.AO_LOG_STATE: -			state.set_state(state()); +			listener.set_state(state());  			break;  		case AltosLib.AO_LOG_SENSOR: -			state.set_ms5607(pres(), temp()); -			state.set_apogee_voltage(pyro_voltage(sense_a())); -			state.set_main_voltage(pyro_voltage(sense_m())); -			state.set_battery_voltage(battery_voltage(v_batt())); +			AltosPresTemp pt = eeprom.config_data().ms5607().pres_temp(pres(), temp()); +			listener.set_pressure(pt.pres); +			listener.set_temperature(pt.temp); +			listener.set_apogee_voltage(pyro_voltage(sense_a())); +			listener.set_main_voltage(pyro_voltage(sense_m())); +			listener.set_battery_voltage(battery_voltage(v_batt()));  			break;  		}  	} diff --git a/altoslib/AltosEepromRecordSet.java b/altoslib/AltosEepromRecordSet.java index 653a1305..69159cdf 100644 --- a/altoslib/AltosEepromRecordSet.java +++ b/altoslib/AltosEepromRecordSet.java @@ -17,45 +17,32 @@ package org.altusmetrum.altoslib_11;  import java.io.*;  import java.util.*; -public class AltosEepromRecordSet implements Iterable<AltosState>, AltosRecordSet { +public class AltosEepromRecordSet implements AltosRecordSet {  	AltosEepromNew			eeprom;  	TreeSet<AltosEepromRecord>	ordered; -	AltosState			start_state; +	AltosCalData			cal_data; -	class RecordIterator implements Iterator<AltosState> { -		Iterator<AltosEepromRecord> riterator; -		AltosState state; -		boolean started; - -		public boolean hasNext() { -			return state == null || riterator.hasNext(); -		} +	public AltosConfigData config_data() { +		return eeprom.config_data(); +	} -		public AltosState next() { -			if (state == null) -				state = start_state.clone(); -			else { -				state = state.clone(); -				AltosEepromRecord	r = riterator.next(); -				r.update_state(state); +	public AltosCalData cal_data() { +		if (cal_data == null) { +			cal_data = new AltosCalData(config_data()); +			for (AltosEepromRecord record : ordered) { +				if (record.cmd() == AltosLib.AO_LOG_FLIGHT) { +					cal_data.set_tick(record.tick()); +					cal_data.set_boost_tick(); +				}  			} -			return state; -		} - -		public RecordIterator() { -			riterator = ordered.iterator(); -			state = null;  		} +		return cal_data;  	} -	public Iterator<AltosState> iterator() { -		return new RecordIterator(); -	} - -	public void capture_series(AltosFlightSeries series) { -		series.set_config_data(eeprom.config_data()); +	public void capture_series(AltosDataListener listener) { +		AltosCalData	cal_data = cal_data();  		for (AltosEepromRecord record : ordered) { -			record.update_state(series); +			record.provide_data(listener, cal_data);  		}  	} @@ -103,9 +90,6 @@ public class AltosEepromRecordSet implements Iterable<AltosState>, AltosRecordSe  		int	tick = 0;  		boolean first = true; -		start_state = new AltosState(); -		start_state.set_config_data(record.eeprom.config_data()); -  		for (;;) {  			int	t = record.tick(); diff --git a/altoslib/AltosEepromRecordTiny.java b/altoslib/AltosEepromRecordTiny.java index e70f8cdc..705fbd9e 100644 --- a/altoslib/AltosEepromRecordTiny.java +++ b/altoslib/AltosEepromRecordTiny.java @@ -14,7 +14,7 @@  package org.altusmetrum.altoslib_11; -public class AltosEepromRecordTiny extends AltosEepromRecord { +public class AltosEepromRecordTiny extends AltosEepromRecord implements AltosDataProvider {  	public static final int	record_length = 2;  	private int value() { @@ -50,21 +50,21 @@ public class AltosEepromRecordTiny extends AltosEepromRecord {  		return tick;  	} -	public void update_state(AltosFlightListener state) { +	public void provide_data(AltosDataListener listener, AltosCalData cal_data) {  		int value = data16(-header_length); -		state.set_tick(tick()); +		cal_data.set_tick(tick());  		switch (cmd()) {  		case AltosLib.AO_LOG_FLIGHT: -			state.set_state(AltosLib.ao_flight_pad); -			state.set_flight(value); -			state.set_boost_tick(0); +			listener.set_state(AltosLib.ao_flight_pad); +			cal_data.set_flight(value); +			cal_data.set_boost_tick();  			break;  		case AltosLib.AO_LOG_STATE: -			state.set_state(value & 0x7fff); +			listener.set_state(value & 0x7fff);  			break;  		case AltosLib.AO_LOG_SENSOR: -			state.set_pressure(AltosConvert.barometer_to_pressure(value)); +			listener.set_pressure(AltosConvert.barometer_to_pressure(value));  			break;  		}  	} diff --git a/altoslib/AltosFile.java b/altoslib/AltosFile.java index ef75762a..691e70b4 100644 --- a/altoslib/AltosFile.java +++ b/altoslib/AltosFile.java @@ -66,7 +66,7 @@ public class AltosFile extends File {  		     extension);  	} -	public AltosFile(AltosState state) { -		this(state.serial, state.flight, state.receiver_serial, "telem"); +	public AltosFile(AltosCalData cal_data) { +		this(cal_data.serial, cal_data.flight, cal_data.receiver_serial, "telem");  	}  } diff --git a/altoslib/AltosFlightListener.java b/altoslib/AltosFlightListener.java index f7705165..5b478ed0 100644 --- a/altoslib/AltosFlightListener.java +++ b/altoslib/AltosFlightListener.java @@ -16,13 +16,22 @@ package org.altusmetrum.altoslib_11;  public abstract class AltosFlightListener { -	int flight; +	public int	flight; +	public int	serial; +	public int	tick; +	public int	boost_tick; +	public int	state; -	public int tick; -	int boost_tick; +	public double	accel_plus_g; +	public double	accel_minus_g; +	public double	accel; -	AltosGPS temp_gps; -	int temp_gps_sat_tick; +	public double	ground_pressure; +	public double	ground_altitude; + +	AltosGPS	temp_gps; +	int		temp_gps_sat_tick; +	int		gps_sequence;  	/* AltosEepromRecord */  	public void set_boost_tick(int boost_tick) { @@ -38,7 +47,10 @@ public abstract class AltosFlightListener {  	public double time() {  		if (tick == AltosLib.MISSING)  			return AltosLib.MISSING; -		return tick / 100.0; +		if (boost_tick != AltosLib.MISSING) +			return (tick - boost_tick) / 100.0; +		else +			return tick / 100.0;  	}  	public double boost_time() { @@ -47,9 +59,23 @@ public abstract class AltosFlightListener {  		return boost_tick / 100.0;  	} +	public abstract void set_rssi(int rssi, int status); +	public abstract void set_received_time(long received_time); +  	/* AltosEepromRecordFull */ -	public abstract void set_state(int state); +	public void set_serial(int serial) { +		if (serial != AltosLib.MISSING) +			this.serial = serial; +	} + +	public void set_state(int state) { +		if (state != AltosLib.MISSING) +			this.state = state; +	} + +	public int state() { return state; } +  	public abstract void set_ground_accel(double ground_accel);  	public void set_flight(int flight) {  		if (flight != AltosLib.MISSING) @@ -60,6 +86,7 @@ public abstract class AltosFlightListener {  	}  	public abstract void set_accel(double accel); +	public abstract void set_acceleration(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_thrust(double N); @@ -90,10 +117,15 @@ public abstract class AltosFlightListener {  		return temp_gps;  	} -	public abstract void set_ground_pressure(double ground_pressure); +	public void set_ground_pressure(double ground_pressure) { +		if (ground_pressure != AltosLib.MISSING) { +			this.ground_pressure = ground_pressure; +			this.ground_altitude = AltosConvert.pressure_to_altitude(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); @@ -103,16 +135,28 @@ public abstract class AltosFlightListener {  	public void copy(AltosFlightListener old) {  		flight = old.flight; +		serial = old.serial;  		tick = old.tick;  		boost_tick = old.boost_tick; +		accel_plus_g = old.accel_plus_g; +		accel_minus_g = old.accel_minus_g; +		ground_pressure = old.ground_pressure; +		ground_altitude = old.ground_altitude;  		temp_gps = old.temp_gps;  		temp_gps_sat_tick = old.temp_gps_sat_tick;  	}  	public void init() {  		flight = AltosLib.MISSING; +		serial = AltosLib.MISSING;  		tick = AltosLib.MISSING;  		boost_tick = AltosLib.MISSING; +		accel_plus_g = AltosLib.MISSING; +		accel_minus_g = AltosLib.MISSING; +		accel = AltosLib.MISSING; +		ground_pressure = AltosLib.MISSING; +		ground_altitude = AltosLib.MISSING; +		temp_gps = null;  		temp_gps_sat_tick = AltosLib.MISSING;  	}  } diff --git a/altoslib/AltosFlightSeries.java b/altoslib/AltosFlightSeries.java index 0e260fb4..b7434a5c 100644 --- a/altoslib/AltosFlightSeries.java +++ b/altoslib/AltosFlightSeries.java @@ -16,124 +16,261 @@ package org.altusmetrum.altoslib_11;  import java.util.*; -public class AltosFlightSeries extends AltosFlightListener { +public class AltosFlightSeries extends AltosDataListener { -	int flight; +	public ArrayList<AltosTimeSeries> series; -	int tick; -	int boost_tick; +	public int[] indices() { +		int[] indices = new int[series.size()]; +		for (int i = 0; i < indices.length; i++) +			indices[i] = 0; +		return indices; +	} -	AltosGPS temp_gps; -	int temp_gps_sat_tick; +	private double time(int id, int index) { +		AltosTimeSeries		s = series.get(id); +		if (index < s.values.size()) +			return s.values.get(index).time; +		return Double.POSITIVE_INFINITY; +	} -	AltosMs5607 ms5607; +	public boolean step_indices(int[] indices) { +		double	min_next = time(0, indices[0]+1); -	public ArrayList<AltosTimeSeries> series; +		for (int i = 1; i < indices.length; i++) { +			double next = time(i, indices[i]+1); +			if (next < min_next) +				min_next = next; +		} -	/* AltosEepromRecord */ -	public void set_boost_tick(int boost_tick) { -		if (boost_tick != AltosLib.MISSING) -			this.boost_tick = boost_tick; -	} +		if (min_next == Double.POSITIVE_INFINITY) +			return false; -	public void set_tick(int tick) { -		if (tick != AltosLib.MISSING) -			this.tick = tick; +		for (int i = 0; i < indices.length; i++) { +			double	t = time(i, indices[i] + 1); + +			if (t <= min_next) +				indices[i]++; +		} +		return true;  	} -	public double time() { -		if (tick == AltosLib.MISSING) -			return AltosLib.MISSING; -		return tick / 100.0; +	public double time(int[] indices) { +		double max = time(0, indices[0]); + +		for (int i = 1; i < indices.length; i++) { +			double t = time(i, indices[i]); +			if (t >= max) +				max = t; +		} +		return max;  	} -	public double boost_time() { -		if (boost_tick == AltosLib.MISSING) -			return AltosLib.MISSING; -		return boost_tick / 100.0; +	public double value(String name, int[] indices) { +		for (int i = 0; i < indices.length; i++) { +			AltosTimeSeries	s = series.get(i); +			if (s.label.equals(name)) +				return s.values.get(indices[i]).value; +		} +		return AltosLib.MISSING;  	}  	public AltosTimeSeries make_series(String label, AltosUnits units) {  		return new AltosTimeSeries(label, units);  	} +	public void add_series(AltosTimeSeries s) { +		series.add(s); +	} +  	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); +		add_series(s);  		return s;  	} -	/* AltosEepromRecordFull */ +	public void remove_series(AltosTimeSeries s) { +		series.remove(s); +	} + +	public boolean has_series(String label) { +		for (AltosTimeSeries s : series) +			if (s.label.equals(label)) +				return true; +		return false; +	}  	AltosTimeSeries state_series;  	public static final String state_name = "State";  	public void set_state(int state) { +		this.state = state;  		if (state_series == null) -			state_series = add_series(state_name, null); +			state_series = add_series(state_name, AltosConvert.state_name); +		else if ((int) state_series.get(state_series.size()-1).value == state) +			return;  		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) +	public void set_acceleration(double acceleration) { +		if (accel_series == null) { +			System.out.printf("set acceleration %g\n", acceleration);  			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); +		} +		accel_series.add(time(), acceleration);  	} +	private void compute_accel() { +		if (accel_series != null) +			return; -	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; +		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); +		}  	} -	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_received_time(long received_time) {  	} -	public  void set_ground_accel(double ground_accel) { +	AltosTimeSeries rssi_series; + +	public static final String rssi_name = "RSSI"; + +	AltosTimeSeries status_series; + +	public static final String status_name = "Status"; + +	public void set_rssi(int rssi, int status) { +		if (rssi_series == null) +			rssi_series = add_series(rssi_name, null); +		rssi_series.add(time(), rssi); +		if (status_series == null) +			status_series = add_series(status_name, null); +		status_series.add(time(), status);  	}  	AltosTimeSeries pressure_series;  	public static final String pressure_name = "Pressure"; +	AltosTimeSeries altitude_series; + +	public static final String altitude_name = "Altitude"; + +	AltosTimeSeries height_series; + +	public static final String height_name = "Height"; +  	public  void set_pressure(double pa) {  		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); + +		double altitude = AltosConvert.pressure_to_altitude(pa); +		altitude_series.add(time(), altitude); +	} + +	private void compute_height(double ground_altitude) { +		if (height_series == null) { +			height_series = add_series(height_name, AltosConvert.height); +			for (AltosTimeValue alt : altitude_series) +				height_series.add(alt.time, alt.value - ground_altitude); +		} +	} + +	AltosTimeSeries speed_series; + +	public static final String speed_name = "Speed"; + +	private void compute_speed() { +		if (speed_series != null) { +			System.out.printf("speed series already made\n"); +			return; +		} + +		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); + +			alt_speed_series = make_series(speed_name, AltosConvert.speed); +			temp_series.filter(alt_speed_series, 10.0); +		} else { +			System.out.printf("no altitude series\n"); +		} +		if (accel_series != null) { +			AltosTimeSeries temp_series = make_series(speed_name, AltosConvert.speed); +			accel_series.integrate(temp_series); + +			accel_speed_series = make_series(speed_name, AltosConvert.speed); +			temp_series.filter(accel_speed_series, 0.1); +		} else { +			System.out.printf("no accel series\n"); +		} + +		if (alt_speed_series != null && accel_speed_series != null) { +			double	apogee_time = AltosLib.MISSING; +			if (state_series != null) { +				for (AltosTimeValue d : state_series) { +					if (d.value >= AltosLib.ao_flight_drogue){ +						apogee_time = d.time; +						break; +					} +				} +			} +			if (apogee_time == AltosLib.MISSING) { +				speed_series = alt_speed_series; +			} else { +				speed_series = make_series(speed_name, AltosConvert.speed); +				for (AltosTimeValue d : accel_speed_series) { +					if (d.time <= apogee_time) +						speed_series.add(d); +				} +				for (AltosTimeValue d : alt_speed_series) { +					if (d.time > apogee_time) +						speed_series.add(d); +				} + +			} +		} else if (alt_speed_series != null) { +			speed_series = alt_speed_series; +		} else if (accel_speed_series != null) { +			speed_series = accel_speed_series; +		} +		if (speed_series != null) { +			add_series(speed_series); +			System.out.printf("speed series for %s set to %s\n", this.toString(), speed_series.toString()); +		} else +			System.out.printf("didn't manage to make speed series\n"); +	} + +	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"; +	public static final String kalman_accel_name = "Kalman Accel"; + +	public void set_kalman(double height, double speed, double acceleration) { +		if (kalman_height_series == null) { +			kalman_height_series = add_series(kalman_height_name, AltosConvert.height); +			kalman_speed_series = add_series(kalman_speed_name, AltosConvert.speed); +			kalman_accel_series = add_series(kalman_accel_name, AltosConvert.accel); +		} +		kalman_height_series.add(time(), height); +		kalman_speed_series.add(time(), speed); +		kalman_accel_series.add(time(), acceleration);  	}  	AltosTimeSeries thrust_series; @@ -146,114 +283,159 @@ public class AltosFlightSeries extends AltosFlightListener {  		thrust_series.add(time(), N);  	} +	AltosTimeSeries temperature_series; + +	public static final String temperature_name = "Temperature"; +  	public  void set_temperature(double deg_c) { +		if (temperature_series == null) +			temperature_series = add_series(temperature_name, AltosConvert.temperature); +		temperature_series.add(time(), deg_c);  	} -	public  void set_battery_voltage(double volts) { +	AltosTimeSeries battery_voltage_series; + +	public static final String battery_voltage_name = "Battery Voltage"; + +	public void set_battery_voltage(double volts) { +		if (volts == AltosLib.MISSING) +			return; +		if (battery_voltage_series == null) +			battery_voltage_series = add_series(battery_voltage_name, AltosConvert.voltage); +		battery_voltage_series.add(time(), volts);  	} -	public  void set_apogee_voltage(double volts) { +	AltosTimeSeries apogee_voltage_series; + +	public static final String apogee_voltage_name = "Apogee Voltage"; + +	public void set_apogee_voltage(double volts) { +		if (volts == AltosLib.MISSING) +			return; +		if (apogee_voltage_series == null) +			apogee_voltage_series = add_series(apogee_voltage_name, AltosConvert.voltage); +		apogee_voltage_series.add(time(), volts);  	} -	public  void set_main_voltage(double volts) { +	AltosTimeSeries main_voltage_series; + +	public static final String main_voltage_name = "Main Voltage"; + +	public void set_main_voltage(double volts) { +		if (volts == AltosLib.MISSING) +			return; +		if (main_voltage_series == null) +			main_voltage_series = add_series(main_voltage_name, AltosConvert.voltage); +		main_voltage_series.add(time(), volts);  	}  	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; +	public ArrayList<AltosGPSTimeValue> gps_series; +  	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 static final String gps_height_name = "GPS Height"; +	public static final String gps_ground_speed_name = "GPS Ground Speed"; +	public static final String gps_ascent_rate_name = "GPS Ascent Rate"; +	public static final String gps_course_name = "GPS Course"; +	public static final String gps_speed_name = "GPS Speed"; -	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 void set_gps(AltosGPS gps) { +		if (gps_series == null) +			gps_series = new ArrayList<AltosGPSTimeValue>(); +		gps_series.add(new AltosGPSTimeValue(time(), gps)); -	public AltosGPS make_temp_gps(boolean sats) { -		if (temp_gps == null) { -			temp_gps = new AltosGPS(); +		if (sats_in_view == null) { +			sats_in_view = add_series(sats_in_view_name, null); +			sats_in_soln = add_series(sats_in_soln_name, 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 (sats) { -			if (tick != temp_gps_sat_tick) -				temp_gps.cc_gps_sat = null; -			temp_gps_sat_tick = tick; +		if (gps.cc_gps_sat != null) +			sats_in_view.add(time(), gps.cc_gps_sat.length); +		if (gps.locked) { +			sats_in_soln.add(time(), gps.nsat); +			if (gps.alt != AltosLib.MISSING) { +				gps_altitude.add(time(), gps.alt); +				if (cal_data.gps_ground_altitude != AltosLib.MISSING) +					gps_height.add(time(), gps.alt - cal_data.gps_ground_altitude); +			} +			if (gps.ground_speed != AltosLib.MISSING) +				gps_ground_speed.add(time(), gps.ground_speed); +			if (gps.climb_rate != AltosLib.MISSING) +				gps_ascent_rate.add(time(), gps.climb_rate); +			if (gps.course != AltosLib.MISSING) +				gps_course.add(time(), gps.course); +			if (gps.ground_speed != AltosLib.MISSING && gps.climb_rate != AltosLib.MISSING) +				gps_speed.add(time(), Math.sqrt(gps.ground_speed * gps.ground_speed + +								gps.climb_rate * gps.climb_rate));  		} -		return temp_gps;  	} -	public  void set_ground_pressure(double ground_pressure) { +	public static final String accel_across_name = "Accel Across"; +	public static final String accel_along_name = "Accel Along"; +	public static final String accel_through_name = "Accel Through"; + +	public  void set_accel(double along, double across, double through) {  	}  	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_gyro(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 set_mag(double along, double across, double through) {  	} -	public  void check_imu_wrap(AltosIMU imu) { -	} +	public void set_orient(double new_orient) { } -	public  void set_imu(AltosIMU imu) { +	public  void set_pyro_voltage(double volts) {  	} -	public  void set_mag(AltosMag mag) { +	public  void set_ignitor_voltage(double[] voltage) {  	} -	public  void set_pyro_voltage(double volts) { +	public  void set_pyro_fired(int pyro_mask) {  	} -	public  void set_ignitor_voltage(double[] voltage) { +	public void set_companion(AltosCompanion companion) {  	} -	public  void set_pyro_fired(int pyro_mask) { +	public void fill_in() { +		System.out.printf("fill in %s\n", this.toString()); +		compute_speed(); +		compute_accel(); +		if (cal_data.ground_altitude != AltosLib.MISSING) +			compute_height(cal_data.ground_altitude);  	}  	public void init() { -		flight = AltosLib.MISSING; -		tick = AltosLib.MISSING; -		boost_tick = AltosLib.MISSING; -		temp_gps_sat_tick = AltosLib.MISSING; +		time = AltosLib.MISSING;  		series = new ArrayList<AltosTimeSeries>();  	} -	public void copy(AltosFlightSeries old) { -		super.copy(old); -	} -  	public AltosTimeSeries[] series() { +		fill_in();  		return series.toArray(new AltosTimeSeries[0]);  	} -	public AltosFlightSeries() { +	public AltosFlightSeries(AltosCalData cal_data) { +		super(cal_data); +		System.out.printf("new flight series %s\n", this.toString());  		init();  	}  } diff --git a/altoslib/AltosFlightStats.java b/altoslib/AltosFlightStats.java index 98f13dac..7179351e 100644 --- a/altoslib/AltosFlightStats.java +++ b/altoslib/AltosFlightStats.java @@ -48,63 +48,74 @@ public class AltosFlightStats {  	public boolean		has_orient;  	public int		num_ignitor; -	double landed_time(AltosStateIterable states) { -		AltosState state = null; +	double landed_time(AltosFlightSeries series) { +		double	landed_state_time = AltosLib.MISSING; -		for (AltosState s : states) { -			state = s; -			if (state.state() == AltosLib.ao_flight_landed) +		for (AltosTimeValue state : series.state_series) { +			if (state.value == AltosLib.ao_flight_landed) { +				landed_state_time = state.time;  				break; +			}  		} -		if (state == null) +		if (landed_state_time == AltosLib.MISSING)  			return AltosLib.MISSING; -		double	landed_height = state.height(); +		double landed_height = AltosLib.MISSING; +		for (AltosTimeValue height : series.height_series) { +			if (height.time >= landed_state_time) { +				landed_height = height.value; +				break; +			} +		} -		state = null; +		if (landed_height == AltosLib.MISSING) +			return AltosLib.MISSING;  		boolean	above = true;  		double	landed_time = AltosLib.MISSING; -		for (AltosState s : states) { -			state = s; - -			if (state.height() > landed_height + 10) { +		for (AltosTimeValue height : series.height_series) { +			if (height.value > landed_height + 10) {  				above = true;  			} else { -				if (above && Math.abs(state.height() - landed_height) < 2) { +				if (above && Math.abs(height.value - landed_height) < 2) {  					above = false; -					landed_time = state.time; +					landed_time = height.time;  				}  			}  		}  		return landed_time;  	} -	double boost_time(AltosStateIterable states) { -		double boost_time = AltosLib.MISSING; -		AltosState	state = null; +	double boost_time(AltosFlightSeries series) { +		double 		boost_time = AltosLib.MISSING; +		double		boost_state_time = AltosLib.MISSING; -		for (AltosState s : states) { -			state = s; -			if (state.acceleration() < 1) -				boost_time = state.time; -			if (state.state() >= AltosLib.ao_flight_boost && state.state() <= AltosLib.ao_flight_landed) +		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; +			} +		} +		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 (state == null) -			return AltosLib.MISSING; -  		return boost_time;  	} -	public AltosFlightStats(AltosStateIterable states) throws InterruptedException, IOException { -		double		boost_time = boost_time(states); +	public AltosFlightStats(AltosFlightSeries series) throws InterruptedException, IOException { +		AltosCalData	cal_data = series.cal_data; +		double		boost_time = boost_time(series);  		double		end_time = 0; -		double		landed_time = landed_time(states); +		double		landed_time = landed_time(series); + +		System.out.printf("flight stats %s\n", series.toString());  		year = month = day = AltosLib.MISSING;  		hour = minute = second = AltosLib.MISSING; @@ -126,22 +137,44 @@ public class AltosFlightStats {  			state_accel[s] = 0.0;  		} +		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; + +		if (series.gps_series != null) { +			AltosGPS gps = series.gps_series.get(0).gps; + +			year = gps.year; +			month = gps.month; +			day = gps.day; +			hour = gps.hour; +			minute = gps.minute; +			second = gps.second; +		} + +		max_height = AltosLib.MISSING; +		if (series.height_series != null) +			max_height = series.height_series.max(); +		max_speed = AltosLib.MISSING; +		if (series.speed_series != null) +			max_speed = series.speed_series.max(); +		else +			System.out.printf("missing speed series\n"); +		max_acceleration = AltosLib.MISSING; +		if (series.accel_series != null) +			max_acceleration = series.accel_series.max(); +		max_gps_height = AltosLib.MISSING; +		if (series.gps_height != null) +			max_gps_height = series.gps_height.max(); + +/*  		for (AltosState state : states) { -			if (serial == AltosLib.MISSING && state.serial != AltosLib.MISSING) -				serial = state.serial; -			if (flight == AltosLib.MISSING && state.flight != AltosLib.MISSING) -				flight = state.flight; -			if (state.battery_voltage != AltosLib.MISSING) -				has_battery = true; -			if (state.main_voltage != AltosLib.MISSING) -				has_flight_adc = true; -			if (state.rssi != AltosLib.MISSING) -				has_rssi = true;  			end_time = state.time; -			if (state.pressure() != AltosLib.MISSING) -				has_flight_data = true; -  			int state_id = state.state();  			if (boost_time != AltosLib.MISSING && state.time >= boost_time && state_id < AltosLib.ao_flight_boost) {  				state_id = AltosLib.ao_flight_boost; @@ -150,19 +183,6 @@ public class AltosFlightStats {  				state_id = AltosLib.ao_flight_landed;  			} -			if (state.gps != null && state.gps.locked) { -				year = state.gps.year; -				month = state.gps.month; -				day = state.gps.day; -				hour = state.gps.hour; -				minute = state.gps.minute; -				second = state.gps.second; -			} -			max_height = state.max_height(); -			max_speed = state.max_speed(); -			max_acceleration = state.max_acceleration(); -			max_gps_height = state.max_gps_height(); -  			if (0 <= state_id && state_id < AltosLib.ao_flight_invalid) {  				double acceleration = state.acceleration();  				double speed = state.speed(); @@ -198,6 +218,7 @@ public class AltosFlightStats {  			if (state.ignitor_voltage != null && state.ignitor_voltage.length > num_ignitor)  				num_ignitor = state.ignitor_voltage.length;  		} +*/  		for (int s = AltosLib.ao_flight_startup; s <= AltosLib.ao_flight_landed; s++) {  			if (state_count[s] > 0) {  				state_speed[s] /= state_count[s]; diff --git a/altoslib/AltosGPS.java b/altoslib/AltosGPS.java index 0b30ed45..a730957b 100644 --- a/altoslib/AltosGPS.java +++ b/altoslib/AltosGPS.java @@ -383,17 +383,13 @@ public class AltosGPS implements Cloneable {  		}  	} -	static public void update_state(AltosState state, AltosLink link, AltosConfigData config_data) throws InterruptedException { +	static public void provide_data(AltosDataListener listener, AltosLink link, AltosCalData cal_data) throws InterruptedException {  		try { -			AltosGPS	gps = new AltosGPS(link, config_data); - -			if (gps != null) { -				state.set_gps(gps, state.gps_sequence++); -				return; -			} +			AltosGPS gps = new AltosGPS(link, link.config_data()); +			if (gps != null) +				listener.set_gps(gps);  		} catch (TimeoutException te) {  		} -		state.set_gps(null, 0);  	}  	public AltosGPS (AltosLink link, AltosConfigData config_data) throws TimeoutException, InterruptedException { diff --git a/altoslib/AltosGPSTimeValue.java b/altoslib/AltosGPSTimeValue.java new file mode 100644 index 00000000..0a534373 --- /dev/null +++ b/altoslib/AltosGPSTimeValue.java @@ -0,0 +1,28 @@ +/* + * 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; version 2 of the License. + * + * 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_11; + +public class AltosGPSTimeValue { +	public double	time; +	public AltosGPS	gps; + +	public AltosGPSTimeValue(double time, AltosGPS gps) { +		this.time = time; +		this.gps = gps; +	} +} diff --git a/altoslib/AltosIMU.java b/altoslib/AltosIMU.java index f6cadf1d..20a2a413 100644 --- a/altoslib/AltosIMU.java +++ b/altoslib/AltosIMU.java @@ -33,7 +33,7 @@ public class AltosIMU implements Cloneable {  	public static final double	counts_per_g = 2048.0;  	public static double convert_accel(double counts) { -		return counts / counts_per_g * (-AltosConvert.GRAVITATIONAL_ACCELERATION); +		return counts / counts_per_g * AltosConvert.gravity;  	}  	public static final double	counts_per_degsec = 16.4; @@ -72,12 +72,18 @@ public class AltosIMU implements Cloneable {  		return n;  	} -	static public void update_state(AltosState state, AltosLink link, AltosConfigData config_data) throws InterruptedException { +	static public void provide_data(AltosDataListener listener, AltosLink link, AltosCalData cal_data) throws InterruptedException {  		try {  			AltosIMU	imu = new AltosIMU(link); -			if (imu != null) -				state.set_imu(imu); +			if (imu != null) { +				listener.set_accel(cal_data.accel_along(imu.accel_along), +						   cal_data.accel_across(imu.accel_across), +						   cal_data.accel_through(imu.accel_through)); +				listener.set_gyro(cal_data.gyro_roll(imu.gyro_roll), +						  cal_data.gyro_pitch(imu.gyro_pitch), +						  cal_data.gyro_yaw(imu.gyro_yaw)); +			}  		} catch (TimeoutException te) {  		}  	} diff --git a/altoslib/AltosIdleFetch.java b/altoslib/AltosIdleFetch.java index 73717e17..43eb980a 100644 --- a/altoslib/AltosIdleFetch.java +++ b/altoslib/AltosIdleFetch.java @@ -30,7 +30,6 @@ class AltosIdler {  	static final int	idle_gps = 0;  	static final int	idle_imu = 1;  	static final int	idle_mag = 2; -	static final int	idle_ms5607 = 3;  	static final int	idle_mma655x = 4; @@ -42,49 +41,44 @@ class AltosIdler {  	static final int	idle_sensor_tgps = 15;  	static final int	idle_sensor_tmini3 = 16; -	public void update_state(AltosState state, AltosLink link, AltosConfigData config_data) throws InterruptedException, TimeoutException, AltosUnknownProduct { +	public void provide_data(AltosDataListener listener, AltosLink link, AltosCalData cal_data) throws InterruptedException, TimeoutException, AltosUnknownProduct {  		for (int idler : idlers) { -			AltosIdle idle = null;  			switch (idler) {  			case idle_gps: -				AltosGPS.update_state(state, link, config_data); +				AltosGPS.provide_data(listener, link, cal_data);  				break;  			case idle_imu: -				AltosIMU.update_state(state, link, config_data); +				AltosIMU.provide_data(listener, link, cal_data);  				break;  			case idle_mag: -				AltosMag.update_state(state, link, config_data); -				break; -			case idle_ms5607: -				AltosMs5607.update_state(state, link, config_data); +				AltosMag.provide_data(listener, link, cal_data);  				break;  			case idle_mma655x: -				AltosMma655x.update_state(state, link, config_data); +				AltosMma655x.provide_data(listener, link, cal_data);  				break; -			case idle_sensor_tm: -				AltosSensorTM.update_state(state, link, config_data); +/*			case idle_sensor_tm: +				AltosSensorTM.provide_data(listener, link, cal_data);  				break;  			case idle_sensor_metrum: -				AltosSensorMetrum.update_state(state, link, config_data); +				AltosSensorMetrum.provide_data(listener, link, cal_data);  				break;  			case idle_sensor_mega: -				AltosSensorMega.update_state(state, link, config_data); +				AltosSensorMega.provide_data(listener, link, cal_data);  				break;  			case idle_sensor_emini: -				AltosSensorEMini.update_state(state, link, config_data); +				AltosSensorEMini.provide_data(listener, link, cal_data);  				break;  			case idle_sensor_tmini2: -				AltosSensorTMini2.update_state(state, link, config_data); +				AltosSensorTMini2.provide_data(listener, link, cal_data);  				break;  			case idle_sensor_tgps: -				AltosSensorTGPS.update_state(state, link, config_data); +				AltosSensorTGPS.provide_data(listener, link, cal_data);  				break;  			case idle_sensor_tmini3: -				AltosSensorTMini3.update_state(state, link, config_data); +				AltosSensorTMini3.provide_data(listener, link, cal_data);  				break; +*/  			} -			if (idle != null) -				idle.update_state(state);  		}  	} @@ -99,23 +93,20 @@ class AltosIdler {  } -public class AltosIdleFetch implements AltosStateUpdate { +public class AltosIdleFetch implements AltosDataProvider {  	static final AltosIdler[] idlers = {  		new AltosIdler("EasyMini", -			       AltosIdler.idle_ms5607,  			       AltosIdler.idle_sensor_emini),  		new AltosIdler("TeleMini-v1",  			       AltosIdler.idle_sensor_tm),  		new AltosIdler("TeleMini-v2", -			       AltosIdler.idle_ms5607,  			       AltosIdler.idle_sensor_tmini2),  		new AltosIdler("TeleMini-v3", -			       AltosIdler.idle_ms5607,  			       AltosIdler.idle_sensor_tmini3),  		new AltosIdler("TeleMetrum-v1", @@ -124,16 +115,16 @@ public class AltosIdleFetch implements AltosStateUpdate {  		new AltosIdler("TeleMetrum-v2",  			       AltosIdler.idle_gps, -			       AltosIdler.idle_ms5607, AltosIdler.idle_mma655x, +			       AltosIdler.idle_mma655x,  			       AltosIdler.idle_sensor_metrum),  		new AltosIdler("TeleMega",  			       AltosIdler.idle_gps, -			       AltosIdler.idle_ms5607, AltosIdler.idle_mma655x, +			       AltosIdler.idle_mma655x,  			       AltosIdler.idle_imu, AltosIdler.idle_mag,  			       AltosIdler.idle_sensor_mega),  		new AltosIdler("EasyMega", -			       AltosIdler.idle_ms5607, AltosIdler.idle_mma655x, +			       AltosIdler.idle_mma655x,  			       AltosIdler.idle_imu, AltosIdler.idle_mag,  			       AltosIdler.idle_sensor_mega),  		new AltosIdler("TeleGPS", @@ -143,29 +134,22 @@ public class AltosIdleFetch implements AltosStateUpdate {  	AltosLink		link; -	public void update_state(AltosState state) throws InterruptedException, AltosUnknownProduct { +	public void provide_data(AltosDataListener listener, AltosCalData cal_data) throws InterruptedException, AltosUnknownProduct {  		try {  			boolean	matched = false;  			/* Fetch config data from remote */  			AltosConfigData config_data = new AltosConfigData(link); -			state.set_state(AltosLib.ao_flight_stateless); -			state.set_serial(config_data.serial); -			state.set_callsign(config_data.callsign); -			state.set_ground_accel(config_data.accel_cal_plus); -			state.set_accel_g(config_data.accel_cal_plus, config_data.accel_cal_minus); -			state.set_product(config_data.product); -			state.set_firmware_version(config_data.version); -			state.set_log_space(config_data.log_space); +			listener.set_state(AltosLib.ao_flight_stateless);  			for (AltosIdler idler : idlers) {  				if (idler.matches(config_data)) { -					idler.update_state(state, link, config_data); +					idler.provide_data(listener, link, cal_data);  					matched = true;  					break;  				}  			}  			if (!matched)  				throw new AltosUnknownProduct(config_data.product); -			state.set_received_time(System.currentTimeMillis()); +			listener.set_received_time(System.currentTimeMillis());  		} catch (TimeoutException te) {  		} diff --git a/altoslib/AltosIdleMonitor.java b/altoslib/AltosIdleMonitor.java index c374b601..3d73dce6 100644 --- a/altoslib/AltosIdleMonitor.java +++ b/altoslib/AltosIdleMonitor.java @@ -52,20 +52,21 @@ public class AltosIdleMonitor extends Thread {  		return link.reply_abort;  	} -	boolean update_state(AltosState state) throws InterruptedException, TimeoutException, AltosUnknownProduct { +	boolean provide_data(AltosDataListener listener) throws InterruptedException, TimeoutException, AltosUnknownProduct {  		boolean		worked = false;  		boolean		aborted = false; +		AltosCalData	cal_data = new AltosCalData(link.config_data());  		try {  			start_link(); -			fetch.update_state(state); +			fetch.provide_data(listener, cal_data);  			if (!link.has_error && !link.reply_abort)  				worked = true;  		} finally {  			aborted = stop_link();  			if (worked) {  				if (remote) -					state.set_rssi(link.rssi(), 0); +					listener.set_rssi(link.rssi(), 0);  				listener_state.battery = link.monitor_battery();  			}  		} @@ -92,12 +93,14 @@ public class AltosIdleMonitor extends Thread {  	}  	public void run() { -		AltosState state = new AltosState(); +		AltosState state = null;  		try {  			for (;;) {  				try {  					link.config_data(); -					update_state(state); +					if (state == null) +						state = new AltosState(new AltosCalData(link.config_data())); +					provide_data(state);  					listener.update(state, listener_state);  				} catch (TimeoutException te) {  				} catch (AltosUnknownProduct ae) { diff --git a/altoslib/AltosIdleReader.java b/altoslib/AltosIdleReader.java index 5903c968..49d0cf61 100644 --- a/altoslib/AltosIdleReader.java +++ b/altoslib/AltosIdleReader.java @@ -48,11 +48,6 @@ public class AltosIdleReader extends AltosFlightReader {  		boolean worked = false;  		boolean aborted = false; -		if (state == null) -			state = new AltosState(); -		else -			state = state.clone(); -  		long	delay = next_millis - System.currentTimeMillis();  		if (delay > 0) @@ -61,7 +56,9 @@ public class AltosIdleReader extends AltosFlightReader {  		try {  			try {  				start_link(); -				fetch.update_state(state); +				if (state == null) +					state = new AltosState(new AltosCalData(link.config_data())); +				fetch.provide_data(state, state.cal_data);  				if (!link.has_error && !link.reply_abort)  					worked = true;  			} catch (TimeoutException te) { diff --git a/altoslib/AltosKML.java b/altoslib/AltosKML.java index 25108bf9..61e83daa 100644 --- a/altoslib/AltosKML.java +++ b/altoslib/AltosKML.java @@ -36,7 +36,7 @@ public class AltosKML implements AltosWriter {  	File			name;  	PrintWriter		out;  	int			flight_state = -1; -	AltosState		prev = null; +	AltosGPS		prev = null;  	double			gps_start_altitude;  	static final String[] kml_state_colors = { @@ -101,42 +101,43 @@ public class AltosKML implements AltosWriter {  		"</Document>\n" +  		"</kml>\n"; -	void start (AltosState record) { +	void start (int state) { +/*  		out.printf(kml_header_start, record.flight, record.serial);  		out.printf("Date:   %04d-%02d-%02d\n",  			   record.gps.year, record.gps.month, record.gps.day);  		out.printf("Time:     %2d:%02d:%02d\n",  			   record.gps.hour, record.gps.minute, record.gps.second);  		out.printf("%s", kml_header_end); +*/  	}  	boolean	started = false; -	void state_start(AltosState state) { -		String	state_name = AltosLib.state_name(state.state()); -		String	state_color = state_color(state.state()); +	void state_start(int state) { +		String	state_name = AltosLib.state_name(state); +		String	state_color = state_color(state);  		out.printf(kml_style_start, state_name, state_color);  		out.printf("\tState: %s\n", state_name);  		out.printf("%s", kml_style_end);  		out.printf(kml_placemark_start, state_name, state_name);  	} -	void state_end(AltosState state) { +	void state_end() {  		out.printf("%s", kml_placemark_end);  	} -	void coord(AltosState state) { -		AltosGPS	gps = state.gps; +	void coord(double time, AltosGPS gps, int state, double height) {  		double		altitude; -		if (state.height() != AltosLib.MISSING) -			altitude = state.height() + gps_start_altitude; +		if (height != AltosLib.MISSING) +			altitude = height + gps_start_altitude;  		else  			altitude = gps.alt;  		out.printf(kml_coord_fmt,  			   gps.lon, gps.lat,  			   altitude, (double) gps.alt, -			   state.time, gps.nsat); +			   time, gps.nsat);  	}  	void end() { @@ -145,7 +146,7 @@ public class AltosKML implements AltosWriter {  	public void close() {  		if (prev != null) { -			state_end(prev); +			state_end();  			end();  			prev = null;  		} @@ -155,12 +156,7 @@ public class AltosKML implements AltosWriter {  		}  	} -	public void write(AltosState state) { -		AltosGPS	gps = state.gps; - -		if (gps == null) -			return; - +	public void write(AltosGPS gps, int state, double height) {  		if (gps.lat == AltosLib.MISSING)  			return;  		if (gps.lon == AltosLib.MISSING) @@ -170,24 +166,41 @@ public class AltosKML implements AltosWriter {  			started = true;  			gps_start_altitude = gps.alt;  		} -		if (prev != null && prev.gps_sequence == state.gps_sequence) -			return; -		if (state.state() != flight_state) { -			flight_state = state.state(); +		if (state != flight_state) { +			flight_state = state;  			if (prev != null) { -				coord(state); -				state_end(prev); +//				coord(gps, state, height); +				state_end();  			}  			state_start(state);  		} -		coord(state); -		prev = state; +//		coord(0, gps, state, height); +		prev = gps; +	} + +	private int state(AltosFlightSeries series, double time) { +		int s = AltosLib.MISSING; +		for (AltosTimeValue state : series.state_series) { +			if (state.time > time) +				break; +			s = (int) state.value; +		} +		return s; +	} + +	private double height(AltosFlightSeries series, double time) { +		double h = AltosLib.MISSING; +		for (AltosTimeValue height : series.height_series) { +			if (height.time > time) +				break; +			h = height.value; +		} +		return h;  	} -	public void write(AltosStateIterable states) { -		for (AltosState state : states) { -			if ((state.set & AltosState.set_gps) != 0) -				write(state); +	public void write(AltosFlightSeries series) { +		for (AltosGPSTimeValue gps : series.gps_series) { +			write(gps.gps, state(series, gps.time), height(series, gps.time));  		}  	} diff --git a/altoslib/AltosLib.java b/altoslib/AltosLib.java index a3f164d4..2137d1d7 100644 --- a/altoslib/AltosLib.java +++ b/altoslib/AltosLib.java @@ -162,6 +162,16 @@ public class AltosLib {  		return product_any;  	} +	public static boolean has_9dof(int device_type) { +		return device_type == product_telemega || device_type == product_easymega; +	} + +	public static boolean has_gps(int device_type) { +		return device_type == product_telemetrum || +			device_type == product_telemega || +			device_type == product_telegps; +	} +  	/* Bluetooth "identifier" (bluetooth sucks) */  	public final static String bt_product_telebt = "TeleBT"; diff --git a/altoslib/AltosLog.java b/altoslib/AltosLog.java index 6d873d78..d57749a1 100644 --- a/altoslib/AltosLog.java +++ b/altoslib/AltosLog.java @@ -61,8 +61,8 @@ public class AltosLog implements Runnable {  		return file;  	} -	boolean open (AltosState state) throws IOException, InterruptedException { -		AltosFile	a = new AltosFile(state); +	boolean open (AltosCalData cal_data) throws IOException, InterruptedException { +		AltosFile	a = new AltosFile(cal_data);  		log_file = new FileWriter(a, true);  		if (log_file != null) { @@ -80,24 +80,31 @@ public class AltosLog implements Runnable {  	public void run () {  		try { -			AltosState	state = new AltosState();  			AltosConfigData	receiver_config = link.config_data(); -			state.set_receiver_serial(receiver_config.serial); +			AltosCalData	cal_data = new AltosCalData(); +			AltosState	state = null; +			cal_data.set_receiver_serial(receiver_config.serial);  			for (;;) {  				AltosLine	line = input_queue.take();  				if (line.line == null)  					continue;  				try {  					AltosTelemetry	telem = AltosTelemetry.parse(line.line); -					state = state.clone(); -					telem.update_state(state); -					if (state.serial != serial || state.flight != flight || log_file == null) +					if (state == null) +						state = new AltosState(cal_data); +					telem.provide_data(state, cal_data); + +					if (cal_data.serial != serial || +					    cal_data.flight != flight || +					    log_file == null)  					{  						close_log_file(); -						serial = state.serial; -						flight = state.flight; -						if (state.serial != AltosLib.MISSING && state.flight != AltosLib.MISSING) -							open(state); +						serial = cal_data.serial; +						flight = cal_data.flight; +						state = null; +						if (cal_data.serial != AltosLib.MISSING && +						    cal_data.flight != AltosLib.MISSING) +							open(cal_data);  					}  				} catch (ParseException pe) {  				} catch (AltosCRCException ce) { diff --git a/altoslib/AltosMag.java b/altoslib/AltosMag.java index e89ec0de..523a31a5 100644 --- a/altoslib/AltosMag.java +++ b/altoslib/AltosMag.java @@ -72,12 +72,14 @@ public class AltosMag implements Cloneable {  		this.through = through;  	} -	static public void update_state(AltosState state, AltosLink link, AltosConfigData config_data) throws InterruptedException { +	static public void provide_data(AltosDataListener listener, AltosLink link, AltosCalData cal_data) throws InterruptedException {  		try {  			AltosMag	mag = new AltosMag(link);  			if (mag != null) -				state.set_mag(mag); +				listener.set_mag(cal_data.mag_along(mag.along), +						 cal_data.mag_across(mag.across), +						 cal_data.mag_through(mag.through));  		} catch (TimeoutException te) {  		}  	} diff --git a/altoslib/AltosMap.java b/altoslib/AltosMap.java index e3c4a6a7..203a23b5 100644 --- a/altoslib/AltosMap.java +++ b/altoslib/AltosMap.java @@ -220,11 +220,11 @@ public class AltosMap implements AltosMapTileListener, AltosMapStoreListener {  		return false;  	} -	public void show(AltosState state, AltosListenerState listener_state) { +	public void show(AltosGPS gps, int state) { -		/* If insufficient gps data, nothing to update +		/* +		 * If insufficient gps data, nothing to update  		 */ -		AltosGPS	gps = state.gps;  		if (gps == null)  			return; @@ -232,23 +232,23 @@ public class AltosMap implements AltosMapTileListener, AltosMapStoreListener {  		if (!gps.locked && gps.nsat < 4)  			return; -		switch (state.state()) { +		switch (state) {  		case AltosLib.ao_flight_boost:  			if (!have_boost) { -				add_mark(gps.lat, gps.lon, state.state()); +				add_mark(gps.lat, gps.lon, state);  				have_boost = true;  			}  			break;  		case AltosLib.ao_flight_landed:  			if (!have_landed) { -				add_mark(gps.lat, gps.lon, state.state()); +				add_mark(gps.lat, gps.lon, state);  				have_landed = true;  			}  			break;  		}  		if (path != null) { -			AltosMapRectangle	damage = path.add(gps.lat, gps.lon, state.state()); +			AltosMapRectangle	damage = path.add(gps.lat, gps.lon, state);  			if (damage != null)  				repaint(damage, AltosMapPath.stroke_width); @@ -259,6 +259,10 @@ public class AltosMap implements AltosMapTileListener, AltosMapStoreListener {  		maybe_centre(gps.lat, gps.lon);  	} +	public void show(AltosState state, AltosListenerState listener_state) { +		show(state.gps, state.state()); +	} +  	public void centre(AltosLatLon lat_lon) {  		centre = lat_lon;  		set_transform(); @@ -268,10 +272,14 @@ public class AltosMap implements AltosMapTileListener, AltosMapStoreListener {  		centre(new AltosLatLon(lat, lon));  	} -	public void centre(AltosState state) { -		if (!state.gps.locked && state.gps.nsat < 4) +	public void centre(AltosGPS gps) { +		if (!gps.locked && gps.nsat < 4)  			return; -		centre(state.gps.lat, state.gps.lon); +		centre(gps.lat, gps.lon); +	} + +	public void centre(AltosState state) { +		centre(state.gps);  	}  	public void maybe_centre(double lat, double lon) { diff --git a/altoslib/AltosMma655x.java b/altoslib/AltosMma655x.java index 503eb5fd..2aadfc2e 100644 --- a/altoslib/AltosMma655x.java +++ b/altoslib/AltosMma655x.java @@ -46,17 +46,17 @@ public class AltosMma655x implements Cloneable {  		return n;  	} -	static public void update_state(AltosState state, AltosLink link, AltosConfigData config_data) throws InterruptedException, AltosUnknownProduct { +	static public void provide_data(AltosDataListener listener, AltosLink link, AltosCalData cal_data) throws InterruptedException, AltosUnknownProduct {  		try {  			AltosMma655x	mma655x = new AltosMma655x(link);  			if (mma655x != null) {  				int accel = mma655x.accel; -				if (config_data.mma655x_inverted()) +				if (cal_data.mma655x_inverted)  					accel = 4095 - accel; -				if (config_data.pad_orientation == 1) +				if (cal_data.pad_orientation == 1)  					accel = 4095 - accel; -				state.set_accel(accel); +				listener.set_acceleration(cal_data.acceleration(accel));  			}  		} catch (TimeoutException te) {  		} catch (NumberFormatException ne) { diff --git a/altoslib/AltosMs5607.java b/altoslib/AltosMs5607.java index c598d01e..bb6ce4c2 100644 --- a/altoslib/AltosMs5607.java +++ b/altoslib/AltosMs5607.java @@ -22,28 +22,36 @@ import java.util.concurrent.*;  import java.io.*;  public class AltosMs5607 { -	public int	reserved; -	public int	sens; -	public int	off; -	public int	tcs; -	public int	tco; -	public int	tref; -	public int	tempsens; -	public int	crc; - -	public int	raw_pres; -	public int	raw_temp; -	public int	pa; -	public int	cc; - -	static final boolean	ms5611 = false; - -	void convert() { +	public int	reserved = AltosLib.MISSING; +	public int	sens = AltosLib.MISSING; +	public int	off = AltosLib.MISSING; +	public int	tcs = AltosLib.MISSING; +	public int	tco = AltosLib.MISSING; +	public int	tref = AltosLib.MISSING; +	public int	tempsens = AltosLib.MISSING; +	public int	crc = AltosLib.MISSING; +	private boolean	ms5611 = false; + +	public boolean valid_config() { +		return reserved != AltosLib.MISSING && +			sens != AltosLib.MISSING && +			off != AltosLib.MISSING && +			tcs != AltosLib.MISSING && +			tco != AltosLib.MISSING && +			tref != AltosLib.MISSING && +			tempsens != AltosLib.MISSING && +			crc  != AltosLib.MISSING; +	} + +	public AltosPresTemp pres_temp(int raw_pres, int raw_temp) {  		int	dT; -		int TEMP; -		long OFF; -		long SENS; -		//int P; +		int	TEMP; +		long	OFF; +		long	SENS; +		int	P; + +		if (raw_pres == AltosLib.MISSING || raw_temp == AltosLib.MISSING) +			return new AltosPresTemp(AltosLib.MISSING, AltosLib.MISSING);  		dT = raw_temp - ((int) tref << 8); @@ -75,111 +83,61 @@ public class AltosMs5607 {  			SENS -= SENS2;  		} -		pa = (int) (((((long) raw_pres * SENS) >> 21) - OFF) >> 15); -		cc = TEMP; -	} +		P = (int) (((((long) raw_pres * SENS) >> 21) - OFF) >> 15); -	public int set(int in_pres, int in_temp) { -		raw_pres = in_pres; -		raw_temp = in_temp; -		convert(); -		return pa; +		return new AltosPresTemp(P, TEMP / 100.0);  	} -	public boolean parse_line(String line) { -		String[] items = line.split("\\s+"); -		if (line.startsWith("Pressure:")) { -			if (items.length >= 2) { -				raw_pres = Integer.parseInt(items[1]); -			} -		} else if (line.startsWith("Temperature:")) { -			if (items.length >= 2) -				raw_temp = Integer.parseInt(items[1]); -		} else if (line.startsWith("ms5607 reserved:")) { -			if (items.length >= 3) -				reserved = Integer.parseInt(items[2]); -		} else if (line.startsWith("ms5607 sens:")) { -			if (items.length >= 3) { -				sens = Integer.parseInt(items[2]); -			} -		} else if (line.startsWith("ms5607 off:")) { -			if (items.length >= 3) -				off = Integer.parseInt(items[2]); -		} else if (line.startsWith("ms5607 tcs:")) { -			if (items.length >= 3) -				tcs = Integer.parseInt(items[2]); -		} else if (line.startsWith("ms5607 tco:")) { -			if (items.length >= 3) -				tco = Integer.parseInt(items[2]); -		} else if (line.startsWith("ms5607 tref:")) { -			if (items.length >= 3) -				tref = Integer.parseInt(items[2]); -		} else if (line.startsWith("ms5607 tempsens:")) { -			if (items.length >= 3) -				tempsens = Integer.parseInt(items[2]); -		} else if (line.startsWith("ms5607 crc:")) { -			if (items.length >= 3) -				crc = Integer.parseInt(items[2]); -		} else if (line.startsWith("Altitude:")) { -			return false; -		} -		return true; -	} +	public AltosPresTemp pres_temp(AltosLink link) throws InterruptedException, TimeoutException { +		int	raw_pres = AltosLib.MISSING; +		int	raw_temp = AltosLib.MISSING; +		boolean	done = false; -	static public void update_state(AltosState state, AltosLink link, AltosConfigData config_data) throws InterruptedException { -		try { -			AltosMs5607	ms5607 = new AltosMs5607(link, config_data); +		link.printf("B\n"); +		while (!done) { +			String line = link.get_reply_no_dialog(5000); +			if (line == null) +				throw new TimeoutException(); -			if (ms5607 != null) { -				state.set_ms5607(ms5607); -				return; +			String[] items = line.split("\\s+"); +			if (line.startsWith("Pressure:")) { +				if (items.length >= 2) { +					raw_pres = Integer.parseInt(items[1]); +				} +			} else if (line.startsWith("Temperature:")) { +				if (items.length >= 2) +					raw_temp = Integer.parseInt(items[1]); +			} else if (line.startsWith("Altitude:")) { +				done = true;  			} -		} catch (TimeoutException te) {  		} +		return pres_temp(raw_pres, raw_temp);  	} -	public boolean valid_config() { -		return reserved != AltosLib.MISSING && -			sens != AltosLib.MISSING && -			off != AltosLib.MISSING && -			tcs != AltosLib.MISSING && -			tco != AltosLib.MISSING && -			tref != AltosLib.MISSING && -			tempsens != AltosLib.MISSING && -			crc  != AltosLib.MISSING; +	public AltosMs5607(boolean ms5611) { +		this.ms5611 = ms5611;  	}  	public AltosMs5607() { -		raw_pres = AltosLib.MISSING; -		raw_temp = AltosLib.MISSING; -		pa = AltosLib.MISSING; -		cc = AltosLib.MISSING; +		this(false); +	} + +	public AltosMs5607(AltosMs5607 old) { +		reserved = old.reserved; +		sens = old.sens; +		off = old.off; +		tcs = old.tcs; +		tco = old.tco; +		tref = old.tref; +		tempsens = old.tempsens; +		crc = old.crc;  	}  	public AltosMs5607(AltosConfigData config_data) { -		this(); -		reserved = config_data.ms5607_reserved; -		sens = config_data.ms5607_sens; -		off = config_data.ms5607_off; -		tcs = config_data.ms5607_tcs; -		tco = config_data.ms5607_tco; -		tref = config_data.ms5607_tref; -		tempsens = config_data.ms5607_tempsens; -		crc = config_data.ms5607_crc; +		this(config_data.ms5607());  	}  	public AltosMs5607 (AltosLink link, AltosConfigData config_data) throws InterruptedException, TimeoutException {  		this(config_data); -		link.printf("B\n"); -		for (;;) { -			String line = link.get_reply_no_dialog(5000); -			if (line == null) { -				throw new TimeoutException(); -			} -			if (!parse_line(line)) { -				break; -			} -		} -		convert();  	}  } diff --git a/altoslib/AltosPreferences.java b/altoslib/AltosPreferences.java index 35d44631..f446d4dd 100644 --- a/altoslib/AltosPreferences.java +++ b/altoslib/AltosPreferences.java @@ -363,11 +363,11 @@ public class AltosPreferences {  		}  	} -	public static void set_state(AltosState state) { +	public static void set_state(AltosState state, int serial) {  		synchronized(backend) { -			backend.putJson(String.format(statePreferenceFormat, state.serial), new AltosJson(state)); -			backend.putInt(statePreferenceLatest, state.serial); +			backend.putJson(String.format(statePreferenceFormat, serial), new AltosJson(state)); +			backend.putInt(statePreferenceLatest, serial);  			flush_preferences();  		}  	} diff --git a/altoslib/AltosPresTemp.java b/altoslib/AltosPresTemp.java new file mode 100644 index 00000000..d0787033 --- /dev/null +++ b/altoslib/AltosPresTemp.java @@ -0,0 +1,25 @@ +/* + * 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 AltosPresTemp { +	double	pres = AltosLib.MISSING; +	double	temp = AltosLib.MISSING; + +	public AltosPresTemp(double pres, double temp) { +		this.pres = pres; +		this.temp = temp; +	} +} diff --git a/altoslib/AltosRecordSet.java b/altoslib/AltosRecordSet.java index 8a472336..3c6ae575 100644 --- a/altoslib/AltosRecordSet.java +++ b/altoslib/AltosRecordSet.java @@ -17,5 +17,6 @@ package org.altusmetrum.altoslib_11;  import java.util.*;  public interface AltosRecordSet { -	public void capture_series(AltosFlightSeries series); +	public AltosCalData cal_data(); +	public void capture_series(AltosDataListener listener);  } diff --git a/altoslib/AltosSensorTM.java b/altoslib/AltosSensorTM.java index 5d1b1b7f..7d7becfb 100644 --- a/altoslib/AltosSensorTM.java +++ b/altoslib/AltosSensorTM.java @@ -29,18 +29,18 @@ public class AltosSensorTM {  	public int	drogue;  	public int	main; -	static public void update_state(AltosState state, AltosLink link, AltosConfigData config_data) throws InterruptedException { +	static public void provide_data(AltosDataListener listener, AltosLink link, AltosCalData cal_data) throws InterruptedException {  		try {  			AltosSensorTM	sensor_tm = new AltosSensorTM(link);  			if (sensor_tm == null)  				return; -			state.set_accel(sensor_tm.accel); -			state.set_pressure(AltosConvert.barometer_to_pressure(sensor_tm.pres)); -			state.set_temperature(AltosConvert.thermometer_to_temperature(sensor_tm.temp)); -			state.set_battery_voltage(AltosConvert.cc_battery_to_voltage(sensor_tm.batt)); -			state.set_apogee_voltage(AltosConvert.cc_ignitor_to_voltage(sensor_tm.drogue)); -			state.set_main_voltage(AltosConvert.cc_ignitor_to_voltage(sensor_tm.main)); +			listener.set_acceleration(cal_data.acceleration((sensor_tm.accel))); +			listener.set_pressure(AltosConvert.barometer_to_pressure(sensor_tm.pres)); +			listener.set_temperature(AltosConvert.thermometer_to_temperature(sensor_tm.temp)); +			listener.set_battery_voltage(AltosConvert.cc_battery_to_voltage(sensor_tm.batt)); +			listener.set_apogee_voltage(AltosConvert.cc_ignitor_to_voltage(sensor_tm.drogue)); +			listener.set_main_voltage(AltosConvert.cc_ignitor_to_voltage(sensor_tm.main));  		} catch (TimeoutException te) {  		} diff --git a/altoslib/AltosState.java b/altoslib/AltosState.java index 846bda42..f46b12ea 100644 --- a/altoslib/AltosState.java +++ b/altoslib/AltosState.java @@ -24,7 +24,7 @@ package org.altusmetrum.altoslib_11;  import java.io.*; -public class AltosState extends AltosFlightListener implements Cloneable { +public class AltosState extends AltosDataListener {  	public static final int set_position = 1;  	public static final int set_gps = 2; @@ -40,10 +40,12 @@ public class AltosState extends AltosFlightListener implements Cloneable {  	public long	received_time; +	public int	rssi; +	public int	status; +  	public double	time;  	public double	prev_time;  	public double	time_change; -	private int	prev_tick;  	class AltosValue {  		double	value; @@ -289,16 +291,11 @@ public class AltosState extends AltosFlightListener implements Cloneable {  	}  	private int	state; -	public int	flight; -	public int	serial;  	public int	altitude_32;  	public int	receiver_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; @@ -446,6 +443,11 @@ public class AltosState extends AltosFlightListener implements Cloneable {  	}  	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);  	} @@ -684,6 +686,11 @@ public class AltosState extends AltosFlightListener implements Cloneable {  	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); @@ -701,7 +708,6 @@ public class AltosState extends AltosFlightListener implements Cloneable {  	public AltosGPS	temp_gps;  	public int temp_gps_sat_tick;  	public boolean	gps_pending; -	public int gps_sequence;  	public AltosIMU	imu;  	public AltosMag	mag; @@ -728,11 +734,7 @@ public class AltosState extends AltosFlightListener implements Cloneable {  	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 int	log_space; @@ -759,16 +761,11 @@ public class AltosState extends AltosFlightListener implements Cloneable {  		time = AltosLib.MISSING;  		time_change = AltosLib.MISSING;  		prev_time = AltosLib.MISSING; -		tick = AltosLib.MISSING; -		prev_tick = AltosLib.MISSING; -		boost_tick = AltosLib.MISSING;  		state = AltosLib.ao_flight_invalid; -		flight = AltosLib.MISSING;  		landed = false;  		boost = false;  		rssi = AltosLib.MISSING;  		status = 0; -		device_type = AltosLib.MISSING;  		config_major = AltosLib.MISSING;  		config_minor = AltosLib.MISSING;  		apogee_delay = AltosLib.MISSING; @@ -798,7 +795,6 @@ public class AltosState extends AltosFlightListener implements Cloneable {  		gps = null;  		temp_gps = null;  		temp_gps_sat_tick = 0; -		gps_sequence = 0;  		gps_pending = false;  		imu = null; @@ -817,10 +813,6 @@ public class AltosState extends AltosFlightListener implements Cloneable {  		pad_orientation = AltosLib.MISSING; -		gyro_zero_roll = AltosLib.MISSING; -		gyro_zero_pitch = AltosLib.MISSING; -		gyro_zero_yaw = AltosLib.MISSING; -  		set_npad(0);  		ngps = 0; @@ -846,17 +838,11 @@ public class AltosState extends AltosFlightListener implements Cloneable {  		callsign = null;  		firmware_version = null; -		accel_plus_g = AltosLib.MISSING; -		accel_minus_g = AltosLib.MISSING; -		accel = AltosLib.MISSING; -  		ground_accel = AltosLib.MISSING; -		ground_accel_avg = AltosLib.MISSING;  		log_format = AltosLib.MISSING;  		log_space = AltosLib.MISSING;  		product = null; -		serial = AltosLib.MISSING;  		receiver_serial = AltosLib.MISSING;  		altitude_32 = AltosLib.MISSING; @@ -867,8 +853,6 @@ public class AltosState extends AltosFlightListener implements Cloneable {  	}  	void finish_update() { -		prev_tick = tick; -  		ground_altitude.finish_update();  		altitude.finish_update();  		pressure.finish_update(); @@ -881,153 +865,6 @@ public class AltosState extends AltosFlightListener implements Cloneable {  		kalman_acceleration.finish_update();  	} -	void copy(AltosState old) { - -		if (old == null) { -			init(); -			return; -		} - -		super.copy(old); - -		received_time = old.received_time; -		time = old.time; -		time_change = old.time_change; -		prev_time = old.time; - -		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; - -		ground_pressure.copy(old.ground_pressure); -		ground_altitude.copy(old.ground_altitude); -		altitude.copy(old.altitude); -		pressure.copy(old.pressure); -		speed.copy(old.speed); -		acceleration.copy(old.acceleration); -		orient.copy(old.orient); - -		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_sat_tick = old.temp_gps_sat_tick; -		gps_sequence = old.gps_sequence; -		gps_pending = old.gps_pending; - -		if (old.imu != null) -			imu = old.imu.clone(); -		else -			imu = null; -		last_imu_time = old.last_imu_time; - -		if (old.rotation != null) -			rotation = new AltosRotation (old.rotation); - -		if (old.ground_rotation != null) { -			ground_rotation = new AltosRotation(old.ground_rotation); -		} - -		accel_zero_along = old.accel_zero_along; -		accel_zero_across = old.accel_zero_across; -		accel_zero_through = old.accel_zero_through; - -		accel_ground_along = old.accel_ground_along; -		accel_ground_across = old.accel_ground_across; -		accel_ground_through = old.accel_ground_through; -		pad_orientation = old.pad_orientation; - -		gyro_zero_roll = old.gyro_zero_roll; -		gyro_zero_pitch = old.gyro_zero_pitch; -		gyro_zero_yaw = old.gyro_zero_yaw; - -		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; - -		gps_altitude.copy(old.gps_altitude); -		gps_ground_altitude.copy(old.gps_ground_altitude); -		gps_ground_speed.copy(old.gps_ground_speed); -		gps_ascent_rate.copy(old.gps_ascent_rate); -		gps_course.copy(old.gps_course); -		gps_speed.copy(old.gps_speed); - -		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; -		firmware_version = old.firmware_version; - -		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; -		log_space = old.log_space; -		product = old.product; -		serial = old.serial; -		receiver_serial = old.receiver_serial; -		altitude_32 = old.altitude_32; - -		baro = old.baro; -		companion = old.companion; - -		pyro_fired = old.pyro_fired; -	} -  	void update_time() {  	} @@ -1078,19 +915,6 @@ public class AltosState extends AltosFlightListener implements Cloneable {  		}  	} -	public void set_tick(int new_tick) { -		if (new_tick != AltosLib.MISSING) { -			if (prev_tick != AltosLib.MISSING) { -				while (new_tick < prev_tick - 1000) { -					new_tick += 65536; -				} -			} -			tick = new_tick; -			time = tick / 100.0; -			time_change = time - prev_time; -		} -	} -  	public String state_name() {  		return AltosLib.state_name(state);  	} @@ -1112,15 +936,6 @@ public class AltosState extends AltosFlightListener implements Cloneable {  		return state;  	} -	public void set_device_type(int device_type) { -		this.device_type = device_type; -		switch (device_type) { -		case AltosLib.product_telegps: -			this.state = AltosLib.ao_flight_stateless; -			break; -		} -	} -  	public void set_log_format(int log_format) {  		this.log_format = log_format;  		switch (log_format) { @@ -1160,40 +975,38 @@ public class AltosState extends AltosFlightListener implements Cloneable {  	}  	private void re_init() { -		int bt = boost_tick;  		int rs = receiver_serial;  		init(); -		boost_tick = bt;  		receiver_serial = rs;  	} -	public void set_flight(int flight) { - -		/* When the flight changes, reset the state */ -		if (flight != AltosLib.MISSING) { -			if (this.flight != AltosLib.MISSING && -			    this.flight != flight) { -				re_init(); -			} -			this.flight = flight; -		} -	} - -	public void set_serial(int serial) { -		/* When the serial changes, reset the state */ -		if (serial != AltosLib.MISSING) { -			if (this.serial != AltosLib.MISSING && -			    this.serial != serial) { -				re_init(); -			} -			this.serial = serial; -		} -	} - -	public void set_receiver_serial(int serial) { -		if (serial != AltosLib.MISSING) -			receiver_serial = serial; -	} +//	public void set_flight(int flight) { +// +//		/* When the flight changes, reset the state */ +//		if (flight != AltosLib.MISSING) { +//			if (this.flight != AltosLib.MISSING && +//			    this.flight != flight) { +//				re_init(); +//			} +//			this.flight = flight; +//		} +//	} +// +//	public void set_serial(int serial) { +//		/* When the serial changes, reset the state */ +//		if (serial != AltosLib.MISSING) { +//			if (this.serial != AltosLib.MISSING && +//			    this.serial != serial) { +//				re_init(); +//			} +//			this.serial = serial; +//		} +//	} +// +//	public void set_receiver_serial(int serial) { +//		if (serial != AltosLib.MISSING) +//			receiver_serial = serial; +//	}  	public boolean altitude_32() {  		return altitude_32 == 1; @@ -1221,10 +1034,9 @@ public class AltosState extends AltosFlightListener implements Cloneable {  		received_time = ms;  	} -	public void set_gps(AltosGPS gps, int sequence) { +	public void set_gps(AltosGPS gps) {  		if (gps != null) { -			this.gps = gps.clone(); -			gps_sequence = sequence; +			this.gps = gps;  			update_gps();  			set |= set_gps;  		} @@ -1273,18 +1085,6 @@ public class AltosState extends AltosFlightListener implements Cloneable {  		update_pad_rotation();  	} -	public double	gyro_zero_roll; -	public double	gyro_zero_pitch; -	public double	gyro_zero_yaw; - -	public void set_gyro_zero(double roll, double pitch, double yaw) { -		if (roll != AltosLib.MISSING) { -			gyro_zero_roll = roll; -			gyro_zero_pitch = pitch; -			gyro_zero_yaw = yaw; -		} -	} -  	public double	last_imu_time;  	private double radians(double degrees) { @@ -1309,77 +1109,58 @@ public class AltosState extends AltosFlightListener implements Cloneable {  		last_imu_time = time;  	} -	public void set_imu(AltosIMU imu) { -		if (imu != null) -			imu = imu.clone(); -		this.imu = imu; +	private double	gyro_roll, gyro_pitch, gyro_yaw; + +	public void set_gyro(double roll, double pitch, double yaw) { +		gyro_roll = roll; +		gyro_pitch = roll; +		gyro_roll = roll;  		update_orient();  	} -	private double gyro_zero_overflow(double first) { -		double v = first / 128.0; -		if (v < 0) -			v = Math.ceil(v); -		else -			v = Math.floor(v); -		return v * 128.0; -	} +	private double accel_along, accel_across, accel_through; -	public void check_imu_wrap(AltosIMU imu) { -		if (this.imu == null) { -			gyro_zero_roll += gyro_zero_overflow(imu.gyro_roll); -			gyro_zero_pitch += gyro_zero_overflow(imu.gyro_pitch); -			gyro_zero_yaw += gyro_zero_overflow(imu.gyro_yaw); -		} +	public void set_accel(double along, double across, double through) { +		accel_along = along; +		accel_across = across; +		accel_through = through; +		update_orient();  	}  	public double accel_along() { -		if (imu != null && accel_zero_along != AltosLib.MISSING) -			return AltosIMU.convert_accel(imu.accel_along - accel_zero_along); -		return AltosLib.MISSING; +		return accel_along;  	}  	public double accel_across() { -		if (imu != null && accel_zero_across != AltosLib.MISSING) -			return AltosIMU.convert_accel(imu.accel_across - accel_zero_across); -		return AltosLib.MISSING; +		return accel_across;  	}  	public double accel_through() { -		if (imu != null && accel_zero_through != AltosLib.MISSING) -			return AltosIMU.convert_accel(imu.accel_through - accel_zero_through); -		return AltosLib.MISSING; +		return accel_through;  	}  	public double gyro_roll() { -		if (imu != null && gyro_zero_roll != AltosLib.MISSING) { -			return AltosIMU.convert_gyro(imu.gyro_roll - gyro_zero_roll); -		} -		return AltosLib.MISSING; +		return gyro_roll;  	}  	public double gyro_pitch() { -		if (imu != null && gyro_zero_pitch != AltosLib.MISSING) { -			return AltosIMU.convert_gyro(imu.gyro_pitch - gyro_zero_pitch); -		} -		return AltosLib.MISSING; +		return gyro_pitch;  	}  	public double gyro_yaw() { -		if (imu != null && gyro_zero_yaw != AltosLib.MISSING) { -			return AltosIMU.convert_gyro(imu.gyro_yaw - gyro_zero_yaw); -		} -		return AltosLib.MISSING; +		return gyro_yaw;  	} -	public void set_mag(AltosMag mag) { -		this.mag = mag.clone(); +	private double mag_along, mag_across, mag_through; + +	public void set_mag(double along, double across, double through) { +		mag_along = along; +		mag_across = across; +		mag_through = through;  	}  	public double mag_along() { -		if (mag != null) -			return AltosMag.convert_gauss(mag.along); -		return AltosLib.MISSING; +		return mag_along;  	}  	public double mag_across() { @@ -1394,71 +1175,15 @@ public class AltosState extends AltosFlightListener implements Cloneable {  		return AltosLib.MISSING;  	} -	public AltosMs5607 make_baro() { -		if (baro == null) -			baro = new AltosMs5607(); -		return baro; -	} - -	public void set_ms5607(AltosMs5607 ms5607) { -		baro = ms5607; - -		if (baro != null && baro.pa != AltosLib.MISSING && baro.cc != AltosLib.MISSING) { -			set_pressure(baro.pa); -			set_temperature(baro.cc / 100.0); -		} -	} - -	public void set_ms5607(int pres, int temp) { -		if (baro != null) { -			baro.set(pres, temp); - -			set_pressure(baro.pa); -			set_temperature(baro.cc / 100.0); -		} -	} -  	public void set_companion(AltosCompanion companion) {  		this.companion = companion;  	} -	void update_accel() { -		if (accel == AltosLib.MISSING) -			return; -		if (accel_plus_g == AltosLib.MISSING) -			return; -		if (accel_minus_g == AltosLib.MISSING) -			return; - -		double counts_per_g = (accel_minus_g - accel_plus_g) / 2.0; -		double counts_per_mss = counts_per_g / 9.80665; -		acceleration.set_measured((accel_plus_g - accel) / counts_per_mss, time); -	} - -	public void set_accel_g(double accel_plus_g, double accel_minus_g) { -		if (accel_plus_g != AltosLib.MISSING) { -			this.accel_plus_g = accel_plus_g; -			this.accel_minus_g = accel_minus_g; -			update_accel(); -		} -	} - -	public void set_ground_accel(double ground_accel) { -		if (ground_accel != AltosLib.MISSING) -			this.ground_accel = ground_accel; -	} - -	public void set_accel(double accel) { -		if (accel != AltosLib.MISSING) { -			this.accel = accel; -			if (state == AltosLib.ao_flight_pad) { -				if (ground_accel_avg == AltosLib.MISSING) -					ground_accel_avg = accel; -				else -					ground_accel_avg = (ground_accel_avg * 7 + accel) / 8; -			} +	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) { @@ -1504,74 +1229,8 @@ public class AltosState extends AltosFlightListener implements Cloneable {  		this.pyro_fired = fired;  	} -	public double time_since_boost() { -		if (tick == AltosLib.MISSING) -			return 0.0; - -		if (boost_tick == AltosLib.MISSING) -			return tick / 100.0; -		return (tick - boost_tick) / 100.0; -	} - -	public boolean valid() { -		return tick != AltosLib.MISSING && serial != AltosLib.MISSING; -	} - -	public void set_temp_gps() { -		set_gps(temp_gps, gps_sequence + 1); -		gps_pending = false; -		super.set_temp_gps(); -	} - -	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()) -			set_ms5607(ms5607); -	} - -	public AltosState clone() { -		AltosState s = new AltosState(); -		s.copy(this); - -		/* Code to test state save/restore. Enable only for that purpose -		 */ -		if (false) { -			AltosJson	json = new AltosJson(this); -			String		onetrip = json.toPrettyString(); -			AltosJson	back = AltosJson.fromString(onetrip); -			AltosState	tripstate = (AltosState) back.make(this.getClass()); -			AltosJson	tripjson = new AltosJson(tripstate); -			String		twotrip = tripjson.toPrettyString(); - -			if (!onetrip.equals(twotrip)) { -				try { -					FileWriter one_file = new FileWriter("one.json", true); -					one_file.write(onetrip); -					one_file.flush(); -					FileWriter two_file = new FileWriter("two.json", true); -					two_file.write(twotrip); -					two_file.flush(); -				} catch (Exception e) { -				} -				System.out.printf("json error\n"); -				System.exit(1); -			} -		} -		return s; -	} - -	public AltosState () { +	public AltosState (AltosCalData cal_data) { +		super(cal_data);  		init();  	}  } diff --git a/altoslib/AltosStateName.java b/altoslib/AltosStateName.java new file mode 100644 index 00000000..a3ac9261 --- /dev/null +++ b/altoslib/AltosStateName.java @@ -0,0 +1,32 @@ +/* + * 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 AltosStateName extends AltosUnits { + +	public double value(double v, boolean imperial_units) { return v; } + +	public double inverse(double v, boolean imperial_units) { return v; } + +	public String string_value(double v, boolean imperial_units) { +		return AltosLib.state_name((int) v); +	} + +	public String show_units(boolean imperial_units) { return "state"; } + +	public String say_units(boolean imperial_units) { return "state"; } + +	public int show_fraction(int width, boolean imperial_units) { return 0; } +} diff --git a/altoslib/AltosTelemetry.java b/altoslib/AltosTelemetry.java index 5600e7be..b810ac83 100644 --- a/altoslib/AltosTelemetry.java +++ b/altoslib/AltosTelemetry.java @@ -24,7 +24,7 @@ import java.text.*;   * Telemetry data contents   */ -public abstract class AltosTelemetry implements AltosStateUpdate { +public abstract class AltosTelemetry implements AltosDataProvider {  	int[]	bytes;  	/* All telemetry packets have these fields */ @@ -46,13 +46,14 @@ public abstract class AltosTelemetry implements AltosStateUpdate {  		return sum == bytes[bytes.length - 1];  	} -	public void update_state(AltosState state) { -		state.set_serial(serial()); -		if (state.state() == AltosLib.ao_flight_invalid) -			state.set_state(AltosLib.ao_flight_startup); -		state.set_tick(tick()); -		state.set_rssi(rssi(), status()); -		state.set_received_time(received_time); +	public void provide_data(AltosDataListener listener, AltosCalData cal_data) { +		cal_data.set_serial(serial()); +		if (listener.state == AltosLib.ao_flight_invalid) +			listener.set_state(AltosLib.ao_flight_startup); +		cal_data.set_tick(tick()); +		listener.set_time(cal_data.time()); +		listener.set_rssi(rssi(), status()); +		listener.set_received_time(received_time);  	}  	final static int PKT_APPEND_STATUS_1_CRC_OK		= (1 << 7); @@ -108,29 +109,6 @@ public abstract class AltosTelemetry implements AltosStateUpdate {  		return telem;  	} -	public static int extend_height(AltosState state, int height_16) { -		double	compare_height; -		int	height = height_16; - -		if (state.gps != null && state.gps.alt != AltosLib.MISSING) { -			compare_height = state.gps_height(); -		} else { -			compare_height = state.height(); -		} - -		if (compare_height != AltosLib.MISSING) { -			int	high_bits = (int) Math.floor (compare_height / 65536.0); - -			height = (high_bits << 16) | (height_16 & 0xffff); - -			if (Math.abs(height + 65536 - compare_height) < Math.abs(height - compare_height)) -				height += 65536; -			else if (Math.abs(height - 65536 - compare_height) < Math.abs(height - compare_height)) -				height -= 65536; -		} -		return height; -	} -  	public AltosTelemetry() {  		this.received_time = System.currentTimeMillis();  	} diff --git a/altoslib/AltosTelemetryCompanion.java b/altoslib/AltosTelemetryCompanion.java index 2c05e245..f3283c32 100644 --- a/altoslib/AltosTelemetryCompanion.java +++ b/altoslib/AltosTelemetryCompanion.java @@ -49,8 +49,8 @@ public class AltosTelemetryCompanion extends AltosTelemetryStandard {  		super(bytes);  	} -	public void update_state(AltosState state) { -		super.update_state(state); -		state.set_companion(companion()); +	public void provide_data(AltosDataListener listener, AltosCalData cal_data) { +		super.provide_data(listener, cal_data); +		listener.set_companion(companion());  	}  } diff --git a/altoslib/AltosTelemetryConfiguration.java b/altoslib/AltosTelemetryConfiguration.java index d91a03fc..920c3187 100644 --- a/altoslib/AltosTelemetryConfiguration.java +++ b/altoslib/AltosTelemetryConfiguration.java @@ -35,17 +35,17 @@ public class AltosTelemetryConfiguration extends AltosTelemetryStandard {  		super(bytes);  	} -	public void update_state(AltosState state) { -		super.update_state(state); -		state.set_device_type(device_type()); -		state.set_flight(flight()); -		state.set_config(config_major(), config_minor(), flight_log_max()); +	public void provide_data(AltosDataListener listener, AltosCalData cal_data) { +		super.provide_data(listener, cal_data); +		cal_data.set_device_type(device_type()); +		cal_data.set_flight(flight()); +		cal_data.set_config(config_major(), config_minor(), flight_log_max());  		if (device_type() == AltosLib.product_telegps) -			state.set_battery_voltage(AltosConvert.tele_gps_voltage(v_batt())); +			listener.set_battery_voltage(AltosConvert.tele_gps_voltage(v_batt()));  		else -			state.set_flight_params(apogee_delay(), main_deploy()); +			cal_data.set_flight_params(apogee_delay() / 100.0, main_deploy()); -		state.set_callsign(callsign()); -		state.set_firmware_version(version()); +		cal_data.set_callsign(callsign()); +		cal_data.set_firmware_version(version());  	}  } diff --git a/altoslib/AltosTelemetryFile.java b/altoslib/AltosTelemetryFile.java index 9c5f8dae..0b0e6a48 100644 --- a/altoslib/AltosTelemetryFile.java +++ b/altoslib/AltosTelemetryFile.java @@ -22,76 +22,112 @@ import java.io.*;  import java.util.*;  import java.text.*; -class AltosTelemetryIterator implements Iterator<AltosState> { -	AltosState			state; -	Iterator<AltosTelemetry>	telems; -	AltosTelemetry			next; -	boolean				seen; - -	public boolean hasNext() { -		return !seen || telems.hasNext(); +class AltosTelemetryNullListener extends AltosDataListener { +	public void set_rssi(int rssi, int status) { } +	public void set_received_time(long received_time) { } + +	public void set_acceleration(double accel) { } +	public void set_pressure(double pa) { } +	public void set_thrust(double N) { } + +	public void set_kalman(double height, double speed, double accel) { } + +	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) { } + +	public void set_gps(AltosGPS gps) { } + +	public void set_orient(double orient) { } +	public void set_gyro(double roll, double pitch, double yaw) { } +	public void set_accel_ground(double along, double across, double through) { } +	public void set_accel(double along, double across, double through) { } +	public void set_mag(double along, double across, double through) { } +	public void set_pyro_voltage(double volts) { } +	public void set_ignitor_voltage(double[] voltage) { } +	public void set_pyro_fired(int pyro_mask) { } +	public void set_companion(AltosCompanion companion) { } + +	public boolean cal_data_complete() { +		/* All telemetry packets */ +		if (cal_data.serial == AltosLib.MISSING) +			return false; + +		if (cal_data.boost_tick == AltosLib.MISSING) +			return false; + +		/* +		 * TelemetryConfiguration: +		 * +		 * device_type, flight, config version, log max, +		 * flight params, callsign and version +		 */ +		if (cal_data.device_type == AltosLib.MISSING) +			return false; + +		/* +		 * TelemetrySensor or TelemetryMegaData: +		 * +		 * ground_accel, accel+/-, ground pressure +		 */ +		if (cal_data.ground_pressure == AltosLib.MISSING) +			return false; + +		/* +		 * TelemetryLocation +		 */ +		if (AltosLib.has_gps(cal_data.device_type) && cal_data.gps_ground_altitude == AltosLib.MISSING) +			return false; + +		return true;  	} -	public AltosState next() { -		if (seen) { -			AltosState	n = state.clone(); -			AltosTelemetry	t = telems.next(); - -			t.update_state(n); -			state = n; -		} -		seen = true; -		return state; -	} - -	public void remove () { -	} - -	public AltosTelemetryIterator(AltosState start, Iterator<AltosTelemetry> telems) { -		this.state = start; -		this.telems = telems; -		this.seen = false; +	public AltosTelemetryNullListener(AltosCalData cal_data) { +		super(cal_data);  	}  } -public class AltosTelemetryFile extends AltosStateIterable { +public class AltosTelemetryFile implements AltosRecordSet {  	AltosTelemetryIterable	telems; -	AltosState		start; +	AltosCalData		cal_data;  	public void write_comments(PrintStream out) {  	}  	public void write(PrintStream out) { -  	} -	public AltosTelemetryFile(FileInputStream input) { -		telems = new AltosTelemetryIterable(input); -		start = new AltosState(); - -		/* Find boost tick */ -		AltosState	state = start.clone(); +	/* Construct cal data by walking through the telemetry data until we've found everything available */ +	public AltosCalData cal_data() { +		if (cal_data == null) { +			cal_data = new AltosCalData(); +			AltosTelemetryNullListener l = new AltosTelemetryNullListener(cal_data); -		for (AltosTelemetry telem : telems) { -			telem.update_state(state); -			state.finish_update(); -			if (state.state() != AltosLib.ao_flight_invalid && state.state() >= AltosLib.ao_flight_boost) { -				start.set_boost_tick(state.tick); -				break; +			for (AltosTelemetry telem : telems) { +				telem.provide_data(l, cal_data); +				if (l.cal_data_complete()) +					break;  			} +			System.out.printf("Telemetry boost tick %d\n", cal_data.boost_tick);  		} +		return cal_data;  	} -	public Iterator<AltosState> iterator() { -		AltosState			state = start.clone(); -		Iterator<AltosTelemetry>  	i = telems.iterator(); +	public void capture_series(AltosDataListener listener) { +		AltosCalData	cal_data = cal_data(); -		while (i.hasNext() && !state.valid()) { -			AltosTelemetry	t = i.next(); -			t.update_state(state); -			state.finish_update(); +		for (AltosTelemetry telem : telems) { +			int tick = telem.tick(); +			cal_data.set_tick(tick); +			if (cal_data.time() >= -1) +				telem.provide_data(listener, cal_data);  		} -		return new AltosTelemetryIterator(state, i); +	} + +	public AltosTelemetryFile(FileInputStream input) { +		telems = new AltosTelemetryIterable(input);  	}  } diff --git a/altoslib/AltosTelemetryLegacy.java b/altoslib/AltosTelemetryLegacy.java index 2907f111..394d023c 100644 --- a/altoslib/AltosTelemetryLegacy.java +++ b/altoslib/AltosTelemetryLegacy.java @@ -548,23 +548,25 @@ public class AltosTelemetryLegacy extends AltosTelemetry {  		}  	} -	public void update_state(AltosState state) { -		state.set_tick(tick); -		state.set_state(this.state); -		state.set_flight(flight); -		state.set_serial(serial); -		state.set_rssi(rssi, status); - -		state.set_pressure(AltosConvert.barometer_to_pressure(pres)); -		state.set_accel_g(accel_plus_g, accel_minus_g); -		state.set_accel(accel); +	public void provide_data(AltosDataListener listener, AltosCalData cal_data) { +		cal_data.set_tick(tick); +		listener.set_time(cal_data.time()); +		listener.set_state(this.state); +		cal_data.set_state(this.state); +		cal_data.set_flight(flight); +		cal_data.set_serial(serial); +		listener.set_rssi(rssi, status); + +		listener.set_pressure(AltosConvert.barometer_to_pressure(pres)); +		cal_data.set_accel_plus_minus(accel_plus_g, accel_minus_g); +		listener.set_acceleration(cal_data.acceleration(accel));  		if (kalman_height != AltosLib.MISSING) -			state.set_kalman(kalman_height, kalman_speed, kalman_acceleration); -		state.set_temperature(AltosConvert.thermometer_to_temperature(temp)); -		state.set_battery_voltage(AltosConvert.cc_battery_to_voltage(batt)); -		state.set_apogee_voltage(AltosConvert.cc_ignitor_to_voltage(apogee)); -		state.set_main_voltage(AltosConvert.cc_ignitor_to_voltage(main)); +			listener.set_kalman(kalman_height, kalman_speed, kalman_acceleration); +		listener.set_temperature(AltosConvert.thermometer_to_temperature(temp)); +		listener.set_battery_voltage(AltosConvert.cc_battery_to_voltage(batt)); +		listener.set_apogee_voltage(AltosConvert.cc_ignitor_to_voltage(apogee)); +		listener.set_main_voltage(AltosConvert.cc_ignitor_to_voltage(main));  		if (gps != null) -			state.set_gps(gps, gps_sequence); +			listener.set_gps(gps);  	}  } diff --git a/altoslib/AltosTelemetryLocation.java b/altoslib/AltosTelemetryLocation.java index 8ad23ab6..5eb727d6 100644 --- a/altoslib/AltosTelemetryLocation.java +++ b/altoslib/AltosTelemetryLocation.java @@ -49,9 +49,10 @@ public class AltosTelemetryLocation extends AltosTelemetryStandard {  		super(bytes);  	} -	public void update_state(AltosState state) { -		super.update_state(state); -		AltosGPS	gps = state.make_temp_gps(false); +	public void provide_data(AltosDataListener listener, AltosCalData cal_data) { +		super.provide_data(listener, cal_data); + +		AltosGPS	gps = new AltosGPS();  		int flags = flags();  		gps.nsat = flags & 0xf; @@ -74,7 +75,10 @@ public class AltosTelemetryLocation extends AltosTelemetryStandard {  			gps.pdop = pdop() / 10.0;  			gps.hdop = hdop() / 10.0;  			gps.vdop = vdop() / 10.0; + +			if (gps.nsat >= 4) +				cal_data.set_gps_altitude(gps.alt);  		} -		state.set_temp_gps(); +		listener.set_gps(gps);  	}  } diff --git a/altoslib/AltosTelemetryMegaData.java b/altoslib/AltosTelemetryMegaData.java index 916f1e94..c0749e87 100644 --- a/altoslib/AltosTelemetryMegaData.java +++ b/altoslib/AltosTelemetryMegaData.java @@ -39,34 +39,34 @@ public class AltosTelemetryMegaData extends AltosTelemetryStandard {  		super(bytes);  	} -	public void update_state(AltosState state) { -		super.update_state(state); +	public void provide_data(AltosDataListener listener, AltosCalData cal_data) { +		super.provide_data(listener, cal_data); -		state.set_state(state()); +		listener.set_state(state()); +		cal_data.set_state(state()); -		state.set_battery_voltage(AltosConvert.mega_battery_voltage(v_batt())); -		state.set_pyro_voltage(AltosConvert.mega_pyro_voltage(v_pyro())); +		listener.set_battery_voltage(AltosConvert.mega_battery_voltage(v_batt())); +		listener.set_pyro_voltage(AltosConvert.mega_pyro_voltage(v_pyro())); -		state.set_apogee_voltage(AltosConvert.mega_pyro_voltage(sense(4))); -		state.set_main_voltage(AltosConvert.mega_pyro_voltage(sense(5))); +		listener.set_apogee_voltage(AltosConvert.mega_pyro_voltage(sense(4))); +		listener.set_main_voltage(AltosConvert.mega_pyro_voltage(sense(5)));  		double voltages[] = new double[4];  		for (int i = 0; i < 4; i++)  			voltages[i] = AltosConvert.mega_pyro_voltage(sense(i)); -		state.set_ignitor_voltage(voltages); +		listener.set_ignitor_voltage(voltages); -		state.set_ground_accel(ground_accel()); -		state.set_ground_pressure(ground_pres()); -		state.set_accel_g(accel_plus_g(), accel_minus_g()); +		cal_data.set_ground_accel(ground_accel()); +		cal_data.set_ground_pressure(ground_pres()); +		cal_data.set_accel_plus_minus(accel_plus_g(), accel_minus_g());  		/* Fill in the high bits of height from recent GPS  		 * data if available, otherwise guess using the  		 * previous kalman height  		 */ -		state.set_kalman(extend_height(state, height_16()), -				 speed()/16.0, acceleration() / 16.0); +		listener.set_kalman(height_16(), speed()/16.0, acceleration() / 16.0);  	}  } diff --git a/altoslib/AltosTelemetryMegaSensor.java b/altoslib/AltosTelemetryMegaSensor.java index bf560e92..396bdb16 100644 --- a/altoslib/AltosTelemetryMegaSensor.java +++ b/altoslib/AltosTelemetryMegaSensor.java @@ -41,22 +41,41 @@ public class AltosTelemetryMegaSensor extends AltosTelemetryStandard {  		super(bytes);  	} -	public void update_state(AltosState state) { -		super.update_state(state); +	public void provide_data(AltosDataListener listener, AltosCalData cal_data) { +		super.provide_data(listener, cal_data); -		state.set_accel(accel()); -		state.set_pressure(pres()); -		state.set_temperature(temp() / 100.0); +		listener.set_acceleration(cal_data.acceleration(accel())); +		listener.set_pressure(pres()); +		listener.set_temperature(temp() / 100.0); -		state.set_orient(orient()); +		listener.set_orient(orient()); -		state.set_imu(new AltosIMU(accel_y(),	/* along */ -					   accel_x(),	/* across */ -					   accel_z(),	/* through */ -					   gyro_y(),	/* along */ -					   gyro_x(),	/* across */ -					   gyro_z()));	/* through */ +		/* XXX we have no calibration data for these values */ -		state.set_mag(new AltosMag(mag_x(), mag_y(), mag_z())); +		if (cal_data.accel_zero_along == AltosLib.MISSING) +			cal_data.set_accel_zero(0, 0, 0); +		if (cal_data.gyro_zero_roll == AltosLib.MISSING) +			cal_data.set_gyro_zero(0, 0, 0); + +		int	accel_along = accel_y(); +		int	accel_across = accel_x(); +		int	accel_through = accel_z(); +		int	gyro_roll = gyro_y(); +		int	gyro_pitch = gyro_x(); +		int	gyro_yaw = gyro_z(); + +		int	mag_along = mag_x(); +		int	mag_across = mag_y(); +		int	mag_through = mag_z(); + +		listener.set_accel(cal_data.accel_along(accel_along), +				   cal_data.accel_across(accel_across), +				   cal_data.accel_through(accel_through)); +		listener.set_gyro(cal_data.gyro_roll(gyro_roll), +				  cal_data.gyro_pitch(gyro_pitch), +				  cal_data.gyro_yaw(gyro_yaw)); +		listener.set_mag(cal_data.mag_along(mag_along), +				 cal_data.mag_across(mag_across), +				 cal_data.mag_through(mag_through));  	}  } diff --git a/altoslib/AltosTelemetryMetrumData.java b/altoslib/AltosTelemetryMetrumData.java index 7ba591ed..21c60c75 100644 --- a/altoslib/AltosTelemetryMetrumData.java +++ b/altoslib/AltosTelemetryMetrumData.java @@ -30,9 +30,9 @@ public class AltosTelemetryMetrumData extends AltosTelemetryStandard {  		super(bytes);  	} -	public void update_state(AltosState state) { -		state.set_ground_accel(ground_accel()); -		state.set_accel_g(accel_plus_g(), accel_minus_g()); -		state.set_ground_pressure(ground_pres()); +	public void provide_data(AltosDataListener listener, AltosCalData cal_data) { +		cal_data.set_ground_accel(ground_accel()); +		cal_data.set_accel_plus_minus(accel_plus_g(), accel_minus_g()); +		cal_data.set_ground_pressure(ground_pres());  	}  } diff --git a/altoslib/AltosTelemetryMetrumSensor.java b/altoslib/AltosTelemetryMetrumSensor.java index e666f4ec..e003c831 100644 --- a/altoslib/AltosTelemetryMetrumSensor.java +++ b/altoslib/AltosTelemetryMetrumSensor.java @@ -38,21 +38,21 @@ public class AltosTelemetryMetrumSensor extends AltosTelemetryStandard {  		super(bytes);  	} -	public void update_state(AltosState state) { -		super.update_state(state); +	public void provide_data(AltosDataListener listener, AltosCalData cal_data) { +		super.provide_data(listener, cal_data); -		state.set_state(state()); +		listener.set_state(state()); +		cal_data.set_state(state()); -		state.set_accel(accel()); -		state.set_pressure(pres()); -		state.set_temperature(temp()/100.0); +		listener.set_acceleration(cal_data.acceleration(accel())); +		listener.set_pressure(pres()); +		listener.set_temperature(temp()/100.0); -		state.set_kalman(extend_height(state, height_16()), -				 speed()/16.0, acceleration()/16.0); +		listener.set_kalman(height_16(), speed()/16.0, acceleration()/16.0); -		state.set_battery_voltage(AltosConvert.mega_battery_voltage(v_batt())); +		listener.set_battery_voltage(AltosConvert.mega_battery_voltage(v_batt())); -		state.set_apogee_voltage(AltosConvert.mega_pyro_voltage(sense_a())); -		state.set_main_voltage(AltosConvert.mega_pyro_voltage(sense_m())); +		listener.set_apogee_voltage(AltosConvert.mega_pyro_voltage(sense_a())); +		listener.set_main_voltage(AltosConvert.mega_pyro_voltage(sense_m()));  	}  } diff --git a/altoslib/AltosTelemetryMini2.java b/altoslib/AltosTelemetryMini2.java index bc151139..02d1c757 100644 --- a/altoslib/AltosTelemetryMini2.java +++ b/altoslib/AltosTelemetryMini2.java @@ -40,20 +40,21 @@ public class AltosTelemetryMini2 extends AltosTelemetryStandard {  		super(bytes);  	} -	public void update_state(AltosState state) { -		super.update_state(state); +	public void provide_data(AltosDataListener listener, AltosCalData cal_data) { +		super.provide_data(listener, cal_data); -		state.set_state(state()); +		listener.set_state(state()); +		cal_data.set_state(state()); -		state.set_battery_voltage(AltosConvert.tele_mini_2_voltage(v_batt())); -		state.set_apogee_voltage(AltosConvert.tele_mini_2_voltage(sense_a())); -		state.set_main_voltage(AltosConvert.tele_mini_2_voltage(sense_m())); +		listener.set_battery_voltage(AltosConvert.tele_mini_2_voltage(v_batt())); +		listener.set_apogee_voltage(AltosConvert.tele_mini_2_voltage(sense_a())); +		listener.set_main_voltage(AltosConvert.tele_mini_2_voltage(sense_m())); -		state.set_ground_pressure(ground_pres()); +		cal_data.set_ground_pressure(ground_pres()); -		state.set_pressure(pres()); -		state.set_temperature(temp()/100.0); +		listener.set_pressure(pres()); +		listener.set_temperature(temp()/100.0); -		state.set_kalman(height(), speed()/16.0, acceleration()/16.0); +		listener.set_kalman(height(), speed()/16.0, acceleration()/16.0);  	}  } diff --git a/altoslib/AltosTelemetryMini3.java b/altoslib/AltosTelemetryMini3.java index b8a507cc..1d627668 100644 --- a/altoslib/AltosTelemetryMini3.java +++ b/altoslib/AltosTelemetryMini3.java @@ -40,22 +40,22 @@ public class AltosTelemetryMini3 extends AltosTelemetryStandard {  		super(bytes);  	} -	public void update_state(AltosState state) { -		super.update_state(state); +	public void provide_data(AltosDataListener listener, AltosCalData cal_data) { +		super.provide_data(listener, cal_data); -		state.set_state(state()); +		cal_data.set_ground_pressure(ground_pres()); -		state.set_battery_voltage(AltosConvert.tele_mini_3_battery_voltage(v_batt())); +		listener.set_state(state()); +		cal_data.set_state(state()); -		state.set_apogee_voltage(AltosConvert.tele_mini_3_pyro_voltage(sense_a())); -		state.set_main_voltage(AltosConvert.tele_mini_3_pyro_voltage(sense_m())); +		listener.set_battery_voltage(AltosConvert.tele_mini_3_battery_voltage(v_batt())); -		state.set_pressure(pres()); -		state.set_temperature(temp()/100.0); +		listener.set_apogee_voltage(AltosConvert.tele_mini_3_pyro_voltage(sense_a())); +		listener.set_main_voltage(AltosConvert.tele_mini_3_pyro_voltage(sense_m())); -		state.set_kalman(extend_height(state, height_16()), -				 speed()/16.0, acceleration()/16.0); +		listener.set_pressure(pres()); +		listener.set_temperature(temp()/100.0); -		state.set_ground_pressure(ground_pres()); +		listener.set_kalman(height_16(), speed()/16.0, acceleration()/16.0);  	}  } diff --git a/altoslib/AltosTelemetryRaw.java b/altoslib/AltosTelemetryRaw.java index 12c4623b..a7d3a2ca 100644 --- a/altoslib/AltosTelemetryRaw.java +++ b/altoslib/AltosTelemetryRaw.java @@ -23,7 +23,7 @@ public class AltosTelemetryRaw extends AltosTelemetryStandard {  		super(bytes);  	} -	public void update_state(AltosState state) { -		super.update_state(state); +	public void provide_data(AltosDataListener listener, AltosCalData cal_data) { +		super.provide_data(listener, cal_data);  	}  } diff --git a/altoslib/AltosTelemetryReader.java b/altoslib/AltosTelemetryReader.java index 6a93c2c3..96113613 100644 --- a/altoslib/AltosTelemetryReader.java +++ b/altoslib/AltosTelemetryReader.java @@ -28,7 +28,8 @@ public class AltosTelemetryReader extends AltosFlightReader {  	double		frequency;  	int		telemetry;  	int		telemetry_rate; -	AltosState	state = null; +	public AltosState	state = null; +	public AltosCalData	cal_data = null;  	LinkedBlockingQueue<AltosLine> telem; @@ -40,11 +41,11 @@ public class AltosTelemetryReader extends AltosFlightReader {  				throw new IOException("IO error");  		} while (!link.get_monitor());  		AltosTelemetry	telem = AltosTelemetry.parse(l.line); +		if (cal_data == null) +			cal_data = new AltosCalData();  		if (state == null) -			state = new AltosState(); -		else -			state = state.clone(); -		telem.update_state(state); +			state = new AltosState(cal_data); +		telem.provide_data(state, cal_data);  		return state;  	} @@ -55,6 +56,7 @@ public class AltosTelemetryReader extends AltosFlightReader {  	public void reset() {  		flush();  		state = null; +		cal_data = null;  	}  	public void close(boolean interrupted) { diff --git a/altoslib/AltosTelemetryRecordSet.java b/altoslib/AltosTelemetryRecordSet.java new file mode 100644 index 00000000..0cb95261 --- /dev/null +++ b/altoslib/AltosTelemetryRecordSet.java @@ -0,0 +1,97 @@ +/* + * 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.io.*; +import java.util.*; + +public class AltosTelemetryRecordSet implements AltosRecordSet { +	AltosTelemetry			telemetry; +	TreeSet<AltosTelemetryRecord>	ordered; + +	public void capture_series(AltosDataListener series) { +		for (AltosTelemetryRecord record : ordered) { +			record.update_state(series); +		} +	} + +	public AltosTelemetryRecordSet(AltosTelemetry telemetry) { +		this.telemetry = telemetry; + +		AltosTelemetryRecord	record = null; + +		switch (config_data.log_format) { +		case AltosLib.AO_LOG_FORMAT_FULL: +			record = new AltosTelemetryRecordFull(eeprom); +			break; +		case AltosLib.AO_LOG_FORMAT_TINY: +			record = new AltosTelemetryRecordTiny(eeprom); +			break; +		case AltosLib.AO_LOG_FORMAT_TELEMETRY: +		case AltosLib.AO_LOG_FORMAT_TELESCIENCE: +		case AltosLib.AO_LOG_FORMAT_TELEMEGA: +		case AltosLib.AO_LOG_FORMAT_TELEMEGA_OLD: +			record = new AltosTelemetryRecordMega(eeprom); +			break; +		case AltosLib.AO_LOG_FORMAT_TELEMETRUM: +			record = new AltosTelemetryRecordMetrum(eeprom); +			break; +		case AltosLib.AO_LOG_FORMAT_TELEMINI2: +		case AltosLib.AO_LOG_FORMAT_TELEMINI3: +		case AltosLib.AO_LOG_FORMAT_EASYMINI: +			record = new AltosTelemetryRecordMini(eeprom); +			break; +		case AltosLib.AO_LOG_FORMAT_TELEGPS: +			record = new AltosTelemetryRecordGps(eeprom); +			break; +		case AltosLib.AO_LOG_FORMAT_TELEFIRETWO: +			record = new AltosTelemetryRecordFireTwo(eeprom); +			break; +		} + +		if (record == null) { +			System.out.printf("failed to parse log format %d\n", config_data.log_format); +			return; +		} +		ordered = new TreeSet<AltosTelemetryRecord>(); +		int	tick = 0; +		boolean first = true; + +		start_state = new AltosState(); +		start_state.set_config_data(record.eeprom.config_data()); + +		for (;;) { +			int	t = record.tick(); + +			if (first) { +				tick = t; +				first = false; +			} else { +				while (t < tick - 32767) +					t += 65536; +				tick = t; +			} +			record.wide_tick = tick; +			ordered.add(record); +			if (!record.hasNext()) +				break; +			record = record.next(); +		} +	} + +	public AltosTelemetryRecordSet(Reader input) throws IOException { +		this(new AltosTelemetryNew(input)); +	} +} diff --git a/altoslib/AltosTelemetrySatellite.java b/altoslib/AltosTelemetrySatellite.java index ce12d32d..72ddd964 100644 --- a/altoslib/AltosTelemetrySatellite.java +++ b/altoslib/AltosTelemetrySatellite.java @@ -44,12 +44,12 @@ public class AltosTelemetrySatellite extends AltosTelemetryStandard {  		super(bytes);  	} -	public void update_state(AltosState state) { -		super.update_state(state); +	public void provide_data(AltosDataListener listener, AltosCalData cal_data) { +		super.provide_data(listener, cal_data); -		AltosGPS	gps = state.make_temp_gps(true); +		AltosGPS	gps = new AltosGPS();  		gps.cc_gps_sat = sats(); -		state.set_temp_gps(); +		listener.set_gps(gps);  	}  } diff --git a/altoslib/AltosTelemetrySensor.java b/altoslib/AltosTelemetrySensor.java index b669b9e6..37589397 100644 --- a/altoslib/AltosTelemetrySensor.java +++ b/altoslib/AltosTelemetrySensor.java @@ -41,24 +41,26 @@ public class AltosTelemetrySensor extends AltosTelemetryStandard {  		super(bytes);  	} -	public void update_state(AltosState state) { -		super.update_state(state); +	public void provide_data(AltosDataListener listener, AltosCalData cal_data) { +		super.provide_data(listener, cal_data); + +		listener.set_state(state()); +		cal_data.set_state(state()); -		state.set_state(state());  		if (type() == packet_type_TM_sensor) { -			state.set_ground_accel(ground_accel()); -			state.set_accel_g(accel_plus_g(), accel_minus_g()); -			state.set_accel(accel()); +			cal_data.set_ground_accel(ground_accel()); +			cal_data.set_accel_plus_minus(accel_plus_g(), accel_minus_g()); +			listener.set_acceleration(cal_data.acceleration(accel()));  		} -		state.set_ground_pressure(AltosConvert.barometer_to_pressure(ground_pres())); -		state.set_pressure(AltosConvert.barometer_to_pressure(pres())); -		state.set_temperature(AltosConvert.thermometer_to_temperature(temp())); -		state.set_battery_voltage(AltosConvert.cc_battery_to_voltage(v_batt())); +		cal_data.set_ground_pressure(AltosConvert.barometer_to_pressure(ground_pres())); +		listener.set_pressure(AltosConvert.barometer_to_pressure(pres())); +		listener.set_temperature(AltosConvert.thermometer_to_temperature(temp())); +		listener.set_battery_voltage(AltosConvert.cc_battery_to_voltage(v_batt()));  		if (type() == packet_type_TM_sensor || type() == packet_type_Tm_sensor) { -			state.set_apogee_voltage(AltosConvert.cc_ignitor_to_voltage(sense_d())); -			state.set_main_voltage(AltosConvert.cc_ignitor_to_voltage(sense_m())); +			listener.set_apogee_voltage(AltosConvert.cc_ignitor_to_voltage(sense_d())); +			listener.set_main_voltage(AltosConvert.cc_ignitor_to_voltage(sense_m()));  		} -		state.set_kalman(height_16(), speed()/16.0, acceleration()/16.0); +		listener.set_kalman(height_16(), speed()/16.0, acceleration()/16.0);  	}  } diff --git a/altoslib/AltosTelemetryStandard.java b/altoslib/AltosTelemetryStandard.java index 1718e4b7..4429c49a 100644 --- a/altoslib/AltosTelemetryStandard.java +++ b/altoslib/AltosTelemetryStandard.java @@ -104,7 +104,7 @@ public abstract class AltosTelemetryStandard extends AltosTelemetry {  		super(bytes);  	} -	public void update_state(AltosState state) { -		super.update_state(state); +	public void provide_data(AltosDataListener listener, AltosCalData cal_data) { +		super.provide_data(listener, cal_data);  	}  } diff --git a/altoslib/AltosTimeSeries.java b/altoslib/AltosTimeSeries.java index 0ea7b356..1d3d9a6c 100644 --- a/altoslib/AltosTimeSeries.java +++ b/altoslib/AltosTimeSeries.java @@ -21,68 +21,142 @@ public class AltosTimeSeries implements Iterable<AltosTimeValue> {  	public AltosUnits	units;  	List<AltosTimeValue>	values; -	public void add(double x, double y) { -		values.add(new AltosTimeValue(x, y)); +	public void add(AltosTimeValue tv) { +		values.add(tv); +	} + +	public void add(double time, double value) { +		add(new AltosTimeValue(time, value)); +	} + +	public AltosTimeValue get(int i) { +		return values.get(i); +	} + +	public int size() { +		return values.size();  	}  	public Iterator<AltosTimeValue> iterator() {  		return values.iterator();  	} -	public void integrate(AltosTimeSeries integral) { -		double	y = 0.0; -		double 	x = 0.0; +	public double max() { +		double max = AltosLib.MISSING; +		for (AltosTimeValue tv : values) { +			if (max == AltosLib.MISSING || tv.value > max) +				max = tv.value; +		} +		return max; +	} + +	public double min() { +		double min = AltosLib.MISSING; +		for (AltosTimeValue tv : values) { +			if (min == AltosLib.MISSING || tv.value < min) +				min = tv.value; +		} +		return min; +	} + +	public AltosTimeSeries integrate(AltosTimeSeries integral) { +		double	value = 0.0; +		double	pvalue = 0.0; +		double 	time = 0.0;  		boolean start = true;  		for (AltosTimeValue v : values) {  			if (start) { -				y = 0.0; -				x = v.x; +				value = 0.0;  				start = false;  			} else { -				y += v.y * (v.x - x); -				x = v.x; +				value += (pvalue + v.value) / 2.0 * (v.time - time);  			} -			integral.add(x, y); +			pvalue = v.value; +			time = v.time; +//			System.out.printf("%g %g %g\n", time, v.value, value); +			integral.add(time, value); +  		} +		return integral;  	} -	public void differentiate(AltosTimeSeries diff) { -		double y = 0.0; -		double x = 0.0; +	public AltosTimeSeries differentiate(AltosTimeSeries diff) { +		double value = 0.0; +		double time = 0.0;  		boolean start = true;  		for (AltosTimeValue v: values) {  			if (start) { -				y = 0.0; -				x = v.x; +				value = v.value; +				time = v.time;  				start = false;  			} else { -				double	dx = v.x - x; -				double	dy = v.y - y; +				double	dx = v.time - time; +				double	dy = v.value - value; -				x = v.x; -				y = v.y;  				if (dx != 0) -					diff.add(x, dy); +					diff.add(time, dy/dx); + +				time = v.time; +				value = v.value;  			}  		} +		return diff;  	}  	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) +		double t = values.get(i).time - dt; +		for (j = i; j >= 0; j--)	{ +			if (values.get(j).time < t) +				break; +		} +		return j + 1; + +	} + +	private int find_right(int i, double dt) { +		int j; +		double t = values.get(i).time + dt; +		for (j = i; j < values.size(); j++) { +			if (values.get(j).time > t)  				break;  		} -		return j; +		return j - 1;  	} -	public void filter(AltosTimeSeries out, double width) { +	private double filter_coeff(double dist, double width) { +		double ratio = dist / (width / 2); + +		return Math.cos(ratio * Math.PI / 2); +	} + +	public AltosTimeSeries filter(AltosTimeSeries f, double width) { +		double	half_width = width/2;  		for (int i = 0; i < values.size(); i++) { +			double	center_time = values.get(i).time; +			double	left_time = center_time - half_width; +			double	right_time = center_time + half_width; +			double	total_coeff = 0.0; +			double	total_value = 0.0; + +			int	left = find_left(i, half_width); +			int	right = find_right(i, half_width); +			for (int j = left; j <= right; j++) { +				double	j_time = values.get(j).time; + +				if (left_time <= j_time && j_time <= right_time) { +					double	coeff = filter_coeff(j_time - center_time, width); +					total_coeff += coeff; +					total_value += coeff * values.get(j).value; +				} +			} +			if (total_coeff != 0.0) +				f.add(center_time, total_value / total_coeff);  		} +		return f;  	}  	public AltosTimeSeries(String label, AltosUnits units) { diff --git a/altoslib/AltosTimeValue.java b/altoslib/AltosTimeValue.java index 50212361..489050f2 100644 --- a/altoslib/AltosTimeValue.java +++ b/altoslib/AltosTimeValue.java @@ -18,10 +18,11 @@  package org.altusmetrum.altoslib_11;  public class AltosTimeValue { -	public double	x, y; +	public double	time; +	public double	value; -	public AltosTimeValue(double x, double y) { -		this.x = x; -		this.y = y; +	public AltosTimeValue(double time, double value) { +		this.time = time; +		this.value = value;  	}  } diff --git a/altoslib/AltosUnits.java b/altoslib/AltosUnits.java index 717a106a..7744cdb4 100644 --- a/altoslib/AltosUnits.java +++ b/altoslib/AltosUnits.java @@ -41,6 +41,10 @@ public abstract class AltosUnits {  	public abstract double inverse(double v, boolean imperial_units); +	public String string_value(double v, boolean imperial_units) { +		return new Double(value(v, imperial_units)).toString(); +	} +  	public abstract String show_units(boolean imperial_units);  	public abstract String say_units(boolean imperial_units); @@ -113,6 +117,10 @@ public abstract class AltosUnits {  		return say_units(v, AltosConvert.imperial_units);  	} +	public String string_value(double v) { +		return string_value(v, AltosConvert.imperial_units); +	} +  	/* Parsing functions. Use the first range of the type */  	public String parse_units(boolean imperial_units) {  		return first_range(imperial_units).show_units; diff --git a/altoslib/AltosWriter.java b/altoslib/AltosWriter.java index 691dc4de..717f1a8f 100644 --- a/altoslib/AltosWriter.java +++ b/altoslib/AltosWriter.java @@ -20,7 +20,7 @@ package org.altusmetrum.altoslib_11;  public interface AltosWriter { -	public void write(AltosStateIterable states); +	public void write(AltosFlightSeries series);  	public void close();  } diff --git a/altoslib/Makefile.am b/altoslib/Makefile.am index 1b37215c..fa0e8c1b 100644 --- a/altoslib/Makefile.am +++ b/altoslib/Makefile.am @@ -26,6 +26,7 @@ record_files = \  altoslib_JAVA = \  	AltosLib.java \ +	AltosCalData.java \  	AltosCompanion.java \  	AltosConfigData.java \  	AltosConfigDataException.java \ @@ -55,13 +56,15 @@ altoslib_JAVA = \  	AltosFile.java \  	AltosFlash.java \  	AltosFlashListener.java \ -	AltosFlightListener.java \ +	AltosDataListener.java \ +	AltosDataProvider.java \  	AltosFlightSeries.java \  	AltosFlightReader.java \  	AltosFlightStats.java \  	AltosForce.java \  	AltosFrequency.java \  	AltosGPS.java \ +	AltosGPSTimeValue.java \  	AltosGPSSat.java \  	AltosGreatCircle.java \  	AltosHexfile.java \ @@ -85,6 +88,7 @@ altoslib_JAVA = \  	AltosOrient.java \  	AltosParse.java \  	AltosPressure.java \ +	AltosPresTemp.java \  	AltosPreferences.java \  	AltosPreferencesBackend.java \  	AltosProgrammer.java \ @@ -101,8 +105,7 @@ altoslib_JAVA = \  	AltosSensorMetrum.java \  	AltosSensorTGPS.java \  	AltosState.java \ -	AltosStateIterable.java \ -	AltosStateUpdate.java \ +	AltosStateName.java \  	AltosTelemetry.java \  	AltosTelemetryConfiguration.java \  	AltosTelemetryCompanion.java \ | 
