
SUN 的标题里有一组很少见并且值得琢磨的词Persistent Programs持久程序和 Control-to-Learning-to-Real从控制到学习再到真实部署。我第一次读到它们时脑海里的第一反应不是某个新网络结构而是一连串经常发生在机器人项目里的低效重复仿真器里跑好的策略换到真实机械臂上需要改一遍换第二台机器人又得再调一遍过两个月回看实验记录你已经说不清手里的权重文件对应的是哪条任务指令、哪组仿真参数、哪个控制器版本。标题把这个痛点摆到了中心我们要构建的不是一个更聪明的模型而是一类能“活过”仿真、训练和真机部署全流程的持久策略程序。这篇文章不打算替论文下结论而是想从工程实践视角把这个方向背后的设计逻辑、落地路径和应用边界拆开来看。1. 为什么机器人策略需要一个“持久程序”而不是一堆会遗忘的权重技术圈经常用“策略”指代一个可决策的模块。但在真实工程项目里一个可用的机器人策略从来不只是一份权重文件。在“控制-学习-真实”的链条上它可能包含一个基于模型的控制器、一个由强化学习训练的网络、一组真实环境校准参数、一段上线保护逻辑和一堆记录失败样本的日志。问题是这些内容通常分散在不同人的代码仓库里靠人工记忆来拼凑。1.1 一次成功不代表流程已经可复用我刚接触机器人项目时前辈常说一句话机器人实验不是“跑通一次”就算结束能重复三次才叫真的通。这个判断放在今天依然有效。仿真环境里第一次拿到满意的成功率后接下来的问题往往一大堆这个结果依赖哪个随机种子、哪个版本的仿真器、哪组奖励权重换到真实机器人上是直接用原网络还是先做一轮随机化增强如果真实环境里失败应该改网络、改控制器还是改任务描述实验记录里是否保留了重建环境需要的所有脚本和参数这些问题如果没有答案那这次成功本质上是一次不可再生成果。纯学术实验也许还能容忍但在需要持续迭代的产品化场景里这种不可复现会直接拖垮项目进度。持久程序要解决的正是让“一次成功”变成“长期可复用的流程资产”。1.2 “持久”不是模型不换而是结构和经验能跨任务保留很多第一次看到 Persistent Programs 的人会问是不是一个不要反复训练的超级大模型我的理解不是。更合理的思路是把策略拆成一个具有“持久性骨架”的程序骨架里包含任务定义、控制原语、触发条件、模型调用入口和修正记录。你可以随时更新其中某个模块但不用每次从零重写整套决策逻辑。你可以把它类比成一份菜谱菜谱描述“红烧肉”时不需要把每一步火候都写进做菜人的神经系统里。它会固定大流程选料、焯水、炒糖色、炖煮、收汁。具体执行时不同灶台火力不一样那就只修改对应步骤的参数。随着经验增多你会在菜谱边上记下“这次换老抽颜色太深下次少加一点”。菜谱本身还是那份菜谱但它越用越贴近真实环境。把这种思路搬回机器人领域“持久程序”至少应具备三个特征可读程序里的任务名、前置条件和安全约束是人类语言可理解的。可复用同一个底层控制器或技能模块能被多条任务调用不需要复制一份代码。可迭代真机测试发现的问题能被记录成修正项而不是停留在某位工程师的聊天记录里。这三个特征正好指向一个被低估的问题我们缺的不是更优秀的单点算法而是能让算法持续进入项目基线、再被后续任务复用的结构化系统。1.3 把策略分成四层更容易理解持久化的位置为了落地我习惯把一个“持久策略程序”拆成四层来看。这是一种方便理解的通用划分不一定要和论文里的模块名称对齐语言接口层负责把用户指令解析为结构化任务比如“把红色杯子放到托盘 A”。任务路由层根据任务描述选择对应的控制原语、神经网络权重或混合策略。执行层和仿真器/机器人通信执行运动、力控、规划等底层动作。记忆层保存每次执行的输入、输出、日志、失败样例并把可复用的修正回写到路由层。这种分层在软件工程里很常见但机器人策略里往往缺失。缺少之后模型的失败很难定性到底是指令没听懂还是选择了错误的原语还是控制参数错了持久性的起点就是先把策略的调用链变得可观察然后让每一层都能独立更新而不是把所有故障都归罪于“算法不行”。2. 拆开标题“控制-学习-真实”到底在打通什么标题把 Control-to-Learning-to-Real 三个概念连在一起按正常阅读习惯可以理解成一条从“控制策略”走到“学习策略”再到“真实部署策略”的链路。这既是一种学术描述也是一种工程状态诊断目前我们通常不是没有这三种策略而是它们各自为政。2.1 三类策略原本长在不同“语言系统”里经典控制策略的输入输出通常非常物理化比如目标位置、速度、力矩依赖状态估计和动力学模型解释起来明确但设计工作量大处理非结构化环境的能力弱。学习策略通常用神经网络把传感器观测映射成动作适合从数据里挖掘难以手工建模的规律但可解释性弱面对分布外情况容易表现不稳定。真实部署要处理的是通信延时、电机噪声、视觉标定误差、安全停机、人机交互这些仿真之外的问题。过去项目里这三者往往由不同角色完成控制工程师写控制器算法工程师训模型系统集成工程师负责在真机上把两边粘起来。每个人只了解自己那一段出了问题要跨岗位对日志。而且控制器里的参数、训练脚本里的 reward、真机调试时的保护逻辑经常是三种不同格式很难互相验证。2.2 自然语言为什么值得当三者的共同接口如果要让三类策略被同一个持久程序管理就需要一种连通它们的接口。用任务 ID 也能做但扩展性和可读性很差用配置文件也可以但迁移到新任务时不够直观。自然语言的最大优势是它已经是人、语言模型和任务描述之间相对通用的协议。举个例子。一个任务如果被描述成“把红色杯子推到托盘 A”可以映射到三类逻辑控制端把“托盘 A”的位置解析成轨迹终点把“推”变成目标方向和力约束。学习端把整句作为条件变量输入策略网络让模型学习在对应语义下生成动作。真实端实测失败时工程师可以依据“红色杯子”和“托盘 A”去检查视觉识别、坐标变换和碰撞保护而不是查一段难以理解的向量编码。如果三个阶段都围绕同一句话展开调试链路就会短很多。它还能让控制先验、学习数据和真实修正共享同一个命名空间这是把工作流沉淀成系统的重要前提。注意语言接地的难点不在“能识别这句话”而在把语言符号稳定关联到实际物理对象、坐标、控制器和模型路径上。这也是为什么 persistent program 里要做的不是一句简单字幕而是一整套解析与映射机制。2.3 一条可能的执行路径先控制生成再学习迁移最后真实修正这个方向真正重要的不是同时训练一个大模型而是设计一条反复指向真实目标的流水线。按常见理解可以抽象为三步不是论文结论而是一种通用落地思路。第一步用控制逻辑生成高质量的初始经验。对于一个基本明确的任务先用基于模型的控制器或运动规划器在仿真中完成它任务描述和控制器参数同时写入持久程序。第二步让学习策略在控制策略的“指导”下扩展泛化能力。它可以用控制器生成的数据做模仿学习也可以用强化学习继续探索控制器做不到的边界。这里的关键不是让学习策略取代控制器而是让学习处在可控范围内输出异常时还能回到控制原语。第三步在真实机器人上完成闭环修正。跑真机之前持久程序里已经保存好了理论参数和期望行为真机上出现偏差后把偏差记录下来在下一次更新控制器或训练数据前先判断是视觉问题、标定问题、控制参数问题还是学习策略问题。以往很多 sim-to-real 工作只关心一个网络从仿真搬到真实而这个标题真正有意思的地方是它试图把整个“控制-学习-真实”链条统一在一个程序化框架里。单看某一个模块也许并不新颖但把语言、记忆、控制和策略绑定在一起就可能形成新的方法论差异。3. 语言引导不只是“输入一句话”而是给策略安装索引与记忆很多人听到 language-grounded policy第一反应是给神经网络加一个 text encoder。这种理解只拿到了表层。在持久程序框架里语言引导承担着三个更实际的作用任务选择、故障解释、经验沉淀。3.1 语言在选择器之外的三种角色任务选择器当用户说“打开抽屉”程序先查询语言索引得到对应的一套原语、权重和校验规则。这个作用最直观也是当前多任务模型常用做法。故障解释器机器人执行失败后不能只凭一句“loss 没降”来定位问题。语言描述可以帮助人类快速回顾它是否真的碰到了抽屉把手它在接近过程是不是太快它是不是把柜门当成了抽屉语言在这里不是训练标签而是复盘用的共同线索。经验沉淀器真实环境里一次有效的调参如果把“接近速度降低 0.02m/s”附在“打开抽屉”这个任务词条下下次再跑类似任务就能直接继承。没有这种语义锚点修改过的参数只会散落在不同脚本里项目一转手就全部丢失。简单说自然语言为策略提供了外部可见的锚点。模型权重本身不便于人机交流但语言描述像文件夹名把底层实现和上层意图连起来。3.2 持久程序里应该存什么先列一张清单基于工程经验一套语言引导的 persistent program至少需要记录四类内容任务描述与约束自然语言、机器人动作范围、安全限制。控制原语和参数使用哪个控制器、刚度阻尼、规划算法、速度上限。学习策略入口权重路径、输入输出接口、适用观察空间、归一化参数。部署修正与失败案例每次真机实验的时间和结论哪些参数被改过为什么改。与其说它是“程序”不如说是一套可运行的语义化配置系统外加执行引擎。你可以在 YAML 文件里描述任务在控制代码中实现行为在日志库中积累修正记录。关键是这些内容必须能被统一读取而不是散落在实验记录文档里。这里给出一个通用的高层伪代码只是为了帮助理解这类概念并不是 SUN 项目本身的代码# 通用示例按语言任务索引 persistent program registry PersistentProgramRegistry() registry.register( taskopen_drawer, language_aliases[拉开抽屉, open the drawer], control_primitivecartesian_impedance, learned_policyopen_drawer_v2.pt ) def open_drawer(robot, context): controller load_controller( context.task, paramscontext.params ) # 后续执行、回退、记录统一走框架 executor.execute(controller)真实工程实现不一定写成装饰器形式。不过这种结构化方式能让人一眼看出某个任务怎么解析、由谁执行、用哪个权重、有没有后置检查。这正是普通权重文件做不到的。3.3 一套最小系统至少要包含四个模块如果我要做一个实验原型来验证这个方向会先搭四个模块而不是先调模型语言解析模块把自然语言映射成任务名与参数。初期可以先用一套有限模板别急着上大模型先把链路跑通。任务注册表维护任务名、控制原语、权重路径和参数版本。执行引擎连接仿真器或真机加载对应策略并顺序执行。持久存储保存任务配置、回放数据、修改记录。这个存储可以是 Git 仓库加数据库不需要一开始就设计得很复杂。这里的顺序很关键。很多人会先纠结用什么语言模型或强化学习算法但我建议先做任务注册表和存储。因为只有先把“任务索引 → 策略文件 → 实验记录”的链路打通后面加入模型才有观测点。最小验证范围也要控制住先选 3 个差异足够大的任务比如推、拉、抓取各一个。不要一开始就建 100 个任务语义覆盖和原语覆盖不是等比例的。语言能描述 100 个任务不代表底层有 100 套可靠策略。如果一上来就追求用通用语言大模型生成全部动作你很可能陷入一种幻觉指令都能听懂但实际动作不可靠。先让每条语言指令能稳定触发一个已验证的原语再考虑让模型生成新行为这样安全得多。4. 想复现这类方案先把工程底座准备好在缺少原始项目代码前我们无法给出精确的安装命令。但如果目标是复现类似思路你需要准备的不是某个算法而是一套能被多层策略共享的项目底座。下面这节是工程层面的建议需要结合你所在团队已有的机器人平台来确认。4.1 需要对齐的几类接口即使项目同时使用仿真和真实环境也需要定义统一的接口抽象。否则持久程序写完了却发现仿真器、真机和策略网络的数据格式完全不一致。层次常见能力需要的接口/依赖任务描述自然语言指令意图解析、别名映射、参数抽取控制层产生期望动作机器人驱动、运动规划、状态估计学习层神经网络推理预训练权重、观测归一化、推理加速部署层真实环境执行安全急停、日志回放、通信总线具体验证时可再从下面这些问题自查仿真和真机的动作单位是否一致是弧度还是角度是关节空间还是笛卡尔空间语言指令里的“左边”参考系是摄像头坐标、机械臂基座坐标还是用户视角日志能否记录任务 ID、策略版本、执行参数和时间戳程序重启后能不能从持久存储恢复当前注册表与修正记录这些问题看起来基础但恰恰是决定方案能不能长期迭代的关键。4.2 任务从单点到多点的三个周期这里给出一个可复现的三段式推进策略。搭建类似系统时我习惯用“先跑通、再注册、再更新”的顺序每一步都设一个明确验收标准。第一步跑通单任务闭环。选择一个容易复现的控制任务用确定性的控制原语完成它。不要引入学习模型和语言大模型先把“控制参数、任务描述、仿真状态”写进持久程序。第二步注册多任务入口。保留同一个控制框架加入第二个、第三个任务让它们的差异通过参数配置表达而不是复制代码。写一个简单的语言映射表确认不同指令能进到不同任务。第三步加入学习策略与真机修正。在某个原语覆盖不了的任务上训练一个学习策略并将它的入口注册进任务路由层。真机出现偏差后把修正以“规则参数”的形式写回对应任务条目不要只改临时代码。这个顺序能确保持久程序先有“型”再有“智能”。如果反过来一开始就把模型和仿真随机性拉满很难判断问题究竟出在哪个环节。4.3 我见过最容易翻车的四个地方第一个翻车点是把“持久”理解成“把所有记录存到一个数据库”。实际还需要版本管理一条任务指令对应哪个控制器版本、哪份权重、哪个真机标定参数。数据库只解决存储不解决一致性问题。第二个翻车点是语言系统离控制细节太远。解析模型只输出任务名没有输出控制参数结果同样是“推”在粗糙桌面和光滑桌面需要的力可能完全不同。语言应帮助程序理解上下文而不只是选一个代号。第三个翻车点是忽略模拟到真实的观测差异。网络在仿真里看到的是干净位置信息真机上却是带噪声的 RGBD 和关节力矩。persistent program 必须记录观测空间的差异并为同一任务准备多套观测适配器。第四个翻车点是不做失败回退。学习策略一旦在真实环境里表现异常应当有一套控制级保护动作接管并把异常数据记录下来。很多事故不是模型不聪明而是缺少人类可撤销的兜底链路。这个兜底逻辑本身应当写进持久程序而不是只停留在硬件急停按钮上。4.4 排查路径先分层定位再决定修哪里因为持久程序链路较长遇到问题不能急着改模型。建议按照下面顺序排查先看现象是语言无响应指令解析错误动作震荡还是真机和仿真偏差很大再看语言层输入原句是否被错误扩写有没有把任务 A 误触发到任务 B再看任务路由任务名能否在注册表里查到有没有记录策略版本和控制参数再看控制层目标位置、速度限制、力控模式是否与真实任务一致再看学习策略输入通道是否匹配现实传感器权重路径和归一化参数是否过期再看持久存储最近一次修改有没有日志当前程序加载的是哪个版本这个顺序能避免“问题明明出在控制参数上却反复迁移学习模型”的低效循环。排查结论应当记录进持久程序的记忆层否则下一次同类问题还要从头看一遍。5. 一个看起来“方向正确但难落地”的问题怎么判断自己值不值得追前面讲了很多设计和工程坑。最后一个问题也很现实这类方向适合所有人吗我认为不。它的价值建立在长期迭代和跨阶段开发基础上如果只是想要一个能跑 demo 的模型不一定要引入 persistent program 的复杂度。5.1 适合谁不适合谁为了降低选择成本可以直接给一个参考表场景建议原因做多任务长期部署的机器人团队值得投入语言注册表可以成为团队的共享资产想快速复现一篇论文、跑出指标先别做重型框架最小记录和配置其实就够用一次性科研实验不建议持久程序需要持续的维护成本真实场景与人交互、安全要求高必须考虑需要可读、可回退、可审计的逻辑纯做离线数据集训练不需要真机持久层主要瓶颈不在策略部署流程判断标准可以简化成一句你是否需要同一个策略逻辑被不同任务、不同环境或不同团队成员反复复用需要就值得深入不需要就等需要时再引入。5.2 长期价值在于把策略变成“团队资产”而不是个人能力从长期看这样的方向真正改变的是机器人开发的组织方式。传统做法里有经验的工程师往往把调试经验存在脑子里一旦人员变动项目就失忆了。language-grounded persistent program 则鼓励每个决策、参数和失败都沉淀为“可被语言检索的工程资产”。它不是要把经验全部自动化而是要让经验有载体。未来一个新成员接手项目时可以先看