Merge "Add a bit to enable sandstorm mode."
diff --git a/y2019/actors/BUILD b/y2019/actors/BUILD
new file mode 100644
index 0000000..e772718
--- /dev/null
+++ b/y2019/actors/BUILD
@@ -0,0 +1,48 @@
+filegroup(
+    name = "binaries.stripped",
+    srcs = [
+        ":autonomous_action.stripped",
+    ],
+    visibility = ["//visibility:public"],
+)
+
+filegroup(
+    name = "binaries",
+    srcs = [
+        ":autonomous_action",
+    ],
+    visibility = ["//visibility:public"],
+)
+
+cc_library(
+    name = "autonomous_action_lib",
+    srcs = [
+        "autonomous_actor.cc",
+    ],
+    hdrs = [
+        "autonomous_actor.h",
+    ],
+    deps = [
+        "//aos/logging",
+        "//aos/util:phased_loop",
+        "//frc971/autonomous:base_autonomous_actor",
+        "//frc971/control_loops:queues",
+        "//frc971/control_loops/drivetrain:drivetrain_config",
+        "//frc971/control_loops/drivetrain:drivetrain_queue",
+        "//frc971/control_loops/drivetrain:localizer_queue",
+        "//y2019/control_loops/drivetrain:drivetrain_base",
+        "//y2019/control_loops/superstructure:superstructure_queue",
+    ],
+)
+
+cc_binary(
+    name = "autonomous_action",
+    srcs = [
+        "autonomous_actor_main.cc",
+    ],
+    deps = [
+        ":autonomous_action_lib",
+        "//aos:init",
+        "//frc971/autonomous:auto_queue",
+    ],
+)
diff --git a/y2019/actors/autonomous_actor.cc b/y2019/actors/autonomous_actor.cc
new file mode 100644
index 0000000..9ed3e6f
--- /dev/null
+++ b/y2019/actors/autonomous_actor.cc
@@ -0,0 +1,136 @@
+#include "y2019/actors/autonomous_actor.h"
+
+#include <inttypes.h>
+
+#include <chrono>
+#include <cmath>
+
+#include "aos/logging/logging.h"
+#include "aos/util/phased_loop.h"
+
+#include "frc971/control_loops/drivetrain/drivetrain.q.h"
+#include "frc971/control_loops/drivetrain/localizer.q.h"
+#include "y2019/control_loops/drivetrain/drivetrain_base.h"
+
+namespace y2019 {
+namespace actors {
+using ::frc971::control_loops::drivetrain_queue;
+using ::frc971::control_loops::drivetrain::localizer_control;
+using ::aos::monotonic_clock;
+namespace chrono = ::std::chrono;
+
+namespace {
+
+double DoubleSeconds(monotonic_clock::duration duration) {
+  return ::std::chrono::duration_cast<::std::chrono::duration<double>>(duration)
+      .count();
+}
+
+}  // namespace
+
+AutonomousActor::AutonomousActor(
+    ::frc971::autonomous::AutonomousActionQueueGroup *s)
+    : frc971::autonomous::BaseAutonomousActor(
+          s, control_loops::drivetrain::GetDrivetrainConfig()) {}
+
+void AutonomousActor::Reset() {
+  elevator_goal_ = 0.01;
+  wrist_goal_ = -M_PI / 2.0;
+  intake_goal_ = -1.2;
+
+  suction_on_ = false;
+  suction_gamepiece_ = 1;
+
+  elevator_max_velocity_ = 0.0;
+  elevator_max_acceleration_ = 0.0;
+  wrist_max_velocity_ = 0.0;
+  wrist_max_acceleration_ = 0.0;
+
+  InitializeEncoders();
+  SendSuperstructureGoal();
+
+  {
+    auto localizer_resetter = localizer_control.MakeMessage();
+    // Start on the left l2.
+    localizer_resetter->x = 1.0;
+    localizer_resetter->y = 1.5;
+    localizer_resetter->theta = M_PI;
+    if (!localizer_resetter.Send()) {
+      LOG(ERROR, "Failed to reset localizer.\n");
+    }
+  }
+
+  // Wait for the drivetrain to run so it has time to reset the heading.
+  // Otherwise our drivetrain reset will do a 180 right at the start.
+  drivetrain_queue.status.FetchAnother();
+  LOG(INFO, "Heading is %f\n", drivetrain_queue.status->estimated_heading);
+  InitializeEncoders();
+  ResetDrivetrain();
+  drivetrain_queue.status.FetchAnother();
+  LOG(INFO, "Heading is %f\n", drivetrain_queue.status->estimated_heading);
+
+  ResetDrivetrain();
+  InitializeEncoders();
+}
+
+const ProfileParameters kJumpDrive = {2.0, 3.0};
+const ProfileParameters kDrive = {4.0, 3.0};
+const ProfileParameters kTurn = {5.0, 15.0};
+
+bool AutonomousActor::RunAction(
+    const ::frc971::autonomous::AutonomousActionParams &params) {
+  monotonic_clock::time_point start_time = monotonic_clock::now();
+  LOG(INFO, "Starting autonomous action with mode %" PRId32 "\n", params.mode);
+  Reset();
+
+  // Grab the disk, wait until we have vacuum, then jump
+  set_elevator_goal(0.01);
+  set_wrist_goal(-M_PI / 2.0);
+  set_intake_goal(-1.2);
+  set_suction_goal(true, 1);
+  SendSuperstructureGoal();
+
+  if (!WaitForGamePiece()) return true;
+  LOG(INFO, "Has game piece\n");
+
+  StartDrive(-4.5, 0.0, kJumpDrive, kTurn);
+  if (!WaitForDriveNear(3.8, 10.0)) return true;
+  LOG(INFO, "Lifting\n");
+  set_elevator_goal(0.30);
+  SendSuperstructureGoal();
+
+  if (!WaitForDriveNear(3.3, 10.0)) return true;
+  LOG(INFO, "Off the platform\n");
+
+  StartDrive(0.0, 1.00, kDrive, kTurn);
+  LOG(INFO, "Turn started\n");
+  if (!WaitForSuperstructureDone()) return true;
+  LOG(INFO, "Superstructure done\n");
+
+  if (!WaitForDriveNear(1.2, 10.0)) return true;
+  StartDrive(0.0, -0.35, kDrive, kTurn);
+
+  LOG(INFO, "Elevator up\n");
+  set_elevator_goal(0.01);
+  SendSuperstructureGoal();
+
+  if (!WaitForDriveDone()) return true;
+  LOG(INFO, "Done driving\n");
+
+  if (!WaitForSuperstructureDone()) return true;
+
+  LOG(INFO, "Done %f\n", DoubleSeconds(monotonic_clock::now() - start_time));
+
+  ::aos::time::PhasedLoop phased_loop(::std::chrono::milliseconds(5),
+                                      ::std::chrono::milliseconds(5) / 2);
+
+  while (!ShouldCancel()) {
+    phased_loop.SleepUntilNext();
+  }
+  LOG(DEBUG, "Done running\n");
+
+  return true;
+}
+
+}  // namespace actors
+}  // namespace y2019
diff --git a/y2019/actors/autonomous_actor.h b/y2019/actors/autonomous_actor.h
new file mode 100644
index 0000000..82e1aeb
--- /dev/null
+++ b/y2019/actors/autonomous_actor.h
@@ -0,0 +1,158 @@
+#ifndef Y2019_ACTORS_AUTONOMOUS_ACTOR_H_
+#define Y2019_ACTORS_AUTONOMOUS_ACTOR_H_
+
+#include <chrono>
+#include <memory>
+
+#include "aos/actions/actions.h"
+#include "aos/actions/actor.h"
+#include "frc971/autonomous/base_autonomous_actor.h"
+#include "frc971/control_loops/control_loops.q.h"
+#include "frc971/control_loops/drivetrain/drivetrain.q.h"
+#include "frc971/control_loops/drivetrain/drivetrain_config.h"
+#include "y2019/control_loops/superstructure/superstructure.q.h"
+
+namespace y2019 {
+namespace actors {
+
+using ::frc971::ProfileParameters;
+using ::y2019::control_loops::superstructure::superstructure_queue;
+
+class AutonomousActor : public ::frc971::autonomous::BaseAutonomousActor {
+ public:
+  explicit AutonomousActor(::frc971::autonomous::AutonomousActionQueueGroup *s);
+
+  bool RunAction(
+      const ::frc971::autonomous::AutonomousActionParams &params) override;
+
+ private:
+  void Reset();
+
+  double elevator_goal_ = 0.0;
+  double wrist_goal_ = 0.0;
+  double intake_goal_ = 0.0;
+
+  bool suction_on_ = true;
+  int suction_gamepiece_ = 1;
+
+  double elevator_max_velocity_ = 0.0;
+  double elevator_max_acceleration_ = 0.0;
+  double wrist_max_velocity_ = 0.0;
+  double wrist_max_acceleration_ = 0.0;
+
+  void set_elevator_goal(double elevator_goal) {
+    elevator_goal_ = elevator_goal;
+  }
+  void set_wrist_goal(double wrist_goal) { wrist_goal_ = wrist_goal; }
+  void set_intake_goal(double intake_goal) { intake_goal_ = intake_goal; }
+
+  void set_suction_goal(bool on, int gamepiece_mode) {
+    suction_on_ = on;
+    suction_gamepiece_ = gamepiece_mode;
+  }
+
+  void set_elevator_max_velocity(double elevator_max_velocity) {
+    elevator_max_velocity_ = elevator_max_velocity;
+  }
+  void set_elevator_max_acceleration(double elevator_max_acceleration) {
+    elevator_max_acceleration_ = elevator_max_acceleration;
+  }
+  void set_wrist_max_velocity(double wrist_max_velocity) {
+    wrist_max_velocity_ = wrist_max_velocity;
+  }
+  void set_wrist_max_acceleration(double wrist_max_acceleration) {
+    wrist_max_acceleration_ = wrist_max_acceleration;
+  }
+
+  void SendSuperstructureGoal() {
+    auto new_superstructure_goal = superstructure_queue.goal.MakeMessage();
+    new_superstructure_goal->elevator.unsafe_goal = elevator_goal_;
+    new_superstructure_goal->wrist.unsafe_goal = wrist_goal_;
+    new_superstructure_goal->intake.unsafe_goal = intake_goal_;
+
+    new_superstructure_goal->suction.grab_piece = suction_on_;
+    new_superstructure_goal->suction.gamepiece_mode = suction_gamepiece_;
+
+    new_superstructure_goal->elevator.profile_params.max_velocity =
+        elevator_max_velocity_;
+    new_superstructure_goal->elevator.profile_params.max_acceleration =
+        elevator_max_acceleration_;
+
+    new_superstructure_goal->wrist.profile_params.max_velocity =
+        wrist_max_velocity_;
+    new_superstructure_goal->wrist.profile_params.max_acceleration =
+        wrist_max_acceleration_;
+
+    if (!new_superstructure_goal.Send()) {
+      LOG(ERROR, "Sending superstructure goal failed.\n");
+    }
+  }
+
+  bool IsSucked() {
+    superstructure_queue.status.FetchLatest();
+
+    if (superstructure_queue.status.get()) {
+      return superstructure_queue.status->has_piece;
+    }
+    return false;
+  }
+
+  bool WaitForGamePiece() {
+    ::aos::time::PhasedLoop phased_loop(::std::chrono::milliseconds(5),
+                                        ::std::chrono::milliseconds(5) / 2);
+
+    while (true) {
+      if (ShouldCancel()) {
+        return false;
+      }
+      phased_loop.SleepUntilNext();
+      if (IsSucked()) {
+        return true;
+      }
+    }
+  }
+
+  bool IsSuperstructureDone() {
+    superstructure_queue.status.FetchLatest();
+
+    double kElevatorTolerance = 0.01;
+    double kWristTolerance = 0.05;
+
+    if (superstructure_queue.status.get()) {
+      const bool elevator_at_goal =
+          ::std::abs(elevator_goal_ -
+                     superstructure_queue.status->elevator.position) <
+          kElevatorTolerance;
+
+      const bool wrist_at_goal =
+          ::std::abs(wrist_goal_ -
+                     superstructure_queue.status->wrist.position) <
+          kWristTolerance;
+
+      return elevator_at_goal && wrist_at_goal;
+    }
+    return false;
+  }
+
+  bool WaitForSuperstructureDone() {
+    ::aos::time::PhasedLoop phased_loop(::std::chrono::milliseconds(5),
+                                        ::std::chrono::milliseconds(5) / 2);
+
+    while (true) {
+      if (ShouldCancel()) {
+        return false;
+      }
+      phased_loop.SleepUntilNext();
+      superstructure_queue.status.FetchLatest();
+      superstructure_queue.goal.FetchLatest();
+      if (IsSuperstructureDone()) {
+        return true;
+      }
+    }
+  }
+};
+
+}  // namespace actors
+}  // namespace y2019
+
+#endif  // Y2019_ACTORS_AUTONOMOUS_ACTOR_H_
diff --git a/y2019/actors/autonomous_actor_main.cc b/y2019/actors/autonomous_actor_main.cc
new file mode 100644
index 0000000..0a77eb9
--- /dev/null
+++ b/y2019/actors/autonomous_actor_main.cc
@@ -0,0 +1,16 @@
+#include <stdio.h>
+
+#include "aos/init.h"
+#include "frc971/autonomous/auto.q.h"
+#include "y2019/actors/autonomous_actor.h"
+
+int main(int /*argc*/, char * /*argv*/ []) {
+  ::aos::Init(-1);
+
+  ::y2019::actors::AutonomousActor autonomous(
+      &::frc971::autonomous::autonomous_action);
+  autonomous.Run();
+
+  ::aos::Cleanup();
+  return 0;
+}
diff --git a/y2019/jevois/teensy.cc b/y2019/jevois/teensy.cc
index 45a35b0..570892f 100644
--- a/y2019/jevois/teensy.cc
+++ b/y2019/jevois/teensy.cc
@@ -508,28 +508,6 @@
   PERIPHERAL_BITBAND(GPIOD_PDDR, 1) = 0;
   PORTD_PCR1 = PORT_PCR_DSE | PORT_PCR_MUX(1);
 
-  // Set LED pins to GPIO.
-  PERIPHERAL_BITBAND(GPIOC_PDDR, 11) = 1;
-  PORTC_PCR11 = PORT_PCR_DSE | PORT_PCR_MUX(1);
-  PERIPHERAL_BITBAND(GPIOC_PDDR, 10) = 1;
-  PORTC_PCR10 = PORT_PCR_DSE | PORT_PCR_MUX(1);
-  PERIPHERAL_BITBAND(GPIOC_PDDR, 8) = 1;
-  PORTC_PCR8 = PORT_PCR_DSE | PORT_PCR_MUX(1);
-  PERIPHERAL_BITBAND(GPIOC_PDDR, 9) = 1;
-  PORTC_PCR9 = PORT_PCR_DSE | PORT_PCR_MUX(1);
-  PERIPHERAL_BITBAND(GPIOB_PDDR, 18) = 1;
-  PORTB_PCR18 = PORT_PCR_DSE | PORT_PCR_MUX(1);
-  PERIPHERAL_BITBAND(GPIOC_PDDR, 2) = 1;
-  PORTC_PCR2 = PORT_PCR_DSE | PORT_PCR_MUX(1);
-  PERIPHERAL_BITBAND(GPIOD_PDDR, 7) = 1;
-  PORTD_PCR7 = PORT_PCR_DSE | PORT_PCR_MUX(1);
-  PERIPHERAL_BITBAND(GPIOC_PDDR, 1) = 1;
-  PORTC_PCR1 = PORT_PCR_DSE | PORT_PCR_MUX(1);
-  PERIPHERAL_BITBAND(GPIOB_PDDR, 19) = 1;
-  PORTB_PCR19 = PORT_PCR_DSE | PORT_PCR_MUX(1);
-  PERIPHERAL_BITBAND(GPIOD_PDDR, 5) = 1;
-  PORTD_PCR5 = PORT_PCR_DSE | PORT_PCR_MUX(1);
-
   auto next = aos::monotonic_clock::now();
   static constexpr auto kTick = std::chrono::seconds(1);
   while (true) {
@@ -705,8 +683,8 @@
         packetizers[i].clear_received_packet();
         if (decoded) {
           if (verbose) {
-            printf("uart frame cam %d, %d targets\n", (int)i,
-                   (int)decoded->targets.size());
+            printf("uart frame cam %d, %d targets\n", static_cast<int>(i),
+                   static_cast<int>(decoded->targets.size()));
           }
           frame_queue.UpdateFrame(i, *decoded);
           light_rings[i].last_frame = aos::monotonic_clock::now();
@@ -763,7 +741,6 @@
             const y2019::vision::CameraCalibration *const constants =
                 y2019::vision::GetCamera(y2019::vision::CameraSerialNumbers(
                     ProcessorIdentifier())[i]);
-            (void)constants;
             calibration.calibration(0, 0) = constants->intrinsics.mount_angle;
             calibration.calibration(0, 1) = constants->intrinsics.focal_length;
             calibration.calibration(0, 2) = constants->intrinsics.barrel_mount;
@@ -892,6 +869,9 @@
   // Clear the interrupt flag now that we've reconfigured it.
   PORTA_ISFR = 1 << 17;
 
+  // For now, we have no need to dim the LEDs, so we're just going to set them
+  // all to GPIO mode for simplicity of programming.
+#if 0
   // FTM0_CH0 is LED0 (7 in silkscreen, a beacon channel).
   PORTC_PCR1 = PORT_PCR_DSE | PORT_PCR_MUX(4);
   // FTM0_CH1 is LED1 (5 in silkscreen, a beacon channel).
@@ -914,6 +894,29 @@
   PORTC_PCR10 = PORT_PCR_DSE | PORT_PCR_MUX(3);
   // FTM3_CH7 is LED9 (for CAM0).
   PORTC_PCR11 = PORT_PCR_DSE | PORT_PCR_MUX(3);
+#else
+  // Set all the LED pins to GPIO.
+  PERIPHERAL_BITBAND(GPIOC_PDDR, 11) = 1;
+  PORTC_PCR11 = PORT_PCR_DSE | PORT_PCR_MUX(1);
+  PERIPHERAL_BITBAND(GPIOC_PDDR, 10) = 1;
+  PORTC_PCR10 = PORT_PCR_DSE | PORT_PCR_MUX(1);
+  PERIPHERAL_BITBAND(GPIOC_PDDR, 8) = 1;
+  PORTC_PCR8 = PORT_PCR_DSE | PORT_PCR_MUX(1);
+  PERIPHERAL_BITBAND(GPIOC_PDDR, 9) = 1;
+  PORTC_PCR9 = PORT_PCR_DSE | PORT_PCR_MUX(1);
+  PERIPHERAL_BITBAND(GPIOB_PDDR, 18) = 1;
+  PORTB_PCR18 = PORT_PCR_DSE | PORT_PCR_MUX(1);
+  PERIPHERAL_BITBAND(GPIOC_PDDR, 2) = 1;
+  PORTC_PCR2 = PORT_PCR_DSE | PORT_PCR_MUX(1);
+  PERIPHERAL_BITBAND(GPIOD_PDDR, 7) = 1;
+  PORTD_PCR7 = PORT_PCR_DSE | PORT_PCR_MUX(1);
+  PERIPHERAL_BITBAND(GPIOC_PDDR, 1) = 1;
+  PORTC_PCR1 = PORT_PCR_DSE | PORT_PCR_MUX(1);
+  PERIPHERAL_BITBAND(GPIOB_PDDR, 19) = 1;
+  PORTB_PCR19 = PORT_PCR_DSE | PORT_PCR_MUX(1);
+  PERIPHERAL_BITBAND(GPIOD_PDDR, 5) = 1;
+  PORTD_PCR5 = PORT_PCR_DSE | PORT_PCR_MUX(1);
+#endif
 
   // This hardware has been deactivated, but keep this comment for now to
   // document which pins it is on.
diff --git a/y2019/vision/constants.cc b/y2019/vision/constants.cc
index 6a41e14..310faf6 100644
--- a/y2019/vision/constants.cc
+++ b/y2019/vision/constants.cc
@@ -7,12 +7,12 @@
 
 CameraCalibration camera_1 = {
     {
-        -0.898335 / 180.0 * M_PI, 340.971, 1.90889 / 180.0 * M_PI,
+        -0.873939 / 180.0 * M_PI, 338.976, 2.44587 / 180.0 * M_PI,
     },
     {
-        {{-5.24755 * kInchesToMeters, 2.83241 * kInchesToMeters,
-          33.1178 * kInchesToMeters}},
-        181.873 / 180.0 * M_PI,
+        {{-5.46283 * kInchesToMeters, 2.98951 * kInchesToMeters,
+          33.0848 * kInchesToMeters}},
+        181.951 / 180.0 * M_PI,
     },
     {
         1,
@@ -61,12 +61,12 @@
 
 CameraCalibration camera_6 = {
     {
-        -1.11982 / 180.0 * M_PI, 347.32, 1.04799 / 180.0 * M_PI,
+        -1.15844 / 180.0 * M_PI, 348.161, 1.16894 / 180.0 * M_PI,
     },
     {
-        {{4.84356 * kInchesToMeters, 2.12355 * kInchesToMeters,
-          33.1812 * kInchesToMeters}},
-        -11.888 / 180.0 * M_PI,
+        {{4.73183 * kInchesToMeters, 2.0984 * kInchesToMeters,
+          33.2023 * kInchesToMeters}},
+        -11.8598 / 180.0 * M_PI,
     },
     {
         6,
@@ -79,12 +79,12 @@
 
 CameraCalibration camera_7 = {
     {
-        -2.21509 / 180.0 * M_PI, 328.2, 0.922133 / 180.0 * M_PI,
+        -2.24098 / 180.0 * M_PI, 339.231, 1.15487 / 180.0 * M_PI,
     },
     {
-        {{4.7585 * kInchesToMeters, 3.99542 * kInchesToMeters,
-          33.1932 * kInchesToMeters}},
-        19.2585 / 180.0 * M_PI,
+        {{3.50224 * kInchesToMeters, 3.95441 * kInchesToMeters,
+          33.3469 * kInchesToMeters}},
+        18.6782 / 180.0 * M_PI,
     },
     {
         7,
@@ -97,12 +97,12 @@
 
 CameraCalibration camera_8 = {
     {
-        37.1314 / 180.0 * M_PI, 340.763, -0.136505 / 180.0 * M_PI,
+        37.1859 / 180.0 * M_PI, 339.517, 0.0405714 / 180.0 * M_PI,
     },
     {
-        {{3.61159 * kInchesToMeters, 5.16559 * kInchesToMeters,
-          12.6279 * kInchesToMeters}},
-        92.78 / 180.0 * M_PI,
+        {{3.57002 * kInchesToMeters, 5.26966 * kInchesToMeters,
+          12.6807 * kInchesToMeters}},
+        92.6787 / 180.0 * M_PI,
     },
     {
         8,
@@ -115,12 +115,12 @@
 
 CameraCalibration camera_9 = {
     {
-        35.4057 / 180.0 * M_PI, 337.052, 3.57896 / 180.0 * M_PI,
+        35.4154 / 180.0 * M_PI, 337.471, 3.30546 / 180.0 * M_PI,
     },
     {
-        {{4.28266 * kInchesToMeters, -3.04674 * kInchesToMeters,
-          11.4219 * kInchesToMeters}},
-        -93.3496 / 180.0 * M_PI,
+        {{4.25679 * kInchesToMeters, -2.93066 * kInchesToMeters,
+          11.3228 * kInchesToMeters}},
+        -93.219 / 180.0 * M_PI,
     },
     {
         9,
@@ -133,12 +133,12 @@
 
 CameraCalibration camera_10 = {
     {
-        -0.263033 / 180.0 * M_PI, 347.579, 0.213753 / 180.0 * M_PI,
+        -0.190556 / 180.0 * M_PI, 345.022, 0.468494 / 180.0 * M_PI,
     },
     {
-        {{-4.71537 * kInchesToMeters, 2.87784 * kInchesToMeters,
-          33.3979 * kInchesToMeters}},
-        182.17 / 180.0 * M_PI,
+        {{-4.83005 * kInchesToMeters, 2.95565 * kInchesToMeters,
+          33.3624 * kInchesToMeters}},
+        182.204 / 180.0 * M_PI,
     },
     {
         10,
@@ -151,12 +151,12 @@
 
 CameraCalibration camera_14 = {
     {
-        -0.0448007 / 180.0 * M_PI, 343.776, 0.682175 / 180.0 * M_PI,
+        0.108434 / 180.0 * M_PI, 338.756, 0.606249 / 180.0 * M_PI,
     },
     {
-        {{5.51139 * kInchesToMeters, 2.06852 * kInchesToMeters,
-          33.2133 * kInchesToMeters}},
-        -12.2943 / 180.0 * M_PI,
+        {{5.90372 * kInchesToMeters, 2.08009 * kInchesToMeters,
+          33.1342 * kInchesToMeters}},
+        -12.4624 / 180.0 * M_PI,
     },
     {
         14,
@@ -169,12 +169,12 @@
 
 CameraCalibration camera_15 = {
     {
-        -0.699071 / 180.0 * M_PI, 343.108, 1.59015 / 180.0 * M_PI,
+        -0.855459 / 180.0 * M_PI, 348.799, 1.4559 / 180.0 * M_PI,
     },
     {
-        {{3.83957 * kInchesToMeters, 4.15371 * kInchesToMeters,
-          33.5056 * kInchesToMeters}},
-        20.6893 / 180.0 * M_PI,
+        {{3.15291 * kInchesToMeters, 4.16556 * kInchesToMeters,
+          33.5924 * kInchesToMeters}},
+        20.3884 / 180.0 * M_PI,
     },
     {
         15,
@@ -205,12 +205,12 @@
 
 CameraCalibration camera_17 = {
     {
-        34.8608 / 180.0 * M_PI, 337.479, 2.37199 / 180.0 * M_PI,
+        34.8231 / 180.0 * M_PI, 338.051, 2.43035 / 180.0 * M_PI,
     },
     {
-        {{3.1435 * kInchesToMeters, -2.56124 * kInchesToMeters,
-          11.8428 * kInchesToMeters}},
-        -92.0541 / 180.0 * M_PI,
+        {{3.17222 * kInchesToMeters, -2.49752 * kInchesToMeters,
+          11.8333 * kInchesToMeters}},
+        -92.1018 / 180.0 * M_PI,
     },
     {
         17,
@@ -223,12 +223,12 @@
 
 CameraCalibration camera_18 = {
     {
-        33.9889 / 180.0 * M_PI, 337.936, -2.23211 / 180.0 * M_PI,
+        33.9761 / 180.0 * M_PI, 338.017, -2.32243 / 180.0 * M_PI,
     },
     {
-        {{3.93503 * kInchesToMeters, 5.52062 * kInchesToMeters,
-          12.3607 * kInchesToMeters}},
-        96.3738 / 180.0 * M_PI,
+        {{3.95182 * kInchesToMeters, 5.50479 * kInchesToMeters,
+          12.3506 * kInchesToMeters}},
+        96.4141 / 180.0 * M_PI,
     },
     {
         18,