Convert aos over to flatbuffers

Everything builds, and all the tests pass.  I suspect that some entries
are missing from the config files, but those will be found pretty
quickly on startup.

There is no logging or live introspection of queue messages.

Change-Id: I496ee01ed68f202c7851bed7e8786cee30df29f5
diff --git a/y2014/control_loops/claw/BUILD b/y2014/control_loops/claw/BUILD
index 6c162e6..670dd76 100644
--- a/y2014/control_loops/claw/BUILD
+++ b/y2014/control_loops/claw/BUILD
@@ -1,16 +1,40 @@
 package(default_visibility = ["//visibility:public"])
 
-load("//aos/build:queues.bzl", "queue_library")
+load("@com_github_google_flatbuffers//:build_defs.bzl", "flatbuffer_cc_library")
 
-queue_library(
-    name = "claw_queue",
+flatbuffer_cc_library(
+    name = "claw_goal_fbs",
     srcs = [
-        "claw.q",
+        "claw_goal.fbs",
     ],
-    deps = [
-        "//aos/controls:control_loop_queues",
-        "//frc971/control_loops:queues",
+    gen_reflections = 1,
+)
+
+flatbuffer_cc_library(
+    name = "claw_position_fbs",
+    srcs = [
+        "claw_position.fbs",
     ],
+    gen_reflections = 1,
+    includes = [
+        "//frc971/control_loops:control_loops_fbs_includes",
+    ],
+)
+
+flatbuffer_cc_library(
+    name = "claw_output_fbs",
+    srcs = [
+        "claw_output.fbs",
+    ],
+    gen_reflections = 1,
+)
+
+flatbuffer_cc_library(
+    name = "claw_status_fbs",
+    srcs = [
+        "claw_status.fbs",
+    ],
+    gen_reflections = 1,
 )
 
 genrule(
@@ -40,12 +64,13 @@
         "-lm",
     ],
     deps = [
-        ":claw_queue",
+        ":claw_goal_fbs",
+        ":claw_output_fbs",
+        ":claw_position_fbs",
+        ":claw_status_fbs",
         "//aos:math",
         "//aos/controls:control_loop",
         "//aos/controls:polytope",
-        "//aos/logging:matrix_logging",
-        "//aos/logging:queue_logging",
         "//frc971/control_loops:coerce_goal",
         "//frc971/control_loops:hall_effect_tracker",
         "//frc971/control_loops:state_feedback_loop",
@@ -58,9 +83,13 @@
     srcs = [
         "claw_lib_test.cc",
     ],
+    data = ["//y2014:config.json"],
     deps = [
+        ":claw_goal_fbs",
         ":claw_lib",
-        ":claw_queue",
+        ":claw_output_fbs",
+        ":claw_position_fbs",
+        ":claw_status_fbs",
         "//aos/controls:control_loop_test",
         "//aos/testing:googletest",
         "//frc971/control_loops:state_feedback_loop",
@@ -76,6 +105,6 @@
     deps = [
         ":claw_lib",
         "//aos:init",
-        "//aos/events:shm-event-loop",
+        "//aos/events:shm_event_loop",
     ],
 )
diff --git a/y2014/control_loops/claw/claw.cc b/y2014/control_loops/claw/claw.cc
index 14dbf11..56ca6b0 100644
--- a/y2014/control_loops/claw/claw.cc
+++ b/y2014/control_loops/claw/claw.cc
@@ -2,10 +2,7 @@
 
 #include <algorithm>
 
-#include "aos/controls/control_loops.q.h"
 #include "aos/logging/logging.h"
-#include "aos/logging/queue_logging.h"
-#include "aos/logging/matrix_logging.h"
 #include "aos/commonmath.h"
 
 #include "y2014/constants.h"
@@ -46,11 +43,11 @@
 
 namespace y2014 {
 namespace control_loops {
+namespace claw {
 
 using ::frc971::HallEffectTracker;
 using ::y2014::control_loops::claw::kDt;
 using ::frc971::control_loops::DoCoerceGoal;
-using ::y2014::control_loops::ClawPositionToLog;
 
 static const double kZeroingVoltage = 4.0;
 static const double kMaxVoltage = 12.0;
@@ -94,7 +91,7 @@
   double max_voltage = is_zeroing_ ? kZeroingVoltage : kMaxVoltage;
 
   if (::std::abs(u_bottom) > max_voltage || ::std::abs(u_top) > max_voltage) {
-    AOS_LOG_MATRIX(DEBUG, "U at start", U());
+    VLOG(1) << "U at start " << U();
     // H * U <= k
     // U = UPos + UVel
     // H * (UPos + UVel) <= k
@@ -116,7 +113,7 @@
     position_error << error(0, 0), error(1, 0);
     Eigen::Matrix<double, 2, 1> velocity_error;
     velocity_error << error(2, 0), error(3, 0);
-    AOS_LOG_MATRIX(DEBUG, "error", error);
+    VLOG(1) << "error " << error;
 
     const auto &poly = is_zeroing_ ? U_Poly_zeroing_ : U_Poly_;
     const Eigen::Matrix<double, 4, 2> pos_poly_H = poly.H() * position_K;
@@ -183,9 +180,9 @@
       }
     }
 
-    AOS_LOG_MATRIX(DEBUG, "adjusted_pos_error", adjusted_pos_error);
+    VLOG(1) << "adjusted_pos_error " << adjusted_pos_error;
     mutable_U() = velocity_K * velocity_error + position_K * adjusted_pos_error;
-    AOS_LOG_MATRIX(DEBUG, "U is now", U());
+    VLOG(1) << "U is now" << U();
 
     {
       const auto values = constants::GetValues().claw;
@@ -221,69 +218,68 @@
       encoder_(0.0),
       last_encoder_(0.0) {}
 
-void ZeroedStateFeedbackLoop::SetPositionValues(
-    const ::y2014::control_loops::HalfClawPosition &claw) {
-  front_.Update(claw.front);
-  calibration_.Update(claw.calibration);
-  back_.Update(claw.back);
+void ZeroedStateFeedbackLoop::SetPositionValues(const HalfClawPosition *claw) {
+  front_.Update(claw->front());
+  calibration_.Update(claw->calibration());
+  back_.Update(claw->back());
 
   bool any_sensor_triggered = any_triggered();
   if (any_sensor_triggered && any_triggered_last_) {
     // We are still on the hall effect and nothing has changed.
     min_hall_effect_on_angle_ =
-        ::std::min(min_hall_effect_on_angle_, claw.position);
+        ::std::min(min_hall_effect_on_angle_, claw->position());
     max_hall_effect_on_angle_ =
-        ::std::max(max_hall_effect_on_angle_, claw.position);
+        ::std::max(max_hall_effect_on_angle_, claw->position());
   } else if (!any_sensor_triggered && !any_triggered_last_) {
     // We are still off the hall effect and nothing has changed.
     min_hall_effect_off_angle_ =
-        ::std::min(min_hall_effect_off_angle_, claw.position);
+        ::std::min(min_hall_effect_off_angle_, claw->position());
     max_hall_effect_off_angle_ =
-        ::std::max(max_hall_effect_off_angle_, claw.position);
+        ::std::max(max_hall_effect_off_angle_, claw->position());
   }
 
   if (front_.is_posedge()) {
     // Saw a posedge on the hall effect.  Reset the limits.
     min_hall_effect_on_angle_ =
-        ::std::min(claw.front.posedge_value, claw.position);
+        ::std::min(claw->front()->posedge_value(), claw->position());
     max_hall_effect_on_angle_ =
-        ::std::max(claw.front.posedge_value, claw.position);
+        ::std::max(claw->front()->posedge_value(), claw->position());
   }
   if (calibration_.is_posedge()) {
     // Saw a posedge on the hall effect.  Reset the limits.
     min_hall_effect_on_angle_ =
-        ::std::min(claw.calibration.posedge_value, claw.position);
+        ::std::min(claw->calibration()->posedge_value(), claw->position());
     max_hall_effect_on_angle_ =
-        ::std::max(claw.calibration.posedge_value, claw.position);
+        ::std::max(claw->calibration()->posedge_value(), claw->position());
   }
   if (back_.is_posedge()) {
     // Saw a posedge on the hall effect.  Reset the limits.
     min_hall_effect_on_angle_ =
-        ::std::min(claw.back.posedge_value, claw.position);
+        ::std::min(claw->back()->posedge_value(), claw->position());
     max_hall_effect_on_angle_ =
-        ::std::max(claw.back.posedge_value, claw.position);
+        ::std::max(claw->back()->posedge_value(), claw->position());
   }
 
   if (front_.is_negedge()) {
     // Saw a negedge on the hall effect.  Reset the limits.
     min_hall_effect_off_angle_ =
-        ::std::min(claw.front.negedge_value, claw.position);
+        ::std::min(claw->front()->negedge_value(), claw->position());
     max_hall_effect_off_angle_ =
-        ::std::max(claw.front.negedge_value, claw.position);
+        ::std::max(claw->front()->negedge_value(), claw->position());
   }
   if (calibration_.is_negedge()) {
     // Saw a negedge on the hall effect.  Reset the limits.
     min_hall_effect_off_angle_ =
-        ::std::min(claw.calibration.negedge_value, claw.position);
+        ::std::min(claw->calibration()->negedge_value(), claw->position());
     max_hall_effect_off_angle_ =
-        ::std::max(claw.calibration.negedge_value, claw.position);
+        ::std::max(claw->calibration()->negedge_value(), claw->position());
   }
   if (back_.is_negedge()) {
     // Saw a negedge on the hall effect.  Reset the limits.
     min_hall_effect_off_angle_ =
-        ::std::min(claw.back.negedge_value, claw.position);
+        ::std::min(claw->back()->negedge_value(), claw->position());
     max_hall_effect_off_angle_ =
-        ::std::max(claw.back.negedge_value, claw.position);
+        ::std::max(claw->back()->negedge_value(), claw->position());
   }
 
   last_encoder_ = encoder_;
@@ -292,23 +288,22 @@
   } else {
     last_off_encoder_ = encoder_;
   }
-  encoder_ = claw.position;
+  encoder_ = claw->position();
   any_triggered_last_ = any_sensor_triggered;
 }
 
-void ZeroedStateFeedbackLoop::Reset(
-    const ::y2014::control_loops::HalfClawPosition &claw) {
+void ZeroedStateFeedbackLoop::Reset(const HalfClawPosition *claw) {
   set_zeroing_state(ZeroedStateFeedbackLoop::UNKNOWN_POSITION);
 
-  front_.Reset(claw.front);
-  calibration_.Reset(claw.calibration);
-  back_.Reset(claw.back);
+  front_.Reset(claw->front());
+  calibration_.Reset(claw->calibration());
+  back_.Reset(claw->back());
   // close up the min and max edge positions as they are no longer valid and
   // will be expanded in future iterations
-  min_hall_effect_on_angle_ = claw.position;
-  max_hall_effect_on_angle_ = claw.position;
-  min_hall_effect_off_angle_ = claw.position;
-  max_hall_effect_off_angle_ = claw.position;
+  min_hall_effect_on_angle_ = claw->position();
+  max_hall_effect_on_angle_ = claw->position();
+  min_hall_effect_off_angle_ = claw->position();
+  max_hall_effect_off_angle_ = claw->position();
   any_triggered_last_ = any_triggered();
 }
 
@@ -374,8 +369,8 @@
 }
 
 ClawMotor::ClawMotor(::aos::EventLoop *event_loop, const ::std::string &name)
-    : aos::controls::ControlLoop<::y2014::control_loops::ClawQueue>(event_loop,
-                                                                    name),
+    : aos::controls::ControlLoop<Goal, Position, Status, Output>(event_loop,
+                                                                 name),
       has_top_claw_goal_(false),
       top_claw_goal_(0.0),
       top_claw_(this),
@@ -563,45 +558,33 @@
   // first update position based on angle limit
   const double separation = *top_goal - *bottom_goal;
   if (separation > values.claw.soft_max_separation) {
-    AOS_LOG_STRUCT(DEBUG, "before", ClawPositionToLog(*top_goal, *bottom_goal));
     const double dsep = (separation - values.claw.soft_max_separation) / 2.0;
     *bottom_goal += dsep;
     *top_goal -= dsep;
-    AOS_LOG_STRUCT(DEBUG, "after", ClawPositionToLog(*top_goal, *bottom_goal));
   }
   if (separation < values.claw.soft_min_separation) {
-    AOS_LOG_STRUCT(DEBUG, "before", ClawPositionToLog(*top_goal, *bottom_goal));
     const double dsep = (separation - values.claw.soft_min_separation) / 2.0;
     *bottom_goal += dsep;
     *top_goal -= dsep;
-    AOS_LOG_STRUCT(DEBUG, "after", ClawPositionToLog(*top_goal, *bottom_goal));
   }
 
   // now move both goals in unison
   if (*bottom_goal < values.claw.lower_claw.lower_limit) {
-    AOS_LOG_STRUCT(DEBUG, "before", ClawPositionToLog(*top_goal, *bottom_goal));
     *top_goal += values.claw.lower_claw.lower_limit - *bottom_goal;
     *bottom_goal = values.claw.lower_claw.lower_limit;
-    AOS_LOG_STRUCT(DEBUG, "after", ClawPositionToLog(*top_goal, *bottom_goal));
   }
   if (*bottom_goal > values.claw.lower_claw.upper_limit) {
-    AOS_LOG_STRUCT(DEBUG, "before", ClawPositionToLog(*top_goal, *bottom_goal));
     *top_goal -= *bottom_goal - values.claw.lower_claw.upper_limit;
     *bottom_goal = values.claw.lower_claw.upper_limit;
-    AOS_LOG_STRUCT(DEBUG, "after", ClawPositionToLog(*top_goal, *bottom_goal));
   }
 
   if (*top_goal < values.claw.upper_claw.lower_limit) {
-    AOS_LOG_STRUCT(DEBUG, "before", ClawPositionToLog(*top_goal, *bottom_goal));
     *bottom_goal += values.claw.upper_claw.lower_limit - *top_goal;
     *top_goal = values.claw.upper_claw.lower_limit;
-    AOS_LOG_STRUCT(DEBUG, "after", ClawPositionToLog(*top_goal, *bottom_goal));
   }
   if (*top_goal > values.claw.upper_claw.upper_limit) {
-    AOS_LOG_STRUCT(DEBUG, "before", ClawPositionToLog(*top_goal, *bottom_goal));
     *bottom_goal -= *top_goal - values.claw.upper_claw.upper_limit;
     *top_goal = values.claw.upper_claw.upper_limit;
-    AOS_LOG_STRUCT(DEBUG, "after", ClawPositionToLog(*top_goal, *bottom_goal));
   }
 }
 
@@ -609,7 +592,7 @@
   return (
       (top_claw_.zeroing_state() == ZeroedStateFeedbackLoop::CALIBRATED &&
        bottom_claw_.zeroing_state() == ZeroedStateFeedbackLoop::CALIBRATED) ||
-      ((has_joystick_state() ? joystick_state().autonomous : true) &&
+      ((has_joystick_state() ? joystick_state().autonomous() : true) &&
        ((top_claw_.zeroing_state() == ZeroedStateFeedbackLoop::CALIBRATED ||
          top_claw_.zeroing_state() ==
              ZeroedStateFeedbackLoop::DISABLED_CALIBRATION) &&
@@ -621,43 +604,45 @@
 bool ClawMotor::is_zeroing() const { return !is_ready(); }
 
 // Positive angle is up, and positive power is up.
-void ClawMotor::RunIteration(
-    const ::y2014::control_loops::ClawQueue::Goal *goal,
-    const ::y2014::control_loops::ClawQueue::Position *position,
-    ::y2014::control_loops::ClawQueue::Output *output,
-    ::y2014::control_loops::ClawQueue::Status *status) {
+void ClawMotor::RunIteration(const Goal *goal, const Position *position,
+                             aos::Sender<Output>::Builder *output,
+                             aos::Sender<Status>::Builder *status) {
   // Disable the motors now so that all early returns will return with the
   // motors disabled.
+  OutputT output_struct;
   if (output) {
-    output->top_claw_voltage = 0;
-    output->bottom_claw_voltage = 0;
-    output->intake_voltage = 0;
-    output->tusk_voltage = 0;
+    output_struct.top_claw_voltage = 0;
+    output_struct.bottom_claw_voltage = 0;
+    output_struct.intake_voltage = 0;
+    output_struct.tusk_voltage = 0;
   }
 
+  StatusT status_struct;
   if (goal) {
-    if (::std::isnan(goal->bottom_angle) ||
-        ::std::isnan(goal->separation_angle) || ::std::isnan(goal->intake) ||
-        ::std::isnan(goal->centering)) {
+    if (::std::isnan(goal->bottom_angle()) ||
+        ::std::isnan(goal->separation_angle()) ||
+        ::std::isnan(goal->intake()) || ::std::isnan(goal->centering())) {
+      status->Send(Status::Pack(*status->fbb(), &status_struct));
+      output->Send(Output::Pack(*output->fbb(), &output_struct));
       return;
     }
   }
 
   if (WasReset()) {
-    top_claw_.Reset(position->top);
-    bottom_claw_.Reset(position->bottom);
+    top_claw_.Reset(position->top());
+    bottom_claw_.Reset(position->bottom());
   }
 
   const constants::Values &values = constants::GetValues();
 
   if (position) {
     Eigen::Matrix<double, 2, 1> Y;
-    Y << position->bottom.position + bottom_claw_.offset(),
-        position->top.position + top_claw_.offset();
+    Y << position->bottom()->position() + bottom_claw_.offset(),
+        position->top()->position() + top_claw_.offset();
     claw_.Correct(Y);
 
-    top_claw_.SetPositionValues(position->top);
-    bottom_claw_.SetPositionValues(position->bottom);
+    top_claw_.SetPositionValues(position->top());
+    bottom_claw_.SetPositionValues(position->bottom());
 
     if (!has_top_claw_goal_) {
       has_top_claw_goal_ = true;
@@ -671,15 +656,12 @@
       initial_separation_ =
           top_claw_.absolute_position() - bottom_claw_.absolute_position();
     }
-    AOS_LOG_STRUCT(DEBUG, "absolute position",
-                   ClawPositionToLog(top_claw_.absolute_position(),
-                                     bottom_claw_.absolute_position()));
   }
 
   bool autonomous, enabled;
   if (has_joystick_state()) {
-    autonomous = joystick_state().autonomous;
-    enabled = joystick_state().enabled;
+    autonomous = joystick_state().autonomous();
+    enabled = joystick_state().enabled();
   } else {
     autonomous = true;
     enabled = false;
@@ -700,8 +682,8 @@
               ZeroedStateFeedbackLoop::DISABLED_CALIBRATION))))) {
     // Ready to use the claw.
     // Limit the goals here.
-    bottom_claw_goal_ = goal->bottom_angle;
-    top_claw_goal_ = goal->bottom_angle + goal->separation_angle;
+    bottom_claw_goal_ = goal->bottom_angle();
+    top_claw_goal_ = goal->bottom_angle() + goal->separation_angle();
     has_bottom_claw_goal_ = true;
     has_top_claw_goal_ = true;
     doing_calibration_fine_tune_ = false;
@@ -759,7 +741,7 @@
                             bottom_claw_.back())) {
           // do calibration
           bottom_claw_.SetCalibration(
-              position->bottom.calibration.posedge_value,
+              position->bottom()->calibration()->posedge_value(),
               values.claw.lower_claw.calibration.lower_angle);
           bottom_claw_.set_zeroing_state(ZeroedStateFeedbackLoop::CALIBRATED);
           // calibrated so we are done fine tuning bottom
@@ -816,7 +798,7 @@
                                          top_claw_.front(), top_claw_.back())) {
           // do calibration
           top_claw_.SetCalibration(
-              position->top.calibration.posedge_value,
+              position->top()->calibration()->posedge_value(),
               values.claw.upper_claw.calibration.lower_angle);
           top_claw_.set_zeroing_state(ZeroedStateFeedbackLoop::CALIBRATED);
           // calibrated so we are done fine tuning top
@@ -836,10 +818,11 @@
     doing_calibration_fine_tune_ = false;
     if (!was_enabled_ && enabled) {
       if (position) {
-        top_claw_goal_ = position->top.position + top_claw_.offset();
-        bottom_claw_goal_ = position->bottom.position + bottom_claw_.offset();
+        top_claw_goal_ = position->top()->position() + top_claw_.offset();
+        bottom_claw_goal_ =
+            position->bottom()->position() + bottom_claw_.offset();
         initial_separation_ =
-            position->top.position - position->bottom.position;
+            position->top()->position() - position->bottom()->position();
       } else {
         has_top_claw_goal_ = false;
         has_bottom_claw_goal_ = false;
@@ -907,7 +890,6 @@
   if (has_top_claw_goal_ && has_bottom_claw_goal_) {
     claw_.mutable_R() << bottom_claw_goal_, top_claw_goal_ - bottom_claw_goal_,
         bottom_claw_velocity_, top_claw_velocity_ - bottom_claw_velocity_;
-    AOS_LOG_MATRIX(DEBUG, "actual goal", claw_.R());
 
     // Only cap power when one of the halves of the claw is moving slowly and
     // could wind up.
@@ -973,55 +955,60 @@
   if (output) {
     if (goal) {
       //setup the intake
-      output->intake_voltage =
-          (goal->intake > 12.0) ? 12 : (goal->intake < -12.0) ? -12.0
-                                                              : goal->intake;
-      output->tusk_voltage = goal->centering;
-      output->tusk_voltage =
-          (goal->centering > 12.0) ? 12 : (goal->centering < -12.0)
+      output_struct.intake_voltage =
+          (goal->intake() > 12.0)
+              ? 12
+              : (goal->intake() < -12.0) ? -12.0 : goal->intake();
+      output_struct.tusk_voltage = goal->centering();
+      output_struct.tusk_voltage =
+          (goal->centering() > 12.0) ? 12 : (goal->centering() < -12.0)
               ? -12.0
-              : goal->centering;
+              : goal->centering();
     }
-    output->top_claw_voltage = claw_.U(1, 0);
-    output->bottom_claw_voltage = claw_.U(0, 0);
+    output_struct.top_claw_voltage = claw_.U(1, 0);
+    output_struct.bottom_claw_voltage = claw_.U(0, 0);
 
-    if (output->top_claw_voltage > kMaxVoltage) {
-      output->top_claw_voltage = kMaxVoltage;
-    } else if (output->top_claw_voltage < -kMaxVoltage) {
-      output->top_claw_voltage = -kMaxVoltage;
+    if (output_struct.top_claw_voltage > kMaxVoltage) {
+      output_struct.top_claw_voltage = kMaxVoltage;
+    } else if (output_struct.top_claw_voltage < -kMaxVoltage) {
+      output_struct.top_claw_voltage = -kMaxVoltage;
     }
 
-    if (output->bottom_claw_voltage > kMaxVoltage) {
-      output->bottom_claw_voltage = kMaxVoltage;
-    } else if (output->bottom_claw_voltage < -kMaxVoltage) {
-      output->bottom_claw_voltage = -kMaxVoltage;
+    if (output_struct.bottom_claw_voltage > kMaxVoltage) {
+      output_struct.bottom_claw_voltage = kMaxVoltage;
+    } else if (output_struct.bottom_claw_voltage < -kMaxVoltage) {
+      output_struct.bottom_claw_voltage = -kMaxVoltage;
     }
+
+    output->Send(Output::Pack(*output->fbb(), &output_struct));
   }
 
-  status->bottom = bottom_absolute_position();
-  status->separation = top_absolute_position() - bottom_absolute_position();
-  status->bottom_velocity = claw_.X_hat(2, 0);
-  status->separation_velocity = claw_.X_hat(3, 0);
+  status_struct.bottom = bottom_absolute_position();
+  status_struct.separation =
+      top_absolute_position() - bottom_absolute_position();
+  status_struct.bottom_velocity = claw_.X_hat(2, 0);
+  status_struct.separation_velocity = claw_.X_hat(3, 0);
 
   if (goal) {
     bool bottom_done =
-        ::std::abs(bottom_absolute_position() - goal->bottom_angle) < 0.020;
-    bool bottom_velocity_done = ::std::abs(status->bottom_velocity) < 0.2;
+        ::std::abs(bottom_absolute_position() - goal->bottom_angle()) < 0.020;
+    bool bottom_velocity_done = ::std::abs(status_struct.bottom_velocity) < 0.2;
     bool separation_done =
         ::std::abs((top_absolute_position() - bottom_absolute_position()) -
-                   goal->separation_angle) < 0.020;
+                   goal->separation_angle()) < 0.020;
     bool separation_done_with_ball =
         ::std::abs((top_absolute_position() - bottom_absolute_position()) -
-                   goal->separation_angle) < 0.06;
-    status->done = is_ready() && separation_done && bottom_done && bottom_velocity_done;
-    status->done_with_ball =
-        is_ready() && separation_done_with_ball && bottom_done && bottom_velocity_done;
+                   goal->separation_angle()) < 0.06;
+    status_struct.done =
+        is_ready() && separation_done && bottom_done && bottom_velocity_done;
+    status_struct.done_with_ball = is_ready() && separation_done_with_ball &&
+                                   bottom_done && bottom_velocity_done;
   } else {
-    status->done = status->done_with_ball = false;
+    status_struct.done = status_struct.done_with_ball = false;
   }
 
-  status->zeroed = is_ready();
-  status->zeroed_for_auto =
+  status_struct.zeroed = is_ready();
+  status_struct.zeroed_for_auto =
       (top_claw_.zeroing_state() == ZeroedStateFeedbackLoop::CALIBRATED ||
        top_claw_.zeroing_state() ==
            ZeroedStateFeedbackLoop::DISABLED_CALIBRATION) &&
@@ -1029,8 +1016,11 @@
        bottom_claw_.zeroing_state() ==
            ZeroedStateFeedbackLoop::DISABLED_CALIBRATION);
 
+  status->Send(Status::Pack(*status->fbb(), &status_struct));
+
   was_enabled_ = enabled;
 }
 
+}  // namespace claw
 }  // namespace control_loops
 }  // namespace y2014
diff --git a/y2014/control_loops/claw/claw.h b/y2014/control_loops/claw/claw.h
index 082ddce..5bcccc1 100644
--- a/y2014/control_loops/claw/claw.h
+++ b/y2014/control_loops/claw/claw.h
@@ -5,15 +5,19 @@
 
 #include "aos/controls/control_loop.h"
 #include "aos/controls/polytope.h"
-#include "y2014/constants.h"
-#include "frc971/control_loops/state_feedback_loop.h"
 #include "frc971/control_loops/coerce_goal.h"
-#include "y2014/control_loops/claw/claw.q.h"
-#include "y2014/control_loops/claw/claw_motor_plant.h"
 #include "frc971/control_loops/hall_effect_tracker.h"
+#include "frc971/control_loops/state_feedback_loop.h"
+#include "y2014/constants.h"
+#include "y2014/control_loops/claw/claw_goal_generated.h"
+#include "y2014/control_loops/claw/claw_motor_plant.h"
+#include "y2014/control_loops/claw/claw_output_generated.h"
+#include "y2014/control_loops/claw/claw_position_generated.h"
+#include "y2014/control_loops/claw/claw_status_generated.h"
 
 namespace y2014 {
 namespace control_loops {
+namespace claw {
 namespace testing {
 class WindupClawTest;
 };
@@ -77,9 +81,9 @@
   }
   JointZeroingState zeroing_state() const { return zeroing_state_; }
 
-  void SetPositionValues(const ::y2014::control_loops::HalfClawPosition &claw);
+  void SetPositionValues(const HalfClawPosition *claw);
 
-  void Reset(const ::y2014::control_loops::HalfClawPosition &claw);
+  void Reset(const HalfClawPosition *claw);
 
   double absolute_position() const { return encoder() + offset(); }
 
@@ -183,11 +187,10 @@
 };
 
 class ClawMotor
-    : public aos::controls::ControlLoop<::y2014::control_loops::ClawQueue> {
+    : public aos::controls::ControlLoop<Goal, Position, Status, Output> {
  public:
-  explicit ClawMotor(
-      ::aos::EventLoop *event_loop,
-      const ::std::string &name = ".y2014.control_loops.claw_queue");
+  explicit ClawMotor(::aos::EventLoop *event_loop,
+                     const ::std::string &name = "/claw");
 
   // True if the state machine is ready.
   bool capped_goal() const { return capped_goal_; }
@@ -217,11 +220,9 @@
   CalibrationMode mode() const { return mode_; }
 
  protected:
-  virtual void RunIteration(
-      const ::y2014::control_loops::ClawQueue::Goal *goal,
-      const ::y2014::control_loops::ClawQueue::Position *position,
-      ::y2014::control_loops::ClawQueue::Output *output,
-      ::y2014::control_loops::ClawQueue::Status *status);
+  virtual void RunIteration(const Goal *goal, const Position *position,
+                            aos::Sender<Output>::Builder *output,
+                            aos::Sender<Status>::Builder *status);
 
   double top_absolute_position() const {
     return claw_.X_hat(1, 0) + claw_.X_hat(0, 0);
@@ -262,6 +263,7 @@
 void LimitClawGoal(double *bottom_goal, double *top_goal,
                    const constants::Values &values);
 
+}  // namespace claw
 }  // namespace control_loops
 }  // namespace y2014
 
diff --git a/y2014/control_loops/claw/claw.q b/y2014/control_loops/claw/claw.q
deleted file mode 100644
index ff4c8b8..0000000
--- a/y2014/control_loops/claw/claw.q
+++ /dev/null
@@ -1,74 +0,0 @@
-package y2014.control_loops;
-
-import "aos/controls/control_loops.q";
-import "frc971/control_loops/control_loops.q";
-
-struct HalfClawPosition {
-  // The current position of this half of the claw.
-  double position;
-
-  // The hall effect sensor at the front limit.
-  .frc971.HallEffectStruct front;
-  // The hall effect sensor in the middle to use for real calibration.
-  .frc971.HallEffectStruct calibration;
-  // The hall effect at the back limit.
-  .frc971.HallEffectStruct back;
-};
-
-// All angles here are 0 vertical, positive "up" (aka backwards).
-// Published on ".y2014.control_loops.claw_queue"
-queue_group ClawQueue {
-  implements aos.control_loops.ControlLoop;
-
-  message Goal {
-    // The angle of the bottom claw.
-    double bottom_angle;
-    // How much higher the top claw is.
-    double separation_angle;
-    // top claw intake roller
-    double intake;
-    // bottom claw tusk centering
-    double centering;
-  };
-
-  message Position {
-    // All the top claw information.
-    HalfClawPosition top;
-    // All the bottom claw information.
-    HalfClawPosition bottom;
-  };
-
-  message Output {
-    double intake_voltage;
-    double top_claw_voltage;
-    double bottom_claw_voltage;
-    double tusk_voltage;
-  };
-
-  message Status {
-    // True if zeroed enough for the current period (autonomous or teleop).
-    bool zeroed;
-    // True if zeroed as much as we will force during autonomous.
-    bool zeroed_for_auto;
-    // True if zeroed and within tolerance for separation and bottom angle.
-    bool done;
-    // True if zeroed and within tolerance for separation and bottom angle.
-    // seperation allowance much wider as a ball may be included
-    bool done_with_ball;
-    // Dump the values of the state matrix.
-    double bottom;
-    double bottom_velocity;
-    double separation;
-    double separation_velocity;
-  };
-
-  queue Goal goal;
-  queue Position position;
-  queue Output output;
-  queue Status status;
-};
-
-struct ClawPositionToLog {
-	double top;
-	double bottom;
-};
diff --git a/y2014/control_loops/claw/claw_goal.fbs b/y2014/control_loops/claw/claw_goal.fbs
new file mode 100644
index 0000000..eb5860c
--- /dev/null
+++ b/y2014/control_loops/claw/claw_goal.fbs
@@ -0,0 +1,15 @@
+namespace y2014.control_loops.claw;
+
+// All angles here are 0 vertical, positive "up" (aka backwards).
+table Goal {
+  // The angle of the bottom claw.
+  bottom_angle:double;
+  // How much higher the top claw is.
+  separation_angle:double;
+  // top claw intake roller
+  intake:double;
+  // bottom claw tusk centering
+  centering:double;
+}
+
+root_type Goal;
diff --git a/y2014/control_loops/claw/claw_lib_test.cc b/y2014/control_loops/claw/claw_lib_test.cc
index 41dbfca..55e186e 100644
--- a/y2014/control_loops/claw/claw_lib_test.cc
+++ b/y2014/control_loops/claw/claw_lib_test.cc
@@ -8,16 +8,18 @@
 #include "gtest/gtest.h"
 #include "y2014/constants.h"
 #include "y2014/control_loops/claw/claw.h"
-#include "y2014/control_loops/claw/claw.q.h"
+#include "y2014/control_loops/claw/claw_goal_generated.h"
 #include "y2014/control_loops/claw/claw_motor_plant.h"
+#include "y2014/control_loops/claw/claw_output_generated.h"
+#include "y2014/control_loops/claw/claw_position_generated.h"
+#include "y2014/control_loops/claw/claw_status_generated.h"
 
 namespace y2014 {
 namespace control_loops {
+namespace claw {
 namespace testing {
 
-using ::y2014::control_loops::claw::MakeClawPlant;
-using ::frc971::HallEffectStruct;
-using ::y2014::control_loops::HalfClawPosition;
+using ::frc971::HallEffectStructT;
 using ::aos::monotonic_clock;
 namespace chrono = ::std::chrono;
 
@@ -38,10 +40,8 @@
                       double initial_top_position,
                       double initial_bottom_position)
       : event_loop_(event_loop),
-        claw_position_sender_(event_loop_->MakeSender<ClawQueue::Position>(
-            ".y2014.control_loops.claw_queue.position")),
-        claw_output_fetcher_(event_loop_->MakeFetcher<ClawQueue::Output>(
-            ".y2014.control_loops.claw_queue.output")),
+        claw_position_sender_(event_loop_->MakeSender<Position>("/claw")),
+        claw_output_fetcher_(event_loop_->MakeFetcher<Output>("/claw")),
         claw_plant_(new StateFeedbackPlant<4, 2, 2>(MakeClawPlant())) {
     Reinitialize(initial_top_position, initial_bottom_position);
 
@@ -69,7 +69,9 @@
 
     ReinitializePartial(TOP_CLAW, initial_top_position);
     ReinitializePartial(BOTTOM_CLAW, initial_bottom_position);
-    last_position_.Zero();
+
+    last_position_.top.reset();
+    last_position_.bottom.reset();
     SetPhysicalSensors(&last_position_);
   }
 
@@ -99,44 +101,58 @@
 
   void SetHallEffect(double pos,
                      const constants::Values::Claws::AnglePair &pair,
-                     HallEffectStruct *hall_effect) {
+                     HallEffectStructT *hall_effect) {
     hall_effect->current = CheckRange(pos, pair);
   }
 
   void SetClawHallEffects(double pos,
                           const constants::Values::Claws::Claw &claw,
-                          HalfClawPosition *half_claw) {
-    SetHallEffect(pos, claw.front, &half_claw->front);
-    SetHallEffect(pos, claw.calibration, &half_claw->calibration);
-    SetHallEffect(pos, claw.back, &half_claw->back);
+                          HalfClawPositionT *half_claw) {
+    if (!half_claw->front) {
+      half_claw->front.reset(new HallEffectStructT());
+    }
+    if (!half_claw->calibration) {
+      half_claw->calibration.reset(new HallEffectStructT());
+    }
+    if (!half_claw->back) {
+      half_claw->back.reset(new HallEffectStructT());
+    }
+    SetHallEffect(pos, claw.front, half_claw->front.get());
+    SetHallEffect(pos, claw.calibration, half_claw->calibration.get());
+    SetHallEffect(pos, claw.back, half_claw->back.get());
   }
 
   // Sets the values of the physical sensors that can be directly observed
   // (encoder, hall effect).
-  void SetPhysicalSensors(
-      ::y2014::control_loops::ClawQueue::Position *position) {
-    position->top.position = GetPosition(TOP_CLAW);
-    position->bottom.position = GetPosition(BOTTOM_CLAW);
+  void SetPhysicalSensors(PositionT *position) {
+    if (!position->top) {
+      position->top.reset(new HalfClawPositionT());
+    }
+    if (!position->bottom) {
+      position->bottom.reset(new HalfClawPositionT());
+    }
+
+    position->top->position = GetPosition(TOP_CLAW);
+    position->bottom->position = GetPosition(BOTTOM_CLAW);
 
     double pos[2] = {GetAbsolutePosition(TOP_CLAW),
                      GetAbsolutePosition(BOTTOM_CLAW)};
     AOS_LOG(DEBUG, "Physical claws are at {top: %f, bottom: %f}\n",
             pos[TOP_CLAW], pos[BOTTOM_CLAW]);
 
-    const constants::Values& values = constants::GetValues();
+    const constants::Values &values = constants::GetValues();
 
     // Signal that each hall effect sensor has been triggered if it is within
     // the correct range.
-    SetClawHallEffects(pos[TOP_CLAW], values.claw.upper_claw, &position->top);
+    SetClawHallEffects(pos[TOP_CLAW], values.claw.upper_claw,
+                       position->top.get());
     SetClawHallEffects(pos[BOTTOM_CLAW], values.claw.lower_claw,
-                       &position->bottom);
+                       position->bottom.get());
   }
 
-  void UpdateHallEffect(double angle,
-                        double last_angle,
-                        double initial_position,
-                        HallEffectStruct *position,
-                        const HallEffectStruct &last_position,
+  void UpdateHallEffect(double angle, double last_angle,
+                        double initial_position, HallEffectStructT *position,
+                        const HallEffectStructT &last_position,
                         const constants::Values::Claws::AnglePair &pair,
                         const char *claw_name, const char *hall_effect_name) {
     if (position->current && !last_position.current) {
@@ -167,49 +183,64 @@
     }
   }
 
-  void UpdateClawHallEffects(
-      HalfClawPosition *position,
-      const HalfClawPosition &last_position,
-      const constants::Values::Claws::Claw &claw, double initial_position,
-      const char *claw_name) {
-    UpdateHallEffect(position->position + initial_position,
+  void UpdateClawHallEffects(HalfClawPositionT *half_claw,
+                             const HalfClawPositionT &last_position,
+                             const constants::Values::Claws::Claw &claw,
+                             double initial_position, const char *claw_name) {
+    if (!half_claw->front) {
+      half_claw->front.reset(new HallEffectStructT());
+    }
+    if (!half_claw->calibration) {
+      half_claw->calibration.reset(new HallEffectStructT());
+    }
+    if (!half_claw->back) {
+      half_claw->back.reset(new HallEffectStructT());
+    }
+    UpdateHallEffect(half_claw->position + initial_position,
                      last_position.position + initial_position,
-                     initial_position, &position->front, last_position.front,
-                     claw.front, claw_name, "front");
-    UpdateHallEffect(position->position + initial_position,
+                     initial_position, half_claw->front.get(),
+                     *last_position.front.get(), claw.front, claw_name, "front");
+    UpdateHallEffect(half_claw->position + initial_position,
                      last_position.position + initial_position,
-                     initial_position, &position->calibration,
-                     last_position.calibration, claw.calibration, claw_name,
-                     "calibration");
-    UpdateHallEffect(position->position + initial_position,
+                     initial_position, half_claw->calibration.get(),
+                     *last_position.calibration.get(), claw.calibration,
+                     claw_name, "calibration");
+    UpdateHallEffect(half_claw->position + initial_position,
                      last_position.position + initial_position,
-                     initial_position, &position->back, last_position.back,
-                     claw.back, claw_name, "back");
+                     initial_position, half_claw->back.get(),
+                     *last_position.back.get(), claw.back, claw_name, "back");
   }
 
   // Sends out the position queue messages.
   void SendPositionMessage() {
-    ::aos::Sender<::y2014::control_loops::ClawQueue::Position>::Message
-        position = claw_position_sender_.MakeMessage();
+    ::aos::Sender<Position>::Builder builder =
+        claw_position_sender_.MakeBuilder();
 
     // Initialize all the counters to their previous values.
-    *position = last_position_;
 
-    SetPhysicalSensors(position.get());
+    PositionT position;
 
-    const constants::Values& values = constants::GetValues();
+    flatbuffers::FlatBufferBuilder fbb;
+    flatbuffers::Offset<Position> position_offset =
+        Position::Pack(fbb, &last_position_);
+    fbb.Finish(position_offset);
 
-    UpdateClawHallEffects(&position->top, last_position_.top,
+    flatbuffers::GetRoot<Position>(fbb.GetBufferPointer())->UnPackTo(&position);
+    SetPhysicalSensors(&position);
+
+    const constants::Values &values = constants::GetValues();
+
+    UpdateClawHallEffects(position.top.get(), *last_position_.top.get(),
                           values.claw.upper_claw, initial_position_[TOP_CLAW],
                           "Top");
-    UpdateClawHallEffects(&position->bottom, last_position_.bottom,
+    UpdateClawHallEffects(position.bottom.get(), *last_position_.bottom.get(),
                           values.claw.lower_claw,
                           initial_position_[BOTTOM_CLAW], "Bottom");
 
     // Only set calibration if it changed last cycle.  Calibration starts out
     // with a value of 0.
-    last_position_ = *position;
-    position.Send();
+    builder.Send(Position::Pack(*builder.fbb(), &position));
+    last_position_ = std::move(position);
   }
 
   // Simulates the claw moving for one timestep.
@@ -218,8 +249,8 @@
     EXPECT_TRUE(claw_output_fetcher_.Fetch());
 
     Eigen::Matrix<double, 2, 1> U;
-    U << claw_output_fetcher_->bottom_claw_voltage,
-        claw_output_fetcher_->top_claw_voltage;
+    U << claw_output_fetcher_->bottom_claw_voltage(),
+        claw_output_fetcher_->top_claw_voltage();
     claw_plant_->Update(U);
 
     // Check that the claw is within the limits.
@@ -237,8 +268,8 @@
 
  private:
   ::aos::EventLoop *event_loop_;
-  ::aos::Sender<ClawQueue::Position> claw_position_sender_;
-  ::aos::Fetcher<ClawQueue::Output> claw_output_fetcher_;
+  ::aos::Sender<Position> claw_position_sender_;
+  ::aos::Fetcher<Output> claw_output_fetcher_;
 
   // The whole claw.
   ::std::unique_ptr<StateFeedbackPlant<4, 2, 2>> claw_plant_;
@@ -252,18 +283,18 @@
 
   double initial_position_[CLAW_COUNT];
 
-  ::y2014::control_loops::ClawQueue::Position last_position_;
+  PositionT last_position_;
 };
 
 class ClawTest : public ::aos::testing::ControlLoopTest {
  protected:
   ClawTest()
-      : ::aos::testing::ControlLoopTest(chrono::microseconds(5000)),
+      : ::aos::testing::ControlLoopTest(
+            aos::configuration::ReadConfig("y2014/config.json"),
+            chrono::microseconds(5000)),
         test_event_loop_(MakeEventLoop()),
-        claw_goal_sender_(test_event_loop_->MakeSender<ClawQueue::Goal>(
-            ".y2014.control_loops.claw_queue.goal")),
-        claw_goal_fetcher_(test_event_loop_->MakeFetcher<ClawQueue::Goal>(
-            ".y2014.control_loops.claw_queue.goal")),
+        claw_goal_sender_(test_event_loop_->MakeSender<Goal>("/claw")),
+        claw_goal_fetcher_(test_event_loop_->MakeFetcher<Goal>("/claw")),
         claw_event_loop_(MakeEventLoop()),
         claw_motor_(claw_event_loop_.get()),
         claw_plant_event_loop_(MakeEventLoop()),
@@ -275,14 +306,14 @@
     double bottom = claw_motor_plant_.GetAbsolutePosition(BOTTOM_CLAW);
     double separation =
         claw_motor_plant_.GetAbsolutePosition(TOP_CLAW) - bottom;
-    EXPECT_NEAR(claw_goal_fetcher_->bottom_angle, bottom, 1e-4);
-    EXPECT_NEAR(claw_goal_fetcher_->separation_angle, separation, 1e-4);
+    EXPECT_NEAR(claw_goal_fetcher_->bottom_angle(), bottom, 1e-4);
+    EXPECT_NEAR(claw_goal_fetcher_->separation_angle(), separation, 1e-4);
     EXPECT_LE(min_separation_, separation);
   }
 
   ::std::unique_ptr<::aos::EventLoop> test_event_loop_;
-  ::aos::Sender<ClawQueue::Goal> claw_goal_sender_;
-  ::aos::Fetcher<ClawQueue::Goal> claw_goal_fetcher_;
+  ::aos::Sender<Goal> claw_goal_sender_;
+  ::aos::Fetcher<Goal> claw_goal_fetcher_;
 
   // Create a loop and simulation plant.
   ::std::unique_ptr<::aos::EventLoop> claw_event_loop_;
@@ -294,15 +325,15 @@
   // Minimum amount of acceptable separation between the top and bottom of the
   // claw.
   double min_separation_;
-
 };
 
 TEST_F(ClawTest, HandlesNAN) {
   {
-    auto message = claw_goal_sender_.MakeMessage();
-    message->bottom_angle = ::std::nan("");
-    message->separation_angle = ::std::nan("");
-    EXPECT_TRUE(message.Send());
+    auto builder = claw_goal_sender_.MakeBuilder();
+    Goal::Builder goal_builder = builder.MakeBuilder<Goal>();
+    goal_builder.add_bottom_angle(::std::nan(""));
+    goal_builder.add_separation_angle(::std::nan(""));
+    EXPECT_TRUE(builder.Send(goal_builder.Finish()));
   }
 
   SetEnabled(true);
@@ -312,10 +343,11 @@
 // Tests that the wrist zeros correctly and goes to a position.
 TEST_F(ClawTest, ZerosCorrectly) {
   {
-    auto message = claw_goal_sender_.MakeMessage();
-    message->bottom_angle = 0.1;
-    message->separation_angle = 0.2;
-    EXPECT_TRUE(message.Send());
+    auto builder = claw_goal_sender_.MakeBuilder();
+    Goal::Builder goal_builder = builder.MakeBuilder<Goal>();
+    goal_builder.add_bottom_angle(0.1);
+    goal_builder.add_separation_angle(0.2);
+    EXPECT_TRUE(builder.Send(goal_builder.Finish()));
   }
 
   SetEnabled(true);
@@ -409,10 +441,11 @@
   claw_motor_plant_.Reinitialize(GetParam().first, GetParam().second);
 
   {
-    auto message = claw_goal_sender_.MakeMessage();
-    message->bottom_angle = 0.1;
-    message->separation_angle = 0.2;
-    EXPECT_TRUE(message.Send());
+    auto builder = claw_goal_sender_.MakeBuilder();
+    Goal::Builder goal_builder = builder.MakeBuilder<Goal>();
+    goal_builder.add_bottom_angle(0.1);
+    goal_builder.add_separation_angle(0.2);
+    EXPECT_TRUE(builder.Send(goal_builder.Finish()));
   }
 
   SetEnabled(true);
@@ -586,10 +619,11 @@
 // zeroing position is saturating the goal.
 TEST_F(WindupClawTest, NoWindupPositive) {
   {
-    auto message = claw_goal_sender_.MakeMessage();
-    message->bottom_angle = 0.1;
-    message->separation_angle = 0.2;
-    EXPECT_TRUE(message.Send());
+    auto builder = claw_goal_sender_.MakeBuilder();
+    Goal::Builder goal_builder = builder.MakeBuilder<Goal>();
+    goal_builder.add_bottom_angle(0.1);
+    goal_builder.add_separation_angle(0.2);
+    EXPECT_TRUE(builder.Send(goal_builder.Finish()));
   }
 
   TestWindup(ClawMotor::UNKNOWN_LOCATION,
@@ -602,10 +636,11 @@
 // zeroing position is saturating the goal.
 TEST_F(WindupClawTest, NoWindupNegative) {
   {
-    auto message = claw_goal_sender_.MakeMessage();
-    message->bottom_angle = 0.1;
-    message->separation_angle = 0.2;
-    EXPECT_TRUE(message.Send());
+    auto builder = claw_goal_sender_.MakeBuilder();
+    Goal::Builder goal_builder = builder.MakeBuilder<Goal>();
+    goal_builder.add_bottom_angle(0.1);
+    goal_builder.add_separation_angle(0.2);
+    EXPECT_TRUE(builder.Send(goal_builder.Finish()));
   }
 
   TestWindup(ClawMotor::UNKNOWN_LOCATION,
@@ -618,10 +653,11 @@
 // zeroing position is saturating the goal.
 TEST_F(WindupClawTest, NoWindupNegativeFineTune) {
   {
-    auto message = claw_goal_sender_.MakeMessage();
-    message->bottom_angle = 0.1;
-    message->separation_angle = 0.2;
-    EXPECT_TRUE(message.Send());
+    auto builder = claw_goal_sender_.MakeBuilder();
+    Goal::Builder goal_builder = builder.MakeBuilder<Goal>();
+    goal_builder.add_bottom_angle(0.1);
+    goal_builder.add_separation_angle(0.2);
+    EXPECT_TRUE(builder.Send(goal_builder.Finish()));
   }
 
   TestWindup(ClawMotor::FINE_TUNE_BOTTOM,
@@ -631,5 +667,6 @@
 }
 
 }  // namespace testing
+}  // namespace claw
 }  // namespace control_loops
 }  // namespace y2014
diff --git a/y2014/control_loops/claw/claw_main.cc b/y2014/control_loops/claw/claw_main.cc
index 65627d5..f21c7c5 100644
--- a/y2014/control_loops/claw/claw_main.cc
+++ b/y2014/control_loops/claw/claw_main.cc
@@ -1,13 +1,16 @@
 #include "y2014/control_loops/claw/claw.h"
 
-#include "aos/events/shm-event-loop.h"
+#include "aos/events/shm_event_loop.h"
 #include "aos/init.h"
 
 int main() {
   ::aos::InitNRT(true);
 
-  ::aos::ShmEventLoop event_loop;
-  ::y2014::control_loops::ClawMotor claw(&event_loop);
+  aos::FlatbufferDetachedBuffer<aos::Configuration> config =
+      aos::configuration::ReadConfig("config.json");
+
+  ::aos::ShmEventLoop event_loop(&config.message());
+  ::y2014::control_loops::claw::ClawMotor claw(&event_loop);
 
   event_loop.Run();
 
diff --git a/y2014/control_loops/claw/claw_output.fbs b/y2014/control_loops/claw/claw_output.fbs
new file mode 100644
index 0000000..8cb42e0
--- /dev/null
+++ b/y2014/control_loops/claw/claw_output.fbs
@@ -0,0 +1,11 @@
+namespace y2014.control_loops.claw;
+
+// All angles here are 0 vertical, positive "up" (aka backwards).
+table Output {
+  intake_voltage:double;
+  top_claw_voltage:double;
+  bottom_claw_voltage:double;
+  tusk_voltage:double;
+}
+
+root_type Output;
diff --git a/y2014/control_loops/claw/claw_position.fbs b/y2014/control_loops/claw/claw_position.fbs
new file mode 100644
index 0000000..17d9f17
--- /dev/null
+++ b/y2014/control_loops/claw/claw_position.fbs
@@ -0,0 +1,25 @@
+include "frc971/control_loops/control_loops.fbs";
+
+namespace y2014.control_loops.claw;
+
+// All angles here are 0 vertical, positive "up" (aka backwards).
+table HalfClawPosition {
+  // The current position of this half of the claw.
+  position:double;
+
+  // The hall effect sensor at the front limit.
+  front:frc971.HallEffectStruct;
+  // The hall effect sensor in the middle to use for real calibration.
+  calibration:frc971.HallEffectStruct;
+  // The hall effect at the back limit.
+  back:frc971.HallEffectStruct;
+}
+
+table Position {
+  // All the top claw information.
+  top:HalfClawPosition;
+  // All the bottom claw information.
+  bottom:HalfClawPosition;
+}
+
+root_type Position;
diff --git a/y2014/control_loops/claw/claw_status.fbs b/y2014/control_loops/claw/claw_status.fbs
new file mode 100644
index 0000000..eda9279
--- /dev/null
+++ b/y2014/control_loops/claw/claw_status.fbs
@@ -0,0 +1,21 @@
+namespace y2014.control_loops.claw;
+
+// All angles here are 0 vertical, positive "up" (aka backwards).
+table Status {
+  // True if zeroed enough for the current period (autonomous or teleop).
+  zeroed:bool;
+  // True if zeroed as much as we will force during autonomous.
+  zeroed_for_auto:bool;
+  // True if zeroed and within tolerance for separation and bottom angle.
+  done:bool;
+  // True if zeroed and within tolerance for separation and bottom angle.
+  // seperation allowance much wider as a ball may be included
+  done_with_ball:bool;
+  // Dump the values of the state matrix.
+  bottom:double;
+  bottom_velocity:double;
+  separation:double;
+  separation_velocity:double;
+}
+
+root_type Status;