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/y2012/BUILD b/y2012/BUILD
index 401beac..ff6d3f2 100644
--- a/y2012/BUILD
+++ b/y2012/BUILD
@@ -12,9 +12,10 @@
         "//aos/logging",
         "//aos/time",
         "//aos/util:log_interval",
-        "//frc971/autonomous:auto_queue",
-        "//frc971/control_loops/drivetrain:drivetrain_queue",
-        "//y2012/control_loops/accessories:accessories_queue",
+        "//frc971/autonomous:auto_fbs",
+        "//frc971/control_loops:control_loops_fbs",
+        "//frc971/control_loops/drivetrain:drivetrain_goal_fbs",
+        "//y2012/control_loops/accessories:accessories_fbs",
     ],
 )
 
@@ -37,17 +38,18 @@
         "//aos:init",
         "//aos:make_unique",
         "//aos/controls:control_loop",
-        "//aos/events:shm-event-loop",
+        "//aos/controls:control_loop_fbs",
+        "//aos/events:shm_event_loop",
         "//aos/logging",
-        "//aos/logging:queue_logging",
-        "//aos/robot_state",
+        "//aos/robot_state:robot_state_fbs",
         "//aos/stl_mutex",
         "//aos/time",
         "//aos/util:log_interval",
         "//aos/util:phased_loop",
         "//aos/util:wrapping_counter",
-        "//frc971/control_loops:queues",
-        "//frc971/control_loops/drivetrain:drivetrain_queue",
+        "//frc971/control_loops:control_loops_fbs",
+        "//frc971/control_loops/drivetrain:drivetrain_output_fbs",
+        "//frc971/control_loops/drivetrain:drivetrain_position_fbs",
         "//frc971/wpilib:buffered_pcm",
         "//frc971/wpilib:dma",
         "//frc971/wpilib:dma_edge_counting",
@@ -55,13 +57,13 @@
         "//frc971/wpilib:encoder_and_potentiometer",
         "//frc971/wpilib:interrupt_edge_counting",
         "//frc971/wpilib:joystick_sender",
-        "//frc971/wpilib:logging_queue",
+        "//frc971/wpilib:logging_fbs",
         "//frc971/wpilib:loop_output_handler",
         "//frc971/wpilib:sensor_reader",
         "//frc971/wpilib:wpilib_interface",
         "//frc971/wpilib:wpilib_robot_base",
         "//third_party:wpilib",
-        "//y2012/control_loops/accessories:accessories_queue",
+        "//y2012/control_loops/accessories:accessories_fbs",
     ],
 )
 
diff --git a/y2012/control_loops/accessories/BUILD b/y2012/control_loops/accessories/BUILD
index 63f02dd..65a6d1d 100644
--- a/y2012/control_loops/accessories/BUILD
+++ b/y2012/control_loops/accessories/BUILD
@@ -1,25 +1,23 @@
-package(default_visibility = ['//visibility:public'])
+package(default_visibility = ["//visibility:public"])
 
-load('//aos/build:queues.bzl', 'queue_library')
+load("@com_github_google_flatbuffers//:build_defs.bzl", "flatbuffer_cc_library")
 
 cc_binary(
-  name = 'accessories',
-  srcs = [
-    'accessories.cc',
-  ],
-  deps = [
-    ':accessories_queue',
-    '//aos:init',
-    '//aos/controls:control_loop',
-  ],
+    name = "accessories",
+    srcs = [
+        "accessories.cc",
+    ],
+    deps = [
+        ":accessories_fbs",
+        "//aos:init",
+        "//aos/controls:control_loop",
+        "//aos/controls:control_loop_fbs",
+    ],
 )
 
-queue_library(
-  name = 'accessories_queue',
-  srcs = [
-    'accessories.q',
-  ],
-  deps = [
-    '//aos/controls:control_loop_queues',
-  ],
+flatbuffer_cc_library(
+    name = "accessories_fbs",
+    srcs = [
+        "accessories.fbs",
+    ],
 )
diff --git a/y2012/control_loops/accessories/accessories.cc b/y2012/control_loops/accessories/accessories.cc
index 9d96840..726aede 100644
--- a/y2012/control_loops/accessories/accessories.cc
+++ b/y2012/control_loops/accessories/accessories.cc
@@ -1,28 +1,43 @@
-#include "y2012/control_loops/accessories/accessories.q.h"
+#include "y2012/control_loops/accessories/accessories_generated.h"
 
+#include "aos/events/shm_event_loop.h"
 #include "aos/init.h"
 #include "aos/controls/control_loop.h"
+#include "aos/controls/control_loops_generated.h"
 
 namespace y2012 {
 namespace control_loops {
 namespace accessories {
 
 class AccessoriesLoop : public ::aos::controls::ControlLoop<
-                            ::y2012::control_loops::AccessoriesQueue> {
+                            Message, ::aos::control_loops::Position,
+                            ::aos::control_loops::Status, Message> {
  public:
   explicit AccessoriesLoop(
       ::aos::EventLoop *event_loop,
       const ::std::string &name = ".y2012.control_loops.accessories_queue")
-      : ::aos::controls::ControlLoop<::y2012::control_loops::AccessoriesQueue>(
+      : ::aos::controls::ControlLoop<Message, ::aos::control_loops::Position,
+                                     ::aos::control_loops::Status, Message>(
             event_loop, name) {}
 
   void RunIteration(
-      const ::y2012::control_loops::AccessoriesQueue::Message *goal,
+      const Message *goal,
       const ::aos::control_loops::Position * /*position*/,
-      ::y2012::control_loops::AccessoriesQueue::Message *output,
-      ::aos::control_loops::Status * /*status*/) override {
+      ::aos::Sender<Message>::Builder *output,
+      ::aos::Sender<::aos::control_loops::Status>::Builder * /*status*/) override {
     if (output) {
-      *output = *goal;
+      //*output = *goal;
+      Message::Builder output_builder = output->MakeBuilder<Message>();
+      flatbuffers::Offset<flatbuffers::Vector<uint8_t>> solenoid_offset =
+          output->fbb()->template CreateVector<uint8_t>(
+              goal->solenoids()->data(), 3);
+      output_builder.add_solenoids(solenoid_offset);
+      flatbuffers::Offset<flatbuffers::Vector<double>> stick_offset =
+          output->fbb()->template CreateVector<double>(
+              goal->sticks()->data(), 2);
+      output_builder.add_sticks(stick_offset);
+
+      output_builder.Finish();
     }
   }
 };
@@ -34,7 +49,10 @@
 int main() {
   ::aos::InitNRT(true);
 
-  ::aos::ShmEventLoop event_loop;
+  aos::FlatbufferDetachedBuffer<aos::Configuration> config =
+      aos::configuration::ReadConfig("config.json");
+
+  ::aos::ShmEventLoop event_loop(&config.message());
   ::y2012::control_loops::accessories::AccessoriesLoop accessories(&event_loop);
 
   event_loop.Run();
diff --git a/y2012/control_loops/accessories/accessories.fbs b/y2012/control_loops/accessories/accessories.fbs
new file mode 100644
index 0000000..1174b55
--- /dev/null
+++ b/y2012/control_loops/accessories/accessories.fbs
@@ -0,0 +1,8 @@
+namespace y2012.control_loops.accessories;
+
+table Message {
+  solenoids:[bool]; // Exactly 3 values
+  sticks:[double]; // Exactly 2 values
+}
+
+root_type Message;
diff --git a/y2012/control_loops/accessories/accessories.q b/y2012/control_loops/accessories/accessories.q
deleted file mode 100644
index 6427d49..0000000
--- a/y2012/control_loops/accessories/accessories.q
+++ /dev/null
@@ -1,17 +0,0 @@
-package y2012.control_loops;
-
-import "aos/controls/control_loops.q";
-
-// Published on ".y2012.control_loops.accessories_queue"
-queue_group AccessoriesQueue {
-  implements aos.control_loops.ControlLoop;
-  message Message {
-    bool[3] solenoids;
-    double[2] sticks;
-  };
-
-  queue Message goal;
-  queue .aos.control_loops.Position position;
-  queue Message output;
-  queue .aos.control_loops.Status status;
-};
diff --git a/y2012/control_loops/drivetrain/BUILD b/y2012/control_loops/drivetrain/BUILD
index 3be1e9a..35d596a 100644
--- a/y2012/control_loops/drivetrain/BUILD
+++ b/y2012/control_loops/drivetrain/BUILD
@@ -1,7 +1,5 @@
 package(default_visibility = ["//visibility:public"])
 
-load("//aos/build:queues.bzl", "queue_library")
-
 genrule(
     name = "genrule_drivetrain",
     outs = [
@@ -78,7 +76,7 @@
     deps = [
         ":drivetrain_base",
         "//aos:init",
-        "//aos/events:shm-event-loop",
+        "//aos/events:shm_event_loop",
         "//frc971/control_loops/drivetrain:drivetrain_lib",
     ],
 )
diff --git a/y2012/control_loops/drivetrain/drivetrain_main.cc b/y2012/control_loops/drivetrain/drivetrain_main.cc
index 75153cd..735f13f 100644
--- a/y2012/control_loops/drivetrain/drivetrain_main.cc
+++ b/y2012/control_loops/drivetrain/drivetrain_main.cc
@@ -1,6 +1,6 @@
 #include "aos/init.h"
 
-#include "aos/events/shm-event-loop.h"
+#include "aos/events/shm_event_loop.h"
 #include "frc971/control_loops/drivetrain/drivetrain.h"
 #include "y2012/control_loops/drivetrain/drivetrain_base.h"
 
@@ -9,7 +9,10 @@
 int main() {
   ::aos::InitNRT(true);
 
-  ::aos::ShmEventLoop event_loop;
+  aos::FlatbufferDetachedBuffer<aos::Configuration> config =
+      aos::configuration::ReadConfig("config.json");
+
+  ::aos::ShmEventLoop event_loop(&config.message());
   ::frc971::control_loops::drivetrain::DeadReckonEkf localizer(
       &event_loop, ::y2012::control_loops::drivetrain::GetDrivetrainConfig());
   DrivetrainLoop drivetrain(
diff --git a/y2012/joystick_reader.cc b/y2012/joystick_reader.cc
index 460d850..48e6eb5 100644
--- a/y2012/joystick_reader.cc
+++ b/y2012/joystick_reader.cc
@@ -4,15 +4,15 @@
 #include <math.h>
 
 #include "aos/actions/actions.h"
-#include "aos/events/shm-event-loop.h"
+#include "aos/events/shm_event_loop.h"
 #include "aos/init.h"
 #include "aos/input/driver_station_data.h"
 #include "aos/input/joystick_input.h"
 #include "aos/logging/logging.h"
 #include "aos/time/time.h"
 
-#include "frc971/control_loops/drivetrain/drivetrain.q.h"
-#include "y2012/control_loops/accessories/accessories.q.h"
+#include "frc971/control_loops/drivetrain/drivetrain_goal_generated.h"
+#include "y2012/control_loops/accessories/accessories_generated.h"
 
 using ::aos::input::driver_station::ButtonLocation;
 using ::aos::input::driver_station::JoystickAxis;
@@ -81,13 +81,12 @@
   Reader(::aos::EventLoop *event_loop)
       : ::aos::input::JoystickInput(event_loop),
         drivetrain_goal_sender_(
-            event_loop
-                ->MakeSender<::frc971::control_loops::DrivetrainQueue::Goal>(
-                    ".frc971.control_loops.drivetrain_queue.goal")),
+            event_loop->MakeSender<::frc971::control_loops::drivetrain::Goal>(
+                "/drivetrain")),
         accessories_goal_sender_(
             event_loop
-                ->MakeSender<::y2012::control_loops::AccessoriesQueue::Message>(
-                    ".y2012.control_loops.accessories_queue.goal")),
+                ->MakeSender<::y2012::control_loops::accessories::Message>(
+                    "/accessories")),
         is_high_gear_(false) {}
 
   void RunIteration(const ::aos::input::driver_station::Data &data) override {
@@ -106,33 +105,43 @@
     if (data.PosEdge(kShiftHigh)) {
       is_high_gear_ = true;
     }
-    auto drivetrain_message = drivetrain_goal_sender_.MakeMessage();
-    drivetrain_message->wheel = wheel;
-    drivetrain_message->throttle = throttle;
-    drivetrain_message->highgear = is_high_gear_;
-    drivetrain_message->quickturn = data.IsPressed(kQuickTurn);
+    auto builder = drivetrain_goal_sender_.MakeBuilder();
+    frc971::control_loops::drivetrain::Goal::Builder goal_builder =
+        builder.MakeBuilder<frc971::control_loops::drivetrain::Goal>();
+    goal_builder.add_wheel(wheel);
+    goal_builder.add_throttle(throttle);
+    goal_builder.add_highgear(is_high_gear_);
+    goal_builder.add_quickturn(data.IsPressed(kQuickTurn));
 
-    if (!drivetrain_message.Send()) {
+    if (!builder.Send(goal_builder.Finish())) {
       AOS_LOG(WARNING, "sending stick values failed\n");
     }
   }
 
   void HandleTeleop(const ::aos::input::driver_station::Data &data) {
-    auto accessories_message = accessories_goal_sender_.MakeMessage();
-    accessories_message->solenoids[0] = data.IsPressed(kLongShot);
-    accessories_message->solenoids[1] = data.IsPressed(kCloseShot);
-    accessories_message->solenoids[2] = data.IsPressed(kFenderShot);
-    accessories_message->sticks[0] = data.GetAxis(kAdjustClawGoal);
-    accessories_message->sticks[1] = data.GetAxis(kAdjustClawSeparation);
-    if (!accessories_message.Send()) {
+    auto builder = accessories_goal_sender_.MakeBuilder();
+    flatbuffers::Offset<flatbuffers::Vector<uint8_t>> solenoids_offset =
+        builder.fbb()->CreateVector<uint8_t>({data.IsPressed(kLongShot),
+                                     data.IsPressed(kCloseShot),
+                                     data.IsPressed(kFenderShot)});
+
+    flatbuffers::Offset<flatbuffers::Vector<double>> sticks_offset =
+        builder.fbb()->CreateVector<double>({data.GetAxis(kAdjustClawGoal),
+                                     data.GetAxis(kAdjustClawSeparation)});
+
+    y2012::control_loops::accessories::Message::Builder message_builder =
+        builder.MakeBuilder<y2012::control_loops::accessories::Message>();
+    message_builder.add_solenoids(solenoids_offset);
+    message_builder.add_sticks(sticks_offset);
+    if (!builder.Send(message_builder.Finish())) {
       AOS_LOG(WARNING, "sending accessories goal failed\n");
     }
   }
 
  private:
-  ::aos::Sender<::frc971::control_loops::DrivetrainQueue::Goal>
+  ::aos::Sender<::frc971::control_loops::drivetrain::Goal>
       drivetrain_goal_sender_;
-  ::aos::Sender<::y2012::control_loops::AccessoriesQueue::Message>
+  ::aos::Sender<::y2012::control_loops::accessories::Message>
       accessories_goal_sender_;
 
   bool is_high_gear_;
@@ -145,7 +154,10 @@
 int main() {
   ::aos::InitNRT(true);
 
-  ::aos::ShmEventLoop event_loop;
+  aos::FlatbufferDetachedBuffer<aos::Configuration> config =
+      aos::configuration::ReadConfig("config.json");
+
+  ::aos::ShmEventLoop event_loop(&config.message());
   ::y2012::input::joysticks::Reader reader(&event_loop);
 
   event_loop.Run();
diff --git a/y2012/wpilib_interface.cc b/y2012/wpilib_interface.cc
index a85f096..b28c34c 100644
--- a/y2012/wpilib_interface.cc
+++ b/y2012/wpilib_interface.cc
@@ -19,18 +19,19 @@
 #include "frc971/wpilib/wpilib_robot_base.h"
 #undef ERROR
 
-#include "aos/events/shm-event-loop.h"
+#include "aos/controls/control_loops_generated.h"
+#include "aos/events/shm_event_loop.h"
 #include "aos/init.h"
 #include "aos/logging/logging.h"
-#include "aos/logging/queue_logging.h"
 #include "aos/make_unique.h"
-#include "aos/robot_state/robot_state.q.h"
+#include "aos/robot_state/robot_state_generated.h"
 #include "aos/stl_mutex/stl_mutex.h"
 #include "aos/time/time.h"
 #include "aos/util/log_interval.h"
 #include "aos/util/phased_loop.h"
 #include "aos/util/wrapping_counter.h"
-#include "frc971/control_loops/drivetrain/drivetrain.q.h"
+#include "frc971/control_loops/drivetrain/drivetrain_output_generated.h"
+#include "frc971/control_loops/drivetrain/drivetrain_position_generated.h"
 #include "frc971/wpilib/buffered_pcm.h"
 #include "frc971/wpilib/buffered_solenoid.h"
 #include "frc971/wpilib/dma.h"
@@ -39,16 +40,12 @@
 #include "frc971/wpilib/encoder_and_potentiometer.h"
 #include "frc971/wpilib/interrupt_edge_counting.h"
 #include "frc971/wpilib/joystick_sender.h"
-#include "frc971/wpilib/logging.q.h"
+#include "frc971/wpilib/logging_generated.h"
 #include "frc971/wpilib/loop_output_handler.h"
 #include "frc971/wpilib/sensor_reader.h"
-#include "y2012/control_loops/accessories/accessories.q.h"
+#include "y2012/control_loops/accessories/accessories_generated.h"
 
-#ifndef M_PI
-#define M_PI 3.14159265358979323846
-#endif
-
-using ::y2012::control_loops::AccessoriesQueue;
+namespace accessories = ::y2012::control_loops::accessories;
 using namespace frc;
 using aos::make_unique;
 
@@ -74,33 +71,40 @@
       : ::frc971::wpilib::SensorReader(event_loop),
         accessories_position_sender_(
             event_loop->MakeSender<::aos::control_loops::Position>(
-                ".y2012.control_loops.accessories_queue.position")),
+                "/accessories")),
         drivetrain_position_sender_(
-            event_loop->MakeSender<
-                ::frc971::control_loops::DrivetrainQueue::Position>(
-                ".frc971.control_loops.drivetrain_queue.position")) {}
+            event_loop
+                ->MakeSender<::frc971::control_loops::drivetrain::Position>(
+                    "/drivetrain")) {}
 
   void RunIteration() {
     {
-      auto drivetrain_message = drivetrain_position_sender_.MakeMessage();
-      drivetrain_message->right_encoder =
-          drivetrain_translate(drivetrain_right_encoder_->GetRaw());
-      drivetrain_message->left_encoder =
-          -drivetrain_translate(drivetrain_left_encoder_->GetRaw());
-      drivetrain_message->left_speed =
-          drivetrain_velocity_translate(drivetrain_left_encoder_->GetPeriod());
-      drivetrain_message->right_speed =
-          drivetrain_velocity_translate(drivetrain_right_encoder_->GetPeriod());
+      auto builder = drivetrain_position_sender_.MakeBuilder();
 
-      drivetrain_message.Send();
+      frc971::control_loops::drivetrain::Position::Builder position_builder =
+          builder.MakeBuilder<frc971::control_loops::drivetrain::Position>();
+      position_builder.add_right_encoder(
+          drivetrain_translate(drivetrain_right_encoder_->GetRaw()));
+      position_builder.add_left_encoder(
+          -drivetrain_translate(drivetrain_left_encoder_->GetRaw()));
+      position_builder.add_left_speed(
+          drivetrain_velocity_translate(drivetrain_left_encoder_->GetPeriod()));
+      position_builder.add_right_speed(drivetrain_velocity_translate(
+          drivetrain_right_encoder_->GetPeriod()));
+
+      builder.Send(position_builder.Finish());
     }
 
-    accessories_position_sender_.MakeMessage().Send();
+    {
+      auto builder = accessories_position_sender_.MakeBuilder();
+      builder.Send(
+          builder.MakeBuilder<::aos::control_loops::Position>().Finish());
+    }
   }
 
  private:
   ::aos::Sender<::aos::control_loops::Position> accessories_position_sender_;
-  ::aos::Sender<::frc971::control_loops::DrivetrainQueue::Position>
+  ::aos::Sender<::frc971::control_loops::drivetrain::Position>
       drivetrain_position_sender_;
 };
 
@@ -112,11 +116,14 @@
         pcm_(pcm),
         drivetrain_fetcher_(
             event_loop_
-                ->MakeFetcher<::frc971::control_loops::DrivetrainQueue::Output>(
-                    ".y2012.control_loops.drivetrain_queue.output")),
-        accessories_fetcher_(event_loop_->MakeFetcher<
-                             ::y2012::control_loops::AccessoriesQueue::Message>(
-            ".y2012.control_loops.accessories_queue.output")) {
+                ->MakeFetcher<::frc971::control_loops::drivetrain::Output>(
+                    "/drivetrain")),
+        accessories_fetcher_(
+            event_loop_
+                ->MakeFetcher<::y2012::control_loops::accessories::Message>(
+                    "/accessories")),
+        pneumatics_to_log_sender_(
+            event_loop->MakeSender<::frc971::wpilib::PneumaticsToLog>("/aos")) {
     event_loop_->set_name("Solenoids");
     event_loop_->SetRuntimeRealtimePriority(27);
 
@@ -155,29 +162,30 @@
     {
       accessories_fetcher_.Fetch();
       if (accessories_fetcher_.get()) {
-        AOS_LOG_STRUCT(DEBUG, "solenoids", *accessories_fetcher_);
-        s1_->Set(accessories_fetcher_->solenoids[0]);
-        s2_->Set(accessories_fetcher_->solenoids[1]);
-        s3_->Set(accessories_fetcher_->solenoids[2]);
+        s1_->Set(accessories_fetcher_->solenoids()->Get(0));
+        s2_->Set(accessories_fetcher_->solenoids()->Get(1));
+        s3_->Set(accessories_fetcher_->solenoids()->Get(2));
       }
     }
 
     {
       drivetrain_fetcher_.Fetch();
       if (drivetrain_fetcher_.get()) {
-        AOS_LOG_STRUCT(DEBUG, "solenoids", *drivetrain_fetcher_);
-        const bool high =
-            drivetrain_fetcher_->left_high || drivetrain_fetcher_->right_high;
+        const bool high = drivetrain_fetcher_->left_high() ||
+                          drivetrain_fetcher_->right_high();
         drivetrain_high_->Set(high);
         drivetrain_low_->Set(!high);
       }
     }
 
     {
-      ::frc971::wpilib::PneumaticsToLog to_log;
+      auto builder = pneumatics_to_log_sender_.MakeBuilder();
+
+      ::frc971::wpilib::PneumaticsToLog::Builder to_log_builder =
+          builder.MakeBuilder<frc971::wpilib::PneumaticsToLog>();
       pcm_->Flush();
-      to_log.read_solenoids = pcm_->GetAll();
-      AOS_LOG_STRUCT(DEBUG, "pneumatics info", to_log);
+      to_log_builder.add_read_solenoids(pcm_->GetAll());
+      builder.Send(to_log_builder.Finish());
     }
   }
 
@@ -192,28 +200,30 @@
 
   ::std::unique_ptr<Compressor> compressor_;
 
-  ::aos::Fetcher<::frc971::control_loops::DrivetrainQueue::Output>
+  ::aos::Fetcher<::frc971::control_loops::drivetrain::Output>
       drivetrain_fetcher_;
-  ::aos::Fetcher<::y2012::control_loops::AccessoriesQueue::Message>
+  ::aos::Fetcher<::y2012::control_loops::accessories::Message>
       accessories_fetcher_;
+
+  aos::Sender<::frc971::wpilib::PneumaticsToLog> pneumatics_to_log_sender_;
 };
 
-class AccessoriesWriter
-    : public ::frc971::wpilib::LoopOutputHandler<AccessoriesQueue::Message> {
+class AccessoriesWriter : public ::frc971::wpilib::LoopOutputHandler<
+                              control_loops::accessories::Message> {
  public:
   AccessoriesWriter(::aos::EventLoop *event_loop)
-      : ::frc971::wpilib::LoopOutputHandler<AccessoriesQueue::Message>(
-            event_loop, ".y2012.control_loops.accessories_queue.output") {}
+      : ::frc971::wpilib::LoopOutputHandler<
+            control_loops::accessories::Message>(event_loop, "/accessories") {}
 
   void set_talon1(::std::unique_ptr<Talon> t) { talon1_ = ::std::move(t); }
 
   void set_talon2(::std::unique_ptr<Talon> t) { talon2_ = ::std::move(t); }
 
  private:
-  virtual void Write(const AccessoriesQueue::Message &output) override {
-    talon1_->SetSpeed(output.sticks[0]);
-    talon2_->SetSpeed(output.sticks[1]);
-    AOS_LOG_STRUCT(DEBUG, "will output", output);
+  virtual void Write(
+      const control_loops::accessories::Message &output) override {
+    talon1_->SetSpeed(output.sticks()->Get(0));
+    talon2_->SetSpeed(output.sticks()->Get(1));
   }
 
   virtual void Stop() override {
@@ -233,21 +243,24 @@
   }
 
   void Run() override {
+    aos::FlatbufferDetachedBuffer<aos::Configuration> config =
+        aos::configuration::ReadConfig("config.json");
+
     // Thread 1.
-    ::aos::ShmEventLoop joystick_sender_event_loop;
+    ::aos::ShmEventLoop joystick_sender_event_loop(&config.message());
     ::frc971::wpilib::JoystickSender joystick_sender(
         &joystick_sender_event_loop);
     AddLoop(&joystick_sender_event_loop);
 
     // Thread 2.
-    ::aos::ShmEventLoop sensor_reader_event_loop;
+    ::aos::ShmEventLoop sensor_reader_event_loop(&config.message());
     SensorReader sensor_reader(&sensor_reader_event_loop);
     sensor_reader.set_drivetrain_left_encoder(make_encoder(0));
     sensor_reader.set_drivetrain_right_encoder(make_encoder(1));
     AddLoop(&sensor_reader_event_loop);
 
     // Thread 3.
-    ::aos::ShmEventLoop output_event_loop;
+    ::aos::ShmEventLoop output_event_loop(&config.message());
     ::frc971::wpilib::DrivetrainWriter drivetrain_writer(&output_event_loop);
     drivetrain_writer.set_left_controller0(
         ::std::unique_ptr<Talon>(new Talon(3)), true);
@@ -260,7 +273,7 @@
     AddLoop(&output_event_loop);
 
     // Thread 4.
-    ::aos::ShmEventLoop solenoid_writer_event_loop;
+    ::aos::ShmEventLoop solenoid_writer_event_loop(&config.message());
     ::std::unique_ptr<::frc971::wpilib::BufferedPcm> pcm(
         new ::frc971::wpilib::BufferedPcm());
     SolenoidWriter solenoid_writer(&solenoid_writer_event_loop, pcm);