Brian Silverman | fac9b87 | 2020-02-05 20:07:38 -0800 | [diff] [blame] | 1 | namespace frc971.vision.sift; |
| 2 | |
Brian Silverman | 4d4a70d | 2020-02-17 13:03:19 -0800 | [diff] [blame] | 3 | // Represents the location of a keypoint in field coordinates. |
| 4 | struct KeypointFieldLocation { |
Austin Schuh | d7851b0 | 2020-11-14 13:46:27 -0800 | [diff] [blame] | 5 | x:float (id: 0); |
| 6 | y:float (id: 1); |
| 7 | z:float (id: 2); |
Brian Silverman | 4d4a70d | 2020-02-17 13:03:19 -0800 | [diff] [blame] | 8 | } |
| 9 | |
Brian Silverman | fac9b87 | 2020-02-05 20:07:38 -0800 | [diff] [blame] | 10 | // Represents a single feature extracted from an image. |
| 11 | table Feature { |
Brian Silverman | f64b9bd | 2020-02-29 12:51:33 -0800 | [diff] [blame] | 12 | // Contains the descriptor data. OpenCV likes to represent them as floats, but |
| 13 | // they're really ubytes. |
Brian Silverman | fac9b87 | 2020-02-05 20:07:38 -0800 | [diff] [blame] | 14 | // |
| 15 | // TODO(Brian): These are scaled to be convertible to chars. Should we do |
| 16 | // that to minimize storage space? Or maybe int16? |
| 17 | // |
| 18 | // The size of this depends on the parameters. It is width*width*hist_bins. |
| 19 | // Currently we have width=4 and hist_bins=8, which results in a size of |
| 20 | // 4*4*8=128. |
Austin Schuh | d7851b0 | 2020-11-14 13:46:27 -0800 | [diff] [blame] | 21 | descriptor:[ubyte] (id: 0); |
Brian Silverman | fac9b87 | 2020-02-05 20:07:38 -0800 | [diff] [blame] | 22 | |
| 23 | // Location of the keypoint. |
Austin Schuh | d7851b0 | 2020-11-14 13:46:27 -0800 | [diff] [blame] | 24 | x:float (id: 1); |
| 25 | y:float (id: 2); |
Brian Silverman | fac9b87 | 2020-02-05 20:07:38 -0800 | [diff] [blame] | 26 | |
| 27 | // Size of the keypoint neighborhood. |
Austin Schuh | d7851b0 | 2020-11-14 13:46:27 -0800 | [diff] [blame] | 28 | size:float (id: 3); |
Brian Silverman | fac9b87 | 2020-02-05 20:07:38 -0800 | [diff] [blame] | 29 | |
| 30 | // Angle of the keypoint. |
| 31 | // This is in [0,360) clockwise. |
Austin Schuh | d7851b0 | 2020-11-14 13:46:27 -0800 | [diff] [blame] | 32 | angle:float (id: 4); |
Brian Silverman | fac9b87 | 2020-02-05 20:07:38 -0800 | [diff] [blame] | 33 | |
| 34 | // How good of a keypoint this is. |
Austin Schuh | d7851b0 | 2020-11-14 13:46:27 -0800 | [diff] [blame] | 35 | response:float (id: 5); |
Brian Silverman | fac9b87 | 2020-02-05 20:07:38 -0800 | [diff] [blame] | 36 | |
| 37 | // Which octave this keypoint is from. |
Austin Schuh | d7851b0 | 2020-11-14 13:46:27 -0800 | [diff] [blame] | 38 | octave:int (id: 6); |
Brian Silverman | 4d4a70d | 2020-02-17 13:03:19 -0800 | [diff] [blame] | 39 | |
| 40 | // Where this feature's keypoint is on the field. This will only be filled out |
| 41 | // for training features, not ones extracted from query images. |
Austin Schuh | d7851b0 | 2020-11-14 13:46:27 -0800 | [diff] [blame] | 42 | field_location:KeypointFieldLocation (id: 7); |
Brian Silverman | fac9b87 | 2020-02-05 20:07:38 -0800 | [diff] [blame] | 43 | } |
| 44 | |
| 45 | // Represents a single match between a training image and a query image. |
Brian Silverman | 4d4a70d | 2020-02-17 13:03:19 -0800 | [diff] [blame] | 46 | struct Match { |
Brian Silverman | fac9b87 | 2020-02-05 20:07:38 -0800 | [diff] [blame] | 47 | // The index of the feature for the query image. |
Austin Schuh | d7851b0 | 2020-11-14 13:46:27 -0800 | [diff] [blame] | 48 | query_feature:int (id: 0); |
Brian Silverman | fac9b87 | 2020-02-05 20:07:38 -0800 | [diff] [blame] | 49 | // The index of the feature for the training image. |
Austin Schuh | d7851b0 | 2020-11-14 13:46:27 -0800 | [diff] [blame] | 50 | train_feature:int (id: 1); |
Brian Silverman | 4d4a70d | 2020-02-17 13:03:19 -0800 | [diff] [blame] | 51 | // How "good" the match is. |
Austin Schuh | d7851b0 | 2020-11-14 13:46:27 -0800 | [diff] [blame] | 52 | distance:float (id: 2); |
Brian Silverman | fac9b87 | 2020-02-05 20:07:38 -0800 | [diff] [blame] | 53 | } |
| 54 | |
| 55 | // Represents all the matches between a single training image and a query |
| 56 | // image. |
| 57 | table ImageMatch { |
Austin Schuh | d7851b0 | 2020-11-14 13:46:27 -0800 | [diff] [blame] | 58 | matches:[Match] (id: 0); |
Brian Silverman | fac9b87 | 2020-02-05 20:07:38 -0800 | [diff] [blame] | 59 | // The index of the training image within all the training images. |
Austin Schuh | d7851b0 | 2020-11-14 13:46:27 -0800 | [diff] [blame] | 60 | train_image:int (id: 1); |
Brian Silverman | fac9b87 | 2020-02-05 20:07:38 -0800 | [diff] [blame] | 61 | } |
| 62 | |
| 63 | table TransformationMatrix { |
Jim Ostrowski | ad5d8a7 | 2020-02-28 00:15:26 -0800 | [diff] [blame] | 64 | // The matrix data for a row-major 4x4 homogeneous transformation matrix. |
| 65 | // This implies the bottom row is (0, 0, 0, 1). |
Austin Schuh | d7851b0 | 2020-11-14 13:46:27 -0800 | [diff] [blame] | 66 | data:[float] (id: 0); |
Brian Silverman | fac9b87 | 2020-02-05 20:07:38 -0800 | [diff] [blame] | 67 | } |
| 68 | |
Brian Silverman | 4d4a70d | 2020-02-17 13:03:19 -0800 | [diff] [blame] | 69 | // Calibration information for a given camera on a given robot. |
| 70 | table CameraCalibration { |
| 71 | // The name of the camera node which this calibration data applies to. |
Austin Schuh | d7851b0 | 2020-11-14 13:46:27 -0800 | [diff] [blame] | 72 | node_name:string (id: 0); |
Brian Silverman | 4d4a70d | 2020-02-17 13:03:19 -0800 | [diff] [blame] | 73 | // The team number of the robot which this calibration data applies to. |
Austin Schuh | d7851b0 | 2020-11-14 13:46:27 -0800 | [diff] [blame] | 74 | team_number:int (id: 1); |
Brian Silverman | 4d4a70d | 2020-02-17 13:03:19 -0800 | [diff] [blame] | 75 | |
| 76 | // Intrinsics for the camera. |
| 77 | // |
| 78 | // This is the standard OpenCV intrinsics matrix in row major order (3x3). |
Austin Schuh | d7851b0 | 2020-11-14 13:46:27 -0800 | [diff] [blame] | 79 | intrinsics:[float] (id: 2); |
Brian Silverman | 4d4a70d | 2020-02-17 13:03:19 -0800 | [diff] [blame] | 80 | |
| 81 | // Fixed extrinsics for the camera. This transforms from camera coordinates to |
| 82 | // robot coordinates. For example: multiplying (0, 0, 0, 1) by this results in |
| 83 | // the position of the camera aperature in robot coordinates. |
Austin Schuh | d7851b0 | 2020-11-14 13:46:27 -0800 | [diff] [blame] | 84 | fixed_extrinsics:TransformationMatrix (id: 3); |
Brian Silverman | 4d4a70d | 2020-02-17 13:03:19 -0800 | [diff] [blame] | 85 | |
| 86 | // Extrinsics for a camera on a turret. This will only be filled out for |
| 87 | // applicable cameras. For turret-mounted cameras, fixed_extrinsics defines |
| 88 | // a position for the center of rotation of the turret, and this field defines |
| 89 | // a position for the camera on the turret. |
| 90 | // |
| 91 | // The combination of the two transformations is underdefined, so nothing can |
| 92 | // distinguish between the two parts of the final extrinsics for a given |
| 93 | // turret position. |
| 94 | // |
| 95 | // To get the final extrinsics for a camera using this transformation, |
| 96 | // multiply (in order): |
| 97 | // fixed_extrinsics |
| 98 | // rotation around the Z axis by the turret angle |
| 99 | // turret_extrinsics |
Austin Schuh | d7851b0 | 2020-11-14 13:46:27 -0800 | [diff] [blame] | 100 | turret_extrinsics:TransformationMatrix (id: 4); |
Jim Ostrowski | ad5d8a7 | 2020-02-28 00:15:26 -0800 | [diff] [blame] | 101 | |
| 102 | // This is the standard OpenCV 5 parameter distortion coefficients |
Austin Schuh | d7851b0 | 2020-11-14 13:46:27 -0800 | [diff] [blame] | 103 | dist_coeffs:[float] (id: 5); |
Austin Schuh | c1f118e | 2020-04-11 15:50:08 -0700 | [diff] [blame] | 104 | |
| 105 | // Timestamp for when the calibration was taken on the realtime clock. |
Austin Schuh | d7851b0 | 2020-11-14 13:46:27 -0800 | [diff] [blame] | 106 | calibration_timestamp:int64 (id: 6); |
Brian Silverman | 4d4a70d | 2020-02-17 13:03:19 -0800 | [diff] [blame] | 107 | } |
| 108 | |
| 109 | // Contains the information the EKF wants from an image matched against a single |
| 110 | // training image. |
Brian Silverman | fac9b87 | 2020-02-05 20:07:38 -0800 | [diff] [blame] | 111 | // |
Jim Ostrowski | e426426 | 2020-02-29 00:27:24 -0800 | [diff] [blame] | 112 | // This is represented as a transformation from the camera to the target |
| 113 | // (camera_to_target) and a transformatoin from the field to the target |
| 114 | // (field_to_target). |
| 115 | // |
| 116 | // We also send the map from the field to the camera, which can be computed |
| 117 | // with the first two, to make it easier to display. |
Brian Silverman | fac9b87 | 2020-02-05 20:07:38 -0800 | [diff] [blame] | 118 | table CameraPose { |
Jim Ostrowski | e426426 | 2020-02-29 00:27:24 -0800 | [diff] [blame] | 119 | // Transformation matrix from the camera to the target. |
Brian Silverman | 4d4a70d | 2020-02-17 13:03:19 -0800 | [diff] [blame] | 120 | // (0, 0, 0) is the aperture of the camera (we pretend it's an ideal pinhole |
| 121 | // camera). Positive Z is out of the camera. Positive X and Y are right |
| 122 | // handed, but which way they face depends on the camera extrinsics. |
Austin Schuh | d7851b0 | 2020-11-14 13:46:27 -0800 | [diff] [blame] | 123 | camera_to_target:TransformationMatrix (id: 0); |
Brian Silverman | fac9b87 | 2020-02-05 20:07:38 -0800 | [diff] [blame] | 124 | |
| 125 | // Field coordinates of the target, represented as a transformation matrix |
Jim Ostrowski | e426426 | 2020-02-29 00:27:24 -0800 | [diff] [blame] | 126 | // from the field to the target. |
Brian Silverman | fac9b87 | 2020-02-05 20:07:38 -0800 | [diff] [blame] | 127 | // (0, 0, 0) is the center of the field, on the level of most of the field |
| 128 | // (not the region under the truss). Positive X is towards the red alliance's |
| 129 | // PLAYER STATION. Positive Z is up. The coordinate system is right-handed. |
| 130 | // |
| 131 | // Note that the red PLAYER STATION is where the red drive teams are. This is |
| 132 | // often where the blue robots are shooting towards. |
| 133 | // |
| 134 | // The value here will be selected from a small, static set of targets we |
| 135 | // train images on. |
Austin Schuh | d7851b0 | 2020-11-14 13:46:27 -0800 | [diff] [blame] | 136 | field_to_target:TransformationMatrix (id: 1); |
Jim Ostrowski | e426426 | 2020-02-29 00:27:24 -0800 | [diff] [blame] | 137 | |
| 138 | // The pose of the camera in the field coordinate frame |
Austin Schuh | d7851b0 | 2020-11-14 13:46:27 -0800 | [diff] [blame] | 139 | field_to_camera:TransformationMatrix (id: 2); |
Jim Ostrowski | 18f7fbf | 2020-03-01 13:53:22 -0800 | [diff] [blame] | 140 | |
| 141 | // 2D image coordinate representing target location on the matched image |
Austin Schuh | d7851b0 | 2020-11-14 13:46:27 -0800 | [diff] [blame] | 142 | query_target_point_x:float (id: 3); |
| 143 | query_target_point_y:float (id: 4); |
Jim Ostrowski | 18f7fbf | 2020-03-01 13:53:22 -0800 | [diff] [blame] | 144 | // Perceived radius of target circle |
Austin Schuh | d7851b0 | 2020-11-14 13:46:27 -0800 | [diff] [blame] | 145 | query_target_point_radius:float (id: 5); |
James Kuszmaul | 9c65835 | 2021-10-22 19:37:58 -0700 | [diff] [blame] | 146 | // Number of features used in this match. |
| 147 | homography_feature_count:int (id: 6); |
| 148 | // Training image used for this pose. |
| 149 | training_image_index:int (id: 7); |
Brian Silverman | fac9b87 | 2020-02-05 20:07:38 -0800 | [diff] [blame] | 150 | } |
| 151 | |
| 152 | table ImageMatchResult { |
| 153 | // The matches from this image to each of the training images which matched. |
Brian Silverman | 4d4a70d | 2020-02-17 13:03:19 -0800 | [diff] [blame] | 154 | // Each member is against the same captured image. |
Austin Schuh | d7851b0 | 2020-11-14 13:46:27 -0800 | [diff] [blame] | 155 | image_matches:[ImageMatch] (id: 0); |
Jim Ostrowski | ad5d8a7 | 2020-02-28 00:15:26 -0800 | [diff] [blame] | 156 | |
Brian Silverman | fac9b87 | 2020-02-05 20:07:38 -0800 | [diff] [blame] | 157 | // The transformations for this image for each of the training images which |
| 158 | // matched. |
| 159 | // TODO(Brian): Include some kind of covariance information for these. |
Austin Schuh | d7851b0 | 2020-11-14 13:46:27 -0800 | [diff] [blame] | 160 | camera_poses:[CameraPose] (id: 1); |
Brian Silverman | fac9b87 | 2020-02-05 20:07:38 -0800 | [diff] [blame] | 161 | |
| 162 | // The features for this image. |
Austin Schuh | d7851b0 | 2020-11-14 13:46:27 -0800 | [diff] [blame] | 163 | features:[Feature] (id: 2); |
Brian Silverman | 967e5df | 2020-02-09 16:43:34 -0800 | [diff] [blame] | 164 | |
| 165 | // Timestamp when the frame was captured. |
Austin Schuh | d7851b0 | 2020-11-14 13:46:27 -0800 | [diff] [blame] | 166 | image_monotonic_timestamp_ns:long (id: 3); |
Brian Silverman | 4d4a70d | 2020-02-17 13:03:19 -0800 | [diff] [blame] | 167 | |
| 168 | // Information about the camera which took this image. |
Austin Schuh | d7851b0 | 2020-11-14 13:46:27 -0800 | [diff] [blame] | 169 | camera_calibration:CameraCalibration (id: 4); |
milind | 1f1dca3 | 2021-07-03 13:50:07 -0700 | [diff] [blame^] | 170 | |
| 171 | // Total number of match result send failures. |
| 172 | send_failures:uint64 (id: 5); |
Brian Silverman | fac9b87 | 2020-02-05 20:07:38 -0800 | [diff] [blame] | 173 | } |
| 174 | |
| 175 | root_type ImageMatchResult; |