Apollo 11.0
自动驾驶开放平台
point_pillars.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
17/*
18 * Copyright 2018-2019 Autoware Foundation. All rights reserved.
19 *
20 * Licensed under the Apache License, Version 2.0 (the "License");
21 * you may not use this file except in compliance with the License.
22 * You may obtain a copy of the License at
23 *
24 * http://www.apache.org/licenses/LICENSE-2.0
25 *
26 * Unless required by applicable law or agreed to in writing, software
27 * distributed under the License is distributed on an "AS IS" BASIS,
28 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
29 * See the License for the specific language governing permissions and
30 * limitations under the License.
31 */
32
34
35#include <chrono>
36#include <iostream>
37#include <utility>
38
39#include "cyber/common/log.h"
40
41namespace apollo {
42namespace perception {
43namespace lidar {
44
45const float PointPillars::kPillarXSize = Params::kPillarXSize;
46const float PointPillars::kPillarYSize = Params::kPillarYSize;
47const float PointPillars::kPillarZSize = Params::kPillarZSize;
48const float PointPillars::kMinXRange = Params::kMinXRange;
49const float PointPillars::kMinYRange = Params::kMinYRange;
50const float PointPillars::kMinZRange = Params::kMinZRange;
51const float PointPillars::kMaxXRange = Params::kMaxXRange;
52const float PointPillars::kMaxYRange = Params::kMaxYRange;
53const float PointPillars::kMaxZRange = Params::kMaxZRange;
54const int PointPillars::kNumClass = Params::kNumClass;
55const int PointPillars::kMaxNumPillars = Params::kMaxNumPillars;
56const int PointPillars::kMaxNumPointsPerPillar = Params::kMaxNumPointsPerPillar;
57const int PointPillars::kNumPointFeature = Params::kNumPointFeature;
58const int PointPillars::kGridXSize =
59 static_cast<int>((kMaxXRange - kMinXRange) / kPillarXSize);
60const int PointPillars::kGridYSize =
61 static_cast<int>((kMaxYRange - kMinYRange) / kPillarYSize);
62const int PointPillars::kGridZSize =
63 static_cast<int>((kMaxZRange - kMinZRange) / kPillarZSize);
64const int PointPillars::kRpnInputSize = 64 * kGridXSize * kGridYSize;
65const int PointPillars::kNumAnchor = Params::kNumAnchor;
66const int PointPillars::kNumOutputBoxFeature = Params::kNumOutputBoxFeature;
67const int PointPillars::kRpnBoxOutputSize = kNumAnchor * kNumOutputBoxFeature;
68const int PointPillars::kRpnClsOutputSize = kNumAnchor * kNumClass;
69const int PointPillars::kRpnDirOutputSize = kNumAnchor * 2;
70const int PointPillars::kBatchSize = Params::kBatchSize;
71const int PointPillars::kNumIndsForScan = Params::kNumIndsForScan;
72const int PointPillars::kNumThreads = Params::kNumThreads;
73const int PointPillars::kGridSize = Params::kGridSize;
74const int PointPillars::kNumAnchorPerGrid = Params::kNumAnchorPerGrid;
75// if you change kNumThreads, need to modify NUM_THREADS_MACRO in
76// common.h
77const int PointPillars::kNumBoxCorners = Params::kNumBoxCorners;
78const std::vector<int> PointPillars::kAnchorStrides = Params::AnchorStrides();
79const std::vector<int> PointPillars::kAnchorRanges{
80 0,
81 kGridXSize,
82 0,
83 kGridYSize,
84 static_cast<int>(kGridXSize * 0.25),
85 static_cast<int>(kGridXSize * 0.75),
86 static_cast<int>(kGridYSize * 0.25),
87 static_cast<int>(kGridYSize * 0.75)};
88const std::vector<int> PointPillars::kNumAnchorSets = Params::NumAnchorSets();
89const std::vector<std::vector<float>> PointPillars::kAnchorDxSizes =
91const std::vector<std::vector<float>> PointPillars::kAnchorDySizes =
93const std::vector<std::vector<float>> PointPillars::kAnchorDzSizes =
95const std::vector<std::vector<float>> PointPillars::kAnchorZCoors =
97const std::vector<std::vector<int>> PointPillars::kNumAnchorRo =
99const std::vector<std::vector<float>> PointPillars::kAnchorRo =
101
102PointPillars::PointPillars(const bool reproduce_result_mode,
103 const float score_threshold,
104 const float nms_overlap_threshold,
105 const common::Framework& model_type,
106 const std::string& model_file)
107 : reproduce_result_mode_(reproduce_result_mode),
108 score_threshold_(score_threshold),
109 nms_overlap_threshold_(nms_overlap_threshold),
110 model_type_(model_type),
111 model_file_(model_file) {
112 if (reproduce_result_mode_) {
113 preprocess_points_ptr_.reset(new PreprocessPoints(
114 kMaxNumPillars, kMaxNumPointsPerPillar, kNumPointFeature, kGridXSize,
115 kGridYSize, kGridZSize, kPillarXSize, kPillarYSize, kPillarZSize,
116 kMinXRange, kMinYRange, kMinZRange, kNumIndsForScan));
117 } else {
118 preprocess_points_cuda_ptr_.reset(new PreprocessPointsCuda(
119 kNumThreads, kMaxNumPillars, kMaxNumPointsPerPillar, kNumPointFeature,
120 kNumIndsForScan, kGridXSize, kGridYSize, kGridZSize, kPillarXSize,
121 kPillarYSize, kPillarZSize, kMinXRange, kMinYRange, kMinZRange));
122 }
123
124 anchor_mask_cuda_ptr_.reset(new AnchorMaskCuda(
125 kNumThreads, kNumIndsForScan, kNumAnchor, kMinXRange, kMinYRange,
126 kPillarXSize, kPillarYSize, kGridXSize, kGridYSize));
127
128 const float float_min = std::numeric_limits<float>::lowest();
129 const float float_max = std::numeric_limits<float>::max();
130 postprocess_cuda_ptr_.reset(
131 new PostprocessCuda(float_min, float_max, kNumAnchor, kNumClass,
132 score_threshold_, kNumThreads, nms_overlap_threshold_,
133 kNumBoxCorners, kNumOutputBoxFeature));
134
135 DeviceMemoryMalloc();
136 InitTorch();
137 InitAnchors();
138}
139
141 delete[] anchors_px_;
142 delete[] anchors_py_;
143 delete[] anchors_pz_;
144 delete[] anchors_dx_;
145 delete[] anchors_dy_;
146 delete[] anchors_dz_;
147 delete[] anchors_ro_;
148 delete[] box_anchors_min_x_;
149 delete[] box_anchors_min_y_;
150 delete[] box_anchors_max_x_;
151 delete[] box_anchors_max_y_;
152
153 GPU_CHECK(cudaFree(dev_x_coors_));
154 GPU_CHECK(cudaFree(dev_y_coors_));
155 GPU_CHECK(cudaFree(dev_num_points_per_pillar_));
156 GPU_CHECK(cudaFree(dev_sparse_pillar_map_));
157 GPU_CHECK(cudaFree(dev_pillar_point_feature_));
158 GPU_CHECK(cudaFree(dev_pillar_coors_));
159
160 GPU_CHECK(cudaFree(dev_cumsum_along_x_));
161 GPU_CHECK(cudaFree(dev_cumsum_along_y_));
162
163 GPU_CHECK(cudaFree(dev_box_anchors_min_x_));
164 GPU_CHECK(cudaFree(dev_box_anchors_min_y_));
165 GPU_CHECK(cudaFree(dev_box_anchors_max_x_));
166 GPU_CHECK(cudaFree(dev_box_anchors_max_y_));
167 GPU_CHECK(cudaFree(dev_anchor_mask_));
168
169 GPU_CHECK(cudaFree(pfe_buffers_[0]));
170 GPU_CHECK(cudaFree(pfe_buffers_[1]));
171 GPU_CHECK(cudaFree(pfe_buffers_[2]));
172
173 GPU_CHECK(cudaFree(rpn_buffers_[0]));
174 GPU_CHECK(cudaFree(rpn_buffers_[1]));
175 GPU_CHECK(cudaFree(rpn_buffers_[2]));
176 GPU_CHECK(cudaFree(rpn_buffers_[3]));
177
178 GPU_CHECK(cudaFree(dev_scattered_feature_));
179
180 GPU_CHECK(cudaFree(dev_anchors_px_));
181 GPU_CHECK(cudaFree(dev_anchors_py_));
182 GPU_CHECK(cudaFree(dev_anchors_pz_));
183 GPU_CHECK(cudaFree(dev_anchors_dx_));
184 GPU_CHECK(cudaFree(dev_anchors_dy_));
185 GPU_CHECK(cudaFree(dev_anchors_dz_));
186 GPU_CHECK(cudaFree(dev_anchors_ro_));
187 GPU_CHECK(cudaFree(dev_filtered_box_));
188 GPU_CHECK(cudaFree(dev_filtered_score_));
189 GPU_CHECK(cudaFree(dev_filtered_label_));
190 GPU_CHECK(cudaFree(dev_filtered_dir_));
191 GPU_CHECK(cudaFree(dev_box_for_nms_));
192 GPU_CHECK(cudaFree(dev_filter_count_));
193}
194
195void PointPillars::DeviceMemoryMalloc() {
196 GPU_CHECK(cudaMalloc(reinterpret_cast<void**>(&dev_x_coors_),
197 kMaxNumPillars * sizeof(int)));
198 GPU_CHECK(cudaMalloc(reinterpret_cast<void**>(&dev_y_coors_),
199 kMaxNumPillars * sizeof(int)));
200 GPU_CHECK(cudaMalloc(reinterpret_cast<void**>(&dev_num_points_per_pillar_),
201 kMaxNumPillars * sizeof(float)));
202 GPU_CHECK(cudaMalloc(reinterpret_cast<void**>(&dev_sparse_pillar_map_),
203 kNumIndsForScan * kNumIndsForScan * sizeof(int)));
204
205 GPU_CHECK(cudaMalloc(reinterpret_cast<void**>(&dev_pillar_point_feature_),
206 kMaxNumPillars * kMaxNumPointsPerPillar *
207 kNumPointFeature * sizeof(float)));
208 GPU_CHECK(cudaMalloc(reinterpret_cast<void**>(&dev_pillar_coors_),
209 kMaxNumPillars * 4 * sizeof(float)));
210
211 GPU_CHECK(cudaMalloc(reinterpret_cast<void**>(&dev_cumsum_along_x_),
212 kNumIndsForScan * kNumIndsForScan * sizeof(int)));
213 GPU_CHECK(cudaMalloc(reinterpret_cast<void**>(&dev_cumsum_along_y_),
214 kNumIndsForScan * kNumIndsForScan * sizeof(int)));
215
216 // for make anchor mask kernel
217 GPU_CHECK(cudaMalloc(reinterpret_cast<void**>(&dev_box_anchors_min_x_),
218 kNumAnchor * sizeof(float)));
219 GPU_CHECK(cudaMalloc(reinterpret_cast<void**>(&dev_box_anchors_min_y_),
220 kNumAnchor * sizeof(float)));
221 GPU_CHECK(cudaMalloc(reinterpret_cast<void**>(&dev_box_anchors_max_x_),
222 kNumAnchor * sizeof(float)));
223 GPU_CHECK(cudaMalloc(reinterpret_cast<void**>(&dev_box_anchors_max_y_),
224 kNumAnchor * sizeof(float)));
225 GPU_CHECK(cudaMalloc(reinterpret_cast<void**>(&dev_anchor_mask_),
226 kNumAnchor * sizeof(int)));
227
228 // for trt inference
229 // create GPU buffers and a stream
230 GPU_CHECK(
231 cudaMalloc(&pfe_buffers_[0], kMaxNumPillars * kMaxNumPointsPerPillar *
232 kNumPointFeature * sizeof(float)));
233 GPU_CHECK(cudaMalloc(&pfe_buffers_[1], kMaxNumPillars * sizeof(float)));
234 GPU_CHECK(cudaMalloc(&pfe_buffers_[2], kMaxNumPillars * 4 * sizeof(float)));
235
236 GPU_CHECK(cudaMalloc(&rpn_buffers_[0], kRpnInputSize * sizeof(float)));
237 GPU_CHECK(cudaMalloc(&rpn_buffers_[1], kRpnBoxOutputSize * sizeof(float)));
238 GPU_CHECK(cudaMalloc(&rpn_buffers_[2], kRpnClsOutputSize * sizeof(float)));
239 GPU_CHECK(cudaMalloc(&rpn_buffers_[3], kRpnDirOutputSize * sizeof(float)));
240
241 // for scatter kernel
242 GPU_CHECK(cudaMalloc(reinterpret_cast<void**>(&dev_scattered_feature_),
243 kNumThreads * kGridYSize * kGridXSize * sizeof(float)));
244
245 // for filter
246 GPU_CHECK(cudaMalloc(reinterpret_cast<void**>(&dev_anchors_px_),
247 kNumAnchor * sizeof(float)));
248 GPU_CHECK(cudaMalloc(reinterpret_cast<void**>(&dev_anchors_py_),
249 kNumAnchor * sizeof(float)));
250 GPU_CHECK(cudaMalloc(reinterpret_cast<void**>(&dev_anchors_pz_),
251 kNumAnchor * sizeof(float)));
252 GPU_CHECK(cudaMalloc(reinterpret_cast<void**>(&dev_anchors_dx_),
253 kNumAnchor * sizeof(float)));
254 GPU_CHECK(cudaMalloc(reinterpret_cast<void**>(&dev_anchors_dy_),
255 kNumAnchor * sizeof(float)));
256 GPU_CHECK(cudaMalloc(reinterpret_cast<void**>(&dev_anchors_dz_),
257 kNumAnchor * sizeof(float)));
258 GPU_CHECK(cudaMalloc(reinterpret_cast<void**>(&dev_anchors_ro_),
259 kNumAnchor * sizeof(float)));
260 GPU_CHECK(cudaMalloc(reinterpret_cast<void**>(&dev_filtered_box_),
261 kNumAnchor * kNumOutputBoxFeature * sizeof(float)));
262 GPU_CHECK(cudaMalloc(reinterpret_cast<void**>(&dev_filtered_score_),
263 kNumAnchor * sizeof(float)));
264 GPU_CHECK(cudaMalloc(reinterpret_cast<void**>(&dev_filtered_label_),
265 kNumAnchor * sizeof(int)));
266 GPU_CHECK(cudaMalloc(reinterpret_cast<void**>(&dev_filtered_dir_),
267 kNumAnchor * sizeof(int)));
268 GPU_CHECK(cudaMalloc(reinterpret_cast<void**>(&dev_box_for_nms_),
269 kNumAnchor * kNumBoxCorners * sizeof(float)));
270 GPU_CHECK(
271 cudaMalloc(reinterpret_cast<void**>(&dev_filter_count_), sizeof(int)));
272}
273
274void PointPillars::InitAnchors() {
275 // allocate memory for anchors
276 anchors_px_ = new float[kNumAnchor]();
277 anchors_py_ = new float[kNumAnchor]();
278 anchors_pz_ = new float[kNumAnchor]();
279 anchors_dx_ = new float[kNumAnchor]();
280 anchors_dy_ = new float[kNumAnchor]();
281 anchors_dz_ = new float[kNumAnchor]();
282 anchors_ro_ = new float[kNumAnchor]();
283 box_anchors_min_x_ = new float[kNumAnchor]();
284 box_anchors_min_y_ = new float[kNumAnchor]();
285 box_anchors_max_x_ = new float[kNumAnchor]();
286 box_anchors_max_y_ = new float[kNumAnchor]();
287 // deallocate these memories in destructor
288
289 GenerateAnchors(anchors_px_, anchors_py_, anchors_pz_, anchors_dx_,
290 anchors_dy_, anchors_dz_, anchors_ro_);
291
292 ConvertAnchors2BoxAnchors(anchors_px_, anchors_py_, box_anchors_min_x_,
293 box_anchors_min_y_, box_anchors_max_x_,
294 box_anchors_max_y_);
295
296 PutAnchorsInDeviceMemory();
297}
298
299void PointPillars::GenerateAnchors(float* anchors_px_, float* anchors_py_,
300 float* anchors_pz_, float* anchors_dx_,
301 float* anchors_dy_, float* anchors_dz_,
302 float* anchors_ro_) {
303 for (int i = 0; i < kNumAnchor; ++i) {
304 anchors_px_[i] = 0;
305 anchors_py_[i] = 0;
306 anchors_pz_[i] = 0;
307 anchors_dx_[i] = 0;
308 anchors_dy_[i] = 0;
309 anchors_dz_[i] = 0;
310 anchors_ro_[i] = 0;
311 box_anchors_min_x_[i] = 0;
312 box_anchors_min_y_[i] = 0;
313 box_anchors_max_x_[i] = 0;
314 box_anchors_max_y_[i] = 0;
315 }
316
317 int ind = 0;
318 for (size_t head = 0; head < kNumAnchorSets.size(); ++head) {
319 float x_stride = kPillarXSize * kAnchorStrides[head];
320 float y_stride = kPillarYSize * kAnchorStrides[head];
321 int x_ind_start = kAnchorRanges[head * 4 + 0] / kAnchorStrides[head];
322 int x_ind_end = kAnchorRanges[head * 4 + 1] / kAnchorStrides[head];
323 int y_ind_start = kAnchorRanges[head * 4 + 2] / kAnchorStrides[head];
324 int y_ind_end = kAnchorRanges[head * 4 + 3] / kAnchorStrides[head];
325 // coors of first anchor's center
326 float x_offset = kMinXRange + x_stride / 2.0;
327 float y_offset = kMinYRange + y_stride / 2.0;
328
329 std::vector<float> anchor_x_count, anchor_y_count;
330 for (int i = x_ind_start; i < x_ind_end; ++i) {
331 float anchor_coor_x = static_cast<float>(i) * x_stride + x_offset;
332 anchor_x_count.push_back(anchor_coor_x);
333 }
334 for (int i = y_ind_start; i < y_ind_end; ++i) {
335 float anchor_coor_y = static_cast<float>(i) * y_stride + y_offset;
336 anchor_y_count.push_back(anchor_coor_y);
337 }
338
339 for (int y = 0; y < y_ind_end - y_ind_start; ++y) {
340 for (int x = 0; x < x_ind_end - x_ind_start; ++x) {
341 int ro_count = 0;
342 for (size_t c = 0; c < kNumAnchorRo[head].size(); ++c) {
343 for (int i = 0; i < kNumAnchorRo[head][c]; ++i) {
344 anchors_px_[ind] = anchor_x_count[x];
345 anchors_py_[ind] = anchor_y_count[y];
346 anchors_ro_[ind] = kAnchorRo[head][ro_count];
347 anchors_pz_[ind] = kAnchorZCoors[head][c];
348 anchors_dx_[ind] = kAnchorDxSizes[head][c];
349 anchors_dy_[ind] = kAnchorDySizes[head][c];
350 anchors_dz_[ind] = kAnchorDzSizes[head][c];
351 ro_count++;
352 ind++;
353 }
354 }
355 }
356 }
357 }
358}
359
360void PointPillars::PutAnchorsInDeviceMemory() {
361 GPU_CHECK(cudaMemcpy(dev_box_anchors_min_x_, box_anchors_min_x_,
362 kNumAnchor * sizeof(float), cudaMemcpyHostToDevice));
363 GPU_CHECK(cudaMemcpy(dev_box_anchors_min_y_, box_anchors_min_y_,
364 kNumAnchor * sizeof(float), cudaMemcpyHostToDevice));
365 GPU_CHECK(cudaMemcpy(dev_box_anchors_max_x_, box_anchors_max_x_,
366 kNumAnchor * sizeof(float), cudaMemcpyHostToDevice));
367 GPU_CHECK(cudaMemcpy(dev_box_anchors_max_y_, box_anchors_max_y_,
368 kNumAnchor * sizeof(float), cudaMemcpyHostToDevice));
369
370 GPU_CHECK(cudaMemcpy(dev_anchors_px_, anchors_px_, kNumAnchor * sizeof(float),
371 cudaMemcpyHostToDevice));
372 GPU_CHECK(cudaMemcpy(dev_anchors_py_, anchors_py_, kNumAnchor * sizeof(float),
373 cudaMemcpyHostToDevice));
374 GPU_CHECK(cudaMemcpy(dev_anchors_pz_, anchors_pz_, kNumAnchor * sizeof(float),
375 cudaMemcpyHostToDevice));
376 GPU_CHECK(cudaMemcpy(dev_anchors_dx_, anchors_dx_, kNumAnchor * sizeof(float),
377 cudaMemcpyHostToDevice));
378 GPU_CHECK(cudaMemcpy(dev_anchors_dy_, anchors_dy_, kNumAnchor * sizeof(float),
379 cudaMemcpyHostToDevice));
380 GPU_CHECK(cudaMemcpy(dev_anchors_dz_, anchors_dz_, kNumAnchor * sizeof(float),
381 cudaMemcpyHostToDevice));
382 GPU_CHECK(cudaMemcpy(dev_anchors_ro_, anchors_ro_, kNumAnchor * sizeof(float),
383 cudaMemcpyHostToDevice));
384}
385
386void PointPillars::ConvertAnchors2BoxAnchors(float* anchors_px,
387 float* anchors_py,
388 float* box_anchors_min_x_,
389 float* box_anchors_min_y_,
390 float* box_anchors_max_x_,
391 float* box_anchors_max_y_) {
392 // flipping box's dimension
393 float* flipped_anchors_dx = new float[kNumAnchor]();
394 float* flipped_anchors_dy = new float[kNumAnchor]();
395
396 int ind = 0;
397 for (size_t head = 0; head < kNumAnchorSets.size(); ++head) {
398 int num_x_inds =
399 (kAnchorRanges[head * 4 + 1] - kAnchorRanges[head * 4 + 0]) /
400 kAnchorStrides[head];
401 int num_y_inds =
402 (kAnchorRanges[head * 4 + 3] - kAnchorRanges[head * 4 + 2]) /
403 kAnchorStrides[head];
404 int base_ind = ind;
405 int ro_count = 0;
406 for (int x = 0; x < num_x_inds; ++x) {
407 for (int y = 0; y < num_y_inds; ++y) {
408 ro_count = 0;
409 for (size_t c = 0; c < kNumAnchorRo[head].size(); ++c) {
410 for (int i = 0; i < kNumAnchorRo[head][c]; ++i) {
411 if (kAnchorRo[head][ro_count] <= 0.78) {
412 flipped_anchors_dx[base_ind] = kAnchorDxSizes[head][c];
413 flipped_anchors_dy[base_ind] = kAnchorDySizes[head][c];
414 } else {
415 flipped_anchors_dx[base_ind] = kAnchorDySizes[head][c];
416 flipped_anchors_dy[base_ind] = kAnchorDxSizes[head][c];
417 }
418 ro_count++;
419 base_ind++;
420 }
421 }
422 }
423 }
424
425 for (int x = 0; x < num_x_inds; ++x) {
426 for (int y = 0; y < num_y_inds; ++y) {
427 for (size_t i = 0; i < kAnchorRo[head].size(); ++i) {
428 box_anchors_min_x_[ind] =
429 anchors_px[ind] - flipped_anchors_dx[ind] / 2.0f;
430 box_anchors_min_y_[ind] =
431 anchors_py[ind] - flipped_anchors_dy[ind] / 2.0f;
432 box_anchors_max_x_[ind] =
433 anchors_px[ind] + flipped_anchors_dx[ind] / 2.0f;
434 box_anchors_max_y_[ind] =
435 anchors_py[ind] + flipped_anchors_dy[ind] / 2.0f;
436 ind++;
437 }
438 }
439 }
440 }
441
442 delete[] flipped_anchors_dx;
443 delete[] flipped_anchors_dy;
444}
445
446void PointPillars::InitTorch() {
447 // Init inference and data shape
448 inference_.reset(inference::CreateInferenceByName(
449 model_type_, model_file_, "", output_blob_names_, input_blob_names_));
450 CHECK_NOTNULL(inference_.get());
451
452 std::map<std::string, std::vector<int>> shape_map;
453 shape_map.emplace(std::pair<std::string, std::vector<int>>(
454 input_blob_names_[0],
455 {kMaxNumPillars, kMaxNumPointsPerPillar, kNumPointFeature}));
456 shape_map.emplace(std::pair<std::string, std::vector<int>>(
457 input_blob_names_[1], {kMaxNumPillars}));
458 shape_map.emplace(std::pair<std::string, std::vector<int>>(
459 input_blob_names_[2], {kMaxNumPillars, 4}));
460
461 shape_map.emplace(std::pair<std::string, std::vector<int>>(
462 output_blob_names_[0],
463 {1, kGridSize, kGridSize, kNumAnchorPerGrid * kNumClass}));
464 shape_map.emplace(std::pair<std::string, std::vector<int>>(
465 output_blob_names_[1],
466 {1, kGridSize, kGridSize, kNumAnchorPerGrid * 7}));
467 shape_map.emplace(std::pair<std::string, std::vector<int>>(
468 output_blob_names_[2],
469 {1, kGridSize, kGridSize, kNumAnchorPerGrid * 2}));
470
471 ACHECK(inference_->Init(shape_map)) << "Failed to init inference.";
472}
473
474void PointPillars::InitTRT() {
475#if GPU_PLATFORM == NVIDIA
476 // create a TensorRT model from the onnx model and load it into an engine
477 OnnxToTRTModel(pfe_onnx_file_, &pfe_engine_);
478 OnnxToTRTModel(rpn_onnx_file_, &rpn_engine_);
479 if (pfe_engine_ == nullptr || rpn_engine_ == nullptr) {
480 AERROR << "Failed to load ONNX file.";
481 }
482
483 // create execution context from the engine
484 pfe_context_ = pfe_engine_->createExecutionContext();
485 rpn_context_ = rpn_engine_->createExecutionContext();
486 if (pfe_context_ == nullptr || rpn_context_ == nullptr) {
487 AERROR << "Failed to create TensorRT Execution Context.";
488 }
489#elif GPU_PLATFORM == AMD
490 assert(0 && "PointPillars::InitTRT() is not implemented yet");
491#endif
492}
493
494void PointPillars::OnnxToTRTModel(
495 const std::string& model_file, // name of the onnx model
496 nvinfer1::ICudaEngine** engine_ptr) {
497#if GPU_PLATFORM == NVIDIA
498 int verbosity = static_cast<int>(nvinfer1::ILogger::Severity::kWARNING);
499
500 // create the builder
501 const auto explicit_batch =
502 static_cast<uint32_t>(kBatchSize) << static_cast<uint32_t>(
503 nvinfer1::NetworkDefinitionCreationFlag::kEXPLICIT_BATCH);
504 nvinfer1::IBuilder* builder = nvinfer1::createInferBuilder(g_logger_);
505 nvinfer1::INetworkDefinition* network =
506 builder->createNetworkV2(explicit_batch);
507
508 // parse onnx model
509 auto parser = nvonnxparser::createParser(*network, g_logger_);
510 if (!parser->parseFromFile(model_file.c_str(), verbosity)) {
511 std::string msg("failed to parse onnx file");
512 g_logger_.log(nvinfer1::ILogger::Severity::kERROR, msg.c_str());
513 exit(EXIT_FAILURE);
514 }
515
516 // Build the engine
517 builder->setMaxBatchSize(kBatchSize);
518 nvinfer1::IBuilderConfig* config = builder->createBuilderConfig();
519 config->setMaxWorkspaceSize(1 << 20);
520 nvinfer1::ICudaEngine* engine =
521 builder->buildEngineWithConfig(*network, *config);
522
523 *engine_ptr = engine;
524 parser->destroy();
525 network->destroy();
526 config->destroy();
527 builder->destroy();
528#elif GPU_PLATFORM == AMD
529 assert(0 && "PointPillars::OnnxToTRTModel is not implemented yet");
530#endif
531}
532
533void PointPillars::PreprocessCPU(const float* in_points_array,
534 const int in_num_points) {
535 int x_coors[kMaxNumPillars] = {};
536 int y_coors[kMaxNumPillars] = {};
537 float num_points_per_pillar[kMaxNumPillars] = {};
538
539 float* pillar_point_feature =
540 new float[kMaxNumPillars * kMaxNumPointsPerPillar * kNumPointFeature];
541 float* pillar_coors = new float[kMaxNumPillars * 4];
542 float* sparse_pillar_map = new float[kNumIndsForScan * kNumIndsForScan];
543
544 preprocess_points_ptr_->Preprocess(in_points_array, in_num_points, x_coors,
545 y_coors, num_points_per_pillar,
546 pillar_point_feature, pillar_coors,
547 sparse_pillar_map, host_pillar_count_);
548
549 GPU_CHECK(cudaMemset(dev_x_coors_, 0, kMaxNumPillars * sizeof(int)));
550 GPU_CHECK(cudaMemset(dev_y_coors_, 0, kMaxNumPillars * sizeof(int)));
551 GPU_CHECK(cudaMemset(dev_pillar_point_feature_, 0,
552 kMaxNumPillars * kMaxNumPointsPerPillar *
553 kNumPointFeature * sizeof(float)));
554 GPU_CHECK(
555 cudaMemset(dev_pillar_coors_, 0, kMaxNumPillars * 4 * sizeof(float)));
556 GPU_CHECK(cudaMemset(dev_num_points_per_pillar_, 0,
557 kMaxNumPillars * sizeof(float)));
558 GPU_CHECK(cudaMemset(dev_sparse_pillar_map_, 0,
559 kNumIndsForScan * kNumIndsForScan * sizeof(int)));
560
561 GPU_CHECK(cudaMemcpy(dev_x_coors_, x_coors, kMaxNumPillars * sizeof(int),
562 cudaMemcpyHostToDevice));
563 GPU_CHECK(cudaMemcpy(dev_y_coors_, y_coors, kMaxNumPillars * sizeof(int),
564 cudaMemcpyHostToDevice));
565 GPU_CHECK(cudaMemcpy(dev_pillar_point_feature_, pillar_point_feature,
566 kMaxNumPillars * kMaxNumPointsPerPillar *
567 kNumPointFeature * sizeof(float),
568 cudaMemcpyHostToDevice));
569 GPU_CHECK(cudaMemcpy(dev_pillar_coors_, pillar_coors,
570 kMaxNumPillars * 4 * sizeof(float),
571 cudaMemcpyHostToDevice));
572 GPU_CHECK(cudaMemcpy(dev_num_points_per_pillar_, num_points_per_pillar,
573 kMaxNumPillars * sizeof(float), cudaMemcpyHostToDevice));
574 GPU_CHECK(cudaMemcpy(dev_sparse_pillar_map_, sparse_pillar_map,
575 kNumIndsForScan * kNumIndsForScan * sizeof(float),
576 cudaMemcpyHostToDevice));
577
578 delete[] pillar_point_feature;
579 delete[] pillar_coors;
580 delete[] sparse_pillar_map;
581}
582
583void PointPillars::PreprocessGPU(const float* in_points_array,
584 const int in_num_points) {
585 float* dev_points;
586 GPU_CHECK(cudaMalloc(reinterpret_cast<void**>(&dev_points),
587 in_num_points * kNumPointFeature * sizeof(float)));
588 GPU_CHECK(cudaMemcpy(dev_points, in_points_array,
589 in_num_points * kNumPointFeature * sizeof(float),
590 cudaMemcpyHostToDevice));
591
592 GPU_CHECK(cudaMemset(dev_x_coors_, 0, kMaxNumPillars * sizeof(int)));
593 GPU_CHECK(cudaMemset(dev_y_coors_, 0, kMaxNumPillars * sizeof(int)));
594 GPU_CHECK(cudaMemset(dev_num_points_per_pillar_, 0,
595 kMaxNumPillars * sizeof(float)));
596 GPU_CHECK(cudaMemset(dev_pillar_point_feature_, 0,
597 kMaxNumPillars * kMaxNumPointsPerPillar *
598 kNumPointFeature * sizeof(float)));
599 GPU_CHECK(
600 cudaMemset(dev_pillar_coors_, 0, kMaxNumPillars * 4 * sizeof(float)));
601 GPU_CHECK(cudaMemset(dev_sparse_pillar_map_, 0,
602 kNumIndsForScan * kNumIndsForScan * sizeof(int)));
603 host_pillar_count_[0] = 0;
604
605 GPU_CHECK(cudaMemset(dev_anchor_mask_, 0, kNumAnchor * sizeof(int)));
606
607 preprocess_points_cuda_ptr_->DoPreprocessPointsCuda(
608 dev_points, in_num_points, dev_x_coors_, dev_y_coors_,
609 dev_num_points_per_pillar_, dev_pillar_point_feature_, dev_pillar_coors_,
610 dev_sparse_pillar_map_, host_pillar_count_);
611
612 GPU_CHECK(cudaFree(dev_points));
613}
614
615void PointPillars::Preprocess(const float* in_points_array,
616 const int in_num_points) {
617 if (reproduce_result_mode_) {
618 PreprocessCPU(in_points_array, in_num_points);
619 } else {
620 PreprocessGPU(in_points_array, in_num_points);
621 }
622}
623
624void PointPillars::DoInference(const float* in_points_array,
625 const int in_num_points,
626 std::vector<float>* out_detections,
627 std::vector<int>* out_labels) {
628 if (device_id_ < 0) {
629 AERROR << "Torch is not using GPU!";
630 return;
631 }
632
633 Preprocess(in_points_array, in_num_points);
634
635 anchor_mask_cuda_ptr_->DoAnchorMaskCuda(
636 dev_sparse_pillar_map_, dev_cumsum_along_x_, dev_cumsum_along_y_,
637 dev_box_anchors_min_x_, dev_box_anchors_min_y_, dev_box_anchors_max_x_,
638 dev_box_anchors_max_y_, dev_anchor_mask_);
639
640 // put input data to inferece_ blob
641 auto pillar_point_feature = inference_->get_blob(input_blob_names_.at(0));
642 auto points_per_pillar = inference_->get_blob(input_blob_names_.at(1));
643 auto pillar_coors = inference_->get_blob(input_blob_names_.at(2));
644 cudaStream_t stream;
645 GPU_CHECK(cudaStreamCreate(&stream));
646 GPU_CHECK(cudaMemcpyAsync(pillar_point_feature->mutable_gpu_data(),
647 dev_pillar_point_feature_,
648 kMaxNumPillars * kMaxNumPointsPerPillar *
649 kNumPointFeature * sizeof(float),
650 cudaMemcpyDeviceToDevice, stream));
651 GPU_CHECK(cudaMemcpyAsync(points_per_pillar->mutable_gpu_data(),
652 dev_num_points_per_pillar_,
653 kMaxNumPillars * sizeof(float),
654 cudaMemcpyDeviceToDevice, stream));
655 GPU_CHECK(cudaMemcpyAsync(pillar_coors->mutable_gpu_data(),
656 dev_pillar_coors_,
657 kMaxNumPillars * 4 * sizeof(float),
658 cudaMemcpyDeviceToDevice, stream));
659 inference_->Infer();
660
661 auto cls_score = inference_->get_blob(output_blob_names_.at(0));
662 auto bbox_pred = inference_->get_blob(output_blob_names_.at(1));
663 auto dir_cls_preds = inference_->get_blob(output_blob_names_.at(2));
664
665 GPU_CHECK(cudaMemset(dev_filter_count_, 0, sizeof(int)));
666 postprocess_cuda_ptr_->DoPostprocessCuda(
667 bbox_pred->gpu_data(),
668 cls_score->gpu_data(),
669 dir_cls_preds->gpu_data(),
670 dev_anchor_mask_, dev_anchors_px_, dev_anchors_py_, dev_anchors_pz_,
671 dev_anchors_dx_, dev_anchors_dy_, dev_anchors_dz_, dev_anchors_ro_,
672 dev_filtered_box_, dev_filtered_score_, dev_filtered_label_,
673 dev_filtered_dir_, dev_box_for_nms_, dev_filter_count_, out_detections,
674 out_labels);
675
676 // release the stream and the buffers
677 cudaStreamDestroy(stream);
678}
679
680} // namespace lidar
681} // namespace perception
682} // namespace apollo
void log(Severity severity, const char *msg) noexcept override
static std::vector< std::vector< float > > AnchorDySizes()
Definition params.h:58
static constexpr float kMaxYRange
Definition params.h:36
static constexpr float kPillarYSize
Definition params.h:28
static constexpr int kNumAnchor
Definition params.h:40
static constexpr int kNumClass
Definition params.h:38
static constexpr float kPillarXSize
Definition params.h:27
static constexpr int kNumThreads
Definition params.h:44
static constexpr float kMinYRange
Definition params.h:33
static std::vector< std::vector< float > > AnchorRo()
Definition params.h:77
static constexpr int kNumIndsForScan
Definition params.h:43
static constexpr int kMaxNumPillars
Definition params.h:37
static constexpr int kBatchSize
Definition params.h:43
static constexpr float kMaxZRange
Definition params.h:37
static constexpr int kNumAnchorPerGrid
Definition params.h:47
static constexpr int kMaxNumPointsPerPillar
Definition params.h:38
static constexpr int kGridSize
Definition params.h:46
static std::vector< std::vector< float > > AnchorDzSizes()
Definition params.h:63
static constexpr float kMinXRange
Definition params.h:32
static constexpr float kPillarZSize
Definition params.h:29
static std::vector< int > NumAnchorSets()
Definition params.h:51
static std::vector< int > AnchorStrides()
Definition params.h:49
static constexpr int kNumBoxCorners
Definition params.h:45
static std::vector< std::vector< float > > AnchorDxSizes()
Definition params.h:53
static std::vector< std::vector< int > > NumAnchorRo()
Definition params.h:73
static constexpr int kNumOutputBoxFeature
Definition params.h:42
static constexpr float kMinZRange
Definition params.h:34
static constexpr int kNumPointFeature
Definition params.h:41
static constexpr float kMaxXRange
Definition params.h:35
static std::vector< std::vector< float > > AnchorZCoors()
Definition params.h:68
~PointPillars()
Destroy the Point Pillars object
PointPillars(const bool reproduce_result_mode, const float score_threshold, const float nms_overlap_threshold, const common::Framework &model_type, const std::string &model_file)
Constructor
void DoInference(const float *in_points_array, const int in_num_points, std::vector< float > *out_detections, std::vector< int > *out_labels)
Call PointPillars for the inference
Algorithm for PointPillars
#define ACHECK(cond)
Definition log.h:80
#define AERROR
Definition log.h:44
Inference * CreateInferenceByName(const std::string &frame_work, const std::string &proto_file, const std::string &weight_file, const std::vector< std::string > &outputs, const std::vector< std::string > &inputs, const std::string &model_root)
class register implement
Definition arena_queue.h:37
#define GPU_CHECK(ans)