ROS Control:硬件抽象与控制器框架

ROS
4.8k 词

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() {
// 从硬件读取状态 → 更新 pos_, vel_, eff_
}

void write() {
// 将 cmd_ 下发到硬件
}

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); // 50Hz 控制循环
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() {
// 将变量 &pos_, &vel_, &eff_ 注册为 "joint_name" 的状态
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