Apollo 10.0
自动驾驶开放平台
lane_scanning_evaluator.cc
浏览该文件的文档.
1/******************************************************************************
2 * Copyright 2018 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 <algorithm>
20#include <utility>
21
22#include <omp.h>
23
24#include "cyber/common/file.h"
26#include "modules/common_msgs/basic_msgs/pnc_point.pb.h"
32
33namespace apollo {
34namespace prediction {
35
38
43
45 ObstaclesContainer* obstacles_container) {
46 std::vector<Obstacle*> dummy_dynamic_env;
47 Evaluate(obstacle_ptr, obstacles_container, dummy_dynamic_env);
48 return true;
49}
50
52 ObstaclesContainer* obstacles_container,
53 std::vector<Obstacle*> dynamic_env) {
54 // Sanity checks.
55 omp_set_num_threads(1);
56 CHECK_NOTNULL(obstacle_ptr);
57
58 obstacle_ptr->SetEvaluatorType(evaluator_type_);
59
60 int id = obstacle_ptr->id();
61 if (!obstacle_ptr->latest_feature().IsInitialized()) {
62 AERROR << "Obstacle [" << id << "] has no latest feature.";
63 return false;
64 }
65 Feature* latest_feature_ptr = obstacle_ptr->mutable_latest_feature();
66 CHECK_NOTNULL(latest_feature_ptr);
67 if (!latest_feature_ptr->has_lane() ||
68 !latest_feature_ptr->lane().has_lane_graph_ordered()) {
69 AERROR << "Obstacle [" << id << "] has no lane graph.";
70 return false;
71 }
72 LaneGraph* lane_graph_ptr =
73 latest_feature_ptr->mutable_lane()->mutable_lane_graph_ordered();
74 CHECK_NOTNULL(lane_graph_ptr);
75 if (lane_graph_ptr->lane_sequence().empty()) {
76 AERROR << "Obstacle [" << id << "] has no lane sequences.";
77 return false;
78 }
79 ADEBUG << "There are " << lane_graph_ptr->lane_sequence_size()
80 << " lane sequences to scan.";
81
82 // Extract features, and:
83 // - if in offline mode, save it locally for training.
84 // - if in online mode, pass it through trained model to evaluate.
85 std::vector<double> feature_values;
86 ExtractFeatures(obstacle_ptr, lane_graph_ptr, &feature_values);
87 std::vector<std::string> string_feature_values;
88 ExtractStringFeatures(*lane_graph_ptr, &string_feature_values);
89
90 std::vector<double> labels = {0.0};
91 if (FLAGS_prediction_offline_mode ==
93 std::string learning_data_tag = "vehicle_cruise";
94 if (latest_feature_ptr->has_junction_feature()) {
95 learning_data_tag = "vehicle_junction";
96 }
97 FeatureOutput::InsertDataForLearning(*latest_feature_ptr, feature_values,
98 string_feature_values,
99 learning_data_tag, nullptr);
100 ADEBUG << "Save extracted features for learning locally.";
101 return true;
102 }
103
104 feature_values.push_back(static_cast<double>(MAX_NUM_LANE));
105
106 std::vector<torch::jit::IValue> torch_inputs;
107 torch::Tensor torch_input =
108 torch::zeros({1, static_cast<int>(feature_values.size())});
109 for (size_t i = 0; i < feature_values.size(); ++i) {
110 torch_input[0][i] = static_cast<float>(feature_values[i]);
111 }
112 torch_inputs.push_back(std::move(torch_input));
113 ModelInference(torch_inputs, torch_lane_scanning_model_, latest_feature_ptr);
114 return true;
115}
116
118 const LaneGraph& lane_graph,
119 std::vector<std::string>* const string_feature_values) {
120 for (const LaneSequence& lane_sequence : lane_graph.lane_sequence()) {
121 string_feature_values->push_back("|");
122 for (int i = lane_sequence.adc_lane_segment_idx();
123 i < static_cast<int>(lane_sequence.lane_segment_size()); ++i) {
124 string_feature_values->push_back(lane_sequence.lane_segment(i).lane_id());
125 }
126 }
127 return true;
128}
129
131 const Obstacle* obstacle_ptr, const LaneGraph* lane_graph_ptr,
132 std::vector<double>* feature_values) {
133 // Sanity checks.
134 CHECK_NOTNULL(obstacle_ptr);
135 int id = obstacle_ptr->id();
136 CHECK_NOTNULL(lane_graph_ptr);
137
138 // Extract obstacle related features.
139 std::vector<double> obstacle_feature_values;
140 if (!ExtractObstacleFeatures(obstacle_ptr, &obstacle_feature_values)) {
141 ADEBUG << "Failed to extract obstacle features for obs_id = " << id;
142 }
143 if (obstacle_feature_values.size() != OBSTACLE_FEATURE_SIZE) {
144 ADEBUG << "Obstacle [" << id << "] has fewer than "
145 << "expected obstacle feature_values "
146 << obstacle_feature_values.size() << ".";
147 return false;
148 }
149 ADEBUG << "Obstacle feature size = " << obstacle_feature_values.size();
150 feature_values->insert(feature_values->end(), obstacle_feature_values.begin(),
151 obstacle_feature_values.end());
152
153 // Extract static environmental (lane-related) features.
154 std::vector<double> static_feature_values;
155 std::vector<int> lane_sequence_idx_to_remove;
156 if (!ExtractStaticEnvFeatures(obstacle_ptr, lane_graph_ptr,
157 &static_feature_values,
158 &lane_sequence_idx_to_remove)) {
159 AERROR << "Failed to extract static environmental features around obs_id = "
160 << id;
161 }
162 if (static_feature_values.size() %
163 (SINGLE_LANE_FEATURE_SIZE *
164 (LANE_POINTS_SIZE + BACKWARD_LANE_POINTS_SIZE)) !=
165 0) {
166 AERROR << "Obstacle [" << id << "] has incorrect static env feature size: "
167 << static_feature_values.size() << ".";
168 return false;
169 }
170 feature_values->insert(feature_values->end(), static_feature_values.begin(),
171 static_feature_values.end());
172
173 return true;
174}
175
176bool LaneScanningEvaluator::ExtractObstacleFeatures(
177 const Obstacle* obstacle_ptr, std::vector<double>* feature_values) {
178 // Sanity checks.
179 CHECK_NOTNULL(obstacle_ptr);
180 feature_values->clear();
181 FLAGS_cruise_historical_frame_length = 20;
182 int max_num_poly_pt = 20;
183 std::vector<double> has_history(FLAGS_cruise_historical_frame_length, 1.0);
184 std::vector<std::pair<double, double>> pos_history(
185 FLAGS_cruise_historical_frame_length, std::make_pair(0.0, 0.0));
186 std::vector<std::pair<double, double>> vel_history(
187 FLAGS_cruise_historical_frame_length, std::make_pair(0.0, 0.0));
188 std::vector<std::pair<double, double>> acc_history(
189 FLAGS_cruise_historical_frame_length, std::make_pair(0.0, 0.0));
190 std::vector<double> vel_heading_history(FLAGS_cruise_historical_frame_length,
191 0.0);
192 std::vector<double> vel_heading_changing_rate_history(
193 FLAGS_cruise_historical_frame_length, 0.0);
194 std::vector<std::vector<std::pair<double, double>>> polygon_points_history(
195 FLAGS_cruise_historical_frame_length,
196 std::vector<std::pair<double, double>>(max_num_poly_pt,
197 std::make_pair(0.0, 0.0)));
198
199 // Get obstacle's current position to set up the relative coord. system.
200 const Feature& obs_curr_feature = obstacle_ptr->latest_feature();
201 double obs_curr_heading = obs_curr_feature.velocity_heading();
202 std::pair<double, double> obs_curr_pos = std::make_pair(
203 obs_curr_feature.position().x(), obs_curr_feature.position().y());
204 double prev_timestamp = obs_curr_feature.timestamp();
205
206 // Starting from the most recent timestamp and going backward.
207 ADEBUG << "Obstacle has " << obstacle_ptr->history_size()
208 << " history timestamps.";
209 for (std::size_t i = 0; i < std::min(obstacle_ptr->history_size(),
210 FLAGS_cruise_historical_frame_length);
211 ++i) {
212 const Feature& feature = obstacle_ptr->feature(i);
213 if (!feature.IsInitialized()) {
214 has_history[i] = 0.0;
215 continue;
216 }
217 if (i != 0 && has_history[i - 1] == 0.0) {
218 has_history[i] = 0.0;
219 continue;
220 }
221 // Extract normalized position info.
222 if (feature.has_position()) {
223 pos_history[i] =
224 std::make_pair(feature.position().x(), feature.position().y());
225 } else {
226 has_history[i] = 0.0;
227 }
228 // Extract normalized velocity info.
229 if (feature.has_velocity()) {
230 auto vel_end = WorldCoordToObjCoord(
231 std::make_pair(feature.velocity().x(), feature.velocity().y()),
232 obs_curr_pos, obs_curr_heading);
233 auto vel_begin = WorldCoordToObjCoord(std::make_pair(0.0, 0.0),
234 obs_curr_pos, obs_curr_heading);
235 vel_history[i] = std::make_pair(vel_end.first - vel_begin.first,
236 vel_end.second - vel_begin.second);
237 } else {
238 has_history[i] = 0.0;
239 }
240 // Extract normalized acceleration info.
241 if (feature.has_acceleration()) {
242 auto acc_end =
243 WorldCoordToObjCoord(std::make_pair(feature.acceleration().x(),
244 feature.acceleration().y()),
245 obs_curr_pos, obs_curr_heading);
246 auto acc_begin = WorldCoordToObjCoord(std::make_pair(0.0, 0.0),
247 obs_curr_pos, obs_curr_heading);
248 acc_history[i] = std::make_pair(acc_end.first - acc_begin.first,
249 acc_end.second - acc_begin.second);
250 } else {
251 has_history[i] = 0.0;
252 }
253 // Extract velocity heading info.
254 if (feature.has_velocity_heading()) {
255 vel_heading_history[i] = feature.velocity_heading();
256 if (i != 0) {
257 vel_heading_changing_rate_history[i] =
258 (vel_heading_history[i] - vel_heading_history[i - 1]) /
259 (feature.timestamp() - prev_timestamp + FLAGS_double_precision);
260 prev_timestamp = feature.timestamp();
261 }
262 } else {
263 has_history[i] = 0.0;
264 }
265 // Extract polygon-point info.
266 for (int j = 0; j < feature.polygon_point_size(); ++j) {
267 if (j >= max_num_poly_pt) {
268 break;
269 }
270 polygon_points_history[i][j].first = feature.polygon_point(j).x();
271 polygon_points_history[i][j].second = feature.polygon_point(j).y();
272 }
273 }
274
275 for (std::size_t i = obstacle_ptr->history_size();
276 i < FLAGS_cruise_historical_frame_length; ++i) {
277 has_history[i] = 0.0;
278 }
279
280 // Update the extracted features into the feature_values vector.
281 for (std::size_t i = 0; i < FLAGS_cruise_historical_frame_length; i++) {
282 feature_values->push_back(has_history[i]);
283 feature_values->push_back(pos_history[i].first);
284 feature_values->push_back(pos_history[i].second);
285 feature_values->push_back(vel_history[i].first);
286 feature_values->push_back(vel_history[i].second);
287 feature_values->push_back(acc_history[i].first);
288 feature_values->push_back(acc_history[i].second);
289 feature_values->push_back(vel_heading_history[i]);
290 feature_values->push_back(vel_heading_changing_rate_history[i]);
291 for (int j = 0; j < max_num_poly_pt; ++j) {
292 feature_values->push_back(polygon_points_history[i][j].first);
293 feature_values->push_back(polygon_points_history[i][j].second);
294 }
295 }
296
297 return true;
298}
299
300bool LaneScanningEvaluator::ExtractStaticEnvFeatures(
301 const Obstacle* obstacle_ptr, const LaneGraph* lane_graph_ptr,
302 std::vector<double>* feature_values,
303 std::vector<int>* lane_sequence_idx_to_remove) {
304 // Sanity checks.
305 CHECK_NOTNULL(lane_graph_ptr);
306 feature_values->clear();
307
308 // Get obstacle's current position to set up the relative coord. system.
309 const Feature& obs_curr_feature = obstacle_ptr->latest_feature();
310 double obs_curr_heading = obs_curr_feature.velocity_heading();
311 std::pair<double, double> obs_curr_pos = std::make_pair(
312 obs_curr_feature.position().x(), obs_curr_feature.position().y());
313
314 // Go through every lane-sequence (ordered from left to right) and
315 // extract needed features.
316 for (int i = 0; i < lane_graph_ptr->lane_sequence_size(); ++i) {
317 // Get all the properties of the current lane-sequence.
318 // Go through all the lane-points to fill up the feature_values.
319 const LaneSequence& lane_sequence = lane_graph_ptr->lane_sequence(i);
320
321 // Extract features from backward lane-points.
322 size_t count = 0;
323 std::vector<double> backward_feature_values;
324 for (int j = lane_sequence.adc_lane_segment_idx(); j >= 0; --j) {
325 if (count >= SINGLE_LANE_FEATURE_SIZE * BACKWARD_LANE_POINTS_SIZE) {
326 break;
327 }
328 const LaneSegment& lane_segment = lane_sequence.lane_segment(j);
329 int k_starting_idx = lane_segment.lane_point_size() - 1;
330 if (j == lane_sequence.adc_lane_segment_idx()) {
331 k_starting_idx = std::min(lane_segment.adc_lane_point_idx(),
332 lane_segment.lane_point_size() - 1);
333 }
334 for (int k = k_starting_idx; k >= 0; --k) {
335 if (count >= SINGLE_LANE_FEATURE_SIZE * BACKWARD_LANE_POINTS_SIZE) {
336 break;
337 }
338 const LanePoint& lane_point = lane_segment.lane_point(k);
339 std::pair<double, double> relative_s_l =
340 WorldCoordToObjCoord(std::make_pair(lane_point.position().x(),
341 lane_point.position().y()),
342 obs_curr_pos, obs_curr_heading);
343 double relative_ang =
344 WorldAngleToObjAngle(lane_point.heading(), obs_curr_heading);
345
346 backward_feature_values.push_back(lane_point.kappa());
347 backward_feature_values.push_back(relative_ang);
348 backward_feature_values.push_back(relative_s_l.first);
349 backward_feature_values.push_back(relative_s_l.second);
350
351 count += 4;
352 }
353 }
354 // If lane-points are not enough, then extrapolate linearly.
355 while (count >= SINGLE_LANE_FEATURE_SIZE * 2 &&
356 count < SINGLE_LANE_FEATURE_SIZE * BACKWARD_LANE_POINTS_SIZE) {
357 std::size_t s = backward_feature_values.size();
358 double relative_l_new =
359 2 * backward_feature_values[s - 1] - backward_feature_values[s - 5];
360 double relative_s_new =
361 2 * backward_feature_values[s - 2] - backward_feature_values[s - 6];
362 double relative_ang_new = backward_feature_values[s - 3];
363
364 backward_feature_values.push_back(0.0);
365 backward_feature_values.push_back(relative_ang_new);
366 backward_feature_values.push_back(relative_s_new);
367 backward_feature_values.push_back(relative_l_new);
368
369 count += 4;
370 }
371
372 for (int j = static_cast<int>(backward_feature_values.size()) - 1; j >= 0;
373 --j) {
374 feature_values->push_back(backward_feature_values[j]);
375 }
376
377 // Extract features from forward lane-points.
378 count = 0;
379 for (int j = lane_sequence.adc_lane_segment_idx();
380 j < lane_sequence.lane_segment_size(); ++j) {
381 if (count >= SINGLE_LANE_FEATURE_SIZE * LANE_POINTS_SIZE) {
382 break;
383 }
384 const LaneSegment& lane_segment = lane_sequence.lane_segment(j);
385 int k_starting_idx = 0;
386 if (j == lane_sequence.adc_lane_segment_idx()) {
387 k_starting_idx = std::min(lane_segment.adc_lane_point_idx(),
388 lane_segment.lane_point_size() - 1);
389 }
390 for (int k = k_starting_idx; k < lane_segment.lane_point_size(); ++k) {
391 if (count >= SINGLE_LANE_FEATURE_SIZE * LANE_POINTS_SIZE) {
392 break;
393 }
394 const LanePoint& lane_point = lane_segment.lane_point(k);
395 std::pair<double, double> relative_s_l =
396 WorldCoordToObjCoord(std::make_pair(lane_point.position().x(),
397 lane_point.position().y()),
398 obs_curr_pos, obs_curr_heading);
399 double relative_ang =
400 WorldAngleToObjAngle(lane_point.heading(), obs_curr_heading);
401
402 feature_values->push_back(relative_s_l.second);
403 feature_values->push_back(relative_s_l.first);
404 feature_values->push_back(relative_ang);
405 feature_values->push_back(lane_point.kappa());
406 count += 4;
407 }
408 }
409 // If lane-points are not enough, then extrapolate linearly.
410 while (count >= SINGLE_LANE_FEATURE_SIZE * 2 &&
411 count < SINGLE_LANE_FEATURE_SIZE * LANE_POINTS_SIZE) {
412 std::size_t s = feature_values->size();
413 double relative_l_new = 2 * feature_values->operator[](s - 4) -
414 feature_values->operator[](s - 8);
415 double relative_s_new = 2 * feature_values->operator[](s - 3) -
416 feature_values->operator[](s - 7);
417 double relative_ang_new = feature_values->operator[](s - 2);
418
419 feature_values->push_back(relative_l_new);
420 feature_values->push_back(relative_s_new);
421 feature_values->push_back(relative_ang_new);
422 feature_values->push_back(0.0);
423 count += 4;
424 }
425 }
426
427 if (FLAGS_prediction_offline_mode ==
429 // Early exit without appending zero for offline_dataforlearn_dump
430 return true;
431 }
432
433 size_t max_feature_size =
434 LANE_POINTS_SIZE * SINGLE_LANE_FEATURE_SIZE * MAX_NUM_LANE;
435 while (feature_values->size() < max_feature_size) {
436 feature_values->push_back(0.0);
437 }
438
439 return true;
440}
441
442void LaneScanningEvaluator::LoadModel() {
443 if (FLAGS_use_cuda && torch::cuda::is_available()) {
444 ADEBUG << "CUDA is available";
445 device_ = torch::Device(torch::kCUDA);
446 }
447 torch::set_num_threads(1);
448 torch_lane_scanning_model_ =
449 torch::jit::load(FLAGS_torch_vehicle_lane_scanning_file, device_);
450}
451
452void LaneScanningEvaluator::ModelInference(
453 const std::vector<torch::jit::IValue>& torch_inputs,
454 torch::jit::script::Module torch_model, Feature* feature_ptr) {
455 auto torch_output_tensor = torch_model.forward(torch_inputs).toTensor();
456 auto torch_output = torch_output_tensor.accessor<float, 3>();
457 for (size_t i = 0; i < SHORT_TERM_TRAJECTORY_SIZE; ++i) {
458 TrajectoryPoint point;
459 double dx = static_cast<double>(torch_output[0][0][i]);
460 double dy =
461 static_cast<double>(torch_output[0][0][i + SHORT_TERM_TRAJECTORY_SIZE]);
462 Vec2d offset(dx, dy);
463 Vec2d rotated_offset = offset.rotate(feature_ptr->velocity_heading());
464 double point_x = feature_ptr->position().x() + rotated_offset.x();
465 double point_y = feature_ptr->position().y() + rotated_offset.y();
466 point.mutable_path_point()->set_x(point_x);
467 point.mutable_path_point()->set_y(point_y);
468 point.set_relative_time(static_cast<double>(i) *
469 FLAGS_prediction_trajectory_time_resolution);
470 feature_ptr->add_short_term_predicted_trajectory_points()->CopyFrom(point);
471 }
472}
473
474} // namespace prediction
475} // namespace apollo
Implements a class of 2-dimensional vectors.
Definition vec2d.h:42
double WorldAngleToObjAngle(double input_world_angle, double obj_world_angle)
Definition evaluator.h:116
std::pair< double, double > WorldCoordToObjCoord(std::pair< double, double > input_world_coord, std::pair< double, double > obj_world_coord, double obj_world_angle)
Definition evaluator.h:94
ObstacleConf::EvaluatorType evaluator_type_
Definition evaluator.h:156
static void InsertDataForLearning(const Feature &feature, const std::vector< double > &feature_values, const std::string &category, const LaneSequence *lane_sequence_ptr)
Insert a data_for_learning
bool Evaluate(Obstacle *obstacle_ptr, ObstaclesContainer *obstacles_container) override
Override Evaluate
bool ExtractFeatures(const Obstacle *obstacle_ptr, const LaneGraph *lane_graph_ptr, std::vector< double > *feature_values)
Extract features for learning model's input
bool ExtractStringFeatures(const LaneGraph &lane_graph, std::vector< std::string > *const string_feature_values)
Prediction obstacle.
Definition obstacle.h:52
Feature * mutable_latest_feature()
Get a pointer to the latest feature.
Definition obstacle.cc:88
int id() const
Get the obstacle's ID.
Definition obstacle.cc:60
size_t history_size() const
Get the number of historical features.
Definition obstacle.cc:93
const Feature & feature(const size_t i) const
Get the ith feature from latest to earliest.
Definition obstacle.cc:67
void SetEvaluatorType(const ObstacleConf::EvaluatorType &evaluator_type)
Definition obstacle.cc:1484
const Feature & latest_feature() const
Get the latest feature.
Definition obstacle.cc:78
Use container manager to manage all containers
#define ADEBUG
Definition log.h:41
#define AERROR
Definition log.h:44
class register implement
Definition arena_queue.h:37
Holds all global constants for the prediction module.
optional apollo::common::Point3D velocity
Definition feature.proto:90
optional double velocity_heading
Definition feature.proto:93
optional apollo::common::Point3D position
Definition feature.proto:88
repeated apollo::common::Point3D polygon_point
Definition feature.proto:87
optional apollo::common::Point3D acceleration
Definition feature.proto:92
repeated LaneSequence lane_sequence
Defines the Vec2d class.