Add messages for SIFT features

Change-Id: I05a76480ce93cc3d108624621ebe8d5a6b3c9fd6
diff --git a/y2020/vision/sift/BUILD b/y2020/vision/sift/BUILD
index d3bafc6..ec06126 100644
--- a/y2020/vision/sift/BUILD
+++ b/y2020/vision/sift/BUILD
@@ -1,4 +1,5 @@
 load(":fast_gaussian.bzl", "fast_gaussian")
+load("@com_github_google_flatbuffers//:build_defs.bzl", "flatbuffer_cc_library", "flatbuffer_py_library")
 
 cc_binary(
     name = "fast_gaussian_generator",
@@ -169,3 +170,37 @@
         "@com_github_google_glog//:glog",
     ],
 )
+
+flatbuffer_py_library(
+    name = "sift_fbs_python",
+    srcs = [
+        "sift.fbs",
+        "sift_training.fbs",
+    ],
+    namespace = "frc971.vision.sift",
+    tables = [
+        "Feature",
+        "Match",
+        "ImageMatch",
+        "TransformationMatrix",
+        "CameraPose",
+        "ImageMatchResult",
+        "TrainingImage",
+        "TrainingData",
+    ],
+)
+
+flatbuffer_cc_library(
+    name = "sift_fbs",
+    srcs = ["sift.fbs"],
+    gen_reflections = True,
+    visibility = ["//visibility:public"],
+)
+
+flatbuffer_cc_library(
+    name = "sift_training_fbs",
+    srcs = ["sift_training.fbs"],
+    gen_reflections = True,
+    includes = [":sift_fbs_includes"],
+    visibility = ["//visibility:public"],
+)
diff --git a/y2020/vision/sift/sift.fbs b/y2020/vision/sift/sift.fbs
new file mode 100644
index 0000000..84697de
--- /dev/null
+++ b/y2020/vision/sift/sift.fbs
@@ -0,0 +1,87 @@
+namespace frc971.vision.sift;
+
+// Represents a single feature extracted from an image.
+table Feature {
+  // Contains the descriptor data.
+  //
+  // TODO(Brian): These are scaled to be convertible to chars. Should we do
+  // that to minimize storage space? Or maybe int16?
+  //
+  // The size of this depends on the parameters. It is width*width*hist_bins.
+  // Currently we have width=4 and hist_bins=8, which results in a size of
+  // 4*4*8=128.
+  descriptor:[float];
+
+  // Location of the keypoint.
+  x:float;
+  y:float;
+
+  // Size of the keypoint neighborhood.
+  size:float;
+
+  // Angle of the keypoint.
+  // This is in [0,360) clockwise.
+  angle:float;
+
+  // How good of a keypoint this is.
+  response:float;
+
+  // Which octave this keypoint is from.
+  octave:int;
+}
+
+// Represents a single match between a training image and a query image.
+table Match {
+  // The index of the feature for the query image.
+  query_feature:int;
+  // The index of the feature for the training image.
+  train_feature:int;
+}
+
+// Represents all the matches between a single training image and a query
+// image.
+table ImageMatch {
+  matches:[Match];
+  // The index of the training image within all the training images.
+  train_image:int;
+}
+
+table TransformationMatrix {
+  // The matrix data. This is a row-major 3x4 matrix.
+  data:[double];
+}
+
+// Contains the information the EKF wants from an image.
+//
+// This is represented as a transformation to a target in field coordinates.
+table CameraPose {
+  // Transformation matrix from the target to the camera's origin.
+  camera_to_target:TransformationMatrix;
+
+  // Field coordinates of the target, represented as a transformation matrix
+  // from the target to the field.
+  // (0, 0, 0) is the center of the field, on the level of most of the field
+  // (not the region under the truss). Positive X is towards the red alliance's
+  // PLAYER STATION. Positive Z is up. The coordinate system is right-handed.
+  //
+  // Note that the red PLAYER STATION is where the red drive teams are. This is
+  // often where the blue robots are shooting towards.
+  //
+  // The value here will be selected from a small, static set of targets we
+  // train images on.
+  field_to_target:TransformationMatrix;
+}
+
+table ImageMatchResult {
+  // The matches from this image to each of the training images which matched.
+  image_matches:[ImageMatch];
+  // The transformations for this image for each of the training images which
+  // matched.
+  // TODO(Brian): Include some kind of covariance information for these.
+  camera_poses:[CameraPose];
+
+  // The features for this image.
+  features:[Feature];
+}
+
+root_type ImageMatchResult;
diff --git a/y2020/vision/sift/sift_training.fbs b/y2020/vision/sift/sift_training.fbs
new file mode 100644
index 0000000..2af0233
--- /dev/null
+++ b/y2020/vision/sift/sift_training.fbs
@@ -0,0 +1,23 @@
+include "y2020/vision/sift/sift.fbs";
+
+namespace frc971.vision.sift;
+
+// Represents a single image we train against.
+table TrainingImage {
+  features:[Feature];
+
+  // Field coordinates of the target, represented as a transformation matrix
+  // from the target to the field. See CameraPose in :sift_fbs for details of
+  // the conventions of this.
+  field_to_target:TransformationMatrix;
+
+  // Coordinates of the target in the training image.
+  camera_to_target:TransformationMatrix;
+}
+
+// Represents the information used to match incoming images against.
+table TrainingData {
+  images:[TrainingImage];
+}
+
+root_type TrainingData;