Convert actions to event loops

The logic gets significantly simpler due to Watchers.  But we also get
to port all the users over as well.

Change-Id: Ib4e75951e65f7431acc6c1548b7f1d20da3da295
diff --git a/y2016/actors/autonomous_actor.cc b/y2016/actors/autonomous_actor.cc
index 4f68f20..a5621b3 100644
--- a/y2016/actors/autonomous_actor.cc
+++ b/y2016/actors/autonomous_actor.cc
@@ -45,11 +45,11 @@
 
 }  // namespace
 
-AutonomousActor::AutonomousActor(
-    ::aos::EventLoop *event_loop,
-    ::frc971::autonomous::AutonomousActionQueueGroup *s)
+AutonomousActor::AutonomousActor(::aos::EventLoop *event_loop)
     : frc971::autonomous::BaseAutonomousActor(
-          event_loop, s, control_loops::drivetrain::GetDrivetrainConfig()) {}
+          event_loop, control_loops::drivetrain::GetDrivetrainConfig()),
+      vision_align_actor_factory_(
+          actors::VisionAlignActor::MakeFactory(event_loop)) {}
 
 constexpr double kDoNotTurnCare = 2.0;
 
@@ -194,7 +194,7 @@
 
 void AutonomousActor::AlignWithVisionGoal() {
   actors::VisionAlignActionParams params;
-  vision_action_ = actors::MakeVisionAlignAction(params);
+  vision_action_ = vision_align_actor_factory_.Make(params);
   vision_action_->Start();
 }
 
diff --git a/y2016/actors/autonomous_actor.h b/y2016/actors/autonomous_actor.h
index 4a220ed..a2dda27 100644
--- a/y2016/actors/autonomous_actor.h
+++ b/y2016/actors/autonomous_actor.h
@@ -18,8 +18,7 @@
 
 class AutonomousActor : public ::frc971::autonomous::BaseAutonomousActor {
  public:
-  explicit AutonomousActor(::aos::EventLoop *event_loop,
-                           ::frc971::autonomous::AutonomousActionQueueGroup *s);
+  explicit AutonomousActor(::aos::EventLoop *event_loop);
 
   bool RunAction(
       const ::frc971::autonomous::AutonomousActionParams &params) override;
@@ -85,7 +84,8 @@
 
   void TwoBallAuto();
 
-  ::std::unique_ptr<actors::VisionAlignAction> vision_action_;
+  actors::VisionAlignActor::Factory vision_align_actor_factory_;
+  ::std::unique_ptr<::aos::common::actions::Action> vision_action_;
 };
 
 }  // namespace actors
diff --git a/y2016/actors/autonomous_actor_main.cc b/y2016/actors/autonomous_actor_main.cc
index 16fc5c4..1e2628b 100644
--- a/y2016/actors/autonomous_actor_main.cc
+++ b/y2016/actors/autonomous_actor_main.cc
@@ -8,9 +8,8 @@
   ::aos::Init(-1);
 
   ::aos::ShmEventLoop event_loop;
-  ::y2016::actors::AutonomousActor autonomous(
-      &event_loop, &::frc971::autonomous::autonomous_action);
-  autonomous.Run();
+  ::y2016::actors::AutonomousActor autonomous(&event_loop);
+  event_loop.Run();
 
   ::aos::Cleanup();
   return 0;
diff --git a/y2016/actors/superstructure_action.q b/y2016/actors/superstructure_action.q
index eb23397..1b937aa 100644
--- a/y2016/actors/superstructure_action.q
+++ b/y2016/actors/superstructure_action.q
@@ -21,5 +21,3 @@
   queue Goal goal;
   queue aos.common.actions.Status status;
 };
-
-queue_group SuperstructureActionQueueGroup superstructure_action;
diff --git a/y2016/actors/superstructure_actor.cc b/y2016/actors/superstructure_actor.cc
index d8537ce..f65d05a 100644
--- a/y2016/actors/superstructure_actor.cc
+++ b/y2016/actors/superstructure_actor.cc
@@ -12,10 +12,9 @@
 
 namespace chrono = ::std::chrono;
 
-SuperstructureActor::SuperstructureActor(
-    actors::SuperstructureActionQueueGroup *s)
+SuperstructureActor::SuperstructureActor(::aos::EventLoop *event_loop)
     : aos::common::actions::ActorBase<actors::SuperstructureActionQueueGroup>(
-          s) {}
+          event_loop, ".y2016.actors.superstructure_action") {}
 
 bool SuperstructureActor::RunAction(
     const actors::SuperstructureActionParams &params) {
@@ -105,11 +104,5 @@
   }
 }
 
-::std::unique_ptr<SuperstructureAction> MakeSuperstructureAction(
-    const ::y2016::actors::SuperstructureActionParams& params) {
-  return ::std::unique_ptr<SuperstructureAction>(new SuperstructureAction(
-      &::y2016::actors::superstructure_action, params));
-}
-
 }  // namespace actors
 }  // namespace y2016
diff --git a/y2016/actors/superstructure_actor.h b/y2016/actors/superstructure_actor.h
index d48fc71..be02a33 100644
--- a/y2016/actors/superstructure_actor.h
+++ b/y2016/actors/superstructure_actor.h
@@ -13,7 +13,15 @@
 class SuperstructureActor
     : public ::aos::common::actions::ActorBase<SuperstructureActionQueueGroup> {
  public:
-  explicit SuperstructureActor(SuperstructureActionQueueGroup *s);
+  typedef ::aos::common::actions::TypedActionFactory<
+      SuperstructureActionQueueGroup>
+      Factory;
+
+  explicit SuperstructureActor(::aos::EventLoop *event_loop);
+
+  static Factory MakeFactory(::aos::EventLoop *event_loop) {
+    return Factory(event_loop, ".y2016.actors.superstructure_action");
+  }
 
   // Internal struct holding superstructure goals sent by autonomous to the
   // loop.
@@ -30,13 +38,6 @@
   bool SuperstructureDone();
 };
 
-using SuperstructureAction =
-    ::aos::common::actions::TypedAction<SuperstructureActionQueueGroup>;
-
-// Makes a new SuperstructureActor action.
-::std::unique_ptr<SuperstructureAction> MakeSuperstructureAction(
-    const ::y2016::actors::SuperstructureActionParams &params);
-
 }  // namespace actors
 }  // namespace y2016
 
diff --git a/y2016/actors/superstructure_actor_main.cc b/y2016/actors/superstructure_actor_main.cc
index 69bea8a..a97802c 100644
--- a/y2016/actors/superstructure_actor_main.cc
+++ b/y2016/actors/superstructure_actor_main.cc
@@ -1,5 +1,6 @@
 #include <stdio.h>
 
+#include "aos/events/shm-event-loop.h"
 #include "aos/init.h"
 #include "y2016/actors/superstructure_action.q.h"
 #include "y2016/actors/superstructure_actor.h"
@@ -7,9 +8,9 @@
 int main(int /*argc*/, char* /*argv*/ []) {
   ::aos::Init(-1);
 
-  ::y2016::actors::SuperstructureActor superstructure(
-      &::y2016::actors::superstructure_action);
-  superstructure.Run();
+  ::aos::ShmEventLoop event_loop;
+  ::y2016::actors::SuperstructureActor superstructure(&event_loop);
+  event_loop.Run();
 
   ::aos::Cleanup();
   return 0;
diff --git a/y2016/actors/vision_align_action.q b/y2016/actors/vision_align_action.q
index e822bf4..f9f3024 100644
--- a/y2016/actors/vision_align_action.q
+++ b/y2016/actors/vision_align_action.q
@@ -18,5 +18,3 @@
   queue Goal goal;
   queue aos.common.actions.Status status;
 };
-
-queue_group VisionAlignActionQueueGroup vision_align_action;
diff --git a/y2016/actors/vision_align_actor.cc b/y2016/actors/vision_align_actor.cc
index b805747..5aebb06 100644
--- a/y2016/actors/vision_align_actor.cc
+++ b/y2016/actors/vision_align_actor.cc
@@ -22,8 +22,9 @@
 namespace actors {
 using ::frc971::control_loops::drivetrain_queue;
 
-VisionAlignActor::VisionAlignActor(actors::VisionAlignActionQueueGroup *s)
-    : aos::common::actions::ActorBase<actors::VisionAlignActionQueueGroup>(s) {}
+VisionAlignActor::VisionAlignActor(::aos::EventLoop *event_loop)
+    : aos::common::actions::ActorBase<actors::VisionAlignActionQueueGroup>(
+          event_loop, ".y2016.actors.vision_align_action") {}
 
 bool VisionAlignActor::RunAction(
     const actors::VisionAlignActionParams & /*params*/) {
@@ -76,11 +77,5 @@
   return true;
 }
 
-::std::unique_ptr<VisionAlignAction> MakeVisionAlignAction(
-    const ::y2016::actors::VisionAlignActionParams &params) {
-  return ::std::unique_ptr<VisionAlignAction>(
-      new VisionAlignAction(&::y2016::actors::vision_align_action, params));
-}
-
 }  // namespace actors
 }  // namespace y2016
diff --git a/y2016/actors/vision_align_actor.h b/y2016/actors/vision_align_actor.h
index a1f07fa..7fce07a 100644
--- a/y2016/actors/vision_align_actor.h
+++ b/y2016/actors/vision_align_actor.h
@@ -15,18 +15,19 @@
 class VisionAlignActor
     : public ::aos::common::actions::ActorBase<VisionAlignActionQueueGroup> {
  public:
-  explicit VisionAlignActor(VisionAlignActionQueueGroup *s);
+  typedef ::aos::common::actions::TypedActionFactory<
+      VisionAlignActionQueueGroup>
+      Factory;
+
+  explicit VisionAlignActor(::aos::EventLoop *event_loop);
+
+  static Factory MakeFactory(::aos::EventLoop *event_loop) {
+    return Factory(event_loop, ".y2016.actors.vision_align_action");
+  }
 
   bool RunAction(const actors::VisionAlignActionParams &params) override;
 };
 
-typedef ::aos::common::actions::TypedAction<VisionAlignActionQueueGroup>
-    VisionAlignAction;
-
-// Makes a new VisionAlignActor action.
-::std::unique_ptr<VisionAlignAction> MakeVisionAlignAction(
-    const ::y2016::actors::VisionAlignActionParams &params);
-
 }  // namespace actors
 }  // namespace y2016
 
diff --git a/y2016/actors/vision_align_actor_main.cc b/y2016/actors/vision_align_actor_main.cc
index f9854f7..2fd9eb2 100644
--- a/y2016/actors/vision_align_actor_main.cc
+++ b/y2016/actors/vision_align_actor_main.cc
@@ -1,5 +1,6 @@
 #include <stdio.h>
 
+#include "aos/events/shm-event-loop.h"
 #include "aos/init.h"
 #include "y2016/actors/vision_align_action.q.h"
 #include "y2016/actors/vision_align_actor.h"
@@ -7,9 +8,9 @@
 int main(int /*argc*/, char* /*argv*/ []) {
   ::aos::Init(-1);
 
-  ::y2016::actors::VisionAlignActor vision_align(
-      &::y2016::actors::vision_align_action);
-  vision_align.Run();
+  ::aos::ShmEventLoop event_loop;
+  ::y2016::actors::VisionAlignActor vision_align(&event_loop);
+  event_loop.Run();
 
   ::aos::Cleanup();
   return 0;
diff --git a/y2016/dashboard/BUILD b/y2016/dashboard/BUILD
index 2892814..f3998a1 100644
--- a/y2016/dashboard/BUILD
+++ b/y2016/dashboard/BUILD
@@ -28,6 +28,8 @@
     deps = [
         ":gen_embedded",
         "//aos:init",
+        "//aos/events:event-loop",
+        "//aos/events:shm-event-loop",
         "//aos/logging",
         "//aos/seasocks:seasocks_logger",
         "//aos/time",
diff --git a/y2016/dashboard/dashboard.cc b/y2016/dashboard/dashboard.cc
index 84af420..d105a10 100644
--- a/y2016/dashboard/dashboard.cc
+++ b/y2016/dashboard/dashboard.cc
@@ -11,6 +11,7 @@
 #include "internal/Embedded.h"
 #include "seasocks/Server.h"
 
+#include "aos/events/shm-event-loop.h"
 #include "aos/init.h"
 #include "aos/logging/logging.h"
 #include "aos/mutex/mutex.h"
@@ -49,8 +50,11 @@
 // caused problems in the past when auto aiming that still need to be addressed.
 //#define DASHBOARD_READ_VISION_QUEUE
 
-DataCollector::DataCollector()
-    : cur_raw_data_("no data"),
+DataCollector::DataCollector(::aos::EventLoop *event_loop)
+    : vision_status_fetcher_(
+          event_loop->MakeFetcher<::y2016::vision::VisionStatus>(
+              ".y2016.vision.vision_status")),
+      cur_raw_data_("no data"),
       sample_id_(0),
       measure_index_(0),
       overflow_id_(1) {}
@@ -84,16 +88,16 @@
   ::frc971::autonomous::auto_mode.FetchLatest();
   ::y2016::control_loops::superstructure_queue.status.FetchLatest();
   ::y2016::sensors::ball_detector.FetchLatest();
-  ::y2016::vision::vision_status.FetchLatest();
+  vision_status_fetcher_.Fetch();
 
 // Caused glitching with auto-aim at NASA, so be cautious with this until
 // we find a good fix.
 #ifdef DASHBOARD_READ_VISION_QUEUE
-  if (::y2016::vision::vision_status.get() &&
-      (::y2016::vision::vision_status->left_image_valid ||
-       ::y2016::vision::vision_status->right_image_valid)) {
+  if (vision_status_fetcher_.get() &&
+      (vision_status_fetcher_->left_image_valid ||
+       vision_status_fetcher_->right_image_valid)) {
     big_indicator = big_indicator::kAiming;
-    if (::std::abs(::y2016::vision::vision_status->horizontal_angle) < 0.002) {
+    if (::std::abs(vision_status_fetcher_->horizontal_angle) < 0.002) {
       big_indicator = big_indicator::kLockedOn;
     }
   }
@@ -234,8 +238,9 @@
   }
 }
 
-SocketHandler::SocketHandler()
-    : data_collector_thread_(::std::ref(data_collector_)) {}
+SocketHandler::SocketHandler(::aos::EventLoop *event_loop)
+    : data_collector_(event_loop),
+      data_collector_thread_(::std::ref(data_collector_)) {}
 
 void SocketHandler::onConnect(seasocks::WebSocket *connection) {
   connections_.insert(connection);
@@ -270,9 +275,11 @@
 
   ::aos::InitNRT();
 
+  ::aos::ShmEventLoop event_loop;
+
   ::seasocks::Server server(::std::shared_ptr<seasocks::Logger>(
       new ::aos::seasocks::SeasocksLogger(::seasocks::Logger::Level::Info)));
-  ::y2016::dashboard::SocketHandler socket_handler;
+  ::y2016::dashboard::SocketHandler socket_handler(&event_loop);
 
   server.addWebSocketHandler(
       "/ws",
diff --git a/y2016/dashboard/dashboard.h b/y2016/dashboard/dashboard.h
index d9b7c11..8c64348 100644
--- a/y2016/dashboard/dashboard.h
+++ b/y2016/dashboard/dashboard.h
@@ -1,3 +1,6 @@
+#ifndef Y2016_DASHBOARD_DASHBOARD_H_
+#define Y2016_DASHBOARD_DASHBOARD_H_
+
 #include <iostream>
 #include <memory>
 #include <sstream>
@@ -11,10 +14,10 @@
 #include "seasocks/StringUtil.h"
 #include "seasocks/WebSocket.h"
 
-#include "aos/init.h"
-#include "aos/time/time.h"
-#include "aos/util/phased_loop.h"
+#include "aos/events/event-loop.h"
 #include "aos/mutex/mutex.h"
+#include "aos/time/time.h"
+#include "y2016/vision/vision.q.h"
 
 namespace y2016 {
 namespace dashboard {
@@ -31,7 +34,7 @@
 
 class DataCollector {
  public:
-  DataCollector();
+  DataCollector(::aos::EventLoop *event_loop);
   void RunIteration();
 
   // Store a datapoint. In this case, we are reading data points to determine
@@ -60,6 +63,8 @@
     ::std::vector<ItemDatapoint> datapoints;
   };
 
+  ::aos::Fetcher<::y2016::vision::VisionStatus> vision_status_fetcher_;
+
   // Storage vector that is written and overwritten with data in a FIFO fashion.
   ::std::vector<SampleItem> sample_items_;
 
@@ -74,7 +79,7 @@
 
 class SocketHandler : public seasocks::WebSocket::Handler {
  public:
-  SocketHandler();
+  SocketHandler(::aos::EventLoop *event_loop);
   void onConnect(seasocks::WebSocket* connection) override;
   void onData(seasocks::WebSocket* connection, const char* data) override;
   void onDisconnect(seasocks::WebSocket* connection) override;
@@ -94,3 +99,5 @@
 
 }  // namespace dashboard
 }  // namespace y2016
+
+#endif  // Y2016_DASHBOARD_DASHBOARD_H_
diff --git a/y2016/joystick_reader.cc b/y2016/joystick_reader.cc
index 19cd065..33244be 100644
--- a/y2016/joystick_reader.cc
+++ b/y2016/joystick_reader.cc
@@ -69,16 +69,27 @@
 const ButtonLocation kExpand(3, 6);
 const ButtonLocation kWinch(3, 5);
 
+// TODO(austin): ActionJoystickInput
 class Reader : public ::aos::input::JoystickInput {
  public:
   Reader(::aos::EventLoop *event_loop)
       : ::aos::input::JoystickInput(event_loop),
+        vision_status_fetcher_(
+            event_loop->MakeFetcher<::y2016::vision::VisionStatus>(
+                ".y2016.vision.vision_status")),
         is_high_gear_(true),
         intake_goal_(0.0),
         shoulder_goal_(M_PI / 2.0),
         wrist_goal_(0.0),
-        dt_config_(control_loops::drivetrain::GetDrivetrainConfig()) {}
+        dt_config_(control_loops::drivetrain::GetDrivetrainConfig()),
+        autonomous_action_factory_(
+            ::frc971::autonomous::BaseAutonomousActor::MakeFactory(event_loop)),
+        vision_align_action_factory_(
+            actors::VisionAlignActor::MakeFactory(event_loop)),
+        superstructure_action_factory_(
+            actors::SuperstructureActor::MakeFactory(event_loop)) {}
 
+  // TODO(austin): Move this to the ActionJoystickInput class.
   void RunIteration(const ::aos::input::driver_station::Data &data) override {
     bool last_auto_running = auto_running_;
     auto_running_ = data.GetControlBit(ControlBit::kAutonomous) &&
@@ -100,12 +111,12 @@
 
     vision_valid_ = false;
 
-    ::y2016::vision::vision_status.FetchLatest();
+    vision_status_fetcher_.Fetch();
 
-    if (::y2016::vision::vision_status.get()) {
-      vision_valid_ = (::y2016::vision::vision_status->left_image_valid &&
-                      ::y2016::vision::vision_status->right_image_valid);
-      last_angle_ = ::y2016::vision::vision_status->horizontal_angle;
+    if (vision_status_fetcher_.get()) {
+      vision_valid_ = (vision_status_fetcher_->left_image_valid &&
+                       vision_status_fetcher_->right_image_valid);
+      last_angle_ = vision_status_fetcher_->horizontal_angle;
     }
 
     if (!auto_running_) {
@@ -128,7 +139,7 @@
     if (data.IsPressed(kVisionAlign)) {
       if (vision_valid_ && !vision_action_running_) {
         actors::VisionAlignActionParams params;
-        action_queue_.EnqueueAction(actors::MakeVisionAlignAction(params));
+        action_queue_.EnqueueAction(vision_align_action_factory_.Make(params));
         vision_action_running_ = true;
         LOG(INFO, "Starting vision align\n");
       } else {
@@ -258,7 +269,8 @@
         params.delay_time = 0.7;
         params.full_angle = shoulder_goal_;
         params.shooter_angle = wrist_goal_;
-        action_queue_.EnqueueAction(actors::MakeSuperstructureAction(params));
+        action_queue_.EnqueueAction(
+            superstructure_action_factory_.Make(params));
       }
       if (data.IsPressed(kWinch)) {
         voltage_climber = 12.0;
@@ -436,8 +448,7 @@
       LOG(WARNING, "no auto mode values\n");
       params.mode = 0;
     }
-    action_queue_.EnqueueAction(
-        ::frc971::autonomous::MakeAutonomousAction(params));
+    action_queue_.EnqueueAction(autonomous_action_factory_.Make(params));
   }
 
   void StopAuto() {
@@ -445,6 +456,8 @@
     action_queue_.CancelAllActions();
   }
 
+  ::aos::Fetcher<::y2016::vision::VisionStatus> vision_status_fetcher_;
+
   bool is_high_gear_;
   // Whatever these are set to are our default goals to send out after zeroing.
   double intake_goal_;
@@ -486,6 +499,10 @@
 
   bool is_expanding_ = false;
 
+  ::frc971::autonomous::BaseAutonomousActor::Factory autonomous_action_factory_;
+  actors::VisionAlignActor::Factory vision_align_action_factory_;
+  actors::SuperstructureActor::Factory superstructure_action_factory_;
+
   ::aos::util::SimpleLogInterval no_drivetrain_status_ =
       ::aos::util::SimpleLogInterval(::std::chrono::milliseconds(200), WARNING,
                                      "no drivetrain status");
diff --git a/y2016/vision/BUILD b/y2016/vision/BUILD
index 99c50fd..3427973 100644
--- a/y2016/vision/BUILD
+++ b/y2016/vision/BUILD
@@ -132,6 +132,7 @@
         ":vision_data",
         ":vision_queue",
         "//aos:init",
+        "//aos/events:shm-event-loop",
         "//aos/logging",
         "//aos/logging:queue_logging",
         "//aos/mutex",
diff --git a/y2016/vision/target_receiver.cc b/y2016/vision/target_receiver.cc
index 4b95034..57fbd51 100644
--- a/y2016/vision/target_receiver.cc
+++ b/y2016/vision/target_receiver.cc
@@ -10,15 +10,15 @@
 #include <thread>
 #include <vector>
 
+#include "aos/events/event-loop.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/mutex/mutex.h"
 #include "aos/time/time.h"
 #include "aos/vision/events/udp.h"
-
 #include "frc971/control_loops/drivetrain/drivetrain.q.h"
-
 #include "y2016/constants.h"
 #include "y2016/vision/stereo_geometry.h"
 #include "y2016/vision/vision.q.h"
@@ -302,6 +302,12 @@
 };
 
 void Main() {
+  ::aos::ShmEventLoop event_loop;
+
+  ::aos::Sender<::y2016::vision::VisionStatus> vision_status_sender =
+      event_loop.MakeSender<::y2016::vision::VisionStatus>(
+          ".y2016.vision.vision_status");
+
   StereoGeometry stereo(constants::GetValues().vision_name);
   LOG(INFO, "calibration: %s\n",
       stereo.calibration().ShortDebugString().c_str());
@@ -339,7 +345,7 @@
       const bool left_image_valid = left.is_valid();
       const bool right_image_valid = right.is_valid();
 
-      auto new_vision_status = vision_status.MakeMessage();
+      auto new_vision_status = vision_status_sender.MakeMessage();
       new_vision_status->left_image_valid = left_image_valid;
       new_vision_status->right_image_valid = right_image_valid;
       if (left_image_valid && right_image_valid) {
diff --git a/y2016/vision/vision.q b/y2016/vision/vision.q
index 47906dc..da028fd 100644
--- a/y2016/vision/vision.q
+++ b/y2016/vision/vision.q
@@ -1,5 +1,6 @@
 package y2016.vision;
 
+// Published on ".y2016.vision.vision_status"
 message VisionStatus {
   bool left_image_valid;
   bool right_image_valid;