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; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
19 package org.altusmetrum.altoslib_11;
24 public class AltosCSV implements AltosWriter {
27 boolean header_written;
30 LinkedList<AltosState> pad_states;
33 static boolean has_basic;
34 static boolean has_battery;
35 static boolean has_flight_state;
36 static boolean has_advanced;
37 static boolean has_gps;
38 static boolean has_gps_sat;
39 static boolean has_companion;
41 static final int ALTOS_CSV_VERSION = 5;
50 * time (seconds since boost)
51 * clock (tick count / 100)
64 * accelerometer speed (m/s)
65 * barometer speed (m/s)
73 * Advanced sensors (if available)
84 * GPS data (if available)
87 * nsat (used for solution)
98 * from_pad_azimuth (deg true)
100 * from_pad_elevation (deg from horizon)
106 * C/N0 data for all 32 valid SDIDs
109 * companion_id (1-255. 10 is TeleScience)
110 * time of last companion data (seconds since boost)
111 * update_period (0.1-2.55 minimum telemetry interval)
113 * channel data for all 12 possible channels
116 void write_general_header() {
117 out.printf("version,serial,flight,call,time,clock,rssi,lqi");
120 void write_general(AltosState state) {
121 out.printf("%s, %d, %d, %s, %8.2f, %8.2f, %4d, %3d",
122 ALTOS_CSV_VERSION, state.serial, state.flight, state.callsign,
123 (double) state.time_since_boost(), (double) state.tick / 100.0,
125 state.status & 0x7f);
128 void write_flight_header() {
129 out.printf("state,state_name");
132 void write_flight(AltosState state) {
133 out.printf("%d,%8s", state.state(), state.state_name());
136 void write_basic_header() {
137 out.printf("acceleration,pressure,altitude,height,accel_speed,baro_speed,temperature,drogue_voltage,main_voltage");
140 void write_basic(AltosState state) {
141 out.printf("%8.2f,%10.2f,%8.2f,%8.2f,%8.2f,%8.2f,%5.1f,%5.2f,%5.2f",
142 state.acceleration(),
149 state.apogee_voltage,
153 void write_battery_header() {
154 out.printf("battery_voltage");
157 void write_battery(AltosState state) {
158 out.printf("%5.2f", state.battery_voltage);
161 void write_advanced_header() {
162 out.printf("accel_x,accel_y,accel_z,gyro_x,gyro_y,gyro_z,mag_x,mag_y,mag_z");
165 void write_advanced(AltosState state) {
166 out.printf("%7.2f,%7.2f,%7.2f,%7.2f,%7.2f,%7.2f,%7.2f,%7.2f,%7.2f",
167 state.accel_along(), state.accel_across(), state.accel_through(),
168 state.gyro_roll(), state.gyro_pitch(), state.gyro_yaw(),
169 state.mag_along(), state.mag_across(), state.mag_through());
172 void write_gps_header() {
173 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");
176 void write_gps(AltosState state) {
177 AltosGPS gps = state.gps;
179 gps = new AltosGPS();
181 AltosGreatCircle from_pad = state.from_pad;
182 if (from_pad == null)
183 from_pad = new AltosGreatCircle();
185 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",
207 void write_gps_sat_header() {
208 for(int i = 1; i <= 32; i++) {
209 out.printf("sat%02d", i);
215 void write_gps_sat(AltosState state) {
216 AltosGPS gps = state.gps;
217 for(int i = 1; i <= 32; i++) {
219 if (gps != null && gps.cc_gps_sat != null) {
220 for(int j = 0; j < gps.cc_gps_sat.length; j++)
221 if (gps.cc_gps_sat[j].svid == i) {
222 c_n0 = gps.cc_gps_sat[j].c_n0;
226 out.printf ("%3d", c_n0);
232 void write_companion_header() {
233 out.printf("companion_id,companion_time,companion_update,companion_channels");
234 for (int i = 0; i < 12; i++)
235 out.printf(",companion_%02d", i);
238 void write_companion(AltosState state) {
239 AltosCompanion companion = state.companion;
241 int channels_written = 0;
242 if (companion == null) {
243 out.printf("0,0,0,0");
245 out.printf("%3d,%5.2f,%5.2f,%2d",
247 (companion.tick - boost_tick) / 100.0,
248 companion.update_period / 100.0,
250 for (; channels_written < companion.channels; channels_written++)
251 out.printf(",%5d", companion.companion_data[channels_written]);
253 for (; channels_written < 12; channels_written++)
257 void write_header() {
258 out.printf("#"); write_general_header();
259 if (has_flight_state) {
261 write_flight_header();
265 write_basic_header();
269 write_battery_header();
273 write_advanced_header();
281 write_gps_sat_header();
285 write_companion_header();
290 void write_one(AltosState state) {
291 write_general(state);
292 if (has_flight_state) {
302 write_battery(state);
306 write_advanced(state);
314 write_gps_sat(state);
318 write_companion(state);
323 private void flush_pad() {
324 while (!pad_states.isEmpty()) {
325 write_one (pad_states.remove());
329 private void write(AltosState state) {
330 if (state.state() == AltosLib.ao_flight_startup)
332 if (!header_written) {
334 header_written = true;
337 if (state.state() >= AltosLib.ao_flight_boost) {
339 boost_tick = state.tick;
346 pad_states.add(state);
349 private PrintStream out() {
353 public void close() {
354 if (!pad_states.isEmpty()) {
355 boost_tick = pad_states.element().tick;
361 public void write(AltosStateIterable states) {
362 states.write_comments(out());
364 has_flight_state = false;
367 has_advanced = false;
370 has_companion = false;
371 for (AltosState state : states) {
372 if (state.state() != AltosLib.ao_flight_stateless && state.state() != AltosLib.ao_flight_invalid && state.state() != AltosLib.ao_flight_startup)
373 has_flight_state = true;
374 if (state.acceleration() != AltosLib.MISSING || state.pressure() != AltosLib.MISSING)
376 if (state.battery_voltage != AltosLib.MISSING)
378 if (state.accel_across() != AltosLib.MISSING)
380 if (state.gps != null) {
382 if (state.gps.cc_gps_sat != null)
385 if (state.companion != null)
386 has_companion = true;
388 for (AltosState state : states)
392 public AltosCSV(PrintStream in_out, File in_name) {
395 pad_states = new LinkedList<AltosState>();
398 public AltosCSV(File in_name) throws FileNotFoundException {
399 this(new PrintStream(in_name), in_name);
402 public AltosCSV(String in_string) throws FileNotFoundException {
403 this(new File(in_string));