From aed5d7b588241284516b469ef92d875bbb5aae8f Mon Sep 17 00:00:00 2001 From: Xuewei Guo <909336740@qq.com> Date: Sat, 19 Sep 2026 09:27:17 +0800 Subject: [PATCH] =?UTF-8?q?Create=20=E7=AC=AC=E4=B8=80=E7=AB=A0=E2=80=94?= =?UTF-8?q?=E2=80=94=E5=85=B7=E8=BA=AB=E6=99=BA=E8=83=BD=E5=88=B0=E5=BA=95?= =?UTF-8?q?=E5=9C=A8=E5=81=9A=E4=BB=80=E4=B9=88.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...章——具身智能到底在做什么.md | 327 ++++++++++++++++++ 1 file changed, 327 insertions(+) create mode 100644 EmbodiedAI/第一章——具身智能到底在做什么.md diff --git a/EmbodiedAI/第一章——具身智能到底在做什么.md b/EmbodiedAI/第一章——具身智能到底在做什么.md new file mode 100644 index 0000000..00d5936 --- /dev/null +++ b/EmbodiedAI/第一章——具身智能到底在做什么.md @@ -0,0 +1,327 @@ +# 第一章——具身智能到底在做什么 + +这一章先不训练大模型。我们从一个能手算、能写成 Python 的推物例子开始,理解具身智能最基本的工作方式: + +> 观察环境,根据目标决定动作,执行动作,再根据新的观察调整下一步动作。 + +这就是“观察 → 决策 → 动作 → 反馈”的闭环。后续章节中的行为克隆、ACT、Diffusion Policy 和 VLA,虽然生成动作的方式不同,但最终都要进入这个闭环。 + +## 1. 具体问题:机器人怎样把方块推到目标位置 + +假设桌上有一个方块,我们希望机器人把它推到指定位置。机器人在每个时刻都需要回答三个问题: + +1. **现在是什么情况?** 读取相机、关节或位置传感器,得到观察。 +2. **下一步应该做什么?** 策略根据观察和任务目标选择动作。 +3. **动作执行后发生了什么?** 重新观察环境,再决定下一步动作。 + +例如,机器人原本打算把方块向右推 2 厘米,但由于桌面摩擦较小,方块实际移动了 3 厘米。机器人如果重新观察,就能减小下一步的推动量;如果不看执行结果而继续照原计划行动,误差可能越来越大。 + +## 2. 直观解释:闭环为什么重要 + +可以把机器人想象成正在蒙眼走向一个目标的人: + +- 每走一步睁眼看一次,再修正方向,是**闭环控制(closed-loop control)**; +- 开始前记住一串步伐,之后闭眼全部执行,是**开环控制(open-loop control)**。 + +这个类比只说明“是否利用执行后的反馈”。真实机器人还要处理传感器噪声、动作延迟、接触、摩擦和动力学等问题。 + +闭环并不保证一定成功。如果观察错误、策略能力不足或动作超出机器人能力,闭环仍然可能失败。它的意义是:策略有机会利用最新信息修正后续动作。 + +## 3. 五个核心概念 + +下标 \(t\) 表示第 \(t\) 个时间步(timestep)。 + +| 概念 | 符号 | 含义 | 推物例子 | +| --- | --- | --- | --- | +| 状态(State) | \(s_t\) | 足以描述环境当前情况及其后续演化的信息 | 推杆位置、方块位置、方块角度、速度等 | +| 观察(Observation) | \(o_t\) | 机器人通过传感器实际获得的信息 | 相机图像、关节角度、测得的位置 | +| 动作(Action) | \(a_t\) | 策略发送给环境或控制器的指令 | 推杆的目标坐标、机械臂关节目标 | +| 策略(Policy) | \(\pi\) | 根据观察和任务目标选择动作的规则或模型 | 根据方块和目标的位置决定向哪里推 | +| 状态转移(Transition) | \(f\) 或 \(P\) | 环境执行动作后如何变化 | 接触和摩擦使方块移动或旋转 | + +### 3.1 状态不等于观察 + +状态包含环境演化所需的信息,观察则是机器人能够测到的信息,两者不能直接画等号。 + +以 PushT 推物任务为例,一个简化状态可以写成: + +\[ +s_t= +\begin{bmatrix} +x_t^{\text{agent}} & y_t^{\text{agent}} & +x_t^{\text{block}} & y_t^{\text{block}} & +\theta_t^{\text{block}} +\end{bmatrix} +\in\mathbb{R}^{5} +\] + +其中: + +- \(x_t^{\text{agent}},y_t^{\text{agent}}\):推杆在平面中的位置; +- \(x_t^{\text{block}},y_t^{\text{block}}\):方块中心的位置; +- \(\theta_t^{\text{block}}\):方块的旋转角度。 + +一个状态向量的形状是 `(5,)`。如果一次处理 \(B\) 个状态,组成的批量张量形状就是 `(B, 5)`。 + +真实机器人可能只能看到相机图像,无法直接知道精确位置、速度或摩擦系数。因此观察可能不完整,也可能带有噪声。当一次观察不足以判断当前状态时,策略可能需要使用连续多帧观察或历史信息。 + +### 3.2 策略不一定是神经网络 + +策略 \(\pi\) 是从输入到动作的映射。它可以是: + +- 人工编写的规则; +- 传统控制算法; +- 通过示范训练的神经网络; +- Diffusion Policy 或 VLA 等模型。 + +所以,“使用策略”不等于“已经进行了机器学习”。本章先用人工规则理解闭环,第三章再让模型从示范数据中学习策略。 + +## 4. 用公式表示完整闭环 + +先采用无噪声、确定性的简化模型: + +\[ +\begin{aligned} +o_t &= h(s_t),\\ +a_t &= \pi(o_t,g),\\ +s_{t+1} &= f(s_t,a_t),\\ +o_{t+1} &= h(s_{t+1}). +\end{aligned} +\] + +公式中的符号分别表示: + +- \(s_t\):执行动作前的环境状态; +- \(o_t\):策略实际获得的观察; +- \(g\):任务目标,例如方块的目标位置; +- \(a_t\):策略选择的动作; +- \(s_{t+1}\):执行动作后的新状态; +- \(h\):从真实状态产生传感器观察的过程; +- \(\pi\):根据观察和目标选择动作的策略; +- \(f\):环境的状态转移函数。 + +这里把目标 \(g\) 明确写进策略,因为同一个观察面对不同目标时,正确动作可能不同。另一种常见写法是把目标作为观察的一部分: + +\[ +\tilde{o}_t=[o_t,g],\qquad a_t=\pi(\tilde{o}_t). +\] + +真实环境存在不确定性,相同状态下执行相同动作,结果也可能略有不同。这时状态转移可以写成概率形式: + +\[ +s_{t+1}\sim P(\cdot\mid s_t,a_t). +\] + +\(P\) 表示:已知当前状态和动作时,下一个状态可能服从的概率分布。本章只需要知道不确定性存在,暂时不展开概率推导。 + +## 5. 反馈、奖励和成功信号不是一回事 + +闭环中的**反馈(feedback)**通常指执行动作后获得的新观察 \(o_{t+1}\)。**奖励(reward)**则是用数值评价动作结果的信号: + +\[ +r_t=R(s_t,a_t,s_{t+1}). +\] + +例如: + +- 新观察:方块现在位于坐标 \((3.1,2.0)\); +- 奖励:方块更接近目标,得到 \(r_t=0.1\); +- 成功信号:方块进入目标区域,`success=True`。 + +模仿学习主要从专家的“观察—动作”示范中学习,不一定需要奖励;强化学习通常利用奖励改进策略。两者都会在环境中执行策略并获得新的观察。 + +## 6. 数学与手算例子:一维位置控制 + +为了手算,我们先把推物简化成一维位置控制: + +- 当前位置 \(x_0=2\),目标位置 \(g=5\); +- 观察就是当前位置:\(o_t=x_t\); +- 动作是本步移动的距离:\(a_t\in[-1,1]\); +- 暂不考虑接触、摩擦、惯性和传感器噪声。 + +人工策略定义为: + +\[ +a_t=\operatorname{clip}\bigl(0.5(g-o_t),-1,1\bigr), +\] + +状态转移为: + +\[ +x_{t+1}=x_t+a_t. +\] + +`clip(value, -1, 1)` 表示把数值限制在 \([-1,1]\) 内。这里的 \(x_t\)、\(g\)、\(o_t\) 和 \(a_t\) 都是标量;如果统一写成一维张量,形状均为 `(1,)`。 + +第一步可以手算为: + +\[ +\begin{aligned} +o_0 &= x_0=2,\\ +a_0 &= \operatorname{clip}(0.5\times(5-2),-1,1)=1,\\ +x_1 &= x_0+a_0=2+1=3. +\end{aligned} +\] + +第二步为: + +\[ +\begin{aligned} +o_1 &= x_1=3,\\ +a_1 &= \operatorname{clip}(0.5\times(5-3),-1,1)=1,\\ +x_2 &= x_1+a_1=3+1=4. +\end{aligned} +\] + +## 7. 代码 Demo:观察、动作和反馈的循环 + +> **Demo 类型:原理演示。** 这段程序不是物理仿真,也没有训练神经网络,只用来展示闭环交互和人工策略。真实 PushT 的动作表示和物理过程会在第七章介绍。 + +将下面的代码保存为 `chapter01_closed_loop.py`,使用 Python 3 运行即可,不需要安装第三方库。 + +```python +def policy(observation, goal, gain=0.5): + """根据当前位置和目标位置计算动作。""" + raw_action = gain * (goal - observation) + return max(-1.0, min(1.0, raw_action)) + + +def run_episode(add_disturbance=False): + x = 2.0 + goal = 5.0 + + for t in range(6): + # 1. 观察 + observation = x + + # 2. 决策 + action = policy(observation, goal) + + # 3. 执行动作,环境状态发生变化 + next_x = x + action + + # 在第 2 步执行后加入外部扰动 + if add_disturbance and t == 1: + next_x -= 0.8 + + # 4. 记录结果。下一轮会重新观察 next_x + print( + f"t={t}, observation={observation:.4f}, " + f"action={action:.4f}, next_x={next_x:.4f}" + ) + x = next_x + + +print("无扰动:") +run_episode(add_disturbance=False) + +print("\n加入扰动:") +run_episode(add_disturbance=True) +``` + +实际运行结果如下: + +```text +无扰动: +t=0, observation=2.0000, action=1.0000, next_x=3.0000 +t=1, observation=3.0000, action=1.0000, next_x=4.0000 +t=2, observation=4.0000, action=0.5000, next_x=4.5000 +t=3, observation=4.5000, action=0.2500, next_x=4.7500 +t=4, observation=4.7500, action=0.1250, next_x=4.8750 +t=5, observation=4.8750, action=0.0625, next_x=4.9375 + +加入扰动: +t=0, observation=2.0000, action=1.0000, next_x=3.0000 +t=1, observation=3.0000, action=1.0000, next_x=3.2000 +t=2, observation=3.2000, action=0.9000, next_x=4.1000 +t=3, observation=4.1000, action=0.4500, next_x=4.5500 +t=4, observation=4.5500, action=0.2250, next_x=4.7750 +t=5, observation=4.7750, action=0.1125, next_x=4.8875 +``` + +## 8. 结果解读 + +前两步计算出的原始动作大于或等于 1,因此动作被限制在 1。这表示执行器每一步最多只能移动一个单位。 + +当位置进入目标附近后,动作逐步变小。定义位置误差: + +\[ +e_t=g-x_t. +\] + +当动作没有触发上下限时: + +\[ +\begin{aligned} +a_t &= 0.5e_t,\\ +e_{t+1} &= g-x_{t+1}\\ +&=g-(x_t+0.5e_t)\\ +&=0.5e_t. +\end{aligned} +\] + +也就是说,误差每一步缩小一半。它会逐渐接近零,但有限步内通常不会恰好等于零。因此工程中通常使用容差判断成功,例如: + +\[ +|g-x_t|<\varepsilon, +\] + +其中 \(\varepsilon\) 是允许误差。如果 \(\varepsilon=0.1\),无扰动实验执行 6 步后的误差为 \(5-4.9375=0.0625\),可以判定成功。 + +扰动实验中,第 2 步执行后的位置由 4.0 变成了 3.2。下一轮策略重新观察到 3.2,于是把动作从原本可能采用的 0.5 调整为 0.9。这正是反馈在闭环中的作用。 + +`gain=0.5` 是策略中的比例系数:数值较小通常移动得更慢;数值过大时可能反复越过目标甚至振荡。这个例子省略了惯性和时间单位,因此只能解释闭环原理,不能直接作为真实机器人的控制器。 + +## 9. 从原理 Demo 连接到机器人仿真 + +Gymnasium 是常见的仿真环境接口。一个完整回合(episode)通常写成: + +```python +observation, info = env.reset(seed=0) + +while True: + action = policy(observation) + next_observation, reward, terminated, truncated, info = env.step(action) + observation = next_observation + + if terminated or truncated: + break +``` + +其中: + +- `reset()`:开始一个新回合并返回初始观察; +- `step(action)`:执行一个动作并将环境推进一个时间步; +- `reward`:当前动作得到的奖励; +- `terminated`:任务因成功或失败等内部条件结束; +- `truncated`:任务因时间上限等外部条件结束; +- `info`:用于调试或评测的额外信息。 + +本章代码中的 `observation → policy → action → next_x`,与这个接口中的交互结构相同。区别在于,真实推物仿真会用物理引擎计算碰撞、摩擦和方块旋转。 + +## 10. 小练习 + +请先自己计算或修改代码,再核对运行结果。 + +1. 已知 \(x_1=3\),手算 \(a_1\) 和 \(x_2\)。代码输出是否一致? +2. 如果目标从 \(g=5\) 改为 \(g=-2\),为什么只写 \(a_t=\pi(o_t)\) 不足以完整描述这里的策略? +3. 将扰动从 `next_x -= 0.8` 改为 `next_x += 0.8`。下一步动作会变大还是变小?为什么? +4. 分别把 `gain` 改为 `0.2` 和 `1.2`,比较 6 步后的位置和误差。哪个更快?是否出现越过目标的情况? +5. 用自己的话解释:状态、观察、动作和策略分别是什么?反馈与奖励有什么区别? + +完成本章后,你应该能够: + +- 用自己的话解释“观察 → 决策 → 动作 → 反馈”的闭环; +- 区分状态和观察、反馈和奖励; +- 根据公式手算至少两个时间步; +- 运行 Demo,并解释扰动后动作为什么发生变化; +- 说明本章 Demo 是原理演示,不是真实机器人策略实验。 + +## 11. 参考资料与许可 + +- [Gymnasium:Basic Usage](https://gymnasium.farama.org/introduction/basic_usage/):`reset()`、`step()`、观察空间和动作空间的基础说明。 +- [Gymnasium:Env API](https://gymnasium.farama.org/api/env/):环境、终止和截断信号的接口定义。 +- [Hugging Face gym-pusht](https://github.com/huggingface/gym-pusht):后续完整推物实验使用的 Gymnasium 环境,上游项目采用 Apache-2.0 许可证。 +- [Diffusion Policy 项目主页](https://diffusion-policy.cs.columbia.edu/):PushT 任务及扩散策略的代表性工作,后续第五章会展开介绍。 + +本章文字和一维控制代码为本教程原创。示例仅使用 Python 标准库,没有复制上游项目代码。引用外部项目时请同时遵守对应仓库的许可证。