diff options
author | Keith Packard <keithp@keithp.com> | 2014-05-22 18:46:58 -0700 |
---|---|---|
committer | Keith Packard <keithp@keithp.com> | 2014-05-22 18:46:58 -0700 |
commit | b60a3689910731d9bdb8a431a3dcc9e99f961b35 (patch) | |
tree | b40fdb9c02fb4b79ffb76a12f55b93c56f0b4c39 /altoslib/AltosCSV.java | |
parent | 2625a464417c8475c66101757ca2c30cd6c74e0c (diff) |
altoslib: Move CSV/KML output code to altoslib
It's sharable, so share it
Signed-off-by: Keith Packard <keithp@keithp.com>
Diffstat (limited to 'altoslib/AltosCSV.java')
-rw-r--r-- | altoslib/AltosCSV.java | 334 |
1 files changed, 334 insertions, 0 deletions
diff --git a/altoslib/AltosCSV.java b/altoslib/AltosCSV.java new file mode 100644 index 00000000..8176d21b --- /dev/null +++ b/altoslib/AltosCSV.java @@ -0,0 +1,334 @@ +/* + * Copyright © 2010 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_3; + +import java.io.*; +import java.util.*; + +public class AltosCSV implements AltosWriter { + File name; + PrintStream out; + boolean header_written; + boolean seen_boost; + int boost_tick; + LinkedList<AltosState> pad_states; + AltosState state; + + static final int ALTOS_CSV_VERSION = 5; + + /* Version 4 format: + * + * General info + * version number + * serial number + * flight number + * callsign + * time (seconds since boost) + * clock (tick count / 100) + * rssi + * link quality + * + * Flight status + * state + * state name + * + * Basic sensors + * acceleration (m/s²) + * pressure (mBar) + * altitude (m) + * height (m) + * accelerometer speed (m/s) + * barometer speed (m/s) + * temp (°C) + * battery (V) + * drogue (V) + * main (V) + * + * Advanced sensors (if available) + * accel_x (m/s²) + * accel_y (m/s²) + * accel_z (m/s²) + * gyro_x (d/s) + * gyro_y (d/s) + * gyro_z (d/s) + * mag_x (g) + * mag_y (g) + * mag_z (g) + * + * GPS data (if available) + * connected (1/0) + * locked (1/0) + * nsat (used for solution) + * latitude (°) + * longitude (°) + * altitude (m) + * year (e.g. 2010) + * month (1-12) + * day (1-31) + * hour (0-23) + * minute (0-59) + * second (0-59) + * from_pad_dist (m) + * from_pad_azimuth (deg true) + * from_pad_range (m) + * from_pad_elevation (deg from horizon) + * hdop + * + * GPS Sat data + * C/N0 data for all 32 valid SDIDs + * + * Companion data + * companion_id (1-255. 10 is TeleScience) + * time of last companion data (seconds since boost) + * update_period (0.1-2.55 minimum telemetry interval) + * channels (0-12) + * channel data for all 12 possible channels + */ + + void write_general_header() { + out.printf("version,serial,flight,call,time,clock,rssi,lqi"); + } + + void write_general(AltosState state) { + out.printf("%s, %d, %d, %s, %8.2f, %8.2f, %4d, %3d", + ALTOS_CSV_VERSION, state.serial, state.flight, state.callsign, + (double) state.time, (double) state.tick / 100.0, + state.rssi, + state.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()); + } + + void write_basic_header() { + out.printf("acceleration,pressure,altitude,height,accel_speed,baro_speed,temperature,battery_voltage,drogue_voltage,main_voltage"); + } + + void write_basic(AltosState state) { + out.printf("%8.2f,%10.2f,%8.2f,%8.2f,%8.2f,%8.2f,%5.1f,%5.2f,%5.2f,%5.2f", + state.acceleration(), + state.pressure(), + state.altitude(), + state.height(), + state.speed(), + state.speed(), + state.temperature, + state.battery_voltage, + state.apogee_voltage, + state.main_voltage); + } + + void write_advanced_header() { + out.printf("accel_x,accel_y,accel_z,gyro_x,gyro_y,gyro_z"); + } + + void write_advanced(AltosState state) { + AltosIMU imu = state.imu; + AltosMag mag = state.mag; + + if (imu == null) + imu = new AltosIMU(); + if (mag == null) + mag = new AltosMag(); + out.printf("%6d,%6d,%6d,%6d,%6d,%6d,%6d,%6d,%6d", + imu.accel_x, imu.accel_y, imu.accel_z, + imu.gyro_x, imu.gyro_y, imu.gyro_z, + mag.x, mag.y, mag.z); + } + + 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,hdop"); + } + + void write_gps(AltosState state) { + AltosGPS gps = state.gps; + if (gps == null) + gps = new AltosGPS(); + + AltosGreatCircle from_pad = state.from_pad; + if (from_pad == null) + from_pad = new AltosGreatCircle(); + + out.printf("%2d,%2d,%3d,%12.7f,%12.7f,%8.1f,%5d,%3d,%3d,%3d,%3d,%3d,%9.0f,%9.0f,%4.0f,%4.0f,%6.1f", + gps.connected?1:0, + gps.locked?1:0, + gps.nsat, + gps.lat, + gps.lon, + gps.alt, + gps.year, + gps.month, + gps.day, + gps.hour, + gps.minute, + gps.second, + from_pad.distance, + state.range, + from_pad.bearing, + state.elevation, + gps.hdop); + } + + void write_gps_sat_header() { + for(int i = 1; i <= 32; i++) { + out.printf("sat%02d", i); + if (i != 32) + out.printf(","); + } + } + + void write_gps_sat(AltosState state) { + AltosGPS gps = state.gps; + for(int i = 1; i <= 32; i++) { + int c_n0 = 0; + if (gps != null && gps.cc_gps_sat != null) { + for(int j = 0; j < gps.cc_gps_sat.length; j++) + if (gps.cc_gps_sat[j].svid == i) { + c_n0 = gps.cc_gps_sat[j].c_n0; + break; + } + } + out.printf ("%3d", c_n0); + if (i != 32) + out.printf(","); + } + } + + void write_companion_header() { + out.printf("companion_id,companion_time,companion_update,companion_channels"); + for (int i = 0; i < 12; i++) + out.printf(",companion_%02d", i); + } + + void write_companion(AltosState state) { + AltosCompanion companion = state.companion; + + int channels_written = 0; + if (companion == null) { + out.printf("0,0,0,0"); + } else { + out.printf("%3d,%5.2f,%5.2f,%2d", + companion.board_id, + (companion.tick - boost_tick) / 100.0, + companion.update_period / 100.0, + companion.channels); + for (; channels_written < companion.channels; channels_written++) + out.printf(",%5d", companion.companion_data[channels_written]); + } + for (; channels_written < 12; channels_written++) + out.printf(",0"); + } + + void write_header(boolean advanced, boolean gps, boolean companion) { + out.printf("#"); write_general_header(); + out.printf(","); write_flight_header(); + out.printf(","); write_basic_header(); + if (advanced) + out.printf(","); write_advanced_header(); + if (gps) { + out.printf(","); write_gps_header(); + out.printf(","); write_gps_sat_header(); + } + if (companion) { + out.printf(","); write_companion_header(); + } + out.printf ("\n"); + } + + void write_one(AltosState state) { + write_general(state); out.printf(","); + write_flight(state); out.printf(","); + write_basic(state); out.printf(","); + if (state.imu != null || state.mag != null) + write_advanced(state); + if (state.gps != null) { + out.printf(","); + write_gps(state); out.printf(","); + write_gps_sat(state); + } + if (state.companion != null) { + out.printf(","); + write_companion(state); + } + out.printf ("\n"); + } + + void flush_pad() { + while (!pad_states.isEmpty()) { + write_one (pad_states.remove()); + } + } + + public void write(AltosState state) { + if (state.state == AltosLib.ao_flight_startup) + return; + if (!header_written) { + write_header(state.imu != null || state.mag != null, + state.gps != null, state.companion != null); + 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); + } + + public PrintStream out() { + return out; + } + + 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()); + for (AltosState state : states) + write(state); + } + + 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 { + this(new PrintStream(in_name), in_name); + } + + public AltosCSV(String in_string) throws FileNotFoundException { + this(new File(in_string)); + } +} |