Apollo 11.0
自动驾驶开放平台
birdview_img_feature_renderer.cc
浏览该文件的文档.
1/******************************************************************************
2 * Copyright 2020 The Apollo Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *****************************************************************************/
16
18
19#include <string>
20#include <utility>
21#include <vector>
22
23#include "modules/common_msgs/perception_msgs/traffic_light_detection.pb.h"
24
25#include "cyber/common/log.h"
28
29namespace apollo {
30namespace planning {
31
32// TODO(Jinyun): take map name from upstream and move to conf
33static const char ROADMAP_IMG_PATH[] =
34 "/apollo/modules/planning/planning_base/learning_based/data/semantic_map/"
35 "sunnyvale_with_two_offices.png";
36static const char SPEEDLIMITMAP_IMG_PATH[] =
37 "/apollo/modules/planning/planning_base/learning_based/data/semantic_map/"
38 "sunnyvale_with_two_offices_speedlimit.png";
39
40BirdviewImgFeatureRenderer::BirdviewImgFeatureRenderer() {}
41
43 config_ = config;
44 ego_vehicle_config_ = common::VehicleConfigHelper::GetConfig();
45
46 // a redundant call to HDMapUtil::BaseMap() to save time for renderering when
47 // the basemap is not yet initialized in HDMapUtil
49
50 const std::string map_name =
51 FLAGS_map_dir.substr(FLAGS_map_dir.find_last_of("/") + 1);
52 if (map_name != "sunnyvale_with_two_offices" && map_name != "sunnyvale") {
53 AERROR << "Map other than sunnyvale_with_two_offices are not supported";
54 }
55 // TODO(Jinyun): add sunnyvale map or draw basemap online
56 if (map_name == "sunnyvale") {
57 AWARN << "use sunnyvale_with_two_offices for sunnyvale for now";
58 }
59
60 // TODO(Jinyun): move to a more managable place
61 map_bottom_left_point_x_ = 585875.3316302994;
62 map_bottom_left_point_y_ = 4139916.6342316796;
63 bool roadmap_img_status = LoadRoadMap(ROADMAP_IMG_PATH);
64 bool speedlimit_img_status = LoadSpeedlimitMap(SPEEDLIMITMAP_IMG_PATH);
65
66 if (!roadmap_img_status || !speedlimit_img_status) {
67 AERROR << "Base map image read failed";
68 return false;
69 }
70
71 ego_cur_point_img_ =
72 cv::Mat(config_.height(), config_.width(), CV_8UC1, cv::Scalar(0));
73 ego_cur_box_img_ =
74 cv::Mat(config_.height(), config_.width(), CV_8UC1, cv::Scalar(0));
75
76 bool render_ego_point_status = RenderEgoCurrentPoint(&ego_cur_point_img_);
77 bool render_ego_box_status = RenderEgoCurrentBox(&ego_cur_box_img_);
78
79 if (!render_ego_point_status || !render_ego_box_status) {
80 AERROR << "Ego point or box img rendering failed";
81 return false;
82 }
83
84 if (base_roadmap_img_.size[0] != base_speedlimit_img_.size[0] ||
85 base_roadmap_img_.size[1] != base_speedlimit_img_.size[1]) {
86 AERROR << "base map sizes doesn't match";
87 return false;
88 }
89
90 std::vector<cv::Mat> merge_imgs = {ego_cur_point_img_, ego_cur_box_img_};
91 cv::merge(merge_imgs, stacked_ego_cur_status_img_);
92
93 return true;
94}
95
97 const LearningDataFrame& learning_data_frame, cv::Mat* img_feature) {
98 int ego_trajectory_point_history_size =
99 learning_data_frame.adc_trajectory_point_size();
100 if (ego_trajectory_point_history_size < 1) {
101 AERROR << "Ego past history is empty";
102 return false;
103 }
104
105 cv::Mat ego_past =
106 cv::Mat(config_.height(), config_.width(), CV_8UC1, cv::Scalar(0));
107 cv::Mat obs_past =
108 cv::Mat(config_.height(), config_.width(), CV_8UC1, cv::Scalar(0));
109 cv::Mat obs_future =
110 cv::Mat(config_.height(), config_.width(), CV_8UC1, cv::Scalar(0));
111 cv::Mat road_map =
112 cv::Mat(config_.height(), config_.width(), CV_8UC3, cv::Scalar(0, 0, 0));
113 cv::Mat routing =
114 cv::Mat(config_.height(), config_.width(), CV_8UC1, cv::Scalar(0));
115 cv::Mat speed_limit =
116 cv::Mat(config_.height(), config_.width(), CV_8UC3, cv::Scalar(0, 0, 0));
117 cv::Mat traffic_light =
118 cv::Mat(config_.height(), config_.width(), CV_8UC1, cv::Scalar(0));
119
120 const auto& current_traj_point = learning_data_frame.adc_trajectory_point(
121 ego_trajectory_point_history_size - 1);
122 const double current_time_sec = current_traj_point.timestamp_sec();
123 const auto& current_path_point =
124 current_traj_point.trajectory_point().path_point();
125 const double current_x = current_path_point.x();
126 const double current_y = current_path_point.y();
127 const double current_heading = current_path_point.theta();
128
129 if (!RenderEgoPastPoint(learning_data_frame, current_time_sec, current_x,
130 current_y, current_heading, &ego_past)) {
131 AERROR << "RenderEgoPastPoint failed";
132 return false;
133 }
134 if (!RenderObsPastBox(learning_data_frame, current_time_sec, &obs_past)) {
135 AERROR << "RenderObsPastBox failed";
136 return false;
137 }
138 if (!RenderObsFutureBox(learning_data_frame, current_time_sec, &obs_future)) {
139 AERROR << "RenderObsFutureBox failed";
140 return false;
141 }
142 if (!RenderLocalRoadMap(current_x, current_y, current_heading, &road_map)) {
143 AERROR << "RenderLocalRoadMap failed";
144 return false;
145 }
146 if (!RenderRouting(learning_data_frame, current_x, current_y, current_heading,
147 &routing)) {
148 AERROR << "RenderRouting failed";
149 return false;
150 }
151 if (!RenderLocalSpeedlimitMap(current_x, current_y, current_heading,
152 &speed_limit)) {
153 AERROR << "RenderLocalSpeedlimitMap failed";
154 return false;
155 }
156 if (!RenderTrafficLight(learning_data_frame, current_x, current_y,
157 current_heading, &traffic_light)) {
158 AERROR << "RenderTrafficLight failed";
159 return false;
160 }
161
162 std::vector<cv::Mat> merge_imgs = {ego_cur_box_img_, ego_past, obs_past,
163 obs_future, road_map, routing,
164 speed_limit, traffic_light};
165 cv::merge(merge_imgs, *img_feature);
166 return true;
167}
168
170 const LearningDataFrame& learning_data_frame, cv::Mat* img_feature) {
171 int ego_trajectory_point_history_size =
172 learning_data_frame.adc_trajectory_point_size();
173 if (ego_trajectory_point_history_size < 1) {
174 AERROR << "Ego past history is empty";
175 return false;
176 }
177
178 cv::Mat bgr_canvas =
179 cv::Mat(config_.height(), config_.width(), CV_8UC3, cv::Scalar(0, 0, 0));
180
181 const auto& current_traj_point = learning_data_frame.adc_trajectory_point(
182 ego_trajectory_point_history_size - 1);
183 const double current_time_sec = current_traj_point.timestamp_sec();
184 const auto& current_path_point =
185 current_traj_point.trajectory_point().path_point();
186 const double current_x = current_path_point.x();
187 const double current_y = current_path_point.y();
188 const double current_heading = current_path_point.theta();
189
190 if (!RenderLocalRoadMap(current_x, current_y, current_heading, &bgr_canvas)) {
191 AERROR << "RenderLocalRoadMap failed";
192 return false;
193 }
194 if (!RenderRouting(learning_data_frame, current_x, current_y, current_heading,
195 &bgr_canvas)) {
196 AERROR << "RenderRouting failed";
197 return false;
198 }
199 if (!RenderTrafficLight(learning_data_frame, current_x, current_y,
200 current_heading, &bgr_canvas)) {
201 AERROR << "RenderTrafficLight failed";
202 return false;
203 }
204 if (!RenderObsPastBox(learning_data_frame, current_time_sec, &bgr_canvas)) {
205 AERROR << "RenderObsPastBox failed";
206 return false;
207 }
208 if (!RenderObsFutureBox(learning_data_frame, current_time_sec, &bgr_canvas)) {
209 AERROR << "RenderObsFutureBox failed";
210 return false;
211 }
212 if (!RenderEgoCurrentBox(&bgr_canvas)) {
213 AERROR << "RenderEgoCurrentBox failed";
214 return false;
215 }
216 if (!RenderEgoPastPoint(learning_data_frame, current_time_sec, current_x,
217 current_y, current_heading, &bgr_canvas)) {
218 AERROR << "RenderEgoPastPoint failed";
219 return false;
220 }
221
222 bgr_canvas.copyTo(*img_feature);
223
224 return true;
225}
226
228 const LearningDataFrame& learning_data_frame, cv::Mat* img_feature) {
229 stacked_ego_cur_status_img_.copyTo(*img_feature);
230 return true;
231}
232
234 const LearningDataFrame& learning_data_frame, cv::Mat* img_feature) {
235 ego_cur_point_img_.copyTo(*img_feature);
236 return true;
237}
238
240 const LearningDataFrame& learning_data_frame, cv::Mat* img_feature) {
241 ego_cur_box_img_.copyTo(*img_feature);
242 return true;
243}
244
245bool BirdviewImgFeatureRenderer::LoadRoadMap(const std::string& map_file) {
246 base_roadmap_img_ = cv::imread(map_file);
247 return !base_roadmap_img_.empty();
248}
249
250bool BirdviewImgFeatureRenderer::LoadSpeedlimitMap(
251 const std::string& map_file) {
252 base_speedlimit_img_ = cv::imread(map_file);
253 return !base_speedlimit_img_.empty();
254}
255
256bool BirdviewImgFeatureRenderer::RenderLocalRoadMap(
257 const double ego_current_x, const double ego_current_y,
258 const double ego_current_heading, cv::Mat* img_feature) {
259 return CropByPose(ego_current_x, ego_current_y, ego_current_heading,
260 base_roadmap_img_, img_feature);
261}
262
263bool BirdviewImgFeatureRenderer::RenderLocalSpeedlimitMap(
264 const double ego_current_x, const double ego_current_y,
265 const double ego_current_heading, cv::Mat* img_feature) {
266 return CropByPose(ego_current_x, ego_current_y, ego_current_heading,
267 base_speedlimit_img_, img_feature);
268}
269
270bool BirdviewImgFeatureRenderer::RenderEgoCurrentPoint(
271 cv::Mat* img_feature, const cv::Scalar& gray_scale,
272 const cv::Scalar& bgr_color) {
273 cv::Scalar color;
274 if ((*img_feature).channels() == 3) {
275 color = bgr_color;
276 } else {
277 color = gray_scale;
278 }
279 (*img_feature).at<uchar>(config_.ego_idx_y(), config_.ego_idx_x()) = color[0];
280 return true;
281}
282
283bool BirdviewImgFeatureRenderer::RenderEgoCurrentBox(
284 cv::Mat* img_feature, const cv::Scalar& gray_scale,
285 const cv::Scalar& bgr_color) {
286 cv::Scalar color;
287 if ((*img_feature).channels() == 3) {
288 color = bgr_color;
289 } else {
290 color = gray_scale;
291 }
292 const auto& param = ego_vehicle_config_.vehicle_param();
293 std::vector<cv::Point2i> box_corner_points =
294 GetAffinedBoxImgIdx(0.0, 0.0, M_PI_2,
295 {
296 std::make_pair(param.front_edge_to_center(),
297 param.left_edge_to_center()),
298 std::make_pair(param.front_edge_to_center(),
299 -param.right_edge_to_center()),
300 std::make_pair(-param.back_edge_to_center(),
301 -param.right_edge_to_center()),
302 std::make_pair(-param.back_edge_to_center(),
303 param.left_edge_to_center()),
304 },
305 0.0, 0.0, 0.0);
306 cv::fillPoly(
307 *img_feature,
308 std::vector<std::vector<cv::Point>>({std::move(box_corner_points)}),
309 color);
310 return true;
311}
312
313bool BirdviewImgFeatureRenderer::RenderEgoPastPoint(
314 const LearningDataFrame& learning_data_frame, const double current_time_sec,
315 const double ego_current_x, const double ego_current_y,
316 const double ego_current_heading, cv::Mat* img_feature,
317 const cv::Scalar& gray_scale, const cv::Scalar& bgr_color) {
318 cv::Scalar color;
319 if ((*img_feature).channels() == 3) {
320 color = bgr_color;
321 } else {
322 color = gray_scale;
323 }
324 const auto& ego_past = learning_data_frame.adc_trajectory_point();
325 cv::Scalar gradual_change_color;
326 for (const auto& ego_past_point : ego_past) {
327 const double relative_time =
328 current_time_sec - ego_past_point.timestamp_sec();
329 if (relative_time > config_.max_ego_past_horizon()) {
330 continue;
331 }
332 gradual_change_color =
333 color * (1 - relative_time / config_.max_ego_past_horizon());
334 cv::circle(*img_feature,
335 GetAffinedPointImgIdx(
336 ego_past_point.trajectory_point().path_point().x(),
337 ego_past_point.trajectory_point().path_point().y(),
338 ego_current_x, ego_current_y, M_PI_2 - ego_current_heading),
339 2, gradual_change_color, -1);
340 }
341 return true;
342}
343
344bool BirdviewImgFeatureRenderer::RenderObsPastBox(
345 const LearningDataFrame& learning_data_frame, const double current_time_sec,
346 cv::Mat* img_feature, const cv::Scalar& gray_scale,
347 const cv::Scalar& bgr_color) {
348 cv::Scalar color;
349 if ((*img_feature).channels() == 3) {
350 color = bgr_color;
351 } else {
352 color = gray_scale;
353 }
354
355 for (const auto& obstacle : learning_data_frame.obstacle()) {
356 if (obstacle.obstacle_trajectory().evaluated_trajectory_point_size() == 0) {
357 continue;
358 }
359 const double obstacle_box_length = obstacle.length();
360 const double obstacle_box_width = obstacle.width();
361 const auto& past_traj =
362 obstacle.obstacle_trajectory().evaluated_trajectory_point();
363 cv::Scalar gradual_change_color;
364 for (const auto& traj_point : past_traj) {
365 const double relative_time =
366 current_time_sec - traj_point.timestamp_sec();
367 if (relative_time > config_.max_obs_past_horizon()) {
368 continue;
369 }
370 gradual_change_color =
371 color * (1 - relative_time / config_.max_obs_past_horizon());
372 const auto& path_point = traj_point.trajectory_point().path_point();
373 std::vector<cv::Point2i> box_corner_points = GetAffinedBoxImgIdx(
374 path_point.x(), path_point.y(), M_PI_2 + path_point.theta(),
375 {
376 std::make_pair(obstacle_box_length / 2, obstacle_box_width / 2),
377 std::make_pair(obstacle_box_length / 2, -obstacle_box_width / 2),
378 std::make_pair(-obstacle_box_length / 2, -obstacle_box_width / 2),
379 std::make_pair(-obstacle_box_length / 2, obstacle_box_width / 2),
380 },
381 0.0, 0.0, M_PI_2);
382 cv::fillPoly(
383 *img_feature,
384 std::vector<std::vector<cv::Point>>({std::move(box_corner_points)}),
385 color);
386 }
387 }
388
389 return true;
390}
391
392bool BirdviewImgFeatureRenderer::RenderObsFutureBox(
393 const LearningDataFrame& learning_data_frame, const double current_time_sec,
394 cv::Mat* img_feature, const cv::Scalar& gray_scale,
395 const cv::Scalar& bgr_color) {
396 cv::Scalar color;
397 if ((*img_feature).channels() == 3) {
398 color = bgr_color;
399 } else {
400 color = gray_scale;
401 }
402
403 for (const auto& obstacle : learning_data_frame.obstacle()) {
404 const double obstacle_box_length = obstacle.length();
405 const double obstacle_box_width = obstacle.width();
406
407 if (obstacle.obstacle_prediction().is_static()) {
408 const auto& past_traj_points_size =
409 obstacle.obstacle_trajectory().evaluated_trajectory_point_size();
410 if (past_traj_points_size == 0) {
411 AERROR << "obstacle[" << obstacle.id()
412 << "] is static without tracking history points";
413 return false;
414 }
415 const auto& last_past_traj_point =
416 obstacle.obstacle_trajectory().evaluated_trajectory_point(
417 past_traj_points_size - 1);
418 const auto& path_point =
419 last_past_traj_point.trajectory_point().path_point();
420 std::vector<cv::Point2i> box_corner_points = GetAffinedBoxImgIdx(
421 path_point.x(), path_point.y(), M_PI_2 + path_point.theta(),
422 {
423 std::make_pair(obstacle_box_length / 2, obstacle_box_width / 2),
424 std::make_pair(obstacle_box_length / 2, -obstacle_box_width / 2),
425 std::make_pair(-obstacle_box_length / 2, -obstacle_box_width / 2),
426 std::make_pair(-obstacle_box_length / 2, obstacle_box_width / 2),
427 },
428 0.0, 0.0, M_PI_2);
429 cv::fillPoly(
430 *img_feature,
431 std::vector<std::vector<cv::Point>>({std::move(box_corner_points)}),
432 color);
433 continue;
434 }
435
436 const auto& predicted_traj_size =
437 obstacle.obstacle_prediction().trajectory_size();
438 if (predicted_traj_size == 0) {
439 AWARN << "obstacle[" << obstacle.id() << "] has no prediction trajectory";
440 continue;
441 }
442
443 int max_prob = 0;
444 int max_prob_idx = 0;
445 for (int i = 0; i < predicted_traj_size; ++i) {
446 const auto& trajectory = obstacle.obstacle_prediction().trajectory(i);
447 if (trajectory.probability() > max_prob) {
448 max_prob = trajectory.probability();
449 max_prob_idx = i;
450 }
451 }
452
453 const auto& predicted_traj = obstacle.obstacle_prediction()
454 .trajectory(max_prob_idx)
455 .trajectory_point();
456 cv::Scalar gradual_change_color;
457 for (const auto& traj_point : predicted_traj) {
458 const double relative_time =
459 traj_point.timestamp_sec() - current_time_sec;
460 if (relative_time > config_.max_obs_future_horizon()) {
461 break;
462 }
463 gradual_change_color =
464 color * relative_time / config_.max_obs_past_horizon();
465 const auto& path_point = traj_point.trajectory_point().path_point();
466 std::vector<cv::Point2i> box_corner_points = GetAffinedBoxImgIdx(
467 path_point.x(), path_point.y(), M_PI_2 + path_point.theta(),
468 {
469 std::make_pair(obstacle_box_length / 2, obstacle_box_width / 2),
470 std::make_pair(obstacle_box_length / 2, -obstacle_box_width / 2),
471 std::make_pair(-obstacle_box_length / 2, -obstacle_box_width / 2),
472 std::make_pair(-obstacle_box_length / 2, obstacle_box_width / 2),
473 },
474 0.0, 0.0, M_PI_2);
475 cv::fillPoly(
476 *img_feature,
477 std::vector<std::vector<cv::Point>>({std::move(box_corner_points)}),
478 color);
479 }
480 }
481 return true;
482}
483
484bool BirdviewImgFeatureRenderer::RenderTrafficLight(
485 const LearningDataFrame& learning_data_frame, const double ego_current_x,
486 const double ego_current_y, const double ego_current_heading,
487 cv::Mat* img_feature, const cv::Scalar& gray_scale,
488 const cv::Scalar& bgr_color) {
489 cv::Scalar color;
490 if ((*img_feature).channels() == 3) {
491 color = bgr_color;
492 } else {
493 color = gray_scale;
494 }
495 for (const auto& traffic_light_status :
496 learning_data_frame.traffic_light_detection().traffic_light()) {
497 const auto& traffic_light =
499 hdmap::MakeMapId(traffic_light_status.id()));
500 if (traffic_light == nullptr) {
501 AERROR << "traffic_light [" << traffic_light_status.id() << "] not found";
502 return false;
503 }
504 if (traffic_light_status.color() == perception::TrafficLight::RED) {
505 color = cv::Scalar(255);
506 } else if (traffic_light_status.color() ==
508 color = cv::Scalar(192);
509 } else {
510 color = cv::Scalar(128);
511 }
512 for (const auto& overlap_id : traffic_light->signal().overlap_id()) {
513 const auto& overlap =
515 if (overlap == nullptr) {
516 AERROR << "overlap [" << overlap_id.id() << "] not found";
517 return false;
518 }
519 for (const auto& overlap_object : overlap->overlap().object()) {
520 if (!overlap_object.has_lane_overlap_info()) {
521 continue;
522 }
524 overlap_object.id());
525 if (lane == nullptr) {
526 AERROR << "lane [" << overlap_object.id().id() << "] not found";
527 return false;
528 }
529 for (const auto& segment : lane->lane().central_curve().segment()) {
530 const int segment_point_size = segment.line_segment().point_size();
531 for (int i = 0; i < segment_point_size - 1; ++i) {
532 const auto& p0 = GetAffinedPointImgIdx(
533 segment.line_segment().point(i).x(),
534 segment.line_segment().point(i).y(), ego_current_x,
535 ego_current_y, M_PI_2 - ego_current_heading);
536 const auto& p1 = GetAffinedPointImgIdx(
537 segment.line_segment().point(i + 1).x(),
538 segment.line_segment().point(i + 1).y(), ego_current_x,
539 ego_current_y, M_PI_2 - ego_current_heading);
540 cv::line(*img_feature, p0, p1, color, 4);
541 }
542 }
543 }
544 }
545 }
546
547 return true;
548}
549
550bool BirdviewImgFeatureRenderer::RenderRouting(
551 const LearningDataFrame& learning_data_frame, const double ego_current_x,
552 const double ego_current_y, const double ego_current_heading,
553 cv::Mat* img_feature, const cv::Scalar& gray_scale,
554 const cv::Scalar& bgr_color) {
555 cv::Scalar color;
556 if ((*img_feature).channels() == 3) {
557 color = bgr_color;
558 } else {
559 color = gray_scale;
560 }
561
562 const int routing_lanes_size =
563 learning_data_frame.routing().local_routing_lane_id_size();
564 if (routing_lanes_size == 0) {
565 AERROR << "routing is empty";
566 return false;
567 }
568
569 cv::Scalar color_gradient = color / routing_lanes_size;
570 for (int i = 0; i < routing_lanes_size; ++i) {
571 const cv::Scalar routing_color = color - color_gradient * i;
572 const auto& lane =
574 learning_data_frame.routing().local_routing_lane_id(i)));
575 if (lane == nullptr) {
576 AERROR << "lane ["
577 << learning_data_frame.routing().local_routing_lane_id(i)
578 << "] not found";
579 return false;
580 }
581 for (const auto& segment : lane->lane().central_curve().segment()) {
582 const int segment_point_size = segment.line_segment().point_size();
583 for (int i = 0; i < segment_point_size - 1; ++i) {
584 const auto& p0 = GetAffinedPointImgIdx(
585 segment.line_segment().point(i).x(),
586 segment.line_segment().point(i).y(), ego_current_x, ego_current_y,
587 M_PI_2 - ego_current_heading);
588 const auto& p1 = GetAffinedPointImgIdx(
589 segment.line_segment().point(i + 1).x(),
590 segment.line_segment().point(i + 1).y(), ego_current_x,
591 ego_current_y, M_PI_2 - ego_current_heading);
592 cv::line(*img_feature, p0, p1, routing_color, 12);
593 }
594 }
595 }
596 return true;
597}
598
599bool BirdviewImgFeatureRenderer::CropByPose(const double ego_x,
600 const double ego_y,
601 const double ego_heading,
602 const cv::Mat& base_map,
603 cv::Mat* img_feature) {
604 // use dimension of base_roadmap_img as it's assumed that all base maps have
605 // the same size
606 cv::Point2i ego_img_idx = GetPointImgIdx(ego_x - map_bottom_left_point_x_,
607 ego_y - map_bottom_left_point_y_, 0,
608 base_roadmap_img_.size[0]);
609 if (ego_img_idx.x < 0 || ego_img_idx.x + 1 > base_roadmap_img_.size[1] ||
610 ego_img_idx.y < 0 || ego_img_idx.y + 1 > base_roadmap_img_.size[0]) {
611 AERROR << "ego vehicle position out of bound of base map";
612 return false;
613 }
614
615 const int rough_radius = static_cast<int>(sqrt(
616 config_.height() * config_.height() + config_.width() * config_.width()));
617 if (ego_img_idx.x - rough_radius < 0 || ego_img_idx.y - rough_radius < 0) {
618 AERROR << "cropping out of bound of base map";
619 return false;
620 }
621
622 cv::Rect rough_rect(ego_img_idx.x - rough_radius,
623 ego_img_idx.y - rough_radius, 2 * rough_radius,
624 2 * rough_radius);
625 cv::Mat rotation_matrix =
626 cv::getRotationMatrix2D(cv::Point2i(rough_radius, rough_radius),
627 90.0 - ego_heading * 180.0 / M_PI, 1.0);
628 cv::Mat rotated_mat;
629 cv::warpAffine(base_map(rough_rect), rotated_mat, rotation_matrix,
630 base_map(rough_rect).size());
631
632 cv::Rect fine_rect(rough_radius - config_.ego_idx_x(),
633 rough_radius - config_.ego_idx_y(), config_.height(),
634 config_.width());
635
636 rotated_mat(fine_rect).copyTo(*img_feature);
637 return true;
638}
639
640cv::Point2i BirdviewImgFeatureRenderer::GetPointImgIdx(
641 const double local_point_x, const double local_point_y,
642 const int center_point_idx_x, const int center_point_idx_y) {
643 return cv::Point2i(
644 center_point_idx_x +
645 static_cast<int>(local_point_x / config_.resolution()),
646 center_point_idx_y -
647 static_cast<int>(local_point_y / config_.resolution()));
648}
649
650cv::Point2i BirdviewImgFeatureRenderer::GetAffinedPointImgIdx(
651 const double point_x, const double point_y, const double center_x,
652 const double center_y, const double theta) {
653 const double local_x = point_x - center_x;
654 const double local_y = point_y - center_y;
655
656 const double rotated_local_x = local_x * cos(theta) - local_y * sin(theta);
657 const double rotated_local_y = local_x * sin(theta) + local_y * cos(theta);
658
659 return GetPointImgIdx(rotated_local_x, rotated_local_y, config_.ego_idx_x(),
660 config_.ego_idx_y());
661}
662
663std::vector<cv::Point2i> BirdviewImgFeatureRenderer::GetAffinedBoxImgIdx(
664 const double box_center_x, const double box_center_y,
665 const double box_theta,
666 const std::vector<std::pair<double, double>>& box_corner_points,
667 const double center_x, const double center_y, const double theta) {
668 const double local_box_center_x = box_center_x - center_x;
669 const double local_box_center_y = box_center_y - center_y;
670
671 const double affined_local_box_center_x =
672 local_box_center_x * cos(theta) - local_box_center_y * sin(theta);
673 const double affined_local_box_center_y =
674 local_box_center_x * sin(theta) + local_box_center_y * cos(theta);
675
676 std::vector<cv::Point2i> affined_box;
677
678 for (const auto& point : box_corner_points) {
679 const double affined_corner_x = point.first * cos(box_theta) -
680 point.second * sin(box_theta) +
681 affined_local_box_center_x;
682 const double affined_corner_y = point.first * sin(box_theta) +
683 point.second * cos(box_theta) +
684 affined_local_box_center_y;
685 affined_box.push_back(GetPointImgIdx(affined_corner_x, affined_corner_y,
686 config_.ego_idx_x(),
687 config_.ego_idx_y()));
688 }
689
690 return affined_box;
691}
692
693} // namespace planning
694} // namespace apollo
Define the birdview img feature renderer class
static const VehicleConfig & GetConfig()
Get the current vehicle configuration.
static const HDMap & BaseMap()
LaneInfoConstPtr GetLaneById(const Id &id) const
Definition hdmap.cc:34
OverlapInfoConstPtr GetOverlapById(const Id &id) const
Definition hdmap.cc:74
SignalInfoConstPtr GetSignalById(const Id &id) const
Definition hdmap.cc:46
bool RenderBGREnv(const LearningDataFrame &learning_data_frame, cv::Mat *img_feature)
generate bgr img as input feature for certain model
bool RenderCurrentEgoPoint(const LearningDataFrame &learning_data_frame, cv::Mat *img_feature)
generate a single channel img
bool Init(const PlanningSemanticMapConfig &config)
initialize renderer
bool RenderCurrentEgoBox(const LearningDataFrame &learning_data_frame, cv::Mat *img_feature)
generate a single channel img
bool RenderMultiChannelEnv(const LearningDataFrame &learning_data_frame, cv::Mat *img_feature)
generate multi-channel img as input feature for certain model
bool RenderCurrentEgoStatus(const LearningDataFrame &learning_data_frame, cv::Mat *img_feature)
generate a two channel img, one for cur box, one for cur point
Planning module main class.
#define AERROR
Definition log.h:44
#define AWARN
Definition log.h:43
float cos(Angle16 a)
Definition angle.cc:42
float sin(Angle16 a)
Definition angle.cc:25
unsigned char uchar
Definition common.h:40
apollo::hdmap::Id MakeMapId(const std::string &id)
create a Map ID given a string.
Definition hdmap_util.h:85
class register implement
Definition arena_queue.h:37
optional VehicleParam vehicle_param
repeated ADCTrajectoryPoint adc_trajectory_point