2 * Copyright © 2010 Keith Packard <keithp@keithp.com>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 2 of the License.
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
18 package org.altusmetrum.altoslib_11;
23 public class AltosCSV implements AltosWriter {
26 boolean header_written;
29 LinkedList<AltosState> pad_states;
32 static boolean has_basic;
33 static boolean has_battery;
34 static boolean has_flight_state;
35 static boolean has_advanced;
36 static boolean has_gps;
37 static boolean has_gps_sat;
38 static boolean has_companion;
40 static final int ALTOS_CSV_VERSION = 5;
49 * time (seconds since boost)
50 * clock (tick count / 100)
63 * accelerometer speed (m/s)
64 * barometer speed (m/s)
72 * Advanced sensors (if available)
83 * GPS data (if available)
86 * nsat (used for solution)
97 * from_pad_azimuth (deg true)
99 * from_pad_elevation (deg from horizon)
105 * C/N0 data for all 32 valid SDIDs
108 * companion_id (1-255. 10 is TeleScience)
109 * time of last companion data (seconds since boost)
110 * update_period (0.1-2.55 minimum telemetry interval)
112 * channel data for all 12 possible channels
115 void write_general_header() {
116 out.printf("version,serial,flight,call,time,clock,rssi,lqi");
119 void write_general(AltosState state) {
120 out.printf("%s, %d, %d, %s, %8.2f, %8.2f, %4d, %3d",
121 ALTOS_CSV_VERSION, state.serial, state.flight, state.callsign,
122 (double) state.time_since_boost(), (double) state.tick / 100.0,
124 state.status & 0x7f);
127 void write_flight_header() {
128 out.printf("state,state_name");
131 void write_flight(AltosState state) {
132 out.printf("%d,%8s", state.state(), state.state_name());
135 void write_basic_header() {
136 out.printf("acceleration,pressure,altitude,height,accel_speed,baro_speed,temperature,drogue_voltage,main_voltage");
139 void write_basic(AltosState state) {
140 out.printf("%8.2f,%10.2f,%8.2f,%8.2f,%8.2f,%8.2f,%5.1f,%5.2f,%5.2f",
141 state.acceleration(),
148 state.apogee_voltage,
152 void write_battery_header() {
153 out.printf("battery_voltage");
156 void write_battery(AltosState state) {
157 out.printf("%5.2f", state.battery_voltage);
160 void write_advanced_header() {
161 out.printf("accel_x,accel_y,accel_z,gyro_x,gyro_y,gyro_z,mag_x,mag_y,mag_z");
164 void write_advanced(AltosState state) {
165 out.printf("%7.2f,%7.2f,%7.2f,%7.2f,%7.2f,%7.2f,%7.2f,%7.2f,%7.2f",
166 state.accel_along(), state.accel_across(), state.accel_through(),
167 state.gyro_roll(), state.gyro_pitch(), state.gyro_yaw(),
168 state.mag_along(), state.mag_across(), state.mag_through());
171 void write_gps_header() {
172 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");
175 void write_gps(AltosState state) {
176 AltosGPS gps = state.gps;
178 gps = new AltosGPS();
180 AltosGreatCircle from_pad = state.from_pad;
181 if (from_pad == null)
182 from_pad = new AltosGreatCircle();
184 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,%6.1f,%6.1f",
206 void write_gps_sat_header() {
207 for(int i = 1; i <= 32; i++) {
208 out.printf("sat%02d", i);
214 void write_gps_sat(AltosState state) {
215 AltosGPS gps = state.gps;
216 for(int i = 1; i <= 32; i++) {
218 if (gps != null && gps.cc_gps_sat != null) {
219 for(int j = 0; j < gps.cc_gps_sat.length; j++)
220 if (gps.cc_gps_sat[j].svid == i) {
221 c_n0 = gps.cc_gps_sat[j].c_n0;
225 out.printf ("%3d", c_n0);
231 void write_companion_header() {
232 out.printf("companion_id,companion_time,companion_update,companion_channels");
233 for (int i = 0; i < 12; i++)
234 out.printf(",companion_%02d", i);
237 void write_companion(AltosState state) {
238 AltosCompanion companion = state.companion;
240 int channels_written = 0;
241 if (companion == null) {
242 out.printf("0,0,0,0");
244 out.printf("%3d,%5.2f,%5.2f,%2d",
246 (companion.tick - boost_tick) / 100.0,
247 companion.update_period / 100.0,
249 for (; channels_written < companion.channels; channels_written++)
250 out.printf(",%5d", companion.companion_data[channels_written]);
252 for (; channels_written < 12; channels_written++)
256 void write_header() {
257 out.printf("#"); write_general_header();
258 if (has_flight_state) {
260 write_flight_header();
264 write_basic_header();
268 write_battery_header();
272 write_advanced_header();
280 write_gps_sat_header();
284 write_companion_header();
289 void write_one(AltosState state) {
290 write_general(state);
291 if (has_flight_state) {
301 write_battery(state);
305 write_advanced(state);
313 write_gps_sat(state);
317 write_companion(state);
322 private void flush_pad() {
323 while (!pad_states.isEmpty()) {
324 write_one (pad_states.remove());
328 private void write(AltosState state) {
329 if (state.state() == AltosLib.ao_flight_startup)
331 if (!header_written) {
333 header_written = true;
336 if (state.state() >= AltosLib.ao_flight_boost) {
338 boost_tick = state.tick;
345 pad_states.add(state);
348 private PrintStream out() {
352 public void close() {
353 if (!pad_states.isEmpty()) {
354 boost_tick = pad_states.element().tick;
360 public void write(AltosStateIterable states) {
361 states.write_comments(out());
363 has_flight_state = false;
366 has_advanced = false;
369 has_companion = false;
370 for (AltosState state : states) {
371 if (state.state() != AltosLib.ao_flight_stateless && state.state() != AltosLib.ao_flight_invalid && state.state() != AltosLib.ao_flight_startup)
372 has_flight_state = true;
373 if (state.acceleration() != AltosLib.MISSING || state.pressure() != AltosLib.MISSING)
375 if (state.battery_voltage != AltosLib.MISSING)
377 if (state.accel_across() != AltosLib.MISSING)
379 if (state.gps != null) {
381 if (state.gps.cc_gps_sat != null)
384 if (state.companion != null)
385 has_companion = true;
387 for (AltosState state : states)
391 public AltosCSV(PrintStream in_out, File in_name) {
394 pad_states = new LinkedList<AltosState>();
397 public AltosCSV(File in_name) throws FileNotFoundException {
398 this(new PrintStream(in_name), in_name);
401 public AltosCSV(String in_string) throws FileNotFoundException {
402 this(new File(in_string));