Re-enable polytopes for closed loop driving

I reproduced the original bug which resulted in this being disabled in a
test and fixed it already (I99a1299e538a395685c2e7e555dfccab48055349).
This commit fixes another issue observed in testing and re-enables the
polytopes.

Change-Id: Ic27e0ab8b2ea6dd480d7998c44530918443874db
diff --git a/frc971/control_loops/drivetrain/ssdrivetrain.cc b/frc971/control_loops/drivetrain/ssdrivetrain.cc
index 049b576..9fdfe1c 100644
--- a/frc971/control_loops/drivetrain/ssdrivetrain.cc
+++ b/frc971/control_loops/drivetrain/ssdrivetrain.cc
@@ -18,98 +18,95 @@
 DrivetrainMotorsSS::LimitedDrivetrainLoop::LimitedDrivetrainLoop(
     StateFeedbackLoop<4, 2, 2> &&loop)
     : StateFeedbackLoop<4, 2, 2>(::std::move(loop)),
-      U_Poly_((Eigen::Matrix<double, 4, 2>() << 1, 0, -1, 0, 0, 1, 0, -1)
+      U_poly_((Eigen::Matrix<double, 4, 2>() << 1, 0, -1, 0, 0, 1, 0, -1)
                   .finished(),
               (Eigen::Matrix<double, 4, 1>() << 12.0, 12.0, 12.0, 12.0)
                   .finished()) {
   ::aos::controls::HPolytope<0>::Init();
-  T << 1, -1, 1, 1;
-  T_inverse = T.inverse();
+  T_ << 1, 1, 1, -1;
+  T_inverse_ = T_.inverse();
 }
 
+// This intentionally runs the U-capping code even when it's unnecessary to help
+// make it more deterministic. Only running it when one or both sides want
+// out-of-range voltages could lead to things like running out of CPU under
+// certain situations, which would be bad.
 void DrivetrainMotorsSS::LimitedDrivetrainLoop::CapU() {
+  output_was_capped_ = ::std::abs(U(0, 0)) > 12.0 || ::std::abs(U(1, 0)) > 12.0;
+
   const Eigen::Matrix<double, 4, 1> error = R() - X_hat();
 
-  if (::std::abs(U(0, 0)) > 12.0 || ::std::abs(U(1, 0)) > 12.0) {
-    mutable_U() =
-        U() * 12.0 / ::std::max(::std::abs(U(0, 0)), ::std::abs(U(1, 0)));
-    LOG_MATRIX(DEBUG, "U is now", U());
-    // TODO(Austin): Figure out why the polytope stuff wasn't working and
-    // remove this hack.
-    output_was_capped_ = true;
-    return;
+  LOG_MATRIX(DEBUG, "U at start", U());
+  LOG_MATRIX(DEBUG, "R at start", R());
+  LOG_MATRIX(DEBUG, "Xhat at start", X_hat());
 
-    LOG_MATRIX(DEBUG, "U at start", U());
-    LOG_MATRIX(DEBUG, "R at start", R());
-    LOG_MATRIX(DEBUG, "Xhat at start", X_hat());
+  Eigen::Matrix<double, 2, 2> position_K;
+  position_K << K(0, 0), K(0, 2), K(1, 0), K(1, 2);
+  Eigen::Matrix<double, 2, 2> velocity_K;
+  velocity_K << K(0, 1), K(0, 3), K(1, 1), K(1, 3);
 
-    Eigen::Matrix<double, 2, 2> position_K;
-    position_K << K(0, 0), K(0, 2), K(1, 0), K(1, 2);
-    Eigen::Matrix<double, 2, 2> velocity_K;
-    velocity_K << K(0, 1), K(0, 3), K(1, 1), K(1, 3);
+  Eigen::Matrix<double, 2, 1> position_error;
+  position_error << error(0, 0), error(2, 0);
+  // drive_error = [total_distance_error, left_error - right_error]
+  const auto drive_error = T_inverse_ * position_error;
+  Eigen::Matrix<double, 2, 1> velocity_error;
+  velocity_error << error(1, 0), error(3, 0);
+  LOG_MATRIX(DEBUG, "error", error);
 
-    Eigen::Matrix<double, 2, 1> position_error;
-    position_error << error(0, 0), error(2, 0);
-    const auto drive_error = T_inverse * position_error;
-    Eigen::Matrix<double, 2, 1> velocity_error;
-    velocity_error << error(1, 0), error(3, 0);
-    LOG_MATRIX(DEBUG, "error", error);
+  const ::aos::controls::HPolytope<2> pos_poly(U_poly_, position_K * T_,
+                                               -velocity_K * velocity_error);
 
-    const auto &poly = U_Poly_;
-    const Eigen::Matrix<double, 4, 2> pos_poly_H = poly.H() * position_K * T;
-    const Eigen::Matrix<double, 4, 1> pos_poly_k =
-        poly.k() - poly.H() * velocity_K * velocity_error;
-    const ::aos::controls::HPolytope<2> pos_poly(pos_poly_H, pos_poly_k);
+  Eigen::Matrix<double, 2, 1> adjusted_pos_error;
+  {
+    const auto &P = drive_error;
 
-    Eigen::Matrix<double, 2, 1> adjusted_pos_error;
-    {
-      const auto &P = drive_error;
+    Eigen::Matrix<double, 1, 2> L45;
+    L45 << ::aos::sign(P(1, 0)), -::aos::sign(P(0, 0));
+    const double w45 = 0;
 
-      Eigen::Matrix<double, 1, 2> L45;
-      L45 << ::aos::sign(P(1, 0)), -::aos::sign(P(0, 0));
-      const double w45 = 0;
+    Eigen::Matrix<double, 1, 2> LH;
+    if (::std::abs(P(0, 0)) > ::std::abs(P(1, 0))) {
+      LH << 0, 1;
+    } else {
+      LH << 1, 0;
+    }
+    const double wh = LH.dot(P);
 
-      Eigen::Matrix<double, 1, 2> LH;
-      if (::std::abs(P(0, 0)) > ::std::abs(P(1, 0))) {
-        LH << 0, 1;
-      } else {
-        LH << 1, 0;
-      }
-      const double wh = LH.dot(P);
+    Eigen::Matrix<double, 2, 2> standard;
+    standard << L45, LH;
+    Eigen::Matrix<double, 2, 1> W;
+    W << w45, wh;
+    const Eigen::Matrix<double, 2, 1> intersection = standard.inverse() * W;
 
-      Eigen::Matrix<double, 2, 2> standard;
-      standard << L45, LH;
-      Eigen::Matrix<double, 2, 1> W;
-      W << w45, wh;
-      const Eigen::Matrix<double, 2, 1> intersection = standard.inverse() * W;
-
-      bool is_inside_h;
-      const auto adjusted_pos_error_h =
-          DoCoerceGoal(pos_poly, LH, wh, drive_error, &is_inside_h);
-      const auto adjusted_pos_error_45 =
-          DoCoerceGoal(pos_poly, L45, w45, intersection, nullptr);
-      if (pos_poly.IsInside(intersection)) {
-        adjusted_pos_error = adjusted_pos_error_h;
-      } else {
-        if (is_inside_h) {
-          if (adjusted_pos_error_h.norm() > adjusted_pos_error_45.norm() ||
-              adjusted_pos_error_45.norm() > intersection.norm()) {
-            adjusted_pos_error = adjusted_pos_error_h;
-          } else {
-            adjusted_pos_error = adjusted_pos_error_45;
-          }
+    bool is_inside_h, is_inside_45;
+    const auto adjusted_pos_error_h =
+        DoCoerceGoal(pos_poly, LH, wh, drive_error, &is_inside_h);
+    const auto adjusted_pos_error_45 =
+        DoCoerceGoal(pos_poly, L45, w45, intersection, &is_inside_45);
+    if (pos_poly.IsInside(intersection)) {
+      adjusted_pos_error = adjusted_pos_error_h;
+    } else {
+      if (is_inside_h) {
+        if (adjusted_pos_error_h.norm() > adjusted_pos_error_45.norm() ||
+            adjusted_pos_error_45.norm() > intersection.norm()) {
+          adjusted_pos_error = adjusted_pos_error_h;
         } else {
           adjusted_pos_error = adjusted_pos_error_45;
         }
+      } else {
+        adjusted_pos_error = adjusted_pos_error_45;
       }
     }
+  }
 
-    LOG_MATRIX(DEBUG, "adjusted_pos_error", adjusted_pos_error);
-    mutable_U() =
-        velocity_K * velocity_error + position_K * T * adjusted_pos_error;
-    LOG_MATRIX(DEBUG, "U is now", U());
-  } else {
-    output_was_capped_ = false;
+  mutable_U() =
+      velocity_K * velocity_error + position_K * T_ * adjusted_pos_error;
+  LOG_MATRIX(DEBUG, "U is now", U());
+
+  if (!output_was_capped_) {
+    if ((U() - U_uncapped()).norm() > 0.0001) {
+      LOG(FATAL, "U unnecessarily capped\n");
+    }
   }
 }