blob: d5f39a05d2f2e3ca5e5ab0859873a55d3fc43945 [file] [log] [blame]
Ravago Jonese8700072023-01-14 19:41:56 -08001#include <linux/videodev2.h>
2#include <sys/ioctl.h>
3
Austin Schuhdb2ed9d2022-12-26 14:02:26 -08004#include "absl/strings/str_cat.h"
5#include "absl/strings/str_split.h"
Philipp Schrader790cb542023-07-05 21:06:52 -07006
Austin Schuhdb2ed9d2022-12-26 14:02:26 -08007#include "aos/events/shm_event_loop.h"
8#include "aos/init.h"
Austin Schuh9f164e92022-12-29 16:15:28 -08009#include "aos/realtime.h"
Austin Schuhdb2ed9d2022-12-26 14:02:26 -080010#include "frc971/vision/media_device.h"
11#include "frc971/vision/v4l2_reader.h"
Ravago Jonese8700072023-01-14 19:41:56 -080012#include "y2023/vision/rkisp1-config.h"
Austin Schuhdb2ed9d2022-12-26 14:02:26 -080013
14DEFINE_string(config, "aos_config.json", "Path to the config file to use.");
Ravago Jonese8700072023-01-14 19:41:56 -080015DEFINE_bool(lowlight_camera, true, "Switch to use imx462 image sensor.");
milind-u50c9a582023-05-03 20:05:22 -070016DEFINE_int32(gain, 150, "analogue_gain");
Ravago Jonese8700072023-01-14 19:41:56 -080017
18DEFINE_double(red, 1.252, "Red gain");
19DEFINE_double(green, 1, "Green gain");
20DEFINE_double(blue, 1.96, "Blue gain");
Ravago Jones0f2e3a12023-01-29 16:13:29 -080021DEFINE_double(exposure, 150, "Camera exposure");
milind-ufd08c432023-02-05 15:15:21 -080022DEFINE_bool(send_downsized_images, false,
23 "Whether to send downsized image for driver cam streaming.");
Austin Schuhdb2ed9d2022-12-26 14:02:26 -080024
Maxwell Hendersonad312342023-01-10 12:07:47 -080025namespace y2023 {
Austin Schuhdb2ed9d2022-12-26 14:02:26 -080026namespace vision {
27namespace {
28
29using namespace frc971::vision;
30
Austin Schuhdb2ed9d2022-12-26 14:02:26 -080031void CameraReaderMain() {
32 std::optional<MediaDevice> media_device = FindMediaDevice("platform:rkisp1");
33
34 if (VLOG_IS_ON(1)) {
35 media_device->Log();
36 }
37
milind-ufd08c432023-02-05 15:15:21 -080038 const int kWidth = (FLAGS_lowlight_camera ? 1920 : 1296);
39 const int kHeight = (FLAGS_lowlight_camera ? 1080 : 972);
40 const int kColorFormat = (FLAGS_lowlight_camera ? MEDIA_BUS_FMT_SRGGB10_1X10
41 : MEDIA_BUS_FMT_SBGGR10_1X10);
42
43 const std::string_view kCameraDeviceString =
44 (FLAGS_lowlight_camera ? "arducam-pivariety 4-000c" : "ov5647 4-0036");
45
46 // Scale down the selfpath images so we can log at 30 Hz (but still detect
47 // april tags at a far enough distance)
48 const double kSelfpathScalar = 2.0 / 3.0;
49 const int kSelfpathWidth = kWidth * kSelfpathScalar;
50 const int kSelfpathHeight = kHeight * kSelfpathScalar;
51
52 // Send heavily downsized images to the drivercam. They go over the network,
53 // and in this case frame rate is more important than quality
54 constexpr int kMainpathWidth = 640;
55 constexpr int kMainpathHeight = 480;
Ravago Jonesa0a2e062023-01-03 21:45:18 -080056
Austin Schuhdb2ed9d2022-12-26 14:02:26 -080057 media_device->Reset();
58
milind-ufd08c432023-02-05 15:15:21 -080059 Entity *camera = media_device->FindEntity(kCameraDeviceString);
60 camera->pads()[0]->SetSubdevFormat(kWidth, kHeight, kColorFormat);
Austin Schuhdb2ed9d2022-12-26 14:02:26 -080061
62 Entity *rkisp1_csi = media_device->FindEntity("rkisp1_csi");
milind-ufd08c432023-02-05 15:15:21 -080063 rkisp1_csi->pads()[0]->SetSubdevFormat(kWidth, kHeight, kColorFormat);
64 rkisp1_csi->pads()[1]->SetSubdevFormat(kWidth, kHeight, kColorFormat);
Austin Schuhdb2ed9d2022-12-26 14:02:26 -080065
66 // TODO(austin): Should we set this on the link?
Austin Schuhdb2ed9d2022-12-26 14:02:26 -080067 Entity *rkisp1_isp = media_device->FindEntity("rkisp1_isp");
milind-ufd08c432023-02-05 15:15:21 -080068 rkisp1_isp->pads(0)->SetSubdevFormat(kWidth, kHeight, kColorFormat);
69 rkisp1_isp->pads(0)->SetSubdevCrop(kWidth, kHeight);
Austin Schuhdb2ed9d2022-12-26 14:02:26 -080070
milind-ufd08c432023-02-05 15:15:21 -080071 rkisp1_isp->pads(2)->SetSubdevFormat(kWidth, kHeight,
72 MEDIA_BUS_FMT_YUYV8_2X8);
73 rkisp1_isp->pads(2)->SetSubdevCrop(kWidth, kHeight);
Austin Schuhdb2ed9d2022-12-26 14:02:26 -080074
75 Entity *rkisp1_resizer_selfpath =
76 media_device->FindEntity("rkisp1_resizer_selfpath");
milind-ufd08c432023-02-05 15:15:21 -080077 rkisp1_resizer_selfpath->pads(0)->SetSubdevFormat(kWidth, kHeight,
Austin Schuhdb2ed9d2022-12-26 14:02:26 -080078 MEDIA_BUS_FMT_YUYV8_2X8);
Ravago Jonese3182ee2023-01-28 22:33:05 -080079 rkisp1_resizer_selfpath->pads(1)->SetSubdevFormat(
milind-ufd08c432023-02-05 15:15:21 -080080 kSelfpathWidth, kSelfpathHeight, MEDIA_BUS_FMT_YUYV8_2X8);
81 rkisp1_resizer_selfpath->pads(0)->SetSubdevCrop(kWidth, kHeight);
Austin Schuhdb2ed9d2022-12-26 14:02:26 -080082
83 Entity *rkisp1_resizer_mainpath =
84 media_device->FindEntity("rkisp1_resizer_mainpath");
milind-ufd08c432023-02-05 15:15:21 -080085 rkisp1_resizer_mainpath->pads(0)->SetSubdevFormat(kWidth, kHeight,
Austin Schuhdb2ed9d2022-12-26 14:02:26 -080086 MEDIA_BUS_FMT_YUYV8_2X8);
Ravago Jones65469be2023-01-13 21:28:23 -080087
milind-ufd08c432023-02-05 15:15:21 -080088 rkisp1_resizer_mainpath->pads(0)->SetSubdevCrop(kWidth, kHeight);
89 rkisp1_resizer_mainpath->pads(1)->SetSubdevFormat(
90 kMainpathWidth, kMainpathHeight, MEDIA_BUS_FMT_YUYV8_2X8);
Austin Schuhdb2ed9d2022-12-26 14:02:26 -080091
92 Entity *rkisp1_mainpath = media_device->FindEntity("rkisp1_mainpath");
milind-ufd08c432023-02-05 15:15:21 -080093 rkisp1_mainpath->SetFormat(kMainpathWidth, kMainpathHeight,
94 V4L2_PIX_FMT_YUYV);
Austin Schuhdb2ed9d2022-12-26 14:02:26 -080095
96 Entity *rkisp1_selfpath = media_device->FindEntity("rkisp1_selfpath");
milind-ufd08c432023-02-05 15:15:21 -080097 rkisp1_selfpath->SetFormat(kSelfpathWidth, kSelfpathHeight,
98 V4L2_PIX_FMT_YUYV);
Austin Schuhdb2ed9d2022-12-26 14:02:26 -080099
Ravago Jones65469be2023-01-13 21:28:23 -0800100 media_device->Enable(
milind-ufd08c432023-02-05 15:15:21 -0800101 media_device->FindLink(kCameraDeviceString, 0, "rkisp1_csi", 0));
Ravago Jones65469be2023-01-13 21:28:23 -0800102 media_device->Enable(
103 media_device->FindLink("rkisp1_csi", 1, "rkisp1_isp", 0));
104 media_device->Enable(
105 media_device->FindLink("rkisp1_isp", 2, "rkisp1_resizer_selfpath", 0));
106 media_device->Enable(
107 media_device->FindLink("rkisp1_isp", 2, "rkisp1_resizer_mainpath", 0));
108
Austin Schuhdb2ed9d2022-12-26 14:02:26 -0800109 aos::FlatbufferDetachedBuffer<aos::Configuration> config =
110 aos::configuration::ReadConfig(FLAGS_config);
111
112 aos::ShmEventLoop event_loop(&config.message());
113
114 event_loop.SetRuntimeRealtimePriority(55);
Austin Schuh9f164e92022-12-29 16:15:28 -0800115 event_loop.SetRuntimeAffinity(aos::MakeCpusetFromCpus({2}));
Austin Schuhdb2ed9d2022-12-26 14:02:26 -0800116
milind-ufd08c432023-02-05 15:15:21 -0800117 // Reader for vision processing
118 RockchipV4L2Reader v4l2_reader_selfpath(&event_loop, event_loop.epoll(),
119 rkisp1_selfpath->device(),
120 camera->device());
Ravago Jonesa0a2e062023-01-03 21:45:18 -0800121 if (FLAGS_lowlight_camera) {
Austin Schuh83c2c9c2023-03-22 20:27:24 -0700122 v4l2_reader_selfpath.SetGainExt(FLAGS_gain);
milind-ufd08c432023-02-05 15:15:21 -0800123 v4l2_reader_selfpath.SetVerticalBlanking(1000);
124 v4l2_reader_selfpath.SetExposure(FLAGS_exposure);
Ravago Jonesa0a2e062023-01-03 21:45:18 -0800125 } else {
milind-ufd08c432023-02-05 15:15:21 -0800126 v4l2_reader_selfpath.SetGainExt(1000);
127 v4l2_reader_selfpath.SetExposure(1000);
128 }
129
130 std::unique_ptr<RockchipV4L2Reader> v4l2_reader_mainpath;
131 if (FLAGS_send_downsized_images) {
132 // Reader for driver cam streaming on logger pi, sending lower res images
133 v4l2_reader_mainpath = std::make_unique<RockchipV4L2Reader>(
134 &event_loop, event_loop.epoll(), rkisp1_mainpath->device(),
135 camera->device(), "/camera/downsized");
Ravago Jonesa0a2e062023-01-03 21:45:18 -0800136 }
Austin Schuhdb2ed9d2022-12-26 14:02:26 -0800137
Ravago Jonese8700072023-01-14 19:41:56 -0800138 {
139 Entity *rkisp1_params = media_device->FindEntity("rkisp1_params");
140
141 LOG(INFO) << "Opening " << rkisp1_params->device();
142 aos::ScopedFD fd(open(rkisp1_params->device().c_str(), O_RDWR));
143 PCHECK(fd >= 0);
144
145 struct v4l2_capability capability;
146 memset(&capability, 0, sizeof(capability));
147 PCHECK(ioctl(fd.get(), VIDIOC_QUERYCAP, &capability) == 0);
148 CHECK(capability.device_caps & V4L2_CAP_META_OUTPUT);
149
150 // V4L2_META_FMT_RK_ISP1_PARAMS
151 // RK1P
152 uint32_t meta_params_format = (uint32_t)('R') | ((uint32_t)('K') << 8) |
153 ((uint32_t)('1') << 16) |
154 ((uint32_t)('P') << 24);
155 struct v4l2_format format;
156 std::memset(&format, 0, sizeof(format));
157 format.type = V4L2_BUF_TYPE_META_OUTPUT;
158
159 PCHECK(ioctl(fd.get(), VIDIOC_G_FMT, &format) == 0);
160 CHECK_EQ(format.fmt.meta.buffersize, 3048ul);
161 CHECK_EQ(format.fmt.meta.dataformat, meta_params_format);
162
163 struct v4l2_requestbuffers request;
164 memset(&request, 0, sizeof(request));
165 request.count = 1;
166 request.type = V4L2_BUF_TYPE_META_OUTPUT;
167 request.memory = V4L2_MEMORY_USERPTR;
168 PCHECK(ioctl(fd.get(), VIDIOC_REQBUFS, &request) == 0);
169
170 struct rkisp1_params_cfg configuration;
171 memset(&configuration, 0, sizeof(configuration));
172
173 configuration.module_cfg_update |= RKISP1_CIF_ISP_MODULE_AWB_GAIN;
174
175 configuration.others.awb_gain_config.gain_red = 256 * FLAGS_red;
176 configuration.others.awb_gain_config.gain_green_r = 256 * FLAGS_green;
177 configuration.others.awb_gain_config.gain_blue = 256 * FLAGS_blue;
178 configuration.others.awb_gain_config.gain_green_b = 256 * FLAGS_green;
179
180 // Enable the AWB gains
181 configuration.module_en_update |= RKISP1_CIF_ISP_MODULE_AWB_GAIN;
182 configuration.module_ens |= RKISP1_CIF_ISP_MODULE_AWB_GAIN;
183
184 struct v4l2_buffer buffer;
185 memset(&buffer, 0, sizeof(buffer));
186 buffer.memory = V4L2_MEMORY_USERPTR;
187 buffer.index = 0;
188 buffer.type = V4L2_BUF_TYPE_META_OUTPUT;
189 buffer.m.userptr = reinterpret_cast<uintptr_t>(&configuration);
190 buffer.length = format.fmt.meta.buffersize;
191
192 int type = V4L2_BUF_TYPE_META_OUTPUT;
193 PCHECK(ioctl(fd.get(), VIDIOC_STREAMON, &type) == 0);
194
195 PCHECK(ioctl(fd.get(), VIDIOC_QBUF, &buffer) == 0);
196 CHECK(buffer.flags & V4L2_BUF_FLAG_QUEUED);
197
198 PCHECK(ioctl(fd.get(), VIDIOC_DQBUF, &buffer) == 0);
199 }
200
Austin Schuhdb2ed9d2022-12-26 14:02:26 -0800201 event_loop.Run();
202}
203
204} // namespace
205} // namespace vision
Maxwell Hendersonad312342023-01-10 12:07:47 -0800206} // namespace y2023
Austin Schuhdb2ed9d2022-12-26 14:02:26 -0800207
208int main(int argc, char **argv) {
209 aos::InitGoogle(&argc, &argv);
Maxwell Hendersonad312342023-01-10 12:07:47 -0800210 y2023::vision::CameraReaderMain();
Austin Schuhdb2ed9d2022-12-26 14:02:26 -0800211}