Apollo 10.0
自动驾驶开放平台
laps_checker.cc
浏览该文件的文档.
1/******************************************************************************
2 * Copyright 2019 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 *****************************************************************************/
17
18#include <algorithm>
19#include <cmath>
20#include <fstream>
21#include <iostream>
22#include <limits>
23
24#include <boost/property_tree/json_parser.hpp>
25#include <boost/property_tree/ptree.hpp>
26
27namespace apollo {
28namespace hdmap {
29
30LapsChecker::LapsChecker(const std::vector<FramePose> &poses, int laps_to_check,
31 std::shared_ptr<JsonConf> sp_conf)
32 : poses_(poses), sp_conf_(sp_conf) {
33 laps_to_check_ = laps_to_check;
34 maxx_ = 0.0;
35 maxy_ = 0.0;
36 minx_ = 0.0;
37 miny_ = 0.0;
38 possible_max_laps_ = (laps_to_check_ + 1) * 10;
39 confidence_.resize(possible_max_laps_ + 1, 0.0);
40 finished_ = false;
41 return_state_ = ErrorCode::SUCCESS;
42 AINFO << "instance has " << poses.size() << " poses";
43 AINFO << "confidence size: " << possible_max_laps_ + 1;
44}
45
46int LapsChecker::SetProgress(double p) {
47 progress_ = p;
48 return 0;
49}
50
51double LapsChecker::GetProgress() const { return progress_; }
52
53size_t LapsChecker::GetLap() const { return lap_; }
54
56 double res = 0.0;
57 lap_ = laps_to_check_;
58 for (size_t i = 0; i < confidence_.size(); ++i) {
59 AINFO << "confidence[" << i << "]: " << confidence_[i];
60 }
61 AINFO << "laps to check: " << laps_to_check_;
62 for (size_t i = laps_to_check_; i < confidence_.size(); ++i) {
63 res += confidence_[i];
64 }
65 AINFO << "current confidence: " << res
66 << ",confidence thresh:" << sp_conf_->laps_rate_thresh;
67 if (res < sp_conf_->laps_rate_thresh) {
68 if (confidence_.empty()) {
69 AINFO << "some problems induce lap problem";
70 return 0.0;
71 }
72 res = confidence_[0];
73 lap_ = 0;
74 for (size_t i = 1; i < confidence_.size(); ++i) {
75 if (i == laps_to_check_) {
76 continue;
77 }
78 if (confidence_[i] > res) {
79 lap_ = i;
80 res = confidence_[i];
81 }
82 }
83 }
84 return res;
85}
86
88 if (poses_.empty()) {
90 return return_state_;
91 }
92 DoCheck();
93 finished_ = true;
94 return return_state_;
95}
96
97void LapsChecker::DoCheck() {
98 AINFO << "do_check";
99 SetProgress(0.0);
100 int ret = 0;
101 AINFO << "check->check_params";
102 ret = CheckParams();
103 if (ret < 0) {
104 AINFO << "check_params failed";
105 }
106 SetProgress(0.1);
107
108 AINFO << "check->setup_grids_map";
109 ret = SetupGridsMap();
110 if (ret < 0) {
111 AINFO << "setup_grids_map failed";
112 }
113 SetProgress(0.5);
114 AINFO << "check->setup_grids_map done";
115
116 AINFO << "check->check_laps";
117 ret = CheckLaps();
118 if (ret < 0) {
119 AINFO << "check_laps failed";
120 }
121 SetProgress(1.0);
122 AINFO << "check->check_laps done";
123
124 AINFO << "do_check done";
125}
126
127int LapsChecker::CheckParams() {
128 int n_pose = static_cast<int>(poses_.size());
129 if (n_pose < sp_conf_->laps_frames_thresh) {
130 return -1;
131 }
132 return 0;
133}
134
135int LapsChecker::SetupGridsMap() {
136 AINFO << "setup_grids_map->get_min_max";
137 GetMinMax();
138 AINFO << "setup_grids_map->do_setup_grids_map";
139 int ret = DoSetupGridsMap();
140 if (ret < 0) {
141 AINFO << "do_setup_grids_map failed";
142 return -1;
143 }
144 AINFO << "setup_grids_map done";
145 return 0;
146}
147
148int LapsChecker::CheckLaps() {
149 int height = static_cast<int>(grids_map_.size());
150 if (height <= 2 || height > 1000000) {
151 AINFO << "grids_map_ size error. height = " << height;
152 return -1;
153 }
154
155 int width = static_cast<int>(grids_map_[0].size());
156 if (width <= 2 || width >= 1000000) {
157 AINFO << "grids_map_ size error. width = " << width;
158 return -1;
159 }
160
161 for (int y = 0; y < height; y++) {
162 for (int x = 0; x < width; x++) {
163 Grid &grid = grids_map_[y][x];
164 size_t t_size = grid.size();
165 if (t_size == 0) {
166 continue;
167 }
168 for (size_t i = 0; i < t_size; ++i) {
169 std::vector<double> stamps;
170 GatherTimestamps(&stamps, grid[i].alpha, x, y);
171 if (stamps.empty()) {
172 continue;
173 }
174 std::sort(stamps.begin(), stamps.end());
175 double thresh_in_sec = sp_conf_->laps_time_err_thresh * 60;
176 size_t segment = 1;
177 for (size_t j = 1; j < stamps.size(); ++j) {
178 if (stamps[j] - stamps[j - 1] > thresh_in_sec) {
179 segment++;
180 }
181 }
182 if (segment <= possible_max_laps_) {
183 confidence_[segment] += 1;
184 }
185 }
186 }
187 }
188
189 double all = 0.0;
190 for (size_t i = 0; i < confidence_.size(); ++i) {
191 all += confidence_[i];
192 }
193 if (all == 0.0) {
194 AINFO << "there seems no poses";
195 return -1;
196 }
197 AINFO << "confidence size: " << confidence_.size();
198 for (size_t i = 0; i < confidence_.size(); ++i) {
199 confidence_[i] /= all;
200 }
201
202 return 0;
203}
204
205int LapsChecker::GatherTimestamps(std::vector<double> *sp_stamps, double alpha,
206 int center_x, int center_y) {
207 int search_d = sp_conf_->laps_search_diameter;
208 if ((search_d & 1) == 0) {
209 AINFO << "laps_search_diameter should be an odd";
210 return -1;
211 }
212 int search_r = (search_d >> 1);
213 size_t height = grids_map_.size(), width = grids_map_[0].size();
214 std::vector<double> &stamps = *sp_stamps;
215 stamps.clear();
216 const size_t start_y = std::max(0, center_y - search_r);
217 const size_t end_y =
218 std::min(static_cast<int>(height) - 1, center_y + search_r);
219 const size_t start_x = std::max(0, center_x - search_r);
220 const size_t end_x =
221 std::min(static_cast<int>(width) - 1, center_x + search_r);
222 for (size_t y = start_y; y <= end_y; y++) {
223 for (size_t x = start_x; x <= end_x; x++) {
224 Grid &grid = grids_map_[y][x];
225 for (size_t i = 0; i < grid.size(); ++i) {
226 if (std::abs(alpha - grid[i].alpha) < sp_conf_->laps_alpha_err_thresh) {
227 std::vector<int> &idxs = grid[i].idxs;
228 for (size_t j = 0; j < idxs.size(); ++j) {
229 if (idxs[j] >= static_cast<int>(poses_.size())) {
230 AINFO << "index error, index: " << idxs[j]
231 << ", pose size: " << poses_.size();
232 } else {
233 stamps.push_back(poses_[idxs[j]].time_stamp);
234 }
235 }
236 }
237 }
238 }
239 }
240
241 return 0;
242}
243
244int LapsChecker::GetMinMax() {
245 minx_ = std::numeric_limits<double>::max();
246 miny_ = std::numeric_limits<double>::max();
247 maxx_ = std::numeric_limits<double>::min();
248 maxy_ = std::numeric_limits<double>::min();
249 size_t size = poses_.size();
250 AINFO << "get_min_max pose size: " << size;
251 for (size_t i = 0; i < size; ++i) {
252 double tx = poses_[i].tx, ty = poses_[i].ty;
253 if (tx < minx_) {
254 minx_ = tx;
255 }
256 if (tx > maxx_) {
257 maxx_ = tx;
258 }
259 if (ty < miny_) {
260 miny_ = ty;
261 }
262 if (ty > maxy_) {
263 maxy_ = ty;
264 }
265 }
266 return 0;
267}
268
269int LapsChecker::DoSetupGridsMap() {
270 size_t width = size_t(maxx_ - minx_ + 1);
271 size_t height = size_t(maxy_ - miny_ + 1);
272 AINFO << "grid map width: " << width << ", height: " << height;
273 size_t size = poses_.size();
274 if (1 >= size || 0 == height || 0 == width || height > 1000000 ||
275 width > 1000000) {
276 AINFO << "pose size: " << size << ", height: " << height
277 << ", width: " << width;
278 AINFO << "pose size error or grid map size error";
279 return -1;
280 }
281
282 grids_map_.resize(height);
283 for (size_t i = 0; i < height; ++i) {
284 grids_map_[i].resize(width);
285 }
286 // first pose can not be used
287 for (size_t i = 1; i < size; ++i) {
288 int x = static_cast<int>(poses_[i].tx - minx_);
289 int y = static_cast<int>(poses_[i].ty - miny_);
290 PutPoseToGrid(static_cast<int>(i), y, x);
291 PutPoseToNeighborGrid(static_cast<int>(i));
292 }
293 return 0;
294}
295
296double LapsChecker::CalcAlpha(int pose_index) {
297 double vecx = poses_[pose_index].tx - poses_[pose_index - 1].tx;
298 double vecy = poses_[pose_index].ty - poses_[pose_index - 1].ty;
299 double alpha = acos(vecx / sqrt(vecx * vecx + vecy * vecy)) * 180 / M_PI;
300 if (alpha > 0) {
301 return alpha;
302 }
303 return 360 + alpha;
304}
305
306int LapsChecker::PutPoseToGrid(int pose_index, int grid_y, int grid_x) {
307 if (pose_index <= 0) {
308 return 0;
309 }
310 double alpha = CalcAlpha(pose_index);
311 if (std::isnan(alpha)) {
312 AERROR << "ignore static pose " << pose_index;
313 return 0;
314 }
315
316 Grid &grid = grids_map_[grid_y][grid_x];
317 size_t t_size = grid.size();
318 for (size_t j = 0; j < t_size; ++j) {
319 if (std::abs(alpha - grid[j].alpha) < sp_conf_->laps_alpha_err_thresh) {
320 grid[j].idxs.push_back(pose_index);
321 grid[j].alpha = (grid[j].alpha + alpha) / 2;
322 return 0;
323 }
324 }
325
326 GridMeta gm;
327 gm.alpha = alpha;
328 gm.idxs = {pose_index};
329 grid.push_back(gm);
330 return 0;
331}
332
333int LapsChecker::PutPoseToNeighborGrid(int pose_index) {
334 if (pose_index <= 0) {
335 return 0;
336 }
337 std::vector<int> x, y;
338 GetPassedGrid(pose_index, &x, &y);
339 for (size_t i = 0; i < x.size(); ++i) {
340 PutPoseToGrid(pose_index, y[i], x[i]);
341 }
342 return 0;
343}
344
345int LapsChecker::GetPassedGrid(int pose_index, std::vector<int> *sp_grid_x,
346 std::vector<int> *sp_grid_y) {
347 if (pose_index <= 0) {
348 return 0;
349 }
350 std::vector<int> &grid_x = *sp_grid_x;
351 std::vector<int> &grid_y = *sp_grid_y;
352 grid_x.clear();
353 grid_y.clear();
354 double x = poses_[pose_index].tx - minx_;
355 double y = poses_[pose_index].ty - miny_;
356 double last_x = poses_[pose_index - 1].tx - minx_;
357 double last_y = poses_[pose_index - 1].ty - miny_;
358 if (std::abs(x - last_x) < 1e-6) { // current trace is vertical
359 int start_y = static_cast<int>(std::min(y, last_y)) + 1;
360 int end_y = static_cast<int>(std::max(y, last_y));
361 int start_x = static_cast<int>(x);
362 while ((start_y++) < end_y) {
363 grid_x.push_back(start_x);
364 grid_y.push_back(start_y);
365 }
366 } else if (std::abs(y - last_y) < 1e-6) { // current trace is horizontal
367 int start_x = static_cast<int>(std::min(x, last_x));
368 int end_x = static_cast<int>(std::max(x, last_x));
369 int start_y = static_cast<int>(y);
370 while ((++start_x) < end_x) {
371 grid_x.push_back(start_x);
372 grid_y.push_back(start_y);
373 }
374 } else {
375 double k = Slope(last_x, last_y, x, y);
376 if (k > 99999999.0) {
377 AERROR << "slope error";
378 return -1;
379 }
380 int steps = static_cast<int>(std::abs(last_x - x));
381 int step = 0;
382 double xx = 0.0, yy = 0.0;
383 if (x < last_x) {
384 xx = x, yy = y;
385 } else {
386 xx = last_x, yy = last_y;
387 }
388 while ((step++) < steps) {
389 xx = xx + 1;
390 yy = yy + k;
391 grid_x.push_back(static_cast<int>(xx));
392 grid_y.push_back(static_cast<int>(yy));
393 }
394 }
395 return 0;
396}
397
398double LapsChecker::Slope(double x1, double y1, double x2, double y2) {
399 if (std::abs(x1 - x2) < 1e-6) {
400 return std::numeric_limits<double>::max();
401 }
402 if (std::abs(y1 - y2) < 1e-6) {
403 return 0.0;
404 }
405 return (y2 - y1) / (x2 - x1);
406}
407
408ErrorCode LapsChecker::GetReturnState() { return return_state_; }
409
410} // namespace hdmap
411} // namespace apollo
Definition grid.h:23
std::vector< std::vector< Grid > > grids_map_
LapsChecker(const std::vector< FramePose > &poses, int laps_to_check, std::shared_ptr< JsonConf > sp_conf)
const std::vector< FramePose > & poses_
#define AERROR
Definition log.h:44
#define AINFO
Definition log.h:42
uint32_t height
Height of point cloud
uint32_t width
Width of point cloud
class register implement
Definition arena_queue.h:37