Apollo 10.0
自动驾驶开放平台
mlp_evaluator.cc
浏览该文件的文档.
1/******************************************************************************
2 * Copyright 2017 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 <limits>
20
21#include "cyber/common/file.h"
28
29namespace apollo {
30namespace prediction {
31namespace {
32
34
35double ComputeMean(const std::vector<double>& nums, size_t start, size_t end) {
36 int count = 0;
37 double sum = 0.0;
38 for (size_t i = start; i <= end && i < nums.size(); i++) {
39 sum += nums[i];
40 ++count;
41 }
42 return (count == 0) ? 0.0 : sum / count;
43}
44
45} // namespace
46
49 LoadModel(FLAGS_evaluator_vehicle_mlp_file);
50}
51
53
55 ObstaclesContainer* obstacles_container) {
56 Clear();
57 CHECK_NOTNULL(obstacle_ptr);
58 CHECK_LE(LANE_FEATURE_SIZE, 4 * FLAGS_max_num_lane_point);
59
60 obstacle_ptr->SetEvaluatorType(evaluator_type_);
61
62 int id = obstacle_ptr->id();
63 if (!obstacle_ptr->latest_feature().IsInitialized()) {
64 AERROR << "Obstacle [" << id << "] has no latest feature.";
65 return false;
66 }
67
68 Feature* latest_feature_ptr = obstacle_ptr->mutable_latest_feature();
69 CHECK_NOTNULL(latest_feature_ptr);
70 if (!latest_feature_ptr->has_lane() ||
71 !latest_feature_ptr->lane().has_lane_graph()) {
72 ADEBUG << "Obstacle [" << id << "] has no lane graph.";
73 return false;
74 }
75
76 double speed = latest_feature_ptr->speed();
77
78 LaneGraph* lane_graph_ptr =
79 latest_feature_ptr->mutable_lane()->mutable_lane_graph();
80 CHECK_NOTNULL(lane_graph_ptr);
81 if (lane_graph_ptr->lane_sequence().empty()) {
82 AERROR << "Obstacle [" << id << "] has no lane sequences.";
83 return false;
84 }
85
86 std::vector<double> obstacle_feature_values;
87 SetObstacleFeatureValues(obstacle_ptr, &obstacle_feature_values);
88 if (obstacle_feature_values.size() != OBSTACLE_FEATURE_SIZE) {
89 ADEBUG << "Obstacle [" << id << "] has fewer than "
90 << "expected obstacle feature_values "
91 << obstacle_feature_values.size() << ".";
92 return false;
93 }
94
95 for (int i = 0; i < lane_graph_ptr->lane_sequence_size(); ++i) {
96 LaneSequence* lane_sequence_ptr = lane_graph_ptr->mutable_lane_sequence(i);
97 ACHECK(lane_sequence_ptr != nullptr);
98 std::vector<double> lane_feature_values;
99 SetLaneFeatureValues(obstacle_ptr, lane_sequence_ptr, &lane_feature_values);
100 if (lane_feature_values.size() != LANE_FEATURE_SIZE) {
101 ADEBUG << "Obstacle [" << id << "] has fewer than "
102 << "expected lane feature_values" << lane_feature_values.size()
103 << ".";
104 continue;
105 }
106
107 std::vector<double> feature_values;
108 feature_values.insert(feature_values.end(), obstacle_feature_values.begin(),
109 obstacle_feature_values.end());
110 feature_values.insert(feature_values.end(), lane_feature_values.begin(),
111 lane_feature_values.end());
112
113 // Insert features to DataForLearning
114 if (FLAGS_prediction_offline_mode ==
116 !obstacle_ptr->IsNearJunction()) {
117 FeatureOutput::InsertDataForLearning(*latest_feature_ptr, feature_values,
118 "mlp", lane_sequence_ptr);
119 ADEBUG << "Save extracted features for learning locally.";
120 return true; // Skip Compute probability for offline mode
121 }
122 double probability = ComputeProbability(feature_values);
123
124 double centripetal_acc_probability =
126 *lane_sequence_ptr, speed);
127 probability *= centripetal_acc_probability;
128 lane_sequence_ptr->set_probability(probability);
129 }
130 return true;
131}
132
134 LaneSequence* lane_sequence_ptr,
135 std::vector<double>* feature_values) {
136 int id = obstacle_ptr->id();
137 std::vector<double> obstacle_feature_values;
138
139 SetObstacleFeatureValues(obstacle_ptr, &obstacle_feature_values);
140
141 if (obstacle_feature_values.size() != OBSTACLE_FEATURE_SIZE) {
142 ADEBUG << "Obstacle [" << id << "] has fewer than "
143 << "expected obstacle feature_values "
144 << obstacle_feature_values.size() << ".";
145 return;
146 }
147
148 std::vector<double> lane_feature_values;
149 SetLaneFeatureValues(obstacle_ptr, lane_sequence_ptr, &lane_feature_values);
150 if (lane_feature_values.size() != LANE_FEATURE_SIZE) {
151 ADEBUG << "Obstacle [" << id << "] has fewer than "
152 << "expected lane feature_values" << lane_feature_values.size()
153 << ".";
154 return;
155 }
156
157 feature_values->insert(feature_values->end(), obstacle_feature_values.begin(),
158 obstacle_feature_values.end());
159 feature_values->insert(feature_values->end(), lane_feature_values.begin(),
160 lane_feature_values.end());
161}
162
163void MLPEvaluator::SaveOfflineFeatures(
164 LaneSequence* sequence, const std::vector<double>& feature_values) {
165 for (double feature_value : feature_values) {
166 sequence->mutable_features()->add_mlp_features(feature_value);
167 }
168}
169
170void MLPEvaluator::SetObstacleFeatureValues(
171 Obstacle* obstacle_ptr, std::vector<double>* feature_values) {
172 feature_values->clear();
173 feature_values->reserve(OBSTACLE_FEATURE_SIZE);
174
175 std::vector<double> thetas;
176 std::vector<double> lane_ls;
177 std::vector<double> dist_lbs;
178 std::vector<double> dist_rbs;
179 std::vector<int> lane_types;
180 std::vector<double> speeds;
181 std::vector<double> timestamps;
182
183 double duration =
184 obstacle_ptr->timestamp() - FLAGS_prediction_trajectory_time_length;
185 int count = 0;
186 for (std::size_t i = 0; i < obstacle_ptr->history_size(); ++i) {
187 const Feature& feature = obstacle_ptr->feature(i);
188 if (!feature.IsInitialized()) {
189 continue;
190 }
191 if (feature.timestamp() < duration) {
192 break;
193 }
194 if (feature.has_lane() && feature.lane().has_lane_feature()) {
195 thetas.push_back(feature.lane().lane_feature().angle_diff());
196 lane_ls.push_back(feature.lane().lane_feature().lane_l());
197 dist_lbs.push_back(feature.lane().lane_feature().dist_to_left_boundary());
198 dist_rbs.push_back(
199 feature.lane().lane_feature().dist_to_right_boundary());
200 lane_types.push_back(feature.lane().lane_feature().lane_turn_type());
201 timestamps.push_back(feature.timestamp());
202 speeds.push_back(feature.speed());
203 ++count;
204 }
205 }
206 if (count <= 0) {
207 return;
208 }
209 size_t curr_size = 5;
210 size_t hist_size = obstacle_ptr->history_size();
211 double theta_mean = ComputeMean(thetas, 0, hist_size - 1);
212 double theta_filtered = ComputeMean(thetas, 0, curr_size - 1);
213 double lane_l_mean = ComputeMean(lane_ls, 0, hist_size - 1);
214 double lane_l_filtered = ComputeMean(lane_ls, 0, curr_size - 1);
215 double speed_mean = ComputeMean(speeds, 0, hist_size - 1);
216
217 double time_diff = timestamps.front() - timestamps.back();
218 double dist_lb_rate = (timestamps.size() > 1)
219 ? (dist_lbs.front() - dist_lbs.back()) / time_diff
220 : 0.0;
221 double dist_rb_rate = (timestamps.size() > 1)
222 ? (dist_rbs.front() - dist_rbs.back()) / time_diff
223 : 0.0;
224
225 double delta_t = 0.0;
226 if (timestamps.size() > 1) {
227 delta_t = (timestamps.front() - timestamps.back()) /
228 static_cast<double>(timestamps.size() - 1);
229 }
230 double angle_curr = ComputeMean(thetas, 0, curr_size - 1);
231 double angle_prev = ComputeMean(thetas, curr_size, 2 * curr_size - 1);
232 double angle_diff =
233 (hist_size >= 2 * curr_size) ? angle_curr - angle_prev : 0.0;
234
235 double lane_l_curr = ComputeMean(lane_ls, 0, curr_size - 1);
236 double lane_l_prev = ComputeMean(lane_ls, curr_size, 2 * curr_size - 1);
237 double lane_l_diff =
238 (hist_size >= 2 * curr_size) ? lane_l_curr - lane_l_prev : 0.0;
239
240 double angle_diff_rate = 0.0;
241 double lane_l_diff_rate = 0.0;
242 if (delta_t > std::numeric_limits<double>::epsilon()) {
243 angle_diff_rate = angle_diff / (delta_t * static_cast<double>(curr_size));
244 lane_l_diff_rate = lane_l_diff / (delta_t * static_cast<float>(curr_size));
245 }
246
247 double acc = 0.0;
248 if (speeds.size() >= 3 * curr_size &&
249 delta_t > std::numeric_limits<double>::epsilon()) {
250 double speed_1 = ComputeMean(speeds, 0, curr_size - 1);
251 double speed_2 = ComputeMean(speeds, curr_size, 2 * curr_size - 1);
252 double speed_3 = ComputeMean(speeds, 2 * curr_size, 3 * curr_size - 1);
253 acc = (speed_1 - 2 * speed_2 + speed_3) /
254 (static_cast<float>(curr_size) * static_cast<float>(curr_size) *
255 delta_t * delta_t);
256 }
257
258 double dist_lb_rate_curr = 0.0;
259 if (hist_size >= 2 * curr_size &&
260 delta_t > std::numeric_limits<double>::epsilon()) {
261 double dist_lb_curr = ComputeMean(dist_lbs, 0, curr_size - 1);
262 double dist_lb_prev = ComputeMean(dist_lbs, curr_size, 2 * curr_size - 1);
263 dist_lb_rate_curr = (dist_lb_curr - dist_lb_prev) /
264 (static_cast<float>(curr_size) * delta_t);
265 }
266
267 double dist_rb_rate_curr = 0.0;
268 if (hist_size >= 2 * curr_size &&
269 delta_t > std::numeric_limits<double>::epsilon()) {
270 double dist_rb_curr = ComputeMean(dist_rbs, 0, curr_size - 1);
271 double dist_rb_prev = ComputeMean(dist_rbs, curr_size, 2 * curr_size - 1);
272 dist_rb_rate_curr = (dist_rb_curr - dist_rb_prev) /
273 (static_cast<float>(curr_size) * delta_t);
274 }
275
276 // setup obstacle feature values
277 feature_values->push_back(theta_filtered);
278 feature_values->push_back(theta_mean);
279 feature_values->push_back(theta_filtered - theta_mean);
280 feature_values->push_back(angle_diff);
281 feature_values->push_back(angle_diff_rate);
282
283 feature_values->push_back(lane_l_filtered);
284 feature_values->push_back(lane_l_mean);
285 feature_values->push_back(lane_l_filtered - lane_l_mean);
286 feature_values->push_back(lane_l_diff);
287 feature_values->push_back(lane_l_diff_rate);
288
289 feature_values->push_back(speed_mean);
290 feature_values->push_back(acc);
291
292 feature_values->push_back(dist_lbs.front());
293 feature_values->push_back(dist_lb_rate);
294 feature_values->push_back(dist_lb_rate_curr);
295
296 feature_values->push_back(dist_rbs.front());
297 feature_values->push_back(dist_rb_rate);
298 feature_values->push_back(dist_rb_rate_curr);
299
300 feature_values->push_back(lane_types.front() == 0 ? 1.0 : 0.0);
301 feature_values->push_back(lane_types.front() == 1 ? 1.0 : 0.0);
302 feature_values->push_back(lane_types.front() == 2 ? 1.0 : 0.0);
303 feature_values->push_back(lane_types.front() == 3 ? 1.0 : 0.0);
304}
305
306void MLPEvaluator::SetLaneFeatureValues(Obstacle* obstacle_ptr,
307 LaneSequence* lane_sequence_ptr,
308 std::vector<double>* feature_values) {
309 feature_values->clear();
310 feature_values->reserve(LANE_FEATURE_SIZE);
311 const Feature& feature = obstacle_ptr->latest_feature();
312 if (!feature.IsInitialized()) {
313 ADEBUG << "Obstacle [" << obstacle_ptr->id() << "] has no latest feature.";
314 return;
315 } else if (!feature.has_position()) {
316 ADEBUG << "Obstacle [" << obstacle_ptr->id() << "] has no position.";
317 return;
318 }
319
320 double heading = feature.velocity_heading();
321 for (int i = 0; i < lane_sequence_ptr->lane_segment_size(); ++i) {
322 if (feature_values->size() >= LANE_FEATURE_SIZE) {
323 break;
324 }
325 const LaneSegment& lane_segment = lane_sequence_ptr->lane_segment(i);
326 for (int j = 0; j < lane_segment.lane_point_size(); ++j) {
327 if (feature_values->size() >= LANE_FEATURE_SIZE) {
328 break;
329 }
330 const LanePoint& lane_point = lane_segment.lane_point(j);
331 if (!lane_point.has_position()) {
332 AERROR << "Lane point has no position.";
333 continue;
334 }
335 double diff_x = lane_point.position().x() - feature.position().x();
336 double diff_y = lane_point.position().y() - feature.position().y();
337 double angle = std::atan2(diff_y, diff_x);
338 feature_values->push_back(std::sin(angle - heading));
339 feature_values->push_back(lane_point.relative_l());
340 feature_values->push_back(lane_point.heading());
341 feature_values->push_back(lane_point.angle_diff());
342 }
343 }
344
345 std::size_t size = feature_values->size();
346 while (size >= 4 && size < LANE_FEATURE_SIZE) {
347 double heading_diff = feature_values->operator[](size - 4);
348 double lane_l_diff = feature_values->operator[](size - 3);
349 double heading = feature_values->operator[](size - 2);
350 double angle_diff = feature_values->operator[](size - 1);
351 feature_values->push_back(heading_diff);
352 feature_values->push_back(lane_l_diff);
353 feature_values->push_back(heading);
354 feature_values->push_back(angle_diff);
355 size = feature_values->size();
356 }
357}
358
359void MLPEvaluator::LoadModel(const std::string& model_file) {
360 model_ptr_.reset(new FnnVehicleModel());
361 ACHECK(model_ptr_ != nullptr);
362 ACHECK(cyber::common::GetProtoFromFile(model_file, model_ptr_.get()))
363 << "Unable to load model file: " << model_file << ".";
364
365 AINFO << "Succeeded in loading the model file: " << model_file << ".";
366}
367
368double MLPEvaluator::ComputeProbability(
369 const std::vector<double>& feature_values) {
370 CHECK_NOTNULL(model_ptr_.get());
371 double probability = 0.0;
372
373 if (model_ptr_->dim_input() != static_cast<int>(feature_values.size())) {
374 ADEBUG << "Model feature size not consistent with model proto definition. "
375 << "model input dim = " << model_ptr_->dim_input()
376 << "; feature value size = " << feature_values.size();
377 return probability;
378 }
379 std::vector<double> layer_input;
380 layer_input.reserve(model_ptr_->dim_input());
381 std::vector<double> layer_output;
382
383 // normalization
384 for (int i = 0; i < model_ptr_->dim_input(); ++i) {
385 double mean = model_ptr_->samples_mean().columns(i);
386 double std = model_ptr_->samples_std().columns(i);
387 layer_input.push_back(
388 apollo::prediction::math_util::Normalize(feature_values[i], mean, std));
389 }
390
391 for (int i = 0; i < model_ptr_->num_layer(); ++i) {
392 if (i > 0) {
393 layer_input.swap(layer_output);
394 layer_output.clear();
395 }
396 const Layer& layer = model_ptr_->layer(i);
397 for (int col = 0; col < layer.layer_output_dim(); ++col) {
398 double neuron_output = layer.layer_bias().columns(col);
399 for (int row = 0; row < layer.layer_input_dim(); ++row) {
400 double weight = layer.layer_input_weight().rows(row).columns(col);
401 neuron_output += (layer_input[row] * weight);
402 }
403 if (layer.layer_activation_func() == Layer::RELU) {
404 neuron_output = apollo::prediction::math_util::Relu(neuron_output);
405 } else if (layer.layer_activation_func() == Layer::SIGMOID) {
406 neuron_output = Sigmoid(neuron_output);
407 } else if (layer.layer_activation_func() == Layer::TANH) {
408 neuron_output = std::tanh(neuron_output);
409 } else {
410 AERROR << "Undefined activation function ["
411 << layer.layer_activation_func()
412 << "]. A default sigmoid will be used instead.";
413 neuron_output = Sigmoid(neuron_output);
414 }
415 layer_output.push_back(neuron_output);
416 }
417 }
418
419 if (layer_output.size() != 1) {
420 AERROR << "Model output layer has incorrect # outputs: "
421 << layer_output.size();
422 } else {
423 probability = layer_output[0];
424 }
425
426 return probability;
427}
428
429} // namespace prediction
430} // namespace apollo
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
void Clear()
Clear obstacle feature map
bool Evaluate(Obstacle *obstacle_ptr, ObstaclesContainer *obstacles_container) override
Override Evaluate
void ExtractFeatureValues(Obstacle *obstacle_ptr, LaneSequence *lane_sequence_ptr, std::vector< double > *feature_values)
Extract feature vector
Prediction obstacle.
Definition obstacle.h:52
bool IsNearJunction()
Check if the obstacle is near a junction.
Definition obstacle.cc:130
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
void SetEvaluatorType(const ObstacleConf::EvaluatorType &evaluator_type)
Definition obstacle.cc:1484
const Feature & latest_feature() const
Get the latest feature.
Definition obstacle.cc:78
static double ProbabilityByCentripetalAcceleration(const LaneSequence &lane_sequence, const double speed)
Compute the probability by centripetal acceleration
#define ACHECK(cond)
Definition log.h:80
#define ADEBUG
Definition log.h:41
#define AERROR
Definition log.h:44
#define AINFO
Definition log.h:42
double Sigmoid(const double x)
Definition math_utils.h:171
bool GetProtoFromFile(const std::string &file_name, google::protobuf::Message *message)
Parses the content of the file specified by the file_name as a representation of protobufs,...
Definition file.cc:132
double Relu(const double value)
RELU function used in neural networks as an activation function.
double Normalize(const double value, const double mean, const double std)
Normalize the value by specified mean and standard deviation.
double ComputeMean(const std::vector< double > &nums, size_t start, size_t end)
class register implement
Definition arena_queue.h:37
Definition future.h:29
Holds all global constants for the prediction module.
optional int32 layer_input_dim
optional Matrix layer_input_weight
optional ActivationFunc layer_activation_func
optional Vector layer_bias
optional int32 layer_output_dim
repeated Vector rows
repeated double columns
repeated LaneSequence lane_sequence