blob: c82a08944ba5c2e6926f4ecf5d7cd21a6bba9f64 [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"
13
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 }
59 bool operator!=(const Target &other) const {
60 return !(*this == other);
61 }
62
Brian Silverman1c0612e2019-01-26 17:26:08 -080063 // Distance to the target in meters. Specifically, the distance from the
64 // center of the camera's image plane to the center of the target.
65 float distance;
66
67 // Height of the target in meters. Specifically, the distance from the floor
68 // to the center of the target.
69 float height;
70
71 // Heading of the center of the target in radians. Zero is straight out
72 // perpendicular to the camera's image plane. Images to the left (looking at a
73 // camera image) are at a positive angle.
74 float heading;
75
76 // The angle between the target and the camera's image plane. This is
77 // projected so both are assumed to be perpendicular to the floor. Parallel
78 // targets have a skew of zero. Targets rotated such that their left edge
79 // (looking at a camera image) is closer are at a positive angle.
80 float skew;
81};
82
83// The information extracted from a single camera frame.
84//
85// This is all the information sent from each camera to the Teensy.
86struct Frame {
Brian Silverman246cb222019-02-02 16:38:18 -080087 bool operator==(const Frame &other) const {
88 if (other.targets != targets) {
89 return false;
90 }
91 if (other.age != age) {
92 return false;
93 }
94 return true;
95 }
96 bool operator!=(const Frame &other) const {
97 return !(*this == other);
98 }
99
Brian Silverman1c0612e2019-01-26 17:26:08 -0800100 // The top most interesting targets found in this frame.
101 aos::SizedArray<Target, 3> targets;
102
103 // How long ago from the current time this frame was captured.
104 camera_duration age;
105};
106
107// This is all the information sent from the Teensy to each camera.
108struct CameraCalibration {
Brian Silverman246cb222019-02-02 16:38:18 -0800109 bool operator==(const CameraCalibration &other) const {
110 if (other.calibration != calibration) {
111 return false;
112 }
113 return true;
114 }
115 bool operator!=(const CameraCalibration &other) const {
116 return !(*this == other);
117 }
118
Brian Silverman1c0612e2019-01-26 17:26:08 -0800119 // The calibration matrix. This defines where the camera is pointing.
120 //
Brian Silverman246cb222019-02-02 16:38:18 -0800121 // TODO(Parker): What are the details on how this is defined?
Brian Silverman1c0612e2019-01-26 17:26:08 -0800122 Eigen::Matrix<float, 3, 4> calibration;
123};
124
125// This is all the information the Teensy sends to the RoboRIO.
126struct TeensyToRoborio {
Brian Silverman246cb222019-02-02 16:38:18 -0800127 bool operator==(const TeensyToRoborio &other) const {
128 if (other.frames != frames) {
129 return false;
130 }
131 return true;
132 }
133 bool operator!=(const TeensyToRoborio &other) const {
134 return !(*this == other);
135 }
136
Brian Silverman1c0612e2019-01-26 17:26:08 -0800137 // The newest frames received from up to three cameras. These will be the
138 // three earliest-received of all buffered frames.
139 aos::SizedArray<Frame, 3> frames;
140};
141
142// This is all the information the RoboRIO sends to the Teensy.
143struct RoborioToTeensy {
Brian Silverman246cb222019-02-02 16:38:18 -0800144 bool operator==(const RoborioToTeensy &other) const {
145 if (other.beacon_brightness != beacon_brightness) {
146 return false;
147 }
148 if (other.light_rings != light_rings) {
149 return false;
150 }
151 return true;
152 }
153 bool operator!=(const RoborioToTeensy &other) const {
154 return !(*this == other);
155 }
156
Brian Silverman1c0612e2019-01-26 17:26:08 -0800157 // Brightnesses for each of the beacon light channels. 0 is off, 255 is fully
158 // on.
159 std::array<uint8_t, 3> beacon_brightness;
160
161 // Whether the light ring for each camera should be on.
162 std::bitset<5> light_rings;
163};
164
165} // namespace jevois
166} // namespace frc971
167
168#endif // Y2019_JEVOIS_STRUCTURES_H_