ros_control 是 ROS 中连接控制器算法与真实/仿真硬件的核心框架。理解它,才能真正掌握机器人底层控制。
一、整体架构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| ┌──────────────────────────────────────────────┐ │ ros_control │ │ │ │ ┌──────────────┐ ┌────────────────────┐ │ │ │ Controllers │───→│ Controller Manager │ │ │ │ (PID/轨迹等) │ └────────┬───────────┘ │ │ └──────────────┘ │ │ │ ↓ │ │ ┌──────────────────────────────────────────┐ │ │ │ Hardware Interface │ │ │ │ ┌─────────┐ ┌──────────┐ ┌─────────┐ │ │ │ │ │ Joint │ │ Actuator │ │ Joint │ │ │ │ │ │ State │ │ State │ │ Command │ │ │ │ │ │Interface │ │Interface │ │Interface │ │ │ │ │ └─────────┘ └──────────┘ └─────────┘ │ │ │ └────────────────────┬─────────────────────┘ │ │ │ │ │ ┌────────▼────────┐ │ │ │ RobotHW (派生) │ │ │ │ read()/write() │ │ │ └────────┬────────┘ │ └───────────────────────┼───────────────────────┘ ↓ ┌──────────────────┐ │ 真实硬件 / Gazebo │ └──────────────────┘
|
核心流程:Controller 更新指令 → Hardware Interface 传递 → RobotHW::write() 下发硬件 → 硬件响应 → RobotHW::read() 读取 → 回到 Controller。
二、编写自定义 RobotHW
继承 hardware_interface::RobotHW,实现三个核心方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| #include <hardware_interface/robot_hw.h> #include <controller_manager/controller_manager.h>
class MyRobotHW : public hardware_interface::RobotHW { public: MyRobotHW() {}
void read() { }
void write() { }
private: double pos_, vel_, eff_; double cmd_; };
int main(int argc, char** argv) { ros::init(argc, argv, "my_robot_controller"); ros::NodeHandle nh;
MyRobotHW robot_hw; controller_manager::ControllerManager cm(&robot_hw);
ros::Time prev = ros::Time::now(); ros::Rate rate(50); while (ros::ok()) { ros::Time now = ros::Time::now(); ros::Duration dt = now - prev; robot_hw.read(); cm.update(now, dt); robot_hw.write(); prev = now; rate.sleep(); } }
|
三、注册接口:让 Controller 找到变量
ros_control 通过 Handle 将变量与关节名绑定:
仿真环境(JointStateHandle)
Gazebo 直接生成 JointStateHandle 对应 joints:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| MyRobotHW() { hardware_interface::JointStateHandle state_handle( "joint_name", &pos_, &vel_, &eff_); jnt_state_interface.registerHandle(state_handle);
hardware_interface::JointHandle cmd_handle( jnt_state_interface.getHandle("joint_name"), &cmd_); effort_joint_interface.registerHandle(cmd_handle);
registerInterface(&jnt_state_interface); registerInterface(&effort_joint_interface); }
|
真实硬件(ActuatorStateHandle)
真实电机需要通过 Transmission 建立 actuator 与 joint 的联系:
1 2 3
| hardware_interface::ActuatorStateHandle act_state_handle( "motor_name", &pos_, &vel_, &eff_); act_state_interface.registerHandle(act_state_handle);
|
区别:仿真中 joint 直接对应状态;真实硬件中,电机(actuator)的状态需要经过减速比等变换才能对应到关节(joint)。
四、控制器类型
内置控制器
| 类别 |
控制器 |
用途 |
| effort_controllers |
joint_effort_controller |
力/力矩控制 |
|
joint_position_controller |
位置控制 |
|
joint_velocity_controller |
速度控制 |
| joint_state_controller |
joint_state_controller |
读取所有关节位置 |
| position_controllers |
joint_position_controller |
单关节位置 |
|
joint_group_position_controller |
关节组位置 |
| velocity_controllers |
joint_velocity_controller |
单关节速度 |
|
joint_group_velocity_controller |
关节组速度 |
| joint_trajectory_controllers |
position_controller |
轨迹跟踪 |
命令行管理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| rosrun controller_manager controller_manager load my_controller
rosrun controller_manager controller_manager start my_controller rosrun controller_manager controller_manager stop my_controller
rosrun controller_manager spawner ctrl1 ctrl2 ctrl3
rosrun controller_manager unspawner ctrl1 ctrl2
rosrun controller_manager spawner --stopped ctrl1 ctrl2
|
Launch 文件管理
1 2 3 4 5 6 7
| <node pkg="controller_manager" type="spawner" args="ctrl1 ctrl2" />
<node pkg="controller_manager" type="spawner" args="--stopped ctrl1 ctrl2" />
|
五、Transmission:关节与执行器的桥梁
1 2 3 4 5 6 7 8 9 10
| <transmission name="simple_trans"> <type>transmission_interface/SimpleTransmission</type> <joint name="foo_joint"> <hardwareInterface>EffortJointInterface</hardwareInterface> </joint> <actuator name="foo_motor"> <mechanicalReduction>50</mechanicalReduction> <hardwareInterface>EffortJointInterface</hardwareInterface> </actuator> </transmission>
|
joint name:必须对应 URDF 中定义的关节名
type:当前仅实现了 SimpleTransmission
hardwareInterface:目前仅 EffortJointInterface 功能完整
mechanicalReduction:电机减速比(actuator → joint 的变换系数)
六、Gazebo 中启用 ros_control
在 URDF 末尾添加:
1 2 3 4 5
| <gazebo> <plugin name="gazebo_ros_control" filename="libgazebo_ros_control.so"> <robotNamespace>/my_robot</robotNamespace> </plugin> </gazebo>
|
这个插件自动解析 transmission 标签,加载硬件接口和 controller manager。
七、Joint Limits
可通过参数服务器或 URDF 配置关节限制——速度、位置、加速度、力矩、软限位等。
1 2 3 4 5 6 7 8 9
| joint_limits: foo_joint: has_position_limits: true min_position: -1.57 max_position: 1.57 has_velocity_limits: true max_velocity: 3.14 has_effort_limits: true max_effort: 10.0
|