blob: a8d284361375d7e36692238804c0ae8baa175ac3 [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
Stephan Pleinesd99b1ee2024-02-02 20:56:44 -080014namespace frc971::jevois {
Brian Silverman1c0612e2019-01-26 17:26:08 -080015
16// The overall flow to get data to the roboRIO consists of:
17// 1. Camera captures a frame and grabs an absolute timestamp.
18// 2. Camera processes the frame.
19// 3. Camera grabs another absolute timestamp and subtracts to get a
20// camera_duration.
21// 4. Camera sends the frame via UART to the Teensy.
22// 5. Teensy grabs an absolute timestamp for the first character received.
23// 6. Teensy buffers at most one frame from each camera.
24// 7. roboRIO toggles the CS line.
25// 8. Teensy grabs an absolute timestamp for CS being asserted.
26// 9. Teensy pulls together up to three frames and adds the time each one
27// spent in its queue to the timestamps, and queues them in its SPI
28// peripheral. This all happens before the roboRIO has enough time to start
29// actually moving data.
30// 10. roboRIO transfers the frames, and sends back light/status commands.
31
32using camera_duration = std::chrono::duration<uint8_t, std::milli>;
33
34// This file declares the shared datastructures for the JeVois-based image
35// system.
36//
37// Note that floating-point numbers are represented with floats. This is because
38// a float has more bits than we need for anything, and the Teensy can't handle
39// doubles very quickly. It would probably be quick enough, but it's easier to
40// just use floats and not worry about it.
41
42struct Target {
Brian Silverman246cb222019-02-02 16:38:18 -080043 bool operator==(const Target &other) const {
44 if (other.distance != distance) {
45 return false;
46 }
47 if (other.height != height) {
48 return false;
49 }
50 if (other.heading != heading) {
51 return false;
52 }
53 if (other.skew != skew) {
54 return false;
55 }
56 return true;
57 }
Tyler Chatowbf0609c2021-07-31 16:13:27 -070058 bool operator!=(const Target &other) const { return !(*this == other); }
Brian Silverman246cb222019-02-02 16:38:18 -080059
Brian Silverman1c0612e2019-01-26 17:26:08 -080060 // Distance to the target in meters. Specifically, the distance from the
61 // center of the camera's image plane to the center of the target.
62 float distance;
63
James Kuszmaul81df16a2019-03-03 17:17:34 -080064 // Height of the target in meters. Specifically, the distance from the camera
Brian Silverman1c0612e2019-01-26 17:26:08 -080065 // to the center of the target.
66 float height;
67
68 // Heading of the center of the target in radians. Zero is straight out
69 // perpendicular to the camera's image plane. Images to the left (looking at a
70 // camera image) are at a positive angle.
71 float heading;
72
73 // The angle between the target and the camera's image plane. This is
74 // projected so both are assumed to be perpendicular to the floor. Parallel
75 // targets have a skew of zero. Targets rotated such that their left edge
76 // (looking at a camera image) is closer are at a positive angle.
77 float skew;
78};
79
80// The information extracted from a single camera frame.
81//
82// This is all the information sent from each camera to the Teensy.
Brian Silvermanc41fb862019-03-02 21:14:46 -080083struct CameraFrame {
84 bool operator==(const CameraFrame &other) const {
Brian Silverman246cb222019-02-02 16:38:18 -080085 if (other.targets != targets) {
86 return false;
87 }
88 if (other.age != age) {
89 return false;
90 }
91 return true;
92 }
Tyler Chatowbf0609c2021-07-31 16:13:27 -070093 bool operator!=(const CameraFrame &other) const { return !(*this == other); }
Brian Silverman246cb222019-02-02 16:38:18 -080094
Brian Silverman1c0612e2019-01-26 17:26:08 -080095 // The top most interesting targets found in this frame.
96 aos::SizedArray<Target, 3> targets;
97
98 // How long ago from the current time this frame was captured.
99 camera_duration age;
100};
101
Brian Silvermanc41fb862019-03-02 21:14:46 -0800102// The information extracted from a single camera frame, from a given camera.
103struct RoborioFrame {
104 bool operator==(const RoborioFrame &other) const {
105 if (other.targets != targets) {
106 return false;
107 }
108 if (other.age != age) {
109 return false;
110 }
111 if (other.camera_index != camera_index) {
112 return false;
113 }
114 return true;
115 }
Tyler Chatowbf0609c2021-07-31 16:13:27 -0700116 bool operator!=(const RoborioFrame &other) const { return !(*this == other); }
Brian Silvermanc41fb862019-03-02 21:14:46 -0800117
118 // The top most interesting targets found in this frame.
119 aos::SizedArray<Target, 3> targets;
120
121 // How long ago from the current time this frame was captured.
122 camera_duration age;
123 // Which camera this is from (which position on the robot, not a serial
124 // number).
125 int camera_index;
126};
127
Brian Silvermane9924fd2019-03-02 15:20:42 -0800128enum class CameraCommand : char {
129 // Stay in normal mode.
130 kNormal,
131 // Go to camera passthrough mode.
132 kCameraPassthrough,
133 // Go to being a useful USB device.
134 kUsb,
Brian Silvermanbac77542019-03-03 13:57:00 -0800135 // Send As, which triggers the bootstrap script to drop directly into USB
136 // mode.
137 kAs,
Austin Schuh4e2629d2019-03-28 14:44:37 -0700138 // Log camera images
139 kLog,
Brian Silvermane9924fd2019-03-02 15:20:42 -0800140};
141
Brian Silverman1c0612e2019-01-26 17:26:08 -0800142// This is all the information sent from the Teensy to each camera.
143struct CameraCalibration {
Brian Silverman246cb222019-02-02 16:38:18 -0800144 bool operator==(const CameraCalibration &other) const {
145 if (other.calibration != calibration) {
146 return false;
147 }
Brian Silverman2eb89762019-02-17 15:16:37 -0800148 if (other.teensy_now != teensy_now) {
149 return false;
150 }
151 if (other.realtime_now != realtime_now) {
152 return false;
153 }
154 if (other.camera_command != camera_command) {
155 return false;
156 }
Brian Silverman246cb222019-02-02 16:38:18 -0800157 return true;
158 }
159 bool operator!=(const CameraCalibration &other) const {
160 return !(*this == other);
161 }
162
Brian Silverman1c0612e2019-01-26 17:26:08 -0800163 // The calibration matrix. This defines where the camera is pointing.
164 //
Brian Silverman246cb222019-02-02 16:38:18 -0800165 // TODO(Parker): What are the details on how this is defined?
Alex Perry3bf1bee2019-02-23 20:01:15 -0800166 // [0][0]: mount_angle
167 // [0][1]: focal_length
168 // [0][2]: barrel_mount
Brian Silverman1c0612e2019-01-26 17:26:08 -0800169 Eigen::Matrix<float, 3, 4> calibration;
Brian Silvermana3688802019-02-16 19:31:26 -0800170
171 // A local timestamp from the Teensy. This starts at 0 when the Teensy is
172 // powered on.
173 aos::monotonic_clock::time_point teensy_now;
174
175 // A realtime timestamp from the roboRIO. This will be min_time if the roboRIO
176 // has never sent anything.
177 aos::realtime_clock::time_point realtime_now;
178
179 // What mode the camera should transition into.
180 CameraCommand camera_command;
Brian Silverman1c0612e2019-01-26 17:26:08 -0800181};
182
183// This is all the information the Teensy sends to the RoboRIO.
184struct TeensyToRoborio {
Brian Silverman246cb222019-02-02 16:38:18 -0800185 bool operator==(const TeensyToRoborio &other) const {
186 if (other.frames != frames) {
187 return false;
188 }
189 return true;
190 }
191 bool operator!=(const TeensyToRoborio &other) const {
192 return !(*this == other);
193 }
194
Brian Silverman1c0612e2019-01-26 17:26:08 -0800195 // The newest frames received from up to three cameras. These will be the
196 // three earliest-received of all buffered frames.
Brian Silvermanc41fb862019-03-02 21:14:46 -0800197 aos::SizedArray<RoborioFrame, 3> frames;
Brian Silverman1c0612e2019-01-26 17:26:08 -0800198};
199
200// This is all the information the RoboRIO sends to the Teensy.
201struct RoborioToTeensy {
Brian Silverman246cb222019-02-02 16:38:18 -0800202 bool operator==(const RoborioToTeensy &other) const {
203 if (other.beacon_brightness != beacon_brightness) {
204 return false;
205 }
206 if (other.light_rings != light_rings) {
207 return false;
208 }
Brian Silvermanc41fb862019-03-02 21:14:46 -0800209 if (other.realtime_now != realtime_now) {
210 return false;
211 }
212 if (other.camera_command != camera_command) {
213 return false;
214 }
Brian Silverman246cb222019-02-02 16:38:18 -0800215 return true;
216 }
217 bool operator!=(const RoborioToTeensy &other) const {
218 return !(*this == other);
219 }
220
Brian Silverman1c0612e2019-01-26 17:26:08 -0800221 // Brightnesses for each of the beacon light channels. 0 is off, 255 is fully
222 // on.
223 std::array<uint8_t, 3> beacon_brightness;
224
225 // Whether the light ring for each camera should be on.
226 std::bitset<5> light_rings;
Brian Silvermana3688802019-02-16 19:31:26 -0800227
228 // The current time.
229 aos::realtime_clock::time_point realtime_now;
Brian Silvermane9924fd2019-03-02 15:20:42 -0800230
231 // A command to send to all the cameras.
232 CameraCommand camera_command;
Brian Silverman1c0612e2019-01-26 17:26:08 -0800233};
234
Stephan Pleinesd99b1ee2024-02-02 20:56:44 -0800235} // namespace frc971::jevois
Brian Silverman1c0612e2019-01-26 17:26:08 -0800236
237#endif // Y2019_JEVOIS_STRUCTURES_H_