blob: 7128890e5cd915da2f58a80c7800dd116f077741 [file] [log] [blame]
Jim Ostrowskiff7b3de2022-01-22 22:20:26 -08001#ifndef Y2022_VISION_CAMERA_READER_H_
2#define Y2022_VISION_CAMERA_READER_H_
3
4#include <math.h>
5
6#include <opencv2/calib3d.hpp>
7#include <opencv2/features2d.hpp>
Henry Speiser1f34eea2022-01-30 14:35:21 -08008#include <opencv2/imgcodecs.hpp>
Jim Ostrowskiff7b3de2022-01-22 22:20:26 -08009#include <opencv2/imgproc.hpp>
10
Henry Speiser1f34eea2022-01-30 14:35:21 -080011#include "aos/events/shm_event_loop.h"
Jim Ostrowskiff7b3de2022-01-22 22:20:26 -080012#include "aos/flatbuffer_merge.h"
13#include "aos/network/team_number.h"
14#include "frc971/vision/v4l2_reader.h"
15#include "frc971/vision/vision_generated.h"
Milind Upadhyayd67e9cf2022-03-13 13:56:57 -070016#include "y2022/localizer/localizer_output_generated.h"
Jim Ostrowski007e2ea2022-01-30 13:13:26 -080017#include "y2022/vision/calibration_data.h"
18#include "y2022/vision/calibration_generated.h"
Jim Ostrowski2a483b32022-02-15 18:19:14 -080019#include "y2022/vision/gpio.h"
milind-u92195982022-01-22 20:29:31 -080020#include "y2022/vision/target_estimate_generated.h"
Milind Upadhyayf61e1482022-02-11 20:42:55 -080021#include "y2022/vision/target_estimator.h"
Jim Ostrowskiff7b3de2022-01-22 22:20:26 -080022
23namespace y2022 {
24namespace vision {
25
26using namespace frc971::vision;
Milind Upadhyayd67e9cf2022-03-13 13:56:57 -070027using frc971::controls::LedOutput;
Jim Ostrowskiff7b3de2022-01-22 22:20:26 -080028
Jim Ostrowski2a483b32022-02-15 18:19:14 -080029// TODO<jim>: Probably need to break out LED control to separate process
Jim Ostrowskiff7b3de2022-01-22 22:20:26 -080030class CameraReader {
31 public:
Henry Speiser1f34eea2022-01-30 14:35:21 -080032 CameraReader(aos::ShmEventLoop *event_loop,
Jim Ostrowski007e2ea2022-01-30 13:13:26 -080033 const calibration::CalibrationData *calibration_data,
34 V4L2Reader *reader)
Jim Ostrowskiff7b3de2022-01-22 22:20:26 -080035 : event_loop_(event_loop),
Jim Ostrowski007e2ea2022-01-30 13:13:26 -080036 calibration_data_(calibration_data),
Jim Ostrowskiff7b3de2022-01-22 22:20:26 -080037 camera_calibration_(FindCameraCalibration()),
38 reader_(reader),
39 image_sender_(event_loop->MakeSender<CameraImage>("/camera")),
Milind Upadhyayf61e1482022-02-11 20:42:55 -080040 target_estimator_(CameraIntrinsics(), CameraExtrinsics()),
milind-u92195982022-01-22 20:29:31 -080041 target_estimate_sender_(
42 event_loop->MakeSender<TargetEstimate>("/camera")),
Milind Upadhyayd67e9cf2022-03-13 13:56:57 -070043 localizer_output_fetcher_(
44 event_loop->MakeFetcher<frc971::controls::LocalizerOutput>(
45 "/localizer")),
Jim Ostrowski2a483b32022-02-15 18:19:14 -080046 read_image_timer_(event_loop->AddTimer([this]() { ReadImage(); })),
Jim Ostrowskia49d20e2022-02-26 18:34:05 -080047 gpio_imu_pin_(GPIOControl(GPIO_PIN_SCLK_IMU, kGPIOIn)),
Jim Ostrowski2a483b32022-02-15 18:19:14 -080048 gpio_pwm_control_(GPIOPWMControl(GPIO_PIN_SCK_PWM, duty_cycle_)),
49 gpio_disable_control_(
50 GPIOControl(GPIO_PIN_MOSI_DISABLE, kGPIOOut, kGPIOLow)) {
Jim Ostrowskiff7b3de2022-01-22 22:20:26 -080051 event_loop->OnRun(
52 [this]() { read_image_timer_->Setup(event_loop_->monotonic_now()); });
53 }
54
Jim Ostrowski2a483b32022-02-15 18:19:14 -080055 void SetDutyCycle(double duty_cycle) {
56 duty_cycle_ = duty_cycle;
57 gpio_pwm_control_.setPWMDutyCycle(duty_cycle_);
58 }
59
60 double GetDutyCycle() { return duty_cycle_; }
61
Jim Ostrowskiff7b3de2022-01-22 22:20:26 -080062 private:
Jim Ostrowski007e2ea2022-01-30 13:13:26 -080063 const calibration::CameraCalibration *FindCameraCalibration() const;
Jim Ostrowskiff7b3de2022-01-22 22:20:26 -080064
65 // Processes an image (including sending the results).
Milind Upadhyay3c1a5c02022-03-27 16:27:19 -070066 void ProcessImage(cv::Mat image_mat_distorted,
67 int64_t image_monotonic_timestamp_ns);
Jim Ostrowskiff7b3de2022-01-22 22:20:26 -080068
69 // Reads an image, and then performs all of our processing on it.
70 void ReadImage();
71
72 cv::Mat CameraIntrinsics() const {
milind-ucafdd5d2022-03-01 19:58:57 -080073 cv::Mat result(3, 3, CV_32F,
74 const_cast<void *>(static_cast<const void *>(
75 camera_calibration_->intrinsics()->data())));
76 result.convertTo(result, CV_64F);
Jim Ostrowskiff7b3de2022-01-22 22:20:26 -080077 CHECK_EQ(result.total(), camera_calibration_->intrinsics()->size());
78 return result;
79 }
80
milind-u92195982022-01-22 20:29:31 -080081 cv::Mat CameraExtrinsics() const {
James Kuszmaul246e51c2022-03-13 21:43:29 -070082 // TODO(james): What's the principled way to handle non-z-axis turrets?
83 const frc971::vision::calibration::TransformationMatrix *transform =
84 camera_calibration_->has_turret_extrinsics()
85 ? camera_calibration_->turret_extrinsics()
86 : camera_calibration_->fixed_extrinsics();
87
88 cv::Mat result(4, 4, CV_32F,
89 const_cast<void *>(
90 static_cast<const void *>(transform->data()->data())));
milind-ucafdd5d2022-03-01 19:58:57 -080091 result.convertTo(result, CV_64F);
James Kuszmaul246e51c2022-03-13 21:43:29 -070092 CHECK_EQ(result.total(), transform->data()->size());
milind-u92195982022-01-22 20:29:31 -080093 return result;
94 }
95
Jim Ostrowskiff7b3de2022-01-22 22:20:26 -080096 cv::Mat CameraDistCoeffs() const {
97 const cv::Mat result(5, 1, CV_32F,
98 const_cast<void *>(static_cast<const void *>(
99 camera_calibration_->dist_coeffs()->data())));
100 CHECK_EQ(result.total(), camera_calibration_->dist_coeffs()->size());
101 return result;
102 }
103
Henry Speiser1f34eea2022-01-30 14:35:21 -0800104 aos::ShmEventLoop *const event_loop_;
Jim Ostrowski007e2ea2022-01-30 13:13:26 -0800105 const calibration::CalibrationData *const calibration_data_;
106 const calibration::CameraCalibration *const camera_calibration_;
Jim Ostrowskiff7b3de2022-01-22 22:20:26 -0800107 V4L2Reader *const reader_;
108 aos::Sender<CameraImage> image_sender_;
Milind Upadhyayf61e1482022-02-11 20:42:55 -0800109 TargetEstimator target_estimator_;
milind-u92195982022-01-22 20:29:31 -0800110 aos::Sender<TargetEstimate> target_estimate_sender_;
Jim Ostrowskiff7b3de2022-01-22 22:20:26 -0800111
Milind Upadhyayd67e9cf2022-03-13 13:56:57 -0700112 LedOutput prev_led_output_ = LedOutput::ON;
113 aos::Fetcher<frc971::controls::LocalizerOutput> localizer_output_fetcher_;
114
milind-u92195982022-01-22 20:29:31 -0800115 // We schedule this immediately to read an image. Having it on a timer
116 // means other things can run on the event loop in between.
Jim Ostrowskiff7b3de2022-01-22 22:20:26 -0800117 aos::TimerHandler *const read_image_timer_;
Jim Ostrowski2a483b32022-02-15 18:19:14 -0800118
119 double duty_cycle_ = 0.0;
Jim Ostrowskia49d20e2022-02-26 18:34:05 -0800120 GPIOControl gpio_imu_pin_;
Jim Ostrowski2a483b32022-02-15 18:19:14 -0800121 GPIOPWMControl gpio_pwm_control_;
122 GPIOControl gpio_disable_control_;
Jim Ostrowskiff7b3de2022-01-22 22:20:26 -0800123};
124
125} // namespace vision
126} // namespace y2022
127#endif // Y2022_VISION_CAMERA_READER_H_