ROS2中Controller Manager未加载控制器参数的问题排查与解决
问题:ROS2 Controller Manager未加载控制器配置参数
我为移动机器人开发了若干控制器,编译过程无报错,但运行后执行指令ros2 param list /controller_manager,仅显示默认参数,看不到arm_position_controller、shovel_position_controller等自定义控制器的相关配置。以下是相关文件:
控制器launch文件
from launch import LaunchDescription from launch_ros.actions import Node from ament_index_python.packages import get_package_share_directory from launch.substitutions import Command import os def generate_launch_description(): # Path to URDF file urdf_file = os.path.join(get_package_share_directory('localisation_sim_task'), 'urdf', 'load_vehicle.urdf') # Path to the controllers configuration (params.yaml) params_file = os.path.join(get_package_share_directory('localisation_sim_task'), 'config', 'params.yaml') robot_description = Command(['xacro ', urdf_file]) return LaunchDescription([ # Robot state publisher to publish the URDF Node( package='robot_state_publisher', executable='robot_state_publisher', name='robot_state_publisher', output='screen', parameters=[{'robot_description': robot_description}], ), # Start ros2_control_node with the controllers from params.yaml Node( package='controller_manager', executable='ros2_control_node', parameters=[params_file], output='screen', ), # Load and start the arm position controller Node( package='controller_manager', executable='spawner', arguments=['arm_position_controller'], output='screen', ), # Load and start the shovel position controller Node( package='controller_manager', executable='spawner', arguments=['shovel_position_controller'], output='screen', ), # Start custom node for controlling the arm and shovel Node( package='localisation_sim_task', executable='arm_shovel_controller', name='arm_shovel_controller', output='screen', ), # Start steering velocity controller Node( package='localisation_sim_task', executable='steering_velocity_controller', name='steering_velocity_controller', output='screen', ), ])
控制器节点CPP文件
#include "rclcpp/rclcpp.hpp" #include "std_msgs/msg/float64.hpp" class ArmShovelController : public rclcpp::Node { public: ArmShovelController() : Node("arm_shovel_controller") { arm_pub_ = this->create_publisher<std_msgs::msg::Float64>("/arm_position_controller/command", 10); shovel_pub_ = this->create_publisher<std_msgs::msg::Float64>("/shovel_position_controller/command", 10); // Publish commands to move the arm and shovel timer_ = this->create_wall_timer( std::chrono::milliseconds(100), std::bind(&ArmShovelController::publish_commands, this)); } private: void publish_commands() { auto arm_msg = std_msgs::msg::Float64(); auto shovel_msg = std_msgs::msg::Float64(); // Example positions arm_msg.data = 0.5; // Example: move the arm to 0.5 radians shovel_msg.data = 0.2; // Example: move the shovel to 0.2 radians arm_pub_->publish(arm_msg); shovel_pub_->publish(shovel_msg); } rclcpp::Publisher<std_msgs::msg::Float64>::SharedPtr arm_pub_; rclcpp::Publisher<std_msgs::msg::Float64>::SharedPtr shovel_pub_; rclcpp::TimerBase::SharedPtr timer_; }; int main(int argc, char **argv) { rclcpp::init(argc, argv); rclcpp::spin(std::make_shared<ArmShovelController>()); rclcpp::shutdown(); return 0; }
params.yaml参数文件
arm_position_controller: ros__parameters: type: position_controllers/JointPositionController # Define the type of the controller joint: arm_joint command_interfaces: - position state_interfaces: - position - velocity shovel_position_controller: ros__parameters: type: position_controllers/JointPositionController # Define the type of the controller joint: shovel_joint command_interfaces: - position state_interfaces: - position - velocity steering_velocity_controller: ros__parameters: type: velocity_controllers/JointVelocityController # Define the type of the controller joint: steering_joint command_interfaces: - velocity state_interfaces: - velocity
运行后ros2 param list /controller_manager输出:
qos_overrides./parameter_events.publisher.depth qos_overrides./parameter_events.publisher.durability qos_overrides./parameter_events.publisher.history qos_overrides./parameter_events.publisher.reliability use_sim_time
原因分析
- params.yaml结构不符合ROS2 Control规范:ROS2 Control要求所有控制器配置必须嵌套在
controller_manager节点的ros__parameters字段下,当前配置直接将控制器作为顶级键,导致controller_manager无法识别并加载这些参数。 - 缺少controller_manager必需的更新频率参数:
controller_manager需要指定update_rate参数来控制硬件接口的更新频率,当前配置中未包含该参数,这也会导致配置加载异常。 - Spawner节点时序问题:Spawner节点可能在
controller_manager完全加载配置前就执行,导致控制器加载失败(即使参数正确,也可能出现这类问题)。
解决步骤
1. 修改params.yaml结构
将所有控制器配置嵌套到controller_manager.ros__parameters下,并添加update_rate参数:
controller_manager: ros__parameters: update_rate: 100 # 硬件接口更新频率,单位Hz,必须指定 arm_position_controller: type: position_controllers/JointPositionController joint: arm_joint command_interfaces: - position state_interfaces: - position - velocity shovel_position_controller: type: position_controllers/JointPositionController joint: shovel_joint command_interfaces: - position state_interfaces: - position - velocity steering_velocity_controller: type: velocity_controllers/JointVelocityController joint: steering_joint command_interfaces: - velocity state_interfaces: - velocity
2. 调整Launch文件中的Spawner节点
给Spawner节点添加--wait参数,让其等待controller_manager的服务可用后再加载控制器,避免时序问题:
# 加载并启动机械臂位置控制器 Node( package='controller_manager', executable='spawner', arguments=['arm_position_controller', '--wait'], output='screen', ), # 加载并启动铲斗位置控制器 Node( package='controller_manager', executable='spawner', arguments=['shovel_position_controller', '--wait'], output='screen', ),
3. 验证配置
- 重新编译包:
colcon build --packages-select localisation_sim_task - 刷新环境变量:
source install/setup.bash - 启动launch文件:
ros2 launch localisation_sim_task <你的launch文件名>.launch.py - 检查参数:执行
ros2 param list /controller_manager,此时应能看到所有控制器的相关参数 - 检查控制器状态:执行
ros2 control list_controllers,确认控制器处于active状态
内容的提问来源于stack exchange,提问作者Macedon971
相关产品推荐
相关产品推荐

