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_12;
24 public class AltosCSV implements AltosWriter {
27 boolean header_written;
33 boolean has_flight_state;
37 boolean has_companion;
39 AltosFlightSeries series;
42 static final int ALTOS_CSV_VERSION = 5;
51 * time (seconds since boost)
52 * clock (tick count / 100)
65 * accelerometer speed (m/s)
66 * barometer speed (m/s)
74 * Advanced sensors (if available)
85 * GPS data (if available)
88 * nsat (used for solution)
99 * from_pad_azimuth (deg true)
101 * from_pad_elevation (deg from horizon)
107 * C/N0 data for all 32 valid SDIDs
110 * companion_id (1-255. 10 is TeleScience)
111 * time of last companion data (seconds since boost)
112 * update_period (0.1-2.55 minimum telemetry interval)
114 * channel data for all 12 possible channels
117 void write_general_header() {
118 out.printf("version,serial,flight,call,time,clock,rssi,lqi");
122 return series.time(indices);
126 return (int) series.value(AltosFlightSeries.rssi_name, indices);
130 return (int) series.value(AltosFlightSeries.status_name, indices);
133 void write_general() {
134 double time = time();
135 out.printf("%s, %d, %d, %s, %8.2f, %8.2f, %4d, %3d",
136 ALTOS_CSV_VERSION, series.cal_data().serial,
137 series.cal_data().flight, series.cal_data().callsign,
139 rssi(), status() & 0x7f);
142 void write_flight_header() {
143 out.printf("state,state_name");
147 return (int) series.value(AltosFlightSeries.state_name, indices);
150 void write_flight() {
152 out.printf("%d,%8s", state, AltosLib.state_name(state));
155 void write_basic_header() {
156 out.printf("acceleration,pressure,altitude,height,accel_speed,baro_speed,temperature,drogue_voltage,main_voltage");
159 double acceleration() { return series.value(AltosFlightSeries.accel_name, indices); }
160 double pressure() { return series.value(AltosFlightSeries.pressure_name, indices); }
161 double altitude() { return series.value(AltosFlightSeries.altitude_name, indices); }
162 double height() { return series.value(AltosFlightSeries.height_name, indices); }
163 double speed() { return series.value(AltosFlightSeries.speed_name, indices); }
164 double temperature() { return series.value(AltosFlightSeries.temperature_name, indices); }
165 double apogee_voltage() { return series.value(AltosFlightSeries.apogee_voltage_name, indices); }
166 double main_voltage() { return series.value(AltosFlightSeries.main_voltage_name, indices); }
169 out.printf("%8.2f,%10.2f,%8.2f,%8.2f,%8.2f,%8.2f,%5.1f,%5.2f,%5.2f",
181 void write_battery_header() {
182 out.printf("battery_voltage");
185 double battery_voltage() { return series.value(AltosFlightSeries.battery_voltage_name, indices); }
187 void write_battery() {
188 out.printf("%5.2f", battery_voltage());
191 void write_advanced_header() {
192 out.printf("accel_x,accel_y,accel_z,gyro_x,gyro_y,gyro_z,mag_x,mag_y,mag_z");
195 double accel_along() { return series.value(AltosFlightSeries.accel_along_name, indices); }
196 double accel_across() { return series.value(AltosFlightSeries.accel_across_name, indices); }
197 double accel_through() { return series.value(AltosFlightSeries.accel_through_name, indices); }
199 double gyro_roll() { return series.value(AltosFlightSeries.gyro_roll_name, indices); }
200 double gyro_pitch() { return series.value(AltosFlightSeries.gyro_pitch_name, indices); }
201 double gyro_yaw() { return series.value(AltosFlightSeries.gyro_yaw_name, indices); }
203 double mag_along() { return series.value(AltosFlightSeries.mag_along_name, indices); }
204 double mag_across() { return series.value(AltosFlightSeries.mag_across_name, indices); }
205 double mag_through() { return series.value(AltosFlightSeries.mag_through_name, indices); }
207 void write_advanced() {
208 out.printf("%7.2f,%7.2f,%7.2f,%7.2f,%7.2f,%7.2f,%7.2f,%7.2f,%7.2f",
209 accel_along(), accel_across(), accel_through(),
210 gyro_roll(), gyro_pitch(), gyro_yaw(),
211 mag_along(), mag_across(), mag_through());
214 void write_gps_header() {
215 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");
219 AltosGPS gps = series.gps_before(series.time(indices));
221 AltosGreatCircle from_pad;
223 if (series.cal_data().gps_pad != null && gps != null)
224 from_pad = new AltosGreatCircle(series.cal_data().gps_pad, gps);
226 from_pad = new AltosGreatCircle();
229 gps = new AltosGPS();
231 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",
253 void write_gps_sat_header() {
254 for(int i = 1; i <= 32; i++) {
255 out.printf("sat%02d", i);
261 void write_gps_sat() {
262 AltosGPS gps = series.gps_before(series.time(indices));
263 for(int i = 1; i <= 32; i++) {
265 if (gps != null && gps.cc_gps_sat != null) {
266 for(int j = 0; j < gps.cc_gps_sat.length; j++)
267 if (gps.cc_gps_sat[j].svid == i) {
268 c_n0 = gps.cc_gps_sat[j].c_n0;
272 out.printf ("%3d", c_n0);
278 void write_companion_header() {
280 out.printf("companion_id,companion_time,companion_update,companion_channels");
281 for (int i = 0; i < 12; i++)
282 out.printf(",companion_%02d", i);
286 void write_companion() {
288 AltosCompanion companion = state.companion;
290 int channels_written = 0;
291 if (companion == null) {
292 out.printf("0,0,0,0");
294 out.printf("%3d,%5.2f,%5.2f,%2d",
296 (companion.tick - boost_tick) / 100.0,
297 companion.update_period / 100.0,
299 for (; channels_written < companion.channels; channels_written++)
300 out.printf(",%5d", companion.companion_data[channels_written]);
302 for (; channels_written < 12; channels_written++)
307 void write_header() {
308 out.printf("#"); write_general_header();
309 if (has_flight_state) {
311 write_flight_header();
315 write_basic_header();
319 write_battery_header();
323 write_advanced_header();
331 write_gps_sat_header();
335 write_companion_header();
342 if (has_flight_state) {
373 private void write() {
374 if (state() == AltosLib.ao_flight_startup)
376 if (!header_written) {
378 header_written = true;
383 private PrintStream out() {
387 public void close() {
391 public void write(AltosFlightSeries series) {
392 // series.write_comments(out());
394 this.series = series;
398 has_flight_state = false;
401 has_advanced = false;
404 has_companion = false;
406 if (series.has_series(AltosFlightSeries.state_name))
407 has_flight_state = true;
408 if (series.has_series(AltosFlightSeries.accel_name) || series.has_series(AltosFlightSeries.pressure_name))
410 if (series.has_series(AltosFlightSeries.battery_voltage_name))
412 if (series.has_series(AltosFlightSeries.accel_across_name))
415 if (series.gps_series != null)
417 if (series.sats_in_view != null)
420 if (state.companion != null)
421 has_companion = true;
424 indices = series.indices();
428 if (!series.step_indices(indices))
433 public AltosCSV(PrintStream in_out, File in_name) {
438 public AltosCSV(File in_name) throws FileNotFoundException {
439 this(new PrintStream(in_name), in_name);
442 public AltosCSV(String in_string) throws FileNotFoundException {
443 this(new File(in_string));