Apollo 11.0
自动驾驶开放平台
apollo::planning::STObstaclesProcessor类 参考

#include <st_obstacles_processor.h>

apollo::planning::STObstaclesProcessor 的协作图:

Public 成员函数

 STObstaclesProcessor ()
 
void Init (const double planning_distance, const double planning_time, const PathData &path_data, PathDecision *const path_decision, History *const history)
 
virtual ~STObstaclesProcessor ()=default
 
common::Status MapObstaclesToSTBoundaries (PathDecision *const path_decision)
 
std::unordered_map< std::string, STBoundary > GetAllSTBoundaries ()
 
bool GetSBoundsFromDecisions (double t, std::vector< std::pair< double, double > > *const available_s_bounds, std::vector< std::vector< std::pair< std::string, ObjectDecisionType > > > *const available_obs_decisions)
 Given a time t, get the lower and upper s-boundaries.
 
bool GetLimitingSpeedInfo (double t, std::pair< double, double > *const limiting_speed_info)
 Provided that decisions for all existing obstacles are made, get the speed limiting info from limiting st-obstacles.
 
void SetObstacleDecision (const std::string &obs_id, const ObjectDecisionType &obs_decision)
 Set the decision for a given obstacle.
 
void SetObstacleDecision (const std::vector< std::pair< std::string, ObjectDecisionType > > &obstacle_decisions)
 Set the decision for a list of obstacles.
 

详细描述

在文件 st_obstacles_processor.h 第 48 行定义.

构造及析构函数说明

◆ STObstaclesProcessor()

apollo::planning::STObstaclesProcessor::STObstaclesProcessor ( )
inline

在文件 st_obstacles_processor.h 第 50 行定义.

50{}

◆ ~STObstaclesProcessor()

virtual apollo::planning::STObstaclesProcessor::~STObstaclesProcessor ( )
virtualdefault

成员函数说明

◆ GetAllSTBoundaries()

std::unordered_map< std::string, STBoundary > apollo::planning::STObstaclesProcessor::GetAllSTBoundaries ( )

在文件 st_obstacles_processor.cc 第 273 行定义.

273 {
274 return obs_id_to_st_boundary_;
275}

◆ GetLimitingSpeedInfo()

bool apollo::planning::STObstaclesProcessor::GetLimitingSpeedInfo ( double  t,
std::pair< double, double > *const  limiting_speed_info 
)

Provided that decisions for all existing obstacles are made, get the speed limiting info from limiting st-obstacles.

参数
Timet.
Theactual limiting speed-info: (lower, upper)
返回
True if there is speed limiting info; otherwise, false.

在文件 st_obstacles_processor.cc 第 277 行定义.

278 {
279 if (obs_id_to_decision_.empty()) {
280 // If no obstacle, then no speed limits.
281 return false;
282 }
283
284 double s_min = 0.0;
285 double s_max = planning_distance_;
286 for (auto it : obs_id_to_decision_) {
287 auto obs_id = it.first;
288 auto obs_decision = it.second;
289 auto obs_st_boundary = obs_id_to_st_boundary_[obs_id];
290 double obs_s_min = 0.0;
291 double obs_s_max = 0.0;
292 obs_st_boundary.GetBoundarySRange(t, &obs_s_max, &obs_s_min);
293 double obs_ds_lower = 0.0;
294 double obs_ds_upper = 0.0;
295 obs_st_boundary.GetBoundarySlopes(t, &obs_ds_upper, &obs_ds_lower);
296 if (obs_decision.has_yield() || obs_decision.has_stop()) {
297 if (obs_s_min <= s_max) {
298 s_max = obs_s_min;
299 limiting_speed_info->second = obs_ds_lower;
300 }
301 } else if (it.second.has_overtake()) {
302 if (obs_s_max >= s_min) {
303 s_min = obs_s_max;
304 limiting_speed_info->first = obs_ds_upper;
305 }
306 }
307 }
308 return s_min <= s_max;
309}

◆ GetSBoundsFromDecisions()

bool apollo::planning::STObstaclesProcessor::GetSBoundsFromDecisions ( double  t,
std::vector< std::pair< double, double > > *const  available_s_bounds,
std::vector< std::vector< std::pair< std::string, ObjectDecisionType > > > *const  available_obs_decisions 
)

Given a time t, get the lower and upper s-boundaries.

If the boundary is well-defined based on decision made previously, fill "available_s_bounds" with only one boundary. Otherwise, fill "available_s_bounds with all candidates and "available_obs_decisions" with corresponding possible obstacle decisions.

参数
Timet
Theavailable s-boundaries to be filled up.
Thecorresponding possible obstacle decisions.
返回
Whether we can get valid s-bounds.

在文件 st_obstacles_processor.cc 第 311 行定义.

314 {
315 // Sanity checks.
316 available_s_bounds->clear();
317 available_obs_decisions->clear();
318
319 // Gather any possible change in st-boundary situations.
320 ADEBUG << "There are " << obs_t_edges_.size() << " t-edges.";
321 std::vector<ObsTEdge> new_t_edges;
322 while (obs_t_edges_idx_ < static_cast<int>(obs_t_edges_.size()) &&
323 std::get<1>(obs_t_edges_[obs_t_edges_idx_]) <= t) {
324 if (std::get<0>(obs_t_edges_[obs_t_edges_idx_]) == 0 &&
325 std::get<1>(obs_t_edges_[obs_t_edges_idx_]) == t) {
326 break;
327 }
328 ADEBUG << "Seeing a new t-edge at t = "
329 << std::get<1>(obs_t_edges_[obs_t_edges_idx_]);
330 new_t_edges.push_back(obs_t_edges_[obs_t_edges_idx_]);
331 ++obs_t_edges_idx_;
332 }
333
334 // For st-boundaries that disappeared before t, remove them.
335 for (const auto& obs_t_edge : new_t_edges) {
336 if (std::get<0>(obs_t_edge) == 0) {
337 ADEBUG << "Obstacle id: " << std::get<4>(obs_t_edge)
338 << " is leaving st-graph.";
339 if (obs_id_to_decision_.count(std::get<4>(obs_t_edge)) != 0) {
340 obs_id_to_decision_.erase(std::get<4>(obs_t_edge));
341 }
342 }
343 }
344
345 // For overtaken obstacles, remove them if we are after
346 // their high right-of-road ending time (with a margin).
347 std::vector<std::string> obs_id_to_remove;
348 for (const auto& obs_id_to_decision_pair : obs_id_to_decision_) {
349 auto obs_id = obs_id_to_decision_pair.first;
350 auto obs_decision = obs_id_to_decision_pair.second;
351 auto obs_st_boundary = obs_id_to_st_boundary_[obs_id];
352 if (obs_decision.has_overtake() &&
353 obs_st_boundary.min_t() <= t - kOvertakenObsCautionTime &&
354 obs_st_boundary.obstacle_road_right_ending_t() <=
356 obs_id_to_remove.push_back(obs_id_to_decision_pair.first);
357 }
358 }
359 for (const auto& obs_id : obs_id_to_remove) {
360 obs_id_to_decision_.erase(obs_id);
361 // Change the displayed st-boundary to the alternative one:
362 if (obs_id_to_alternative_st_boundary_.count(obs_id) > 0) {
363 Obstacle* obs_ptr = path_decision_->Find(obs_id);
364 obs_id_to_st_boundary_[obs_id] =
365 obs_id_to_alternative_st_boundary_[obs_id];
366 obs_id_to_st_boundary_[obs_id].SetBoundaryType(
368 obs_ptr->set_path_st_boundary(obs_id_to_alternative_st_boundary_[obs_id]);
369 }
370 }
371
372 // Based on existing decisions, get the s-boundary.
373 double s_min = 0.0;
374 double s_max = planning_distance_;
375 for (auto it : obs_id_to_decision_) {
376 auto obs_id = it.first;
377 auto obs_decision = it.second;
378 auto obs_st_boundary = obs_id_to_st_boundary_[obs_id];
379 double obs_s_min = 0.0;
380 double obs_s_max = 0.0;
381 obs_st_boundary.GetBoundarySRange(t, &obs_s_max, &obs_s_min);
382 if (obs_decision.has_yield() || obs_decision.has_stop()) {
383 s_max = std::fmin(s_max, obs_s_min);
384 } else if (it.second.has_overtake()) {
385 s_min = std::fmax(s_min, obs_s_max);
386 }
387 }
388 if (s_min > s_max) {
389 return false;
390 }
391 ADEBUG << "S-boundary based on existing decisions = (" << s_min << ", "
392 << s_max << ")";
393
394 // For newly entering st_boundaries, determine possible new-boundaries.
395 // For apparent ones, make decisions directly.
396 std::vector<ObsTEdge> ambiguous_t_edges;
397 for (auto obs_t_edge : new_t_edges) {
398 ADEBUG << "For obstacle id: " << std::get<4>(obs_t_edge)
399 << ", its s-range = [" << std::get<2>(obs_t_edge) << ", "
400 << std::get<3>(obs_t_edge) << "]";
401 if (std::get<0>(obs_t_edge) == 1) {
402 if (std::get<2>(obs_t_edge) >= s_max) {
403 ADEBUG << " Apparently, it should be yielded.";
404 obs_id_to_decision_[std::get<4>(obs_t_edge)] =
405 DetermineObstacleDecision(std::get<2>(obs_t_edge),
406 std::get<3>(obs_t_edge), s_max);
407 obs_id_to_st_boundary_[std::get<4>(obs_t_edge)].SetBoundaryType(
409 } else if (std::get<3>(obs_t_edge) <= s_min) {
410 ADEBUG << " Apparently, it should be overtaken.";
411 obs_id_to_decision_[std::get<4>(obs_t_edge)] =
412 DetermineObstacleDecision(std::get<2>(obs_t_edge),
413 std::get<3>(obs_t_edge), s_min);
414 obs_id_to_st_boundary_[std::get<4>(obs_t_edge)].SetBoundaryType(
416 } else {
417 ADEBUG << " It should be further analyzed.";
418 ambiguous_t_edges.push_back(obs_t_edge);
419 }
420 }
421 }
422 // For ambiguous ones, enumerate all decisions and corresponding bounds.
423 auto s_gaps = FindSGaps(ambiguous_t_edges, s_min, s_max);
424 if (s_gaps.empty()) {
425 return false;
426 }
427 for (auto s_gap : s_gaps) {
428 available_s_bounds->push_back(s_gap);
429 std::vector<std::pair<std::string, ObjectDecisionType>> obs_decisions;
430 for (auto obs_t_edge : ambiguous_t_edges) {
431 std::string obs_id = std::get<4>(obs_t_edge);
432 double obs_s_min = std::get<2>(obs_t_edge);
433 double obs_s_max = std::get<3>(obs_t_edge);
434 obs_decisions.emplace_back(
435 obs_id,
436 DetermineObstacleDecision(obs_s_min, obs_s_max,
437 (s_gap.first + s_gap.second) / 2.0));
438 }
439 available_obs_decisions->push_back(obs_decisions);
440 }
441
442 return true;
443}
const Obstacle * Find(const std::string &object_id) const
#define ADEBUG
Definition log.h:41
constexpr double kOvertakenObsCautionTime

◆ Init()

void apollo::planning::STObstaclesProcessor::Init ( const double  planning_distance,
const double  planning_time,
const PathData &  path_data,
PathDecision *const  path_decision,
History *const  history 
)

在文件 st_obstacles_processor.cc 第 50 行定义.

54 {
55 planning_time_ = planning_time;
56 planning_distance_ = planning_distance;
57 path_data_ = path_data;
59 adc_path_init_s_ = path_data_.discretized_path().front().s();
60 path_decision_ = path_decision;
61 history_ = history;
62
63 obs_t_edges_.clear();
64 obs_t_edges_idx_ = 0;
65
66 obs_id_to_st_boundary_.clear();
67 obs_id_to_decision_.clear();
68 candidate_clear_zones_.clear();
69 obs_id_to_alternative_st_boundary_.clear();
70}
static const VehicleConfig & GetConfig()
Get the current vehicle configuration.
const DiscretizedPath & discretized_path() const
Definition path_data.cc:90
optional VehicleParam vehicle_param

◆ MapObstaclesToSTBoundaries()

Status apollo::planning::STObstaclesProcessor::MapObstaclesToSTBoundaries ( PathDecision *const  path_decision)

在文件 st_obstacles_processor.cc 第 72 行定义.

73 {
74 // Sanity checks.
75 if (path_decision == nullptr) {
76 const std::string msg = "path_decision is nullptr";
77 AERROR << msg;
78 return Status(ErrorCode::PLANNING_ERROR, msg);
79 }
80 if (planning_time_ < 0.0) {
81 const std::string msg = "Negative planning time.";
82 AERROR << msg;
83 return Status(ErrorCode::PLANNING_ERROR, msg);
84 }
85 if (planning_distance_ < 0.0) {
86 const std::string msg = "Negative planning distance.";
87 AERROR << msg;
88 return Status(ErrorCode::PLANNING_ERROR, msg);
89 }
90 if (path_data_.discretized_path().size() <= 1) {
91 const std::string msg = "Number of path points is too few.";
92 AERROR << msg;
93 return Status(ErrorCode::PLANNING_ERROR, msg);
94 }
95 obs_id_to_st_boundary_.clear();
96
97 // Some preprocessing to save the adc_low_road_right segments.
98 bool is_adc_low_road_right_beginning = true;
99 for (const auto& path_pt_info : path_data_.path_point_decision_guide()) {
100 double path_pt_s = 0.0;
101 PathData::PathPointType path_pt_type;
102 std::tie(path_pt_s, path_pt_type, std::ignore) = path_pt_info;
105 if (is_adc_low_road_right_beginning) {
106 adc_low_road_right_segments_.emplace_back(path_pt_s, path_pt_s);
107 is_adc_low_road_right_beginning = false;
108 } else {
109 adc_low_road_right_segments_.back().second = path_pt_s;
110 }
111 } else if (path_pt_type == PathData::PathPointType::IN_LANE) {
112 if (!is_adc_low_road_right_beginning) {
113 is_adc_low_road_right_beginning = true;
114 }
115 }
116 }
117
118 // Map obstacles into ST-graph.
119 // Go through every obstacle and plot them in ST-graph.
120 std::unordered_set<std::string> non_ignore_obstacles;
121 std::tuple<std::string, STBoundary, Obstacle*> closest_stop_obstacle;
122 std::get<0>(closest_stop_obstacle) = "NULL";
123 for (const auto* obs_item_ptr : path_decision->obstacles().Items()) {
124 // Sanity checks.
125 Obstacle* obs_ptr = path_decision->Find(obs_item_ptr->Id());
126 if (obs_ptr == nullptr) {
127 const std::string msg = "Null obstacle pointer.";
128 AERROR << msg;
129 return Status(ErrorCode::PLANNING_ERROR, msg);
130 }
131
132 // Draw the obstacle's st-boundary.
133 std::vector<STPoint> lower_points;
134 std::vector<STPoint> upper_points;
135 bool is_caution_obstacle = false;
136 double obs_caution_end_t = 0.0;
137 if (!ComputeObstacleSTBoundary(*obs_ptr, &lower_points, &upper_points,
138 &is_caution_obstacle, &obs_caution_end_t)) {
139 // Obstacle doesn't appear on ST-Graph.
140 continue;
141 }
142 auto boundary =
143 STBoundary::CreateInstanceAccurate(lower_points, upper_points);
144 boundary.set_id(obs_ptr->Id());
145 if (is_caution_obstacle) {
146 boundary.set_obstacle_road_right_ending_t(obs_caution_end_t);
147 }
148 // Update the trimmed obstacle into alternative st-bound storage
149 // for later uses.
150 while (lower_points.size() > 2 &&
151 lower_points.back().t() > obs_caution_end_t) {
152 lower_points.pop_back();
153 }
154 while (upper_points.size() > 2 &&
155 upper_points.back().t() > obs_caution_end_t) {
156 upper_points.pop_back();
157 }
158 auto alternative_boundary =
159 STBoundary::CreateInstanceAccurate(lower_points, upper_points);
160 alternative_boundary.set_id(obs_ptr->Id());
161 obs_id_to_alternative_st_boundary_[obs_ptr->Id()] = alternative_boundary;
162 ADEBUG << "Obstacle " << obs_ptr->Id()
163 << " has an alternative st-boundary with "
164 << lower_points.size() + upper_points.size() << " points.";
165
166 // Store all Keep-Clear zone together.
167 if (obs_item_ptr->Id().find("KC") != std::string::npos) {
168 candidate_clear_zones_.push_back(
169 make_tuple(obs_ptr->Id(), boundary, obs_ptr));
170 continue;
171 }
172
173 // Process all other obstacles than Keep-Clear zone.
174 if (obs_ptr->Trajectory().trajectory_point().empty()) {
175 // Obstacle is static.
176 if (std::get<0>(closest_stop_obstacle) == "NULL" ||
177 std::get<1>(closest_stop_obstacle).bottom_left_point().s() >
178 boundary.bottom_left_point().s()) {
179 // If this static obstacle is closer for ADC to stop, record it.
180 closest_stop_obstacle =
181 std::make_tuple(obs_ptr->Id(), boundary, obs_ptr);
182 }
183 } else {
184 // Obstacle is dynamic.
185 if (boundary.bottom_left_point().s() - adc_path_init_s_ <
187 boundary.bottom_left_point().t() > kTIgnoreThreshold) {
188 // Ignore obstacles that are behind.
189 // TODO(jiacheng): don't ignore if ADC is in dangerous segments.
190 continue;
191 }
192 obs_id_to_st_boundary_[obs_ptr->Id()] = boundary;
193 obs_ptr->set_path_st_boundary(boundary);
194 non_ignore_obstacles.insert(obs_ptr->Id());
195 ADEBUG << "Adding " << obs_ptr->Id() << " into the ST-graph.";
196 }
197 }
198 // For static obstacles, only retain the closest one (also considers
199 // Keep-Clear zone here).
200 // Note: We only need to check the overlapping between the closest obstacle
201 // and all the Keep-Clear zones. Because if there is another obstacle
202 // overlapping with a Keep-Clear zone, which results in an even closer
203 // stop fence, then that very Keep-Clear zone must also overlap with
204 // the closest obstacle. (Proof omitted here)
205 if (std::get<0>(closest_stop_obstacle) != "NULL") {
206 std::string closest_stop_obs_id;
207 STBoundary closest_stop_obs_boundary;
208 Obstacle* closest_stop_obs_ptr;
209 std::tie(closest_stop_obs_id, closest_stop_obs_boundary,
210 closest_stop_obs_ptr) = closest_stop_obstacle;
211 ADEBUG << "Closest obstacle ID = " << closest_stop_obs_id;
212 // Go through all Keep-Clear zones, and see if there is an even closer
213 // stop fence due to them.
214 if (!closest_stop_obs_ptr->IsVirtual()) {
215 for (const auto& clear_zone : candidate_clear_zones_) {
216 const auto& clear_zone_boundary = std::get<1>(clear_zone);
217 if (closest_stop_obs_boundary.min_s() >= clear_zone_boundary.min_s() &&
218 closest_stop_obs_boundary.min_s() <= clear_zone_boundary.max_s()) {
219 std::tie(closest_stop_obs_id, closest_stop_obs_boundary,
220 closest_stop_obs_ptr) = clear_zone;
221 ADEBUG << "Clear zone " << closest_stop_obs_id << " is closer.";
222 break;
223 }
224 }
225 }
226 obs_id_to_st_boundary_[closest_stop_obs_id] = closest_stop_obs_boundary;
227 closest_stop_obs_ptr->set_path_st_boundary(closest_stop_obs_boundary);
228 non_ignore_obstacles.insert(closest_stop_obs_id);
229 ADEBUG << "Adding " << closest_stop_obs_ptr->Id() << " into the ST-graph.";
230 ADEBUG << "min_s = " << closest_stop_obs_boundary.min_s();
231 }
232
233 // Set IGNORE decision for those that are not in ST-graph:
234 for (const auto* obs_item_ptr : path_decision->obstacles().Items()) {
235 Obstacle* obs_ptr = path_decision->Find(obs_item_ptr->Id());
236 if (non_ignore_obstacles.count(obs_ptr->Id()) == 0) {
237 ObjectDecisionType ignore_decision;
238 ignore_decision.mutable_ignore();
239 if (!obs_ptr->HasLongitudinalDecision()) {
240 obs_ptr->AddLongitudinalDecision("st_obstacle_processor",
241 ignore_decision);
242 }
243 if (!obs_ptr->HasLateralDecision()) {
244 obs_ptr->AddLateralDecision("st_obstacle_processor", ignore_decision);
245 }
246 }
247 }
248
249 // Preprocess the obstacles for sweep-line algorithms.
250 // Fetch every obstacle's beginning end ending t-edges only.
251 for (const auto& it : obs_id_to_st_boundary_) {
252 obs_t_edges_.emplace_back(true, it.second.min_t(),
253 it.second.bottom_left_point().s(),
254 it.second.upper_left_point().s(), it.first);
255 obs_t_edges_.emplace_back(false, it.second.max_t(),
256 it.second.bottom_right_point().s(),
257 it.second.upper_right_point().s(), it.first);
258 }
259 // Sort the edges.
260 std::sort(obs_t_edges_.begin(), obs_t_edges_.end(),
261 [](const ObsTEdge& lhs, const ObsTEdge& rhs) {
262 if (std::get<1>(lhs) != std::get<1>(rhs)) {
263 return std::get<1>(lhs) < std::get<1>(rhs);
264 } else {
265 return std::get<0>(lhs) > std::get<0>(rhs);
266 }
267 });
268
269 return Status::OK();
270}
static Status OK()
generate a success status.
Definition status.h:60
static STBoundary CreateInstanceAccurate(const std::vector< STPoint > &lower_points, const std::vector< STPoint > &upper_points)
Wrapper of the constructor.
#define AERROR
Definition log.h:44
constexpr double kSIgnoreThreshold
constexpr double kTIgnoreThreshold

◆ SetObstacleDecision() [1/2]

void apollo::planning::STObstaclesProcessor::SetObstacleDecision ( const std::string &  obs_id,
const ObjectDecisionType &  obs_decision 
)

Set the decision for a given obstacle.

在文件 st_obstacles_processor.cc 第 445 行定义.

446 {
447 obs_id_to_decision_[obs_id] = obs_decision;
448 ObjectStatus object_status;
449 object_status.mutable_motion_type()->mutable_dynamic();
450 if (obs_decision.has_yield() || obs_decision.has_stop()) {
451 obs_id_to_st_boundary_[obs_id].SetBoundaryType(
453 object_status.mutable_decision_type()->mutable_yield();
454 } else if (obs_decision.has_overtake()) {
455 obs_id_to_st_boundary_[obs_id].SetBoundaryType(
457 object_status.mutable_decision_type()->mutable_overtake();
458 }
459 history_->mutable_history_status()->SetObjectStatus(obs_id, object_status);
460}
void SetObjectStatus(const std::string &id, const ObjectStatus &object_status)
Definition history.cc:137
HistoryStatus * mutable_history_status()
Definition history.h:107

◆ SetObstacleDecision() [2/2]

void apollo::planning::STObstaclesProcessor::SetObstacleDecision ( const std::vector< std::pair< std::string, ObjectDecisionType > > &  obstacle_decisions)

Set the decision for a list of obstacles.

在文件 st_obstacles_processor.cc 第 462 行定义.

464 {
465 for (auto obs_decision : obstacle_decisions) {
466 SetObstacleDecision(obs_decision.first, obs_decision.second);
467 }
468}
void SetObstacleDecision(const std::string &obs_id, const ObjectDecisionType &obs_decision)
Set the decision for a given obstacle.

该类的文档由以下文件生成: