基于 A2C 算法的双足机器人行走控制

文章目录

  • [技术文档:基于 A2C 算法的双足机器人行走控制](#技术文档:基于 A2C 算法的双足机器人行走控制)
    • [1. 项目概述](#1. 项目概述)
      • [1.1 项目目标](#1.1 项目目标)
      • [1.2 技术栈](#1.2 技术栈)
    • [2. 系统架构设计](#2. 系统架构设计)
    • [3. 环境设计与状态空间](#3. 环境设计与状态空间)
      • [3.1 观测空间(Observation Space)](#3.1 观测空间(Observation Space))
      • [3.2 动作空间(Action Space)](#3.2 动作空间(Action Space))
      • [3.3 奖励函数(Reward Function)](#3.3 奖励函数(Reward Function))
    • [4. 核心算法:A2C 与 GAE](#4. 核心算法:A2C 与 GAE)
      • [4.1 算法原理](#4.1 算法原理)
      • [4.2 广义优势估计(GAE)](#4.2 广义优势估计(GAE))
      • [4.3 损失函数(Loss Function)](#4.3 损失函数(Loss Function))
    • [5. 网络结构](#5. 网络结构)
    • [6. 训练流程与超参数配置](#6. 训练流程与超参数配置)
      • [6.1 训练循环](#6.1 训练循环)
      • [6.2 关键超参数](#6.2 关键超参数)
    • [7. 代码模块说明](#7. 代码模块说明)
      • [7.1 目录结构](#7.1 目录结构)
      • [7.2 核心类与函数](#7.2 核心类与函数)
    • [8. 快速部署与运行指南](#8. 快速部署与运行指南)
      • [8.1 环境配置](#8.1 环境配置)
      • [8.2 训练启动](#8.2 训练启动)
      • [8.3 模型恢复与验证](#8.3 模型恢复与验证)
    • [9. 实验结果与收敛性分析](#9. 实验结果与收敛性分析)
      • [9.1 预期收敛曲线](#9.1 预期收敛曲线)
      • [9.2 奖励组成分析](#9.2 奖励组成分析)

技术文档:基于 A2C 算法的双足机器人行走控制

项目名称 :Humanoid Walking Control via Advantage Actor-Critic (A2C)

仿真平台 :PyBullet

深度学习框架 :PyTorch

文档版本 :1.0

日期:2026-07-29


1. 项目概述

1.1 项目目标

本项目旨在通过**无模型的深度强化学习(Model-free Deep Reinforcement Learning)**方法,训练一个双足机器人(Humanoid)在物理仿真环境中学会稳定向前行走。智能体(Agent)通过与环境的实时交互,自主探索最优的关节控制策略,无需人类示教或预定义步态。

1.2 技术栈

组件 技术选型 用途
物理引擎 PyBullet 3.x 刚体动力学仿真、碰撞检测、URDF 模型加载
深度学习 PyTorch 2.x 策略网络与价值网络的构建、自动微分、GPU 加速训练
强化学习算法 A2C (Advantage Actor-Critic) 在线策略梯度方法,适用于连续动作空间
依赖管理 Python 3.8+ / Conda 环境隔离与包管理

2. 系统架构设计

系统采用经典的 Actor-Critic(演员-评论家) 架构,包含三大核心模块:

  1. 仿真环境模块(Environment):封装 PyBullet,负责重置物理状态、执行动作、返回观测值与奖励。
  2. 智能体模块(Agent):包含策略网络(Actor)和价值网络(Critic)。
  3. 训练调度模块(Trainer):负责采样轨迹、计算优势估计(GAE)、执行反向传播并更新网络参数。

#mermaid-svg-NKJzEccF1ESOW6my{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-NKJzEccF1ESOW6my .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-NKJzEccF1ESOW6my .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-NKJzEccF1ESOW6my .error-icon{fill:#552222;}#mermaid-svg-NKJzEccF1ESOW6my .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-NKJzEccF1ESOW6my .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-NKJzEccF1ESOW6my .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-NKJzEccF1ESOW6my .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-NKJzEccF1ESOW6my .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-NKJzEccF1ESOW6my .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-NKJzEccF1ESOW6my .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-NKJzEccF1ESOW6my .marker{fill:#333333;stroke:#333333;}#mermaid-svg-NKJzEccF1ESOW6my .marker.cross{stroke:#333333;}#mermaid-svg-NKJzEccF1ESOW6my svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-NKJzEccF1ESOW6my p{margin:0;}#mermaid-svg-NKJzEccF1ESOW6my .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-NKJzEccF1ESOW6my .cluster-label text{fill:#333;}#mermaid-svg-NKJzEccF1ESOW6my .cluster-label span{color:#333;}#mermaid-svg-NKJzEccF1ESOW6my .cluster-label span p{background-color:transparent;}#mermaid-svg-NKJzEccF1ESOW6my .label text,#mermaid-svg-NKJzEccF1ESOW6my span{fill:#333;color:#333;}#mermaid-svg-NKJzEccF1ESOW6my .node rect,#mermaid-svg-NKJzEccF1ESOW6my .node circle,#mermaid-svg-NKJzEccF1ESOW6my .node ellipse,#mermaid-svg-NKJzEccF1ESOW6my .node polygon,#mermaid-svg-NKJzEccF1ESOW6my .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-NKJzEccF1ESOW6my .rough-node .label text,#mermaid-svg-NKJzEccF1ESOW6my .node .label text,#mermaid-svg-NKJzEccF1ESOW6my .image-shape .label,#mermaid-svg-NKJzEccF1ESOW6my .icon-shape .label{text-anchor:middle;}#mermaid-svg-NKJzEccF1ESOW6my .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-NKJzEccF1ESOW6my .rough-node .label,#mermaid-svg-NKJzEccF1ESOW6my .node .label,#mermaid-svg-NKJzEccF1ESOW6my .image-shape .label,#mermaid-svg-NKJzEccF1ESOW6my .icon-shape .label{text-align:center;}#mermaid-svg-NKJzEccF1ESOW6my .node.clickable{cursor:pointer;}#mermaid-svg-NKJzEccF1ESOW6my .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-NKJzEccF1ESOW6my .arrowheadPath{fill:#333333;}#mermaid-svg-NKJzEccF1ESOW6my .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-NKJzEccF1ESOW6my .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-NKJzEccF1ESOW6my .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-NKJzEccF1ESOW6my .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-NKJzEccF1ESOW6my .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-NKJzEccF1ESOW6my .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-NKJzEccF1ESOW6my .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-NKJzEccF1ESOW6my .cluster text{fill:#333;}#mermaid-svg-NKJzEccF1ESOW6my .cluster span{color:#333;}#mermaid-svg-NKJzEccF1ESOW6my div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-NKJzEccF1ESOW6my .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-NKJzEccF1ESOW6my rect.text{fill:none;stroke-width:0;}#mermaid-svg-NKJzEccF1ESOW6my .icon-shape,#mermaid-svg-NKJzEccF1ESOW6my .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-NKJzEccF1ESOW6my .icon-shape p,#mermaid-svg-NKJzEccF1ESOW6my .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-NKJzEccF1ESOW6my .icon-shape .label rect,#mermaid-svg-NKJzEccF1ESOW6my .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-NKJzEccF1ESOW6my .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-NKJzEccF1ESOW6my .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-NKJzEccF1ESOW6my :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 观测状态 s_t
采样动作 a_t
奖励 r_t, 终止状态 done
计算优势 & 目标值
更新价值参数
更新策略参数
环境 Environment
策略网络 Actor
训练器 Trainer
价值网络 Critic


3. 环境设计与状态空间

3.1 观测空间(Observation Space)

算法动态检测环境中的可动关节数量(本项目为 4 个),构建观测向量。具体包含:

特征组 具体内容 维度
身体信息 X, Y, Z 坐标;Roll, Pitch, Yaw 欧拉角;线速度 (Vx, Vy, Vz);角速度 (Wx, Wy, Wz) 12
关节信息 每个可动关节的角度 (Position)角速度 (Velocity) n_joints * 2 = 8
总维度 - 20

3.2 动作空间(Action Space)

  • 类型:连续(Continuous)。
  • 维度n_joints = 4
  • 数值范围 :每个动作值被限制在 [-1, 1] 区间,对应关节目标角度的幅度(单位:弧度)。
  • 控制模式 :位置控制(POSITION_CONTROL),通过 setJointMotorControl2 设置目标角度。

3.3 奖励函数(Reward Function)

奖励函数是引导智能体行为的核心,设计如下:

R = R f o r w a r d + R e n e r g y + R a l i v e + R f a l l R = R_{forward} + R_{energy} + R_{alive} + R_{fall} R=Rforward+Renergy+Ralive+Rfall

  • 前进奖励 ( R f o r w a r d R_{forward} Rforward): 1.0 * delta_x。鼓励机器人沿 X 轴正向移动。
  • 能量惩罚 ( R e n e r g y R_{energy} Renergy): -0.01 * mean(action^2)。抑制关节高频抖动,鼓励平滑运动。
  • 存活奖励 ( R a l i v e R_{alive} Ralive): +0.1。每步给予微小正奖励,防止智能体因害怕惩罚而主动摔倒不动。
  • 摔倒惩罚 ( R f a l l R_{fall} Rfall): 当身体高度低于 0.3m 或滚转角/俯仰角超过 57°(1.0 rad)时,触发 -10.0 并终止当前回合(Episode)。

4. 核心算法:A2C 与 GAE

4.1 算法原理

本项目采用 优势演员-评论家(A2C) 算法。与传统 REINFORCE 算法相比,A2C 通过引入优势函数(Advantage Function) 降低了梯度估计的方差。

策略梯度(Policy Gradient) 更新公式如下:

∇ J ( θ ) ≈ E ∇ θ log ⁡ π θ ( a t ∣ s t ) ⋅ A ( s t , a t ) \nabla J(\theta) \approx \mathbb{E} \left \\nabla_\\theta \\log \\pi_\\theta(a_t\|s_t) \\cdot A(s_t, a_t) \\right ∇J(θ)≈E∇θlogπθ(at∣st)⋅A(st,at)

其中 A ( s t , a t ) A(s_t, a_t) A(st,at) 即为优势函数,衡量动作值 Q ( s t , a t ) Q(s_t, a_t) Q(st,at) 相对于基准状态值 V ( s t ) V(s_t) V(st) 的优势。

4.2 广义优势估计(GAE)

为了权衡偏差与方差,我们使用 GAE(Generalized Advantage Estimation) 计算优势函数:

A t G A E ( γ , λ ) = ∑ l = 0 ∞ ( γ λ ) l δ t + l A^{GAE(\gamma, \lambda)}t = \sum{l=0}^{\infty} (\gamma \lambda)^l \delta_{t+l} AtGAE(γ,λ)=l=0∑∞(γλ)lδt+l

其中:

  • γ \gamma γ(折扣因子)= 0.99,控制对未来奖励的重视程度。
  • λ \lambda λ(GAE 系数)= 0.95,控制优势估计的方差与偏差平衡。
  • δ t = r t + γ V ( s t + 1 ) − V ( s t ) \delta_t = r_t + \gamma V(s_{t+1}) - V(s_t) δt=rt+γV(st+1)−V(st),即时序差分误差(TD Error)。

4.3 损失函数(Loss Function)

网络总损失由三部分组成:

  1. 策略损失(Policy Loss)

    L p o l i c y = − E log ⁡ π θ ( a t ∣ s t ) ⋅ A t L_{policy} = -\mathbb{E} \left \\log \\pi_\\theta(a_t\|s_t) \\cdot A_t \\right Lpolicy=−Elogπθ(at∣st)⋅At

    配合熵正则化(Entropy Bonus) ,鼓励探索: L e n t r o p y = − β ⋅ H ( π θ ) L_{entropy} = -\beta \cdot \mathcal{H}(\pi_\theta) Lentropy=−β⋅H(πθ),其中 β = 0.01 \beta=0.01 β=0.01。

  2. 价值损失(Value Loss)

    使用均方误差(MSE): L v a l u e = 1 2 E ( V ϕ ( s t ) − R t ) 2 L_{value} = \frac{1}{2} \mathbb{E} \left (V_\\phi(s_t) - R_t)\^2 \\right Lvalue=21E(Vϕ(st)−Rt)2,其中 R t R_t Rt 是实际折扣回报。


5. 网络结构

考虑到状态空间较小(20维)且是连续控制任务,网络采用全连接多层感知机(MLP),而非 Transformer。

网络模块 层次 输入维度 输出维度 激活函数
共享特征层 Linear + BN 20 256 ReLU
Linear + BN 256 256 ReLU
Actor 头 Linear 256 4 (均值) Tanh (隐式)
Log_Std - 4 (可学习) -
Critic 头 Linear 256 1 无 (线性输出)
  • 动作采样 :Actor 输出动作均值 μ \mu μ 和对数标准差 log ⁡ σ \log\sigma logσ,构建对角高斯分布 N ( μ , σ ) \mathcal{N}(\mu, \sigma) N(μ,σ) 进行采样。

6. 训练流程与超参数配置

6.1 训练循环

  1. 采样 :智能体在当前策略下运行 N = 256 N=256 N=256 个仿真步(update_interval),收集轨迹片段。
  2. 计算 GAE :利用 Critic 网络估计的最后状态价值 V ( s t + 1 ) V(s_{t+1}) V(st+1),反向计算每一步的优势值和回报。
  3. 标准化:对优势值进行 Z-score 标准化(减去均值,除以标准差),使训练更稳定。
  4. 梯度更新:对收集的批次数据计算上述三种损失,合并后进行反向传播。
  5. 重置:若机器人摔倒或超出步数限制,重置仿真环境并开始新 Episode。

6.2 关键超参数

参数名称 符号 数值 说明
最大训练步数 max_steps 1,000,000 物理仿真总步数
折扣因子 γ \gamma γ 0.99 未来奖励衰减率
GAE 系数 λ \lambda λ 0.95 权衡优势估计的偏差/方差
学习率 lr 3e-4 Adam 优化器学习率
更新批量大小 update_interval 256 每收集 256 步更新一次
最大单回合步数 max_episode_steps 500 防止无限循环
熵系数 β \beta β 0.01 控制探索程度
梯度裁剪 clip_grad_norm 0.5 防止梯度爆炸

7. 代码模块说明

7.1 目录结构

复制代码
src/
├── train_humanoid_mlp.py    # 主训练脚本(包含环境、网络、训练循环)
└── models/                  # 自动保存的训练检查点
    ├── humanoid_checkpoint_50000.pth
    └── humanoid_model.pth   # 最终模型

7.2 核心类与函数

  • Config (dataclass):统一管理所有超参数,支持动态修改。
  • PolicyNetwork (nn.Module):定义共享特征层、Actor 头和 Critic 头。
  • HumanoidEnv
    • reset():重置关节角度和位置,返回初始观测。
    • _get_obs():动态拼接身体与关节状态,自适应维度。
    • step(action):执行动作,结算奖励,返回下一状态和终止标志。
  • train():主循环,实现轨迹收集、GAE 计算、模型优化与日志输出。

8. 快速部署与运行指南

8.1 环境配置

bash 复制代码
# 创建虚拟环境(可选)
conda create -n rl_walk python=3.10
conda activate rl_walk

# 安装依赖
pip install torch numpy pybullet tqdm

8.2 训练启动

bash 复制代码
python train_humanoid_mlp.py
  • 默认以 render=False 启动(无图形界面,训练更快)。
  • 若要实时观察训练过程,请将脚本中 env = HumanoidEnv(render=False) 改为 render=True

8.3 模型恢复与验证

如果训练中断,只需注释掉 train() 函数中的模型初始化,加载保存的 checkpoint 即可继续(需在代码中补充加载逻辑)。


9. 实验结果与收敛性分析

9.1 预期收敛曲线

  • 初期(0 ~ 50k 步):平均 Episode 奖励为负(约 -50 ~ -20),机器人频繁摔倒,缺乏协调性。
  • 中期(50k ~ 300k 步):奖励快速上升,机器人学会保持髋部平衡,能够踉跄前行。
  • 后期(300k ~ 1M 步):奖励趋于收敛,机器人展现稳定、周期性的行走步态,平均速度接近 0.5 m/s。

9.2 奖励组成分析

  • 前进奖励 贡献逐步上升,成为奖励的主要来源。
  • 能量惩罚 有效抑制了高频抖动,使步态更加自然。
  • 熵正则化 确保了策略的多样性,防止过早陷入局部最优。


相关推荐
MomentYY1 小时前
RAG 混合检索:关键词 + 语义
人工智能·agent·ai编程
Black蜡笔小新1 小时前
EasyAIS+国标GB28181视频监控平台EasyCVR强强联动,全域视频AI识别能力落地!
大数据·人工智能·音视频
Microvision维视智造1 小时前
智能工厂等级自检表:梯度培育,你的工厂在第几级?
人工智能·计算机视觉·视觉检测·机器视觉
时光不负努力1 小时前
skill 定义 + 多个skill 协作
人工智能·openai
武子康2 小时前
MCP 2026-07-28 无状态核心之后:身份、任务、幂等与审计状态到底放在哪里?
人工智能·llm·mcp
瓦学妹2 小时前
X(Twitter)新号如何防封?2026 养号与防限流全攻略
大数据·网络·人工智能·新媒体运营·twitter
EAIReport2 小时前
企业GEO全域运营技术落地路线与量化效果验证方案(AI大数据行业适配)
大数据·人工智能
极地野狼 音乐哔哔2 小时前
AI Agent 30天速成|Day4 笔记
人工智能·笔记
小保CPP2 小时前
OpenCV C++车型识别1-图像预处理
c++·人工智能·opencv·计算机视觉
普密斯科技2 小时前
如何一键解决手机镜头磨切片微米级尺寸测量难题?
人工智能·计算机视觉·智能手机·测量