32bool CameraDetectionOccComponent::InitDetector(
33 const CameraDetectionBEV &detection_param) {
35 auto detector_plugin_param = detection_param.detector_plugin_param();
36 init_options.
config_path = detector_plugin_param.config_path();
37 init_options.
config_file = detector_plugin_param.config_file();
38 init_options.
gpu_id = detection_param.gpu_id();
41 std::string camera_name = detection_param.camera_name();
43 algorithm::SensorManager::Instance()->GetUndistortCameraModel(
45 ACHECK(model) <<
"Can't find " << camera_name
46 <<
" in data/conf/sensor_meta.pb.txt";
47 auto pinhole =
static_cast<base::PinholeCameraModel *
>(model.get());
48 init_options.
intrinsic = pinhole->get_intrinsic_params();
51 image_height_ = model->get_height();
52 image_width_ = model->get_width();
55 detector_.reset(BaseObstacleDetectorRegisterer::GetInstanceByName(
56 detector_plugin_param.name()));
57 detector_->Init(init_options);
61bool CameraDetectionOccComponent::InitCameraFrame(
62 const CameraDetectionBEV &detection_param) {
63 DataProvider::InitOptions init_options;
65 init_options.image_width = image_width_;
66 init_options.do_undistortion = detection_param.enable_undistortion();
67 init_options.device_id = detection_param.gpu_id();
68 AINFO <<
"init_options.device_id: " << init_options.device_id
69 <<
" camera_name: " << init_options.sensor_name;
71 std::vector<std::string> bev_sensor_name{
72 detection_param.sensors().bev_camera_name().begin(),
73 detection_param.sensors().bev_camera_name().end()};
75 frame_ptr_ = std::make_shared<CameraFrame>();
76 frame_ptr_->data_provider.resize(bev_sensor_name.size());
77 frame_ptr_->k_lidar2img.clear();
79 for (
int i = 0; i < bev_sensor_name.size(); ++i) {
80 init_options.sensor_name = bev_sensor_name[i];
85 std::string camera_extrinsic_file_path = FLAGS_obs_sensor_intrinsic_path +
86 "/" + init_options.sensor_name +
88 Eigen::Affine3d camera2lidar_rt = Eigen::Affine3d::Identity();
90 if (detection_param.dataset_type() ==
"nuscenes") {
91 std::string lidar_extrinsic_file_path =
92 FLAGS_obs_sensor_intrinsic_path +
"/LIDAR_TOP_novatel_extrinsics.yaml";
93 LoadCameraExtrinsicNus(
94 camera_extrinsic_file_path,
95 lidar_extrinsic_file_path,
98 LoadCameraExtrinsic(camera_extrinsic_file_path, &camera2lidar_rt);
100 Eigen::Matrix4d lidar2camera_rt =
101 camera2lidar_rt.inverse().matrix();
104 algorithm::SensorManager *sensor_manager =
105 algorithm::SensorManager::Instance();
106 if (!sensor_manager->IsSensorExist(init_options.sensor_name)) {
107 AERROR <<
"Sensor '" << init_options.sensor_name <<
"' not exists!";
111 Eigen::Matrix3f camera_intrinsic =
112 std::dynamic_pointer_cast<base::BrownCameraDistortionModel>(
113 sensor_manager->GetDistortCameraModel(init_options.sensor_name))
114 ->get_intrinsic_params();
115 Eigen::Matrix4f viewpad = Eigen::Matrix4f::Identity();
116 viewpad(0, 0) = camera_intrinsic(0, 0);
117 viewpad(0, 2) = camera_intrinsic(0, 2);
118 viewpad(1, 1) = camera_intrinsic(1, 1);
119 viewpad(1, 2) = camera_intrinsic(1, 2);
122 Eigen::Matrix4d lidar2img_rt =
123 viewpad.cast<
double>() * lidar2camera_rt;
125 for (
size_t i = 0; i < lidar2img_rt.rows(); i++) {
126 for (
size_t j = 0; j < lidar2img_rt.cols(); j++) {
127 frame_ptr_->k_lidar2img.push_back(lidar2img_rt(i, j));
131 frame_ptr_->data_provider[i] = std::make_shared<DataProvider>();
132 frame_ptr_->data_provider[i]->Init(init_options);
137bool CameraDetectionOccComponent::LoadCameraExtrinsic(
138 const std::string &file_path, Eigen::Affine3d *camera2lidar_rt) {
139 CHECK_NOTNULL(camera2lidar_rt);
141 YAML::Node config = YAML::LoadFile(file_path);
142 if (config[
"transform"]) {
143 if (config[
"transform"][
"translation"]) {
144 camera2lidar_rt->translation()(0) =
145 config[
"transform"][
"translation"][
"x"].as<double>();
146 camera2lidar_rt->translation()(1) =
147 config[
"transform"][
"translation"][
"y"].as<double>();
148 camera2lidar_rt->translation()(2) =
149 config[
"transform"][
"translation"][
"z"].as<double>();
150 if (config[
"transform"][
"rotation"]) {
151 double qx = config[
"transform"][
"rotation"][
"x"].as<
double>();
152 double qy = config[
"transform"][
"rotation"][
"y"].as<
double>();
153 double qz = config[
"transform"][
"rotation"][
"z"].as<
double>();
154 double qw = config[
"transform"][
"rotation"][
"w"].as<
double>();
155 camera2lidar_rt->linear() =
156 Eigen::Quaterniond(qw, qx, qy, qz).toRotationMatrix();
164bool CameraDetectionOccComponent::LoadCameraExtrinsicNus(
165 const std::string &camera_extrinsic_file_path,
166 const std::string &lidar_extrinsic_file_path,
167 Eigen::Affine3d *camera2lidar_rt) {
168 CHECK_NOTNULL(camera2lidar_rt);
169 Eigen::Affine3d local2lidar_rt = Eigen::Affine3d::Identity();
170 YAML::Node config = YAML::LoadFile(lidar_extrinsic_file_path);
171 if (config[
"transform"]) {
172 if (config[
"transform"][
"translation"]) {
173 local2lidar_rt.translation()(0) =
174 config[
"transform"][
"translation"][
"x"].as<double>();
175 local2lidar_rt.translation()(1) =
176 config[
"transform"][
"translation"][
"y"].as<double>();
177 local2lidar_rt.translation()(2) =
178 config[
"transform"][
"translation"][
"z"].as<double>();
179 if (config[
"transform"][
"rotation"]) {
180 double qx = config[
"transform"][
"rotation"][
"x"].as<
double>();
181 double qy = config[
"transform"][
"rotation"][
"y"].as<
double>();
182 double qz = config[
"transform"][
"rotation"][
"z"].as<
double>();
183 double qw = config[
"transform"][
"rotation"][
"w"].as<
double>();
184 local2lidar_rt.linear() =
185 Eigen::Quaterniond(qw, qx, qy, qz).toRotationMatrix();
197 Eigen::Affine3d local2cam_rt = Eigen::Affine3d::Identity();
198 config = YAML::LoadFile(camera_extrinsic_file_path);
199 if (config[
"transform"]) {
200 if (config[
"transform"][
"translation"]) {
201 local2cam_rt.translation()(0) =
202 config[
"transform"][
"translation"][
"x"].as<double>();
203 local2cam_rt.translation()(1) =
204 config[
"transform"][
"translation"][
"y"].as<double>();
205 local2cam_rt.translation()(2) =
206 config[
"transform"][
"translation"][
"z"].as<double>();
207 if (config[
"transform"][
"rotation"]) {
208 double qx = config[
"transform"][
"rotation"][
"x"].as<
double>();
209 double qy = config[
"transform"][
"rotation"][
"y"].as<
double>();
210 double qz = config[
"transform"][
"rotation"][
"z"].as<
double>();
211 double qw = config[
"transform"][
"rotation"][
"w"].as<
double>();
212 local2cam_rt.linear() =
213 Eigen::Quaterniond(qw, qx, qy, qz).toRotationMatrix();
226 *camera2lidar_rt = (local2cam_rt.inverse() * local2lidar_rt).inverse();
230bool CameraDetectionOccComponent::InitListeners(
231 const CameraDetectionBEV &detection_param) {
232 for (
const auto &channel :
233 detection_param.channel().input_camera_channel_name()) {
234 std::shared_ptr<cyber::Reader<drivers::Image>> reader;
236 detection_param.channel().input_camera_channel_name()
237 [detection_param.channel().input_camera_channel_name().size() -
239 reader =
node_->CreateReader<drivers::Image>(
240 channel, [&](
const std::shared_ptr<drivers::Image> &msg) {
244 reader =
node_->CreateReader<drivers::Image>(channel);
246 readers_.emplace_back(reader);
251bool CameraDetectionOccComponent::InitTransformWrapper(
252 const CameraDetectionBEV &detection_param) {
253 trans_wrapper_.reset(
new onboard::TransformWrapper());
255 trans_wrapper_->Init(detection_param.frame_id());
262 AERROR <<
"Load camera detection 3d component config failed!";
269 BaseTrackerRegisterer::GetInstanceByName(tracker_plugin_param.name());
270 CHECK_NOTNULL(tracker);
271 tracker_.reset(tracker);
274 tracker_init_options.
config_path = tracker_plugin_param.config_path();
275 tracker_init_options.
config_file = tracker_plugin_param.config_file();
276 ACHECK(tracker_->Init(tracker_init_options)) <<
"camera tracker init error";
292 InitDetector(detection_param);
293 InitCameraFrame(detection_param);
294 InitListeners(detection_param);
295 InitTransformWrapper(detection_param);
302void CameraDetectionOccComponent::CameraToWorldCoor(
303 const Eigen::Affine3d &camera2world, std::vector<base::ObjectPtr> *objs) {
304 for (
auto &obj : *objs) {
305 Eigen::Vector3d local_center =
306 obj->camera_supplement.local_center.cast<
double>();
307 obj->center = camera2world * local_center;
309 obj->direction = camera2world.linear().cast<
float>() * obj->direction;
310 obj->theta = std::atan2(obj->direction(1), obj->direction(0));
312 for (
size_t i = 0; i < obj->polygon.size(); ++i) {
313 auto &pt = obj->polygon.at(i);
314 Eigen::Vector3d local_polygon_point =
315 Eigen::Vector3f(pt.x, pt.y, pt.z).cast<
double>();
316 Eigen::Vector3d world_polygon_point = camera2world * local_polygon_point;
317 pt.x = world_polygon_point[0];
318 pt.y = world_polygon_point[1];
319 pt.z = world_polygon_point[2];
324int CameraDetectionOccComponent::ConvertObjectToPb(
326 if (!object_ptr || !pb_msg) {
329 pb_msg->set_id(object_ptr->track_id);
330 pb_msg->set_theta(object_ptr->theta);
331 pb_msg->set_confidence(object_ptr->confidence);
334 obj_center->set_x(object_ptr->center(0));
335 obj_center->set_y(object_ptr->center(1));
336 obj_center->set_z(object_ptr->center(2));
339 obj_velocity->set_x(object_ptr->velocity(0));
340 obj_velocity->set_y(object_ptr->velocity(1));
341 obj_velocity->set_z(object_ptr->velocity(2));
344 obj_acceleration->set_x(object_ptr->acceleration(0));
345 obj_acceleration->set_y(object_ptr->acceleration(1));
346 obj_acceleration->set_z(object_ptr->acceleration(2));
348 pb_msg->set_length(object_ptr->size(0));
349 pb_msg->set_width(object_ptr->size(1));
350 pb_msg->set_height(object_ptr->size(2));
354 pb_msg->set_sub_type(
356 pb_msg->set_timestamp(object_ptr->latest_tracked_time);
358 pb_msg->set_height_above_ground(object_ptr->size(2));
360 for (
size_t i = 0; i < object_ptr->polygon.size(); ++i) {
361 auto &pt = object_ptr->polygon.at(i);
370int CameraDetectionOccComponent::MakeProtobufMsg(
371 double msg_timestamp,
int seq_num,
372 const std::vector<base::ObjectPtr> &objects,
373 PerceptionObstacles *obstacles) {
375 auto header = obstacles->mutable_header();
376 header->set_timestamp_sec(publish_time);
377 header->set_module_name(
"perception_camera");
378 header->set_sequence_num(seq_num);
381 header->set_lidar_timestamp(
static_cast<uint64_t
>(msg_timestamp * 1e9));
382 header->set_camera_timestamp(
static_cast<uint64_t
>(msg_timestamp * 1e9));
386 for (
const auto &obj : objects) {
387 obj->track_id = count++;
389 if (ConvertObjectToPb(obj, obstacle) !=
cyber::SUCC) {
390 AERROR <<
"ConvertObjectToPb failed, Object:" << obj->ToString();
398bool CameraDetectionOccComponent::OnReceiveImage(
399 const std::shared_ptr<drivers::Image> &msg) {
400 const double msg_timestamp = msg->measurement_time() + timestamp_offset_;
402 for (
size_t i = 0; i < readers_.size(); ++i) {
403 readers_[i]->Observe();
404 const auto &camera_msg = readers_[i]->GetLatestObserved();
405 if (camera_msg ==
nullptr) {
406 AERROR <<
"Failed to get camera message, camera_name: "
410 frame_ptr_->data_provider[i]->FillImageData(
411 image_height_, image_width_,
412 reinterpret_cast<const uint8_t *
>(camera_msg->data().data()),
413 camera_msg->encoding());
416 frame_ptr_->timestamp = msg_timestamp;
417 ++frame_ptr_->frame_id;
421 detector_->Detect(frame_ptr_.get());
442 Eigen::Affine3d lidar2world_trans;
443 if (!trans_wrapper_->GetSensor2worldTrans(msg_timestamp,
444 &lidar2world_trans)) {
445 const std::string err_str =
446 absl::StrCat(
"failed to get camera to world pose, ts: ", msg_timestamp,
447 " camera_name: ", msg->frame_id());
452 CameraToWorldCoor(lidar2world_trans, &frame_ptr_->detected_objects);
469 std::shared_ptr<PerceptionObstacles> out_message(
new (std::nothrow)
471 if (MakeProtobufMsg(msg_timestamp, seq_num_, frame_ptr_->detected_objects,
473 AERROR <<
"MakeProtobufMsg failed ts: " << msg_timestamp;
478 writer_->Write(out_message);
483bool CameraDetectionOccComponent::ConvertToBaseFrame(
const CameraFrame *frame,
484 base::Frame *base_frame) {
485 base_frame->timestamp = frame->timestamp;
486 for (
size_t i = 0; i < frame->detected_objects.size(); ++i) {
488 base_frame->objects.emplace_back(
object);
static double NowInSeconds()
gets the current time in second.
bool GetProtoConfig(T *config) const
std::shared_ptr< Node > node_
apollo::perception::PerceptionObstacle PerceptionObstacle
apollo::perception::PerceptionObstacles PerceptionObstacles
bool Init() override
Init for camera detection 2d compoment
std::shared_ptr< BaseCameraModel > BaseCameraModelPtr
std::shared_ptr< Object > ObjectPtr
optional perception::PluginParam tracker_plugin_param
optional DetectionChannel channel
optional string output_obstacles_channel_name
Eigen::Matrix3f intrinsic