具身智能实战:让机器鸭爬梯子——双策略交接与接触力控制的深度解读

教一只四足机器人爬梯子,比教它走路难在哪里?本文从 Datawhale 具身智能组队学习的第 6 课出发,用大白话拆解"梯面攀爬"任务中的两个核心工程难点:双策略交接 和接触力控制。

一、这节课到底在讲什么?

1.1 任务目标

一句话总结:训练一只叫 MicroDuck 的四足机器人,从地面沿着带横档的斜梯爬上去,翻到桌面上,然后站稳。

整个过程分两个阶段:

复制代码
阶段1(攀爬):用脚一级一级踩上横档,像攀岩一样往上爬
阶段2(起身):翻到桌面后,从趴着的状态站起来,保持平衡

先来看最终效果------下面是 MicroDuck 从地面到桌面的完整攀爬序列(12 帧抽帧):

完整攀爬序列(12 帧)

从上到下、从左到右,展示了 MicroDuck 从地面到桌面的完整过程:

  • 第 1-3 帧:鸭子从地面接近梯子,开始用前脚踩上第一根横档
  • 第 4-6 帧:交替踩横档,身体逐渐升高,重心前移
  • 第 7-9 帧:接近梯子顶部,身体开始翻向桌面
  • 第 10 帧:前脚已经踩到桌面边缘,后脚还在梯子上
  • 第 11 帧:身体翻到桌面上,但还在趴着(这是 climber → getup 的交接点)
  • 第 12 帧:getup 策略接管,鸭子站起来,稳稳站在桌面上

关键观察:第 10-11 帧之间发生了策略交接。注意鸭子的姿态变化------从"攀爬姿态"(身体前倾)变成"趴着"(身体贴桌面),然后 getup 把它拉起来。

看完效果,你可能好奇:这是怎么做到的?接下来我们一步步拆解。

1.2 为什么这个任务有挑战性?

和之前学过的平地走路、篮球平衡、高跷行走相比,爬梯子有三个本质区别:

维度 平地走路 爬梯子
支撑面 连续地面,踩哪都行 离散横档,必须踩准(间距约 5cm)
力的方向 主要靠垂直支撑力 需要摩擦力防止滑下去,需要法向力防止掉下去
失败后果 摔倒,重新走 从梯子上掉下来,可能卡住或翻车

通俗比喻:平地走路像在操场上走,爬梯子像在攀岩墙上爬------每一步都要精确控制脚的位置和力度。

1.3 整体流程

复制代码
环境配置 → 加载攀爬策略(climber) → 接触力仿真 → 
策略交接(handoff) → 加载起身策略(getup) → 站稳验证 → ONNX导出 → BPU部署

Notebook 共 8 个步骤,从模型检查到板端部署,形成一条完整的可复用流程。


二、需要理解的名词概念

在深入技术细节之前,先统一"语言":

概念 大白话解释 在本文中的角色
策略(Policy) AI 的"大脑",输入当前状态(61个数字),输出动作(14个关节角度) 攀爬和起身各有一个策略
ONNX 一种通用的模型文件格式,让 AI 模型能在不同平台运行 把训练好的策略打包成可部署格式
HBM "Hardware Binary Model"------给 RDK 开发板用的编译后模型 相当于把 Python 编译成机器码
BPU "Brain Processing Unit"------RDK 开发板上的 AI 专用芯片 专门跑神经网络推理的小芯片
MuJoCo 物理仿真引擎,模拟重力、碰撞、摩擦等物理效果 充当机器人的"身体"和"世界"
接触力(Contact Force) 脚和梯子横档之间的力 法向力=支撑力,切向力=摩擦力
策略交接(Handoff) climber 爬到顶后,自动切换到 getup 的过程 本文核心机制之一
闭环(In-the-loop) 每个控制周期:读观测→AI推理→执行动作→物理更新→下一周期 真实反馈循环
61维观测 AI 每次"看到"的信息:身体姿态、速度、关节角度等 61 个数字 策略的输入
14维动作 AI 每次"做出"的决策:14 个关节的目标角度 策略的输出
MDP "Markov Decision Process"------马尔可夫决策过程,强化学习的数学框架 定义状态、动作、奖励
奖励函数(Reward) 告诉 AI "什么行为是好的"的评分机制 本文核心机制之一
课程训练(Curriculum) 先学简单的,再学难的,循序渐进 从有支撑板到无支撑板

三、攀爬和起身,这两个动作分别是如何学会的?

3.1 不是"一个策略包打天下"

很多人会想:为什么不训练一个策略,让它既能爬梯子又能站起来?

答案是:两个任务的物理状态差异太大。

  • 攀爬时:鸭子身体前倾,重心在梯子方向,脚在横档上交替踩踏
  • 起身时:鸭子身体从趴着变成直立,重心从低到高,脚从悬空到踩实桌面

如果让一个策略同时学这两件事,它会在两种状态之间"精神分裂"------既学不会爬,也学不会站。

工程上的做法:拆成两个独立策略,各学各的,然后在合适的时机交接。

3.2 攀爬策略(climber)是怎么训练的?

数据来源 :社区开源项目 HannesVonEssen/microduck-climb,提供了完整的训练代码、checkpoint 和 ONNX 模型。

训练框架:基于 PPO(Proximal Policy Optimization)算法,在 MuJoCo 仿真环境中训练。

关键参数:

参数 值 说明
观测维度 61 身体姿态、速度、关节角度等
动作维度 14 14 个可控关节的目标角度
控制频率 50 Hz 每秒做 50 次决策
仿真频率 200 Hz 每秒推进 200 步物理仿真
并行环境数 64 64 个仿真环境同时训练
训练迭代 4000+ 每轮采样 + 策略优化

训练过程:

复制代码
初始化策略(随机动作)
    ↓
在 64 个并行环境中同时试错
    ↓
每步计算奖励(爬得越高越好、脚踩得越准越好)
    ↓
PPO 算法更新策略参数
    ↓
重复 4000+ 轮,直到策略稳定
    ↓
导出 ONNX 模型

3.3 起身策略(getup)是怎么训练的?

训练起点不同 :getup 不是从零开始学的,而是用预训练 checkpoint 续训。

复制代码
预训练 checkpoint(已经学会基本站立)
    ↓
在"翻到桌面后趴着"的初始状态下续训
    ↓
奖励函数:身体直立 + 双脚踩实 + 不滑动
    ↓
训练到稳定起身
    ↓
导出 ONNX 模型

为什么用预训练? 因为从零学"从趴着到站立"太难了------初始状态离目标状态太远,随机探索几乎不可能碰巧学会。用预训练 checkpoint 相当于"站在巨人的肩膀上",只需要微调就能学会。

3.4 两个策略的接口完全一致

虽然功能不同,但 climber 和 getup 的输入输出完全一样:

复制代码
输入:obs[1, 61]  →  61 维观测向量
输出:action[1, 14]  →  14 维关节目标角度

这意味着切换策略时,不需要改变仿真环境的接口------只需要把推理的模型从 climber.onnx 换成 getup.onnx 就行。


四、接触力控制是如何做到的?

4.1 核心原则:不直接控制力,而是引导 AI 学会正确的接触方式

这是很多人容易误解的地方。代码里没有一行代码直接设置"脚和横档之间应该有多大的力"。

取而代之的是:通过奖励函数引导 AI 自己学会正确的接触方式。

4.2 五个奖励函数,五个"老师"

老师 1:路径进度奖励(ladder_path_progress)
python 复制代码
# 伪代码
progress = 0.75 × 水平进度 + 0.25 × 垂直进度
reward = 当前progress - 上次progress

大白话:鸭子每往前/往上移动一点,就给奖励。75% 看水平进度,25% 看垂直进度。

效果:鼓励鸭子沿着梯子方向前进,而不是原地打转或往回走。

老师 2:高度进度奖励(ladder_height_progress)
python 复制代码
# 伪代码
height_progress = (当前高度 - 起始高度) / (桌面高度 - 起始高度)
reward = 当前progress - 上次progress

大白话:专门奖励"往上爬"。鸭子每升高一点,就给奖励。

效果:和路径进度配合,确保鸭子既往前又往上,而不是只往前不往上(比如沿着地面跑)。

老师 3:脚部对齐奖励(ladder_foot_alignment)------接触控制的核心

这是最复杂也最重要的一个奖励函数:

python 复制代码
# 伪代码
# 1. 计算每只脚到最近横档的距离
rung_error = sqrt((沿梯子方向偏差)² + (垂直方向偏差)²)

# 2. 计算三个维度的得分
score = exp(-(横向偏差/0.045)²)      # 脚不能偏出梯子两侧(4.5cm以内)
      × exp(-(左右偏差/梯宽)²)        # 脚不能超出梯子宽度
      × exp(-(rung_error/0.065)²)     # 脚必须靠近某个横档(6.5cm以内)

# 3. 加一个"门控":只有进入梯子区域才生效
score *= gate  # 梯子入口前=0,梯子上=1,桌面后=0

大白话:

这个函数在告诉 AI:"你的脚应该踩在横档上"。怎么判断?

  • 横向偏差:脚不能偏出梯子两侧(左右 4.5cm 以内)
  • 纵向偏差:脚必须靠近某个横档(6.5cm 以内)
  • 门控机制:只有鸭子真正进入梯子区域,这个奖励才生效

效果:AI 通过几万次试错,最终学会"把脚放到横档上"。一旦脚放对了,MuJoCo 物理引擎自然算出正确的接触力。

老师 4:脚部滑动惩罚(foot_slip)
python 复制代码
cfg.rewards["foot_slip"].weight = -0.2

大白话:脚在接触面上滑动,扣分。

效果:鼓励 AI 学会"踩稳",而不是"脚底打滑"。

老师 5:脚部离地惩罚(foot_clearance)
python 复制代码
cfg.rewards["foot_clearance"].weight = -0.5

大白话:脚抬太高,扣分。

效果:鼓励 AI 学会"贴着横档走",而不是"高抬腿"浪费能量。

4.3 物理引擎的角色

MuJoCo 负责:

  • 计算脚和横档之间的真实碰撞(法向力、摩擦力)
  • 判断是否滑落(摩擦力不够时自然滑落)
  • 判断是否卡住(脚卡在两根横档之间)

AI 负责:

  • 输出 14 个关节的目标角度
  • 通过奖励函数引导,学会"把脚放到正确位置"

两者配合:

复制代码
AI 输出动作 → MuJoCo 算物理 → 反馈新的状态 → AI 再输出
     ↑                                              ↓
     └──────────────── 闭环循环 ────────────────────┘

这就是"闭环"------AI 不是在一开始就知道所有答案,而是在和物理世界的持续互动中,不断调整自己的行为。

4.4 梯子几何的真实建模

V2 版本按参考视频中的空间关系重做了梯子几何:

组件 描述 碰撞属性
两根斜梁 矩形截面,沿斜面布置 真实碰撞几何
14 根横档 密集排列,间距约 5cm 真实碰撞几何
顶部平台(桌面) 四条腿支撑 真实碰撞几何
梯脚落地木块 防止梯子看起来像浮在空中 真实碰撞几何
桌后方的椅子 视觉装饰,不影响物理 不参与碰撞

关键设计 :所有梯梁、横档、桌面和梯脚都是真实 MuJoCo 碰撞几何,不是"看起来像"的视觉模型。这意味着 AI 在训练中感受到的物理反馈,和真实世界中是一样的。


五、双策略交接是如何做到的?

5.1 为什么需要交接?

想象你爬梯子到桌面后:

  • climber(攀爬策略):擅长一级一级往上踩,但它的"世界观"里只有梯子,不知道到了桌面该怎么办
  • getup(起身策略):擅长从趴着变成站着,但它不会爬梯子

所以必须两个策略接力:climber 爬到顶 → 切换 → getup 把鸭子拉起来站稳。

5.2 交接的触发条件

代码里有一个叫 foot_desktop_eligible 的函数,它判断"是否可以交棒了"。条件有三个,必须同时满足:

复制代码
条件1:脚碰到了桌面
条件2:身体已经在桌面范围内
条件3:持续了至少 1 个控制步(约 0.02 秒)
条件1:脚碰到了桌面

用 MuJoCo 的物理引擎检测:鸭子的左脚或右脚,是否和桌面(tread_31/desktop)发生了真实碰撞(距离 ≤ 0)。

不是"差不多到了",是物理引擎真的算出脚和桌面接触了。

条件2:身体已经在桌面范围内

鸭子的身体重心,必须在桌面的矩形范围内(前后左右都算),而且高度要超过 0.66(说明已经翻上来了,不是还在梯子上)。

条件3:持续了至少 1 个控制步

不能是"一瞬间碰到就切换",必须稳定接触至少 1 步,防止误触发。

5.3 切换的完整流程

关键代码在 OfficialPair.step() 里,用大白话翻译:

python 复制代码
# 步骤1:记忆机制
# 把"上一步做了什么动作"塞回输入的 34-48 槽位
observation[34:48] = self.raw
# 这样策略知道"我刚才在干嘛",不会突然懵掉

# 步骤2:状态机切换
self.recovering = self.recovering or eligible
# 一旦 eligible=true,就永久进入 getup 模式
# 不会"切过去又切回来"

# 步骤3:推理
if self.recovering:
    self.raw = self.getup.infer(observation)   # 用 getup 策略
else:
    self.raw = self.climber.infer(observation) # 用 climber 策略

# 步骤4:柔顺过渡
if self.recovering:
    # getup 输出不是直接用的,而是和"上一步的动作"做加权平均
    self.executed = alpha × self.raw + (1-alpha) × self.executed
    # 腿用 alpha=0.7,头颈用 alpha=0.5
    # 这样过渡是平滑的,不会"咔"一下突然换动作

四个关键设计:

设计 作用 如果不做会怎样
记忆机制 让策略知道上一步做了什么 切换后策略"失忆",动作不连贯
单向切换 一旦切换永不回头 可能在两个策略之间反复横跳
柔顺过渡 动作平滑过渡 突然换动作,鸭子可能摔倒
不同 alpha 值 腿 0.7,头颈 0.5 头颈过渡太慢影响视觉,腿过渡太快影响平衡

5.4 怎么验证交接成功?

不是"触发了切换"就算成功。代码里还有一个 desktop_standing 函数,要求:

条件 阈值 大白话
双脚都在桌面上 all(feet) 两只脚都踩稳了
身体在桌面范围内 inside_desktop 没掉下去
重力方向朝下 gravity_z < -0.82 身体是直立的,不是歪的
线速度 < 0.25 linear_speed 没在滑动
角速度 < 2.5 angular_speed 没在旋转
稳定持续 ≥ 2 秒 stable_seconds >= 2.0 不是"碰巧站稳一瞬间"

大白话:必须"双脚踩稳 + 身体直立 + 不滑动 + 不旋转 + 保持 2 秒以上",才算真正成功。


六、总结与启发

6.1 核心设计哲学

机制 实现方式 设计哲学
双策略交接 物理接触检测 + 状态机 + 平滑过渡 不硬编码切换时机,让物理世界告诉 AI 何时切换
接触力控制 奖励函数引导 + MuJoCo 物理仿真 不直接控制力,而是告诉 AI "脚应该在哪"
成功验证 多条件组合 + 持续时间 不是"触发了"就算成功,必须"稳定保持"

6.2 对工程实践的启发

  1. 拆分比统一好:两个差异大的任务,拆成两个策略比一个策略包打天下更有效
  2. 引导比控制好:用奖励函数引导 AI 学会正确行为,比硬编码规则更灵活
  3. 物理真实性很重要:所有几何体都用真实碰撞模型,仿真结果才能迁移到真实世界
  4. 交接需要平滑:策略切换不是"咔"一下换,而是加权平均的柔顺过渡
  5. 验证要全面:不是"触发了"就算成功,必须多条件组合 + 持续时间

6.3 下一步

如果你想动手试试:

  1. 修改梯子间距:测试不同梯级距离对策略的影响
  2. 添加滑动:模拟湿滑梯面,测试策略的鲁棒性
  3. 对比不同模型:原模型 vs ONNX vs BPU,看精度和速度差异
  4. 部署到真机:如果有 RDK 开发板,尝试板端推理

作者:华仔,39 岁技术人,正在探索 AI 赋能个人工作流的第二曲线。

课程来源:Datawhale 具身智能组队学习 --- MicroDuck 运动策略与任务开发专题,第 6 课"梯面攀爬"。

模型来源 :HannesVonEssen/microduck-climb --- 社区开源的攀爬/起身策略、ONNX、PPO 检查点、训练代码和梯子模型。

如果你对具身智能、AI Agent、个人助手建设感兴趣,欢迎交流。

相关推荐
学逆向的43 分钟前
C++ 别名命名空间
开发语言·c++·网络安全
oscar9991 小时前
EMIB 与桥接路线——在“不铺满硅”的前提下逼近 2.5D 的互连密度
人工智能·芯片·封装·emib
TickDB1 小时前
美股历史数据下载:用 Codex 取数,Python 导出 CSV
python·websocket·mcp·行情数据 api
数字融合1 小时前
透明化数字孪生:以空间计算赋能全域智能决策
人工智能·数码相机·pygame
赛博守夜人1 小时前
AI安全攻防与治理之十:模型输出中的敏感信息从哪里来,记忆、检索、日志与上下文泄露的区别
人工智能·安全
云南新人和数采集团1 小时前
开源项目吐槽大会:一篇技术文章的大纲设计
python·scrapy·开源
fengyangaiGEO1 小时前
外贸B2B GEO优化:为何是平台成功的关键?
大数据·人工智能·python
poiu12346571 小时前
学生课程汇报PPT怎么准备?AI辅助工具使用观察
人工智能
解决问题no解决代码问题1 小时前
Java金融后端转LLM应用开发 Day9:AGI认知、负责任AI与全课程知识体系收官全指南
人工智能