飞机起飞异常地铁信号故障工厂机械臂伤人如何用STPA模型做系统安全评估提前堵住危险漏洞
你有没有注意到一个反直觉的现象:很多事故报告里写的是“设备正常运行”“传感器数据未超限”“软件无报错”,但危险还是发生了。飞机起飞阶段抬头角度突然偏大、地铁信号机明明显示绿灯却放行了不该放行的列车、工厂机械臂在操作员还没撤离时猛地缩回——这些都不是某个螺丝松了或某块芯片烧了,而是系统里的“控制关系”出了毛病。
传统安全分析喜欢问:“哪个零件会坏?”但现代系统越来越复杂,零件本身已经够可靠了,真正脆弱的是它们怎么被组织在一起、怎么传递指令、怎么互相牵制。STPA(System-Theoretic Process Analysis,系统理论过程分析)就是专门解决这个问题的。它不盯着故障树往下挖,而是往上走:看谁在控制谁,控制动作对不对,约束够不够硬。
先把“谁管谁”画清楚:控制结构是安全分析的底图
做STPA的第一步,不是翻事故报告,也不是列风险清单,而是画一张控制结构图。你可以把它想象成画一张“指挥链”:谁发号施令,谁执行动作,信息从哪里传回来。
以地铁信号系统为例:
- 控制器:中央调度系统、区域信号机、车载ATP
- 被控对象:道岔、轨道电路、列车本身
- 反馈通道:列车位置报告、道岔状态、轨道占用信息
- 约束:联锁逻辑、限速曲线、调度规程
飞机起飞也是类似的链路:飞行员/自动驾驶系统 → 飞控计算机 → 舵面/发动机 → 飞机姿态 → 传感器回传数据 → 再次调整。
工厂机械臂更典型:PLC或安全控制器 → 伺服驱动器 → 机械臂本体 → 外部传感器(光栅、 RFID、视觉) → 反馈给控制器。
很多人在这一步就踩坑:只画“硬件框图”,忘了画人和环境的角色。比如操作员按下了急停按钮,这个动作算不算控制输入?车间地面湿滑导致光栅误触发,算不算环境约束变化?STPA要求你把所有能影响控制动作的要素都放进闭环里,哪怕它只是一个保安巡场时随手关上的门。
揪出“不安全控制动作”:UCA才是事故的直接推手
STPA的核心概念叫 Unsafe Control Action(UCA,不安全控制动作)。说白了,就是“该给的没给、不该给的给了、给的太多/太少、给的时机不对”。
不用记术语,你把它套到日常场景里就明白了。比如煮粥:火开太大会溢锅,火开太小糊底,该关火时没关,不该关火时反而关了。系统安全也一样。
把UCA拆成四类,逐一对应你的案例:
| UCA类型 | 飞机起飞 | 地铁信号 | 工厂机械臂 |
|---|---|---|---|
| 给太多/太快 | 抬轮指令超出飞行包线,机头过早昂起 | 信号放行速度高于线路允许值 | 机械臂回缩速度超过安全阈值 |
| 给太少/太慢 | 推力不足导致离地距离超标 | 道岔未及时转换,列车被迫紧急制动 | 安全区域未锁定时仍允许低速运行 |
| 该给时没给 | 未发出风切变警告或改出指令 | 轨道占用时未给出红灯/停车约束 | 人员进入危险区未触发停机 |
| 不该给时给了 | 地面模式下意外激活爬升逻辑 | 检修模式未解除却按正常模式发车 | 维修工在臂下时发出自动运行指令 |
注意,UCA不是“故障”,它是控制行为本身的偏差。一个传感器完好、一个继电器正常、一段代码没报错,组合起来照样可能发出错误的控制动作。这也是为什么很多事故复盘时发现“每个环节都合规”,但系统整体就是不安全。
追问因果链:别只写“操作员失误”,要写“系统为什么允许他失误”
找到UCA之后,STPA会逼你往下追一层:这个不安全动作是怎么发生的?
传统做法容易写成“操作员未按规程操作”或“设备老化”。STPA不允许这么轻飘飘地结案。它要求你把因果场景拆成五类根源:
- 约束缺失或模糊:系统没有明确规定“什么情况下不能发这个指令”。比如地铁信号系统的联锁表里,有一条边界条件没覆盖“轨道电路瞬时丢失+道岔位置未知”的组合,结果信号机给出了隐晦的“允许通行”状态。
- 反馈延迟或失真:控制器拿到的信息是错的或慢的。工厂机械臂的光栅被纸箱挡住一部分,控制器以为区域清空,实际还有人的手臂在行程内。
- 控制器自身误判:算法逻辑本身有漏洞。自动驾驶在起飞阶段的风切变检测阈值设得太高,导致它“看不见”真实风险。
- 多控制器冲突:两个系统同时发号施令,且优先级没定义清楚。比如人工模式与自动模式切换时,飞控计算机和飞行员输入发生叠加。
- 环境或人因变化:温度骤变、电磁干扰、夜班疲劳、培训不到位,让原本合理的约束失效。
举个例子。地铁信号故障那次,如果只写“继电器接触不良”,下次换同型号继电器照样可能出事。但用STPA追下去会发现:真正的问题是系统把“继电器状态正常”当成了充分条件,却没有把“轨道占用确认”作为互锁前提。约束层级错位,才是根因。
把安全写进系统:从“事后补救”变成“事前卡死”
分析到这一步,目标已经很明确:针对每个UCA,设计足够硬的约束,让它不可能被执行,或者执行时立刻被拦截。
约束不是越多越好,而是要分三层:
1. 物理/逻辑硬约束(做不到)
这类约束不依赖人的判断,也不依赖软件提示,而是从结构上杜绝可能性。
IF 人员区域传感器 == 激活
THEN 机械臂运动权限 = 锁定
速度上限 = 0
报警 = 持续蜂鸣 + HMI红色闪烁
这不是伪代码炫技,而是很多安全控制器(SIL2/SIL3等级)里真实存在的逻辑骨架。关键点是:约束必须可验证、可测试、可审计。不能写“系统应确保安全”,这种话在工程评审里会被直接打回。
2. 程序/管理软约束(知道怎么做)
操作规程、挂牌上锁(LOTO)、双人确认、交接班检查。软约束的好处是灵活,坏处是依赖执行质量。所以STPA会要求你标明:这条约束的失效后果是什么?有没有硬约束兜底?
3. 动态自适应约束(看情况调整)
成熟系统不会一刀切。比如飞机起飞阶段,风切变警告阈值会根据空速、迎角、垂直加速度实时调整;地铁在夜间低峰期可以放宽部分联锁,但必须把“施工模式”单独隔离,防止白天恢复运营时残留状态污染正常逻辑。
这里有个很实用的原则:每一条安全约束,都要能反向追溯到至少一个UCA;每一个UCA,都要有至少一种约束来拦截。 如果查到最后发现某个UCA“靠培训提醒就行”,那大概率是约束设计偷懒了。
和FMEA、FTA比,STPA到底强在哪
很多人第一次接触安全分析,习惯先上FMEA(失效模式与影响分析)或FTA(故障树分析)。它们当然有用,尤其是面对单一组件可靠性评估时。但它们有个共同盲区:假设系统出事是因为部件失效。
现实是,现代系统里单个部件失效率已经压得很低,事故往往来自:
- 多个正常部件的异常交互
- 软件状态机跳转逻辑遗漏
- 人机接口信息过载或误导
- 维护后参数未复位
- 边界工况未被纳入设计约束
STPA不排斥FMEA/FTA,它是把它们放在更大的框架里。你可以用FMEA查零件,用FTA追具体事件,但用STPA先看清整个控制架构的约束缺口。顺序很重要:先画控制结构,再找UCA,再追因果,最后才去细化某个模块的故障概率。
落地时的几个“老手才知道”的细节
- 别把控制结构图画成静态框图。加上时间维度:启动阶段、巡航阶段、着陆阶段、检修阶段,每个阶段的控制器和约束可能完全不同。飞机起飞异常之所以危险,就是因为起飞阶段留给控制器的反应窗口极短,任何约束延迟都会被放大。
- 人不是系统的“噪声”,人是控制器的一部分。操作员、调度员、维修工都会做出控制动作。把他们纳入闭环,而不是写成“人为因素待优化”。
- UCA要量化到可测试。不要写“避免过早抬轮”,要写“在V1前,俯仰指令不得超过+2.5°/s,除非收到明确的风切变警告”。这样测试用例才能直接对应。
- 保留“安全边际”的文档痕迹。监管审查时,他们最关心的不是你是不是用了STPA,而是你能不能证明:每条约束都有来源、每个UCA都有拦截路径、每次变更都重新跑过控制结构图。
安全不是靠运气堆出来的,也不是靠事故报告倒逼出来的。把飞机、地铁、机械臂这些看似不同的系统放在一起看,你会发现它们共享同一套底层逻辑:危险从来不是孤立发生的,它藏在指令传递的缝隙里、藏在反馈失真的盲区里、藏在“大家都觉得没问题”的默认假设里。
STPA的价值,就是让你提前把这些缝隙照亮。你不需要等零件坏掉才发现问题,只需要问对三个问题:谁在控制谁?什么动作不该出现?什么约束能保证它不出现?把这三个问题答实了,漏洞自然就堵上了。