blob: ba3defea98b7977b20a0186276dbc9a5d9c343cd [file] [log] [blame]
Ravago Jonese8700072023-01-14 19:41:56 -08001#include <linux/videodev2.h>
2#include <sys/ioctl.h>
3
Austin Schuh99f7c6a2024-06-25 22:07:44 -07004#include "absl/flags/flag.h"
Austin Schuhdb2ed9d2022-12-26 14:02:26 -08005#include "absl/strings/str_cat.h"
6#include "absl/strings/str_split.h"
Philipp Schrader790cb542023-07-05 21:06:52 -07007
Austin Schuhdb2ed9d2022-12-26 14:02:26 -08008#include "aos/events/shm_event_loop.h"
9#include "aos/init.h"
Austin Schuh9f164e92022-12-29 16:15:28 -080010#include "aos/realtime.h"
Austin Schuhdb2ed9d2022-12-26 14:02:26 -080011#include "frc971/vision/media_device.h"
12#include "frc971/vision/v4l2_reader.h"
Ravago Jonese8700072023-01-14 19:41:56 -080013#include "y2023/vision/rkisp1-config.h"
Austin Schuhdb2ed9d2022-12-26 14:02:26 -080014
Austin Schuh99f7c6a2024-06-25 22:07:44 -070015ABSL_FLAG(std::string, config, "aos_config.json",
16 "Path to the config file to use.");
17ABSL_FLAG(bool, lowlight_camera, true, "Switch to use imx462 image sensor.");
18ABSL_FLAG(int32_t, gain, 150, "analogue_gain");
Ravago Jonese8700072023-01-14 19:41:56 -080019
Austin Schuh99f7c6a2024-06-25 22:07:44 -070020ABSL_FLAG(double, red, 1.252, "Red gain");
21ABSL_FLAG(double, green, 1, "Green gain");
22ABSL_FLAG(double, blue, 1.96, "Blue gain");
23ABSL_FLAG(double, exposure, 150, "Camera exposure");
24ABSL_FLAG(bool, send_downsized_images, false,
25 "Whether to send downsized image for driver cam streaming.");
Austin Schuhdb2ed9d2022-12-26 14:02:26 -080026
Stephan Pleinesf63bde82024-01-13 15:59:33 -080027namespace y2023::vision {
Austin Schuhdb2ed9d2022-12-26 14:02:26 -080028namespace {
29
30using namespace frc971::vision;
31
Austin Schuhdb2ed9d2022-12-26 14:02:26 -080032void CameraReaderMain() {
33 std::optional<MediaDevice> media_device = FindMediaDevice("platform:rkisp1");
34
35 if (VLOG_IS_ON(1)) {
36 media_device->Log();
37 }
38
Austin Schuh99f7c6a2024-06-25 22:07:44 -070039 const int kWidth = (absl::GetFlag(FLAGS_lowlight_camera) ? 1920 : 1296);
40 const int kHeight = (absl::GetFlag(FLAGS_lowlight_camera) ? 1080 : 972);
41 const int kColorFormat =
42 (absl::GetFlag(FLAGS_lowlight_camera) ? MEDIA_BUS_FMT_SRGGB10_1X10
43 : MEDIA_BUS_FMT_SBGGR10_1X10);
milind-ufd08c432023-02-05 15:15:21 -080044
45 const std::string_view kCameraDeviceString =
Austin Schuh99f7c6a2024-06-25 22:07:44 -070046 (absl::GetFlag(FLAGS_lowlight_camera) ? "arducam-pivariety 4-000c"
47 : "ov5647 4-0036");
milind-ufd08c432023-02-05 15:15:21 -080048
49 // Scale down the selfpath images so we can log at 30 Hz (but still detect
50 // april tags at a far enough distance)
51 const double kSelfpathScalar = 2.0 / 3.0;
52 const int kSelfpathWidth = kWidth * kSelfpathScalar;
53 const int kSelfpathHeight = kHeight * kSelfpathScalar;
54
55 // Send heavily downsized images to the drivercam. They go over the network,
56 // and in this case frame rate is more important than quality
57 constexpr int kMainpathWidth = 640;
58 constexpr int kMainpathHeight = 480;
Ravago Jonesa0a2e062023-01-03 21:45:18 -080059
Austin Schuhdb2ed9d2022-12-26 14:02:26 -080060 media_device->Reset();
61
milind-ufd08c432023-02-05 15:15:21 -080062 Entity *camera = media_device->FindEntity(kCameraDeviceString);
63 camera->pads()[0]->SetSubdevFormat(kWidth, kHeight, kColorFormat);
Austin Schuhdb2ed9d2022-12-26 14:02:26 -080064
65 Entity *rkisp1_csi = media_device->FindEntity("rkisp1_csi");
milind-ufd08c432023-02-05 15:15:21 -080066 rkisp1_csi->pads()[0]->SetSubdevFormat(kWidth, kHeight, kColorFormat);
67 rkisp1_csi->pads()[1]->SetSubdevFormat(kWidth, kHeight, kColorFormat);
Austin Schuhdb2ed9d2022-12-26 14:02:26 -080068
69 // TODO(austin): Should we set this on the link?
Austin Schuhdb2ed9d2022-12-26 14:02:26 -080070 Entity *rkisp1_isp = media_device->FindEntity("rkisp1_isp");
milind-ufd08c432023-02-05 15:15:21 -080071 rkisp1_isp->pads(0)->SetSubdevFormat(kWidth, kHeight, kColorFormat);
72 rkisp1_isp->pads(0)->SetSubdevCrop(kWidth, kHeight);
Austin Schuhdb2ed9d2022-12-26 14:02:26 -080073
milind-ufd08c432023-02-05 15:15:21 -080074 rkisp1_isp->pads(2)->SetSubdevFormat(kWidth, kHeight,
75 MEDIA_BUS_FMT_YUYV8_2X8);
76 rkisp1_isp->pads(2)->SetSubdevCrop(kWidth, kHeight);
Austin Schuhdb2ed9d2022-12-26 14:02:26 -080077
78 Entity *rkisp1_resizer_selfpath =
79 media_device->FindEntity("rkisp1_resizer_selfpath");
milind-ufd08c432023-02-05 15:15:21 -080080 rkisp1_resizer_selfpath->pads(0)->SetSubdevFormat(kWidth, kHeight,
Austin Schuhdb2ed9d2022-12-26 14:02:26 -080081 MEDIA_BUS_FMT_YUYV8_2X8);
Ravago Jonese3182ee2023-01-28 22:33:05 -080082 rkisp1_resizer_selfpath->pads(1)->SetSubdevFormat(
milind-ufd08c432023-02-05 15:15:21 -080083 kSelfpathWidth, kSelfpathHeight, MEDIA_BUS_FMT_YUYV8_2X8);
84 rkisp1_resizer_selfpath->pads(0)->SetSubdevCrop(kWidth, kHeight);
Austin Schuhdb2ed9d2022-12-26 14:02:26 -080085
86 Entity *rkisp1_resizer_mainpath =
87 media_device->FindEntity("rkisp1_resizer_mainpath");
milind-ufd08c432023-02-05 15:15:21 -080088 rkisp1_resizer_mainpath->pads(0)->SetSubdevFormat(kWidth, kHeight,
Austin Schuhdb2ed9d2022-12-26 14:02:26 -080089 MEDIA_BUS_FMT_YUYV8_2X8);
Ravago Jones65469be2023-01-13 21:28:23 -080090
milind-ufd08c432023-02-05 15:15:21 -080091 rkisp1_resizer_mainpath->pads(0)->SetSubdevCrop(kWidth, kHeight);
92 rkisp1_resizer_mainpath->pads(1)->SetSubdevFormat(
93 kMainpathWidth, kMainpathHeight, MEDIA_BUS_FMT_YUYV8_2X8);
Austin Schuhdb2ed9d2022-12-26 14:02:26 -080094
95 Entity *rkisp1_mainpath = media_device->FindEntity("rkisp1_mainpath");
milind-ufd08c432023-02-05 15:15:21 -080096 rkisp1_mainpath->SetFormat(kMainpathWidth, kMainpathHeight,
97 V4L2_PIX_FMT_YUYV);
Austin Schuhdb2ed9d2022-12-26 14:02:26 -080098
99 Entity *rkisp1_selfpath = media_device->FindEntity("rkisp1_selfpath");
milind-ufd08c432023-02-05 15:15:21 -0800100 rkisp1_selfpath->SetFormat(kSelfpathWidth, kSelfpathHeight,
101 V4L2_PIX_FMT_YUYV);
Austin Schuhdb2ed9d2022-12-26 14:02:26 -0800102
Ravago Jones65469be2023-01-13 21:28:23 -0800103 media_device->Enable(
milind-ufd08c432023-02-05 15:15:21 -0800104 media_device->FindLink(kCameraDeviceString, 0, "rkisp1_csi", 0));
Ravago Jones65469be2023-01-13 21:28:23 -0800105 media_device->Enable(
106 media_device->FindLink("rkisp1_csi", 1, "rkisp1_isp", 0));
107 media_device->Enable(
108 media_device->FindLink("rkisp1_isp", 2, "rkisp1_resizer_selfpath", 0));
109 media_device->Enable(
110 media_device->FindLink("rkisp1_isp", 2, "rkisp1_resizer_mainpath", 0));
111
Austin Schuhdb2ed9d2022-12-26 14:02:26 -0800112 aos::FlatbufferDetachedBuffer<aos::Configuration> config =
Austin Schuh99f7c6a2024-06-25 22:07:44 -0700113 aos::configuration::ReadConfig(absl::GetFlag(FLAGS_config));
Austin Schuhdb2ed9d2022-12-26 14:02:26 -0800114
115 aos::ShmEventLoop event_loop(&config.message());
116
117 event_loop.SetRuntimeRealtimePriority(55);
Austin Schuh9f164e92022-12-29 16:15:28 -0800118 event_loop.SetRuntimeAffinity(aos::MakeCpusetFromCpus({2}));
Austin Schuhdb2ed9d2022-12-26 14:02:26 -0800119
milind-ufd08c432023-02-05 15:15:21 -0800120 // Reader for vision processing
121 RockchipV4L2Reader v4l2_reader_selfpath(&event_loop, event_loop.epoll(),
122 rkisp1_selfpath->device(),
123 camera->device());
Austin Schuh99f7c6a2024-06-25 22:07:44 -0700124 if (absl::GetFlag(FLAGS_lowlight_camera)) {
125 v4l2_reader_selfpath.SetGainExt(absl::GetFlag(FLAGS_gain));
milind-ufd08c432023-02-05 15:15:21 -0800126 v4l2_reader_selfpath.SetVerticalBlanking(1000);
Austin Schuh99f7c6a2024-06-25 22:07:44 -0700127 v4l2_reader_selfpath.SetExposure(absl::GetFlag(FLAGS_exposure));
Ravago Jonesa0a2e062023-01-03 21:45:18 -0800128 } else {
milind-ufd08c432023-02-05 15:15:21 -0800129 v4l2_reader_selfpath.SetGainExt(1000);
130 v4l2_reader_selfpath.SetExposure(1000);
131 }
132
133 std::unique_ptr<RockchipV4L2Reader> v4l2_reader_mainpath;
Austin Schuh99f7c6a2024-06-25 22:07:44 -0700134 if (absl::GetFlag(FLAGS_send_downsized_images)) {
milind-ufd08c432023-02-05 15:15:21 -0800135 // Reader for driver cam streaming on logger pi, sending lower res images
136 v4l2_reader_mainpath = std::make_unique<RockchipV4L2Reader>(
137 &event_loop, event_loop.epoll(), rkisp1_mainpath->device(),
138 camera->device(), "/camera/downsized");
Ravago Jonesa0a2e062023-01-03 21:45:18 -0800139 }
Austin Schuhdb2ed9d2022-12-26 14:02:26 -0800140
Ravago Jonese8700072023-01-14 19:41:56 -0800141 {
142 Entity *rkisp1_params = media_device->FindEntity("rkisp1_params");
143
144 LOG(INFO) << "Opening " << rkisp1_params->device();
145 aos::ScopedFD fd(open(rkisp1_params->device().c_str(), O_RDWR));
Maxwell Hendersonb963ffc2024-02-02 21:55:04 -0800146 PCHECK(fd.get() >= 0);
Ravago Jonese8700072023-01-14 19:41:56 -0800147
148 struct v4l2_capability capability;
149 memset(&capability, 0, sizeof(capability));
150 PCHECK(ioctl(fd.get(), VIDIOC_QUERYCAP, &capability) == 0);
151 CHECK(capability.device_caps & V4L2_CAP_META_OUTPUT);
152
153 // V4L2_META_FMT_RK_ISP1_PARAMS
154 // RK1P
155 uint32_t meta_params_format = (uint32_t)('R') | ((uint32_t)('K') << 8) |
156 ((uint32_t)('1') << 16) |
157 ((uint32_t)('P') << 24);
158 struct v4l2_format format;
159 std::memset(&format, 0, sizeof(format));
160 format.type = V4L2_BUF_TYPE_META_OUTPUT;
161
162 PCHECK(ioctl(fd.get(), VIDIOC_G_FMT, &format) == 0);
163 CHECK_EQ(format.fmt.meta.buffersize, 3048ul);
164 CHECK_EQ(format.fmt.meta.dataformat, meta_params_format);
165
166 struct v4l2_requestbuffers request;
167 memset(&request, 0, sizeof(request));
168 request.count = 1;
169 request.type = V4L2_BUF_TYPE_META_OUTPUT;
170 request.memory = V4L2_MEMORY_USERPTR;
171 PCHECK(ioctl(fd.get(), VIDIOC_REQBUFS, &request) == 0);
172
173 struct rkisp1_params_cfg configuration;
174 memset(&configuration, 0, sizeof(configuration));
175
176 configuration.module_cfg_update |= RKISP1_CIF_ISP_MODULE_AWB_GAIN;
177
Austin Schuh99f7c6a2024-06-25 22:07:44 -0700178 configuration.others.awb_gain_config.gain_red =
179 256 * absl::GetFlag(FLAGS_red);
180 configuration.others.awb_gain_config.gain_green_r =
181 256 * absl::GetFlag(FLAGS_green);
182 configuration.others.awb_gain_config.gain_blue =
183 256 * absl::GetFlag(FLAGS_blue);
184 configuration.others.awb_gain_config.gain_green_b =
185 256 * absl::GetFlag(FLAGS_green);
Ravago Jonese8700072023-01-14 19:41:56 -0800186
187 // Enable the AWB gains
188 configuration.module_en_update |= RKISP1_CIF_ISP_MODULE_AWB_GAIN;
189 configuration.module_ens |= RKISP1_CIF_ISP_MODULE_AWB_GAIN;
190
191 struct v4l2_buffer buffer;
192 memset(&buffer, 0, sizeof(buffer));
193 buffer.memory = V4L2_MEMORY_USERPTR;
194 buffer.index = 0;
195 buffer.type = V4L2_BUF_TYPE_META_OUTPUT;
196 buffer.m.userptr = reinterpret_cast<uintptr_t>(&configuration);
197 buffer.length = format.fmt.meta.buffersize;
198
199 int type = V4L2_BUF_TYPE_META_OUTPUT;
200 PCHECK(ioctl(fd.get(), VIDIOC_STREAMON, &type) == 0);
201
202 PCHECK(ioctl(fd.get(), VIDIOC_QBUF, &buffer) == 0);
203 CHECK(buffer.flags & V4L2_BUF_FLAG_QUEUED);
204
205 PCHECK(ioctl(fd.get(), VIDIOC_DQBUF, &buffer) == 0);
206 }
207
Austin Schuhdb2ed9d2022-12-26 14:02:26 -0800208 event_loop.Run();
209}
210
211} // namespace
Stephan Pleinesf63bde82024-01-13 15:59:33 -0800212} // namespace y2023::vision
Austin Schuhdb2ed9d2022-12-26 14:02:26 -0800213
214int main(int argc, char **argv) {
215 aos::InitGoogle(&argc, &argv);
Maxwell Hendersonad312342023-01-10 12:07:47 -0800216 y2023::vision::CameraReaderMain();
Austin Schuhdb2ed9d2022-12-26 14:02:26 -0800217}