Added the .csv logger to work with the angle adjust.
diff --git a/frc971/atom_code/atom_code.gyp b/frc971/atom_code/atom_code.gyp
index 865195e..bcf573a 100644
--- a/frc971/atom_code/atom_code.gyp
+++ b/frc971/atom_code/atom_code.gyp
@@ -11,6 +11,7 @@
         '../control_loops/control_loops.gyp:hall_effect_lib_test',
         '../control_loops/angle_adjust/angle_adjust.gyp:angle_adjust',
         '../control_loops/angle_adjust/angle_adjust.gyp:angle_adjust_lib_test',
+        '../control_loops/angle_adjust/angle_adjust.gyp:angle_adjust_csv',
         '../input/input.gyp:JoystickReader',
         '../input/input.gyp:SensorReader',
         '../input/input.gyp:GyroReader',
diff --git a/frc971/control_loops/angle_adjust/angle_adjust.cc b/frc971/control_loops/angle_adjust/angle_adjust.cc
index 6f11d89..e64f5e4 100644
--- a/frc971/control_loops/angle_adjust/angle_adjust.cc
+++ b/frc971/control_loops/angle_adjust/angle_adjust.cc
@@ -24,9 +24,6 @@
         true, 5.0),
     error_count_(0),
     time_(0.0) {
-  if (testing) {
-    hall_effect_.loop_->StartDataFile("angle_adjust.csv");
-  }
 }
 
 /*static*/ const double AngleAdjustMotor::dt = 0.01;
@@ -158,11 +155,6 @@
     output->voltage = LimitVoltage(hall_effect_.absolute_position_,
                                    hall_effect_.loop_->U(0, 0));
   }
-
-  if (testing) {
-    hall_effect_.loop_->RecordDatum("angle_adjust.csv", time_);
-  }
-  time_ += dt;
 }  // RunIteration
 
 }  // namespace control_loops
diff --git a/frc971/control_loops/angle_adjust/angle_adjust.gyp b/frc971/control_loops/angle_adjust/angle_adjust.gyp
index 1a0af94..7a7a1ea 100644
--- a/frc971/control_loops/angle_adjust/angle_adjust.gyp
+++ b/frc971/control_loops/angle_adjust/angle_adjust.gyp
@@ -53,6 +53,19 @@
       ],
     },
     {
+      'target_name': 'angle_adjust_csv',
+      'type': 'executable',
+      'sources': [
+        'angle_adjust_csv.cc',
+      ],
+      'dependencies': [
+        '<(AOS)/build/aos.gyp:libaos',
+        '<(AOS)/common/common.gyp:time',
+        '<(AOS)/common/common.gyp:timing',
+        'angle_adjust_loop',
+      ],
+    },
+    {
       'target_name': 'angle_adjust',
       'type': 'executable',
       'sources': [
diff --git a/frc971/control_loops/angle_adjust/angle_adjust_csv.cc b/frc971/control_loops/angle_adjust/angle_adjust_csv.cc
new file mode 100644
index 0000000..d0215de
--- /dev/null
+++ b/frc971/control_loops/angle_adjust/angle_adjust_csv.cc
@@ -0,0 +1,53 @@
+#include "stdio.h"
+
+#include "aos/aos_core.h"
+#include "aos/common/control_loop/Timing.h"
+#include "aos/common/time.h"
+#include "frc971/control_loops/angle_adjust/angle_adjust_motor.q.h"
+
+using ::frc971::control_loops::angle_adjust;
+using ::aos::time::Time;
+
+// Records data from the queue and stores it in a .csv file which can then
+// be plotted/processed with relative ease.
+int main(int argc, char * argv[]) {
+  FILE *data_file = NULL;
+  FILE *output_file = NULL;
+
+  if (argc == 2) {
+    data_file = fopen(argv[1], "w");
+    output_file = data_file;
+  } else {
+    printf("Not saving to a CSV file.\n");
+    output_file = stdout;
+  }
+
+  fprintf(data_file, "time, power, position");
+
+  ::aos::Init();
+
+  Time start_time = Time::Now();
+
+  while (true) {
+    ::aos::time::PhasedLoop10MS(2000);
+    angle_adjust.goal.FetchLatest();
+    angle_adjust.status.FetchLatest();
+    angle_adjust.position.FetchLatest();
+    angle_adjust.output.FetchLatest();
+    if (angle_adjust.output.get() &&
+        angle_adjust.position.get()) {
+      fprintf(output_file, "\n%f, %f, %f",
+              (angle_adjust.position->sent_time - start_time).ToSeconds(), 
+              angle_adjust.output->voltage,
+              angle_adjust.position->bottom_angle);
+    }
+  }
+
+  if (data_file) {
+    fclose(data_file);
+  }
+
+  ::aos::Cleanup();
+  return 0;
+}
+
diff --git a/frc971/control_loops/state_feedback_loop.h b/frc971/control_loops/state_feedback_loop.h
index 6046c9a..8fe18f8 100644
--- a/frc971/control_loops/state_feedback_loop.h
+++ b/frc971/control_loops/state_feedback_loop.h
@@ -153,22 +153,6 @@
     }
   }
 
-  // Starts the file for storing recorded data.
-  // file_name is the name of the file to write to.
-  virtual void StartDataFile(const char *file_name) {
-    FILE *data_file = fopen(file_name, "w");
-    fprintf(data_file, "time, power, position");
-    fclose(data_file);
-  }
-
-  // Records a single data point to the file of file_name,
-  // using a time of time.
-  virtual void RecordDatum(const char *file_name, double time) {
-    FILE *data_file = fopen(file_name, "a");
-    fprintf(data_file, "\n%f, %f, %f", time, U[0], Y[0]);
-    fclose(data_file);
-  }
-
  protected:
   // these are accessible from non-templated subclasses
   static const int kNumStates = number_of_states;