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_14;
24 public class AltosCSV implements AltosWriter {
27 boolean header_written;
34 boolean has_flight_state;
39 boolean has_companion;
41 AltosFlightSeries series;
44 static final int ALTOS_CSV_VERSION = 6;
53 * time (seconds since boost)
55 * Radio info (if available)
68 * accelerometer speed (m/s)
69 * barometer speed (m/s)
77 * Advanced sensors (if available)
89 * Extra igniter voltages (if available)
96 * GPS data (if available)
99 * nsat (used for solution)
110 * from_pad_azimuth (deg true)
112 * from_pad_elevation (deg from horizon)
118 * C/N0 data for all 32 valid SDIDs
121 * companion_id (1-255. 10 is TeleScience)
122 * time of last companion data (seconds since boost)
123 * update_period (0.1-2.55 minimum telemetry interval)
125 * channel data for all 12 possible channels
128 void write_general_header() {
129 out.printf("version,serial,flight,call,time");
133 return series.time(indices);
136 void write_general() {
137 out.printf("%s, %d, %d, %s, %8.2f",
139 series.cal_data().serial,
140 series.cal_data().flight,
141 series.cal_data().callsign,
145 void write_radio_header() {
146 out.printf("rssi,lqi");
150 return (int) series.value(AltosFlightSeries.rssi_name, indices);
154 return (int) series.value(AltosFlightSeries.status_name, indices);
158 out.printf("%4d, %3d",
159 rssi(), status() & 0x7f);
162 void write_flight_header() {
163 out.printf("state,state_name");
167 return (int) series.value(AltosFlightSeries.state_name, indices);
170 void write_flight() {
172 out.printf("%2d,%8s", state, AltosLib.state_name(state));
175 void write_basic_header() {
176 out.printf("acceleration,pressure,altitude,height,accel_speed,baro_speed,temperature,drogue_voltage,main_voltage");
179 double acceleration() { return series.value(AltosFlightSeries.accel_name, indices); }
180 double pressure() { return series.value(AltosFlightSeries.pressure_name, indices); }
181 double altitude() { return series.value(AltosFlightSeries.altitude_name, indices); }
182 double height() { return series.value(AltosFlightSeries.height_name, indices); }
183 double speed() { return series.value(AltosFlightSeries.speed_name, indices); }
184 double temperature() { return series.value(AltosFlightSeries.temperature_name, indices); }
185 double apogee_voltage() { return series.value(AltosFlightSeries.apogee_voltage_name, indices); }
186 double main_voltage() { return series.value(AltosFlightSeries.main_voltage_name, indices); }
189 out.printf("%8.2f,%10.2f,%8.2f,%8.2f,%8.2f,%8.2f,%5.1f,%5.2f,%5.2f",
201 void write_battery_header() {
202 out.printf("battery_voltage");
205 double battery_voltage() { return series.value(AltosFlightSeries.battery_voltage_name, indices); }
207 void write_battery() {
208 out.printf("%5.2f", battery_voltage());
211 void write_advanced_header() {
212 out.printf("accel_x,accel_y,accel_z,gyro_roll,gyro_pitch,gyro_yaw,mag_x,mag_y,mag_z,tilt");
215 double accel_along() { return series.value(AltosFlightSeries.accel_along_name, indices); }
216 double accel_across() { return series.value(AltosFlightSeries.accel_across_name, indices); }
217 double accel_through() { return series.value(AltosFlightSeries.accel_through_name, indices); }
219 double gyro_roll() { return series.value(AltosFlightSeries.gyro_roll_name, indices); }
220 double gyro_pitch() { return series.value(AltosFlightSeries.gyro_pitch_name, indices); }
221 double gyro_yaw() { return series.value(AltosFlightSeries.gyro_yaw_name, indices); }
223 double mag_along() { return series.value(AltosFlightSeries.mag_along_name, indices); }
224 double mag_across() { return series.value(AltosFlightSeries.mag_across_name, indices); }
225 double mag_through() { return series.value(AltosFlightSeries.mag_through_name, indices); }
227 double tilt() { return series.value(AltosFlightSeries.orient_name, indices); }
229 void write_advanced() {
230 out.printf("%7.2f,%7.2f,%7.2f,%7.2f,%7.2f,%7.2f,%7.2f,%7.2f,%7.2f,%7.2f",
231 accel_along(), accel_across(), accel_through(),
232 gyro_roll(), gyro_pitch(), gyro_yaw(),
233 mag_along(), mag_across(), mag_through(),
237 void write_igniter_header() {
239 for (int i = 0; i < series.igniter_voltage.length; i++)
240 out.printf(",%s", AltosLib.igniter_short_name(i));
243 double pyro() { return series.value(AltosFlightSeries.pyro_voltage_name, indices); }
245 double igniter_value(int channel) { return series.value(series.igniter_voltage_name(channel), indices); }
247 void write_igniter() {
248 out.printf("%5.2f", pyro());
249 for (int i = 0; i < series.igniter_voltage.length; i++)
250 out.printf(",%5.2f", igniter_value(i));
253 void write_gps_header() {
254 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");
258 AltosGPS gps = series.gps_before(series.time(indices));
260 AltosGreatCircle from_pad;
262 if (series.cal_data().gps_pad != null && gps != null)
263 from_pad = new AltosGreatCircle(series.cal_data().gps_pad, gps);
265 from_pad = new AltosGreatCircle();
268 gps = new AltosGPS();
270 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",
292 void write_gps_sat_header() {
293 for(int i = 1; i <= 32; i++) {
294 out.printf("sat%02d", i);
300 void write_gps_sat() {
301 AltosGPS gps = series.gps_before(series.time(indices));
302 for(int i = 1; i <= 32; i++) {
304 if (gps != null && gps.cc_gps_sat != null) {
305 for(int j = 0; j < gps.cc_gps_sat.length; j++)
306 if (gps.cc_gps_sat[j].svid == i) {
307 c_n0 = gps.cc_gps_sat[j].c_n0;
311 out.printf ("%3d", c_n0);
317 void write_companion_header() {
319 out.printf("companion_id,companion_time,companion_update,companion_channels");
320 for (int i = 0; i < 12; i++)
321 out.printf(",companion_%02d", i);
325 void write_companion() {
327 AltosCompanion companion = state.companion;
329 int channels_written = 0;
330 if (companion == null) {
331 out.printf("0,0,0,0");
333 out.printf("%3d,%5.2f,%5.2f,%2d",
335 (companion.tick - boost_tick) / 100.0,
336 companion.update_period / 100.0,
338 for (; channels_written < companion.channels; channels_written++)
339 out.printf(",%5d", companion.companion_data[channels_written]);
341 for (; channels_written < 12; channels_written++)
346 void write_header() {
347 out.printf("#"); write_general_header();
350 write_radio_header();
352 if (has_flight_state) {
354 write_flight_header();
358 write_basic_header();
362 write_battery_header();
366 write_advanced_header();
370 write_igniter_header();
378 write_gps_sat_header();
382 write_companion_header();
393 if (has_flight_state) {
428 private void write() {
429 if (state() == AltosLib.ao_flight_startup)
431 if (!header_written) {
433 header_written = true;
438 private PrintStream out() {
442 public void close() {
446 public void write(AltosFlightSeries series) {
447 // series.write_comments(out());
449 this.series = series;
454 has_flight_state = false;
457 has_advanced = false;
461 has_companion = false;
463 if (series.has_series(AltosFlightSeries.rssi_name))
465 if (series.has_series(AltosFlightSeries.state_name))
466 has_flight_state = true;
467 if (series.has_series(AltosFlightSeries.accel_name) || series.has_series(AltosFlightSeries.pressure_name))
469 if (series.has_series(AltosFlightSeries.battery_voltage_name))
471 if (series.has_series(AltosFlightSeries.accel_across_name))
473 if (series.has_series(AltosFlightSeries.pyro_voltage_name))
476 if (series.gps_series != null)
478 if (series.sats_in_view != null)
481 if (state.companion != null)
482 has_companion = true;
485 indices = series.indices();
489 if (!series.step_indices(indices))
494 public AltosCSV(PrintStream in_out, File in_name) {
499 public AltosCSV(File in_name) throws FileNotFoundException {
500 this(new PrintStream(in_name), in_name);
503 public AltosCSV(String in_string) throws FileNotFoundException {
504 this(new File(in_string));