@@ -93,26 +93,56 @@ void StartPlannerModule::onFreespacePlannerTimer()
93
93
{
94
94
const ScopedFlag flag (is_freespace_planner_cb_running_);
95
95
96
- if (getCurrentStatus () == ModuleStatus::IDLE) {
96
+ std::shared_ptr<const PlannerData> local_planner_data{nullptr };
97
+ std::optional<ModuleStatus> current_status_opt{std::nullopt};
98
+ std::optional<StartPlannerParameters> parameters_opt{std::nullopt};
99
+ std::optional<PullOutStatus> pull_out_status_opt{std::nullopt};
100
+ bool is_stopped;
101
+
102
+ // making a local copy of thread sensitive data
103
+ {
104
+ std::lock_guard<std::mutex> guard (start_planner_data_mutex_);
105
+ if (start_planner_data_) {
106
+ const auto & start_planner_data = start_planner_data_.value ();
107
+ local_planner_data = std::make_shared<PlannerData>(start_planner_data.planner_data );
108
+ current_status_opt = start_planner_data.current_status ;
109
+ parameters_opt = start_planner_data.parameters ;
110
+ pull_out_status_opt = start_planner_data.main_thread_pull_out_status ;
111
+ is_stopped = start_planner_data.is_stopped ;
112
+ }
113
+ }
114
+ // finish copying thread sensitive data
115
+ if (!local_planner_data || !current_status_opt || !parameters_opt || !pull_out_status_opt) {
97
116
return ;
98
117
}
99
118
100
- if (!planner_data_) {
119
+ const auto & current_status = current_status_opt.value ();
120
+ const auto & parameters = parameters_opt.value ();
121
+ const auto & pull_out_status = pull_out_status_opt.value ();
122
+
123
+ if (current_status == ModuleStatus::IDLE) {
101
124
return ;
102
125
}
103
126
104
- if (!planner_data_ ->costmap ) {
127
+ if (!local_planner_data ->costmap ) {
105
128
return ;
106
129
}
107
130
108
131
const bool is_new_costmap =
109
- (clock_->now () - planner_data_ ->costmap ->header .stamp ).seconds () < 1.0 ;
132
+ (clock_->now () - local_planner_data ->costmap ->header .stamp ).seconds () < 1.0 ;
110
133
if (!is_new_costmap) {
111
134
return ;
112
135
}
113
136
114
- if (isStuck ()) {
115
- planFreespacePath ();
137
+ const bool is_stuck = is_stopped && pull_out_status.planner_type == PlannerType::STOP &&
138
+ !pull_out_status.found_pull_out_path ;
139
+ if (is_stuck) {
140
+ const auto free_space_status =
141
+ planFreespacePath (parameters, local_planner_data, pull_out_status);
142
+ if (free_space_status) {
143
+ std::lock_guard<std::mutex> guard (start_planner_data_mutex_);
144
+ freespace_thread_status_ = free_space_status;
145
+ }
116
146
}
117
147
}
118
148
@@ -172,6 +202,38 @@ void StartPlannerModule::updateObjectsFilteringParams(
172
202
173
203
void StartPlannerModule::updateData ()
174
204
{
205
+ // The method PlannerManager::run() calls SceneModuleInterface::setData and
206
+ // SceneModuleInterface::setPreviousModuleOutput() before this module's run() method is called
207
+ // with module_ptr->run(). Then module_ptr->run() invokes StartPlannerModule::updateData and,
208
+ // finally, the planWaitingApproval()/plan() methods are called by run(). So we can copy the
209
+ // latest current_status to start_planner_data_ here for later usage.
210
+
211
+ // NOTE: onFreespacePlannerTimer copies start_planner_data to its thread local variable, so we
212
+ // need to lock start_planner_data_ here to avoid data race. But the following clone process is
213
+ // lightweight because most of the member variables of PlannerData/RouteHandler is
214
+ // shared_ptrs/bool
215
+ // making a local copy of thread sensitive data
216
+ {
217
+ std::lock_guard<std::mutex> guard (start_planner_data_mutex_);
218
+ if (!start_planner_data_) {
219
+ start_planner_data_ = StartPlannerData ();
220
+ }
221
+ start_planner_data_.value ().update (
222
+ *parameters_, *planner_data_, getCurrentStatus (), status_, isStopped ());
223
+ if (freespace_thread_status_) {
224
+ // if freespace solution is available, copy it to status_ on main thread
225
+ const auto & freespace_status = freespace_thread_status_.value ();
226
+ status_.pull_out_path = freespace_status.pull_out_path ;
227
+ status_.pull_out_start_pose = freespace_status.pull_out_start_pose ;
228
+ status_.planner_type = freespace_status.planner_type ;
229
+ status_.found_pull_out_path = freespace_status.found_pull_out_path ;
230
+ status_.driving_forward = freespace_status.driving_forward ;
231
+ // and then reset it
232
+ freespace_thread_status_ = std::nullopt;
233
+ }
234
+ }
235
+ // finish copying thread sensitive data
236
+
175
237
if (receivedNewRoute ()) {
176
238
resetStatus ();
177
239
DEBUG_PRINT (" StartPlannerModule::updateData() received new route, reset status" );
@@ -1128,19 +1190,6 @@ bool StartPlannerModule::needToPrepareBlinkerBeforeStartDrivingForward() const
1128
1190
return elapsed < parameters_->prepare_time_before_start ;
1129
1191
}
1130
1192
1131
- bool StartPlannerModule::isStuck ()
1132
- {
1133
- if (!isStopped ()) {
1134
- return false ;
1135
- }
1136
-
1137
- if (status_.planner_type == PlannerType::STOP || !status_.found_pull_out_path ) {
1138
- return true ;
1139
- }
1140
-
1141
- return false ;
1142
- }
1143
-
1144
1193
bool StartPlannerModule::hasFinishedCurrentPath ()
1145
1194
{
1146
1195
const auto current_path = getCurrentPath ();
@@ -1336,19 +1385,21 @@ BehaviorModuleOutput StartPlannerModule::generateStopOutput()
1336
1385
return output;
1337
1386
}
1338
1387
1339
- bool StartPlannerModule::planFreespacePath ()
1388
+ std::optional<PullOutStatus> StartPlannerModule::planFreespacePath (
1389
+ const StartPlannerParameters & parameters,
1390
+ const std::shared_ptr<const PlannerData> & planner_data, const PullOutStatus & pull_out_status)
1340
1391
{
1341
- const Pose & current_pose = planner_data_ ->self_odometry ->pose .pose ;
1342
- const auto & route_handler = planner_data_ ->route_handler ;
1392
+ const Pose & current_pose = planner_data ->self_odometry ->pose .pose ;
1393
+ const auto & route_handler = planner_data ->route_handler ;
1343
1394
1344
- const double end_pose_search_start_distance = parameters_-> end_pose_search_start_distance ;
1345
- const double end_pose_search_end_distance = parameters_-> end_pose_search_end_distance ;
1346
- const double end_pose_search_interval = parameters_-> end_pose_search_interval ;
1395
+ const double end_pose_search_start_distance = parameters. end_pose_search_start_distance ;
1396
+ const double end_pose_search_end_distance = parameters. end_pose_search_end_distance ;
1397
+ const double end_pose_search_interval = parameters. end_pose_search_interval ;
1347
1398
1348
1399
const double backward_path_length =
1349
- planner_data_ ->parameters .backward_path_length + parameters_-> max_back_distance ;
1400
+ planner_data ->parameters .backward_path_length + parameters. max_back_distance ;
1350
1401
const auto current_lanes = utils::getExtendedCurrentLanes (
1351
- planner_data_ , backward_path_length, std::numeric_limits<double >::max (),
1402
+ planner_data , backward_path_length, std::numeric_limits<double >::max (),
1352
1403
/* forward_only_in_route*/ true );
1353
1404
1354
1405
const auto current_arc_coords = lanelet::utils::getArcCoordinates (current_lanes, current_pose);
@@ -1361,23 +1412,23 @@ bool StartPlannerModule::planFreespacePath()
1361
1412
1362
1413
for (const auto & p : center_line_path.points ) {
1363
1414
const Pose end_pose = p.point .pose ;
1364
- freespace_planner_->setPlannerData (planner_data_ );
1415
+ freespace_planner_->setPlannerData (planner_data );
1365
1416
auto freespace_path = freespace_planner_->plan (current_pose, end_pose);
1366
1417
1367
1418
if (!freespace_path) {
1368
1419
continue ;
1369
1420
}
1370
1421
1371
- const std::lock_guard<std::mutex> lock (mutex_) ;
1372
- status_ .pull_out_path = *freespace_path;
1373
- status_ .pull_out_start_pose = current_pose;
1374
- status_ .planner_type = freespace_planner_->getPlannerType ();
1375
- status_ .found_pull_out_path = true ;
1376
- status_ .driving_forward = true ;
1377
- return true ;
1422
+ auto status = pull_out_status ;
1423
+ status .pull_out_path = *freespace_path;
1424
+ status .pull_out_start_pose = current_pose;
1425
+ status .planner_type = freespace_planner_->getPlannerType ();
1426
+ status .found_pull_out_path = true ;
1427
+ status .driving_forward = true ;
1428
+ return std::make_optional<PullOutStatus>(status) ;
1378
1429
}
1379
1430
1380
- return false ;
1431
+ return std::nullopt ;
1381
1432
}
1382
1433
1383
1434
void StartPlannerModule::setDrivableAreaInfo (BehaviorModuleOutput & output) const
@@ -1665,4 +1716,43 @@ void StartPlannerModule::logPullOutStatus(rclcpp::Logger::Level log_level) const
1665
1716
1666
1717
logFunc (" =======================================" );
1667
1718
}
1719
+
1720
+ StartPlannerModule::StartPlannerData StartPlannerModule::StartPlannerData::clone () const
1721
+ {
1722
+ StartPlannerData start_planner_data;
1723
+ start_planner_data.update (
1724
+ parameters, planner_data, current_status, main_thread_pull_out_status, is_stopped);
1725
+ return start_planner_data;
1726
+ }
1727
+
1728
+ void StartPlannerModule::StartPlannerData::update (
1729
+ const StartPlannerParameters & parameters_, const PlannerData & planner_data_,
1730
+ const ModuleStatus & current_status_, const PullOutStatus & pull_out_status_,
1731
+ const bool is_stopped_)
1732
+ {
1733
+ parameters = parameters_;
1734
+ planner_data = planner_data_;
1735
+ // TODO(Mamoru Sobue): in the future we will add planner_data->is_route_handler_updated flag to
1736
+ // avoid the copy overhead of lanelet objects inside the RouteHandler. behavior_path_planner can
1737
+ // tell us the flag if map/route changed, so we can skip route_handler update if it
1738
+ // is false in the following way
1739
+ /*
1740
+ auto route_handler_self = planner_data.route_handler;
1741
+ planner_data = planner_data_; // sync planer_data to planner_data_, planner_data.route_handler
1742
+ is once re-pointed
1743
+
1744
+ if (!planner_data_->is_route_handler_updated && route_handler_self != nullptr) {
1745
+ // we do not need to sync planner_data.route_handler with that of planner_data_
1746
+ // re-point to the original again
1747
+ planner_data.route_handler = route_handler_self;
1748
+ } else {
1749
+ // this is actually heavy if the lanelet_map is HUGE
1750
+ planner_data.route_handler = std::make_shared<RouteHandler>(*(planner_data_.route_handler));
1751
+ }
1752
+ */
1753
+ planner_data.route_handler = std::make_shared<RouteHandler>(*(planner_data_.route_handler ));
1754
+ current_status = current_status_;
1755
+ main_thread_pull_out_status = pull_out_status_;
1756
+ is_stopped = is_stopped_;
1757
+ }
1668
1758
} // namespace behavior_path_planner
0 commit comments