Skip to content

Commit 8b98b22

Browse files
feat(autoware_behavior_path_planner): prevent infinite loop in approving scene module process (autowarefoundation#7881)
* prevent infinite loop Signed-off-by: kyoichi-sugahara <kyoichi.sugahara@tier4.jp> * calculate max_iteration_num from number of scene modules Signed-off-by: kyoichi-sugahara <kyoichi.sugahara@tier4.jp> * add doxygen explanation for calculateMaxIterationNum Signed-off-by: kyoichi-sugahara <kyoichi.sugahara@tier4.jp> --------- Signed-off-by: kyoichi-sugahara <kyoichi.sugahara@tier4.jp>
1 parent 61509a2 commit 8b98b22

File tree

4 files changed

+56
-15
lines changed

4 files changed

+56
-15
lines changed

planning/behavior_path_planner/config/behavior_path_planner.param.yaml

-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
/**:
22
ros__parameters:
3-
max_iteration_num: 100
43
traffic_light_signal_timeout: 1.0
54
planning_hz: 10.0
65
backward_path_length: 5.0

planning/behavior_path_planner/include/behavior_path_planner/planner_manager.hpp

+19-4
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ struct SceneModuleStatus
9696
class PlannerManager
9797
{
9898
public:
99-
PlannerManager(rclcpp::Node & node, const size_t max_iteration_num);
99+
explicit PlannerManager(rclcpp::Node & node);
100100

101101
/**
102102
* @brief run all candidate and approved modules.
@@ -111,6 +111,17 @@ class PlannerManager
111111
*/
112112
void launchScenePlugin(rclcpp::Node & node, const std::string & name);
113113

114+
/**
115+
* @brief calculate max iteration numbers.
116+
* Let N be the number of scene modules. The maximum number of iterations executed in a loop is N,
117+
* but after that, if there are any modules that have succeeded or failed, the approve_modules of
118+
* all modules are cleared, and the loop is executed for N-1 modules. As this process repeats, it
119+
* becomes N + (N-1) + (N-2) + … + 1, therefore the maximum number of iterations is N(N+1)/2.
120+
* @param number of scene module
121+
*
122+
*/
123+
void calculateMaxIterationNum(const size_t scene_module_num);
124+
114125
/**
115126
* @brief unregister managers.
116127
* @param node.
@@ -393,11 +404,13 @@ class PlannerManager
393404
* @brief run all modules in approved_module_ptrs_ and get a planning result as
394405
* approved_modules_output.
395406
* @param planner data.
407+
* @param deleted modules.
396408
* @return valid planning result.
397409
* @details in this function, expired modules (ModuleStatus::FAILURE or ModuleStatus::SUCCESS) are
398-
* removed from approved_module_ptrs_.
410+
* removed from approved_module_ptrs_ and added to deleted_modules.
399411
*/
400-
BehaviorModuleOutput runApprovedModules(const std::shared_ptr<PlannerData> & data);
412+
BehaviorModuleOutput runApprovedModules(
413+
const std::shared_ptr<PlannerData> & data, std::vector<SceneModulePtr> & deleted_modules);
401414

402415
/**
403416
* @brief select a module that should be execute at first.
@@ -417,10 +430,12 @@ class PlannerManager
417430
/**
418431
* @brief get all modules that make execution request.
419432
* @param decided (=approved) path.
433+
* @param deleted modules.
420434
* @return request modules.
421435
*/
422436
std::vector<SceneModulePtr> getRequestModules(
423-
const BehaviorModuleOutput & previous_module_output) const;
437+
const BehaviorModuleOutput & previous_module_output,
438+
const std::vector<SceneModulePtr> & deleted_modules) const;
424439

425440
/**
426441
* @brief checks whether a path of trajectory has forward driving direction

planning/behavior_path_planner/src/behavior_path_planner_node.cpp

+4-3
Original file line numberDiff line numberDiff line change
@@ -132,16 +132,18 @@ BehaviorPathPlannerNode::BehaviorPathPlannerNode(const rclcpp::NodeOptions & nod
132132

133133
const std::lock_guard<std::mutex> lock(mutex_manager_); // for planner_manager_
134134

135-
const auto & p = planner_data_->parameters;
136-
planner_manager_ = std::make_shared<PlannerManager>(*this, p.max_iteration_num);
135+
planner_manager_ = std::make_shared<PlannerManager>(*this);
137136

137+
size_t scene_module_num = 0;
138138
for (const auto & name : declare_parameter<std::vector<std::string>>("launch_modules")) {
139139
// workaround: Since ROS 2 can't get empty list, launcher set [''] on the parameter.
140140
if (name == "") {
141141
break;
142142
}
143143
planner_manager_->launchScenePlugin(*this, name);
144+
scene_module_num++;
144145
}
146+
planner_manager_->calculateMaxIterationNum(scene_module_num);
145147

146148
for (const auto & manager : planner_manager_->getSceneModuleManagers()) {
147149
path_candidate_publishers_.emplace(
@@ -208,7 +210,6 @@ BehaviorPathPlannerParameters BehaviorPathPlannerNode::getCommonParam()
208210
{
209211
BehaviorPathPlannerParameters p{};
210212

211-
p.max_iteration_num = declare_parameter<int>("max_iteration_num");
212213
p.traffic_light_signal_timeout = declare_parameter<double>("traffic_light_signal_timeout");
213214

214215
// vehicle info

planning/behavior_path_planner/src/planner_manager.cpp

+33-7
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,10 @@
3030

3131
namespace behavior_path_planner
3232
{
33-
PlannerManager::PlannerManager(rclcpp::Node & node, const size_t max_iteration_num)
33+
PlannerManager::PlannerManager(rclcpp::Node & node)
3434
: plugin_loader_("behavior_path_planner", "behavior_path_planner::SceneModuleManagerInterface"),
3535
logger_(node.get_logger().get_child("planner_manager")),
36-
clock_(*node.get_clock()),
37-
max_iteration_num_{max_iteration_num}
36+
clock_(*node.get_clock())
3837
{
3938
processing_time_.emplace("total_time", 0.0);
4039
debug_publisher_ptr_ = std::make_unique<DebugPublisher>(&node, "~/debug");
@@ -64,6 +63,11 @@ void PlannerManager::launchScenePlugin(rclcpp::Node & node, const std::string &
6463
}
6564
}
6665

66+
void PlannerManager::calculateMaxIterationNum(const size_t scene_module_num)
67+
{
68+
max_iteration_num_ = scene_module_num * (scene_module_num + 1) / 2;
69+
}
70+
6771
void PlannerManager::removeScenePlugin(rclcpp::Node & node, const std::string & name)
6872
{
6973
auto it = std::remove_if(manager_ptrs_.begin(), manager_ptrs_.end(), [&](const auto plugin) {
@@ -122,17 +126,19 @@ BehaviorModuleOutput PlannerManager::run(const std::shared_ptr<PlannerData> & da
122126
"Ego is out of route, no module is running. Skip running scene modules.");
123127
return output;
124128
}
129+
std::vector<SceneModulePtr>
130+
deleted_modules; // store the scene modules deleted from approved modules
125131

126132
for (size_t itr_num = 1;; ++itr_num) {
127133
/**
128134
* STEP1: get approved modules' output
129135
*/
130-
auto approved_modules_output = runApprovedModules(data);
136+
auto approved_modules_output = runApprovedModules(data, deleted_modules);
131137

132138
/**
133139
* STEP2: check modules that need to be launched
134140
*/
135-
const auto request_modules = getRequestModules(approved_modules_output);
141+
const auto request_modules = getRequestModules(approved_modules_output, deleted_modules);
136142

137143
/**
138144
* STEP3: if there is no module that need to be launched, return approved modules' output
@@ -243,7 +249,8 @@ void PlannerManager::generateCombinedDrivableArea(
243249
}
244250

245251
std::vector<SceneModulePtr> PlannerManager::getRequestModules(
246-
const BehaviorModuleOutput & previous_module_output) const
252+
const BehaviorModuleOutput & previous_module_output,
253+
const std::vector<SceneModulePtr> & deleted_modules) const
247254
{
248255
if (previous_module_output.path.points.empty()) {
249256
RCLCPP_ERROR_STREAM(
@@ -261,6 +268,18 @@ std::vector<SceneModulePtr> PlannerManager::getRequestModules(
261268

262269
for (const auto & manager_ptr : manager_ptrs_) {
263270
stop_watch_.tic(manager_ptr->name());
271+
/**
272+
* skip the module that is already deleted.
273+
*/
274+
{
275+
const auto name = manager_ptr->name();
276+
const auto find_deleted_module = [&name](const auto & m) { return m->name() == name; };
277+
const auto itr =
278+
std::find_if(deleted_modules.begin(), deleted_modules.end(), find_deleted_module);
279+
if (itr != deleted_modules.end()) {
280+
continue;
281+
}
282+
}
264283

265284
/**
266285
* determine the execution capability of modules based on existing approved modules.
@@ -635,7 +654,8 @@ std::pair<SceneModulePtr, BehaviorModuleOutput> PlannerManager::runRequestModule
635654
return std::make_pair(module_ptr, results.at(module_ptr->name()));
636655
}
637656

638-
BehaviorModuleOutput PlannerManager::runApprovedModules(const std::shared_ptr<PlannerData> & data)
657+
BehaviorModuleOutput PlannerManager::runApprovedModules(
658+
const std::shared_ptr<PlannerData> & data, std::vector<SceneModulePtr> & deleted_modules)
639659
{
640660
std::unordered_map<std::string, BehaviorModuleOutput> results;
641661
BehaviorModuleOutput output = getReferencePath(data);
@@ -751,6 +771,9 @@ BehaviorModuleOutput PlannerManager::runApprovedModules(const std::shared_ptr<Pl
751771
const auto itr = std::find_if(
752772
approved_module_ptrs_.begin(), approved_module_ptrs_.end(),
753773
[](const auto & m) { return m->getCurrentStatus() == ModuleStatus::FAILURE; });
774+
if (itr != approved_module_ptrs_.end()) {
775+
deleted_modules.push_back(*itr);
776+
}
754777

755778
std::for_each(itr, approved_module_ptrs_.end(), [this](auto & m) {
756779
debug_info_.emplace_back(m, Action::DELETE, "From Approved");
@@ -822,6 +845,9 @@ BehaviorModuleOutput PlannerManager::runApprovedModules(const std::shared_ptr<Pl
822845
}))
823846
resetCurrentRouteLanelet(data);
824847

848+
std::copy_if(
849+
itr, approved_module_ptrs_.end(), std::back_inserter(deleted_modules), success_module_cond);
850+
825851
std::for_each(itr, approved_module_ptrs_.end(), [&](auto & m) {
826852
debug_info_.emplace_back(m, Action::DELETE, "From Approved");
827853
deleteExpiredModules(m);

0 commit comments

Comments
 (0)