Skip to content

Commit 2bdc00b

Browse files
committed
Add changes to properly use activate_asap in context of switching controllers
1 parent 25ea188 commit 2bdc00b

File tree

3 files changed

+50
-43
lines changed

3 files changed

+50
-43
lines changed

controller_manager/include/controller_manager/controller_manager.hpp

Lines changed: 14 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
#include "controller_manager_msgs/srv/unload_controller.hpp"
4141

4242
#include "diagnostic_updater/diagnostic_updater.hpp"
43+
#include "hardware_interface/helpers.hpp"
4344
#include "hardware_interface/resource_manager.hpp"
4445

4546
#include "pluginlib/class_loader.hpp"
@@ -259,7 +260,7 @@ class ControllerManager : public rclcpp::Node
259260
*/
260261
void deactivate_controllers(
261262
const std::vector<ControllerSpec> & rt_controller_list,
262-
const std::vector<std::string> controllers_to_deactivate);
263+
const std::vector<std::string> & controllers_to_deactivate);
263264

264265
/**
265266
* Switch chained mode for all the controllers with respect to the following cases:
@@ -282,22 +283,7 @@ class ControllerManager : public rclcpp::Node
282283
*/
283284
void activate_controllers(
284285
const std::vector<ControllerSpec> & rt_controller_list,
285-
const std::vector<std::string> controllers_to_activate);
286-
287-
/// Activate chosen controllers from real-time controller list.
288-
/**
289-
* Activate controllers with names \p controllers_to_activate from list \p rt_controller_list.
290-
* The controller list will be iterated as many times as there are controller names.
291-
*
292-
* *NOTE*: There is currently not difference to `activate_controllers` method.
293-
* Check https://github.com/ros-controls/ros2_control/issues/263 for more information.
294-
*
295-
* \param[in] rt_controller_list controllers in the real-time list.
296-
* \param[in] controllers_to_activate names of the controller that have to be activated.
297-
*/
298-
void activate_controllers_asap(
299-
const std::vector<ControllerSpec> & rt_controller_list,
300-
const std::vector<std::string> controllers_to_activate);
286+
const std::vector<std::string> & controllers_to_activate);
301287

302288
void list_controllers_srv_cb(
303289
const std::shared_ptr<controller_manager_msgs::srv::ListControllers::Request> request,
@@ -681,18 +667,27 @@ class ControllerManager : public rclcpp::Node
681667
activate_asap = false;
682668
}
683669

684-
bool do_switch;
670+
std::atomic_bool do_switch;
685671
bool started;
686672

687673
// Switch options
688674
int strictness;
689-
bool activate_asap;
675+
std::atomic_bool activate_asap;
690676
std::chrono::nanoseconds timeout;
691677

692678
// conditional variable and mutex to wait for the switch to complete
693679
std::condition_variable cv;
694680
std::mutex mutex;
695681

682+
bool skip_cycle(const controller_manager::ControllerSpec & spec) const
683+
{
684+
const std::string controller_name = spec.info.name;
685+
return ros2_control::has_item(activate_request, controller_name) ||
686+
ros2_control::has_item(deactivate_request, controller_name) ||
687+
ros2_control::has_item(to_chained_mode_request, controller_name) ||
688+
ros2_control::has_item(from_chained_mode_request, controller_name);
689+
}
690+
696691
// The controllers list to activate and deactivate
697692
std::vector<std::string> activate_request;
698693
std::vector<std::string> deactivate_request;

controller_manager/src/controller_manager.cpp

Lines changed: 34 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1298,6 +1298,7 @@ controller_interface::return_type ControllerManager::configure_controller(
12981298
void ControllerManager::clear_requests()
12991299
{
13001300
switch_params_.do_switch = false;
1301+
switch_params_.activate_asap = false;
13011302
switch_params_.deactivate_request.clear();
13021303
switch_params_.activate_request.clear();
13031304
// Set these interfaces as unavailable when clearing requests to avoid leaving them in available
@@ -1871,17 +1872,27 @@ controller_interface::return_type ControllerManager::switch_controller_cb(
18711872
switch_params_.do_switch = true;
18721873

18731874
// wait until switch is finished
1874-
RCLCPP_DEBUG(get_logger(), "Requested atomic controller switch from realtime loop");
1875-
std::unique_lock<std::mutex> switch_params_guard(switch_params_.mutex);
1876-
if (!switch_params_.cv.wait_for(
1877-
switch_params_guard, switch_params_.timeout, [this] { return !switch_params_.do_switch; }))
1878-
{
1879-
message = fmt::format(
1880-
FMT_COMPILE("Switch controller timed out after {} seconds!"),
1881-
static_cast<double>(switch_params_.timeout.count()) / 1e9);
1882-
RCLCPP_ERROR(get_logger(), "%s", message.c_str());
1883-
clear_requests();
1884-
return controller_interface::return_type::ERROR;
1875+
if (switch_params_.activate_asap)
1876+
{
1877+
RCLCPP_DEBUG(get_logger(), "Requested atomic controller switch from realtime loop");
1878+
std::unique_lock<std::mutex> switch_params_guard(switch_params_.mutex);
1879+
if (!switch_params_.cv.wait_for(
1880+
switch_params_guard, switch_params_.timeout,
1881+
[this] { return !switch_params_.do_switch; }))
1882+
{
1883+
message = fmt::format(
1884+
FMT_COMPILE("Switch controller timed out after {} seconds!"),
1885+
static_cast<double>(switch_params_.timeout.count()) / 1e9);
1886+
RCLCPP_ERROR(get_logger(), "%s", message.c_str());
1887+
clear_requests();
1888+
return controller_interface::return_type::ERROR;
1889+
}
1890+
}
1891+
else
1892+
{
1893+
RCLCPP_INFO(get_logger(), "Requested controller switch from non-realtime loop");
1894+
// This should work as the realtime thread operation is read-only operation
1895+
manage_switch();
18851896
}
18861897

18871898
// copy the controllers spec from the used to the unused list
@@ -1983,7 +1994,7 @@ controller_interface::ControllerInterfaceBaseSharedPtr ControllerManager::add_co
19831994

19841995
void ControllerManager::deactivate_controllers(
19851996
const std::vector<ControllerSpec> & rt_controller_list,
1986-
const std::vector<std::string> controllers_to_deactivate)
1997+
const std::vector<std::string> & controllers_to_deactivate)
19871998
{
19881999
// deactivate controllers
19892000
for (const auto & controller_name : controllers_to_deactivate)
@@ -2087,7 +2098,7 @@ void ControllerManager::switch_chained_mode(
20872098

20882099
void ControllerManager::activate_controllers(
20892100
const std::vector<ControllerSpec> & rt_controller_list,
2090-
const std::vector<std::string> controllers_to_activate)
2101+
const std::vector<std::string> & controllers_to_activate)
20912102
{
20922103
for (const auto & controller_name : controllers_to_activate)
20932104
{
@@ -2239,14 +2250,6 @@ void ControllerManager::activate_controllers(
22392250
}
22402251
}
22412252

2242-
void ControllerManager::activate_controllers_asap(
2243-
const std::vector<ControllerSpec> & rt_controller_list,
2244-
const std::vector<std::string> controllers_to_activate)
2245-
{
2246-
// https://github.com/ros-controls/ros2_control/issues/263
2247-
activate_controllers(rt_controller_list, controllers_to_activate);
2248-
}
2249-
22502253
void ControllerManager::list_controllers_srv_cb(
22512254
const std::shared_ptr<controller_manager_msgs::srv::ListControllers::Request>,
22522255
std::shared_ptr<controller_manager_msgs::srv::ListControllers::Response> response)
@@ -2788,6 +2791,15 @@ controller_interface::return_type ControllerManager::update(
27882791
rt_buffer_.deactivate_controllers_list.clear();
27892792
for (const auto & loaded_controller : rt_controller_list)
27902793
{
2794+
if (
2795+
switch_params_.do_switch && !switch_params_.activate_asap &&
2796+
switch_params_.skip_cycle(loaded_controller))
2797+
{
2798+
RCLCPP_DEBUG(
2799+
get_logger(), "Skipping update for controller '%s' as it is being switched",
2800+
loaded_controller.info.name.c_str());
2801+
continue;
2802+
}
27912803
// TODO(v-lopez) we could cache this information
27922804
// https://github.com/ros-controls/ros2_control/issues/153
27932805
if (is_controller_active(*loaded_controller.c))
@@ -2944,7 +2956,7 @@ controller_interface::return_type ControllerManager::update(
29442956
resource_manager_->enforce_command_limits(period);
29452957

29462958
// there are controllers to (de)activate
2947-
if (switch_params_.do_switch)
2959+
if (switch_params_.do_switch && switch_params_.activate_asap)
29482960
{
29492961
manage_switch();
29502962
}

hardware_interface/include/hardware_interface/helpers.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ template <typename Container, typename T>
3838
{
3939
if constexpr (std::is_same_v<Container, std::vector<T>>)
4040
{
41-
return std::find(container.begin(), container.end(), item);
41+
return std::find(container.cbegin(), container.cend(), item);
4242
}
4343
else if constexpr (
4444
std::is_same_v<Container, std::map<T, typename Container::mapped_type>> ||
@@ -68,7 +68,7 @@ template <typename Container, typename T>
6868
template <typename Container, typename T>
6969
[[nodiscard]] bool has_item(const Container & container, const T & item)
7070
{
71-
return get_item_iterator(container, item) != container.end();
71+
return get_item_iterator(container, item) != container.cend();
7272
}
7373

7474
/**

0 commit comments

Comments
 (0)