Skip to content

Commit a352835

Browse files
authored
Merge pull request #1128 from tier4/fix/threads_v0.20.1
fix(goal_planner): fix multithread and magin
2 parents b632aeb + 8c0de1c commit a352835

File tree

4 files changed

+109
-32
lines changed

4 files changed

+109
-32
lines changed

planning/behavior_path_goal_planner_module/include/behavior_path_goal_planner_module/goal_planner_module.hpp

+45
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
#include <autoware_auto_planning_msgs/msg/path_with_lane_id.hpp>
3838
#include <autoware_auto_vehicle_msgs/msg/hazard_lights_command.hpp>
3939

40+
#include <atomic>
4041
#include <deque>
4142
#include <limits>
4243
#include <memory>
@@ -290,6 +291,35 @@ class GoalPlannerModule : public SceneModuleInterface
290291
std::unordered_map<std::string, std::shared_ptr<ObjectsOfInterestMarkerInterface>> &
291292
objects_of_interest_marker_interface_ptr_map);
292293

294+
~GoalPlannerModule()
295+
{
296+
if (lane_parking_timer_) {
297+
lane_parking_timer_->cancel();
298+
}
299+
if (freespace_parking_timer_) {
300+
freespace_parking_timer_->cancel();
301+
}
302+
303+
while (is_lane_parking_cb_running_.load() || is_freespace_parking_cb_running_.load()) {
304+
const std::string running_callbacks = std::invoke([&]() {
305+
if (is_lane_parking_cb_running_ && is_freespace_parking_cb_running_) {
306+
return "lane parking and freespace parking";
307+
}
308+
if (is_lane_parking_cb_running_) {
309+
return "lane parking";
310+
}
311+
return "freespace parking";
312+
});
313+
RCLCPP_INFO_THROTTLE(
314+
getLogger(), *clock_, 1000, "Waiting for %s callback to finish...",
315+
running_callbacks.c_str());
316+
std::this_thread::sleep_for(std::chrono::milliseconds(10));
317+
}
318+
319+
RCLCPP_INFO_THROTTLE(
320+
getLogger(), *clock_, 1000, "lane parking and freespace parking callbacks finished");
321+
}
322+
293323
void updateModuleParams(const std::any & parameters) override
294324
{
295325
parameters_ = std::any_cast<std::shared_ptr<GoalPlannerParameters>>(parameters);
@@ -330,6 +360,18 @@ class GoalPlannerModule : public SceneModuleInterface
330360
CandidateOutput planCandidate() const override { return CandidateOutput{}; }
331361

332362
private:
363+
// Flag class for managing whether a certain callback is running in multi-threading
364+
class ScopedFlag
365+
{
366+
public:
367+
explicit ScopedFlag(std::atomic<bool> & flag) : flag_(flag) { flag_.store(true); }
368+
369+
~ScopedFlag() { flag_.store(false); }
370+
371+
private:
372+
std::atomic<bool> & flag_;
373+
};
374+
333375
/*
334376
* state transitions and plan function used in each state
335377
*
@@ -404,10 +446,12 @@ class GoalPlannerModule : public SceneModuleInterface
404446
// pre-generate lane parking paths in a separate thread
405447
rclcpp::TimerBase::SharedPtr lane_parking_timer_;
406448
rclcpp::CallbackGroup::SharedPtr lane_parking_timer_cb_group_;
449+
std::atomic<bool> is_lane_parking_cb_running_;
407450

408451
// generate freespace parking paths in a separate thread
409452
rclcpp::TimerBase::SharedPtr freespace_parking_timer_;
410453
rclcpp::CallbackGroup::SharedPtr freespace_parking_timer_cb_group_;
454+
std::atomic<bool> is_freespace_parking_cb_running_;
411455

412456
// debug
413457
mutable GoalPlannerDebugData debug_data_;
@@ -493,6 +537,7 @@ class GoalPlannerModule : public SceneModuleInterface
493537
std::optional<BehaviorModuleOutput> last_previous_module_output_{};
494538
bool hasPreviousModulePathShapeChanged() const;
495539
bool hasDeviatedFromLastPreviousModulePath() const;
540+
bool hasDeviatedFromCurrentPreviousModulePath() const;
496541

497542
// timer for generating pull over path candidates in a separate thread
498543
void onTimer();

planning/behavior_path_goal_planner_module/src/goal_planner_module.cpp

+30-31
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ GoalPlannerModule::GoalPlannerModule(
6262
parameters_{parameters},
6363
vehicle_info_{vehicle_info_util::VehicleInfoUtil(node).getVehicleInfo()},
6464
thread_safe_data_{mutex_, clock_},
65+
is_lane_parking_cb_running_{false},
66+
is_freespace_parking_cb_running_{false},
6567
debug_stop_pose_with_info_{&stop_pose_}
6668
{
6769
LaneDepartureChecker lane_departure_checker{};
@@ -161,9 +163,18 @@ bool GoalPlannerModule::hasDeviatedFromLastPreviousModulePath() const
161163
planner_data_->self_odometry->pose.pose.position)) > 0.3;
162164
}
163165

166+
bool GoalPlannerModule::hasDeviatedFromCurrentPreviousModulePath() const
167+
{
168+
return std::abs(motion_utils::calcLateralOffset(
169+
getPreviousModuleOutput().path.points,
170+
planner_data_->self_odometry->pose.pose.position)) > 0.3;
171+
}
172+
164173
// generate pull over candidate paths
165174
void GoalPlannerModule::onTimer()
166175
{
176+
const ScopedFlag flag(is_lane_parking_cb_running_);
177+
167178
if (getCurrentStatus() == ModuleStatus::IDLE) {
168179
return;
169180
}
@@ -179,15 +190,19 @@ void GoalPlannerModule::onTimer()
179190

180191
// check if new pull over path candidates are needed to be generated
181192
const bool need_update = std::invoke([&]() {
193+
if (hasDeviatedFromCurrentPreviousModulePath()) {
194+
RCLCPP_DEBUG(getLogger(), "has deviated from current previous module path");
195+
return false;
196+
}
182197
if (thread_safe_data_.get_pull_over_path_candidates().empty()) {
183198
return true;
184199
}
185200
if (hasPreviousModulePathShapeChanged()) {
186-
RCLCPP_ERROR(getLogger(), "has previous module path shape changed");
201+
RCLCPP_DEBUG(getLogger(), "has previous module path shape changed");
187202
return true;
188203
}
189204
if (hasDeviatedFromLastPreviousModulePath() && !hasDecidedPath()) {
190-
RCLCPP_ERROR(getLogger(), "has deviated from last previous module path");
205+
RCLCPP_DEBUG(getLogger(), "has deviated from last previous module path");
191206
return true;
192207
}
193208
return false;
@@ -276,6 +291,8 @@ void GoalPlannerModule::onTimer()
276291

277292
void GoalPlannerModule::onFreespaceParkingTimer()
278293
{
294+
const ScopedFlag flag(is_freespace_parking_cb_running_);
295+
279296
if (getCurrentStatus() == ModuleStatus::IDLE) {
280297
return;
281298
}
@@ -1554,27 +1571,9 @@ bool GoalPlannerModule::checkObjectsCollision(
15541571
}
15551572

15561573
/* Expand ego collision check polygon
1557-
* - `collision_check_margin` in all directions
1558-
* - `extra_stopping_margin` in the moving direction
1559-
* - `extra_lateral_margin` in external direction of path curve
1560-
*
1561-
*
1562-
* ^ moving direction
1563-
* x
1564-
* x
1565-
* x
1566-
* +----------------------+------x--+
1567-
* | | x |
1568-
* | +---------------+ | xx |
1569-
* | | | | xx |
1570-
* | | ego footprint |xxxxx |
1571-
* | | | | |
1572-
* | +---------------+ | extra_stopping_margin
1573-
* | margin | |
1574-
* +----------------------+ |
1575-
* | extra_lateral_margin |
1576-
* +--------------------------------+
1577-
*
1574+
* - `collision_check_margin` is added in all directions.
1575+
* - `extra_stopping_margin` adds stopping margin under deceleration constraints forward.
1576+
* - `extra_lateral_margin` adds the lateral margin on curves.
15781577
*/
15791578
std::vector<Polygon2d> ego_polygons_expanded{};
15801579
const auto curvatures = motion_utils::calcCurvature(path.points);
@@ -1585,19 +1584,19 @@ bool GoalPlannerModule::checkObjectsCollision(
15851584
std::pow(p.point.longitudinal_velocity_mps, 2) * 0.5 / parameters_->maximum_deceleration,
15861585
parameters_->object_recognition_collision_check_max_extra_stopping_margin);
15871586

1588-
double extra_lateral_margin = (-1) * curvatures.at(i) * p.point.longitudinal_velocity_mps *
1589-
std::abs(p.point.longitudinal_velocity_mps);
1590-
extra_lateral_margin =
1591-
std::clamp(extra_lateral_margin, -extra_stopping_margin, extra_stopping_margin);
1587+
// The square is meant to imply centrifugal force, but it is not a very well-founded formula.
1588+
// TODO(kosuke55): It is needed to consider better way because there is an inherently different
1589+
// conception of the inside and outside margins.
1590+
const double extra_lateral_margin = std::min(
1591+
extra_stopping_margin,
1592+
std::abs(curvatures.at(i) * std::pow(p.point.longitudinal_velocity_mps, 2)));
15921593

1593-
const auto lateral_offset_pose =
1594-
tier4_autoware_utils::calcOffsetPose(p.point.pose, 0.0, extra_lateral_margin / 2.0, 0.0);
15951594
const auto ego_polygon = tier4_autoware_utils::toFootprint(
1596-
lateral_offset_pose,
1595+
p.point.pose,
15971596
planner_data_->parameters.base_link2front + collision_check_margin + extra_stopping_margin,
15981597
planner_data_->parameters.base_link2rear + collision_check_margin,
15991598
planner_data_->parameters.vehicle_width + collision_check_margin * 2.0 +
1600-
std::abs(extra_lateral_margin));
1599+
extra_lateral_margin * 2.0);
16011600
ego_polygons_expanded.push_back(ego_polygon);
16021601
}
16031602

planning/behavior_path_start_planner_module/include/behavior_path_start_planner_module/start_planner_module.hpp

+30
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535

3636
#include <tf2/utils.h>
3737

38+
#include <atomic>
3839
#include <deque>
3940
#include <memory>
4041
#include <string>
@@ -83,6 +84,21 @@ class StartPlannerModule : public SceneModuleInterface
8384
std::unordered_map<std::string, std::shared_ptr<ObjectsOfInterestMarkerInterface>> &
8485
objects_of_interest_marker_interface_ptr_map);
8586

87+
~StartPlannerModule()
88+
{
89+
if (freespace_planner_timer_) {
90+
freespace_planner_timer_->cancel();
91+
}
92+
93+
while (is_freespace_planner_cb_running_.load()) {
94+
RCLCPP_INFO_THROTTLE(
95+
getLogger(), *clock_, 1000, "Waiting for freespace planner callback to finish...");
96+
std::this_thread::sleep_for(std::chrono::milliseconds(100));
97+
}
98+
99+
RCLCPP_INFO_THROTTLE(getLogger(), *clock_, 1000, "freespace planner callback finished");
100+
}
101+
86102
void updateModuleParams(const std::any & parameters) override
87103
{
88104
parameters_ = std::any_cast<std::shared_ptr<StartPlannerParameters>>(parameters);
@@ -135,6 +151,18 @@ class StartPlannerModule : public SceneModuleInterface
135151
bool isFreespacePlanning() const { return status_.planner_type == PlannerType::FREESPACE; }
136152

137153
private:
154+
// Flag class for managing whether a certain callback is running in multi-threading
155+
class ScopedFlag
156+
{
157+
public:
158+
explicit ScopedFlag(std::atomic<bool> & flag) : flag_(flag) { flag_.store(true); }
159+
160+
~ScopedFlag() { flag_.store(false); }
161+
162+
private:
163+
std::atomic<bool> & flag_;
164+
};
165+
138166
bool canTransitSuccessState() override;
139167

140168
bool canTransitFailureState() override { return false; }
@@ -202,6 +230,8 @@ class StartPlannerModule : public SceneModuleInterface
202230
std::unique_ptr<PullOutPlannerBase> freespace_planner_;
203231
rclcpp::TimerBase::SharedPtr freespace_planner_timer_;
204232
rclcpp::CallbackGroup::SharedPtr freespace_planner_timer_cb_group_;
233+
std::atomic<bool> is_freespace_planner_cb_running_;
234+
205235
// TODO(kosuke55)
206236
// Currently, we only do lock when updating a member of status_.
207237
// However, we need to ensure that the value does not change when referring to it.

planning/behavior_path_start_planner_module/src/start_planner_module.cpp

+4-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,8 @@ StartPlannerModule::StartPlannerModule(
5454
objects_of_interest_marker_interface_ptr_map)
5555
: SceneModuleInterface{name, node, rtc_interface_ptr_map, objects_of_interest_marker_interface_ptr_map}, // NOLINT
5656
parameters_{parameters},
57-
vehicle_info_{vehicle_info_util::VehicleInfoUtil(node).getVehicleInfo()}
57+
vehicle_info_{vehicle_info_util::VehicleInfoUtil(node).getVehicleInfo()},
58+
is_freespace_planner_cb_running_{false}
5859
{
5960
lane_departure_checker_ = std::make_shared<LaneDepartureChecker>();
6061
lane_departure_checker_->setVehicleInfo(vehicle_info_);
@@ -85,6 +86,8 @@ StartPlannerModule::StartPlannerModule(
8586

8687
void StartPlannerModule::onFreespacePlannerTimer()
8788
{
89+
const ScopedFlag flag(is_freespace_planner_cb_running_);
90+
8891
if (getCurrentStatus() == ModuleStatus::IDLE) {
8992
return;
9093
}

0 commit comments

Comments
 (0)