blob: fcc268ef9a4e0d87030dea51d988f2ece8c28528 [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 Silverman1c0612e2019-01-26 17:26:08 -080014
15namespace frc971 {
16namespace jevois {
17
18// The overall flow to get data to the roboRIO consists of:
19// 1. Camera captures a frame and grabs an absolute timestamp.
20// 2. Camera processes the frame.
21// 3. Camera grabs another absolute timestamp and subtracts to get a
22// camera_duration.
23// 4. Camera sends the frame via UART to the Teensy.
24// 5. Teensy grabs an absolute timestamp for the first character received.
25// 6. Teensy buffers at most one frame from each camera.
26// 7. roboRIO toggles the CS line.
27// 8. Teensy grabs an absolute timestamp for CS being asserted.
28// 9. Teensy pulls together up to three frames and adds the time each one
29// spent in its queue to the timestamps, and queues them in its SPI
30// peripheral. This all happens before the roboRIO has enough time to start
31// actually moving data.
32// 10. roboRIO transfers the frames, and sends back light/status commands.
33
34using camera_duration = std::chrono::duration<uint8_t, std::milli>;
35
36// This file declares the shared datastructures for the JeVois-based image
37// system.
38//
39// Note that floating-point numbers are represented with floats. This is because
40// a float has more bits than we need for anything, and the Teensy can't handle
41// doubles very quickly. It would probably be quick enough, but it's easier to
42// just use floats and not worry about it.
43
44struct Target {
Brian Silverman246cb222019-02-02 16:38:18 -080045 bool operator==(const Target &other) const {
46 if (other.distance != distance) {
47 return false;
48 }
49 if (other.height != height) {
50 return false;
51 }
52 if (other.heading != heading) {
53 return false;
54 }
55 if (other.skew != skew) {
56 return false;
57 }
58 return true;
59 }
60 bool operator!=(const Target &other) const {
61 return !(*this == other);
62 }
63
Brian Silverman1c0612e2019-01-26 17:26:08 -080064 // Distance to the target in meters. Specifically, the distance from the
65 // center of the camera's image plane to the center of the target.
66 float distance;
67
68 // Height of the target in meters. Specifically, the distance from the floor
69 // to the center of the target.
70 float height;
71
72 // Heading of the center of the target in radians. Zero is straight out
73 // perpendicular to the camera's image plane. Images to the left (looking at a
74 // camera image) are at a positive angle.
75 float heading;
76
77 // The angle between the target and the camera's image plane. This is
78 // projected so both are assumed to be perpendicular to the floor. Parallel
79 // targets have a skew of zero. Targets rotated such that their left edge
80 // (looking at a camera image) is closer are at a positive angle.
81 float skew;
82};
83
84// The information extracted from a single camera frame.
85//
86// This is all the information sent from each camera to the Teensy.
87struct Frame {
Brian Silverman246cb222019-02-02 16:38:18 -080088 bool operator==(const Frame &other) const {
89 if (other.targets != targets) {
90 return false;
91 }
92 if (other.age != age) {
93 return false;
94 }
95 return true;
96 }
97 bool operator!=(const Frame &other) const {
98 return !(*this == other);
99 }
100
Brian Silverman1c0612e2019-01-26 17:26:08 -0800101 // The top most interesting targets found in this frame.
102 aos::SizedArray<Target, 3> targets;
103
104 // How long ago from the current time this frame was captured.
105 camera_duration age;
106};
107
108// This is all the information sent from the Teensy to each camera.
109struct CameraCalibration {
Brian Silverman2eb89762019-02-17 15:16:37 -0800110 enum class CameraCommand : char {
Brian Silvermana3688802019-02-16 19:31:26 -0800111 // Stay in normal mode.
112 kNormal,
113 // Go to camera passthrough mode.
114 kCameraPassthrough,
115 // Go to being a useful USB device.
116 kUsb,
117 };
118
Brian Silverman246cb222019-02-02 16:38:18 -0800119 bool operator==(const CameraCalibration &other) const {
120 if (other.calibration != calibration) {
121 return false;
122 }
Brian Silverman2eb89762019-02-17 15:16:37 -0800123 if (other.teensy_now != teensy_now) {
124 return false;
125 }
126 if (other.realtime_now != realtime_now) {
127 return false;
128 }
129 if (other.camera_command != camera_command) {
130 return false;
131 }
Brian Silverman246cb222019-02-02 16:38:18 -0800132 return true;
133 }
134 bool operator!=(const CameraCalibration &other) const {
135 return !(*this == other);
136 }
137
Brian Silverman1c0612e2019-01-26 17:26:08 -0800138 // The calibration matrix. This defines where the camera is pointing.
139 //
Brian Silverman246cb222019-02-02 16:38:18 -0800140 // TODO(Parker): What are the details on how this is defined?
Brian Silverman1c0612e2019-01-26 17:26:08 -0800141 Eigen::Matrix<float, 3, 4> calibration;
Brian Silvermana3688802019-02-16 19:31:26 -0800142
143 // A local timestamp from the Teensy. This starts at 0 when the Teensy is
144 // powered on.
145 aos::monotonic_clock::time_point teensy_now;
146
147 // A realtime timestamp from the roboRIO. This will be min_time if the roboRIO
148 // has never sent anything.
149 aos::realtime_clock::time_point realtime_now;
150
151 // What mode the camera should transition into.
152 CameraCommand camera_command;
Brian Silverman1c0612e2019-01-26 17:26:08 -0800153};
154
155// This is all the information the Teensy sends to the RoboRIO.
156struct TeensyToRoborio {
Brian Silverman246cb222019-02-02 16:38:18 -0800157 bool operator==(const TeensyToRoborio &other) const {
158 if (other.frames != frames) {
159 return false;
160 }
161 return true;
162 }
163 bool operator!=(const TeensyToRoborio &other) const {
164 return !(*this == other);
165 }
166
Brian Silverman1c0612e2019-01-26 17:26:08 -0800167 // The newest frames received from up to three cameras. These will be the
168 // three earliest-received of all buffered frames.
169 aos::SizedArray<Frame, 3> frames;
170};
171
172// This is all the information the RoboRIO sends to the Teensy.
173struct RoborioToTeensy {
Brian Silverman246cb222019-02-02 16:38:18 -0800174 bool operator==(const RoborioToTeensy &other) const {
175 if (other.beacon_brightness != beacon_brightness) {
176 return false;
177 }
178 if (other.light_rings != light_rings) {
179 return false;
180 }
181 return true;
182 }
183 bool operator!=(const RoborioToTeensy &other) const {
184 return !(*this == other);
185 }
186
Brian Silverman1c0612e2019-01-26 17:26:08 -0800187 // Brightnesses for each of the beacon light channels. 0 is off, 255 is fully
188 // on.
189 std::array<uint8_t, 3> beacon_brightness;
190
191 // Whether the light ring for each camera should be on.
192 std::bitset<5> light_rings;
Brian Silvermana3688802019-02-16 19:31:26 -0800193
194 // The current time.
195 aos::realtime_clock::time_point realtime_now;
Brian Silverman1c0612e2019-01-26 17:26:08 -0800196};
197
198} // namespace jevois
199} // namespace frc971
200
201#endif // Y2019_JEVOIS_STRUCTURES_H_