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_5;
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");
164 void write_advanced(AltosState state) {
165 AltosIMU imu = state.imu;
166 AltosMag mag = state.mag;
169 imu = new AltosIMU();
171 mag = new AltosMag();
172 out.printf("%7.2f,%7.2f,%7.2f,%7.2f,%7.2f,%7.2f,%7.2f,%7.2f,%7.2f",
173 imu.accel_x, imu.accel_y, imu.accel_z,
174 imu.gyro_x, imu.gyro_y, imu.gyro_z,
175 mag.x, mag.y, mag.z);
178 void write_gps_header() {
179 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");
182 void write_gps(AltosState state) {
183 AltosGPS gps = state.gps;
185 gps = new AltosGPS();
187 AltosGreatCircle from_pad = state.from_pad;
188 if (from_pad == null)
189 from_pad = new AltosGreatCircle();
191 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",
213 void write_gps_sat_header() {
214 for(int i = 1; i <= 32; i++) {
215 out.printf("sat%02d", i);
221 void write_gps_sat(AltosState state) {
222 AltosGPS gps = state.gps;
223 for(int i = 1; i <= 32; i++) {
225 if (gps != null && gps.cc_gps_sat != null) {
226 for(int j = 0; j < gps.cc_gps_sat.length; j++)
227 if (gps.cc_gps_sat[j].svid == i) {
228 c_n0 = gps.cc_gps_sat[j].c_n0;
232 out.printf ("%3d", c_n0);
238 void write_companion_header() {
239 out.printf("companion_id,companion_time,companion_update,companion_channels");
240 for (int i = 0; i < 12; i++)
241 out.printf(",companion_%02d", i);
244 void write_companion(AltosState state) {
245 AltosCompanion companion = state.companion;
247 int channels_written = 0;
248 if (companion == null) {
249 out.printf("0,0,0,0");
251 out.printf("%3d,%5.2f,%5.2f,%2d",
253 (companion.tick - boost_tick) / 100.0,
254 companion.update_period / 100.0,
256 for (; channels_written < companion.channels; channels_written++)
257 out.printf(",%5d", companion.companion_data[channels_written]);
259 for (; channels_written < 12; channels_written++)
263 void write_header() {
264 out.printf("#"); write_general_header();
265 if (has_flight_state) {
267 write_flight_header();
271 write_basic_header();
275 write_battery_header();
279 write_advanced_header();
287 write_gps_sat_header();
291 write_companion_header();
296 void write_one(AltosState state) {
297 write_general(state);
298 if (has_flight_state) {
308 write_battery(state);
312 write_advanced(state);
320 write_gps_sat(state);
324 write_companion(state);
329 private void flush_pad() {
330 while (!pad_states.isEmpty()) {
331 write_one (pad_states.remove());
335 private void write(AltosState state) {
336 if (state.state == AltosLib.ao_flight_startup)
338 if (!header_written) {
340 header_written = true;
343 if (state.state >= AltosLib.ao_flight_boost) {
345 boost_tick = state.tick;
352 pad_states.add(state);
355 private PrintStream out() {
359 public void close() {
360 if (!pad_states.isEmpty()) {
361 boost_tick = pad_states.element().tick;
367 public void write(AltosStateIterable states) {
368 states.write_comments(out());
370 has_flight_state = false;
373 has_advanced = false;
376 has_companion = false;
377 for (AltosState state : states) {
378 if (state.state != AltosLib.ao_flight_stateless && state.state != AltosLib.ao_flight_invalid && state.state != AltosLib.ao_flight_startup)
379 has_flight_state = true;
380 if (state.acceleration() != AltosLib.MISSING || state.pressure() != AltosLib.MISSING)
382 if (state.battery_voltage != AltosLib.MISSING)
384 if (state.imu != null || state.mag != null)
386 if (state.gps != null) {
388 if (state.gps.cc_gps_sat != null)
391 if (state.companion != null)
392 has_companion = true;
394 for (AltosState state : states)
398 public AltosCSV(PrintStream in_out, File in_name) {
401 pad_states = new LinkedList<AltosState>();
404 public AltosCSV(File in_name) throws FileNotFoundException {
405 this(new PrintStream(in_name), in_name);
408 public AltosCSV(String in_string) throws FileNotFoundException {
409 this(new File(in_string));