@@ -292,7 +292,46 @@ ControllerManager::ControllerManager(
292292 init_controller_manager ();
293293}
294294
295- ControllerManager::~ControllerManager () { CLEAR_ALL_ROS2_CONTROL_INTROSPECTION_REGISTRIES (); }
295+ ControllerManager::~ControllerManager ()
296+ {
297+ CLEAR_ALL_ROS2_CONTROL_INTROSPECTION_REGISTRIES ();
298+ if (preshutdown_cb_handle_)
299+ {
300+ rclcpp::Context::SharedPtr context = this ->get_node_base_interface ()->get_context ();
301+ context->remove_pre_shutdown_callback (*(preshutdown_cb_handle_.get ()));
302+ preshutdown_cb_handle_.reset ();
303+ }
304+ }
305+
306+ bool ControllerManager::shutdown_controllers ()
307+ {
308+ RCLCPP_INFO (get_logger (), " Shutting down all controllers in the controller manager." );
309+ // Shutdown all controllers
310+ std::lock_guard<std::recursive_mutex> guard (rt_controllers_wrapper_.controllers_lock_ );
311+ std::vector<ControllerSpec> controllers_list = rt_controllers_wrapper_.get_updated_list (guard);
312+ bool ctrls_shutdown_status = true ;
313+ for (auto & controller : controllers_list)
314+ {
315+ if (is_controller_active (controller.c ))
316+ {
317+ RCLCPP_INFO (
318+ get_logger (), " Deactivating controller '%s'" , controller.c ->get_node ()->get_name ());
319+ controller.c ->get_node ()->deactivate ();
320+ controller.c ->release_interfaces ();
321+ }
322+ if (is_controller_inactive (*controller.c ) || is_controller_unconfigured (*controller.c ))
323+ {
324+ RCLCPP_INFO (
325+ get_logger (), " Shutting down controller '%s'" , controller.c ->get_node ()->get_name ());
326+ shutdown_controller (controller);
327+ }
328+ ctrls_shutdown_status &=
329+ (controller.c ->get_node ()->get_current_state ().id () ==
330+ lifecycle_msgs::msg::State::PRIMARY_STATE_FINALIZED);
331+ executor_->remove_node (controller.c ->get_node ()->get_node_base_interface ());
332+ }
333+ return ctrls_shutdown_status;
334+ }
296335
297336void ControllerManager::init_controller_manager ()
298337{
@@ -332,10 +371,34 @@ void ControllerManager::init_controller_manager()
332371 diagnostics_updater_.add (
333372 " Controller Manager Activity" , this ,
334373 &ControllerManager::controller_manager_diagnostic_callback);
374+
335375 INITIALIZE_ROS2_CONTROL_INTROSPECTION_REGISTRY (
336376 this , hardware_interface::DEFAULT_INTROSPECTION_TOPIC,
337377 hardware_interface::DEFAULT_REGISTRY_KEY);
338378 START_ROS2_CONTROL_INTROSPECTION_PUBLISHER_THREAD (hardware_interface::DEFAULT_REGISTRY_KEY);
379+
380+ // Add on_shutdown callback to stop the controller manager
381+ rclcpp::Context::SharedPtr context = this ->get_node_base_interface ()->get_context ();
382+ preshutdown_cb_handle_ =
383+ std::make_unique<rclcpp::PreShutdownCallbackHandle>(context->add_pre_shutdown_callback (
384+ [this ]()
385+ {
386+ RCLCPP_INFO (get_logger (), " Shutdown request received...." );
387+ if (this ->get_node_base_interface ()->get_associated_with_executor_atomic ().load ())
388+ {
389+ executor_->remove_node (this ->get_node_base_interface ());
390+ }
391+ executor_->cancel ();
392+ if (!this ->shutdown_controllers ())
393+ {
394+ RCLCPP_ERROR (get_logger (), " Failed shutting down the controllers." );
395+ }
396+ if (!resource_manager_->shutdown_components ())
397+ {
398+ RCLCPP_ERROR (get_logger (), " Failed shutting down hardware components." );
399+ }
400+ RCLCPP_INFO (get_logger (), " Shutting down the controller manager." );
401+ }));
339402}
340403
341404void ControllerManager::initialize_parameters ()
0 commit comments