blob: 85cca2129137ce10210886f2e278622e898dd40f [file] [log] [blame]
Brian Silverman1c0612e2019-01-26 17:26:08 -08001#ifndef Y2019_JEVOIS_STRUCTURES_H_
2#define Y2019_JEVOIS_STRUCTURES_H_
3
Brian Silverman1c0612e2019-01-26 17:26:08 -08004#include <array>
5#include <bitset>
6#include <chrono>
Tyler Chatowbf0609c2021-07-31 16:13:27 -07007#include <cstdint>
Brian Silverman1c0612e2019-01-26 17:26:08 -08008
9#include "Eigen/Dense"
Philipp Schrader790cb542023-07-05 21:06:52 -070010
Brian Silverman1c0612e2019-01-26 17:26:08 -080011#include "aos/containers/sized_array.h"
Brian Silvermana3688802019-02-16 19:31:26 -080012#include "aos/time/time.h"
Brian Silverman1c0612e2019-01-26 17:26:08 -080013
14namespace frc971 {
15namespace jevois {
16
17// The overall flow to get data to the roboRIO consists of:
18// 1. Camera captures a frame and grabs an absolute timestamp.
19// 2. Camera processes the frame.
20// 3. Camera grabs another absolute timestamp and subtracts to get a
21// camera_duration.
22// 4. Camera sends the frame via UART to the Teensy.
23// 5. Teensy grabs an absolute timestamp for the first character received.
24// 6. Teensy buffers at most one frame from each camera.
25// 7. roboRIO toggles the CS line.
26// 8. Teensy grabs an absolute timestamp for CS being asserted.
27// 9. Teensy pulls together up to three frames and adds the time each one
28// spent in its queue to the timestamps, and queues them in its SPI
29// peripheral. This all happens before the roboRIO has enough time to start
30// actually moving data.
31// 10. roboRIO transfers the frames, and sends back light/status commands.
32
33using camera_duration = std::chrono::duration<uint8_t, std::milli>;
34
35// This file declares the shared datastructures for the JeVois-based image
36// system.
37//
38// Note that floating-point numbers are represented with floats. This is because
39// a float has more bits than we need for anything, and the Teensy can't handle
40// doubles very quickly. It would probably be quick enough, but it's easier to
41// just use floats and not worry about it.
42
43struct Target {
Brian Silverman246cb222019-02-02 16:38:18 -080044 bool operator==(const Target &other) const {
45 if (other.distance != distance) {
46 return false;
47 }
48 if (other.height != height) {
49 return false;
50 }
51 if (other.heading != heading) {
52 return false;
53 }
54 if (other.skew != skew) {
55 return false;
56 }
57 return true;
58 }
Tyler Chatowbf0609c2021-07-31 16:13:27 -070059 bool operator!=(const Target &other) const { return !(*this == other); }
Brian Silverman246cb222019-02-02 16:38:18 -080060
Brian Silverman1c0612e2019-01-26 17:26:08 -080061 // Distance to the target in meters. Specifically, the distance from the
62 // center of the camera's image plane to the center of the target.
63 float distance;
64
James Kuszmaul81df16a2019-03-03 17:17:34 -080065 // Height of the target in meters. Specifically, the distance from the camera
Brian Silverman1c0612e2019-01-26 17:26:08 -080066 // to the center of the target.
67 float height;
68
69 // Heading of the center of the target in radians. Zero is straight out
70 // perpendicular to the camera's image plane. Images to the left (looking at a
71 // camera image) are at a positive angle.
72 float heading;
73
74 // The angle between the target and the camera's image plane. This is
75 // projected so both are assumed to be perpendicular to the floor. Parallel
76 // targets have a skew of zero. Targets rotated such that their left edge
77 // (looking at a camera image) is closer are at a positive angle.
78 float skew;
79};
80
81// The information extracted from a single camera frame.
82//
83// This is all the information sent from each camera to the Teensy.
Brian Silvermanc41fb862019-03-02 21:14:46 -080084struct CameraFrame {
85 bool operator==(const CameraFrame &other) const {
Brian Silverman246cb222019-02-02 16:38:18 -080086 if (other.targets != targets) {
87 return false;
88 }
89 if (other.age != age) {
90 return false;
91 }
92 return true;
93 }
Tyler Chatowbf0609c2021-07-31 16:13:27 -070094 bool operator!=(const CameraFrame &other) const { return !(*this == other); }
Brian Silverman246cb222019-02-02 16:38:18 -080095
Brian Silverman1c0612e2019-01-26 17:26:08 -080096 // The top most interesting targets found in this frame.
97 aos::SizedArray<Target, 3> targets;
98
99 // How long ago from the current time this frame was captured.
100 camera_duration age;
101};
102
Brian Silvermanc41fb862019-03-02 21:14:46 -0800103// The information extracted from a single camera frame, from a given camera.
104struct RoborioFrame {
105 bool operator==(const RoborioFrame &other) const {
106 if (other.targets != targets) {
107 return false;
108 }
109 if (other.age != age) {
110 return false;
111 }
112 if (other.camera_index != camera_index) {
113 return false;
114 }
115 return true;
116 }
Tyler Chatowbf0609c2021-07-31 16:13:27 -0700117 bool operator!=(const RoborioFrame &other) const { return !(*this == other); }
Brian Silvermanc41fb862019-03-02 21:14:46 -0800118
119 // The top most interesting targets found in this frame.
120 aos::SizedArray<Target, 3> targets;
121
122 // How long ago from the current time this frame was captured.
123 camera_duration age;
124 // Which camera this is from (which position on the robot, not a serial
125 // number).
126 int camera_index;
127};
128
Brian Silvermane9924fd2019-03-02 15:20:42 -0800129enum class CameraCommand : char {
130 // Stay in normal mode.
131 kNormal,
132 // Go to camera passthrough mode.
133 kCameraPassthrough,
134 // Go to being a useful USB device.
135 kUsb,
Brian Silvermanbac77542019-03-03 13:57:00 -0800136 // Send As, which triggers the bootstrap script to drop directly into USB
137 // mode.
138 kAs,
Austin Schuh4e2629d2019-03-28 14:44:37 -0700139 // Log camera images
140 kLog,
Brian Silvermane9924fd2019-03-02 15:20:42 -0800141};
142
Brian Silverman1c0612e2019-01-26 17:26:08 -0800143// This is all the information sent from the Teensy to each camera.
144struct CameraCalibration {
Brian Silverman246cb222019-02-02 16:38:18 -0800145 bool operator==(const CameraCalibration &other) const {
146 if (other.calibration != calibration) {
147 return false;
148 }
Brian Silverman2eb89762019-02-17 15:16:37 -0800149 if (other.teensy_now != teensy_now) {
150 return false;
151 }
152 if (other.realtime_now != realtime_now) {
153 return false;
154 }
155 if (other.camera_command != camera_command) {
156 return false;
157 }
Brian Silverman246cb222019-02-02 16:38:18 -0800158 return true;
159 }
160 bool operator!=(const CameraCalibration &other) const {
161 return !(*this == other);
162 }
163
Brian Silverman1c0612e2019-01-26 17:26:08 -0800164 // The calibration matrix. This defines where the camera is pointing.
165 //
Brian Silverman246cb222019-02-02 16:38:18 -0800166 // TODO(Parker): What are the details on how this is defined?
Alex Perry3bf1bee2019-02-23 20:01:15 -0800167 // [0][0]: mount_angle
168 // [0][1]: focal_length
169 // [0][2]: barrel_mount
Brian Silverman1c0612e2019-01-26 17:26:08 -0800170 Eigen::Matrix<float, 3, 4> calibration;
Brian Silvermana3688802019-02-16 19:31:26 -0800171
172 // A local timestamp from the Teensy. This starts at 0 when the Teensy is
173 // powered on.
174 aos::monotonic_clock::time_point teensy_now;
175
176 // A realtime timestamp from the roboRIO. This will be min_time if the roboRIO
177 // has never sent anything.
178 aos::realtime_clock::time_point realtime_now;
179
180 // What mode the camera should transition into.
181 CameraCommand camera_command;
Brian Silverman1c0612e2019-01-26 17:26:08 -0800182};
183
184// This is all the information the Teensy sends to the RoboRIO.
185struct TeensyToRoborio {
Brian Silverman246cb222019-02-02 16:38:18 -0800186 bool operator==(const TeensyToRoborio &other) const {
187 if (other.frames != frames) {
188 return false;
189 }
190 return true;
191 }
192 bool operator!=(const TeensyToRoborio &other) const {
193 return !(*this == other);
194 }
195
Brian Silverman1c0612e2019-01-26 17:26:08 -0800196 // The newest frames received from up to three cameras. These will be the
197 // three earliest-received of all buffered frames.
Brian Silvermanc41fb862019-03-02 21:14:46 -0800198 aos::SizedArray<RoborioFrame, 3> frames;
Brian Silverman1c0612e2019-01-26 17:26:08 -0800199};
200
201// This is all the information the RoboRIO sends to the Teensy.
202struct RoborioToTeensy {
Brian Silverman246cb222019-02-02 16:38:18 -0800203 bool operator==(const RoborioToTeensy &other) const {
204 if (other.beacon_brightness != beacon_brightness) {
205 return false;
206 }
207 if (other.light_rings != light_rings) {
208 return false;
209 }
Brian Silvermanc41fb862019-03-02 21:14:46 -0800210 if (other.realtime_now != realtime_now) {
211 return false;
212 }
213 if (other.camera_command != camera_command) {
214 return false;
215 }
Brian Silverman246cb222019-02-02 16:38:18 -0800216 return true;
217 }
218 bool operator!=(const RoborioToTeensy &other) const {
219 return !(*this == other);
220 }
221
Brian Silverman1c0612e2019-01-26 17:26:08 -0800222 // Brightnesses for each of the beacon light channels. 0 is off, 255 is fully
223 // on.
224 std::array<uint8_t, 3> beacon_brightness;
225
226 // Whether the light ring for each camera should be on.
227 std::bitset<5> light_rings;
Brian Silvermana3688802019-02-16 19:31:26 -0800228
229 // The current time.
230 aos::realtime_clock::time_point realtime_now;
Brian Silvermane9924fd2019-03-02 15:20:42 -0800231
232 // A command to send to all the cameras.
233 CameraCommand camera_command;
Brian Silverman1c0612e2019-01-26 17:26:08 -0800234};
235
236} // namespace jevois
237} // namespace frc971
238
239#endif // Y2019_JEVOIS_STRUCTURES_H_