引言
实验室里能跑的机器人和现场能用的机器人之间,隔着三件事:实时性、故障恢复、功能安全。实时性决定控制回路是否稳定;故障恢复决定单点失效是否导致整机停机;功能安全决定人机协作时是否会造成伤害,以及在合规层面能否交付。
实时性常被误解为「快」。真正的定义是「可预测」:任务必须在截止时间前完成,超时的概率要有界。一个平均 100 µs、偶尔 10 ms 的回路,比一个稳定 500 µs 的回路糟糕得多。Linux 的默认调度器在负载波动时会给出毫秒级的抖动,这在 1 kHz 的控制回路上足以引起可听见的关节噪声。
功能安全是另一个维度的要求,且往往在项目末期才被提起,此时架构已定,改造成本极高。ISO 10218-1/-2 规定了工业机器人的安全要求,ISO/TS 15066 补充了协作机器人的功率与力限制。这些标准的核心思想是「安全功能必须独立于主控制系统」,即安全回路不能依赖跑着 ROS2 的那颗 CPU。
本文按「实时内核 → 线程模型 → 现场总线 → 故障恢复 → 功能安全标准 → 安全功能 → 协作模式 → 部署运维 → 事故分析」的顺序展开,给出可执行的配置、测量方法与合规要点。
目录
- 实时内核与延迟测量
- 线程模型、优先级与 CPU 隔离
- 现场总线:EtherCAT、CAN 与以太网
- 看门狗、故障检测与恢复
- 功能安全标准:ISO 10218 与 TS 15066
- 安全功能:STO、SS1、SLS 与安全 PLC
- 协作机器人的四种安全模式
- 部署、OTA 与车队管理
- 监控、日志与事故分析
1. 实时内核与延迟测量
Linux 的实时能力有三个层次,选择取决于控制周期。
层次 1:标准内核(CONFIG_PREEMPT_NONE / VOLUNTARY)
最坏延迟:几十毫秒(内核不可抢占区)
适用:感知、规划、非实时任务
层次 2:CONFIG_PREEMPT(低延迟桌面)
最坏延迟:几毫秒
适用:软实时,100 Hz 以下的控制
层次 3:CONFIG_PREEMPT_RT(实时补丁,5.15 起逐步并入主线)
最坏延迟:50~200 µs(x86 良好配置下)
适用:硬实时,1 kHz 控制回路
# 测量最坏延迟的标准工具:cyclictest
# -t1 单线程,-p80 优先级 80,-i1000 周期 1ms,-m 锁内存
sudo cyclictest -t1 -p80 -n -i1000 -l100000 -m -c0
# 输出示例(PREEMPT_RT,x86 i7):
# T: 0 ( 1234) P:80 I:1000 C: 100000 Min: 8 Act: 12 Avg: 11 Max: 47
# T: 0 ( 1234) P:80 I:1000 C: 100000 Min: 9 Act: 14 Avg: 12 Max: 142
# Max 在 50~150 µs 之间是可接受的;超过 1 ms 需要排查
# 找出延迟尖峰的来源
sudo trace-cmd record -p function_graph -l 'irq*' -l 'sched*' sleep 10
sudo trace-cmd report | grep -A5 'latency'
延迟尖峰的常见来源按出现频率排序:SMI(系统管理中断,BIOS 层面,需要在 BIOS 关闭)、CPU 频率调节(改用 performance 调频策略)、内存回收(mlockall 加预留内存)、以及网卡中断(用 IRQ affinity 绑到非实时核)。
# 基础调优清单
sudo cpupower frequency-set -g performance # 关闭调频
echo 0 | sudo tee /proc/sys/kernel/sched_rt_runtime_us # 关闭 RT 限流(谨慎)
sudo tuned-adm profile realtime # 或手工配置
# BIOS 中关闭:C-States、SMI、Hyper-Threading(视情况)
sched_rt_runtime_us 设为 -1(即 0 表示不限制?实际是设为 950000 或 -1 关闭限流)需要谨慎:关闭后一个死循环的实时线程会锁死系统。更稳妥的做法是保留限流但给足额度(如 950000,即 95%)。
2. 线程模型、优先级与 CPU 隔离
线程的优先级分配决定了「谁能在截止时间前完成」。
推荐优先级分配(数值越大优先级越高,1~99 为实时):
90:安全监控线程(急停响应、安全状态检查)
85:现场总线通信线程(EtherCAT 周期任务)
80:控制回路线程(1 kHz 伺服循环)
70:状态估计线程(1 kHz IMU 融合)
50:传感器驱动线程(雷达、相机)
10:规划线程(非实时,但需要及时响应)
0:日志、可视化、遥测(普通调度)
原则:
1. 安全 > 通信 > 控制 > 估计 > 感知 > 规划 > 工具
2. 同优先级线程不要过多(调度开销)
3. 实时线程之间不要共享需要加锁的数据(用[无锁数据结构](/cpp-lockfree-data-structures/))
# CPU 隔离:把实时线程绑到专用核
# 内核参数:isolcpus=2,3 nohz_full=2,3 rcu_nocbs=2,3
# 然后用 taskset 或 cgroup 绑定
# 用 cset 创建隔离的 CPU 集
sudo cset shield --cpu 2,3 --kthread on
sudo cset shield --exec -- chrt -f 80 ./control_node
# 中断亲和性:把网卡中断绑到非实时核
echo 1 | sudo tee /proc/irq/$(cat /proc/interrupts | grep eth0 | cut -d: -f1 | tr -d ' ')/smp_affinity
# 验证线程的实际调度策略与优先级
chrt -p $(pgrep -f control_node)
ps -eLo pid,tid,class,rtprio,comm | grep control
内存隔离同样重要。实时线程必须锁定内存页,并避免在运行时分配。
// 在实时线程启动时锁内存
#include <sys/mman.h>
if (mlockall(MCL_CURRENT | MCL_FUTURE) != 0) {
perror("mlockall failed"); // 需要 CAP_IPC_LOCK 或足够的 memlock 限制
}
// /etc/security/limits.conf:
// robot_user hard memlock unlimited
// robot_user soft memlock unlimited
3. 现场总线:EtherCAT、CAN 与以太网
执行器与传感器的通信方式直接决定控制周期的下限。
EtherCAT(工业伺服首选):
原理:从站硬件转发以太网帧,主站一个周期内遍历所有从站
周期:125 µs ~ 1 ms,抖动 < 1 µs
拓扑:线型、环型(环型支持冗余)
实现:IgH EtherCAT Master(内核模块)、SOEM(用户态)
典型:1 kHz 控制 6 轴伺服,周期时间约 250 µs
CAN / CANopen(低成本、中低速):
速率:经典 CAN 1 Mbps,CAN FD 5~8 Mbps
周期:1 ms 可行,但抖动大于 EtherCAT
优势:成本极低、抗干扰好、线束简单
适用:移动底盘、简单执行器、电池管理
工业以太网(EtherNet/IP、PROFINET):
周期:1~10 ms
适用:与工厂 PLC 对接、非紧实时
普通以太网 + 自研协议:
周期:受协议栈影响,用户态 UDP 约 100~500 µs 抖动
适用:非紧实时、成本敏感的定制方案
// SOEM 的 EtherCAT 主站循环骨架(用户态,无内核模块)
ec_init("eth0");
ec_config_init(FALSE); // 初始化并枚举从站
ec_config_map(&IOmap); // 映射过程数据
ec_configdc(); // 配置分布式时钟
ec_statecheck(0, EC_STATE_OPERATIONAL, 50000);
while (running) {
ec_send_processdata();
ec_receive_processdata(EC_TIMEOUTRET);
// 此处更新 IOmap 中的指令与状态
updateCommands(IOmap);
readFeedback(IOmap);
osal_usleep(1000); // 1 kHz
}
分布式时钟(DC)是 EtherCAT 的关键特性:所有从站共享同一个时钟,采样与输出的时间偏差小于 1 µs。没有 DC 时,多轴之间的同步误差可能达到几十微秒,在插补运动中表现为轨迹误差。
4. 看门狗、故障检测与恢复
故障检测的目标是「在危害发生前停下来」,恢复的目标是「停之后能安全地回来」。
三层看门狗:
1. 硬件看门狗(SoC 内置)
由内核喂狗,系统级死机时复位
超时通常 1~10 秒
2. 软件看门狗(进程级)
每个关键线程定期更新心跳计数器
监控线程检查所有计数器,任一停止则触发安全状态
超时按周期数设定:控制线程 10 个周期(10 ms)
3. 通信看门狗
检查关键话题/总线数据的时效
超过 3 倍标称周期未更新则判定失效
// 心跳监控的简单实现
struct Watchdog {
std::atomic<uint64_t> counter{0};
std::atomic<uint64_t> timeout_ms{100};
std::atomic<uint64_t> last_update_ms{0};
void kick() { last_update_ms = nowMs(); counter++; }
bool alive() const { return nowMs() - last_update_ms < timeout_ms; }
};
// 监控线程(优先级 90,高于被监控者)
while (running) {
for (auto & [name, wd] : watchdogs_) {
if (!wd.alive()) {
RCLCPP_FATAL(logger, "watchdog timeout: %s", name.c_str());
triggerSafeStop(); // 立即进入安全状态
break;
}
}
std::this_thread::sleep_for(10ms);
}
故障恢复要分级,不能「一停就要人工复位」。合理的分级是:瞬时故障(通信丢包)自动重试;可恢复故障(传感器超时)降级运行并告警;不可恢复故障(硬件错误)进入安全停止并要求人工介入。分级策略必须写进状态机并在测试中验证。
5. 功能安全标准:ISO 10218 与 TS 15066
功能安全的核心是「安全功能独立且可靠」,用性能等级(PL)或安全完整性等级(SIL)量化。
ISO 10218-1:机器人本体(制造商负责)
规定机器人本体的安全要求、安全功能、验证方法
2025 版将协作要求并入正文(原 TS 15066 的内容)
ISO 10218-2:机器人系统与集成(集成商负责)
规定应用集成的安全要求:风险评估、安全防护、验证
ISO/TS 15066:协作机器人(技术规范,2025 版已并入 10218)
规定四种协作操作模式的功率与力限制
给出人体各部位的准静态接触力与压强限值表
性能等级(PL,ISO 13849-1):
PL a~e,e 最高
由架构类别(Cat. B~4)、MTTFd、DC、CCF 决定
机器人安全功能通常要求 PL d(Category 3)
Category 3 = 双通道 + 诊断覆盖率足够
安全完整性等级(SIL,IEC 62061):
SIL 1~3,与 PL 有对应关系(SIL 2 ≈ PL d)
ISO/TS 15066 的力限值摘录(准静态接触,单点接触):
部位 力限值(N) 压强限值(N/cm²)
额头 130 130
面部 65 110
胸部 140 140
手臂 150 160
手/手指 140 190
大腿 220 220
小腿 130 210
准静态 = 接触时间 > 0.5 s;瞬态(< 0.5 s)的限值约为 2 倍
这些限值决定了协作机器人的「功率与力限制」模式的参数。设计时要做实际测量验证:用带力传感器的测量装置在最高速度下模拟碰撞,确认峰值力与压强低于对应部位的限值。测量必须在最不利的条件下做(最硬的材料、最尖锐的接触点、最高速度)。
6. 安全功能:STO、SS1、SLS 与安全 PLC
安全功能由驱动器的安全转矩关断(STO)等硬件功能与安全 PLC 共同实现。
常见安全功能(IEC 61800-5-2):
STO(Safe Torque Off):
切断驱动器的输出级供电,电机无力矩
最快的停止方式但不可控(自由停车)
典型响应时间 < 10 ms
SS1(Safe Stop 1):
先按可控方式减速,到达零速后触发 STO
需要安全编码器反馈速度
适用:需要可控停止的场合(避免自由停车撞到东西)
SS2(Safe Stop 2):
减速后保持位置监控(不是 STO)
适用:需要保持位置的安全状态
SLS(Safely Limited Speed):
限制最大速度,超限则触发停止
适用:协作模式下的人员接近时降速
SLP(Safely Limited Position):
限制运动范围,超限则停止
适用:限制机械臂不进入危险区域
SDI(Safe Direction):
只允许单一方向运动
安全功能的实现层次有两种:安全 PLC + 安全继电器(传统工业方案,成本高但认证成熟)与驱动内置安全功能 + 安全 I/O(现代方案,如伺服驱动器的 STO 输入配合双通道安全继电器)。协作机器人通常内置这些安全功能,通过安全 I/O 接口(双通道)接收外部急停与安全信号。
关键设计原则:安全回路绝不能依赖运行 ROS2 的 CPU。安全停止应由硬件链路直接触发(急停按钮 → 安全继电器 → 驱动器 STO),ROS2 收到信号只是「知道发生了」并做状态记录。如果安全依赖软件,那么软件崩溃时就没有安全。
7. 协作机器人的四种安全模式
ISO 10218 定义了四种协作操作模式,选择取决于应用与风险评估。
1. 安全 rated monitored stop(安全监控停止)
人在工作区内时机器人停止,人离开后自动恢复
实现最简单,节拍损失最大
适用:人偶尔进入的场景
2. Hand guiding(手动引导)
操作员用引导装置(通常是末端的手柄)直接拖动机器人
机器人处于力控/零重力模式
安全要求:引导装置上必须有急停,速度受限
适用:示教、精密定位
3. Speed and separation monitoring(速度与分离监控)
实时监测人与机器人的距离,距离近则降速,过近则停止
需要安全 rated 的人员检测(安全激光扫描仪、安全视觉)
节拍损失小,实现复杂度高
关键:最小保护距离 = 停止距离 + 人的接近距离 + 余量
4. Power and force limiting(功率与力限制)
机器人本体设计为碰撞力受限,不需要外部防护
需要按 TS 15066 验证各部位的力与压强
节拍损失最小,但对机器人与工件都有约束(工件不能太尖锐)
适用:真正的共享工作空间
最小保护距离的计算是速度与分离监控的核心:
S = S_h + S_r + S_s + C + Z_d + Z_r
S_h:人的接近距离(按 1.6 m/s 行走速度 × 停止时间)
S_r:机器人的停止距离(含响应延迟)
S_s:机器人停止后的位移
C:侵入距离(人体部位可伸入的距离,通常取 500 mm)
Z_d:位置测量的不确定度
Z_r:机器人的位置重复性
典型取值:总距离 1.0~1.5 m(取决于速度与停止时间)
8. 部署、OTA 与车队管理
多台机器人的运维需要一套基础设施,单机思维在现场会崩溃。
部署清单:
1. 系统镜像化
用 Docker 或只读 rootfs(如 RAUC、Mender 做 A/B 分区)
只读 rootfs 能避免现场误操作与文件系统损坏
2. 配置与代码分离
参数放配置中心或本地 YAML,随版本管理
敏感信息(密钥、标定值)加密存储
3. 版本可追溯
每个部署都有明确的版本号(含 git commit 与构建时间)
能回答「这台机器人跑的是哪个版本」
OTA 升级要点(与 [OTA 固件升级](/iot-ota-firmware-update/)的思路一致,但机器人的镜像更大、失败代价更高):
1. 分阶段:先 1 台 → 5% → 25% → 全量
2. 可回滚:A/B 分区或镜像版本保留,回滚时间 < 5 分钟
3. 校验:升级后自检(传感器、通信、控制回路)通过才标记成功
4. 断点续传:现场网络差,必须支持断点续传与完整性校验
5. 升级窗口:避开生产时段,且有现场人员或远程可介入
车队管理:
状态上报:位置、电量、任务、健康度、版本
远程诊断:日志拉取、参数查看、远程重启
批量操作:批量升级、批量配置、批量任务下发
告警聚合:按机器人与故障类型聚合,避免告警风暴
9. 监控、日志与事故分析
事故分析的目标是「下次不再发生」,因此数据必须可追溯。
必须记录的数据(按时间对齐):
1. 全量 rosbag(关键话题),至少保留最近 7 天
2. 安全事件日志(急停、安全停止、看门狗触发)——永久保留
3. 系统指标(CPU、内存、温度、网络)——保留 30 天
4. 版本与配置快照(每次升级与配置变更时记录)
事故分析流程:
1. 确定时间点,拉取对应时段的 rosbag
2. 回放,复现问题(注意:回放不能驱动机器人)
3. 对齐安全事件日志与系统指标,定位因果链
4. 归因到具体模块,写进问题库
5. 加监控指标,防止同类问题再次发生
# 事故时段的数据拉取
ros2 bag record -s mcap -a -o incident_$(date +%s)
# 用 ros2 bag 的切片功能只取事故前后 60 秒
ros2 bag convert -i full.mcap -o slice.mcap \
--start-time 1696500000 --end-time 1696500060
监控指标的分级:致命(安全事件、控制回路超时)立即告警并可能触发停机;严重(规划失败率突增、传感器丢帧)告警但不影响运行;提示(温度偏高、磁盘将满)记录并定期巡检。告警必须分级且有抑制规则,否则现场会对告警脱敏,真正的问题被淹没。
权衡取舍
| 决策 | 选 A | 选 B |
|---|---|---|
| 内核 | 标准内核:感知规划、软实时 | PREEMPT_RT:1 kHz 硬实时 |
| 总线 | EtherCAT:多轴同步、微秒级 | CAN:成本低、周期 1 ms 够用 |
| 安全实现 | 安全 PLC:认证成熟、成本高 | 驱动器内置 STO:成本低、需验证 |
| 协作模式 | 安全监控停止:实现简单 | 功率力限制:节拍好、验证成本高 |
| 系统镜像 | 可写:调试方便 | 只读 A/B:现场可靠 |
| 告警 | 全量上报:信息全 | 分级抑制:可操作 |
核心原则:安全回路必须硬件独立,实时回路必须软件可预测。这两条不是优化项而是底线,任何为了成本或进度而妥协的方案都会在事故或认证阶段付出更大代价。
常见坑清单
- 用标准内核跑 1 kHz 控制,抖动到毫秒级——必须用 PREEMPT_RT 并用
cyclictest验证。 - 未关闭 SMI 与 C-States,延迟尖峰偶发到毫秒——BIOS 层面关闭并验证。
- 实时线程未
mlockall,内存回收导致周期性停顿——锁内存并预留独立内存。 - 实时线程之间用互斥锁共享数据,优先级反转——改用无锁队列或优先级继承互斥量。
sched_rt_runtime_us设为不限流,死循环线程锁死系统——保留限流或严格审查代码。- EtherCAT 未配置分布式时钟,多轴同步误差几十微秒——启用 DC 并验证同步。
- 安全停止依赖 ROS2 软件实现,软件崩溃时无安全——安全回路必须硬件独立。
- 协作机器人未按 TS 15066 实测力限值,认证失败——按最不利条件测量各部位。
- 最小保护距离按理论值设定,未考虑停止延迟与测量不确定度——按公式完整计算并留余量。
- OTA 无回滚机制,升级失败只能人工现场恢复——A/B 分区或保留可回滚镜像。
小结
机器人部署的三根支柱是实时性、故障恢复与功能安全。实时性靠 PREEMPT_RT、CPU 隔离、无锁通信与实测验证;故障恢复靠分层看门狗与分级恢复策略;功能安全靠硬件独立的安全回路与按标准的验证。三者的共同要求是「可预测」而非「快」或「聪明」。
下一步建议回顾机器人软件栈全景 ,把本文的实时与安全要求对应到分层模型的具体位置;ROS2 架构 中的 QoS 与执行器配置是实时性的软件侧基础;传感器融合与状态估计 的失效模式是故障恢复策略的输入。如果要做协作机器人,机器人视觉与抓取 讲清了人员检测与抓取安全的相关约束。
最后一句:安全与实时性是设计出来的,不是测试出来的。在架构阶段就把安全回路与实时边界划清楚,比在项目末期打补丁便宜一个数量级。
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。