Skip to content

Commit 70514dd

Browse files
authored
Full functionality of chainable controllers in controller manager (#667)
* auto-switching of chained mode in controllers * interface-matching approach for managing chaining controllers
1 parent 1410716 commit 70514dd

File tree

15 files changed

+1618
-54
lines changed

15 files changed

+1618
-54
lines changed

controller_interface/include/controller_interface/controller_interface.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ class ControllerInterface : public controller_interface::ControllerInterfaceBase
5353
/**
5454
* Controller is not chainable, therefore no chained mode can be set.
5555
*
56-
* \returns false;
56+
* \returns false.
5757
*/
5858
CONTROLLER_INTERFACE_PUBLIC
5959
bool set_chained_mode(bool chained_mode) final;

controller_interface/include/controller_interface/helpers.hpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,11 @@ bool get_ordered_interfaces(
4848
{
4949
if (!interface_type.empty())
5050
{
51-
if ((name == interface.get_name()) && (interface_type == interface.get_interface_name()))
51+
// check case where:
52+
// (<joint> == <joint> AND <interface> == <interface>) OR <joint>/<interface> == 'full name'
53+
if (
54+
((name == interface.get_name()) && (interface_type == interface.get_interface_name())) ||
55+
((name + "/" + interface_type) == interface.get_full_name()))
5256
{
5357
ordered_interfaces.push_back(std::ref(interface));
5458
}

controller_manager/CMakeLists.txt

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,16 @@ if(BUILD_TESTING)
8989
DESTINATION lib
9090
)
9191

92+
add_library(test_chainable_controller SHARED test/test_chainable_controller/test_chainable_controller.cpp)
93+
target_include_directories(test_chainable_controller PRIVATE include)
94+
target_link_libraries(test_chainable_controller controller_manager)
95+
target_compile_definitions(test_chainable_controller PRIVATE "CONTROLLER_MANAGER_BUILDING_DLL")
96+
pluginlib_export_plugin_description_file(
97+
controller_interface test/test_chainable_controller/test_chainable_controller.xml)
98+
install(TARGETS test_chainable_controller
99+
DESTINATION lib
100+
)
101+
92102
ament_add_gmock(
93103
test_controller_manager
94104
test/test_controller_manager.cpp
@@ -114,6 +124,14 @@ if(BUILD_TESTING)
114124
target_link_libraries(test_load_controller ${PROJECT_NAME} test_controller test_controller_failed_init)
115125
ament_target_dependencies(test_load_controller ros2_control_test_assets)
116126

127+
ament_add_gmock(
128+
test_controllers_chaining_with_controller_manager
129+
test/test_controllers_chaining_with_controller_manager.cpp
130+
)
131+
target_include_directories(test_controllers_chaining_with_controller_manager PRIVATE include)
132+
target_link_libraries(test_controllers_chaining_with_controller_manager controller_manager test_chainable_controller test_controller)
133+
ament_target_dependencies(test_controllers_chaining_with_controller_manager ros2_control_test_assets)
134+
117135
ament_add_gmock(
118136
test_controller_manager_srvs
119137
test/test_controller_manager_srvs.cpp

controller_manager/include/controller_manager/controller_manager.hpp

Lines changed: 89 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,11 @@
1515
#ifndef CONTROLLER_MANAGER__CONTROLLER_MANAGER_HPP_
1616
#define CONTROLLER_MANAGER__CONTROLLER_MANAGER_HPP_
1717

18+
#include <map>
1819
#include <memory>
1920
#include <string>
2021
#include <tuple>
22+
#include <unordered_map>
2123
#include <vector>
2224

2325
#include "controller_interface/chainable_controller_interface.hpp"
@@ -40,15 +42,21 @@
4042
#include "controller_manager_msgs/srv/switch_controller.hpp"
4143
#include "controller_manager_msgs/srv/unload_controller.hpp"
4244

45+
#include "hardware_interface/handle.hpp"
4346
#include "hardware_interface/resource_manager.hpp"
4447

4548
#include "pluginlib/class_loader.hpp"
4649

4750
#include "rclcpp/executor.hpp"
4851
#include "rclcpp/node.hpp"
52+
#include "rclcpp/node_interfaces/node_logging_interface.hpp"
53+
#include "rclcpp/node_interfaces/node_parameters_interface.hpp"
54+
#include "rclcpp/parameter.hpp"
4955

5056
namespace controller_manager
5157
{
58+
using ControllersListIterator = std::vector<controller_manager::ControllerSpec>::const_iterator;
59+
5260
class ControllerManager : public rclcpp::Node
5361
{
5462
public:
@@ -169,6 +177,18 @@ class ControllerManager : public rclcpp::Node
169177
CONTROLLER_MANAGER_PUBLIC
170178
void stop_controllers();
171179

180+
/**
181+
* Switch chained mode for all the controllers with respect to the following cases:
182+
* - a preceding controller is getting activated --> switch controller to chained mode;
183+
* - all preceding controllers are deactivated --> switch controller from chained mode.
184+
*
185+
* \param[in] chained_mode_switch_list list of controller to switch chained mode.
186+
* \param[in] to_chained_mode flag if controller should be switched *to* or *from* chained mode.
187+
*/
188+
CONTROLLER_MANAGER_PUBLIC
189+
void switch_chained_mode(
190+
const std::vector<std::string> & chained_mode_switch_list, bool to_chained_mode);
191+
172192
CONTROLLER_MANAGER_PUBLIC
173193
void start_controllers();
174194

@@ -243,11 +263,78 @@ class ControllerManager : public rclcpp::Node
243263
// Per controller update rate support
244264
unsigned int update_loop_counter_ = 0;
245265
unsigned int update_rate_ = 100;
266+
std::vector<std::vector<std::string>> chained_controllers_configuration_;
267+
268+
std::unique_ptr<hardware_interface::ResourceManager> resource_manager_;
246269

247270
private:
248271
std::vector<std::string> get_controller_names();
249272

250-
std::unique_ptr<hardware_interface::ResourceManager> resource_manager_;
273+
/**
274+
* Clear request lists used when switching controllers. The lists are shared between "callback" and
275+
* "control loop" threads.
276+
*/
277+
void clear_requests();
278+
279+
/**
280+
* If a controller is deactivated all following controllers (if any exist) should be switched
281+
* 'from' the chained mode.
282+
*
283+
* \param[in] controllers list with controllers.
284+
*/
285+
void propagate_deactivation_of_chained_mode(const std::vector<ControllerSpec> & controllers);
286+
287+
/// Check if all the following controllers will be in active state and in the chained mode
288+
/// after controllers' switch.
289+
/**
290+
* Check recursively that all following controllers of the @controller_it
291+
* - are already active,
292+
* - will not be deactivated,
293+
* - or will be activated.
294+
* The following controllers are added to the request to switch in the chained mode or removed
295+
* from the request to switch from the chained mode.
296+
*
297+
* For each controller the whole chain of following controllers is checked.
298+
*
299+
* NOTE: The automatically adding of following controller into starting list is not implemented
300+
* yet.
301+
*
302+
* \param[in] controllers list with controllers.
303+
* \param[in] strictness if value is equal "MANIPULATE_CONTROLLERS_CHAIN" then all following
304+
* controllers will be automatically added to the activate request list if they are not in the
305+
* deactivate request.
306+
* \param[in] controller_it iterator to the controller for which the following controllers are
307+
* checked.
308+
*
309+
* \returns return_type::OK if all following controllers pass the checks, otherwise
310+
* return_type::ERROR.
311+
*/
312+
controller_interface::return_type check_following_controllers_for_activate(
313+
const std::vector<ControllerSpec> & controllers, int strictness,
314+
const ControllersListIterator controller_it);
315+
316+
/// Check if all the preceding controllers will be in inactive state after controllers' switch.
317+
/**
318+
* Check that all preceding controllers of the @controller_it
319+
* - are inactive,
320+
* - will be deactivated,
321+
* - and will not be activated.
322+
*
323+
* NOTE: The automatically adding of preceding controllers into stopping list is not implemented
324+
* yet.
325+
*
326+
* \param[in] controllers list with controllers.
327+
* \param[in] strictness if value is equal "MANIPULATE_CONTROLLERS_CHAIN" then all preceding
328+
* controllers will be automatically added to the deactivate request list.
329+
* \param[in] controller_it iterator to the controller for which the preceding controllers are
330+
* checked.
331+
*
332+
* \returns return_type::OK if all preceding controllers pass the checks, otherwise
333+
* return_type::ERROR.
334+
*/
335+
controller_interface::return_type check_preceeding_controllers_for_deactivate(
336+
const std::vector<ControllerSpec> & controllers, int strictness,
337+
const ControllersListIterator controller_it);
251338

252339
std::shared_ptr<rclcpp::Executor> executor_;
253340

@@ -366,6 +453,7 @@ class ControllerManager : public rclcpp::Node
366453
set_hardware_component_state_service_;
367454

368455
std::vector<std::string> start_request_, stop_request_;
456+
std::vector<std::string> to_chained_mode_request_, from_chained_mode_request_;
369457
std::vector<std::string> start_command_interface_request_, stop_command_interface_request_;
370458

371459
struct SwitchParams

0 commit comments

Comments
 (0)