Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(goal_planner): divide Planners to isolated threads #9514

Merged
merged 10 commits into from
Dec 15, 2024

Conversation

soblin
Copy link
Contributor

@soblin soblin commented Nov 28, 2024

Description

Currently thread_safe_data_ member variable is accessed from many member functions. This structure is not healthy because there are other possible not thread-safe member variables, and numerous number of call to lock() is very insufficient.

After this PR, there are 3 agents

  • goal_planner_module
  • LaneParkingPlannerThread
  • FreespaceParkingThread

goal_planner_module

Lock the lane_parking_mutex_, and

  • prepare the LaneParkingRequest member
  • copy the LaneParkingResponse to local scope

Lock the freespace_parking_mutex_, and

  • prepare the FreespaceParkingRequest member
  • copy the FreespaceParkingResponse to local scope

LaneParkingThread

Lock the lane_parking_mutex_ which is shared with goal_planner_module via reference, and

  • copy LaneParkingResponse to local scope

After computation,
Lock the lane_parking_mutex_, and

  • set LaneParkingResponse

This will be used by goal_planner_module

FreespaceParkingThread

Lock the freespace_parking_mutex_ which is shared with goal_planner_module via reference, and

  • copy FreespaceParkingResponse to local scope

After computation,
Lock the freespace_parking_mutex_, and

  • set FreespaceParkingResponse

This will be used by goal_planner_module

Overall, thread safe data has been divided to above 4 classes, and the response value is copied to module side PullOverContextData member, so repetitive access to thread_safe_data with lock have been purged.

Related links

Parent Issue:

How was this PR tested?

Notes for reviewers

None.

Interface changes

None.

Effects on system behavior

None.

@github-actions github-actions bot added the component:planning Route planning, decision-making, and navigation. (auto-assigned) label Nov 28, 2024
Copy link

github-actions bot commented Nov 28, 2024

Thank you for contributing to the Autoware project!

🚧 If your pull request is in progress, switch it to draft mode.

Please ensure:

@soblin soblin force-pushed the feat/goal-planner/divide-thread branch 5 times, most recently from 6161574 to 919e4b9 Compare November 28, 2024 12:05
@soblin soblin force-pushed the feat/goal-planner/divide-thread branch 8 times, most recently from e183b1e to b172a68 Compare December 2, 2024 06:35
@soblin soblin force-pushed the feat/goal-planner/divide-thread branch 12 times, most recently from 7410599 to 4ce8b96 Compare December 12, 2024 08:51
Signed-off-by: Mamoru Sobue <[email protected]>
Signed-off-by: Mamoru Sobue <[email protected]>
@soblin soblin force-pushed the feat/goal-planner/divide-thread branch from 4ce8b96 to 4edb7a1 Compare December 12, 2024 14:01
@soblin soblin marked this pull request as ready for review December 12, 2024 15:13
Signed-off-by: Mamoru Sobue <[email protected]>
Comment on lines 94 to 101
auto lane_parking_planner = std::make_unique<LaneParkingPlanner>(
node, lane_parking_mutex_, lane_parking_request_, lane_parking_response_,
is_lane_parking_cb_running_, getLogger(), *parameters_);
lane_parking_timer_ = rclcpp::create_timer(
&node, clock_, lane_parking_period_ns, std::bind(&GoalPlannerModule::onTimer, this),
&node, clock_, lane_parking_period_ns,
[lane_parking_planner_bind = std::move(lane_parking_planner)]() {
lane_parking_planner_bind->onTimer();
},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is it necessary to create lane_parking_planner temporaly variable?
creating planner in lamda is ok?

  const auto lane_parking_period_ns = rclcpp::Rate(1.0).period();
  lane_parking_timer_cb_group_ =
    node.create_callback_group(rclcpp::CallbackGroupType::MutuallyExclusive);
  lane_parking_timer_ = rclcpp::create_timer(
    &node, clock_, lane_parking_period_ns,
    [lane_parkng_planner = std::make_unique<LaneParkingPlanner>(
       node, lane_parking_mutex_, lane_parking_request_, lane_parking_response_,
       is_lane_parking_cb_running_, getLogger(), *parameters_)]() {
      lane_parkng_planner->onTimer();
    },
    lane_parking_timer_cb_group_);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

renamed to lane_parking_executor in d42fc0d

Comment on lines 106 to 117
auto freespace_planner = std::make_shared<FreespacePullOver>(node, *parameters, vehicle_info);
const auto freespace_parking_period_ns = rclcpp::Rate(1.0).period();
freespace_parking_timer_cb_group_ =
node.create_callback_group(rclcpp::CallbackGroupType::MutuallyExclusive);
auto freespace_parking_planner = std::make_unique<FreespaceParkingPlanner>(
freespace_parking_mutex_, freespace_parking_request_, freespace_parking_response_,
is_freespace_parking_cb_running_, getLogger(), clock_, freespace_planner);
freespace_parking_timer_ = rclcpp::create_timer(
&node, clock_, freespace_parking_period_ns,
std::bind(&GoalPlannerModule::onFreespaceParkingTimer, this),
[freespace_parking_planner_bind = std::move(freespace_parking_planner)]() {
freespace_parking_planner_bind->onTimer();
},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same to lane_parking

is it necessary to create lane_parking_planner temporaly variable?
creating planner in lamda is ok?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

renamed to freespace_parking_executor in d42fc0d

Comment on lines 106 to 117
auto freespace_planner = std::make_shared<FreespacePullOver>(node, *parameters, vehicle_info);
const auto freespace_parking_period_ns = rclcpp::Rate(1.0).period();
freespace_parking_timer_cb_group_ =
node.create_callback_group(rclcpp::CallbackGroupType::MutuallyExclusive);
auto freespace_parking_planner = std::make_unique<FreespaceParkingPlanner>(
freespace_parking_mutex_, freespace_parking_request_, freespace_parking_response_,
is_freespace_parking_cb_running_, getLogger(), clock_, freespace_planner);
freespace_parking_timer_ = rclcpp::create_timer(
&node, clock_, freespace_parking_period_ns,
std::bind(&GoalPlannerModule::onFreespaceParkingTimer, this),
[freespace_parking_planner_bind = std::move(freespace_parking_planner)]() {
freespace_parking_planner_bind->onTimer();
},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nits:
freespace_planner and freespace_parking_planner are little confusing.
FreespaceParkingPlanner is more like a thread or something.

Comment on lines -260 to -261
std::optional<GoalPlannerData> gp_planner_data_{std::nullopt};
std::mutex gp_planner_data_mutex_;
Copy link
Contributor

@kosuke55 kosuke55 Dec 13, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

gp_planner_data is deleted but still remain in comments. please modify or remove comments if they are not necessary.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

delete in d42fc0d

}
auto & gp_planner_data = gp_planner_data_.value();
auto & lane_parking_request = lane_parking_request_.value();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question:
why creating refrence?
we can not use update() of lane_parking_request_ directly?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed in d42fc0d

// GoalPlannerModule::occupancy_grid_map_ and gp_planner_data.occupancy_grid_map share the
// ownership, and gp_planner_data.occupancy_grid_map maybe also shared by the local
// planner_data on onFreespaceParkingTimer thread local memory space. So following operation
// is thread-safe because gp_planner_data.occupancy_grid_map is only re-pointed here and its
// prior resource is still owned by the onFreespaceParkingTimer thread locally.
occupancy_grid_map_ = gp_planner_data.occupancy_grid_map;
occupancy_grid_map_ = freespace_parking_request.get_occupancy_grid_map();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

occupancy_grid_map is not only for freepace_parking, it is also used for lane_parking.

for example,
checkOccupancyGridCollision(parking_path, occupancy_grid_map_)) { is in selectPullOverPath

occupancy_grid_map is come from planner_data

occupancy_grid_map->setMap(*(planner_data.occupancy_grid));

not from freespace parking.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove ogm-based-collision-detector from FreespaceExecutor in the future

std::atomic<bool> & is_lane_parking_cb_running_;
rclcpp::Logger logger_;

std::vector<std::shared_ptr<PullOverPlannerBase>> pull_over_planners_;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nits:
(I know this is just using previous code. but we can use unique_ptr or just vector. I want refactor in the future)

Comment on lines +315 to +317
if (pull_over_planners_.empty()) {
RCLCPP_ERROR(logger_, "Not found enabled planner");
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (pull_over_planners_.empty()) {
RCLCPP_ERROR(logger_, "Not found enabled planner");
}
if (pull_over_planners_.empty()) {
RCLCPP_WARN(
getLogger(),
"No enabled planner found. The vehicle will stop in the road lane without pull over. Please "
"check the parameters if this is the intended behavior.");
}

currently I changed some log messages in #9562

there may be similar parts, so please check

Signed-off-by: Mamoru Sobue <[email protected]>
auto path_and_goal_opt =
const auto & pull_over_path_candidates =
context_data.lane_parking_response.pull_over_path_candidates;
auto lane_pull_over_path_opt =
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
auto lane_pull_over_path_opt =
const auto lane_pull_over_path_opt =

?

I can build with const

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed in 181415e

Signed-off-by: Mamoru Sobue <[email protected]>
@soblin soblin added the tag:run-build-and-test-differential Mark to enable build-and-test-differential workflow. (used-by-ci) label Dec 13, 2024
Copy link

codecov bot commented Dec 13, 2024

Codecov Report

Attention: Patch coverage is 0% with 195 lines in your changes missing coverage. Please review.

Project coverage is 29.85%. Comparing base (9ff1c38) to head (83e3f8f).

Files with missing lines Patch % Lines
...th_goal_planner_module/src/goal_planner_module.cpp 0.00% 146 Missing ⚠️
...avior_path_goal_planner_module/src/thread_data.cpp 0.00% 24 Missing ⚠️
.../behavior_path_goal_planner_module/thread_data.hpp 0.00% 13 Missing ⚠️
...r_path_goal_planner_module/goal_planner_module.hpp 0.00% 12 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #9514      +/-   ##
==========================================
- Coverage   29.90%   29.85%   -0.05%     
==========================================
  Files        1441     1446       +5     
  Lines      108349   108409      +60     
  Branches    42492    42496       +4     
==========================================
- Hits        32403    32370      -33     
- Misses      72763    72852      +89     
- Partials     3183     3187       +4     
Flag Coverage Δ *Carryforward flag
differential 0.52% <0.00%> (?)
total 29.93% <ø> (+0.02%) ⬆️ Carriedforward from f0f215c

*This pull request uses carry forward flags. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@soblin soblin force-pushed the feat/goal-planner/divide-thread branch from 58c879a to 83e3f8f Compare December 15, 2024 06:55
@soblin soblin merged commit 657c894 into autowarefoundation:main Dec 15, 2024
31 of 33 checks passed
@soblin soblin deleted the feat/goal-planner/divide-thread branch December 15, 2024 07:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
component:planning Route planning, decision-making, and navigation. (auto-assigned) tag:run-build-and-test-differential Mark to enable build-and-test-differential workflow. (used-by-ci)
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

2 participants