altoslib: Ensure CSV output is consistent
[fw/altos] / altoslib / AltosCSV.java
index 8176d21b4a21c038ff16f9cc2a23bdddd8be398b..4a9278d901fefd1348120d4a5d72d4f75991cf8f 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-package org.altusmetrum.altoslib_3;
+package org.altusmetrum.altoslib_5;
 
 import java.io.*;
 import java.util.*;
@@ -29,6 +29,14 @@ public class AltosCSV implements AltosWriter {
        LinkedList<AltosState>  pad_states;
        AltosState              state;
 
+       static boolean          has_basic;
+       static boolean          has_battery;
+       static boolean          has_flight_state;
+       static boolean          has_advanced;
+       static boolean          has_gps;
+       static boolean          has_gps_sat;
+       static boolean          has_companion;
+
        static final int ALTOS_CSV_VERSION = 5;
 
        /* Version 4 format:
@@ -55,10 +63,12 @@ public class AltosCSV implements AltosWriter {
         *      accelerometer speed (m/s)
         *      barometer speed (m/s)
         *      temp (°C)
-        *      battery (V)
         *      drogue (V)
         *      main (V)
         *
+        * Battery
+        *      battery (V)
+        *
         * Advanced sensors (if available)
         *      accel_x (m/s²)
         *      accel_y (m/s²)
@@ -87,7 +97,9 @@ public class AltosCSV implements AltosWriter {
         *      from_pad_azimuth (deg true)
         *      from_pad_range (m)
         *      from_pad_elevation (deg from horizon)
+        *      pdop
         *      hdop
+        *      vdop
         *
         * GPS Sat data
         *      C/N0 data for all 32 valid SDIDs
@@ -107,7 +119,7 @@ public class AltosCSV implements AltosWriter {
        void write_general(AltosState state) {
                out.printf("%s, %d, %d, %s, %8.2f, %8.2f, %4d, %3d",
                           ALTOS_CSV_VERSION, state.serial, state.flight, state.callsign,
-                          (double) state.time, (double) state.tick / 100.0,
+                          (double) state.time_since_boost(), (double) state.tick / 100.0,
                           state.rssi,
                           state.status & 0x7f);
        }
@@ -121,11 +133,11 @@ public class AltosCSV implements AltosWriter {
        }
 
        void write_basic_header() {
-               out.printf("acceleration,pressure,altitude,height,accel_speed,baro_speed,temperature,battery_voltage,drogue_voltage,main_voltage");
+               out.printf("acceleration,pressure,altitude,height,accel_speed,baro_speed,temperature,drogue_voltage,main_voltage");
        }
 
        void write_basic(AltosState state) {
-               out.printf("%8.2f,%10.2f,%8.2f,%8.2f,%8.2f,%8.2f,%5.1f,%5.2f,%5.2f,%5.2f",
+               out.printf("%8.2f,%10.2f,%8.2f,%8.2f,%8.2f,%8.2f,%5.1f,%5.2f,%5.2f",
                           state.acceleration(),
                           state.pressure(),
                           state.altitude(),
@@ -133,11 +145,18 @@ public class AltosCSV implements AltosWriter {
                           state.speed(),
                           state.speed(),
                           state.temperature,
-                          state.battery_voltage,
                           state.apogee_voltage,
                           state.main_voltage);
        }
 
+       void write_battery_header() {
+               out.printf("battery_voltage");
+       }
+
+       void write_battery(AltosState state) {
+               out.printf("%5.2f", state.battery_voltage);
+       }
+
        void write_advanced_header() {
                out.printf("accel_x,accel_y,accel_z,gyro_x,gyro_y,gyro_z");
        }
@@ -150,14 +169,14 @@ public class AltosCSV implements AltosWriter {
                        imu = new AltosIMU();
                if (mag == null)
                        mag = new AltosMag();
-               out.printf("%6d,%6d,%6d,%6d,%6d,%6d,%6d,%6d,%6d",
+               out.printf("%7.2f,%7.2f,%7.2f,%7.2f,%7.2f,%7.2f,%7.2f,%7.2f,%7.2f",
                           imu.accel_x, imu.accel_y, imu.accel_z,
                           imu.gyro_x, imu.gyro_y, imu.gyro_z,
                           mag.x, mag.y, mag.z);
        }
 
        void write_gps_header() {
-               out.printf("connected,locked,nsat,latitude,longitude,altitude,year,month,day,hour,minute,second,pad_dist,pad_range,pad_az,pad_el,hdop");
+               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");
        }
 
        void write_gps(AltosState state) {
@@ -169,7 +188,7 @@ public class AltosCSV implements AltosWriter {
                if (from_pad == null)
                        from_pad = new AltosGreatCircle();
 
-               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",
+               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",
                           gps.connected?1:0,
                           gps.locked?1:0,
                           gps.nsat,
@@ -186,7 +205,9 @@ public class AltosCSV implements AltosWriter {
                           state.range,
                           from_pad.bearing,
                           state.elevation,
-                          gps.hdop);
+                          gps.pdop,
+                          gps.hdop,
+                          gps.vdop);
        }
 
        void write_gps_sat_header() {
@@ -239,52 +260,83 @@ public class AltosCSV implements AltosWriter {
                        out.printf(",0");
        }
 
-       void write_header(boolean advanced, boolean gps, boolean companion) {
+       void write_header() {
                out.printf("#"); write_general_header();
-               out.printf(","); write_flight_header();
-               out.printf(","); write_basic_header();
-               if (advanced)
-                       out.printf(","); write_advanced_header();
-               if (gps) {
-                       out.printf(","); write_gps_header();
-                       out.printf(","); write_gps_sat_header();
+               if (has_flight_state) {
+                       out.printf(",");
+                       write_flight_header();
                }
-               if (companion) {
-                       out.printf(","); write_companion_header();
+               if (has_basic) {
+                       out.printf(",");
+                       write_basic_header();
+               }
+               if (has_battery) {
+                       out.printf(",");
+                       write_battery_header();
+               }
+               if (has_advanced) {
+                       out.printf(",");
+                       write_advanced_header();
+               }
+               if (has_gps) {
+                       out.printf(",");
+                       write_gps_header();
+               }
+               if (has_gps_sat) {
+                       out.printf(",");
+                       write_gps_sat_header();
+               }
+               if (has_companion) {
+                       out.printf(",");
+                       write_companion_header();
                }
                out.printf ("\n");
        }
 
        void write_one(AltosState state) {
-               write_general(state); out.printf(",");
-               write_flight(state); out.printf(",");
-               write_basic(state); out.printf(",");
-               if (state.imu != null || state.mag != null)
+               write_general(state);
+               if (has_flight_state) {
+                       out.printf(",");
+                       write_flight(state);
+               }
+               if (has_basic) {
+                       out.printf(",");
+                       write_basic(state);
+               }
+               if (has_battery) {
+                       out.printf(",");
+                       write_battery(state);
+               }
+               if (has_advanced) {
+                       out.printf(",");
                        write_advanced(state);
-               if (state.gps != null) {
+               }
+               if (has_gps) {
+                       out.printf(",");
+                       write_gps(state);
+               }
+               if (has_gps_sat) {
                        out.printf(",");
-                       write_gps(state); out.printf(",");
                        write_gps_sat(state);
                }
-               if (state.companion != null) {
+               if (has_companion) {
                        out.printf(",");
                        write_companion(state);
                }
                out.printf ("\n");
        }
 
-       void flush_pad() {
+       private void flush_pad() {
                while (!pad_states.isEmpty()) {
                        write_one (pad_states.remove());
                }
        }
 
-       public void write(AltosState state) {
+       private void write(AltosState state) {
                if (state.state == AltosLib.ao_flight_startup)
                        return;
                if (!header_written) {
-                       write_header(state.imu != null || state.mag != null,
-                                    state.gps != null, state.companion != null);
+                       write_header();
                        header_written = true;
                }
                if (!seen_boost) {
@@ -300,7 +352,7 @@ public class AltosCSV implements AltosWriter {
                        pad_states.add(state);
        }
 
-       public PrintStream out() {
+       private PrintStream out() {
                return out;
        }
 
@@ -314,6 +366,31 @@ public class AltosCSV implements AltosWriter {
 
        public void write(AltosStateIterable states) {
                states.write_comments(out());
+
+               has_flight_state = false;
+               has_basic = false;
+               has_battery = false;
+               has_advanced = false;
+               has_gps = false;
+               has_gps_sat = false;
+               has_companion = false;
+               for (AltosState state : states) {
+                       if (state.state != AltosLib.ao_flight_stateless && state.state != AltosLib.ao_flight_invalid && state.state != AltosLib.ao_flight_startup)
+                               has_flight_state = true;
+                       if (state.acceleration() != AltosLib.MISSING || state.pressure() != AltosLib.MISSING)
+                               has_basic = true;
+                       if (state.battery_voltage != AltosLib.MISSING)
+                               has_battery = true;
+                       if (state.imu != null || state.mag != null)
+                               has_advanced = true;
+                       if (state.gps != null) {
+                               has_gps = true;
+                               if (state.gps.cc_gps_sat != null)
+                                       has_gps_sat = true;
+                       }
+                       if (state.companion != null)
+                               has_companion = true;
+               }
                for (AltosState state : states)
                        write(state);
        }