Apollo 11.0
自动驾驶开放平台
trajectory_imitation_libtorch_inference.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 "opencv2/opencv.hpp"
24
25#include "cyber/common/log.h"
30
31namespace apollo {
32namespace planning {
36
37bool TrajectoryImitationLibtorchInference::LoadCNNModel() {
38 // run a fake inference at init time as first inference is relative slow
39 torch::Tensor input_feature_tensor = torch::zeros({1, 12, 200, 200});
40 std::vector<torch::jit::IValue> torch_inputs;
41 torch_inputs.push_back(input_feature_tensor.to(device_));
42 try {
43 auto torch_output_tensor =
44 model_.forward(torch_inputs).toTensor().to(torch::kCPU);
45 } catch (const c10::Error& e) {
46 AERROR << "Fail to do initial inference on CNN Model";
47 return false;
48 }
49 return true;
50}
51
52bool TrajectoryImitationLibtorchInference::LoadCNNLSTMModel() {
53 // run a fake inference at init time as first inference is relative slow
54 torch::Tensor input_feature_tensor = torch::zeros({1, 12, 200, 200});
55 torch::Tensor current_v = torch::zeros({1, 1});
56 std::vector<torch::jit::IValue> torch_inputs;
57 torch_inputs.push_back(
58 c10::ivalue::Tuple::create({std::move(input_feature_tensor.to(device_)),
59 std::move(current_v.to(device_))}));
60 try {
61 auto torch_output_tensor =
62 model_.forward(torch_inputs).toTensor().to(torch::kCPU);
63 } catch (const c10::Error& e) {
64 AERROR << "Fail to do initial inference on HISTORY_UNCONDITIONED_CNN_LSTM "
65 "Model";
66 return false;
67 }
68 return true;
69}
70
72 if (config_.use_cuda() && torch::cuda::is_available()) {
73 ADEBUG << "CUDA is available";
74 device_ = torch::Device(torch::kCUDA);
75 try {
76 model_ = torch::jit::load(config_.gpu_model_file(), device_);
77 } catch (const c10::Error& e) {
78 AERROR << "Failed to load model on to device";
79 return false;
80 }
81 } else {
82 model_ = torch::jit::load(config_.cpu_model_file(), device_);
83 }
84
85 torch::set_num_threads(1);
86 switch (config_.model_type()) {
88 if (!LoadCNNModel()) {
89 return false;
90 }
91 break;
92 }
94 if (!LoadCNNLSTMModel()) {
95 return false;
96 }
97 break;
98 }
99 default: {
100 AERROR << "Configured model type not defined and implemented";
101 break;
102 }
103 }
104 return true;
105}
106
107void TrajectoryImitationLibtorchInference::output_postprocessing(
108 const at::Tensor& torch_output_tensor,
109 LearningDataFrame* const learning_data_frame) {
110 const int past_points_size = learning_data_frame->adc_trajectory_point_size();
111 const auto& cur_traj_point =
112 learning_data_frame->adc_trajectory_point(past_points_size - 1);
113 const double cur_time_sec = cur_traj_point.timestamp_sec();
114 const auto& cur_path_point = cur_traj_point.trajectory_point().path_point();
115 const double cur_x = cur_path_point.x();
116 const double cur_y = cur_path_point.y();
117 const double cur_heading = cur_path_point.theta();
118 ADEBUG << "cur_x[" << cur_x << "], cur_y[" << cur_y << "], cur_heading["
119 << cur_heading << "], cur_v[" << cur_traj_point.trajectory_point().v()
120 << "]";
121
122 learning_data_frame->mutable_output()->clear_adc_future_trajectory_point();
123 const double delta_t = config_.trajectory_delta_t();
124 auto torch_output = torch_output_tensor.accessor<float, 3>();
125 for (int i = 0; i < torch_output_tensor.size(1); ++i) {
126 const double dx = static_cast<double>(torch_output[0][i][0]);
127 const double dy = static_cast<double>(torch_output[0][i][1]);
128 const double dtheta = static_cast<double>(torch_output[0][i][2]);
129 const double v = static_cast<double>(torch_output[0][i][3]);
130 ADEBUG << "dx[" << dx << "], dy[" << dy << "], dtheta[" << dtheta << "], v["
131 << v << "]";
132 const double time_sec = cur_time_sec + delta_t * (i + 1);
133 apollo::common::math::Vec2d offset(dx, dy);
134 apollo::common::math::Vec2d rotated_offset = offset.rotate(cur_heading);
135 const double x = cur_x + rotated_offset.x();
136 const double y = cur_y + rotated_offset.y();
137 const double heading =
138 apollo::common::math::NormalizeAngle(dtheta + cur_heading);
139
140 auto* traj_point = learning_data_frame->mutable_output()
141 ->add_adc_future_trajectory_point();
142 traj_point->set_timestamp_sec(time_sec);
143 traj_point->mutable_trajectory_point()->mutable_path_point()->set_x(x);
144 traj_point->mutable_trajectory_point()->mutable_path_point()->set_y(y);
145 traj_point->mutable_trajectory_point()->mutable_path_point()->set_theta(
146 heading);
147 traj_point->mutable_trajectory_point()->set_v(v);
148 traj_point->mutable_trajectory_point()->set_relative_time(delta_t *
149 (i + 1));
150 }
151}
152
153bool TrajectoryImitationLibtorchInference::DoCNNMODELInference(
154 LearningDataFrame* const learning_data_frame) {
155 const int past_points_size = learning_data_frame->adc_trajectory_point_size();
156 if (past_points_size == 0) {
157 AERROR << "No current trajectory point status";
158 return false;
159 }
160
161 auto input_renderering_start_time = std::chrono::system_clock::now();
162
163 cv::Mat input_feature;
164 if (!BirdviewImgFeatureRenderer::Instance()->RenderMultiChannelEnv(
165 *learning_data_frame, &input_feature)) {
166 AERROR << "Render multi-channel input image failed";
167 return false;
168 }
169
170 auto input_renderering_end_time = std::chrono::system_clock::now();
171 std::chrono::duration<double> rendering_diff =
172 input_renderering_end_time - input_renderering_start_time;
173 ADEBUG << "trajectory imitation model input renderer used time: "
174 << rendering_diff.count() * 1000 << " ms.";
175
176 auto input_preprocessing_start_time = std::chrono::system_clock::now();
177
178 cv::Mat input_feature_float;
179 input_feature.convertTo(input_feature_float, CV_32F, 1.0 / 255);
180 torch::Tensor input_feature_tensor =
181 torch::from_blob(input_feature_float.data,
182 {1, input_feature_float.rows, input_feature_float.cols,
183 input_feature_float.channels()});
184 input_feature_tensor = input_feature_tensor.permute({0, 3, 1, 2});
185 for (int i = 0; i < input_feature_float.channels(); ++i) {
186 input_feature_tensor[0][i] = input_feature_tensor[0][i].sub(0.5).div(0.5);
187 }
188
189 auto input_preprocessing_end_time = std::chrono::system_clock::now();
190 std::chrono::duration<double> preprocessing_diff =
191 input_preprocessing_end_time - input_preprocessing_start_time;
192 ADEBUG << "trajectory imitation model input preprocessing used time: "
193 << preprocessing_diff.count() * 1000 << " ms.";
194
195 auto inference_start_time = std::chrono::system_clock::now();
196
197 std::vector<torch::jit::IValue> torch_inputs;
198 torch_inputs.push_back(input_feature_tensor.to(device_));
199 at::Tensor torch_output_tensor =
200 model_.forward(torch_inputs).toTensor().to(torch::kCPU);
201
202 auto inference_end_time = std::chrono::system_clock::now();
203 std::chrono::duration<double> inference_diff =
204 inference_end_time - inference_start_time;
205 ADEBUG << "trajectory imitation model inference used time: "
206 << inference_diff.count() * 1000 << " ms.";
207
208 output_postprocessing(torch_output_tensor, learning_data_frame);
209
210 return true;
211}
212
213bool TrajectoryImitationLibtorchInference::DoCNNLSTMMODELInference(
214 LearningDataFrame* const learning_data_frame) {
215 const int past_points_size = learning_data_frame->adc_trajectory_point_size();
216 if (past_points_size == 0) {
217 AERROR << "No current trajectory point status";
218 return false;
219 }
220
221 auto input_renderering_start_time = std::chrono::system_clock::now();
222
223 cv::Mat input_feature;
224 if (!BirdviewImgFeatureRenderer::Instance()->RenderMultiChannelEnv(
225 *learning_data_frame, &input_feature)) {
226 AERROR << "Render multi-channel input image failed";
227 return false;
228 }
229
230 auto input_renderering_end_time = std::chrono::system_clock::now();
231 std::chrono::duration<double> rendering_diff =
232 input_renderering_end_time - input_renderering_start_time;
233 ADEBUG << "trajectory imitation model input renderer used time: "
234 << rendering_diff.count() * 1000 << " ms.";
235
236 auto input_preprocessing_start_time = std::chrono::system_clock::now();
237
238 cv::Mat input_feature_float;
239 input_feature.convertTo(input_feature_float, CV_32F, 1.0 / 255);
240 torch::Tensor input_feature_tensor =
241 torch::from_blob(input_feature_float.data,
242 {1, input_feature_float.rows, input_feature_float.cols,
243 input_feature_float.channels()});
244 input_feature_tensor = input_feature_tensor.permute({0, 3, 1, 2});
245 for (int i = 0; i < input_feature_float.channels(); ++i) {
246 input_feature_tensor[0][i] = input_feature_tensor[0][i].sub(0.5).div(0.5);
247 }
248
249 const auto& current_traj_point =
250 learning_data_frame
251 ->adc_trajectory_point(
252 learning_data_frame->adc_trajectory_point_size() - 1)
253 .trajectory_point();
254
255 torch::Tensor current_v_tensor = torch::zeros({1, 1});
256 const double current_v = current_traj_point.v();
257 current_v_tensor[0][0] = current_v;
258
259 auto input_preprocessing_end_time = std::chrono::system_clock::now();
260 std::chrono::duration<double> preprocessing_diff =
261 input_preprocessing_end_time - input_preprocessing_start_time;
262 ADEBUG << "trajectory imitation model input preprocessing used time: "
263 << preprocessing_diff.count() * 1000 << " ms.";
264
265 auto inference_start_time = std::chrono::system_clock::now();
266
267 std::vector<torch::jit::IValue> torch_inputs;
268 torch_inputs.push_back(
269 c10::ivalue::Tuple::create({std::move(input_feature_tensor.to(device_)),
270 std::move(current_v_tensor.to(device_))}));
271 at::Tensor torch_output_tensor =
272 model_.forward(torch_inputs).toTensor().to(torch::kCPU);
273
274 auto inference_end_time = std::chrono::system_clock::now();
275 std::chrono::duration<double> inference_diff =
276 inference_end_time - inference_start_time;
277 ADEBUG << "trajectory imitation model inference used time: "
278 << inference_diff.count() * 1000 << " ms.";
279
280 output_postprocessing(torch_output_tensor, learning_data_frame);
281
282 return true;
283}
284
286 LearningDataFrame* const learning_data_frame) {
287 switch (config_.model_type()) {
289 if (!DoCNNMODELInference(learning_data_frame)) {
290 return false;
291 }
292 break;
293 }
295 if (!DoCNNLSTMMODELInference(learning_data_frame)) {
296 return false;
297 }
298 break;
299 }
300 default: {
301 AERROR << "Configured model type not defined and implemented";
302 break;
303 }
304 }
305 return true;
306}
307} // namespace planning
308} // namespace apollo
Define the birdview img feature renderer class
Implements a class of 2-dimensional vectors.
Definition vec2d.h:42
double y() const
Getter for y component
Definition vec2d.h:57
Vec2d rotate(const double angle) const
rotate the vector by angle.
Definition vec2d.cc:65
double x() const
Getter for x component
Definition vec2d.h:54
LearningModelInferenceTaskConfig config_
TrajectoryImitationLibtorchInference(const LearningModelInferenceTaskConfig &config)
Constructor
bool DoInference(LearningDataFrame *const learning_data_frame) override
inference a learned model
Planning module main class.
Math-related util functions.
#define ADEBUG
Definition log.h:41
#define AERROR
Definition log.h:44
double NormalizeAngle(const double angle)
Normalize angle to [-PI, PI).
Definition math_utils.cc:53
class register implement
Definition arena_queue.h:37
repeated ADCTrajectoryPoint adc_trajectory_point
Define the trajectory_imitation_libtorch_inference class
Defines the Vec2d class.