39bool ValidFeatureHistory(
const ObstacleHistory& obstacle_history,
40 const double curr_base_x,
const double curr_base_y) {
41 if (obstacle_history.feature_size() == 0) {
45 double center_x = curr_base_x + FLAGS_base_image_half_range;
46 double center_y = curr_base_y + FLAGS_base_image_half_range;
48 const Feature& feature = obstacle_history.feature(0);
49 double diff_x = feature.position().x() - center_x;
50 double diff_y = feature.position().y() - center_y;
51 double distance = std::hypot(diff_x, diff_y);
52 return distance < FLAGS_caution_distance_threshold;
60 curr_img_ = cv::Mat(2000, 2000, CV_8UC3, cv::Scalar(0, 0, 0));
61 obstacle_id_history_map_.clear();
63 affine_transformer_.Init(cv::Size(2000, 2000), CV_8UC3);
68 const std::unordered_map<int, ObstacleHistory>& obstacle_id_history_map) {
69 if (obstacle_id_history_map.find(FLAGS_ego_vehicle_id) ==
70 obstacle_id_history_map.end()) {
74 ego_feature_ = obstacle_id_history_map.at(FLAGS_ego_vehicle_id).feature(0);
75 if (!FLAGS_enable_async_draw_base_image) {
78 curr_base_x_ = x - FLAGS_base_image_half_range;
79 curr_base_y_ = y - FLAGS_base_image_half_range;
80 DrawBaseMap(x, y, curr_base_x_, curr_base_y_);
81 base_img_.copyTo(curr_img_);
83 base_img_.copyTo(curr_img_);
84 curr_base_x_ = base_x_;
85 curr_base_y_ = base_y_;
86 task_future_ = cyber::Async(&SemanticMap::DrawBaseMapThread,
this);
88 if (!started_drawing_) {
89 started_drawing_ =
true;
95 if (FLAGS_enable_draw_adc_trajectory) {
96 DrawADCTrajectory(cv::Scalar(0, 255, 255),
97 curr_base_x_, curr_base_y_, &curr_img_);
101 for (
const auto obstacle_id_history_pair : obstacle_id_history_map) {
102 DrawHistory(obstacle_id_history_pair.second, cv::Scalar(0, 255, 255),
103 curr_base_x_, curr_base_y_, &curr_img_);
106 obstacle_id_history_map_ = obstacle_id_history_map;
109 if (FLAGS_img_show_semantic_map) {
111 if (
GetMapById(FLAGS_ego_vehicle_id, &output_img)) {
112 cv::namedWindow(
"Demo window", cv::WINDOW_NORMAL);
113 cv::imshow(
"Demo window", output_img);
119void SemanticMap::DrawBaseMap(
const double x,
const double y,
120 const double base_x,
const double base_y) {
121 base_img_ = cv::Mat(2000, 2000, CV_8UC3, cv::Scalar(0, 0, 0));
123 DrawRoads(center_point, base_x, base_y);
124 DrawJunctions(center_point, base_x, base_y);
125 DrawCrosswalks(center_point, base_x, base_y);
126 DrawLanes(center_point, base_x, base_y);
129void SemanticMap::DrawBaseMapThread() {
130 std::lock_guard<std::mutex> lock(draw_base_map_thread_mutex_);
133 base_x_ = x - FLAGS_base_image_half_range;
134 base_y_ = y - FLAGS_base_image_half_range;
135 DrawBaseMap(x, y, base_x_, base_y_);
138void SemanticMap::DrawRoads(
const common::PointENU& center_point,
139 const double base_x,
const double base_y,
140 const cv::Scalar& color) {
141 std::vector<apollo::hdmap::RoadInfoConstPtr> roads;
143 for (
const auto& road : roads) {
144 for (
const auto& section : road->road().section()) {
145 std::vector<cv::Point> polygon;
146 for (
const auto& edge : section.boundary().outer_polygon().edge()) {
147 if (edge.type() == 2) {
148 for (
const auto& segment : edge.curve().segment()) {
149 for (
const auto& point : segment.line_segment().point()) {
150 polygon.push_back(std::move(
151 GetTransPoint(point.x(), point.y(), base_x, base_y)));
154 }
else if (edge.type() == 3) {
155 for (
const auto& segment : edge.curve().segment()) {
156 for (
const auto& point : segment.line_segment().point()) {
157 polygon.insert(polygon.begin(),
158 std::move(GetTransPoint(point.x(), point.y(),
164 cv::fillPoly(base_img_,
165 std::vector<std::vector<cv::Point>>({std::move(polygon)}),
171void SemanticMap::DrawJunctions(
const common::PointENU& center_point,
172 const double base_x,
const double base_y,
173 const cv::Scalar& color) {
174 std::vector<apollo::hdmap::JunctionInfoConstPtr> junctions;
177 for (
const auto& junction : junctions) {
178 std::vector<cv::Point> polygon;
179 for (
const auto& point : junction->junction().polygon().point()) {
181 std::move(GetTransPoint(point.x(), point.y(), base_x, base_y)));
183 cv::fillPoly(base_img_,
184 std::vector<std::vector<cv::Point>>({std::move(polygon)}),
189void SemanticMap::DrawCrosswalks(
const common::PointENU& center_point,
190 const double base_x,
const double base_y,
191 const cv::Scalar& color) {
192 std::vector<apollo::hdmap::CrosswalkInfoConstPtr> crosswalks;
195 for (
const auto& crosswalk : crosswalks) {
196 std::vector<cv::Point> polygon;
197 for (
const auto& point : crosswalk->crosswalk().polygon().point()) {
199 std::move(GetTransPoint(point.x(), point.y(), base_x, base_y)));
201 cv::fillPoly(base_img_,
202 std::vector<std::vector<cv::Point>>({std::move(polygon)}),
207void SemanticMap::DrawLanes(
const common::PointENU& center_point,
208 const double base_x,
const double base_y,
209 const cv::Scalar& color) {
210 std::vector<apollo::hdmap::LaneInfoConstPtr> lanes;
212 for (
const auto& lane : lanes) {
214 for (
const auto& segment : lane->lane().central_curve().segment()) {
215 for (
int i = 0; i < segment.line_segment().point_size() - 1; ++i) {
217 GetTransPoint(segment.line_segment().point(i).x(),
218 segment.line_segment().point(i).y(), base_x, base_y);
219 const auto& p1 = GetTransPoint(segment.line_segment().point(i + 1).x(),
220 segment.line_segment().point(i + 1).y(),
222 double theta = atan2(segment.line_segment().point(i + 1).y() -
223 segment.line_segment().point(i).y(),
224 segment.line_segment().point(i + 1).x() -
225 segment.line_segment().point(i).x());
226 double H = theta >= 0 ? theta / (2 * M_PI) : theta / (2 * M_PI) + 1;
235 cv::line(base_img_, p0, p1, HSVtoRGB(H), 4);
239 if (lane->lane().type() == 2 && lane->lane().left_boundary().virtual_() &&
240 lane->lane().right_boundary().virtual_()) {
244 for (
const auto& segment : lane->lane().left_boundary().curve().segment()) {
245 for (
int i = 0; i < segment.line_segment().point_size() - 1; ++i) {
247 GetTransPoint(segment.line_segment().point(i).x(),
248 segment.line_segment().point(i).y(), base_x, base_y);
249 const auto& p1 = GetTransPoint(segment.line_segment().point(i + 1).x(),
250 segment.line_segment().point(i + 1).y(),
252 cv::line(base_img_, p0, p1, color, 2);
256 for (
const auto& segment :
257 lane->lane().right_boundary().curve().segment()) {
258 for (
int i = 0; i < segment.line_segment().point_size() - 1; ++i) {
260 GetTransPoint(segment.line_segment().point(i).x(),
261 segment.line_segment().point(i).y(), base_x, base_y);
262 const auto& p1 = GetTransPoint(segment.line_segment().point(i + 1).x(),
263 segment.line_segment().point(i + 1).y(),
265 cv::line(base_img_, p0, p1, color, 2);
271cv::Scalar SemanticMap::HSVtoRGB(
double H,
double S,
double V) {
272 int I =
static_cast<int>(floor(H * 6.0));
273 double F = H * 6.0 - floor(H * 6.0);
274 double M = V * (1.0 - S);
275 double N = V * (1.0 - S * F);
276 double K = V * (1.0 - S * (1.0 - F));
279 return cv::Scalar(V, K, M) * 255.0;
281 return cv::Scalar(N, V, M) * 255.0;
283 return cv::Scalar(M, V, K) * 255.0;
285 return cv::Scalar(M, N, V) * 255.0;
287 return cv::Scalar(K, M, V) * 255.0;
289 return cv::Scalar(V, M, N) * 255.0;
293void SemanticMap::DrawRect(
const Feature& feature,
const cv::Scalar& color,
294 const double base_x,
const double base_y,
296 double obs_l = feature.length();
297 double obs_w = feature.width();
298 double obs_x = feature.position().x();
299 double obs_y = feature.position().y();
300 double theta = feature.theta();
301 std::vector<cv::Point> polygon;
303 polygon.push_back(std::move(GetTransPoint(
304 obs_x + (
cos(theta) * obs_l -
sin(theta) * obs_w) / 2,
305 obs_y + (
sin(theta) * obs_l +
cos(theta) * obs_w) / 2, base_x, base_y)));
307 polygon.push_back(std::move(GetTransPoint(
308 obs_x + (
cos(theta) * -obs_l -
sin(theta) * obs_w) / 2,
309 obs_y + (
sin(theta) * -obs_l +
cos(theta) * obs_w) / 2, base_x, base_y)));
311 polygon.push_back(std::move(
312 GetTransPoint(obs_x + (
cos(theta) * -obs_l -
sin(theta) * -obs_w) / 2,
313 obs_y + (
sin(theta) * -obs_l +
cos(theta) * -obs_w) / 2,
316 polygon.push_back(std::move(GetTransPoint(
317 obs_x + (
cos(theta) * obs_l -
sin(theta) * -obs_w) / 2,
318 obs_y + (
sin(theta) * obs_l +
cos(theta) * -obs_w) / 2, base_x, base_y)));
319 cv::fillPoly(*img, std::vector<std::vector<cv::Point>>({std::move(polygon)}),
323void SemanticMap::DrawPoly(
const Feature& feature,
const cv::Scalar& color,
324 const double base_x,
const double base_y,
326 std::vector<cv::Point> polygon;
327 for (
auto& polygon_point : feature.polygon_point()) {
328 polygon.push_back(std::move(
329 GetTransPoint(polygon_point.x(), polygon_point.y(), base_x, base_y)));
331 cv::fillPoly(*img, std::vector<std::vector<cv::Point>>({std::move(polygon)}),
335void SemanticMap::DrawHistory(
const ObstacleHistory& history,
336 const cv::Scalar& color,
const double base_x,
337 const double base_y, cv::Mat* img) {
338 for (
int i = history.feature_size() - 1; i >= 0; --i) {
339 const Feature& feature = history.feature(i);
340 double time_decay = 1.0 - ego_feature_.
timestamp() + feature.timestamp();
341 cv::Scalar decay_color = color * time_decay;
342 if (feature.id() == FLAGS_ego_vehicle_id) {
343 DrawRect(feature, decay_color, base_x, base_y, img);
345 if (feature.polygon_point_size() == 0) {
346 AERROR <<
"No polygon points in feature, please check!";
349 DrawPoly(feature, decay_color, base_x, base_y, img);
354void SemanticMap::DrawADCTrajectory(
const cv::Scalar& color,
359 for (
size_t i = 0; i < traj_num; ++i) {
362 cv::Scalar decay_color = color * time_decay;
363 DrawPoly(ego_feature_, decay_color, base_x, base_y, img);
367cv::Mat SemanticMap::CropArea(
const cv::Mat& input_img,
368 const cv::Point2i& center_point,
369 const double heading) {
372 affine_transformer_.AffineTransformsFromMat(input_img,
373 center_point, heading, 1.0, &rotated_mat);
375 cv::Mat rotation_mat =
376 cv::getRotationMatrix2D(center_point, 90.0 - heading * 180.0 / M_PI, 1.0);
377 cv::warpAffine(input_img, rotated_mat, rotation_mat, input_img.size());
379 cv::Rect rect(center_point.x - 200, center_point.y - 300, 400, 400);
381 cv::resize(rotated_mat(rect), output_img, cv::Size(224, 224));
385cv::Mat SemanticMap::CropByHistory(
const ObstacleHistory& history,
386 const cv::Scalar& color,
const double base_x,
387 const double base_y) {
388 cv::Mat feature_map = curr_img_.clone();
389 DrawHistory(history, color, base_x, base_y, &feature_map);
390 const Feature& curr_feature = history.feature(0);
391 const cv::Point2i& center_point = GetTransPoint(
392 curr_feature.position().x(), curr_feature.position().y(), base_x, base_y);
393 return CropArea(feature_map, center_point, curr_feature.theta());
397 if (obstacle_id_history_map_.find(obstacle_id) ==
398 obstacle_id_history_map_.end()) {
401 const auto& obstacle_history = obstacle_id_history_map_[obstacle_id];
403 if (!ValidFeatureHistory(obstacle_history, curr_base_x_, curr_base_y_)) {
408 CropByHistory(obstacle_id_history_map_[obstacle_id],
409 cv::Scalar(0, 0, 255), curr_base_x_, curr_base_y_);
410 output_img.copyTo(*feature_map);
static PointENU ToPointENU(const double x, const double y, const double z=0)
static const HDMap & BaseMap()
int GetCrosswalks(const apollo::common::PointENU &point, double distance, std::vector< CrosswalkInfoConstPtr > *crosswalks) const
get all crosswalks in certain range
int GetLanes(const apollo::common::PointENU &point, double distance, std::vector< LaneInfoConstPtr > *lanes) const
get all lanes in certain range
int GetRoads(const apollo::common::PointENU &point, double distance, std::vector< RoadInfoConstPtr > *roads) const
get all roads in certain range
int GetJunctions(const apollo::common::PointENU &point, double distance, std::vector< JunctionInfoConstPtr > *junctions) const
get all junctions in certain range
void RunCurrFrame(const std::unordered_map< int, ObstacleHistory > &obstacle_id_history_map)
bool GetMapById(const int obstacle_id, cv::Mat *feature_map)
Use container manager to manage all containers
Some string util functions.
optional double relative_time
optional double timestamp
repeated apollo::common::TrajectoryPoint adc_trajectory_point
optional apollo::common::Point3D position