如果目标是既要多模态理解、又要实时与安全,把控制责任压在 UnifoLM-WLA-1.0 这类模型上通常不划算:模型擅长的是理解与给出动作建议,实时周期保证和越界拦截应当留在下游控制环。判断方向很简单——模型只输出结构化建议,控制环决定采不采纳、什么时候超时、越界时怎么刹车。要落地,先把模型侧能承诺的输出字段与更新节奏固定下来,再把超时分支、限位数值和兜底动作写成控制环里可配置、可记录的规则,最后用一次人为降频测试验证这些规则真的会触发。
更稳的切分是:模型负责多模态理解并输出动作建议,不直接下发控制指令;实时周期、超时判定和安全限位放在下游控制环。先核对模型侧能稳定给出哪些字段、以什么节奏更新,再把超时阈值、限位来源和兜底分支写进控制环配置。判断这套约定成不成立,看日志里能否复现超时与拦截分支,而不是看模型回答得多好。模型不可信或停更时,控制环保持最后安全状态或回到停止态,不接管模型职责。
列出模型侧实际能给出的输出字段与更新节奏
先确定上游能承诺什么,再谈下游怎么接。下面是一份通用字段清单,字段名可以按你的接入层改,但语义要稳定。凡是当前还没在接口、日志或文档里确认的项,先标成待核对,别当成既成事实往下写。
| 字段名 | 含义 | 是否连续给出 | 备注 |
|---|---|---|---|
| frame_id | 本次理解对应的输入帧/回合标识 | 每条建议都给 | 用于和控制环日志对齐,建议保留 |
| ts_model | 模型产生该建议的时间戳 | 每条都给 | 单位与时钟源需要和环境确认,待核对 |
| intent | 离散意图,如 pick / move / stop / hold | 事件驱动,非逐周期 | 枚举值需冻结,避免自由文本 |
| action_hint | 动作建议,如目标位姿或相对增量 | 视任务而定,待核对 | 只作建议,不等于可执行指令 |
| confidence | 建议的置信度或有效标志 | 与 action_hint 同批 | 阈值怎么用由控制环决定 |
| valid_until | 该建议的有效期约束 | 建议给出 | 未确认时由控制环兜底设定 |
更新节奏同样要写清:模型侧通常是事件驱动或按推理周期给建议,而不是每个控制周期都给一次。控制环不能假设“每拍必有新建议”,要按“最近一次有效建议 + 有效期”来处理。接入层可以先加一个最小校验骨架,把缺字段和建议直接挡在外面:
def validate_hint(h):
required = ["frame_id", "ts_model", "intent", "valid_until"]
missing = [k for k in required if h.get(k) is None]
if missing:
return None, "missing_fields:" + ",".join(missing)
if h["intent"] not in ALLOWED_INTENTS:
return None, "intent_not_allowed"
return h, "ok"
在下游控制环里定义超时与兜底分支
实时性责任要放在能保证实时的那一层。控制环每个周期检查“是否还有效建议”,失效就走兜底分支,而不是继续沿用旧建议硬跑。超时判定条件和对应动作建议成对写,并落到配置文件字段上,方便事后核对。下面的字段名是通用示例,替换成你的控制环实际使用的键名。
control_loop:
cycle_ms: <控制周期,按你的控制器实际能力填写>
hint_timeout_ms: <超时阈值,需结合环境确认>
on_timeout: hold # hold | stop | safe_home
hold_decay: none # 保持最后安全状态,不做外推
stale_frame_max: 1
- 超时判定条件:当前时刻与最近一次有效建议的时间差超过 hint_timeout_ms,或 frame_id 长时间未更新超过 stale_frame_max。
- 超时后执行的动作:通常先 hold(保持当前位置与姿态,不新增动作),确认无法恢复再转 stop;需要回安全位时用 safe_home,但回程路径要另行限速。
- 建议不要用“继续执行上一条建议”当默认兜底,那等于把实时责任又交回模型。
- 超时期间是否允许人工接管,需要结合现场作业规程确认,并在配置里显式开关。
把安全限位写在控制环而不是模型提示里
护栏不能依赖模型是否听话。限位是控制环的职责,模型给再漂亮的建议,越界也在控制环被截住。限位的数值来源建议优先取机械行程、关节软限位、工艺安全区这些确定性参数,来自设备手册、标定记录或控制器既有参数;具体取哪个值、留多少余量,需要结合环境和机构确认,不要凭模型输出反推。
safety_limits:
pos_min: <来自机构/标定>
pos_max: <来自机构/标定>
vel_max: <来自控制器参数>
clamp_enabled: true
log_key: cmd_clamped
拦截发生时要能在日志里认出来,建议统一关键字,方便 grep 复盘:cmd_clamped 表示建议被限位截断,limit_source 记录命中的是哪个限位,hint_rejected 表示建议因格式或意图不在白名单被丢弃,timeout_branch 表示走了超时分支。控制环执行的是截断后的安全值,而不是原样透传模型建议。
做一次人为降频测试并观察兜底是否触发
约定不验证就只是纸面规则。人为让上游建议变慢或变稀,看控制环是否按预期切到兜底分支。下面是可复现的测试记录表,填你自己的观测值,不预设任何延迟数字。
| 项 | 记录内容 |
|---|---|
| 降频方式 | 在接入层对建议下发加固定延时,或临时拉长推理调度间隔,待核对具体手段 |
| 变更位置 | 只改上游/接入层,不动控制环配置,保证对照干净 |
| 触发时间点 | 延时开始后、最近一次有效建议失效的那一刻 |
| 控制环实际分支 | 预期进入 on_timeout 指定分支,日志出现 timeout_branch 与 cmd_clamped 等关键字 |
| 恢复动作 | 恢复建议节奏后,控制环是否重新采纳新建议,还是需要人工确认复位 |
验证时按“配置改了什么、日志在哪个时刻出现哪个关键字、执行器实际停在哪”三件事对齐。如果超时后控制环仍在动,说明兜底分支没生效或限位没兜住,先修控制环再谈模型侧优化。恢复建议节奏后需要人工确认复位的,把这一步写进操作规程,别默认自动恢复。