@@ -857,6 +857,7 @@ controller_interface::return_type ControllerManager::configure_controller(
857
857
858
858
void ControllerManager::clear_requests ()
859
859
{
860
+ switch_params_.do_switch = false ;
860
861
deactivate_request_.clear ();
861
862
activate_request_.clear ();
862
863
// Set these interfaces as unavailable when clearing requests to avoid leaving them in available
@@ -886,7 +887,8 @@ controller_interface::return_type ControllerManager::switch_controller(
886
887
return controller_interface::return_type::ERROR;
887
888
}
888
889
889
- switch_params_ = SwitchParams ();
890
+ // reset the switch param internal variables
891
+ switch_params_.reset ();
890
892
891
893
if (!deactivate_request_.empty () || !activate_request_.empty ())
892
894
{
@@ -1307,19 +1309,27 @@ controller_interface::return_type ControllerManager::switch_controller(
1307
1309
// start the atomic controller switching
1308
1310
switch_params_.strictness = strictness;
1309
1311
switch_params_.activate_asap = activate_asap;
1310
- switch_params_.init_time = rclcpp::Clock ().now ();
1311
- switch_params_.timeout = timeout;
1312
+ if (timeout == rclcpp::Duration{0 , 0 })
1313
+ {
1314
+ RCLCPP_INFO_ONCE (get_logger (), " Switch controller timeout is set to 0, using default 1s!" );
1315
+ switch_params_.timeout = std::chrono::nanoseconds (1'000'000'000 );
1316
+ }
1317
+ else
1318
+ {
1319
+ switch_params_.timeout = timeout.to_chrono <std::chrono::nanoseconds>();
1320
+ }
1312
1321
switch_params_.do_switch = true ;
1313
-
1314
1322
// wait until switch is finished
1315
1323
RCLCPP_DEBUG (get_logger (), " Requested atomic controller switch from realtime loop" );
1316
- while (rclcpp::ok () && switch_params_.do_switch )
1324
+ std::unique_lock<std::mutex> switch_params_guard (switch_params_.mutex , std::defer_lock);
1325
+ if (!switch_params_.cv .wait_for (
1326
+ switch_params_guard, switch_params_.timeout , [this ] { return !switch_params_.do_switch ; }))
1317
1327
{
1318
- if (! rclcpp::ok ())
1319
- {
1320
- return controller_interface::return_type::ERROR ;
1321
- }
1322
- std::this_thread::sleep_for ( std::chrono::microseconds ( 100 )) ;
1328
+ RCLCPP_ERROR (
1329
+ get_logger (), " Switch controller timed out after %f seconds! " ,
1330
+ static_cast < double >(switch_params_. timeout . count ()) / 1e9 ) ;
1331
+ clear_requests ();
1332
+ return controller_interface::return_type::ERROR ;
1323
1333
}
1324
1334
1325
1335
// copy the controllers spec from the used to the unused list
@@ -2155,6 +2165,12 @@ void ControllerManager::read(const rclcpp::Time & time, const rclcpp::Duration &
2155
2165
2156
2166
void ControllerManager::manage_switch ()
2157
2167
{
2168
+ std::unique_lock<std::mutex> guard (switch_params_.mutex , std::try_to_lock);
2169
+ if (!guard.owns_lock ())
2170
+ {
2171
+ RCLCPP_DEBUG (get_logger (), " Unable to lock switch mutex. Retrying in next cycle." );
2172
+ return ;
2173
+ }
2158
2174
// Ask hardware interfaces to change mode
2159
2175
if (!resource_manager_->perform_command_mode_switch (
2160
2176
activate_command_interface_request_, deactivate_command_interface_request_))
@@ -2183,6 +2199,7 @@ void ControllerManager::manage_switch()
2183
2199
2184
2200
// All controllers switched --> switching done
2185
2201
switch_params_.do_switch = false ;
2202
+ switch_params_.cv .notify_all ();
2186
2203
}
2187
2204
2188
2205
controller_interface::return_type ControllerManager::update (
0 commit comments