ros2_control - rolling
Loading...
Searching...
No Matches
controller_manager.hpp
1// Copyright 2020 Open Source Robotics Foundation, Inc.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#ifndef CONTROLLER_MANAGER__CONTROLLER_MANAGER_HPP_
16#define CONTROLLER_MANAGER__CONTROLLER_MANAGER_HPP_
17
18#include <map>
19#include <memory>
20#include <string>
21#include <unordered_map>
22#include <utility>
23#include <vector>
24
25#include "controller_interface/chainable_controller_interface.hpp"
26#include "controller_interface/controller_interface.hpp"
27#include "controller_interface/controller_interface_base.hpp"
28
29#include "controller_manager/controller_spec.hpp"
30#include "controller_manager_msgs/msg/controller_manager_activity.hpp"
31#include "controller_manager_msgs/srv/cleanup_controller.hpp"
32#include "controller_manager_msgs/srv/configure_controller.hpp"
33#include "controller_manager_msgs/srv/list_controller_types.hpp"
34#include "controller_manager_msgs/srv/list_controllers.hpp"
35#include "controller_manager_msgs/srv/list_hardware_components.hpp"
36#include "controller_manager_msgs/srv/list_hardware_interfaces.hpp"
37#include "controller_manager_msgs/srv/load_controller.hpp"
38#include "controller_manager_msgs/srv/reload_controller_libraries.hpp"
39#include "controller_manager_msgs/srv/set_hardware_component_state.hpp"
40#include "controller_manager_msgs/srv/switch_controller.hpp"
41#include "controller_manager_msgs/srv/unload_controller.hpp"
42
43#include "diagnostic_updater/diagnostic_updater.hpp"
44#include "hardware_interface/helpers.hpp"
45#include "hardware_interface/resource_manager.hpp"
46
47#include "pluginlib/class_loader.hpp"
48
49#include "rclcpp/executor.hpp"
50#include "rclcpp/node.hpp"
51#include "std_msgs/msg/string.hpp"
52
53namespace controller_manager
54{
55class ParamListener;
56struct Params;
57using ControllersListIterator = std::vector<controller_manager::ControllerSpec>::const_iterator;
58
59rclcpp::NodeOptions get_cm_node_options();
60
61class ControllerManager : public rclcpp::Node
62{
63public:
64 static constexpr bool kWaitForAllResources = false;
65 static constexpr auto kInfiniteTimeout = 0;
66
68 std::unique_ptr<hardware_interface::ResourceManager> resource_manager,
69 std::shared_ptr<rclcpp::Executor> executor,
70 const std::string & manager_node_name = "controller_manager",
71 const std::string & node_namespace = "",
72 const rclcpp::NodeOptions & options = get_cm_node_options());
73
75 std::shared_ptr<rclcpp::Executor> executor,
76 const std::string & manager_node_name = "controller_manager",
77 const std::string & node_namespace = "",
78 const rclcpp::NodeOptions & options = get_cm_node_options());
79
81 std::shared_ptr<rclcpp::Executor> executor, const std::string & urdf,
82 bool activate_all_hw_components, const std::string & manager_node_name = "controller_manager",
83 const std::string & node_namespace = "",
84 const rclcpp::NodeOptions & options = get_cm_node_options());
85
86 virtual ~ControllerManager();
87
89
93
94 void robot_description_callback(const std_msgs::msg::String & msg);
95
96 void init_resource_manager(const std::string & robot_description);
97
98 controller_interface::ControllerInterfaceBaseSharedPtr load_controller(
99 const std::string & controller_name, const std::string & controller_type);
100
102
107 controller_interface::ControllerInterfaceBaseSharedPtr load_controller(
108 const std::string & controller_name);
109
110 controller_interface::return_type unload_controller(const std::string & controller_name);
111
112 controller_interface::return_type cleanup_controller(const std::string & controller_name);
113
114 std::vector<ControllerSpec> get_loaded_controllers() const;
115
116 template <
117 typename T, typename std::enable_if<
118 std::is_convertible<T *, controller_interface::ControllerInterfaceBase *>::value,
119 T>::type * = nullptr>
120 controller_interface::ControllerInterfaceBaseSharedPtr add_controller(
121 std::shared_ptr<T> controller, const std::string & controller_name,
122 const std::string & controller_type)
123 {
124 ControllerSpec controller_spec;
125 controller_spec.c = controller;
126 controller_spec.info.name = controller_name;
127 controller_spec.info.type = controller_type;
128 controller_spec.last_update_cycle_time = std::make_shared<rclcpp::Time>(0);
129 return add_controller_impl(controller_spec);
130 }
131
132 controller_interface::ControllerInterfaceBaseSharedPtr add_controller(
133 const ControllerSpec & controller_spec)
134 {
135 return add_controller_impl(controller_spec);
136 }
137
139
144 controller_interface::return_type configure_controller(const std::string & controller_name);
145
147
155 controller_interface::return_type switch_controller(
156 const std::vector<std::string> & activate_controllers,
157 const std::vector<std::string> & deactivate_controllers, int strictness,
158 bool activate_asap = kWaitForAllResources,
159 const rclcpp::Duration & timeout = rclcpp::Duration::from_nanoseconds(kInfiniteTimeout));
160
162
171 controller_interface::return_type switch_controller_cb(
172 const std::vector<std::string> & activate_controllers,
173 const std::vector<std::string> & deactivate_controllers, int strictness, bool activate_asap,
174 const rclcpp::Duration & timeout, std::string & message);
175
177
184 void read(const rclcpp::Time & time, const rclcpp::Duration & period);
185
187
194 controller_interface::return_type update(
195 const rclcpp::Time & time, const rclcpp::Duration & period);
196
198
205 void write(const rclcpp::Time & time, const rclcpp::Duration & period);
206
208
212 // TODO(anyone): Due to issues with the MultiThreadedExecutor, this control loop does not rely on
213 // the executor (see issue #260).
214 // rclcpp::CallbackGroup::SharedPtr deterministic_callback_group_;
215
217
222 {
223 return resource_manager_ && resource_manager_->are_components_initialized();
224 }
225
227
233 unsigned int get_update_rate() const;
234
236
246 rclcpp::Clock::SharedPtr get_trigger_clock() const;
247
248protected:
249 void init_services();
250
251 controller_interface::ControllerInterfaceBaseSharedPtr add_controller_impl(
252 const ControllerSpec & controller);
253
254 void manage_switch();
255
257
265 const std::vector<ControllerSpec> & rt_controller_list,
266 const std::vector<std::string> & controllers_to_deactivate);
267
277 const std::vector<std::string> & chained_mode_switch_list, bool to_chained_mode);
278
280
289 const std::vector<ControllerSpec> & rt_controller_list,
290 const std::vector<std::string> & controllers_to_activate, int strictness);
291
292 void list_controllers_srv_cb(
293 const std::shared_ptr<controller_manager_msgs::srv::ListControllers::Request> request,
294 std::shared_ptr<controller_manager_msgs::srv::ListControllers::Response> response);
295
296 void list_hardware_interfaces_srv_cb(
297 const std::shared_ptr<controller_manager_msgs::srv::ListHardwareInterfaces::Request> request,
298 std::shared_ptr<controller_manager_msgs::srv::ListHardwareInterfaces::Response> response);
299
300 void load_controller_service_cb(
301 const std::shared_ptr<controller_manager_msgs::srv::LoadController::Request> request,
302 std::shared_ptr<controller_manager_msgs::srv::LoadController::Response> response);
303
304 void configure_controller_service_cb(
305 const std::shared_ptr<controller_manager_msgs::srv::ConfigureController::Request> request,
306 std::shared_ptr<controller_manager_msgs::srv::ConfigureController::Response> response);
307
308 void reload_controller_libraries_service_cb(
309 const std::shared_ptr<controller_manager_msgs::srv::ReloadControllerLibraries::Request> request,
310 std::shared_ptr<controller_manager_msgs::srv::ReloadControllerLibraries::Response> response);
311
312 void switch_controller_service_cb(
313 const std::shared_ptr<controller_manager_msgs::srv::SwitchController::Request> request,
314 std::shared_ptr<controller_manager_msgs::srv::SwitchController::Response> response);
315
316 void unload_controller_service_cb(
317 const std::shared_ptr<controller_manager_msgs::srv::UnloadController::Request> request,
318 std::shared_ptr<controller_manager_msgs::srv::UnloadController::Response> response);
319
320 void cleanup_controller_service_cb(
321 const std::shared_ptr<controller_manager_msgs::srv::CleanupController::Request> request,
322 std::shared_ptr<controller_manager_msgs::srv::CleanupController::Response> response);
323
324 void list_controller_types_srv_cb(
325 const std::shared_ptr<controller_manager_msgs::srv::ListControllerTypes::Request> request,
326 std::shared_ptr<controller_manager_msgs::srv::ListControllerTypes::Response> response);
327
328 void list_hardware_components_srv_cb(
329 const std::shared_ptr<controller_manager_msgs::srv::ListHardwareComponents::Request> request,
330 std::shared_ptr<controller_manager_msgs::srv::ListHardwareComponents::Response> response);
331
332 void set_hardware_component_state_srv_cb(
333 const std::shared_ptr<controller_manager_msgs::srv::SetHardwareComponentState::Request> request,
334 std::shared_ptr<controller_manager_msgs::srv::SetHardwareComponentState::Response> response);
335
336 // Per controller update rate support
337 unsigned int update_loop_counter_ = 0;
338 unsigned int update_rate_;
339 std::vector<std::vector<std::string>> chained_controllers_configuration_;
340
341 std::unique_ptr<hardware_interface::ResourceManager> resource_manager_;
342
343private:
344 std::vector<std::string> get_controller_names();
345 std::pair<std::string, std::string> split_command_interface(
346 const std::string & command_interface);
347 void init_controller_manager();
348
349 void initialize_parameters();
350
356 controller_interface::return_type cleanup_controller(
357 const controller_manager::ControllerSpec & controller);
358
364 void shutdown_controller(const controller_manager::ControllerSpec & controller) const;
365
370 void clear_requests();
371
382 void perform_hardware_command_mode_change(
383 const std::vector<ControllerSpec> & rt_controller_list,
384 const std::vector<std::string> & activate_controllers_list,
385 const std::vector<std::string> & deactivate_controllers_list,
386 const std::string & rt_cycle_name);
387
394 void propagate_deactivation_of_chained_mode(const std::vector<ControllerSpec> & controllers);
395
398
422 controller_interface::return_type check_following_controllers_for_activate(
423 const std::vector<ControllerSpec> & controllers, int strictness,
424 const ControllersListIterator controller_it, std::string & message);
425
427
446 controller_interface::return_type check_preceding_controllers_for_deactivate(
447 const std::vector<ControllerSpec> & controllers, int strictness,
448 const ControllersListIterator controller_it, std::string & message);
449
452
459 controller_interface::return_type check_fallback_controllers_state_pre_activation(
460 const std::vector<ControllerSpec> & controllers, const ControllersListIterator controller_it,
461 std::string & message);
462
472 controller_interface::return_type check_for_interfaces_availability_to_activate(
473 const std::vector<ControllerSpec> & controllers, const std::vector<std::string> activation_list,
474 const std::vector<std::string> deactivation_list, std::string & message);
475
495 void update_list_with_controller_chain(
496 const std::string & ctrl_name, std::vector<std::string>::iterator controller_iterator,
497 bool append_to_controller);
498
505 void build_controllers_topology_info(const std::vector<ControllerSpec> & controllers);
506
512 void publish_activity();
513
514 void controller_activity_diagnostic_callback(diagnostic_updater::DiagnosticStatusWrapper & stat);
515
516 void hardware_components_diagnostic_callback(diagnostic_updater::DiagnosticStatusWrapper & stat);
517
518 void controller_manager_diagnostic_callback(diagnostic_updater::DiagnosticStatusWrapper & stat);
519
527 rclcpp::NodeOptions determine_controller_node_options(const ControllerSpec & controller) const;
528
534 void cleanup_controller_exported_interfaces(const ControllerSpec & controller);
535
536 std::shared_ptr<controller_manager::ParamListener> cm_param_listener_;
537 std::shared_ptr<controller_manager::Params> params_;
538 diagnostic_updater::Updater diagnostics_updater_;
539
540 std::shared_ptr<rclcpp::Executor> executor_;
541
542 std::shared_ptr<pluginlib::ClassLoader<controller_interface::ControllerInterface>> loader_;
543 std::shared_ptr<pluginlib::ClassLoader<controller_interface::ChainableControllerInterface>>
544 chainable_loader_;
545
547
551 rclcpp::CallbackGroup::SharedPtr best_effort_callback_group_;
552
564 class RTControllerListWrapper
565 {
566 // *INDENT-OFF*
567 public:
568 // *INDENT-ON*
570
575 std::vector<ControllerSpec> & update_and_get_used_by_rt_list();
576
585 std::vector<ControllerSpec> & get_unused_list(
586 const std::lock_guard<std::recursive_mutex> & guard);
587
589
594 const std::vector<ControllerSpec> & get_updated_list(
595 const std::lock_guard<std::recursive_mutex> & guard) const;
596
603 void switch_updated_list(const std::lock_guard<std::recursive_mutex> & guard);
604
606
609 void set_on_switch_callback(std::function<void()> callback);
610
611 // Mutex protecting the controllers list
612 // must be acquired before using any list other than the "used by rt"
613 mutable std::recursive_mutex controllers_lock_;
614
615 // *INDENT-OFF*
616 private:
617 // *INDENT-ON*
619
622 int get_other_list(int index) const;
623
624 void wait_until_rt_not_using(
625 int index, std::chrono::microseconds sleep_delay = std::chrono::microseconds(200)) const;
626
627 std::vector<ControllerSpec> controllers_lists_[2];
629 int updated_controllers_index_ = 0;
631 int used_by_realtime_controllers_index_ = -1;
633 std::function<void()> on_switch_callback_ = nullptr;
634 };
635
636 bool use_sim_time_;
637 rclcpp::Clock::SharedPtr trigger_clock_ = nullptr;
638 std::unique_ptr<rclcpp::PreShutdownCallbackHandle> preshutdown_cb_handle_{nullptr};
639 RTControllerListWrapper rt_controllers_wrapper_;
640 std::unordered_map<std::string, ControllerChainSpec> controller_chain_spec_;
641 std::vector<std::string> ordered_controllers_names_;
644 std::mutex services_lock_;
645 rclcpp::Publisher<controller_manager_msgs::msg::ControllerManagerActivity>::SharedPtr
646 controller_manager_activity_publisher_;
647 rclcpp::Service<controller_manager_msgs::srv::ListControllers>::SharedPtr
648 list_controllers_service_;
649 rclcpp::Service<controller_manager_msgs::srv::ListControllerTypes>::SharedPtr
650 list_controller_types_service_;
651 rclcpp::Service<controller_manager_msgs::srv::LoadController>::SharedPtr load_controller_service_;
652 rclcpp::Service<controller_manager_msgs::srv::ConfigureController>::SharedPtr
653 configure_controller_service_;
654 rclcpp::Service<controller_manager_msgs::srv::ReloadControllerLibraries>::SharedPtr
655 reload_controller_libraries_service_;
656 rclcpp::Service<controller_manager_msgs::srv::SwitchController>::SharedPtr
657 switch_controller_service_;
658 rclcpp::Service<controller_manager_msgs::srv::UnloadController>::SharedPtr
659 unload_controller_service_;
660 rclcpp::Service<controller_manager_msgs::srv::CleanupController>::SharedPtr
661 cleanup_controller_service_;
662
663 rclcpp::Service<controller_manager_msgs::srv::ListHardwareComponents>::SharedPtr
664 list_hardware_components_service_;
665 rclcpp::Service<controller_manager_msgs::srv::ListHardwareInterfaces>::SharedPtr
666 list_hardware_interfaces_service_;
667 rclcpp::Service<controller_manager_msgs::srv::SetHardwareComponentState>::SharedPtr
668 set_hardware_component_state_service_;
669
670 std::map<std::string, std::vector<std::string>> controller_chained_reference_interfaces_cache_;
671 std::map<std::string, std::vector<std::string>> controller_chained_state_interfaces_cache_;
672
673 std::string robot_description_;
674 rclcpp::Subscription<std_msgs::msg::String>::SharedPtr robot_description_subscription_;
675 rclcpp::TimerBase::SharedPtr robot_description_notification_timer_;
676
677 struct ControllerManagerExecutionTime
678 {
679 double read_time = 0.0;
680 double update_time = 0.0;
681 double write_time = 0.0;
682 double switch_time = 0.0;
683 double total_time = 0.0;
684 double switch_chained_mode_time = 0.0;
685 double switch_perform_mode_time = 0.0;
686 double deactivation_time = 0.0;
687 double activation_time = 0.0;
688 };
689
690 ControllerManagerExecutionTime execution_time_;
691
693
694 struct SwitchParams
695 {
696 void reset()
697 {
698 do_switch = false;
699 strictness = 0;
700 activate_asap = false;
701 ready_to_switch = false;
702 }
703
704 std::atomic_bool do_switch{false};
705 std::atomic_bool ready_to_switch{false};
706
707 // Switch options
708 int strictness;
709 std::atomic_bool activate_asap{false};
710 std::chrono::nanoseconds timeout;
711
712 // conditional variable and mutex to wait for the switch to complete
713 std::condition_variable cv;
714 std::mutex mutex;
715
716 bool skip_cycle(const controller_manager::ControllerSpec & spec) const
717 {
718 const std::string controller_name = spec.info.name;
719 return ros2_control::has_item(activate_request, controller_name) ||
720 ros2_control::has_item(deactivate_request, controller_name) ||
721 ros2_control::has_item(to_chained_mode_request, controller_name) ||
722 ros2_control::has_item(from_chained_mode_request, controller_name);
723 }
724
725 // The controllers list to activate and deactivate
726 std::vector<std::string> activate_request;
727 std::vector<std::string> deactivate_request;
728 std::vector<std::string> to_chained_mode_request;
729 std::vector<std::string> from_chained_mode_request;
730 std::vector<std::string> activate_command_interface_request;
731 std::vector<std::string> deactivate_command_interface_request;
732 };
733
734 SwitchParams switch_params_;
735
736 struct RTBufferVariables
737 {
738 RTBufferVariables()
739 {
740 deactivate_controllers_list.reserve(1000);
741 activate_controllers_using_interfaces_list.reserve(1000);
742 fallback_controllers_list.reserve(1000);
743 interfaces_to_start.reserve(1000);
744 interfaces_to_stop.reserve(1000);
745 concatenated_string.reserve(5000);
746 }
747
748 const std::string & get_concatenated_string(
749 const std::vector<std::string> & strings, bool clear_string = true)
750 {
751 if (clear_string)
752 {
753 concatenated_string.clear();
754 }
755 for (const auto & str : strings)
756 {
757 concatenated_string.append(str);
758 concatenated_string.append(" ");
759 }
760 return concatenated_string;
761 }
762
763 std::vector<std::string> deactivate_controllers_list;
764 std::vector<std::string> activate_controllers_using_interfaces_list;
765 std::vector<std::string> fallback_controllers_list;
766 std::vector<std::string> interfaces_to_start;
767 std::vector<std::string> interfaces_to_stop;
768 std::string concatenated_string;
769 };
770 RTBufferVariables rt_buffer_;
771};
772
773} // namespace controller_manager
774
775#endif // CONTROLLER_MANAGER__CONTROLLER_MANAGER_HPP_
Definition controller_manager.hpp:62
void read(const rclcpp::Time &time, const rclcpp::Duration &period)
Read values to state interfaces.
Definition controller_manager.cpp:3201
controller_interface::return_type switch_controller(const std::vector< std::string > &activate_controllers, const std::vector< std::string > &deactivate_controllers, int strictness, bool activate_asap=kWaitForAllResources, const rclcpp::Duration &timeout=rclcpp::Duration::from_nanoseconds(kInfiniteTimeout))
switch_controller Deactivates some controllers and activates others.
Definition controller_manager.cpp:1774
unsigned int get_update_rate() const
Update rate of the main control loop in the controller manager.
Definition controller_manager.cpp:3723
controller_interface::return_type update(const rclcpp::Time &time, const rclcpp::Duration &period)
Run update on controllers.
Definition controller_manager.cpp:3298
bool shutdown_controllers()
Shutdown all controllers in the controller manager.
Definition controller_manager.cpp:603
controller_interface::return_type switch_controller_cb(const std::vector< std::string > &activate_controllers, const std::vector< std::string > &deactivate_controllers, int strictness, bool activate_asap, const rclcpp::Duration &timeout, std::string &message)
switch_controller Deactivates some controllers and activates others.
Definition controller_manager.cpp:1784
void switch_chained_mode(const std::vector< std::string > &chained_mode_switch_list, bool to_chained_mode)
Definition controller_manager.cpp:2516
rclcpp::Clock::SharedPtr get_trigger_clock() const
Get the trigger clock of the controller manager.
Definition controller_manager.cpp:3725
void deactivate_controllers(const std::vector< ControllerSpec > &rt_controller_list, const std::vector< std::string > &controllers_to_deactivate)
Deactivate chosen controllers from real-time controller list.
Definition controller_manager.cpp:2455
void activate_controllers(const std::vector< ControllerSpec > &rt_controller_list, const std::vector< std::string > &controllers_to_activate, int strictness)
Activate chosen controllers from real-time controller list.
Definition controller_manager.cpp:2562
void write(const rclcpp::Time &time, const rclcpp::Duration &period)
Write values from command interfaces.
Definition controller_manager.cpp:3524
controller_interface::return_type configure_controller(const std::string &controller_name)
configure_controller Configure controller by name calling their "configure" method.
Definition controller_manager.cpp:1523
bool is_resource_manager_initialized() const
Deterministic (real-time safe) callback group, e.g., update function.
Definition controller_manager.hpp:221
Definition statistics_types.hpp:49
Controller Specification.
Definition controller_spec.hpp:40
std::string type
Controller type.
Definition controller_info.hpp:34
std::string name
Controller name.
Definition controller_info.hpp:31