Add Game Piece Detector

Signed-off-by: Filip Kujawa <filip.j.kujawa@gmail.com>
Change-Id: I4f460e64b1fb9fbe1e0d50581412e106a89515e2
diff --git a/y2023/BUILD b/y2023/BUILD
index a500a83..309ada4 100644
--- a/y2023/BUILD
+++ b/y2023/BUILD
@@ -70,6 +70,7 @@
         "//aos/starter:irq_affinity",
         "//y2023/vision:camera_reader",
         "//aos/events/logging:logger_main",
+        "//y2023/vision:game_pieces_detector",
     ],
     target_compatible_with = ["//tools/platforms/hardware:raspberry_pi"],
     target_type = "pi",
@@ -114,6 +115,7 @@
             "//frc971/vision:target_map_fbs",
             "//frc971/vision:vision_fbs",
             "//y2023/localizer:visualization_fbs",
+            "//y2023/vision:game_pieces_fbs",
             "@com_github_foxglove_schemas//:schemas",
         ],
         target_compatible_with = ["@platforms//os:linux"],
@@ -166,6 +168,7 @@
         "//frc971/vision:vision_fbs",
         "//frc971/vision:target_map_fbs",
         "//y2023/constants:constants_fbs",
+        "//y2023/vision:game_pieces_fbs",
     ],
     target_compatible_with = ["@platforms//os:linux"],
     visibility = ["//visibility:public"],
diff --git a/y2023/vision/BUILD b/y2023/vision/BUILD
index 05e4f6c..9bd29fa 100644
--- a/y2023/vision/BUILD
+++ b/y2023/vision/BUILD
@@ -1,3 +1,5 @@
+load("@com_github_google_flatbuffers//:build_defs.bzl", "flatbuffer_cc_library")
+
 cc_binary(
     name = "camera_reader",
     srcs = [
@@ -167,3 +169,46 @@
         "//y2023/vision:vision_util",
     ],
 )
+
+cc_binary(
+    name = "game_pieces_detector",
+    srcs = [
+        "game_pieces_main.cc",
+    ],
+    target_compatible_with = ["@platforms//os:linux"],
+    visibility = ["//y2023:__subpackages__"],
+    deps = [
+        ":game_pieces_lib",
+        "//aos:init",
+        "//aos/events:shm_event_loop",
+    ],
+)
+
+cc_library(
+    name = "game_pieces_lib",
+    srcs = [
+        "game_pieces.cc",
+    ],
+    hdrs = [
+        "game_pieces.h",
+    ],
+    data = [
+        "//y2023:aos_config",
+    ],
+    target_compatible_with = ["@platforms//os:linux"],
+    visibility = ["//y2023:__subpackages__"],
+    deps = [
+        ":game_pieces_fbs",
+        "//aos/events:event_loop",
+        "//aos/events:shm_event_loop",
+        "//frc971/vision:vision_fbs",
+    ],
+)
+
+flatbuffer_cc_library(
+    name = "game_pieces_fbs",
+    srcs = ["game_pieces.fbs"],
+    gen_reflections = 1,
+    target_compatible_with = ["@platforms//os:linux"],
+    visibility = ["//visibility:public"],
+)
diff --git a/y2023/vision/game_pieces.cc b/y2023/vision/game_pieces.cc
new file mode 100644
index 0000000..868d5b0
--- /dev/null
+++ b/y2023/vision/game_pieces.cc
@@ -0,0 +1,47 @@
+#include "y2023/vision/game_pieces.h"
+
+#include "aos/events/event_loop.h"
+#include "aos/events/shm_event_loop.h"
+#include "frc971/vision/vision_generated.h"
+
+namespace y2023 {
+namespace vision {
+GamePiecesDetector::GamePiecesDetector(aos::EventLoop *event_loop)
+    : game_pieces_sender_(
+          event_loop->MakeSender<GamePieces>("/camera")) {
+  event_loop->MakeWatcher("/camera", [this](const CameraImage &camera_image) {
+    this->ProcessImage(camera_image);
+  });
+}
+
+void GamePiecesDetector::ProcessImage(const CameraImage &image) {
+  // Param is not used for now.
+  (void)image;
+
+  auto builder = game_pieces_sender_.MakeBuilder();
+
+  auto box_builder = builder.MakeBuilder<Box>();
+  box_builder.add_h(10);
+  box_builder.add_w(20);
+  box_builder.add_x(30);
+  box_builder.add_y(40);
+  auto box_offset = box_builder.Finish();
+
+  auto game_piece_builder = builder.MakeBuilder<GamePiece>();
+  game_piece_builder.add_piece_class(y2023::vision::Class::CONE_DOWN);
+  game_piece_builder.add_box(box_offset);
+  game_piece_builder.add_confidence(0.9);
+  auto game_piece = game_piece_builder.Finish();
+
+  flatbuffers::FlatBufferBuilder fbb;
+  auto game_pieces_vector =
+      fbb.CreateVector(std::vector<flatbuffers::Offset<GamePiece>>{game_piece});
+
+  auto game_pieces_builder = builder.MakeBuilder<GamePieces>();
+  game_pieces_builder.add_game_pieces(game_pieces_vector);
+
+  builder.CheckOk(builder.Send(game_pieces_builder.Finish()));
+}
+
+}  // namespace vision
+}  // namespace y2023
\ No newline at end of file
diff --git a/y2023/vision/game_pieces.fbs b/y2023/vision/game_pieces.fbs
new file mode 100644
index 0000000..e981712
--- /dev/null
+++ b/y2023/vision/game_pieces.fbs
@@ -0,0 +1,29 @@
+namespace y2023.vision;
+
+// Object class.
+enum Class : byte {
+    CONE_DOWN,
+    CONE_UP,
+    CUBE
+}
+
+// Bounding box dimensions and position.
+table Box {
+    //TODO(Filip): Are cords center of box or top left corner?
+    x:uint (id: 0);
+    y:uint (id: 1);
+    w:uint (id: 2);
+    h:uint (id: 3);
+}
+
+table GamePiece {
+    piece_class:Class (id: 0);
+    box:Box (id:1);
+    confidence:float (id:2);
+}
+
+table GamePieces {
+    game_pieces:[GamePiece] (id: 0);
+}
+
+root_type GamePieces;
\ No newline at end of file
diff --git a/y2023/vision/game_pieces.h b/y2023/vision/game_pieces.h
new file mode 100644
index 0000000..a41d52a
--- /dev/null
+++ b/y2023/vision/game_pieces.h
@@ -0,0 +1,26 @@
+#ifndef Y2023_VISION_GAME_PIECES_H_
+#define Y2023_VISION_GAME_PIECES_H_
+
+#include "aos/events/shm_event_loop.h"
+#include "frc971/vision/vision_generated.h"
+#include "y2023/vision/game_pieces_generated.h"
+
+namespace y2023 {
+namespace vision {
+
+using namespace frc971::vision;
+
+// Takes in camera images and detects game pieces in the image.
+// Note: Actual detection has not been implemented yet.
+class GamePiecesDetector {
+ public:
+  GamePiecesDetector(aos::EventLoop *event_loop);
+
+  void ProcessImage(const CameraImage &camera_image);
+
+ private:
+  aos::Sender<GamePieces> game_pieces_sender_;
+};
+}  // namespace vision
+}  // namespace y2023
+#endif
diff --git a/y2023/vision/game_pieces_main.cc b/y2023/vision/game_pieces_main.cc
new file mode 100644
index 0000000..97940b6
--- /dev/null
+++ b/y2023/vision/game_pieces_main.cc
@@ -0,0 +1,25 @@
+#include "aos/events/shm_event_loop.h"
+#include "aos/init.h"
+#include "y2023/vision/game_pieces.h"
+
+DEFINE_string(config, "aos_config.json", "Path to the config file to use.");
+
+namespace y2023 {
+namespace vision {
+namespace {
+
+void GamePiecesDetectorMain() {
+  aos::FlatbufferDetachedBuffer<aos::Configuration> config =
+      aos::configuration::ReadConfig(FLAGS_config);
+  aos::ShmEventLoop event_loop(&config.message());
+  GamePiecesDetector game_pieces_detector(&event_loop);
+  event_loop.Run();
+}
+}  // namespace
+}  // namespace vision
+}  // namespace y2023
+
+int main(int argc, char **argv) {
+  aos::InitGoogle(&argc, &argv);
+  y2023::vision::GamePiecesDetectorMain();
+}
diff --git a/y2023/y2023_logger.json b/y2023/y2023_logger.json
index 840ac23..387915d 100644
--- a/y2023/y2023_logger.json
+++ b/y2023/y2023_logger.json
@@ -41,6 +41,38 @@
       ]
     },
     {
+      "name": "/camera",
+      "type": "y2023.vision.GamePieces",
+      "source_node": "logger",
+      "logger": "LOCAL_AND_REMOTE_LOGGER",
+      "logger_nodes": [
+        "roborio"
+      ],
+      "frequency": 40,
+      "num_senders": 2,
+      "max_size": 1024,
+      "destination_nodes": [
+        {
+          "name": "roborio",
+          "priority": 2,
+          "timestamp_logger": "LOCAL_AND_REMOTE_LOGGER",
+          "timestamp_logger_nodes": [
+            "roborio"
+          ],
+          "time_to_live": 5000000
+        }
+      ]
+    },
+    {
+      "name": "/logger/aos/remote_timestamps/roborio/camera/y2023-vision-GamePieces",
+      "type": "aos.message_bridge.RemoteMessage",
+      "source_node": "logger",
+      "logger": "NOT_LOGGED",
+      "frequency": 40,
+      "num_senders": 2,
+      "max_size": 200
+    },
+    {
       "name": "/roborio/aos/remote_timestamps/logger/drivetrain/frc971-control_loops-drivetrain-Position",
       "type": "aos.message_bridge.RemoteMessage",
       "source_node": "roborio",
@@ -499,6 +531,13 @@
       "nodes": [
         "logger"
       ]
+    },
+    {
+      "name": "game_piece_detector",
+      "executable_name": "game_piece_detector",
+      "nodes": [
+        "logger"
+      ]
     }
   ],
   "nodes": [