blob: 2a0bfbc72eb2bf21215dd9d89efd4a4f61760ac1 [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"
Jim Ostrowski007e2ea2022-01-30 13:13:26 -080016#include "y2022/vision/calibration_data.h"
17#include "y2022/vision/calibration_generated.h"
Jim Ostrowski2a483b32022-02-15 18:19:14 -080018#include "y2022/vision/gpio.h"
milind-u92195982022-01-22 20:29:31 -080019#include "y2022/vision/target_estimate_generated.h"
Jim Ostrowskiff7b3de2022-01-22 22:20:26 -080020
21namespace y2022 {
22namespace vision {
23
24using namespace frc971::vision;
25
Jim Ostrowski2a483b32022-02-15 18:19:14 -080026// TODO<jim>: Probably need to break out LED control to separate process
27// TODO<jim>: Need to add sync with camera to strobe lights
Jim Ostrowskiff7b3de2022-01-22 22:20:26 -080028
29class CameraReader {
30 public:
Henry Speiser1f34eea2022-01-30 14:35:21 -080031 CameraReader(aos::ShmEventLoop *event_loop,
Jim Ostrowski007e2ea2022-01-30 13:13:26 -080032 const calibration::CalibrationData *calibration_data,
33 V4L2Reader *reader)
Jim Ostrowskiff7b3de2022-01-22 22:20:26 -080034 : event_loop_(event_loop),
Jim Ostrowski007e2ea2022-01-30 13:13:26 -080035 calibration_data_(calibration_data),
Jim Ostrowskiff7b3de2022-01-22 22:20:26 -080036 camera_calibration_(FindCameraCalibration()),
37 reader_(reader),
38 image_sender_(event_loop->MakeSender<CameraImage>("/camera")),
milind-u92195982022-01-22 20:29:31 -080039 target_estimate_sender_(
40 event_loop->MakeSender<TargetEstimate>("/camera")),
Jim Ostrowski2a483b32022-02-15 18:19:14 -080041 read_image_timer_(event_loop->AddTimer([this]() { ReadImage(); })),
42 gpio_pwm_control_(GPIOPWMControl(GPIO_PIN_SCK_PWM, duty_cycle_)),
43 gpio_disable_control_(
44 GPIOControl(GPIO_PIN_MOSI_DISABLE, kGPIOOut, kGPIOLow)) {
Jim Ostrowskiff7b3de2022-01-22 22:20:26 -080045 event_loop->OnRun(
46 [this]() { read_image_timer_->Setup(event_loop_->monotonic_now()); });
47 }
48
Jim Ostrowski2a483b32022-02-15 18:19:14 -080049 void SetDutyCycle(double duty_cycle) {
50 duty_cycle_ = duty_cycle;
51 gpio_pwm_control_.setPWMDutyCycle(duty_cycle_);
52 }
53
54 double GetDutyCycle() { return duty_cycle_; }
55
Jim Ostrowskiff7b3de2022-01-22 22:20:26 -080056 private:
Jim Ostrowski007e2ea2022-01-30 13:13:26 -080057 const calibration::CameraCalibration *FindCameraCalibration() const;
Jim Ostrowskiff7b3de2022-01-22 22:20:26 -080058
59 // Processes an image (including sending the results).
Milind Upadhyay2b4404c2022-02-04 21:20:57 -080060 void ProcessImage(cv::Mat image);
Jim Ostrowskiff7b3de2022-01-22 22:20:26 -080061
62 // Reads an image, and then performs all of our processing on it.
63 void ReadImage();
64
65 cv::Mat CameraIntrinsics() const {
66 const cv::Mat result(3, 3, CV_32F,
67 const_cast<void *>(static_cast<const void *>(
68 camera_calibration_->intrinsics()->data())));
69 CHECK_EQ(result.total(), camera_calibration_->intrinsics()->size());
70 return result;
71 }
72
milind-u92195982022-01-22 20:29:31 -080073 cv::Mat CameraExtrinsics() const {
74 const cv::Mat result(
75 4, 4, CV_32F,
76 const_cast<void *>(static_cast<const void *>(
77 camera_calibration_->fixed_extrinsics()->data()->data())));
78 CHECK_EQ(result.total(),
79 camera_calibration_->fixed_extrinsics()->data()->size());
80 return result;
81 }
82
Jim Ostrowskiff7b3de2022-01-22 22:20:26 -080083 cv::Mat CameraDistCoeffs() const {
84 const cv::Mat result(5, 1, CV_32F,
85 const_cast<void *>(static_cast<const void *>(
86 camera_calibration_->dist_coeffs()->data())));
87 CHECK_EQ(result.total(), camera_calibration_->dist_coeffs()->size());
88 return result;
89 }
90
Henry Speiser1f34eea2022-01-30 14:35:21 -080091 aos::ShmEventLoop *const event_loop_;
Jim Ostrowski007e2ea2022-01-30 13:13:26 -080092 const calibration::CalibrationData *const calibration_data_;
93 const calibration::CameraCalibration *const camera_calibration_;
Jim Ostrowskiff7b3de2022-01-22 22:20:26 -080094 V4L2Reader *const reader_;
95 aos::Sender<CameraImage> image_sender_;
milind-u92195982022-01-22 20:29:31 -080096 aos::Sender<TargetEstimate> target_estimate_sender_;
Jim Ostrowskiff7b3de2022-01-22 22:20:26 -080097
milind-u92195982022-01-22 20:29:31 -080098 // We schedule this immediately to read an image. Having it on a timer
99 // means other things can run on the event loop in between.
Jim Ostrowskiff7b3de2022-01-22 22:20:26 -0800100 aos::TimerHandler *const read_image_timer_;
Jim Ostrowski2a483b32022-02-15 18:19:14 -0800101
102 double duty_cycle_ = 0.0;
103 GPIOPWMControl gpio_pwm_control_;
104 GPIOControl gpio_disable_control_;
Jim Ostrowskiff7b3de2022-01-22 22:20:26 -0800105};
106
107} // namespace vision
108} // namespace y2022
109#endif // Y2022_VISION_CAMERA_READER_H_