altosui: Start adding code to write csv files from eeprom/telem files
authorKeith Packard <keithp@keithp.com>
Sat, 7 Aug 2010 04:42:25 +0000 (00:42 -0400)
committerKeith Packard <keithp@keithp.com>
Sat, 7 Aug 2010 04:42:25 +0000 (00:42 -0400)
This is a start to code which can write out a csv file full of flight
data from either an eeprom or telem input file. It's not hooked up,
but the restructuring necessary is finished and the output is started.

Signed-off-by: Keith Packard <keithp@keithp.com>
ao-tools/altosui/AltosCSV.java [new file with mode: 0644]
ao-tools/altosui/AltosEepromReader.java
ao-tools/altosui/AltosReader.java [new file with mode: 0644]
ao-tools/altosui/AltosRecord.java
ao-tools/altosui/AltosTelemetryReader.java [new file with mode: 0644]
ao-tools/altosui/AltosUI.java
ao-tools/altosui/Makefile

diff --git a/ao-tools/altosui/AltosCSV.java b/ao-tools/altosui/AltosCSV.java
new file mode 100644 (file)
index 0000000..2493675
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ * Copyright © 2010 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package altosui;
+
+import java.lang.*;
+import java.io.*;
+import altosui.AltosRecord;
+
+public class AltosCSV {
+       File            name;
+       PrintStream     out;
+       boolean         header_written;
+
+       static final int ALTOS_CSV_VERSION = 1;
+
+       /* Version 1 format:
+        *
+        * General info
+        *      version number
+        *      serial number
+        *      flight number
+        *      callsign
+        *      time (seconds since boost)
+        *
+        * Flight status
+        *      state
+        *      state name
+        *
+        * Basic sensors
+        *      acceleration (m/s²)
+        *      pressure (mBar)
+        *      altitude (m)
+        *      accelerometer speed (m/s)
+        *      barometer speed (m/s)
+        *      temp (°C)
+        *      battery (V)
+        *      drogue (V)
+        *      main (V)
+        *
+        * GPS data
+        *      connected (1/0)
+        *      locked (1/0)
+        *      nsat (used for solution)
+        *      latitude (°)
+        *      longitude (°)
+        *      altitude (m)
+        *      year (e.g. 2010)
+        *      month (1-12)
+        *      day (1-31)
+        *      hour (0-23)
+        *      minute (0-59)
+        *      second (0-59)
+        *
+        * GPS Sat data
+        *      hdop
+        *      C/N0 data for all 32 valid SDIDs
+        */
+
+       void write_general_header() {
+               out.printf("version serial flight call time");
+       }
+
+       void write_general(AltosRecord record) {
+               out.printf("%s,%d,%d,%s,%d",
+                          record.version, record.serial, record.flight, record.callsign, record.tick);
+       }
+
+       void write_flight_header() {
+               out.printf("state state_name");
+       }
+
+       void write_flight(AltosRecord record) {
+               out.printf("%d,%s", record.state, record.state());
+       }
+
+       void write_header() {
+               out.printf("# "); write_general_header();
+               out.printf(" "); write_flight_header();
+               out.printf ("\n");
+       }
+
+       public void write(AltosRecord record) {
+               if (!header_written) {
+                       write_header();
+                       header_written = true;
+               }
+               write_general(record); out.printf(",");
+               write_flight(record);
+               out.printf ("\n");
+       }
+
+       public PrintStream out() {
+               return out;
+       }
+
+       public AltosCSV(File in_name) throws FileNotFoundException {
+               name = in_name;
+               out = new PrintStream(name);
+       }
+}
index 9b928abbfd9795a223f6dd6b5dd539245c5b5b76..c29fd90b12391105d6ed76bfb5841d6c7c9e0e1e 100644 (file)
@@ -64,7 +64,7 @@ class AltosOrderedRecord extends AltosEepromRecord implements Comparable<AltosOr
        }
 }
 
-public class AltosEepromReader {
+public class AltosEepromReader extends AltosReader {
 
        static final int        seen_flight = 1;
        static final int        seen_sensor = 2;
@@ -96,7 +96,9 @@ public class AltosEepromReader {
 
        int                     gps_tick;
 
-       FileInputStream input;
+       boolean                 saw_boost;
+
+       int                     boost_tick;
 
        public AltosRecord read() throws IOException, ParseException {
                for (;;) {
@@ -109,8 +111,11 @@ public class AltosEepromReader {
                                }
                                record = record_iterator.next();
 
-                               if ((seen & seen_basic) == seen_basic && record.tick != state.tick)
-                                       return new AltosRecord(state);
+                               if ((seen & seen_basic) == seen_basic && record.tick != state.tick) {
+                                       AltosRecord r = new AltosRecord(state);
+                                       r.time = (r.tick - boost_tick) / 100.0;
+                                       return r;
+                               }
                        }
 
                        state.tick = record.tick;
@@ -221,6 +226,48 @@ public class AltosEepromReader {
                }
        }
 
+       public void write_comments(PrintStream out) {
+               Iterator<AltosOrderedRecord>    iterator = records.iterator();
+               while (iterator.hasNext()) {
+                       AltosOrderedRecord      record = iterator.next();
+                       switch (record.cmd) {
+                       case Altos.AO_LOG_CONFIG_VERSION:
+                               out.printf("# Config version: %s\n", record.data);
+                               break;
+                       case Altos.AO_LOG_MAIN_DEPLOY:
+                               out.printf("# Main deploy: %s\n", record.a);
+                               break;
+                       case Altos.AO_LOG_APOGEE_DELAY:
+                               out.printf("# Apogee delay: %s\n", record.a);
+                               break;
+                       case Altos.AO_LOG_RADIO_CHANNEL:
+                               out.printf("# Radio channel: %s\n", record.a);
+                               break;
+                       case Altos.AO_LOG_CALLSIGN:
+                               out.printf("# Callsign: %s\n", record.data);
+                               break;
+                       case Altos.AO_LOG_ACCEL_CAL:
+                               out.printf ("# Accel cal: %d %d\n", record.a, record.b);
+                               break;
+                       case Altos.AO_LOG_RADIO_CAL:
+                               out.printf ("# Radio cal: %d %d\n", record.a);
+                               break;
+                       case Altos.AO_LOG_MANUFACTURER:
+                               out.printf ("# Manufacturer: %s\n", record.data);
+                               break;
+                       case Altos.AO_LOG_PRODUCT:
+                               out.printf ("# Product: %s\n", record.data);
+                               break;
+                       case Altos.AO_LOG_SERIAL_NUMBER:
+                               out.printf ("# Serial number: %d\n", record.a);
+                               break;
+                       case Altos.AO_LOG_SOFTWARE_VERSION:
+                               out.printf ("# Software version: %s\n", record.data);
+                               break;
+                       }
+               }
+       }
+
        /*
         * Read the whole file, dumping records into a RB tree so
         * we can enumerate them in time order -- the eeprom data
@@ -228,12 +275,11 @@ public class AltosEepromReader {
         * matching the first packet out of the GPS unit but not
         * written until the final GPS packet has been received.
         */
-       public AltosEepromReader (FileInputStream in_input) {
+       public AltosEepromReader (FileInputStream input) {
                state = new AltosRecord();
                state.state = Altos.ao_flight_pad;
                state.accel_plus_g = 15758;
                state.accel_minus_g = 16294;
-               input = in_input;
                seen = 0;
                records = new TreeSet<AltosOrderedRecord>();
 
@@ -249,11 +295,21 @@ public class AltosEepromReader {
                                if (record == null)
                                        break;
                                tick = record.tick;
+                               if (!saw_boost && record.cmd == Altos.AO_LOG_STATE &&
+                                   record.a == Altos.ao_flight_boost)
+                               {
+                                       saw_boost = true;
+                                       boost_tick = state.tick;
+                               }
                                records.add(record);
                        }
                } catch (IOException io) {
                } catch (ParseException pe) {
                }
                record_iterator = records.iterator();
+               try {
+                       input.close();
+               } catch (IOException ie) {
+               }
        }
 }
diff --git a/ao-tools/altosui/AltosReader.java b/ao-tools/altosui/AltosReader.java
new file mode 100644 (file)
index 0000000..81779e2
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright © 2010 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package altosui;
+
+import java.io.*;
+import java.util.*;
+import java.text.*;
+
+import altosui.AltosRecord;
+
+public class AltosReader {
+       public AltosRecord read() throws IOException, ParseException { return null; }
+}
index 3440d935348f074efec3a5d9b53de8557e4b0319..b670ee371abed05de27cfd835642b16591a00adc 100644 (file)
@@ -48,6 +48,8 @@ public class AltosRecord {
        int     accel_minus_g;
        AltosGPS        gps;
 
+       double  time;   /* seconds since boost */
+
        /*
         * Values for our MP3H6115A pressure sensor
         *
diff --git a/ao-tools/altosui/AltosTelemetryReader.java b/ao-tools/altosui/AltosTelemetryReader.java
new file mode 100644 (file)
index 0000000..f1f6788
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright © 2010 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package altosui;
+
+import java.io.*;
+import java.util.*;
+import java.text.*;
+import altosui.AltosTelemetry;
+
+public class AltosTelemetryReader extends AltosReader {
+       LinkedList<AltosRecord> records;
+
+       Iterator<AltosRecord> record_iterator;
+
+       int     boost_tick;
+
+       public AltosRecord read() throws IOException, ParseException {
+               AltosRecord     r;
+               if (!record_iterator.hasNext())
+                       return null;
+
+               r = record_iterator.next();
+               r.time = (r.tick - boost_tick) / 100.0;
+               return r;
+       }
+
+       public AltosTelemetryReader (FileInputStream input) {
+               boolean saw_boost = false;
+
+               records = new LinkedList<AltosRecord> ();
+
+               try {
+                       for (;;) {
+                               String line = AltosRecord.gets(input);
+                               if (line == null)
+                                       break;
+                               AltosTelemetry record = new AltosTelemetry(line);
+                               if (record == null)
+                                       break;
+                               if (!saw_boost && record.state >= Altos.ao_flight_boost)
+                               {
+                                       saw_boost = true;
+                                       boost_tick = record.tick;
+                               }
+                               records.add(record);
+                       }
+               } catch (IOException io) {
+               } catch (ParseException pe) {
+               }
+               record_iterator = records.iterator();
+               try {
+                       input.close();
+               } catch (IOException ie) {
+               }
+       }
+}
index 2cb0c47935d10ca6c77b70035b56f842c62b6d4d..7d5ac93ac32adb1497160c0867654d32fd90da9f 100644 (file)
@@ -391,21 +391,12 @@ public class AltosUI extends JFrame {
                }
        }
 
-       class TelemetryThread extends DisplayThread {
-
-               String readline() throws InterruptedException { return null; }
-
-               AltosRecord read() throws InterruptedException, ParseException {
-                       return new AltosTelemetry(readline());
-               }
-       }
-
-       class DeviceThread extends TelemetryThread {
+       class DeviceThread extends DisplayThread {
                AltosSerial     serial;
                LinkedBlockingQueue<String> telem;
 
-               String readline() throws InterruptedException {
-                       return telem.take();
+               AltosRecord read() throws InterruptedException, ParseException {
+                       return new AltosTelemetry(telem.take());
                }
 
                void close() {
@@ -453,36 +444,30 @@ public class AltosUI extends JFrame {
         * Open an existing telemetry file and replay it in realtime
         */
 
-       class ReplayTelemetryThread extends TelemetryThread {
-               FileInputStream replay;
-
-               ReplayTelemetryThread(FileInputStream in, String in_name) {
-                       replay = in;
-                       name = in_name;
-               }
+       class ReplayThread extends DisplayThread {
+               AltosReader     reader;
+               String          name;
 
-               String readline() {
+               public AltosRecord read() {
                        try {
-                               String  line = AltosRecord.gets(replay);
-                               System.out.printf("telemetry line %s\n", line);
-                               return line;
-                       } catch (IOException ee) {
+                               return reader.read();
+                       } catch (IOException ie) {
                                JOptionPane.showMessageDialog(AltosUI.this,
                                                              name,
                                                              "error reading",
                                                              JOptionPane.ERROR_MESSAGE);
+                       } catch (ParseException pe) {
                        }
                        return null;
                }
 
-               void close () {
-                       try {
-                               replay.close();
-                       } catch (IOException ee) {
-                       }
+               public void close () {
                        report();
                }
 
+               public ReplayThread(AltosReader in_reader, String in_name) {
+                       reader = in_reader;
+               }
                void update(AltosState state) throws InterruptedException {
                        /* Make it run in realtime after the rocket leaves the pad */
                        if (state.state > Altos.ao_flight_pad)
@@ -490,40 +475,16 @@ public class AltosUI extends JFrame {
                }
        }
 
-       class ReplayEepromThread extends DisplayThread {
-               FileInputStream replay;
-
-               AltosEepromReader       reader;
-
-               ReplayEepromThread(FileInputStream in, String in_name) {
-                       replay = in;
-                       name = in_name;
-                       reader = new AltosEepromReader (in);
+       class ReplayTelemetryThread extends ReplayThread {
+               ReplayTelemetryThread(FileInputStream in, String in_name) {
+                       super(new AltosTelemetryReader(in), in_name);
                }
 
-               AltosRecord read () throws ParseException {
-                       try {
-                               return reader.read();
-                       } catch (IOException ee) {
-                               JOptionPane.showMessageDialog(AltosUI.this,
-                                                             name,
-                                                             "error reading",
-                                                             JOptionPane.ERROR_MESSAGE);
-                       }
-                       return null;
-               }
+       }
 
-               void close () {
-                       try {
-                               replay.close();
-                       } catch (IOException ee) {
-                       }
-                       report();
-               }
-               void update(AltosState state) throws InterruptedException {
-                       /* Make it run in realtime after the rocket leaves the pad */
-                       if (state.state > Altos.ao_flight_pad)
-                               Thread.sleep((int) (Math.min(state.time_change,10) * 1000));
+       class ReplayEepromThread extends ReplayThread {
+               ReplayEepromThread(FileInputStream in, String in_name) {
+                       super(new AltosEepromReader(in), in_name);
                }
        }
 
index 3f55db0b81da40192bf3c35c25863c82e76709ac..8c9e9642fbad134d530da4ec989c5ebc89fa5709 100644 (file)
@@ -4,6 +4,7 @@ CLASSPATH=classes:./*
 CLASSFILES=\
        Altos.class \
        AltosConvert.class \
+       AltosCSV.class \
        AltosEepromDownload.class \
        AltosEepromMonitor.class \
        AltosEepromReader.class \
@@ -21,6 +22,7 @@ CLASSFILES=\
        AltosSerial.class \
        AltosState.class \
        AltosTelemetry.class \
+       AltosTelemetryReader.class \
        AltosUI.class \
        AltosDevice.class \
        AltosDeviceDialog.class \