实时系统
概述
机器人系统是一个多频率、多层级的实时控制系统。从 1kHz 的伺服控制到 10Hz 的感知处理,不同层级对实时性有截然不同的要求。本文涵盖控制频率层级、实时操作系统(RTOS)、ROS2 实时特性及通信总线。
实时 ≠ 快速
实时系统的核心是确定性(determinism)——保证在规定时间内完成任务,而非追求最快速度。一个 1ms 完成但偶尔 10ms 的系统,不如稳定 2ms 的系统可靠。
一、控制频率层级
1.1 多频率架构
机器人系统通常采用分层控制,各层频率不同:
| 层级 | 频率 | 周期 | 功能 | 实时要求 |
|---|---|---|---|---|
| 电流环 | 10-40 kHz | 25-100 μs | 电机电流控制 | 硬实时 |
| 伺服控制 | 1 kHz | 1 ms | 关节位置/速度/力矩控制 | 硬实时 |
| 笛卡尔控制 | 200-500 Hz | 2-5 ms | 末端轨迹插补、阻抗控制 | 硬实时 |
| 运动规划 | 10-100 Hz | 10-100 ms | 路径规划、避障 | 软实时 |
| 感知处理 | 5-30 Hz | 33-200 ms | 视觉、点云处理 | 软实时 |
| 任务规划 | 0.1-1 Hz | 1-10 s | 高层决策、VLA 推理 | 非实时 |
硬实时 vs 软实时
- 硬实时:超过截止时间即为系统失败(可能导致安全事故)
- 软实时:偶尔超时可接受,但会降低性能
- 非实时:对延迟不敏感,可排队处理
1.2 控制环路时序
时刻 t=0ms t=1ms t=2ms t=3ms
│ │ │
伺服控制: ─┤读传感器├─┤计算├─┤输出├─┤读传感器├─ ...
│ │
运动规划: ────┤ 规划计算 (10ms) ├──── ...
│
感知: ────┤ 图像处理 (100ms) ├─ ...
1.3 抖动(Jitter)要求
| 层级 | 允许抖动 | 说明 |
|---|---|---|
| 电流环 | < 1 μs | 由驱动器 FPGA 保证 |
| 伺服控制 | < 50 μs | 需要 RTOS |
| 笛卡尔控制 | < 200 μs | 需要 RTOS |
| 运动规划 | < 5 ms | 普通 Linux 可接受 |
| 感知处理 | < 30 ms | 普通 Linux 可接受 |
二、实时操作系统(RTOS)
2.1 PREEMPT_RT vs Xenomai
| 特性 | PREEMPT_RT | Xenomai (Cobalt) |
|---|---|---|
| 架构 | Linux 内核补丁 | 双内核(微内核 + Linux) |
| 最坏延迟 | 50-100 μs | 10-30 μs |
| 平均延迟 | 10-30 μs | 1-5 μs |
| Linux 兼容性 | 完全兼容 | 需要专用 API (POSIX skin) |
| 维护状态 | 正在合入主线 | 社区维护,逐渐式微 |
| 适用场景 | 1kHz 控制足够 | 需要 >1kHz 或极低抖动 |
| 驱动兼容 | 所有 Linux 驱动 | 需要适配或使用 RTDM |
| 开发难度 | 低(标准 Linux API) | 中(需学习 Xenomai API) |
| 典型用户 | Universal Robots, Franka | KUKA (早期), 部分 CNC |
选择建议
2024-2025 年的趋势是 PREEMPT_RT。随着其逐步合入 Linux 主线内核,生态优势越来越大。除非需要 <20μs 的极端实时性,否则推荐 PREEMPT_RT。
2.2 实时 Linux 配置要点
# 1. 安装 PREEMPT_RT 内核
sudo apt install linux-image-rt-amd64
# 2. CPU 隔离(isolcpus)— 防止普通进程干扰
# 在 GRUB 中添加:
GRUB_CMDLINE_LINUX="isolcpus=2,3 nohz_full=2,3 rcu_nocbs=2,3"
# 3. 设置实时优先级
sudo chrt -f 99 ./robot_controller
# 4. 锁定内存(防止页面交换)
mlockall(MCL_CURRENT | MCL_FUTURE);
# 5. 禁用频率调节
sudo cpupower frequency-set -g performance
关键配置项:
| 配置 | 作用 | 命令 |
|---|---|---|
isolcpus |
CPU 核心隔离 | 内核启动参数 |
mlockall |
内存锁定 | 程序内调用 |
sched_setscheduler |
实时调度策略 | SCHED_FIFO/SCHED_RR |
cpu affinity |
CPU 绑定 | taskset 或 pthread_setaffinity |
IRQ affinity |
中断绑核 | /proc/irq/*/smp_affinity |
2.3 延迟测试
使用 cyclictest 评估实时性能:
# 测试 10 分钟,在隔离核心上运行
sudo cyclictest -t1 -p99 -n -i1000 -l600000 -a2 -m
# 关注指标:
# Min: 最小延迟
# Avg: 平均延迟(目标 < 20μs)
# Max: 最大延迟(目标 < 100μs)
三、ROS2 实时特性
3.1 DDS QoS 配置
ROS2 基于 DDS(Data Distribution Service),通过 QoS 策略控制通信行为:
| QoS 策略 | 实时场景推荐 | 说明 |
|---|---|---|
| Reliability | BEST_EFFORT | 避免重传延迟 |
| Durability | VOLATILE | 不缓存历史数据 |
| History | KEEP_LAST(1) | 只保留最新消息 |
| Deadline | 设为控制周期 | 检测通信超时 |
| Liveliness | MANUAL_BY_TOPIC | 检测节点存活 |
from rclpy.qos import QoSProfile, ReliabilityPolicy, HistoryPolicy
rt_qos = QoSProfile(
reliability=ReliabilityPolicy.BEST_EFFORT,
history=HistoryPolicy.KEEP_LAST,
depth=1,
deadline=Duration(nanoseconds=1_000_000), # 1ms
)
# 用于关节状态发布
joint_pub = node.create_publisher(JointState, '/joint_states', rt_qos)
3.2 实时执行器(Real-time Executor)
// ROS2 实时执行器配置
#include <rclcpp/executors/static_single_threaded_executor.hpp>
// 使用静态单线程执行器(避免动态内存分配)
auto executor = std::make_shared<
rclcpp::executors::StaticSingleThreadedExecutor>();
// 设置实时优先级
struct sched_param param;
param.sched_priority = 90;
pthread_setschedparam(pthread_self(), SCHED_FIFO, ¶m);
// 锁定内存
mlockall(MCL_CURRENT | MCL_FUTURE);
executor->add_node(controller_node);
executor->spin();
3.3 ros2_control 框架
┌─────────────────────────────────────────┐
│ Controller Manager │
│ ┌──────────┐ ┌──────────┐ ┌────────┐ │
│ │ Position │ │ Velocity │ │ Force │ │
│ │Controller│ │Controller│ │Control │ │
│ └────┬─────┘ └────┬─────┘ └───┬────┘ │
│ │ │ │ │
│ ┌────┴──────────────┴────────────┴────┐ │
│ │ Hardware Interface Layer │ │
│ └────┬──────────────┬────────────┬────┘ │
└───────┼──────────────┼────────────┼──────┘
│ │ │
┌────┴────┐ ┌────┴────┐ ┌───┴─────┐
│EtherCAT │ │ CAN │ │ Serial │
│ Driver │ │ Driver │ │ Driver │
└─────────┘ └─────────┘ └─────────┘
四、通信总线
4.1 工业通信总线对比
| 总线 | 带宽 | 典型延迟 | 抖动 | 拓扑 | 典型应用 |
|---|---|---|---|---|---|
| EtherCAT | 100 Mbps / 1 Gbps | < 100 μs | < 1 μs | 菊花链/星型 | 高性能伺服 |
| PROFINET IRT | 100 Mbps | < 1 ms | < 1 μs | 星型 | Siemens 生态 |
| CAN/CANopen | 1 Mbps | 1-10 ms | 100 μs | 总线 | 移动机器人 |
| CAN FD | 8 Mbps | 0.5-5 ms | 50 μs | 总线 | 新一代关节 |
| SPI | 10-50 MHz | < 10 μs | < 1 μs | 主从 | 板内传感器 |
| RS-485/Modbus | 115.2 kbps | 5-50 ms | 1 ms | 总线 | 简单设备 |
| USB | 480 Mbps | 1-10 ms | 1 ms | 星型 | 相机、外设 |
4.2 EtherCAT 详解
EtherCAT(Ethernet for Control Automation Technology)是机器人领域最主流的实时总线:
工作原理:
- 主站发送以太网帧,从站在帧经过时"飞速"读写数据
- 帧只需遍历一次所有从站,极低延迟
- 典型:16 个伺服驱动器,周期 1ms,抖动 < 1μs
协议栈:
应用层: CoE (CANopen over EtherCAT) / SoE / EoE
传输层: EtherCAT 邮箱协议
数据链路层: EtherCAT 帧处理
物理层: 标准以太网 (100BASE-TX / 1000BASE-T)
开源主站:
| 主站 | 许可 | 特点 |
|---|---|---|
| IgH EtherCAT Master | GPL | Linux 内核模块,功能完整 |
| SOEM (Simple Open EtherCAT Master) | LGPL | 用户空间,跨平台 |
| EtherLab | GPL | 集成 MATLAB/Simulink |
4.3 CAN 总线
CAN(Controller Area Network)在移动机器人和低成本关节中广泛使用:
- 优势:成本低、布线简单、可靠性高(差分信号)
- 劣势:带宽有限(1 Mbps),不适合高频控制多轴
- 典型应用:Dynamixel 舵机(串行总线类似)、AGV 底盘
4.4 通信架构示例
┌──────────┐ EtherCAT (1kHz) ┌──────────┐
│ 主控制器 │◄──────────────────────►│ 关节驱动1 │
│ (x86 PC) │◄──────────────────────►│ 关节驱动2 │
│ │◄──────────────────────►│ ... │
│ │◄──────────────────────►│ 关节驱动7 │
│ │ └──────────┘
│ │ USB 3.0 (30Hz) ┌──────────┐
│ │◄───────────────────────│ RGB-D 相机│
│ │ └──────────┘
│ │ Ethernet (10Hz) ┌──────────┐
│ │◄───────────────────────│ LiDAR │
│ │ └──────────┘
│ │ SPI (10kHz) ┌──────────┐
│ │◄───────────────────────│ IMU │
└──────────┘ └──────────┘
五、实时性能优化
5.1 代码层面
- 避免动态内存分配:预分配所有缓冲区
- 避免锁竞争:使用无锁队列(lock-free queue)
- 避免系统调用:减少上下文切换
- 避免 I/O 阻塞:使用异步 I/O
- 避免异常处理:C++ 中禁用 exceptions(
-fno-exceptions)
5.2 系统层面
- 内核旁路:使用用户空间网络栈(DPDK)
- NUMA 感知:在正确的 NUMA 节点分配内存
- 大页内存:减少 TLB 缺失
- 中断合并:减少中断处理开销
5.3 典型延迟预算
以 1kHz 控制循环为例(1ms 周期):
| 环节 | 分配时间 | 说明 |
|---|---|---|
| 传感器读取 | 50 μs | EtherCAT 过程数据 |
| 状态估计 | 50 μs | 滤波、前向运动学 |
| 控制计算 | 200 μs | 逆动力学、力矩计算 |
| 安全检查 | 50 μs | 限位、碰撞检测 |
| 指令输出 | 50 μs | EtherCAT 写入 |
| 余量 | 600 μs | 应对最坏情况 |
| 总计 | 1000 μs |
60% 余量原则
实时系统中,正常工况下 CPU 使用率应不超过 40%,留出充足余量应对最坏情况。
延伸阅读
- 计算平台 - 机器人计算硬件选型
- EtherCAT Technology Group: https://www.ethercat.org/
- ROS2 Real-time Working Group: https://github.com/ros-realtime
- Jan Altenberg. "PREEMPT_RT: Basics and Practical Tips." Embedded Linux Conference, 2020.