@@ -857,6 +857,7 @@ controller_interface::return_type ControllerManager::configure_controller(
857857
858858void ControllerManager::clear_requests ()
859859{
860+ switch_params_.do_switch = false ;
860861 deactivate_request_.clear ();
861862 activate_request_.clear ();
862863 // 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(
886887 return controller_interface::return_type::ERROR;
887888 }
888889
889- switch_params_ = SwitchParams ();
890+ // reset the switch param internal variables
891+ switch_params_.reset ();
890892
891893 if (!deactivate_request_.empty () || !activate_request_.empty ())
892894 {
@@ -1307,19 +1309,27 @@ controller_interface::return_type ControllerManager::switch_controller(
13071309 // start the atomic controller switching
13081310 switch_params_.strictness = strictness;
13091311 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+ }
13121321 switch_params_.do_switch = true ;
1313-
13141322 // wait until switch is finished
13151323 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 ; }))
13171327 {
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 ;
13231333 }
13241334
13251335 // 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 &
21552165
21562166void ControllerManager::manage_switch ()
21572167{
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+ }
21582174 // Ask hardware interfaces to change mode
21592175 if (!resource_manager_->perform_command_mode_switch (
21602176 activate_command_interface_request_, deactivate_command_interface_request_))
@@ -2183,6 +2199,7 @@ void ControllerManager::manage_switch()
21832199
21842200 // All controllers switched --> switching done
21852201 switch_params_.do_switch = false ;
2202+ switch_params_.cv .notify_all ();
21862203}
21872204
21882205controller_interface::return_type ControllerManager::update (
0 commit comments