Apollo 11.0
自动驾驶开放平台
open_space_fallback_decider.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 *****************************************************************************/
16
22
23namespace apollo {
24namespace planning {
30
32 const std::string& config_dir, const std::string& name,
33 const std::shared_ptr<DependencyInjector>& injector) {
34 if (!Decider::Init(config_dir, name, injector)) {
35 return false;
36 }
37 // Load the config this task.
38 return Decider::LoadConfig<OpenSpaceFallBackDeciderConfig>(&config_);
39}
40
41bool OpenSpaceFallbackDecider::QuardraticFormulaLowerSolution(const double a,
42 const double b,
43 const double c,
44 double* sol) {
45 // quardratic formula: ax^2 + bx + c = 0, return lower solution
46 // TODO(QiL): use const from common::math
47 const double kEpsilon = 1e-6;
48 *sol = 0.0;
49 if (std::abs(a) < kEpsilon) {
50 return false;
51 }
52
53 double tmp = b * b - 4 * a * c;
54 if (tmp < kEpsilon) {
55 return false;
56 }
57 double sol1 = (-b + std::sqrt(tmp)) / (2.0 * a);
58 double sol2 = (-b - std::sqrt(tmp)) / (2.0 * a);
59
60 *sol = std::abs(std::min(sol1, sol2));
61 ADEBUG << "QuardraticFormulaLowerSolution finished with sol: " << *sol
62 << "sol1: " << sol1 << ", sol2: " << sol2 << "a: " << a << "b: " << b
63 << "c: " << c;
64 return true;
65}
66
67Status OpenSpaceFallbackDecider::Process(Frame* frame) {
68 std::vector<std::vector<common::math::Box2d>> predicted_bounding_rectangles;
69 size_t first_collision_index = 0;
70 size_t fallback_start_index = 0;
72 AINFO << "has got fallback decider, skip";
73 return Status::OK();
74 }
75 BuildPredictedEnvironment(frame->obstacles(), predicted_bounding_rectangles);
76 ADEBUG << "Numbers of obstsacles are: " << frame->obstacles().size();
77 ADEBUG << "Numbers of predicted bounding rectangles are: "
78 << predicted_bounding_rectangles[0].size()
79 << " and : " << predicted_bounding_rectangles.size();
80 if (!IsCollisionFreeTrajectory(
81 frame->open_space_info().chosen_partitioned_trajectory(),
82 predicted_bounding_rectangles, &fallback_start_index,
83 &first_collision_index)) {
84 // change flag
86
87 // generate fallback trajectory base on current partition trajectory
88 // vehicle speed is decreased to zero inside safety distance
89 TrajGearPair fallback_trajectory_pair_candidate =
90 frame->open_space_info().chosen_partitioned_trajectory();
91 // auto* ptr_fallback_trajectory_pair =
92 // frame_->mutable_open_space_info()->mutable_fallback_trajectory();
93 const auto future_collision_point =
94 fallback_trajectory_pair_candidate.first[first_collision_index];
95
96 // Fallback starts from current location but with vehicle velocity
97 auto fallback_start_point =
98 fallback_trajectory_pair_candidate.first[fallback_start_index];
99 const auto& vehicle_state = injector_->vehicle_state()->vehicle_state();
100 fallback_start_point.set_v(vehicle_state.linear_velocity());
101
103 future_collision_point;
104
105 // min stop distance: (max_acc)
106 double min_stop_distance =
107 0.5 * fallback_start_point.v() * fallback_start_point.v() / 4.0;
108
109 // TODO(QiL): move 1.0 to configs
110 double stop_distance =
111 fallback_trajectory_pair_candidate.second == canbus::Chassis::GEAR_DRIVE
112 ? std::max(future_collision_point.path_point().s() -
113 fallback_start_point.path_point().s() - 1.0,
114 0.0)
115 : std::min(future_collision_point.path_point().s() -
116 fallback_start_point.path_point().s() + 1.0,
117 0.0);
118
119 ADEBUG << "stop distance : " << stop_distance;
120 // const auto& vehicle_config =
121 // common::VehicleConfigHelper::Instance()->GetConfig();
122 const double vehicle_max_acc = 4.0; // vehicle_config.max_acceleration();
123 const double vehicle_max_dec = -4.0; // vehicle_config.max_deceleration();
124
125 double stop_deceleration = 0.0;
126
127 if (fallback_trajectory_pair_candidate.second ==
129 stop_deceleration =
130 std::min(fallback_start_point.v() * fallback_start_point.v() /
131 (2.0 * (stop_distance + 1e-6)),
132 vehicle_max_acc);
133 stop_distance = std::min(-1 * min_stop_distance, stop_distance);
134 } else {
135 stop_deceleration =
136 std::max(-fallback_start_point.v() * fallback_start_point.v() /
137 (2.0 * (stop_distance + 1e-6)),
138 vehicle_max_dec);
139 stop_distance = std::max(min_stop_distance, stop_distance);
140 }
141
142 ADEBUG << "stop_deceleration: " << stop_deceleration;
143
144 // Search stop index in chosen trajectory by distance
145 size_t stop_index = fallback_start_index;
146
147 for (size_t i = fallback_start_index;
148 i < fallback_trajectory_pair_candidate.first.NumOfPoints(); ++i) {
149 if (std::abs(
150 fallback_trajectory_pair_candidate.first[i].path_point().s()) >=
151 std::abs(fallback_start_point.path_point().s() + stop_distance)) {
152 stop_index = i;
153 break;
154 }
155 }
156
157 ADEBUG << "stop index before is: " << stop_index
158 << "; fallback_start index before is: " << fallback_start_index;
159
160 for (size_t i = 0; i < fallback_start_index; ++i) {
161 fallback_trajectory_pair_candidate.first[i].set_v(
162 fallback_start_point.v());
163 fallback_trajectory_pair_candidate.first[i].set_a(stop_deceleration);
164 }
165
166 // TODO(QiL): refine the logic and remove redundant code, change 0.5 to from
167 // loading optimizer configs
168
169 // If stop_index == fallback_start_index;
170 if (fallback_start_index >= stop_index) {
171 // 1. Set fallback start speed to 0, acceleration to max acceleration.
172 AINFO << "Stop distance within safety buffer, stop now!";
173 fallback_start_point.set_v(0.0);
174 fallback_start_point.set_a(0.0);
175 fallback_trajectory_pair_candidate.first[stop_index].set_v(0.0);
176 fallback_trajectory_pair_candidate.first[stop_index].set_a(0.0);
177
178 // 2. Trim all trajectory points after stop index
179 fallback_trajectory_pair_candidate.first.erase(
180 fallback_trajectory_pair_candidate.first.begin() + stop_index + 1,
181 fallback_trajectory_pair_candidate.first.end());
182
183 // 3. AppendTrajectoryPoint with same location but zero velocity
184 for (int i = 0; i < 20; ++i) {
185 common::TrajectoryPoint trajectory_point(
186 fallback_trajectory_pair_candidate.first[stop_index]);
187 trajectory_point.set_relative_time(
188 i * 0.5 + 0.5 +
189 fallback_trajectory_pair_candidate.first[stop_index]
190 .relative_time());
191 fallback_trajectory_pair_candidate.first.AppendTrajectoryPoint(
192 trajectory_point);
193 }
194
196 fallback_trajectory_pair_candidate;
197
198 return Status::OK();
199 }
200
201 ADEBUG << "before change, size : "
202 << fallback_trajectory_pair_candidate.first.size()
203 << ", first index information : "
204 << fallback_trajectory_pair_candidate.first[0].DebugString()
205 << ", second index information : "
206 << fallback_trajectory_pair_candidate.first[1].DebugString();
207
208 // If stop_index > fallback_start_index
209
210 for (size_t i = fallback_start_index; i <= stop_index; ++i) {
211 double new_relative_time = 0.0;
212 double temp_v = 0.0;
213 double c =
214 -2.0 * fallback_trajectory_pair_candidate.first[i].path_point().s();
215
216 if (QuardraticFormulaLowerSolution(stop_deceleration,
217 2.0 * fallback_start_point.v(), c,
218 &new_relative_time) &&
219 std::abs(
220 fallback_trajectory_pair_candidate.first[i].path_point().s()) <=
221 std::abs(stop_distance)) {
222 ADEBUG << "new_relative_time" << new_relative_time;
223 temp_v =
224 fallback_start_point.v() + stop_deceleration * new_relative_time;
225 // speed limit
226 if (std::abs(temp_v) < 1.0) {
227 fallback_trajectory_pair_candidate.first[i].set_v(temp_v);
228 } else {
229 fallback_trajectory_pair_candidate.first[i].set_v(
230 temp_v / std::abs(temp_v) * 1.0);
231 }
232 fallback_trajectory_pair_candidate.first[i].set_a(stop_deceleration);
233
234 fallback_trajectory_pair_candidate.first[i].set_relative_time(
235 new_relative_time);
236 } else {
237 if (i != 0) {
238 fallback_trajectory_pair_candidate.first[i]
239 .mutable_path_point()
240 ->CopyFrom(
241 fallback_trajectory_pair_candidate.first[i - 1].path_point());
242 fallback_trajectory_pair_candidate.first[i].set_v(0.0);
243 fallback_trajectory_pair_candidate.first[i].set_a(0.0);
244 fallback_trajectory_pair_candidate.first[i].set_relative_time(
245 fallback_trajectory_pair_candidate.first[i - 1].relative_time() +
246 0.5);
247 } else {
248 fallback_trajectory_pair_candidate.first[i].set_v(0.0);
249 fallback_trajectory_pair_candidate.first[i].set_a(0.0);
250 }
251 }
252 }
253
254 ADEBUG << "fallback start point after changes: "
255 << fallback_start_point.DebugString();
256
257 ADEBUG << "stop index: " << stop_index;
258 ADEBUG << "fallback start index: " << fallback_start_index;
259
260 // 2. Erase afterwards
261 fallback_trajectory_pair_candidate.first.erase(
262 fallback_trajectory_pair_candidate.first.begin() + stop_index + 1,
263 fallback_trajectory_pair_candidate.first.end());
264
265 // 3. AppendTrajectoryPoint with same location but zero velocity
266 for (int i = 0; i < 20; ++i) {
267 common::TrajectoryPoint trajectory_point(
268 fallback_trajectory_pair_candidate.first[stop_index]);
269 trajectory_point.set_relative_time(
270 i * 0.5 + 0.5 +
271 fallback_trajectory_pair_candidate.first[stop_index].relative_time());
272 fallback_trajectory_pair_candidate.first.AppendTrajectoryPoint(
273 trajectory_point);
274 }
275
277 fallback_trajectory_pair_candidate;
278 } else {
280 }
281
282 if (!IsCollisionFreeEgoBox()) {
283 double relative_time = 0.0;
284 // TODO(Jinyun) Move to conf
285 static constexpr int stop_trajectory_length = 10;
286 static constexpr double relative_stop_time = 0.1;
287 auto fallback_tra_pair =
289
290 fallback_tra_pair->second = canbus::Chassis::GEAR_DRIVE;
291
292 fallback_tra_pair->first.clear();
293 for (size_t i = 0; i < stop_trajectory_length; i++) {
294 TrajectoryPoint point;
295 point.mutable_path_point()->set_x(frame_->vehicle_state().x());
296 point.mutable_path_point()->set_y(frame_->vehicle_state().y());
297 point.mutable_path_point()->set_theta(frame_->vehicle_state().heading());
298 point.mutable_path_point()->set_s(0.0);
299 point.mutable_path_point()->set_kappa(0.0);
300 point.set_relative_time(relative_time);
301 point.set_v(0.0);
302 point.set_a(-4.0);
303 fallback_tra_pair->first.emplace_back(point);
304 relative_time += relative_stop_time;
305 }
306
308
309 } else {
311 }
312
313 return Status::OK();
314}
315
316void OpenSpaceFallbackDecider::BuildPredictedEnvironment(
317 const std::vector<const Obstacle*>& obstacles,
318 std::vector<std::vector<common::math::Box2d>>&
319 predicted_bounding_rectangles) {
320 predicted_bounding_rectangles.clear();
321 double relative_time = 0.0;
322 while (relative_time < config_.open_space_prediction_time_period()) {
323 std::vector<Box2d> predicted_env;
324 for (const Obstacle* obstacle : obstacles) {
325 if (!obstacle->IsVirtual()) {
326 TrajectoryPoint point = obstacle->GetPointAtTime(relative_time);
327 Box2d box = obstacle->GetBoundingBox(point);
328 predicted_env.push_back(std::move(box));
329 }
330 }
331 predicted_bounding_rectangles.emplace_back(std::move(predicted_env));
332 relative_time += FLAGS_trajectory_time_resolution;
333 }
334}
335
336bool OpenSpaceFallbackDecider::IsCollisionFreeEgoBox() {
337 // prediction time resolution: FLAGS_trajectory_time_resolution
338 const auto& vehicle_state = frame_->vehicle_state();
339 double x = vehicle_state.x();
340 double y = vehicle_state.y();
341 double heading = vehicle_state.heading();
342
343 const auto& vehicle_config =
344 common::VehicleConfigHelper::Instance()->GetConfig();
345 double ego_length = vehicle_config.vehicle_param().length();
346 double ego_width = vehicle_config.vehicle_param().width();
347 Box2d ego_box({x, y}, heading, ego_length, ego_width);
348 Polygon2d ego_polygon = Polygon2d(ego_box);
349
350 for (const Obstacle* obstacle : frame_->obstacles()) {
351 if (obstacle->IsVirtual() || !obstacle->IsStatic() ||
352 obstacle->Perception().width() < 0.2 ||
353 obstacle->Perception().length() < 0.2) {
354 continue;
355 }
356 Polygon2d obstacle_polygon = obstacle->PerceptionPolygon();
357 if (ego_polygon.HasOverlap(obstacle_polygon)) {
358 return false;
359 }
360 }
361 return true;
362}
363
364void OpenSpaceFallbackDecider::PathPointNormalizing(
365 double rotate_angle, const Vec2d& translate_origin, double* x, double* y,
366 double* phi) {
367 *x -= translate_origin.x();
368 *y -= translate_origin.y();
369 double tmp_x = *x;
370 *x = (*x) * std::cos(-rotate_angle) - (*y) * std::sin(-rotate_angle);
371 *y = tmp_x * std::sin(-rotate_angle) + (*y) * std::cos(-rotate_angle);
372 *phi = common::math::NormalizeAngle(*phi - rotate_angle);
373}
374
375bool OpenSpaceFallbackDecider::IsCollisionFreeTrajectory(
376 const TrajGearPair& trajectory_gear_pair,
377 const std::vector<std::vector<common::math::Box2d>>&
378 predicted_bounding_rectangles,
379 size_t* current_index, size_t* first_collision_index) {
380 // prediction time resolution: FLAGS_trajectory_time_resolution
381 const auto& vehicle_config =
382 common::VehicleConfigHelper::Instance()->GetConfig();
383 double ego_length = vehicle_config.vehicle_param().length();
384 double ego_width = vehicle_config.vehicle_param().width();
385 auto trajectory_pb = trajectory_gear_pair.first;
386 const size_t point_size = trajectory_pb.NumOfPoints();
387
388 *current_index = trajectory_pb.QueryLowerBoundPoint(0.0);
389
390 for (size_t i = *current_index; i < point_size; ++i) {
391 const auto& trajectory_point = trajectory_pb.TrajectoryPointAt(i);
392 double ego_theta = trajectory_point.path_point().theta();
393 Box2d ego_box(
394 {trajectory_point.path_point().x(), trajectory_point.path_point().y()},
395 ego_theta, ego_length, ego_width);
396 double shift_distance =
397 ego_length / 2.0 - vehicle_config.vehicle_param().back_edge_to_center();
398 Vec2d shift_vec{shift_distance * std::cos(ego_theta),
399 shift_distance * std::sin(ego_theta)};
400 ego_box.Shift(shift_vec);
401 size_t predicted_time_horizon = predicted_bounding_rectangles.size();
402 for (size_t j = 0; j < predicted_time_horizon; j++) {
403 for (const auto& obstacle_box : predicted_bounding_rectangles[j]) {
404 if (ego_box.HasOverlap(obstacle_box)) {
405 ADEBUG << "HasOverlap(obstacle_box) [" << i << "]";
406 const auto& vehicle_state = frame_->vehicle_state();
407 Vec2d vehicle_vec({vehicle_state.x(), vehicle_state.y()});
408 // remove points in previous trajectory
409 if (std::abs(trajectory_point.relative_time() -
410 static_cast<double>(j) *
411 FLAGS_trajectory_time_resolution) <
413 trajectory_point.relative_time() > 0.0) {
414 ADEBUG << "first_collision_index: [" << i << "]";
415 *first_collision_index = i;
416 return false;
417 }
418 }
419 }
420 }
421 }
422
423 return true;
424}
425} // namespace planning
426} // namespace apollo
A general class to denote the return status of an API call.
Definition status.h:43
static Status OK()
generate a success status.
Definition status.h:60
Rectangular (undirected) bounding box in 2-D.
Definition box2d.h:52
The class of polygon in 2-D.
Definition polygon2d.h:42
Implements a class of 2-dimensional vectors.
Definition vec2d.h:42
const OpenSpaceInfo & open_space_info() const
Definition frame.h:167
const common::VehicleState & vehicle_state() const
Definition frame.cc:83
OpenSpaceInfo * mutable_open_space_info()
Definition frame.h:169
bool Init(const std::string &config_dir, const std::string &name, const std::shared_ptr< DependencyInjector > &injector) override
common::TrajectoryPoint * mutable_future_collision_point()
void set_stop_flag(const bool flag)
TrajGearPair * mutable_fallback_trajectory()
void set_fallback_flag(const bool flag)
std::shared_ptr< DependencyInjector > injector_
Definition task.h:59
virtual bool Init(const std::string &config_dir, const std::string &name, const std::shared_ptr< DependencyInjector > &injector)
Definition task.cc:40
Planning module main class.
#define ADEBUG
Definition log.h:41
#define AINFO
Definition log.h:42
double NormalizeAngle(const double angle)
Normalize angle to [-PI, PI).
Definition math_utils.cc:53
std::pair< DiscretizedTrajectory, canbus::Chassis::GearPosition > TrajGearPair
class register implement
Definition arena_queue.h:37
Definition future.h:29