ROS2 多机器人通用 Driver 层复盘:BaseRobotDriver 到多平台 Mock 切换实现

1. Driver 层的作用

在机器人二次开发中,不能把所有逻辑都写在 ROS2 节点里。

ROS2 节点更适合负责:

Topic 通信 Service 调用 参数读取 launch 启动 日志输出 任务逻辑组织

而机器人底层相关能力应该交给 Driver 层,例如:

连接机器人 读取状态 发送速度 普通停止 急停 模式切换

这样设计的核心思想是:

ROS2 节点负责"通信和调度",Driver 层负责"真正控制机器人"。

后续如果从 Mock 机器人换成真实四足机器人、人形机器人或者机械臂,只需要替换 Driver,不需要大改上层 ROS2 节点。


2. BaseRobotDriver 统一接口

BaseRobotDriver 是所有机器人 Driver 的统一标准。

它不直接控制机器人,而是规定每一种机器人都应该具备哪些基础能力。

推荐接口:

connect() get_state() send_velocity(linear_x, angular_z) stop() emergency_stop() set_mode(mode)

每个接口的含义:

|--------------------|------------------------------------|
| 接口 | 作用 |
| connect() | 连接机器人,或初始化模拟机器人 |
| get_state() | 获取机器人状态,例如电量、速度、模式、急停状态 |
| send_velocity() | 发送速度命令 |
| stop() | 普通停止 |
| emergency_stop() | 急停,进入安全停止状态 |
| set_mode() | 切换机器人模式,例如 stand/walk/stop/estop |


3. MockRobotDriver 的意义

MockRobotDriver 是一个模拟机器人驱动。

它不需要真实硬件,而是在代码里模拟机器人状态和控制行为。

它可以模拟:是否连接 connected 当前模式 mode 当前电量 battery 当前线速度 linear_x

当前角速度 angular_z 是否急停 emergency_stop

示例状态:{

"connected": true,

"mode": "stand",

"battery": 87.5,

"linear_x": 0.0,

"angular_z": 0.0,

"emergency_stop": false

}

没有真实机器人时,也能先把 ROS2 通信、状态发布、速度控制、安全保护这些上层逻辑跑通。


4. /robot/state 状态发布

机器人状态是持续变化的数据,所以应该用 ROS2 Topic 发布。

推荐话题名:/robot/state

前期为了简单,可以用:std_msgs/msg/String 里面放 JSON 字符串。

数据流如下:

复制代码
MockRobotDriver
      |
      | get_state()
      v
state_publisher_node
      |
      | publish
      v
/robot/state

也就是说:

  1. state_publisher_node 定时调用 driver.get_state()
  2. Driver 返回当前机器人状态
  3. 节点把状态发布到 /robot/state
  4. 其他模块,比如 FSM、安全模块、可视化模块,都可以订阅这个状态

验证命令:ros2 topic echo /robot/state

也可以查看发布频率:ros2 topic hz /robot/state


5. /cmd_vel 速度控制

移动机器人常用 /cmd_vel 表示速度控制命令。

话题名:/cmd_vel

消息类型:geometry_msgs/msg/Twist

常用字段:linear.x # 前进 / 后退速度 angular.z # 左转 / 右转角速度

控制节点的数据流:

复制代码
/cmd_vel
   |
   | Twist 消息
   v
control_node
   |
   | 提取 linear.x 和 angular.z
   v
driver.send_velocity()

也就是说,control_node 不直接控制硬件,而是把 ROS2 收到的速度命令转交给 Driver 层。

/cmd_vel 负责 ROS2 通信,send_velocity() 负责底层控制。


6. 速度限幅

速度控制不能完全相信上游输入。

因为 /cmd_vel 可能来自:键盘控制节点 视觉闭环节点 FSM 状态机 导航模块 测试脚本

如果某个节点发出了过大的速度,机器人可能发生危险。所以控制节点里要加入速度限幅。

例如参数:max_linear_speed: 0.5 max_angular_speed: 1.0

如果收到:linear.x = 9.9 angular.z = 9.9

实际下发给 Driver 的速度应该被限制成:linear.x = 0.5 angular.z = 1.0

超过最大速度,就裁剪到安全范围内。


7. 普通停止和急停

机器人停止至少要区分两种:普通停止 stop() 急停 emergency_stop()

|--------------------|-------------|--------------|
| 功能 | 含义 | 后续能否继续运动 |
| stop() | 普通停止,把速度清零 | 可以 |
| emergency_stop() | 急停,进入安全锁定状态 | 不应该直接继续 |

stop() 是"停一下",emergency_stop() 是"危险情况下立刻停,并且锁住运动"。

急停后,普通速度命令不应该继续生效。

例如:

复制代码
触发 emergency_stop
        |
        v
速度清零
        |
        v
emergency_stop = True
        |
        v
后续 send_velocity() 被拒绝

急停可以设计成 Service:/robot/emergency_stop

调用命令:ros2 service call /robot/emergency_stop std_srvs/srv/Trigger "{}"


8. Heartbeat 心跳机制

Heartbeat 中文叫心跳机制。它用来判断控制端是否还在线。

例如控制端持续发送:/robot/heartbeat

如果机器人控制节点长时间没有收到心跳,就认为控制端可能崩溃或断开连接。

这时应该自动调用:driver.stop()

它主要解决这个危险场景:

程序崩溃后,机器人继续执行最后一次速度命令。

例如机器人正在前进,控制程序突然退出,如果没有心跳超时保护,机器人可能还会保持前进状态。

心跳逻辑可以理解为:

复制代码
如果当前时间 - 上一次心跳时间 > heartbeat_timeout
    自动停止机器人

9. 多平台 Driver 切换

为了体现"多机器人平台二次开发",不能只写一个 Mock 机器人。

可以设计多个 Driver:

复制代码
BaseRobotDriver
      |
      ├── MockRobotDriver
      ├── MockDogDriver
      └── MockHumanoidDriver

它们都实现同一套接口:connect() get_state() send_velocity() stop() emergency_stop() set_mode()

区别只是底层实现不同。

例如: MockDogDriver 模拟四足机器人

MockHumanoidDriver 模拟人形机器人

MockRobotDriver 通用模拟机器人

上层 ROS2 节点不需要知道当前是哪种机器人,只需要调用统一接口。

这就是接口抽象的价值:

上层代码不变,底层 Driver 可替换。


10. 配置文件切换机器人类型

为了避免在代码里写死机器人类型,可以使用配置文件。

例如:robot_type: mock_dog max_linear_speed: 0.5 max_angular_speed: 1.0 heartbeat_timeout: 2.0

也可以切换成:robot_type: mock_humanoid

切换机器人平台时,只改配置,不改代码。


11. 推荐项目结构

可以采用下面这种结构:

复制代码
robot_base/
├── robot_base/
│   ├── drivers/
│   │   ├── base_driver.py
│   │   ├── mock_robot_driver.py
│   │   ├── mock_dog_driver.py
│   │   └── mock_humanoid_driver.py
│   │
│   ├── nodes/
│   │   ├── state_publisher_node.py
│   │   └── control_node.py
│   │
│   ├── config/
│   │   └── robot_config.yaml
│   │
│   └── utils/
│       └── driver_factory.py
│
├── launch/
│   └── robot_base.launch.py
├── package.xml
└── setup.py

重点是分清职责:

|---------------------|-----------------|
| 模块 | 职责 |
| drivers/ | 封装机器人底层能力 |
| nodes/ | ROS2 通信节点 |
| config/ | 参数和机器人类型配置 |
| launch/ | 一键启动 |
| driver_factory.py | 根据配置创建不同 Driver |

相关推荐
xiaofeichaichai2 小时前
前端安全 XSS 与 CSRF
前端·安全·xss
朗宇芯工控2 小时前
跨越欧亚 链接全球|朗宇芯亮相2026土耳其欧亚国际工业博览会
机器人·自动化·制造·工业·运动控制系统
JS菌2 小时前
Skills 动态加载系统:让 AI Agent 按需获取领域知识
前端·人工智能·后端
weedsfly2 小时前
Sass 代码复用完全指南:从变量到模块化
前端
张拭心2 小时前
Android 17 新特性:后台音频交互限制加强
android·前端
张拭心2 小时前
Android 17 新特性:ProfilingManager 新触发器
android·前端
黄敬峰2 小时前
从 XMLHttpRequest 到 JSON 模拟:打通前后端通信的任督二脉
javascript
weixin_471383032 小时前
Taro-03-页面生命周期
前端·javascript·taro