北境的雪化了三轮,边关的狼烟就起了三次。
第一次,镇北将军带两万铁骑出关,回来不足五千。第二次,朝廷换了新帅,铸新甲、配新弓,兵马比上次雄壮三倍,仍在落鹰峡被截断粮道,十万石军粮烧在山道里。第三次更惨,帅旗没立起来,前锋就溃了。消息传回京城那日,金銮殿上一片死寂。老将军们互相瞪着眼,谁都清楚:再这么打下去,开春之前,雁门关就要易主。
这时,司礼监报上来一个人的名字——说南方来了个年轻人,不讲刀兵,不求粮饷,只要一间静室、一方三尺木盘。
年轻人姓偃,没人知道他的名字。他父亲是江南做皮影的匠人,他从小在幕布后面长大。别的孩子背四书五经,他背的是一箱箱提线。进殿那天,满朝文武都等着看一个江湖艺人的笑话。
他把木盘放到御案前,一言不发,摆了三天三夜。
第四天早晨,请皇帝看盘。
那方木盘里,有城,有河,有山,有兵。山是细灰堆的,河是刻出来的浅槽,城是木头刻的。而兵——三百个拇指高的木人,铜丝铰着关节,丝线从盘底牵出,汇在他的十指之间。他左手一挑,前锋变阵;右手一收,弓箭手齐射;小指一勾,侧翼骑兵已从山后包抄过去。殿外恰好起风,烛火摇曳,满朝文武分明看见,盘上的旌旗也跟着歪了歪,像真被风吹动。
一场决战在盘上打完,从清晨到日暮。收兵时,内侍数了三遍:三百个木人,没有一个倒下。
皇帝起身问他:这仗,是怎么打赢的?
年轻人说:臣不懂兵法。臣只是把每一步都记下来——风从哪边来,马跑几步该停,箭射出第几声该落地,全记进簿册。真兵照册操练,一步不差,就能百战百胜。
皇帝当即下旨:禁军照盘操练。
那个冬天,京郊大营里,三万禁军在冻硬的土地上,一遍遍走着木盘上的步点。都尉每天抱着簿册喊号子,谁快半步就罚,谁慢半拍就打。年轻人得了赏赐,却搬去营房住,夜里仍在盘前推演:晴天、雪天、逆风、顺风、泥地、石板路……每一种,他都推出必胜的走法,记满新的簿册。
只有一个人反对。是当年兵败落鹰峡的尉迟老将军。某天清晨,他拦住年轻人,问:偃先生,你的盘上,有没有一样东西是会累的?
年轻人一怔:盘上的兵,怎么会累?
老人说:会累的兵,才打得赢不会累的仗。说罢第二天就告老还乡,出城时没带走一副铠甲。
开春,匈奴骑兵过了河。
禁军出关,照的是簿册里"泥地行军"那一册——每一步该踩多深、马该跑多快,写得清清楚楚。可真实的泥地不认字:一脚踩下去,拔出来时靴子留在了泥里;再踩下去,脚底一滑,膝盖磕在冻土上。铁甲磨着肩膀,跑出三里,血从甲叶底下渗出来,结成冰碴。弓弦本是上调好的,被倒春寒的潮气一浸,夜里就松了,箭射出去软绵绵地落在半路。最要命的是传令兵——盘上从来没有什么回声,真实的峡谷里喊声撞来撞去,该变的阵没有变,该包的抄没有包。
三万禁军,溃在离落鹰峡不到二十里的野地里。
朝廷要杀年轻人。皇帝没杀,只把他逐出京城。出城那天,百姓朝他扔菜叶。他怀里只抱着那方木盘,从城门走到官道,走了一路,把散开的提线一根一根接好。
他在城外三十里的破庙住下,把木盘供在山神像下,三天没动,没怎么吃东西。
第三天夜里,庙外聚满了看热闹的百姓——他们听说这个骗子终于要疯了。
年轻人那天夜里做的事,后来这一带的人讲了几十年。
他先往盘里撒一层粗沙,把平整的地面弄得坑坑洼洼;又提水浇上,让灰山塌了半边,让刻好的河道糊成泥浆;他在庙门口架起风箱,对着盘呼呼地吹,吹得木人东倒西歪;他拿出凿子,把三百个木人的腿一条一条削短,有长有短,没有两条是对齐的;弓弦也重新上过,紧的紧,松的松,没有一张一样。最后,他端着一盏油灯,把积了几屋子、写满"必胜走法"的簿册,一页一页,全烧了。
百姓在庙外摇头:唯一完美的东西,也被他自己毁了。
可他没毁。火光里,他坐下来,重新提笔。他把三百个木人放进残破的盘里,从溃败的那一步重跑:泥地、逆风、松弓、长短不一的腿、糊掉的河道。风每一次的方向都不同,沙每一回的厚薄都不同,泥的黏稠每遍也不同。每一种"不完美",他都跑上几百遍。簿册烧了一摞,又记了一摞。
有个小乞丐夜里翻进庙里,躲在梁上看。后来他跟人说,那三个月,庙里的灯没熄过,盘上的哒哒声响了整整一个春天。奇怪的是,盘上的兵开始摔倒了——从前一个都不倒,现在时不时就栽进泥里。可每栽倒一次,年轻人就让它重来,再栽,再来。到后来,有的木人摔进泥里,竟能自己挣起来,挣起来,还能把弓端平。
第二年开春,匈奴又来了。
禁军照旧出关。簿册上写的还是那些走法,可队伍里每个人都摔过跤、都穿着磨破的甲、都拉过松垮的弓。匈奴骑兵在峡谷里卷起烟尘,逆风扑面,箭射出去就偏——可队形只是晃了晃,没有散。前排一个兵脚底打滑,半跪进泥里,后排的兵踏着他的背脊踩过去,阵线像水一样绕开那个缺口,又合拢。号角被回声撞得破碎,各营都尉却像早猜到会这样,各自为战,乱中有序。
那一仗没有完胜。史官的记录只有八个字:“互有胜负,边关得守。”
守住了,就够了。
庆功宴上,老皇帝问:你的沙盘已经不完美了,为什么反而能打仗了?
年轻人沉默了很久,说了一句让满朝沉默的话:
“臣的敌人,从来不是匈奴。是那座完美的沙盘。”
后来,这个国家的每一支军队开拔前,将领都要带一方"破沙盘"——沙是粗的,弓是松的,兵的长短是不齐的。有徒弟请示师父:师父,我能不能做一方最完美的沙盘?
师父总会拦住他,说:先学会把它弄坏。
这个故事在讲什么
讲的是仿真到现实的鸿沟(Sim-to-Real Gap,又称 Reality Gap):机器人在近乎完美的物理仿真里训练到接近满分,一旦部署到真实世界,性能就大幅退化。
它的"研究生含量"在于:这不是某个库的用法问题,而是一个横跨机器人学、强化学习、系统辨识的开放难题——你要同时理解接触建模误差、执行器动力学、传感器噪声、材料柔性,还要会用量化手段去弥合它。而"所有二开公司都会碰到"的原因很直白:今天做人形机器人二次开发,无论底层运控还是上层具身智能,几乎都靠仿真(Isaac Gym / MuJoCo / Gazebo)来迭代策略,于是每家都会经历同一个时刻——仿真里 reward 拉满,真机上连站都站不稳。
扩写版比初版多埋了几层对应关系,正好把"弥合鸿沟"的完整方法论语义覆盖到:
| 寓言元素 | 对应的技术概念 |
|---|---|
| 完美的三尺木盘 | 理想化的物理仿真环境 |
| 铜丝铰接、丝线牵引的木人 | 机器人的关节与执行器 |
| 写满"必胜走法"的簿册 | 在仿真中训练得到的策略(policy) |
| 阅兵式上零伤亡 | 仿真中 reward 收敛、成功率 100% |
| 尉迟将军之问:"盘上有没有一样东西是会累的?" | 理想模型里没有执行器饱和、能耗与扭矩极限 |
| 铁甲磨破肩膀、血结成冰碴 | 关节摩擦、背隙等未建模的接触损耗 |
| 泥地拔不出脚 | 足地接触建模不准,软硬地面动力学差异 |
| 潮气浸松弓弦 | 材料柔性、形变未被仿真捕捉 |
| 峡谷回声干扰传令 | 传感器噪声与观测延迟 |
| 三里跑完喘不上气 | 电机扭矩/功率饱和,超出理想执行器假设 |
| 烧掉簿册、撒沙泼水、风箱吹、削短木腿、弓弦松紧不一 | 域随机化(Domain Randomization):随机化地形、摩擦、惯量、延迟等物理参数 |
| 同一套走法在千百种"不完美"里反复重练 | 在随机化环境中大规模采样、重新训练策略 |
| 木人摔倒后能自己挣起来、把弓端平 | 训练出的恢复策略(recovery policy),泛化能力 |
| "互有胜负,边关得守" | 鲁棒 ≠ 完美:sim-to-real 的目标不是复刻满分,而是允许失误下的稳定 |
| 徒弟想造最完美的沙盘,师父说"先学会把它弄坏" | sim-to-real 的核心信条:保真度不是目的,鲁棒性才是 |
顺带一提,老将军那句"会累的兵,才打得赢不会累的仗",其实是整篇里我最喜欢的设计——它对应的是仿真里"理想执行器"这个最隐蔽、也最致命的假设:真实电机有力矩上限、会发热、会掉精度,而仿真里它是一根不知疲倦的轴。