@@ -494,34 +494,38 @@ bool ControllerManager::shutdown_controllers()
494494
495495void ControllerManager::init_controller_manager ()
496496{
497- controller_manager_activity_publisher_ =
498- create_publisher<controller_manager_msgs::msg::ControllerManagerActivity>(
499- " ~/activity" , rclcpp::QoS (1 ).reliable ().transient_local ());
500- rt_controllers_wrapper_.set_on_switch_callback (
501- std::bind (&ControllerManager::publish_activity, this ));
502- resource_manager_->set_on_component_state_switch_callback (
503- std::bind (&ControllerManager::publish_activity, this ));
497+ if (!resource_manager_ && !robot_description_.empty ())
498+ {
499+ init_resource_manager (robot_description_);
500+ }
504501
505- // Get parameters needed for RT "update" loop to work
506- if (is_resource_manager_initialized ())
502+ if (!is_resource_manager_initialized ())
507503 {
508- if (params_->enforce_command_limits )
504+ // fallback state
505+ init_min_resource_manager ();
506+ if (!robot_description_notification_timer_)
509507 {
510- resource_manager_->import_joint_limiters (robot_description_);
508+ robot_description_notification_timer_ = create_wall_timer (
509+ std::chrono::seconds (1 ),
510+ [&]()
511+ {
512+ RCLCPP_WARN (get_logger (), " Waiting for data on 'robot_description' topic to finish initialization" );
513+ });
511514 }
512- init_services ();
513- }
514- else
515+ }else
515516 {
516- robot_description_notification_timer_ = create_wall_timer (
517- std::chrono::seconds (1 ),
518- [&]()
519- {
520- RCLCPP_WARN (
521- get_logger (), " Waiting for data on 'robot_description' topic to finish initialization" );
522- });
517+ RCLCPP_INFO (get_logger (),
518+ " Resource Manager has been successfully initialized. Starting Controller Manager "
519+ " services..." );
520+ init_services ();
523521 }
524522
523+ controller_manager_activity_publisher_ =
524+ create_publisher<controller_manager_msgs::msg::ControllerManagerActivity>(
525+ " ~/activity" , rclcpp::QoS (1 ).reliable ().transient_local ());
526+ rt_controllers_wrapper_.set_on_switch_callback (
527+ std::bind (&ControllerManager::publish_activity, this ));
528+
525529 // set QoS to transient local to get messages that have already been published
526530 // (if robot state publisher starts before controller manager)
527531 robot_description_subscription_ = create_subscription<std_msgs::msg::String>(
@@ -627,9 +631,15 @@ void ControllerManager::robot_description_callback(const std_msgs::msg::String &
627631 get_logger (),
628632 " ResourceManager has already loaded a urdf. Ignoring attempt to reload a robot description." );
629633 return ;
630- }
634+ }
635+
631636 init_resource_manager (robot_description_);
632- if (is_resource_manager_initialized ())
637+ if (!is_resource_manager_initialized ())
638+ {
639+ // The RM failed to init AFTER we received the description - a critical error.
640+ // don't finalize controller manager, instead keep waiting for robot description - fallback state
641+ init_min_resource_manager ();
642+ } else
633643 {
634644 RCLCPP_INFO (
635645 get_logger (),
@@ -641,25 +651,50 @@ void ControllerManager::robot_description_callback(const std_msgs::msg::String &
641651
642652void ControllerManager::init_resource_manager (const std::string & robot_description)
643653{
644- if (params_->enforce_command_limits )
645- {
646- resource_manager_->import_joint_limiters (robot_description_);
647- }
648654 hardware_interface::ResourceManagerParams params;
649655 params.robot_description = robot_description;
650656 params.clock = trigger_clock_;
651657 params.logger = this ->get_logger ();
652658 params.executor = executor_;
653659 params.update_rate = static_cast <unsigned int >(params_->update_rate );
654- if (!resource_manager_->load_and_initialize_components (params))
660+ resource_manager_ = std::make_unique<hardware_interface::ResourceManager>(params, false );
661+
662+ RCLCPP_INFO_EXPRESSION (
663+ get_logger (), params_->enforce_command_limits , " Enforcing command limits is enabled..." );
664+ if (params_->enforce_command_limits )
655665 {
656- RCLCPP_WARN (
666+ try
667+ {
668+ resource_manager_->import_joint_limiters (robot_description);
669+ }
670+ catch (const std::exception & e)
671+ {
672+ RCLCPP_ERROR (get_logger (), " Error importing joint limiters: %s" , e.what ());
673+ return ;
674+ }
675+ }
676+
677+ try
678+ {
679+ if (!resource_manager_->load_and_initialize_components (params))
680+ {
681+ RCLCPP_WARN (
682+ get_logger (),
683+ " Could not load and initialize hardware. Please check previous output for more details. "
684+ " After you have corrected your URDF, try to publish robot description again." );
685+ return ;
686+ }
687+ }
688+ catch (const std::exception &e)
689+ {
690+ // Other possible errors when loading components
691+ RCLCPP_ERROR (
657692 get_logger (),
658- " Could not load and initialize hardware. Please check previous output for more details. "
659- " After you have corrected your URDF, try to publish robot description again." );
693+ " Exception caught while loading and initializing components: %s" , e.what ());
660694 return ;
661695 }
662-
696+ resource_manager_->set_on_component_state_switch_callback (std::bind (&ControllerManager::publish_activity, this ));
697+
663698 // Get all components and if they are not defined in parameters activate them automatically
664699 auto components_to_activate = resource_manager_->get_components_status ();
665700
@@ -807,6 +842,13 @@ void ControllerManager::init_resource_manager(const std::string & robot_descript
807842 }
808843}
809844
845+ void ControllerManager::init_min_resource_manager ()
846+ {
847+ resource_manager_ = std::make_unique<hardware_interface::ResourceManager>(trigger_clock_, get_logger ());
848+ resource_manager_->set_on_component_state_switch_callback (
849+ std::bind (&ControllerManager::publish_activity, this ));
850+ }
851+
810852void ControllerManager::init_services ()
811853{
812854 // TODO(anyone): Due to issues with the MutliThreadedExecutor, this control loop does not rely on
0 commit comments