blob: fcf1ebe3992cb4fefdfb701a7b3e58f59c5ed516 [file] [log] [blame]
Brian Silverman1c0612e2019-01-26 17:26:08 -08001#ifndef Y2019_JEVOIS_STRUCTURES_H_
2#define Y2019_JEVOIS_STRUCTURES_H_
3
4#include <stdint.h>
5
6#include <array>
7#include <bitset>
8#include <chrono>
9
10#include "Eigen/Dense"
11
12#include "aos/containers/sized_array.h"
Brian Silvermana3688802019-02-16 19:31:26 -080013#include "aos/time/time.h"
Brian Silvermanfdfb3132019-02-24 15:27:27 -080014#include "third_party/GSL/include/gsl/gsl"
Brian Silverman1c0612e2019-01-26 17:26:08 -080015
16namespace frc971 {
17namespace jevois {
18
19// The overall flow to get data to the roboRIO consists of:
20// 1. Camera captures a frame and grabs an absolute timestamp.
21// 2. Camera processes the frame.
22// 3. Camera grabs another absolute timestamp and subtracts to get a
23// camera_duration.
24// 4. Camera sends the frame via UART to the Teensy.
25// 5. Teensy grabs an absolute timestamp for the first character received.
26// 6. Teensy buffers at most one frame from each camera.
27// 7. roboRIO toggles the CS line.
28// 8. Teensy grabs an absolute timestamp for CS being asserted.
29// 9. Teensy pulls together up to three frames and adds the time each one
30// spent in its queue to the timestamps, and queues them in its SPI
31// peripheral. This all happens before the roboRIO has enough time to start
32// actually moving data.
33// 10. roboRIO transfers the frames, and sends back light/status commands.
34
35using camera_duration = std::chrono::duration<uint8_t, std::milli>;
36
37// This file declares the shared datastructures for the JeVois-based image
38// system.
39//
40// Note that floating-point numbers are represented with floats. This is because
41// a float has more bits than we need for anything, and the Teensy can't handle
42// doubles very quickly. It would probably be quick enough, but it's easier to
43// just use floats and not worry about it.
44
45struct Target {
Brian Silverman246cb222019-02-02 16:38:18 -080046 bool operator==(const Target &other) const {
47 if (other.distance != distance) {
48 return false;
49 }
50 if (other.height != height) {
51 return false;
52 }
53 if (other.heading != heading) {
54 return false;
55 }
56 if (other.skew != skew) {
57 return false;
58 }
59 return true;
60 }
61 bool operator!=(const Target &other) const {
62 return !(*this == other);
63 }
64
Brian Silverman1c0612e2019-01-26 17:26:08 -080065 // Distance to the target in meters. Specifically, the distance from the
66 // center of the camera's image plane to the center of the target.
67 float distance;
68
James Kuszmaul81df16a2019-03-03 17:17:34 -080069 // Height of the target in meters. Specifically, the distance from the camera
Brian Silverman1c0612e2019-01-26 17:26:08 -080070 // to the center of the target.
71 float height;
72
73 // Heading of the center of the target in radians. Zero is straight out
74 // perpendicular to the camera's image plane. Images to the left (looking at a
75 // camera image) are at a positive angle.
76 float heading;
77
78 // The angle between the target and the camera's image plane. This is
79 // projected so both are assumed to be perpendicular to the floor. Parallel
80 // targets have a skew of zero. Targets rotated such that their left edge
81 // (looking at a camera image) is closer are at a positive angle.
82 float skew;
83};
84
85// The information extracted from a single camera frame.
86//
87// This is all the information sent from each camera to the Teensy.
Brian Silvermanc41fb862019-03-02 21:14:46 -080088struct CameraFrame {
89 bool operator==(const CameraFrame &other) const {
Brian Silverman246cb222019-02-02 16:38:18 -080090 if (other.targets != targets) {
91 return false;
92 }
93 if (other.age != age) {
94 return false;
95 }
96 return true;
97 }
Brian Silvermanc41fb862019-03-02 21:14:46 -080098 bool operator!=(const CameraFrame &other) const {
Brian Silverman246cb222019-02-02 16:38:18 -080099 return !(*this == other);
100 }
101
Brian Silverman1c0612e2019-01-26 17:26:08 -0800102 // The top most interesting targets found in this frame.
103 aos::SizedArray<Target, 3> targets;
104
105 // How long ago from the current time this frame was captured.
106 camera_duration age;
107};
108
Brian Silvermanc41fb862019-03-02 21:14:46 -0800109// The information extracted from a single camera frame, from a given camera.
110struct RoborioFrame {
111 bool operator==(const RoborioFrame &other) const {
112 if (other.targets != targets) {
113 return false;
114 }
115 if (other.age != age) {
116 return false;
117 }
118 if (other.camera_index != camera_index) {
119 return false;
120 }
121 return true;
122 }
123 bool operator!=(const RoborioFrame &other) const {
124 return !(*this == other);
125 }
126
127 // The top most interesting targets found in this frame.
128 aos::SizedArray<Target, 3> targets;
129
130 // How long ago from the current time this frame was captured.
131 camera_duration age;
132 // Which camera this is from (which position on the robot, not a serial
133 // number).
134 int camera_index;
135};
136
Brian Silvermane9924fd2019-03-02 15:20:42 -0800137enum class CameraCommand : char {
138 // Stay in normal mode.
139 kNormal,
140 // Go to camera passthrough mode.
141 kCameraPassthrough,
142 // Go to being a useful USB device.
143 kUsb,
Brian Silvermanbac77542019-03-03 13:57:00 -0800144 // Send As, which triggers the bootstrap script to drop directly into USB
145 // mode.
146 kAs,
Austin Schuh4e2629d2019-03-28 14:44:37 -0700147 // Log camera images
148 kLog,
Brian Silvermane9924fd2019-03-02 15:20:42 -0800149};
150
Brian Silverman1c0612e2019-01-26 17:26:08 -0800151// This is all the information sent from the Teensy to each camera.
152struct CameraCalibration {
Brian Silverman246cb222019-02-02 16:38:18 -0800153 bool operator==(const CameraCalibration &other) const {
154 if (other.calibration != calibration) {
155 return false;
156 }
Brian Silverman2eb89762019-02-17 15:16:37 -0800157 if (other.teensy_now != teensy_now) {
158 return false;
159 }
160 if (other.realtime_now != realtime_now) {
161 return false;
162 }
163 if (other.camera_command != camera_command) {
164 return false;
165 }
Brian Silverman246cb222019-02-02 16:38:18 -0800166 return true;
167 }
168 bool operator!=(const CameraCalibration &other) const {
169 return !(*this == other);
170 }
171
Brian Silverman1c0612e2019-01-26 17:26:08 -0800172 // The calibration matrix. This defines where the camera is pointing.
173 //
Brian Silverman246cb222019-02-02 16:38:18 -0800174 // TODO(Parker): What are the details on how this is defined?
Alex Perry3bf1bee2019-02-23 20:01:15 -0800175 // [0][0]: mount_angle
176 // [0][1]: focal_length
177 // [0][2]: barrel_mount
Brian Silverman1c0612e2019-01-26 17:26:08 -0800178 Eigen::Matrix<float, 3, 4> calibration;
Brian Silvermana3688802019-02-16 19:31:26 -0800179
180 // A local timestamp from the Teensy. This starts at 0 when the Teensy is
181 // powered on.
182 aos::monotonic_clock::time_point teensy_now;
183
184 // A realtime timestamp from the roboRIO. This will be min_time if the roboRIO
185 // has never sent anything.
186 aos::realtime_clock::time_point realtime_now;
187
188 // What mode the camera should transition into.
189 CameraCommand camera_command;
Brian Silverman1c0612e2019-01-26 17:26:08 -0800190};
191
192// This is all the information the Teensy sends to the RoboRIO.
193struct TeensyToRoborio {
Brian Silverman246cb222019-02-02 16:38:18 -0800194 bool operator==(const TeensyToRoborio &other) const {
195 if (other.frames != frames) {
196 return false;
197 }
198 return true;
199 }
200 bool operator!=(const TeensyToRoborio &other) const {
201 return !(*this == other);
202 }
203
Brian Silverman1c0612e2019-01-26 17:26:08 -0800204 // The newest frames received from up to three cameras. These will be the
205 // three earliest-received of all buffered frames.
Brian Silvermanc41fb862019-03-02 21:14:46 -0800206 aos::SizedArray<RoborioFrame, 3> frames;
Brian Silverman1c0612e2019-01-26 17:26:08 -0800207};
208
209// This is all the information the RoboRIO sends to the Teensy.
210struct RoborioToTeensy {
Brian Silverman246cb222019-02-02 16:38:18 -0800211 bool operator==(const RoborioToTeensy &other) const {
212 if (other.beacon_brightness != beacon_brightness) {
213 return false;
214 }
215 if (other.light_rings != light_rings) {
216 return false;
217 }
Brian Silvermanc41fb862019-03-02 21:14:46 -0800218 if (other.realtime_now != realtime_now) {
219 return false;
220 }
221 if (other.camera_command != camera_command) {
222 return false;
223 }
Brian Silverman246cb222019-02-02 16:38:18 -0800224 return true;
225 }
226 bool operator!=(const RoborioToTeensy &other) const {
227 return !(*this == other);
228 }
229
Brian Silverman1c0612e2019-01-26 17:26:08 -0800230 // Brightnesses for each of the beacon light channels. 0 is off, 255 is fully
231 // on.
232 std::array<uint8_t, 3> beacon_brightness;
233
234 // Whether the light ring for each camera should be on.
235 std::bitset<5> light_rings;
Brian Silvermana3688802019-02-16 19:31:26 -0800236
237 // The current time.
238 aos::realtime_clock::time_point realtime_now;
Brian Silvermane9924fd2019-03-02 15:20:42 -0800239
240 // A command to send to all the cameras.
241 CameraCommand camera_command;
Brian Silverman1c0612e2019-01-26 17:26:08 -0800242};
243
244} // namespace jevois
245} // namespace frc971
246
247#endif // Y2019_JEVOIS_STRUCTURES_H_