Drivetrain is now tuned.  Quite stiff.
diff --git a/frc971/control_loops/drivetrain/drivetrain.cc b/frc971/control_loops/drivetrain/drivetrain.cc
index 63e6718..79e2864 100644
--- a/frc971/control_loops/drivetrain/drivetrain.cc
+++ b/frc971/control_loops/drivetrain/drivetrain.cc
@@ -3,6 +3,7 @@
 #include <stdio.h>
 #include <sched.h>
 #include <cmath>
+#include <memory>
 
 #include "aos/aos_core.h"
 #include "aos/common/logging/logging.h"
@@ -21,72 +22,61 @@
 // Width of the robot.
 const double width = 22.0 / 100.0 * 2.54;
 
-class DrivetrainMotorsSS : public StateFeedbackLoop<4, 2, 2> {
+class DrivetrainMotorsSS {
  public:
-  DrivetrainMotorsSS (void)
-      : StateFeedbackLoop(MakeDrivetrainLoop()) {
+  DrivetrainMotorsSS ()
+      : loop_(new StateFeedbackLoop<4, 2, 2>(MakeDrivetrainLoop())) {
     _offset = 0;
     _integral_offset = 0;
     _left_goal = 0.0;
     _right_goal = 0.0;
     _raw_left = 0.0;
     _raw_right = 0.0;
+    _control_loop_driving = false;
   }
   void SetGoal(double left, double left_velocity, double right, double right_velocity) {
     _left_goal = left;
     _right_goal = right;
-    R << left + _integral_offset * width / 2.0, left_velocity, right - _integral_offset * width / 2.0, right_velocity;
+    loop_->R << left, left_velocity, right, right_velocity;
   }
   void SetRawPosition(double left, double right) {
     _raw_right = right;
     _raw_left = left;
-    Y << left + _offset + _integral_offset, right - _offset + _integral_offset;
+    loop_->Y << left, right;
   }
-  void SetPosition(double left, double right, double gyro, bool control_loop_driving) {
+  void SetPosition(
+      double left, double right, double gyro, bool control_loop_driving) {
     // Decay the offset quickly because this gyro is great.
     _offset = (0.25) * (right - left - gyro * width) / 2.0 + 0.75 * _offset;
     const double angle_error = (_right_goal - _left_goal) / width - (_raw_right - _offset - _raw_left - _offset) / width;
-    if (!control_loop_driving) {
-      _integral_offset = 0.0;
-    } else if (::std::abs(angle_error) < M_PI / 10.0) {
-      _integral_offset -= angle_error * 0.010;
-    } else {
-      _integral_offset *= 0.97;
-    }
+    // TODO(aschuh): Add in the gyro.
+    _integral_offset = 0.0;
+    _offset = 0.0;
     _gyro = gyro;
+    _control_loop_driving = control_loop_driving;
     SetRawPosition(left, right);
     LOG(DEBUG, "Left %f->%f Right %f->%f Gyro %f aerror %f ioff %f\n", left + _offset, _left_goal, right - _offset, _right_goal, gyro, angle_error, _integral_offset);
   }
-  double UnDeadband(double value) {
-    const double positive_deadband_power = 0.15 * 12;
-    const double negative_deadband_power = 0.09 * 12;
-    if (value > 0) {
-      value += positive_deadband_power;
-    }
-    if (value < 0) {
-      value -= negative_deadband_power;
-    }
-    if (value > 12.0) {
-      value = 12.0;
-    }
-    if (value < -12.0) {
-      value = -12.0;
-    }
-    return value;
+
+  void Update(bool update_observer, bool stop_motors) {
+    loop_->Update(update_observer, stop_motors);
   }
 
-  void SendMotors(Drivetrain::Output *status) {
-    if (status) {
-      status->left_voltage = UnDeadband(U[0]);
-      status->right_voltage = UnDeadband(U[1]);
+  void SendMotors(Drivetrain::Output *output) {
+    if (output) {
+      output->left_voltage = loop_->U(0, 0);
+      output->right_voltage = loop_->U(1, 0);
     }
   }
   void PrintMotors() const {
     // LOG(DEBUG, "Left Power %f Right Power %f lg %f rg %f le %f re %f gyro %f\n", U[0], U[1], R[0], R[2], Y[0], Y[1], _gyro);
-    LOG(DEBUG, "lg %f rg %f le %f re %f gyro %f off %f\n", R[0], R[2], Y[0], Y[1], _gyro * 180.0 / M_PI, _offset);
+    ::Eigen::Matrix<double, 4, 1> E = loop_->R - loop_->X_hat;
+    LOG(DEBUG, "E[0, 0]: %f E[1, 0] %f E[2, 0] %f E[3, 0] %f\n", E(0, 0), E(1, 0), E(2, 0), E(3, 0));
   }
 
  private:
+  ::std::unique_ptr<StateFeedbackLoop<4, 2, 2>> loop_;
+
   double _integral_offset;
   double _offset;
   double _gyro;
@@ -94,6 +84,7 @@
   double _right_goal;
   double _raw_left;
   double _raw_right;
+  bool _control_loop_driving;
 };
 
 class DrivetrainMotorsOL {
@@ -273,7 +264,8 @@
   double left_goal = goal->left_goal;
   double right_goal = goal->right_goal;
 
-  dt_closedloop.SetGoal(left_goal, 0.0, right_goal, 0.0);
+  dt_closedloop.SetGoal(left_goal, goal->left_velocity_goal,
+                        right_goal, goal->right_velocity_goal);
   if (!bad_pos) {
     const double left_encoder = position->left_encoder;
     const double right_encoder = position->right_encoder;
@@ -284,7 +276,8 @@
       dt_closedloop.SetRawPosition(left_encoder, right_encoder);
     }
   }
-  dt_closedloop.Update(!bad_pos, bad_pos || bad_output);
+  dt_closedloop.Update(position, output == NULL);
+  //dt_closedloop.PrintMotors();
   dt_openloop.SetGoal(wheel, throttle, quickturn, highgear);
   dt_openloop.Update();
   if (control_loop_driving) {
diff --git a/frc971/control_loops/drivetrain/drivetrain.q b/frc971/control_loops/drivetrain/drivetrain.q
index f56c115..2085eb8 100644
--- a/frc971/control_loops/drivetrain/drivetrain.q
+++ b/frc971/control_loops/drivetrain/drivetrain.q
@@ -12,7 +12,9 @@
     bool quickturn;
     bool control_loop_driving;
     float left_goal;
+    float left_velocity_goal;
     float right_goal;
+    float right_velocity_goal;
   };
 
   message Position {
diff --git a/frc971/control_loops/drivetrain/drivetrain_lib_test.cc b/frc971/control_loops/drivetrain/drivetrain_lib_test.cc
index 75a8b8f..d15de44 100644
--- a/frc971/control_loops/drivetrain/drivetrain_lib_test.cc
+++ b/frc971/control_loops/drivetrain/drivetrain_lib_test.cc
@@ -39,7 +39,7 @@
   void Reinitialize() {
     drivetrain_plant_->X(0, 0) = 0.0;
     drivetrain_plant_->X(1, 0) = 0.0;
-    drivetrain_plant_->Y = drivetrain_plant_->C * drivetrain_plant_->X;
+    drivetrain_plant_->Y = drivetrain_plant_->C() * drivetrain_plant_->X;
     last_left_position_ = drivetrain_plant_->Y(0, 0);
     last_right_position_ = drivetrain_plant_->Y(1, 0);
   }
diff --git a/frc971/control_loops/drivetrain/drivetrain_motor_plant.cc b/frc971/control_loops/drivetrain/drivetrain_motor_plant.cc
index d4edba8..e543c9f 100644
--- a/frc971/control_loops/drivetrain/drivetrain_motor_plant.cc
+++ b/frc971/control_loops/drivetrain/drivetrain_motor_plant.cc
@@ -1,16 +1,17 @@
 #include "frc971/control_loops/drivetrain/drivetrain_motor_plant.h"
 
+#include <vector>
+
 #include "frc971/control_loops/state_feedback_loop.h"
 
 namespace frc971 {
 namespace control_loops {
 
-
-StateFeedbackPlant<4, 2, 2> MakeDrivetrainPlant() {
+StateFeedbackPlantCoefficients<4, 2, 2> MakeDrivetrainPlantCoefficients() {
   Eigen::Matrix<double, 4, 4> A;
-  A << 1.0, 0.0081841122497, 0.0, -5.9473473594e-05, 0.0, 0.660289401132, 0.0, -0.0103071702002, 0.0, -5.9473473594e-05, 1.0, 0.0081841122497, 0.0, -0.0103071702002, 0.0, 0.660289401132;
+  A << 1.0, 0.00931379160739, 0.0, 4.70184876909e-06, 0.0, 0.865971883056, 0.0, 0.000895808426591, 0.0, 4.70184876909e-06, 1.0, 0.00931379160739, 0.0, 0.000895808426591, 0.0, 0.865971883056;
   Eigen::Matrix<double, 4, 2> B;
-  B << 0.000333031510271, 1.09073596255e-05, 0.0623024929693, 0.00189032194188, 1.09073596255e-05, 0.000333031510271, 0.00189032194188, 0.0623024929693;
+  B << 0.000126707931029, -8.6819330098e-07, 0.0247482041615, -0.000165410440259, -8.6819330098e-07, 0.000126707931029, -0.000165410440259, 0.0247482041615;
   Eigen::Matrix<double, 2, 4> C;
   C << 1, 0, 0, 0, 0, 0, 1, 0;
   Eigen::Matrix<double, 2, 2> D;
@@ -19,16 +20,28 @@
   U_max << 12.0, 12.0;
   Eigen::Matrix<double, 2, 1> U_min;
   U_min << -12.0, -12.0;
-  return StateFeedbackPlant<4, 2, 2>(A, B, C, D, U_max, U_min);
+  return StateFeedbackPlantCoefficients<4, 2, 2>(A, B, C, D, U_max, U_min);
+}
+
+StateFeedbackController<4, 2, 2> MakeDrivetrainController() {
+  Eigen::Matrix<double, 4, 2> L;
+  L << 1.70597188306, 0.000895808426591, 66.3158545945, 0.117712892743, 0.000895808426591, 1.70597188306, 0.117712892743, 66.3158545945;
+  Eigen::Matrix<double, 2, 4> K;
+  K << 240.432225842, 14.3659115621, 1.60698530163, 0.13242189318, 1.60698530163, 0.13242189318, 240.432225842, 14.3659115621;
+  return StateFeedbackController<4, 2, 2>(L, K, MakeDrivetrainPlantCoefficients());
+}
+
+StateFeedbackPlant<4, 2, 2> MakeDrivetrainPlant() {
+  ::std::vector<StateFeedbackPlantCoefficients<4, 2, 2> *> plants(1);
+  plants[0] = new StateFeedbackPlantCoefficients<4, 2, 2>(MakeDrivetrainPlantCoefficients());
+  return StateFeedbackPlant<4, 2, 2>(plants);
 }
 
 StateFeedbackLoop<4, 2, 2> MakeDrivetrainLoop() {
-  Eigen::Matrix<double, 4, 2> L;
-  L << 1.50028940113, -0.0103071702002, 41.1373728147, -1.1627040905, -0.0103071702002, 1.50028940113, -1.1627040905, 41.1373728147;
-  Eigen::Matrix<double, 2, 4> K;
-  K << 48.196534943, -0.087263189034, -1.46233261597, -0.163410937407, -1.46233261597, -0.163410937407, 48.196534943, -0.087263189034;
-  return StateFeedbackLoop<4, 2, 2>(L, K, MakeDrivetrainPlant());
+  ::std::vector<StateFeedbackController<4, 2, 2> *> controllers(1);
+  controllers[0] = new StateFeedbackController<4, 2, 2>(MakeDrivetrainController());
+  return StateFeedbackLoop<4, 2, 2>(controllers);
 }
 
-}  // namespace frc971
 }  // namespace control_loops
+}  // namespace frc971
diff --git a/frc971/control_loops/drivetrain/drivetrain_motor_plant.h b/frc971/control_loops/drivetrain/drivetrain_motor_plant.h
index af43b46..2060b6f 100644
--- a/frc971/control_loops/drivetrain/drivetrain_motor_plant.h
+++ b/frc971/control_loops/drivetrain/drivetrain_motor_plant.h
@@ -6,11 +6,15 @@
 namespace frc971 {
 namespace control_loops {
 
+StateFeedbackPlantCoefficients<4, 2, 2> MakeDrivetrainPlantCoefficients();
+
+StateFeedbackController<4, 2, 2> MakeDrivetrainController();
+
 StateFeedbackPlant<4, 2, 2> MakeDrivetrainPlant();
 
 StateFeedbackLoop<4, 2, 2> MakeDrivetrainLoop();
 
-}  // namespace frc971
 }  // namespace control_loops
+}  // namespace frc971
 
 #endif  // FRC971_CONTROL_LOOPS_DRIVETRAIN_DRIVETRAIN_MOTOR_PLANT_H_
diff --git a/frc971/control_loops/python/drivetrain.py b/frc971/control_loops/python/drivetrain.py
index e5a8217..0e791cb 100755
--- a/frc971/control_loops/python/drivetrain.py
+++ b/frc971/control_loops/python/drivetrain.py
@@ -18,7 +18,7 @@
     self.free_current = 2.7
     # Moment of inertia of the drivetrain in kg m^2
     # Just borrowed from last year.
-    self.J = 7.0
+    self.J = 6.4
     # Mass of the robot, in kg.
     self.m = 68
     # Radius of the robot, in meters (from last year).
@@ -26,7 +26,7 @@
     # Radius of the wheels, in meters.
     self.r = .04445
     # Resistance of the motor, divided by the number of motors.
-    self.R = 12.0 / self.stall_current / 6
+    self.R = 12.0 / self.stall_current / 6 + 0.03
     # Motor velocity constant
     self.Kv = ((self.free_speed / 60.0 * 2.0 * numpy.pi) /
                (12.0 - self.R * self.free_current))
@@ -65,12 +65,12 @@
     self.D = numpy.matrix([[0, 0],
                            [0, 0]])
 
-    self.ContinuousToDiscrete(self.A_continuous, self.B_continuous,
-                              self.dt, self.C)
+    self.A, self.B = self.ContinuousToDiscrete(
+        self.A_continuous, self.B_continuous, self.dt)
 
     # Poles from last year.
-    self.hp = 0.8
-    self.lp = 0.85
+    self.hp = 0.65
+    self.lp = 0.83
     self.PlaceControllerPoles([self.hp, self.hp, self.lp, self.lp])
 
     print self.K
@@ -81,6 +81,7 @@
 
     self.U_max = numpy.matrix([[12.0], [12.0]])
     self.U_min = numpy.matrix([[-12.0], [-12.0]])
+    self.InitializeState()
 
 def main(argv):
   # Simulate the response of the system to a step input.
@@ -92,9 +93,9 @@
     simulated_left.append(drivetrain.X[0, 0])
     simulated_right.append(drivetrain.X[2, 0])
 
-  pylab.plot(range(100), simulated_left)
-  pylab.plot(range(100), simulated_right)
-  pylab.show()
+  #pylab.plot(range(100), simulated_left)
+  #pylab.plot(range(100), simulated_right)
+  #pylab.show()
 
   # Simulate forwards motion.
   drivetrain = Drivetrain()
@@ -109,9 +110,9 @@
     close_loop_left.append(drivetrain.X[0, 0])
     close_loop_right.append(drivetrain.X[2, 0])
 
-  pylab.plot(range(100), close_loop_left)
-  pylab.plot(range(100), close_loop_right)
-  pylab.show()
+  #pylab.plot(range(100), close_loop_left)
+  #pylab.plot(range(100), close_loop_right)
+  #pylab.show()
 
   # Try turning in place
   drivetrain = Drivetrain()
@@ -126,9 +127,9 @@
     close_loop_left.append(drivetrain.X[0, 0])
     close_loop_right.append(drivetrain.X[2, 0])
 
-  pylab.plot(range(100), close_loop_left)
-  pylab.plot(range(100), close_loop_right)
-  pylab.show()
+  #pylab.plot(range(100), close_loop_left)
+  #pylab.plot(range(100), close_loop_right)
+  #pylab.show()
 
   # Try turning just one side.
   drivetrain = Drivetrain()
@@ -143,19 +144,19 @@
     close_loop_left.append(drivetrain.X[0, 0])
     close_loop_right.append(drivetrain.X[2, 0])
 
-  pylab.plot(range(100), close_loop_left)
-  pylab.plot(range(100), close_loop_right)
-  pylab.show()
+  #pylab.plot(range(100), close_loop_left)
+  #pylab.plot(range(100), close_loop_right)
+  #pylab.show()
 
   # Write the generated constants out to a file.
   if len(argv) != 3:
     print "Expected .h file name and .cc file name"
   else:
+    loop_writer = control_loop.ControlLoopWriter("Drivetrain", [drivetrain])
     if argv[1][-3:] == '.cc':
-      print '.cc file is second'
+      loop_writer.Write(argv[2], argv[1])
     else:
-      drivetrain.DumpHeaderFile(argv[1])
-      drivetrain.DumpCppFile(argv[2], argv[1])
+      loop_writer.Write(argv[1], argv[2])
 
 if __name__ == '__main__':
   sys.exit(main(sys.argv))
diff --git a/frc971/control_loops/update_drivetrain.sh b/frc971/control_loops/update_drivetrain.sh
new file mode 100755
index 0000000..9d17e99
--- /dev/null
+++ b/frc971/control_loops/update_drivetrain.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+#
+# Updates the drivetrain controller.
+
+./python/drivetrain.py drivetrain/drivetrain_motor_plant.h \
+    drivetrain/drivetrain_motor_plant.cc