blob: 15889c438f27d0983474ec197039ac004caada86 [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 Silvermana3688802019-02-16 19:31:26 -0800110 enum class CameraCommand {
111 // 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 }
123 return true;
124 }
125 bool operator!=(const CameraCalibration &other) const {
126 return !(*this == other);
127 }
128
Brian Silverman1c0612e2019-01-26 17:26:08 -0800129 // The calibration matrix. This defines where the camera is pointing.
130 //
Brian Silverman246cb222019-02-02 16:38:18 -0800131 // TODO(Parker): What are the details on how this is defined?
Brian Silverman1c0612e2019-01-26 17:26:08 -0800132 Eigen::Matrix<float, 3, 4> calibration;
Brian Silvermana3688802019-02-16 19:31:26 -0800133
134 // A local timestamp from the Teensy. This starts at 0 when the Teensy is
135 // powered on.
136 aos::monotonic_clock::time_point teensy_now;
137
138 // A realtime timestamp from the roboRIO. This will be min_time if the roboRIO
139 // has never sent anything.
140 aos::realtime_clock::time_point realtime_now;
141
142 // What mode the camera should transition into.
143 CameraCommand camera_command;
Brian Silverman1c0612e2019-01-26 17:26:08 -0800144};
145
146// This is all the information the Teensy sends to the RoboRIO.
147struct TeensyToRoborio {
Brian Silverman246cb222019-02-02 16:38:18 -0800148 bool operator==(const TeensyToRoborio &other) const {
149 if (other.frames != frames) {
150 return false;
151 }
152 return true;
153 }
154 bool operator!=(const TeensyToRoborio &other) const {
155 return !(*this == other);
156 }
157
Brian Silverman1c0612e2019-01-26 17:26:08 -0800158 // The newest frames received from up to three cameras. These will be the
159 // three earliest-received of all buffered frames.
160 aos::SizedArray<Frame, 3> frames;
161};
162
163// This is all the information the RoboRIO sends to the Teensy.
164struct RoborioToTeensy {
Brian Silverman246cb222019-02-02 16:38:18 -0800165 bool operator==(const RoborioToTeensy &other) const {
166 if (other.beacon_brightness != beacon_brightness) {
167 return false;
168 }
169 if (other.light_rings != light_rings) {
170 return false;
171 }
172 return true;
173 }
174 bool operator!=(const RoborioToTeensy &other) const {
175 return !(*this == other);
176 }
177
Brian Silverman1c0612e2019-01-26 17:26:08 -0800178 // Brightnesses for each of the beacon light channels. 0 is off, 255 is fully
179 // on.
180 std::array<uint8_t, 3> beacon_brightness;
181
182 // Whether the light ring for each camera should be on.
183 std::bitset<5> light_rings;
Brian Silvermana3688802019-02-16 19:31:26 -0800184
185 // The current time.
186 aos::realtime_clock::time_point realtime_now;
Brian Silverman1c0612e2019-01-26 17:26:08 -0800187};
188
189} // namespace jevois
190} // namespace frc971
191
192#endif // Y2019_JEVOIS_STRUCTURES_H_