chore: release v0.2.0

This commit is contained in:
motphys-developers
2026-02-10 08:08:11 +00:00
parent dbfa9e31fa
commit b568ac5600
123 changed files with 9732 additions and 497 deletions

View File

@@ -161,6 +161,20 @@ MotrixLab 是一个为机器人训练设计的机器学习通用架构。它基
:::{grid-item-card}
```{video} _static/videos/dm_humanoid_run.mp4
:poster: _static/images/poster/dm_humanoid_run.jpg
:nocontrols:
:autoplay:
:playsinline:
:muted:
:loop:
:width: 100%
```
:::
:::{grid-item-card}
```{video} _static/videos/bounce_ball.mp4
:poster: _static/images/poster/bounce_ball.jpg
:nocontrols:

View File

@@ -0,0 +1,154 @@
# Acrobot 双连杆
Acrobot 是一个双连杆摆动和平衡任务。目标是使用一个电机扭矩摆动双臂并到达目标位置。
```{video} /_static/videos/acrobot.mp4
:poster: _static/images/poster/acrobot.jpg
:nocontrols:
:autoplay:
:playsinline:
:muted:
:loop:
:width: 100%
```
---
## 任务描述
双连杆 Acrobot 由一个铰链关节驱动,该关节由单个电机控制。电机安装在肘关节处,这是系统中唯一的驱动关节。电机的扭矩使连杆在平面内旋转,实现从任意初始角度摆起并到达目标位置。扭矩受限于执行器的 ctrlrange通过调节其大小和方向策略必须积累能量以摆起并到达目标同时保持稳定性。
## 动作空间
| 项目 | 详情 |
| -------- | ------------------------------- |
| **类型** | `Box(-1.0, 1.0, (1,), float32)` |
| **维度** | 1 |
---
## 观察空间
| 项目 | 详情 |
| -------- | ------------------------------- |
| **类型** | `Box(-inf, inf, (6,), float32)` |
| **维度** | 6 |
顺序:`upper_arm_horizontal, lower_arm_horizontal, upper_arm_vertical, lower_arm_vertical, shoulder_velocity, elbow_velocity`。
---
## 奖励函数设计
- 基础稀疏奖励:鼓励末端进入目标区域(半径 = 0.2
- 持续奖励:在目标区域内每步提供 0.1 的奖励
- 距离奖励0.3 \* (1.0 - clip(distance / 2.0, 0, 1.0)) 鼓励向目标移动
- 速度惩罚0.01 \* max(0, velocity_magnitude - 2.0) 惩罚过高的速度
---
## 初始状态
- 肩关节角度随机于 `[-pi, pi]`
- 肘关节角度随机于 `[-pi, pi]`
- 角速度初始化为零
## Episode 终止条件
- Episode 长度由 `max_episode_seconds` 限制
- 对观察值进行 NaN 检查
---
### 1. 环境预览
```bash
uv run scripts/view.py --env acrobot
```
### 2. 开始训练
```bash
# 使用默认参数训练
uv run scripts/train.py --env acrobot
# 自定义并行环境数
uv run scripts/train.py --env acrobot --num-envs 1024
# 开启训练时渲染
uv run scripts/train.py --env acrobot --render
```
### 3. 查看训练进度
```bash
uv run tensorboard --logdir runs/acrobot
```
### 4. 测试训练结果
```bash
# 自动发现最佳策略(推荐)
uv run scripts/play.py --env acrobot
# 手动指定策略文件
uv run scripts/play.py --env acrobot --policy runs/acrobot/nn/best_policy.pickle
```
> **提示**:策略会从 `runs/acrobot/` 中自动选择。你可以使用 `--policy` 参数覆盖。
---
## 配置参数
### 环境配置
```python
@dataclass
class AcrobotEnvCfg(EnvCfg):
model_file: str = ".../acrobot.xml" # MJCF 模型
max_episode_seconds: float = 10.0
sim_dt: float = 0.01
ctrl_dt: float = 0.02
reset_noise_scale: float = 0.1
render_spacing: float = 2.0
```
### 训练配置PPO 示例)
```python
@rlcfg("acrobot", backend="jax")
@dataclass
class AcrobotPPO(PPOCfg):
max_env_steps: int = 60_000_000
check_point_interval: int = 500
# 覆盖 PPO 配置
policy_hidden_layer_sizes: tuple[int, ...] = (32, 32)
value_hidden_layer_sizes: tuple[int, ...] = (32, 32)
rollouts: int = 64
learning_epochs: int = 5
mini_batches: int = 8
learning_rate: float = 3e-4
grad_norm_clip: float = 0.1
clip_predicted_values: bool = False
value_clip: float = 10.0
entropy_loss_scale: float = 0.1
learning_rate_scheduler_kl_threshold: float = 0.02
discount_factor: float = 0.995
lambda_param: float = 0.97
ratio_clip: float = 0.2
value_loss_scale: float = 0.5
random_timesteps: int = 0
learning_starts: int = 0
kl_threshold: float = 0.03
```
---
## 预期训练结果
1. Acrobot 能够摆动双臂到达目标位置
2. 末端能够稳定地停留在目标区域内
3. 过高的震荡通过速度惩罚得到减少
4. 策略能够以平滑的动作高效地接近目标

View File

@@ -1,4 +1,4 @@
# ANYmal-C Locomotion
# ANYmal-C 导航
## 概述

View File

@@ -42,46 +42,323 @@ Bounce Ball 是一个单臂机器人操作任务,使用 6 自由度的配天 A
| 项目 | 详细信息 |
| -------- | -------------------------------- |
| **类型** | `Box(-inf, inf, (25,), float32)` |
| **维度** | 25 |
| **类型** | `Box(-inf, inf, (29,), float32)` |
| **维度** | 29 |
观察空间由以下部分组成(按顺序):
| 部分 | 内容说明 | 维度 | 备注 |
| ----------- | -------------------- | ---- | --------------------------------------------------------------- |
| **dof_pos** | 各关节自由度位置信息 | 13 | 前 6 个为机械臂关节,后 7 个为球的自由关节3 位置 + 4 四元数) |
| **dof_vel** | 各关节自由度速度信息 | 12 | 速度为位置导数 |
| 部分 | 内容说明 | 维度 | 备注 |
| ----------------- | -------------------- | ---- | --------------------------------------------------------------- |
| **dof_pos** | 各关节自由度位置信息 | 13 | 前 6 个为机械臂关节,后 7 个为球的自由关节3 位置 + 4 四元数) |
| **dof_vel** | 各关节自由度速度信息 | 12 | 速度为位置导数 |
| **paddle_pos** | 挡板位置信息 | 3 | 挡板中心的 x, y, z 坐标 |
| **target_height** | 目标高度 | 1 | 当前环境的目标高度 |
| 序号 | 观察量 | 最小值 | 最大值 | XML 名称 | 类型 (单位) |
| ----- | -------------- | ------ | ------ | ----------- | ---------------- |
| 0-5 | 机械臂关节角度 | -Inf | Inf | Joint1-6 | 角度 (rad) |
| 6 | 球 x 坐标 | -Inf | Inf | ball_x | 位置 (m) |
| 7 | 球 y 坐标 | -Inf | Inf | ball_y | 位置 (m) |
| 8 | 球 z 坐标 | -Inf | Inf | ball_z | 位置 (m) |
| 9-12 | 球姿态四元数 | -Inf | Inf | ball_qw/xyz | 四元数 (w,x,y,z) |
| 13-24 | 关节和球速度 | -Inf | Inf | - | 速度/角速度 |
| 序号 | 观察量 | 最小值 | 最大值 | XML 名称 | 类型 (单位) |
| ----- | -------------------------- | ------ | ------ | --------- | ----------------- |
| 0-5 | 机械臂关节角度 | -Inf | Inf | Joint1-6 | 角度 (rad) |
| 6-8 | 球位置 [x, y, z] | -Inf | Inf | ball_link | 位置 (m) |
| 9-12 | 球姿态四元数 [w,x,y,z] | -Inf | Inf | ball_link | 四元数 |
| 13-18 | 机械臂关节角速度 | -Inf | Inf | Joint1-6 | 角速度 (rad/s) |
| 19-24 | 球速度 [vx,vy,vz,wx,wy,wz] | -Inf | Inf | ball_link | 速度 (m/s, rad/s) |
| 25-27 | 挡板位置 [x, y, z] | -Inf | Inf | blocker | 位置 (m) |
| 28 | 目标高度 | -Inf | Inf | - | 位置 (m) |
---
## 奖励函数设计
## 奖励函数
奖励函数由以下几个部分组成:
奖励函数采用复合设计,包含多个奖励和惩罚项,引导机器人学习稳定的颠球策略。所有奖励参数可通过配置文件调整。
```python
# 位置控制奖励:保持球在挡板中心上方
# 受控向上速度奖励:在球位置良好时奖励适中的向上速度
# 高度精度奖励:球接近目标高度
# 连续弹跳奖励:奖励连续成功的弹跳
# 总奖励 = 各项加权组合
```
### 主要奖励项
---
#### 1. 水平位置奖励
## 初始状态
**设计意义**:这是最核心的奖励项,确保球始终保持在挡板正上方。通过垂直距离加权机制,当球接近挡板时(即将击打时刻)对水平位置的要求更严格,引导策略在关键时刻精确对齐。
- **机械臂初始位置**[0, 40, 110, 0, -60, 0] 度,带有随机噪声
- **球的初始位置**:挡板中心上方,带有随机噪声
- **球的初始速度**[0.0, 0.0, 0.0] m/s
**计算公式**
$$
\begin{aligned}
\text{err}_{xy} &= \sqrt{(x_{ball} - x_{target})^2 + (y_{ball} - y_{target})^2} &&\text{(水平位置误差)} \\
d_{vert} &= |z_{ball} - z_{paddle}| &&\text{(垂直距离)} \\
w_{vert} &= e^{-d_{vert} / \sigma_{vert}} &&\text{(垂直距离权重)} \\
\sigma_{pos} &= \sigma_{base} \times (1.0 + k_{weight} \times w_{vert}) &&\text{(自适应尺度)} \\
r_{pos} &= e^{-\frac{\text{err}_{xy}^2}{2\sigma_{pos}^2}} &&\text{(高斯奖励)} \\
\\
\text{其中:} \quad &\sigma_{vert} = 0.15 \text{ m} &&\text{(垂直距离尺度)} \\
&\sigma_{base} = 0.1 \text{ m} &&\text{(基础水平尺度)} \\
&k_{weight} = 3.0 &&\text{(权重因子)} \\
&x_{target} = 0.58856 \text{ m}, \, y_{target} = 0.0 \text{ m} &&\text{(目标位置)}
\end{aligned}
$$
**权重**2.0
#### 2. 位置偏离惩罚
**设计意义**:对严重偏离目标位置的情况施加强惩罚,防止球飞出控制范围。使用 sigmoid 函数实现平滑过渡,避免奖励函数不连续。
**计算公式**
$$
r_{out} = -\frac{2.0}{1 + e^{-(\text{err}_{xy} - 0.05) / 0.03}} \qquad \text{sigmoid 惩罚)}
$$
**权重**1.0
#### 3. 速度匹配奖励
**设计意义**基于抛体运动物理规律激励球的运动轨迹能够在目标高度时具有期望的速度0.5 m/s。这确保球不会过快或过慢地通过目标高度有利于稳定控制。
**计算公式**
$$
\begin{aligned}
\Delta h &= h_{target} - z_{ball} &&\text{(高度差)} \\
v_{desired} &= 0.5 \text{ m/s} &&\text{(期望速度)} \\
\\
\text{情况1}&\text{球向上运动且低于目标高度} \\
v_{z,up}^2 &= v_z^2 - 2g\Delta h &&\text{(能量守恒)} \\
v_{at\_target,up} &= \sqrt{\max(0, v_{z,up}^2)} &&\text{(向上到达速度)} \\
\\
\text{情况2}&\text{球向下运动且高于目标高度} \\
v_{z,down}^2 &= v_z^2 + 2g|\Delta h| &&\text{(能量守恒)} \\
v_{at\_target,down} &= -\sqrt{\max(0, v_{z,down}^2)} &&\text{(向下到达速度)} \\
\\
\text{情况3}&\text{球接近目标高度(} |\Delta h| < 0.05 \text{ m} \\
v_{at\_target,near} &= v_z &&\text{(当前速度)} \\
\\
\text{平滑组合:}& \\
\sigma_{up} &= \frac{1}{1 + e^{-v_z / 0.2}} &&\text{(向上运动权重)} \\
\sigma_{below} &= \frac{1}{1 + e^{-\Delta h / 0.02}} &&\text{(低于目标权重)} \\
\sigma_{down} &= 1 - \sigma_{up} &&\text{(向下运动权重)} \\
\sigma_{above} &= 1 - \sigma_{below} &&\text{(高于目标权重)} \\
w_{near} &= e^{-\frac{\Delta h^2}{2 \times 0.01^2}} &&\text{(接近目标权重)} \\
\\
v_{at\_target} &= v_{at\_target,up} \cdot \sigma_{up} \cdot \sigma_{below} \\
&\quad + v_{at\_target,down} \cdot \sigma_{down} \cdot \sigma_{above} \\
&\quad + v_{at\_target,near} \cdot w_{near} &&\text{(加权组合)} \\
\\
\text{err}_{vel} &= |v_{at\_target} - v_{desired}| &&\text{(速度误差)} \\
r_{vel} &= e^{-\frac{\text{err}_{vel}^2}{2 \times 0.8^2}} &&\text{(高斯奖励)}
\end{aligned}
$$
**权重**2.0
#### 4. 高度奖励
**设计意义**直接激励球接近目标高度这是任务的核心目标之一。较高的权重4.5确保策略优先考虑高度控制。目标高度在每个环境中随机采样0.3-0.6 m提升策略的泛化能力。
**计算公式**
$$
\begin{aligned}
\text{err}_h &= |z_{ball} - h_{target}| &&\text{(高度误差)} \\
r_h &= e^{-\frac{\text{err}_h^2}{2 \times 0.15^2}} &&\text{(高斯奖励)}
\end{aligned}
$$
**权重**4.5
#### 5. 高度进步奖励
**设计意义**:激励球达到更高位置,帮助策略在训练初期快速学会向上击打球,避免陷入"不击打"的局部最优。
**计算公式**
$$
r_{progress} = \max(0, z_{ball} - 0.2) \times 2.0 \qquad \text{(线性奖励)}
$$
**权重**1.0
#### 6. 受控向上速度奖励
**设计意义**:只有当球水平位置良好时才奖励向上速度,避免"乱打"行为。理想速度根据物理公式计算,确保球能恰好达到目标高度。这个奖励引导策略学习精确的击打力度。
**计算公式**
$$
\begin{aligned}
q_{pos} &= e^{-\frac{\text{err}_{xy}^2}{2 \times 0.02^2}} &&\text{(位置质量)} \\
v_{ideal} &= \sqrt{2g \times \max(0, \Delta h)} &&\text{(理想发射速度)} \\
v_{ideal} &\in [0.5, 3.0] \text{ m/s} &&\text{(限制范围)} \\
q_{vel} &= e^{-\frac{(v_z - v_{ideal})^2}{2 \times 0.5^2}} &&\text{(速度质量)} \\
\sigma_{up} &= \frac{1}{1 + e^{-v_z / 0.1}} &&\text{(向上掩码)} \\
r_{controlled} &= q_{pos} \times q_{vel} \times \sigma_{up} \times \text{clip}(v_z, 0, 1.5) &&\text{(组合奖励)}
\end{aligned}
$$
**权重**1.5
#### 7. 连续弹跳奖励
**设计意义**:激励多次连续成功弹跳,引导策略学习稳定的长期控制。使用对数函数避免奖励无限增长,同时要求球位置良好才给予奖励。
**计算公式**
$$
\begin{aligned}
q_{bounce} &= e^{-\frac{\text{err}_{xy}^2}{2 \times 0.05^2}} &&\text{(弹跳位置质量)} \\
r_{bounce\_log} &= 0.5 \times \log(n_{bounces} + 1) &&\text{(对数奖励)} \\
r_{bounce} &= r_{bounce\_log} \times q_{bounce} \times \mathbb{1}_{n_{bounces} > 0} &&\text{(条件奖励)}
\end{aligned}
$$
**权重**0.8
#### 8. 高弹跳次数奖励
**设计意义**对高弹跳次数≥3 次)给予额外奖励,进一步激励长期稳定控制。使用 sigmoid 激活函数使奖励平滑增长。
**计算公式**
$$
\begin{aligned}
\sigma_{high} &= \frac{1}{1 + e^{-(n_{bounces} - 2.0) / 0.5}} &&\text{(高弹跳激活)} \\
r_{high} &= n_{bounces} \times 0.15 \times q_{bounce} \times \sigma_{high} &&\text{(额外奖励)}
\end{aligned}
$$
**权重**0.3
#### 9. 挡板-球水平对齐奖励
**设计意义**激励挡板主动移动到球的正下方而不是等待球落下。垂直距离越近权重越大在即将击打时刻要求更精确的对齐。弹跳时刻给予额外奖励boost强化正确的击打行为。
**计算公式**
$$
\begin{aligned}
\text{err}_{align} &= \|(\mathbf{x}_{ball}, \mathbf{y}_{ball}) - (\mathbf{x}_{paddle}, \mathbf{y}_{paddle})\|_2 &&\text{(对齐误差)} \\
w_{prox} &= e^{-d_{vert} / 0.1} &&\text{(垂直接近权重)} \\
q_{align} &= e^{-\frac{\text{err}_{align}^2}{2 \times 0.03^2}} \times (1.0 + 2.0 \times w_{prox}) &&\text{(对齐质量)} \\
k_{boost} &= \begin{cases} 3.0 & \text{if bounce detected} \\ 1.0 & \text{otherwise} \end{cases} &&\text{(弹跳增益)} \\
r_{align} &= q_{align} \times k_{boost} \times 0.3 &&\text{(对齐奖励)}
\end{aligned}
$$
**权重**0.6
#### 10. 挡板原位奖励
**设计意义**激励挡板在球远离时回到原位home position避免挡板长时间停留在高位。使用距离动态因子当球远离挡板时$d_{vert} > 0.15$ m增大奖励鼓励挡板快速回位当球接近时减小奖励允许挡板上移准备击打。这种设计使挡板运动更加节能和自然。
**计算公式**
$$
\begin{aligned}
\text{err}_{home} &= |z_{paddle} - z_{home}| &&\text{(原位偏离)} \\
k_{dist} &= 1.0 + \frac{0.5}{1 + e^{-(d_{vert} - 0.15) / 0.03}} &&\text{(距离因子)} \\
q_{home} &= e^{-\frac{\text{err}_{home}^2}{2 \times 0.05^2}} &&\text{(原位质量)} \\
r_{home} &= q_{home} \times k_{dist} &&\text{(原位奖励)} \\
\\
\text{其中:} \quad &z_{home} = 0.05 \text{ m} &&\text{(挡板原位高度)}
\end{aligned}
$$
**权重**1.5
### 惩罚项
#### 1. 过高向上速度惩罚
**设计意义**:防止球速度过快(>3.5 m/s失去控制确保球的运动在可控范围内。
**计算公式**
$$
r_{excess} = -\frac{1.0}{1 + e^{-(v_z - 3.5) / 0.3}} \qquad \text{sigmoid 惩罚)}
$$
**权重**1.0
#### 2. 向下速度惩罚
**设计意义**:惩罚球向下运动($v_z < -0.2$ m/s激励策略及时击打球避免球自由下落。
**计算公式**
$$
\begin{aligned}
\text{mag}_{down} &= -v_z \times \text{clip}(-v_z \times 0.3, 0, 0.5) &&\text{(向下幅度)} \\
\sigma_{down} &= \frac{1}{1 + e^{(v_z + 0.2) / 0.2}} &&\text{(向下激活)} \\
r_{down} &= \text{mag}_{down} \times \sigma_{down} &&\text{(向下惩罚)}
\end{aligned}
$$
**权重**1.0
#### 3. 挡板高度违规惩罚
**设计意义**:对挡板偏离原位过远(>0.1 m施加强惩罚确保挡板不会长时间停留在高位。
**计算公式**
$$
\begin{aligned}
\text{viol}_{height} &= \max(0, \text{err}_{home} - 0.1) &&\text{(违规量)} \\
r_{violation} &= -20.0 \times \text{viol}_{height} &&\text{(强惩罚)}
\end{aligned}
$$
**权重**1.0
#### 4. 动作变化率惩罚
**设计意义**:惩罚动作的剧烈变化,鼓励平滑的控制策略。
**计算公式**
$$
\begin{aligned}
r_{action} &= -\|\mathbf{a}_t - \mathbf{a}_{t-1}\|^2 &&\text{L2 惩罚)} \\
\\
\text{其中:} \quad &\mathbf{a}_t \in \mathbb{R}^6 &&\text{(当前动作向量)}
\end{aligned}
$$
**权重**$10^{-4}$
#### 5. 关节速度惩罚
**设计意义**:惩罚过高的关节速度,鼓励节能和平滑的运动。
**计算公式**
$$
\begin{aligned}
r_{joint\_vel} &= -\sum_{i=1}^{6} \dot{q}_i^2 &&\text{(速度平方和惩罚)} \\
\\
\text{其中:} \quad &\dot{\mathbf{q}} = [\dot{q}_1, \dot{q}_2, \dot{q}_3, \dot{q}_4, \dot{q}_5, \dot{q}_6]^T &&\text{(关节角速度向量)}
\end{aligned}
$$
**权重**$10^{-4}$
### 总奖励计算
$$
\begin{aligned}
R_{total} = &\ 2.0 \cdot r_{pos} \\
&+ 1.0 \cdot r_{out} \\
&+ 2.0 \cdot r_{vel} \\
&+ 4.5 \cdot r_h \\
&+ 1.0 \cdot r_{progress} \\
&+ 1.5 \cdot r_{controlled} \\
&+ 0.8 \cdot r_{bounce} \\
&+ 0.3 \cdot r_{high} \\
&+ 0.6 \cdot r_{align} \\
&+ 1.5 \cdot r_{home} \\
&+ 1.0 \cdot r_{excess} \\
&+ 1.0 \cdot r_{down} \\
&+ 1.0 \cdot r_{violation} \\
&+ 10^{-4} \cdot r_{action} \\
&+ 10^{-4} \cdot r_{joint\_vel}
\end{aligned}
$$
---
@@ -89,7 +366,43 @@ Bounce Ball 是一个单臂机器人操作任务,使用 6 自由度的配天 A
- **球掉落**:球的 z 坐标 < 0.05m(接近地面)
- **球过高**:球的 z 坐标 > 目标高度 + 1.0m(失去控制)
- **水平偏离过远**:球的 x 坐标绝对值 > 1.5m
- **水平偏离过远**:球的 x 或 y 坐标绝对值 > 1.5m
- **关节速度过高**:任一关节角速度 > 2π rad/s360°/s
- **超时**Episode 时长超过最大允许时间
---
## 初始状态
### 机器人初始化
**关节角度**
- 默认角度:[0°, 40°, 110°, 0°, -60°, 0°]
- 随机噪声:每个关节在 [-0.1, 0.1] 弧度范围内添加均匀随机噪声
**关节速度**
- 初始化为零,带有小幅随机噪声
### 球初始化
**位置**
- 基准位置:配置文件中的 `ball_init_pos`(默认 [0.58856, 0, 0.45] m
- 随机噪声:在 [-0.01, 0.01] m 范围内添加均匀随机噪声
**速度**
- 初始化为零
**姿态**
- 四元数:[0, 0, 0, 1](单位四元数,无旋转)
### 目标高度
每个环境的目标高度在 [0.4, 0.6] m 范围内随机采样,提升策略的泛化能力。
---
@@ -123,8 +436,14 @@ uv run scripts/play.py --env bounce_ball
## 预期训练结果
1. 连续弹跳:能够实现 3 次以上的连续弹跳
2. 位置控制:球的水平位置x 坐标)稳定在目标位置 ± 0.05m 范围内
3. 高度控制:球的高度稳定在目标高度 0.8 ± 0.1m 范围内
4. 速度控制球的向上速度保持在合理范围0.1-1.5 m/s
5. 稳定控制:能够持续 20 秒的稳定弹跳而不掉落
1. **连续弹跳**:能够实现 3 次以上的连续弹跳
2. **位置控制**:球的水平位置稳定在目标位置 ± 0.05m 范围内
3. **高度控制**:球的高度稳定在目标高度 ± 0.1m 范围内
4. **速度控制**球的向上速度保持在合理范围0.1-1.5 m/s
5. **稳定控制**:能够持续 20 秒的稳定颠球而不触发终止条件
---
## 已知问题
- **JAX 后端训练效果不佳**:当前 JAX 版本的训练效果不理想。建议使用 PyTorch 后端进行该环境的训练以获得更好的效果。

View File

@@ -0,0 +1,169 @@
# 机械手抓球
Bring Ball 是 DeepMind Control Suite 中的 Manipulator 经典任务平面机械手带拇指与手指需要抓取球体并将其移动到目标球位置。MotrixLab 当前提供 1 个 Bring Ball 环境:
- `dm-manipulator-bring-ball`:抓取球体并移动到目标位置
```{video} /_static/videos/bring-ball.mp4
:poster: _static/images/poster/bring-ball.jpg
:nocontrols:
:autoplay:
:playsinline:
:muted:
:loop:
:width: 100%
```
---
## 任务描述
Bring Ball 是一个二维平面x-z内的抓取与搬运任务
- 机械手包含 4 个手臂关节(`arm_root`、`arm_shoulder`、`arm_elbow`、`arm_wrist`)以及拇指/手指关节
- 夹持通过腱 `grasp` 同时驱动 `thumb` 与 `finger` 关节闭合
- 球体可在平面内滑动(`ball_x`、`ball_z`)并绕 y 轴旋转(`ball_y`
- 目标球为 mocap 物体,位置在 reset 时随机采样
---
## 动作空间Action Space
| 项目 | 详细信息 |
| -------- | ------------------------------- |
| **类型** | `Box(-1.0, 1.0, (5,), float32)` |
| **维度** | 5 |
动作对应如下(控制信号施加在关节/腱上):
| 序号 | 动作含义 | 最小值 | 最大值 | 对应 XML 中名称 |
| ---: | ----------------------------- | :----: | :----: | :-------------: |
| 0 | 根部关节驱动 | -1 | 1 | `root` |
| 1 | 肩部关节驱动 | -1 | 1 | `shoulder` |
| 2 | 肘部关节驱动 | -1 | 1 | `elbow` |
| 3 | 腕部关节驱动 | -1 | 1 | `wrist` |
| 4 | 夹持驱动(拇指/手指耦合闭合) | -1 | 1 | `grasp` |
---
## 观察空间
| 项目 | 详细信息 |
| -------- | -------------------------------- |
| **类型** | `Box(-inf, inf, (41,), float32)` |
| **维度** | 41 |
观察向量由以下部分组成(按顺序):
| 部分 | 内容说明 | 维度 | 备注 |
| -------------- | --------------------------- | ---- | ------------------------------------ |
| **arm_pos** | 8 个关节角度的 `sin`/`cos` | 16 | 关节顺序见下表,`sin`/`cos` 交替排列 |
| **arm_vel** | 8 个关节角速度 | 8 | 顺序同 arm_pos |
| **touch** | 触觉传感器 `log(1 + touch)` | 5 | palm/finger/thumb/fingertip/thumbtip |
| **hand_pos** | 抓取点 `grasp` 的世界坐标 | 3 | x, y, z |
| **object_pos** | 球体位置 | 3 | x, y, z |
| **target_pos** | 目标球位置 | 3 | x, y, z |
| **rel** | `object_pos - target_pos` | 3 | 相对位置 |
| 序号 | 观察量范围 | 维度 | 备注 |
| ----- | ---------------------------------------------- | ---- | ----------------------------- |
| 0-15 | 8 个关节角度的 `sin`/`cos` 交替排列 | 16 | 关节顺序arm_root → thumbtip |
| 16-23 | 8 个关节角速度 | 8 | 顺序同上 |
| 24-28 | 触觉palm, finger, thumb, fingertip, thumbtip | 5 | `log(1 + touch)` |
| 29-31 | grasp 位置 (x, y, z) | 3 | hand_pos |
| 32-34 | 球体位置 (x, y, z) | 3 | object_pos |
| 35-37 | 目标球位置 (x, y, z) | 3 | target_pos |
| 38-40 | 球体相对目标位置 (x, y, z) | 3 | rel |
关节顺序为:`arm_root`、`arm_shoulder`、`arm_elbow`、`arm_wrist`、`finger`、`fingertip`、`thumb`、`thumbtip`。
---
## 奖励函数设计
Bring Ball 使用 shaped 奖励,由多个子项加权组合,并加入惩罚项:
```python
# R1: Reach - 手指接近球
r_reach = tolerance(avg_tip_dist)
# R2: Orient - 手掌朝向球体
r_orient = clip(1 - orient_bound + dot(hand_dir, unit_vec_to_ball), 0..1)
# R3: Pause - 靠近球体时抑制臂部抖动
r_pause = tolerance(arm_speed_step) * is_close_to_ball
# R4: Close - 夹持动作与接触条件联合
r_close = r_close_intent * (approach_or_grasp)
# R5: Lift & Transport - 抬升高度 + 接近目标
r_lift_height = tolerance(ball_z)
r_transport = tolerance(move_dist_to_target)
r_lift = mix(r_lift_height, r_transport)
# Precision/Progress - 目标精度与移动进度
r_precision = tolerance(move_dist_to_target, gaussian)
r_progress = (prev_dist - curr_dist) * scale
# Penalty - 侧面接触与悬停惩罚
penalty_side + penalty_hover
```
默认权重(`BringBallCfg`
- reach 1.0、orient 1.5、pause 0.5、close 2.0、lift 6.0、precision 1.0
- lift 内部由 `lift_height_weight` 与 `transport_weight` 组合
- 进度奖励由 `transport_progress_scale` 控制
---
## 初始状态
- **手臂初始化**:默认使用模型初始姿态(`randomize_arm=False`),拇指/手指对称
- **目标位置**`x ∈ [-0.4, 0.4]``z ∈ [0.1, 0.4]``y = 0.001`
- **球体位置**`x ∈ [-0.4, 0.4]``z ∈ [0.2, 0.7]`,并与手部保持最小距离
- **物理稳定**reset 后会进行若干步 settle`settle_steps=300`
---
## Episode 终止条件
- 若观测中出现 `NaN` 值则终止
---
## 使用指南
### 1. 环境预览(随机动作)
```bash
uv run scripts/view.py --env dm-manipulator-bring-ball
```
### 2. 开始训练
建议显式指定训练后端JAX / PyTorch 二选一):
```bash
uv run scripts/train.py --env dm-manipulator-bring-ball --train-backend torch
```
### 3. 查看训练进度
```bash
uv run tensorboard --logdir runs/dm-manipulator-bring-ball
```
### 4. 测试训练结果
```bash
uv run scripts/play.py --env dm-manipulator-bring-ball
```
---
## 预期训练结果
1. 机械手能稳定接近并夹持球体
2. 球体被抬离地面并保持稳定高度
3. 球体最终能稳定到达目标球附近

View File

@@ -127,5 +127,6 @@ uv run scripts/play.py --env dm-cheetah
## 预期训练结果
1. 接近或超过 30.0 m/s 的稳定水平速度
2. 保持躯干直立且步态协调
1. 接近或超过 10.0 m/s 的稳定水平速度奔跑
2. 保持躯体稳定性且步态协调,长距离奔跑不摔倒
3. 奔跑姿态接近真实猎豹,奔跑过程具有伸展感

View File

@@ -0,0 +1,193 @@
# Finger 机械手指
Finger 是 DeepMind Control Suite 中的经典操控任务一个由两段连杆组成的“手指”通过施加关节力矩与旋转拨片spinner交互。MotrixLab 当前提供了 3 个 Finger 相关环境:
```{video} /_static/videos/dm_finger_spin.mp4
:poster: _static/images/poster/dm_finger_spin.jpg
:nocontrols:
:autoplay:
:playsinline:
:muted:
:loop:
:width: 100%
```
```{video} /_static/videos/dm_finger_turn.mp4
:poster: _static/images/poster/dm_finger_turn.jpg
:nocontrols:
:autoplay:
:playsinline:
:muted:
:loop:
:width: 100%
```
- `dm-finger-spin`:让 spinner 持续向指定方向旋转
- `dm-finger-turn-easy`:将 spinner 的顶端tip对准目标点较大目标半径
- `dm-finger-turn-hard`:同 Turn但目标半径更小
---
## 任务描述
Finger 是一个二维平面x-z内的手指与旋转拨片交互任务
- 手指有 2 个受控关节:`proximal`、`distal`
- spinner 通过关节 `hinge` 转动,`tip` 表示 spinner 顶端位置
- Turn 任务会在 spinner 周围随机采样一个目标点target
---
## 动作空间Action Space
| 项目 | 详细信息 |
| -------- | ------------------------------- |
| **类型** | `Box(-1.0, 1.0, (2,), float32)` |
| **维度** | 2 |
动作对应如下:
| 序号 | 动作含义(施加在关节的力矩) | 最小值 | 最大值 | 对应 XML 中名称 |
| ---: | ---------------------------- | :----: | :----: | :-------------: |
| 0 | 近端关节 `proximal` 驱动扭矩 | -1 | 1 | `proximal` |
| 1 | 远端关节 `distal` 驱动扭矩 | -1 | 1 | `distal` |
---
## 观察空间
Finger 环境的观测以 dm_control 的 observation dict 为参考,但在 MotrixLab 中被拼成一个向量。
### Spin 观察空间
| 项目 | 详细信息 |
| -------- | ------------------------------- |
| **类型** | `Box(-inf, inf, (9,), float32)` |
| **维度** | 9 |
组成如下(按顺序):
| 部分 | 内容说明 | 维度 | 备注 |
| ------------ | --------------------------------------------- | ---- | ----------------------------- |
| **position** | `qpos(proximal, distal)` + `tip_xz` | 4 | tip 相对 spinner 的 x、z 位置 |
| **velocity** | `qvel(proximal, distal, hinge)` | 3 | hinge 角速度用于 Spin 奖励 |
| **touch** | `log(1 + touch_top)`、`log(1 + touch_bottom)` | 2 | 触觉传感器的对数压缩 |
| 序号 | 观察量 | 最小值 | 最大值 | XML/Sensor 名称 | 类型 (单位) |
| ---- | ---------------------------------- | ------ | ------ | ----------------------- | -------------- |
| 0 | `proximal` 关节角度 | -Inf | Inf | `proximal` | 角度 (rad) |
| 1 | `distal` 关节角度 | -Inf | Inf | `distal` | 角度 (rad) |
| 2 | tip 相对 spinner 的 x 位移 | -Inf | Inf | `framepos(tip/spinner)` | 位置 (m) |
| 3 | tip 相对 spinner 的 z 位移 | -Inf | Inf | `framepos(tip/spinner)` | 位置 (m) |
| 4 | `proximal` 角速度 | -Inf | Inf | `proximal_velocity` | 角速度 (rad/s) |
| 5 | `distal` 角速度 | -Inf | Inf | `distal_velocity` | 角速度 (rad/s) |
| 6 | spinner 的 `hinge` 角速度 | -Inf | Inf | `hinge_velocity` | 角速度 (rad/s) |
| 7 | 触觉(上侧)`log(1 + touchtop)` | -Inf | Inf | `touchtop` | 无量纲 |
| 8 | 触觉(下侧)`log(1 + touchbottom)` | -Inf | Inf | `touchbottom` | 无量纲 |
### Turn 观察空间
| 项目 | 详细信息 |
| -------- | -------------------------------- |
| **类型** | `Box(-inf, inf, (12,), float32)` |
| **维度** | 12 |
相较 Spin 额外增加:
| 部分 | 内容说明 | 维度 | 备注 |
| ------------------- | -------------------------------- | ---- | ------------------------- |
| **target_position** | target 相对 spinner 的 x、z 坐标 | 2 | target 在 reset 时采样 |
| **dist_to_target** | tip 到 target 球面距离(带符号) | 1 | 负值表示 tip 落在目标球内 |
向量最后 3 个维度为:`target_x`, `target_z`, `dist_to_target`。
---
## 奖励函数设计
### Spin
在 dm_control 中Spin 的稀疏奖励通常由 spinner 的角速度阈值触发。MotrixLab 默认使用更易训练的 dense/shaped 奖励,并同时在 info 中记录稀疏版本:
```python
# hinge_velocity 为 spinner 关节角速度
spin_sparse = 1 if hinge_velocity <= -15 else 0
# shaped: clip(-hinge_velocity / 15, 0..1)
spin = clip(-hinge_velocity / 15, 0, 1)
```
### TurnEasy / Hard
Turn 的核心是 tip 触达并对准目标点:目标点位于 spinner 周围一圈,目标球半径在 easy/hard 中不同。
- `turn_sparse = 1` 当 tip 进入目标球内部(`dist_to_target <= 0`
- 默认 shaped 奖励以 `dist_to_target` 的指数衰减为主,并额外加入“靠近 spinner、增加接触、抑制动作抖动”等项最终裁剪到 `[0, 1]`
---
## 初始状态
- `proximal`、`distal` 关节角:在各自关节限制范围内均匀采样
- spinner 的 `hinge` 角:`[-pi, pi]` 均匀采样
- Turn 任务:每个 episode 在 spinner 周围采样 target角度均匀采样位置落在 x-z 平面)
## Episode 终止条件
- 若观测中出现 `NaN` 值则终止
---
## 使用指南
### 1. 环境预览(随机动作)
```bash
uv run scripts/view.py --env dm-finger-spin
```
```bash
uv run scripts/view.py --env dm-finger-turn-easy
```
```bash
uv run scripts/view.py --env dm-finger-turn-hard
```
### 2. 开始训练
建议显式指定训练后端JAX / PyTorch 二选一):
```bash
uv run scripts/train.py --env dm-finger-spin --train-backend torch
```
```bash
uv run scripts/train.py --env dm-finger-turn-easy --train-backend torch
```
```bash
uv run scripts/train.py --env dm-finger-turn-hard --train-backend torch
```
### 3. 查看训练进度
```bash
uv run tensorboard --logdir runs/dm-finger-spin
```
### 4. 测试训练结果
`scripts/play.py` 默认会自动在 `runs/{env-name}/` 下寻找最新的 `best_agent.*`,也可以用 `--policy` 显式指定:
```bash
uv run scripts/play.py --env dm-finger-turn-hard
```
---
## 预期训练结果
1. `dm-finger-spin`spinner 能稳定持续向目标方向旋转hinge_velocity 达到阈值附近)
2. `dm-finger-turn-easy`:手指能稳定接触并将 tip 对准目标点(成功率较高、抖动较小)
3. `dm-finger-turn-hard`:能对准更小目标,但更容易出现“接触不足/动作抖动”的训练难点

View File

@@ -0,0 +1,236 @@
# 三维人形机器人
三维人形机器人Humanoid是 DeepMind Control Suite 中的经典双足行走任务。其目标是训练一个模拟的三维人形机器人,通过控制其关节力矩,实现站立、行走和奔跑。
```{video} /_static/videos/dm_humanoid_run.mp4
:poster: _static/images/poster/dm_humanoid_run.jpg
:nocontrols:
:autoplay:
:playsinline:
:muted:
:loop:
:width: 100%
```
## 任务描述
Humanoid 是一个三维空间的双足人形机器人任务。机器人由头部、躯干、双臂和双腿组成,拥有 21 个受控关节(执行器),智能体通过向这些关节施加扭矩作为动作,让机器人实现站立平衡、向前行走或快速奔跑。该任务要求协调的双足步态、平衡控制和三维空间姿态稳定能力。
---
## 动作空间Action Space
| 项目 | 详细信息 |
| -------- | -------------------------------- |
| **类型** | `Box(-1.0, 1.0, (21,), float32)` |
| **维度** | 21 |
动作对应如下:
| 序号 | 动作含义(施加在关节的力矩) | 最小值 | 最大值 | 对应 XML 中名称 |
| ---: | ---------------------------- | :----: | :----: | :---------------- |
| 0 | 腹部 Y 轴旋转关节驱动扭矩 | -1.0 | 1.0 | `abdomen_y` |
| 1 | 腹部 Z 轴旋转关节驱动扭矩 | -1.0 | 1.0 | `abdomen_z` |
| 2 | 腹部 X 轴旋转关节驱动扭矩 | -1.0 | 1.0 | `abdomen_x` |
| 3 | 右髋关节 X 轴驱动扭矩 | -1.0 | 1.0 | `right_hip_x` |
| 4 | 右髋关节 Z 轴驱动扭矩 | -1.0 | 1.0 | `right_hip_z` |
| 5 | 右髋关节 Y 轴驱动扭矩 | -1.0 | 1.0 | `right_hip_y` |
| 6 | 右膝关节驱动扭矩 | -1.0 | 1.0 | `right_knee` |
| 7 | 右踝关节 X 轴驱动扭矩 | -1.0 | 1.0 | `right_ankle_x` |
| 8 | 右踝关节 Y 轴驱动扭矩 | -1.0 | 1.0 | `right_ankle_y` |
| 9 | 左髋关节 X 轴驱动扭矩 | -1.0 | 1.0 | `left_hip_x` |
| 10 | 左髋关节 Z 轴驱动扭矩 | -1.0 | 1.0 | `left_hip_z` |
| 11 | 左髋关节 Y 轴驱动扭矩 | -1.0 | 1.0 | `left_hip_y` |
| 12 | 左膝关节驱动扭矩 | -1.0 | 1.0 | `left_knee` |
| 13 | 左踝关节 X 轴驱动扭矩 | -1.0 | 1.0 | `left_ankle_x` |
| 14 | 左踝关节 Y 轴驱动扭矩 | -1.0 | 1.0 | `left_ankle_y` |
| 15 | 右肩关节 1 驱动扭矩 | -1.0 | 1.0 | `right_shoulder1` |
| 16 | 右肩关节 2 驱动扭矩 | -1.0 | 1.0 | `right_shoulder2` |
| 17 | 右肘关节驱动扭矩 | -1.0 | 1.0 | `right_elbow` |
| 18 | 左肩关节 1 驱动扭矩 | -1.0 | 1.0 | `left_shoulder1` |
| 19 | 左肩关节 2 驱动扭矩 | -1.0 | 1.0 | `left_shoulder2` |
| 20 | 左肘关节驱动扭矩 | -1.0 | 1.0 | `left_elbow` |
---
## 观察空间
| 项目 | 详细信息 |
| -------- | -------------------------------- |
| **类型** | `Box(-inf, inf, (73,), float32)` |
| **维度** | 73 |
Humanoid 环境的观测空间由以下部分组成(按顺序):
| 部分 | 内容说明 | 维度 | 备注 |
| ------------------ | ------------------------------------- | ---- | ------------------------------------------------- |
| **joint_angles** | 各关节角度(排除根关节的 7 个自由度) | 22 | 22 个关节的角度信息 |
| **head_height** | 头部高度 | 1 | 头部相对于地面的高度 |
| **extremities** | 四肢末端位置(相对于躯干) | 12 | 左手、左脚、右手、右脚的位置(各 3 维,按此顺序) |
| **torso_vertical** | 躯干垂直方向向量 | 3 | 躯干在局部坐标系中的垂直方向 |
| **com_vel** | 质心线速度 | 3 | 躯干子树的线速度 |
| **qvel** | 所有关节和根部的速度信息 | 29 | 包括根关节的 6 个自由度 |
| **target_local** | 目标方向(局部坐标系) | 3 | 目标方向在躯干局部坐标系中的表示 |
---
## 奖励函数设计
Humanoid 的奖励函数根据任务类型(站立、行走、奔跑)有所不同,但都包含以下核心组件:
### 姿态奖励Posture Reward
```python
# 头部高度奖励:保持头部在目标高度(标准站立高度的 95%,约 1.33m)以上
stand_reward = tolerance(head_height, bounds=(stand_height * 0.95, inf), margin=0.5)
# 躯干直立奖励:保持躯干直立
upright_reward = tolerance(torso_upright, bounds=(0.9, inf), sigmoid="linear", margin=0.9)
# 盆骨高度奖励:保持盆骨在合理高度(标准站立高度的 60%,约 0.84m)以上
pelvis_height_reward = tolerance(pelvis_height, bounds=(stand_height * 0.6, inf), sigmoid="linear", margin=stand_height * 0.6)
# 姿态奖励 = 头部高度奖励 × 躯干直立奖励 × 盆骨高度奖励
posture_reward = stand_reward * upright_reward * pelvis_height_reward
```
### 速度奖励Speed Reward
根据任务类型,速度奖励的计算方式不同:
**站立任务move_speed <= 0**
```python
# 速度奖励:保持接近零速度
speed_reward = tolerance(actual_speed, bounds=(0, 0), margin=1.0, value_at_margin=0.01)
```
**行走任务0 < move_speed <= 3.0**
```python
# 速度奖励在目标方向X 轴正方向)上达到目标速度(默认 1.0 m/s
actual_speed = dot(com_vel[:2], target_direction[:2]) # 速度在目标方向上的投影
speed_reward = tolerance(actual_speed, bounds=(move_speed, move_speed), margin=move_speed, sigmoid="linear")
```
**奔跑任务move_speed > 3.0**
```python
# 速度奖励:在目标方向上达到目标速度(默认 10.0 m/s以上
actual_speed = dot(com_vel[:2], target_direction[:2])
speed_reward = tolerance(actual_speed, bounds=(move_speed, inf), margin=move_speed, sigmoid="linear")
```
### 能量奖励Energy Reward
```python
energy_reward = exp(-energy_coef * mean(ctrls ^ 2))
```
### 步态奖励Gait Reward
```python
# 躯干朝向奖励:躯干正对目标方向
torso_heading_reward = tolerance(dot(torso_forward, target_dir), bounds=(0.9, 1.0), margin=0.3, sigmoid="linear")
# 头部朝向奖励:头部正对目标方向
head_heading_reward = tolerance(dot(head_forward, target_dir), bounds=(0.9, 1.0), margin=0.3, sigmoid="linear")
# 盆骨朝向奖励:盆骨正对目标方向
pelvis_yaw_reward = tolerance(dot(pelvis_forward, target_dir), bounds=(0.9, 1.0), margin=0.3, sigmoid="linear")
# 盆骨水平奖励:盆骨保持水平
pelvis_level_reward = tolerance(pelvis_up, bounds=(0.9, 1.0), margin=0.3, sigmoid="linear")
# 足部高度奖励:足部保持贴近地面
feet_height_reward = tolerance(max_foot_height, bounds=(0.0, 0.3), margin=0.5, sigmoid="quadratic")
# 步态奖励 = 所有朝向和姿态奖励的乘积
gait_reward = torso_heading_reward * head_heading_reward * pelvis_yaw_reward * pelvis_level_reward * feet_height_reward
```
### 总奖励
```python
total_reward = posture_reward * speed_reward * energy_reward * gait_reward
```
---
## 初始状态
- **机器人位置**:躯干初始高度为 1.33 米(标准站立高度的 95%
- **机器人姿态**:躯干保持直立,四元数设置为 (1.0, 0.0, 0.0, 0.0)
- **关节角度**:在关节限位范围内随机初始化
- 躯干/髋部基础关节在较小范围内随机化±15 度)
- 腿部关节:对称初始化,确保左右腿独立随机化,膝盖初始弯曲
- 手臂关节:对称初始化,使用关节限位的中间 80% 范围
- **初始速度**:所有关节速度和线速度初始化为接近零的小随机值(-0.01 到 0.01
- **初始控制**:所有执行器控制量初始化为接近零的小随机值(-0.02 到 0.02
## Episode 终止条件
- 机器人状态观测值出现异常数值NaN 或 Inf
- 头部高度过低:头部高度低于标准站立高度的 50%0.7 米)
- 躯干倾斜过大:躯干垂直分量小于 0.2(躯干严重倾斜)
- 速度异常:任何关节速度的绝对值超过 200.0 rad/s 或 m/s
- Episode 最大时长25 秒
---
## 使用指南
### 1. 环境预览
```bash
uv run scripts/view.py --env dm-humanoid-stand
uv run scripts/view.py --env dm-humanoid-walk
uv run scripts/view.py --env dm-humanoid-run
```
### 2. 开始训练
```bash
uv run scripts/train.py --env dm-humanoid-stand
uv run scripts/train.py --env dm-humanoid-walk
uv run scripts/train.py --env dm-humanoid-run
```
### 3. 查看训练进度
```bash
uv run tensorboard --logdir runs/dm-humanoid-walk
```
### 4. 测试训练结果
```bash
uv run scripts/play.py --env dm-humanoid-stand
uv run scripts/play.py --env dm-humanoid-walk
uv run scripts/play.py --env dm-humanoid-run
```
---
## 预期训练结果
### 站立任务 (dm-humanoid-stand)
1. 头部高度保持在 1.3-1.5m 范围
2. 躯干直立角度偏差小于 15 度
3. 能够稳定站立不倒
4. 速度接近零,无明显移动
### 行走任务 (dm-humanoid-walk)
1. 实际行走速度接近 1.0 m/s
2. 步态协调,无明显摔倒
3. 能够持续稳定行走
4. 躯干和头部朝向目标方向
### 奔跑任务 (dm-humanoid-run)
1. 奔跑速度达到 4.0-10.0 m/s
2. 出现飞行相(双脚同时离地)
3. 步态协调稳定
4. 能够保持高速奔跑姿态

View File

@@ -0,0 +1,138 @@
# 单摆训练示例
单摆Pendulum是经典的单关节摆起并倒立保持任务目标是用一个电机扭矩把摆甩起并稳定在倒立位置。
```{video} /_static/videos/pendulum.mp4
:poster: _static/images/poster/pendulum.jpg
:nocontrols:
:autoplay:
:playsinline:
:muted:
:loop:
:width: 100%
```
---
## 任务描述
单摆由一段杆体和一个铰接关节组成关节由单个电机驱动gear 可配置)。电机施加的扭矩使摆杆在平面内旋转,实现从任意初始角度的摆起、倒立和保持。关节力矩受限于 ctrlrange通过控制扭矩大小与方向策略需要完成能量累积swing-up并在倒立位置维持平衡同时抑制角速度带来的震荡。
---
## 动作空间
| 项目 | 详情 |
| -------- | ------------------------------- |
| **类型** | `Box(-1.0, 1.0, (1,), float32)` |
| **维度** | 1 |
---
## 观察空间
| 项目 | 详情 |
| -------- | ------------------------------- |
| **类型** | `Box(-inf, inf, (3,), float32)` |
| **维度** | 3 |
顺序:`cos(theta), sin(theta), 角速度`。
---
## 奖励设计
- 倒立奖励:鼓励角度围绕 π(倒立)
- 能量 shaping能量接近倒立位置
- 惩罚:`角速度^2`、`ctrl^2`、`(ctrl - prev_ctrl)^2`,抑制震荡与过猛动作
---
## 初始状态
- 角度随机于 `[-pi, pi]`
- 角速度小噪声(如配置)
- 控制历史 `prev_ctrl` 初始化为 0
## Episode 终止条件
- 无跌倒终止;仅 NaN 检查
- Episode 长度由 `max_episode_seconds` 限制
---
### 1. 环境预览
```bash
uv run scripts/view.py --env pendulum
```
### 2. 开始训练
```bash
# 默认参数训练
uv run scripts/train.py --env pendulum
# 自定义并行环境数
uv run scripts/train.py --env pendulum --num-envs 1024
# 开启训练时渲染
uv run scripts/train.py --env pendulum --render
```
### 3. 查看训练进度
```bash
uv run tensorboard --logdir runs/pendulum
```
### 4. 测试训练结果
```bash
# 自动寻找最新/最优策略(推荐)
uv run scripts/play.py --env pendulum
# 手动指定策略文件
uv run scripts/play.py --env pendulum --policy runs/pendulum/nn/best_policy.pickle
```
> **提示**:策略默认在 `runs/pendulum/` 下自动发现,可用 `--policy` 手动指定。
---
## 配置参数
### 环境配置(示例)
```python
@dataclass
class PendulumEnvCfg(EnvCfg):
model_file: str = ".../pendulum.xml" # MJCF 模型,默认 gear=5
max_episode_seconds: float = 20.0
sim_dt: float = 0.0125
ctrl_dt: float = 0.025
```
### 训练配置(示例 PPO
```python
@rlcfg("pendulum")
@dataclass
class PendulumPPO(PPOCfg):
seed: int = 42
max_env_steps: int = 10_000_000
num_envs: int = 1024
learning_rate: float = 3e-4
rollouts: int = 32
learning_epochs: int = 5
mini_batches: int = 4
policy_hidden_layer_sizes: tuple[int, ...] = (64, 64)
value_hidden_layer_sizes: tuple[int, ...] = (64, 64)
```
---
## 预期训练结果
1. 摆能主动摆起并停留在倒立附近
2. 倒立处的震荡由角速度与控制变化惩罚抑制

View File

@@ -0,0 +1,370 @@
# Shadow Hand 立方体重定向
## 概述
本文档详细描述了基于 Shadow Hand 灵巧手的立方体重定向任务环境。该任务是机器人操作领域的经典基准测试,要求机器人在手中重新定向立方体以匹配随机目标姿态。
```{video} /_static/videos/shadow_hand_repose.mp4
:poster: _static/images/poster/shadow_hand_repose.jpg
:nocontrols:
:autoplay:
:playsinline:
:muted:
:loop:
:width: 100%
```
---
## 环境描述
Shadow Hand 立方体重定向任务基于真实的 Shadow Hand 24 自由度灵巧手构建,旨在训练机器人通过精细的多指协调,将手中的立方体旋转到目标姿态。
### 机器人结构
Shadow Hand 是一个高仿真的 24 自由度灵巧手,由以下主要部分组成:
- **手掌Palm**:手的基础结构,固定在基座上
- **5 个手指**
- **拇指Thumb**5 自由度,包括 CMC 旋转、MCP、IP 关节
- **食指Index**4 自由度,包括 MCP、PIP、DIP 关节
- **中指Middle**4 自由度,包括 MCP、PIP、DIP 关节
- **无名指Ring**4 自由度,包括 MCP、PIP、DIP 关节
- **小指Little**4 自由度,包括 MCP、PIP、DIP 关节
- **执行器配置**20 个驱动关节4 个耦合关节由其他关节驱动)
### 手指关节详情
每个手指(除拇指外)包含:
- **MCP 关节**掌指关节2 自由度(外展/内收 + 屈曲)
- **PIP 关节**近端指间关节1 自由度(屈曲)
- **DIP 关节**远端指间关节1 自由度(屈曲)
拇指包含:
- **CMC 关节**腕掌关节2 自由度
- **MCP 关节**掌指关节1 自由度
- **IP 关节**指间关节1 自由度
### 环境物体
- **立方体**50mm × 50mm × 50mm 的正方体
- 质量:约 0.028 kg
- 摩擦系数1.2
- 初始位置:手掌中心上方 `(0.33, 0.00, 0.295)` 米
- **目标可视化**半透明目标姿态指示器mocap body
### 任务目标
机器人需要完成以下操作目标:
1. **保持抓握**:维持立方体在手中的稳定抓握
2. **感知目标**:观察目标姿态(可视化指示器)
3. **精细操作**:通过多指协调旋转立方体
4. **姿态对齐**:将立方体姿态旋转至目标姿态(容差 ±0.1 弧度)
---
## 动作空间
动作空间为 `Box(-1, 1, (20,), float32)`,表示施加到 20 个驱动关节的位置控制指令(归一化)。
### 动作处理流程
```python
# 1. 缩放到执行器限制
targets = scale(actions, lower_limits, upper_limits)
# 2. 动作平滑(可选)
if act_moving_average < 1.0:
targets = α * targets + (1-α) * prev_actions
# 3. 裁剪到限制
targets = clip(targets, lower_limits, upper_limits)
# 4. 应用控制
actuator_ctrls = targets
```
### 动作维度详细说明
| 编号 | 手指 | 关节 | 自由度 | 说明 |
| ----- | ------ | ----- | ------ | ------------- |
| 0-4 | 拇指 | J0-J4 | 5 | CMC, MCP, IP |
| 5-8 | 食指 | J0-J3 | 4 | MCP, PIP, DIP |
| 9-12 | 中指 | J0-J3 | 4 | MCP, PIP, DIP |
| 13-16 | 无名指 | J0-J3 | 4 | MCP, PIP, DIP |
| 17-20 | 小指 | J0-J3 | 4 | MCP, PIP, DIP |
---
## 观测空间
观测空间为 `Box(-inf, inf, (157,), float32)`,包含机器人的本体感知信息、立方体状态、目标状态和指尖状态。
### 观测组成部分
观测向量由以下部分组成(按顺序):
#### 1. 手部关节状态48 维)
- **关节位置24 维)**:未缩放的原始关节角度
- **关节速度24 维)**:缩放 0.2 倍的关节角速度
#### 2. 立方体状态17 维)
- **位置3 维)**:世界坐标系中的立方体位置 `(x, y, z)`
- **姿态4 维)**:四元数 `(x, y, z, w)`
- **线速度3 维)**:立方体线速度
- **角速度3 维)**:缩放 0.2 倍的角速度
- **归一化因子**:速度观测乘以 `vel_obs_scale = 0.2`
#### 3. 目标状态11 维)
- **目标位置3 维)**:固定在 `(0.33, 0.00, 0.295)`
- **目标姿态4 维)**:随机采样的目标四元数
- **相对旋转4 维)**:立方体到目标的相对四元数
#### 4. 指尖状态65 维)
5 个指尖的状态,每个指尖 13 维:
- **位置3 维)**:指尖在笛卡尔空间的位置
- **姿态4 维)**:指尖四元数
- **速度6 维)**:线速度和角速度
**指尖链接名称**
- `rh_ffdistal`:食指指尖
- `rh_mfdistal`:中指指尖
- `rh_rfdistal`:无名指指尖
- `rh_lfdistal`:小指指尖
- `rh_thdistal`:拇指指尖
#### 5. 动作历史20 维)
- 上一步的动作值,用于策略的时间上下文
### 观测详细说明
| 编号 | 观测内容 | 维度 | 范围 | 单位 |
| ------- | ---------------------------- | ---- | ------------ | ------ |
| 0-23 | 手部关节位置(未归一化) | 24 | 关节限制范围 | rad |
| 24-47 | 手部关节速度(× 0.2 | 24 | ±π/2 | rad/s |
| 48-50 | 立方体位置 | 3 | 实数 | m |
| 51-54 | 立方体姿态(四元数 w,x,y,z | 4 | 单位范数 | 无量纲 |
| 55-57 | 立方体线速度 | 3 | 实数 | m/s |
| 58-60 | 立方体角速度(× 0.2 | 3 | 实数 | rad/s |
| 61-63 | 目标位置 | 3 | 固定值 | m |
| 64-67 | 目标姿态(四元数 w,x,y,z | 4 | 单位范数 | 无量纲 |
| 68-71 | 相对旋转(四元数 w,x,y,z | 4 | 单位范数 | 无量纲 |
| 72-136 | 指尖状态5×13 | 65 | - | - |
| 137-156 | 上一步动作 | 20 | [-1, 1] | 无量纲 |
---
## 奖励函数
奖励函数采用复合设计,包含多个奖励和惩罚项。
### 主要奖励项
1. **旋转对齐奖励**(核心目标)
```
rot_reward = rot_reward_scale / (|rot_dist| + rot_eps)
```
- **缩放系数**`1.0`
- **Epsilon**`0.1`
- **旋转距离计算**:使用四元数旋转距离公式
- **激励**:随着立方体姿态接近目标,奖励呈反比增长
2. **位置距离惩罚**
```
dist_reward = dist_reward_scale × goal_dist
```
- **缩放系数**`-10.0`
- **距离计算**:立方体到目标位置的欧氏距离
- **激励**:阻止立方体掉落,保持在目标位置附近
3. **动作正则化惩罚**
```
action_penalty = action_penalty_scale × ||actions||²
```
- **缩放系数**`-0.0002`
- **目的**:鼓励平滑、节能的运动
### 条件奖励
4. **成功奖励**
```
if |rot_dist| ≤ success_tolerance:
reward += reach_goal_bonus
```
- **奖励值**`2.0`
- **容差**`0.1` 弧度(约 5.7°)
- **目的**:达成目标对齐的稀疏奖励
5. **掉落惩罚**
```
if goal_dist ≥ fall_dist:
reward += fall_penalty
terminated = True
```
- **惩罚值**`0.0`(仅终止,无额外惩罚)
- **距离阈值**`0.24`
- **目的**:立方体掉落时终止回合
---
## 初始状态
### 手部初始化
**位置初始化:**
手掌固定在世界坐标系中,位置由模型文件确定。
**关节角度初始化:**
- 使用模型默认关节位置
- 添加均匀随机噪声:`[-0.2, 0.2]` 弧度
- 作用范围:所有 24 个手部自由度
**速度初始化:**
所有关节速度初始化为零。
### 立方体初始化
**位置初始化:**
- 固定位置:`(0.33, 0.00, 0.295)` 手掌中心上方)
- 添加均匀随机噪声:`[-0.01, 0.01]` ±1cm
**姿态初始化:**
- 使用 Shoemake 方法生成均匀分布的随机四元数
- 确保在 SO(3) 空间上的均匀采样
**速度初始化:**
所有线速度和角速度初始化为零。
### 目标初始化
**位置初始化:**
- 固定位置:`(0.33, 0.00, 0.295)`(与立方体初始位置相同)
**姿态初始化:**
- 使用 Shoemake 方法生成均匀分布的随机目标四元数
- 每次重置时重新采样
---
## 终止条件
回合在以下情况下终止:
1. **掉落终止**:立方体距离目标位置 ≥ `fall_dist`0.24m
2. **超时终止**:达到 `max_episode_steps`(默认 1000 步)
3. **NaN 保护**:检测到旋转距离或位置距离为 NaN
### 成功保持机制
环境使用连续成功计数器:
- 当满足旋转容差时,计数器递增
- 当达到 `max_consecutive_successes`50触发成功终止并重置目标
- 旋转容差:`0.1` 弧度
---
## 使用方法
### 训练
```bash
uv run scripts/train.py --env shadow-hand-repose
```
### 策略评估
```bash
uv run scripts/play.py --env shadow-hand-repose
```
### 环境可视化
```bash
uv run scripts/view.py --env shadow-hand-repose
```
### TensorBoard
```bash
uv run tensorboard --logdir runs/shadow-hand-repose
```
---
## 配置参数
### 环境参数
| 参数名 | 默认值 | 说明 |
| --------------------- | ------ | ------------------ |
| `max_episode_seconds` | 10.0 | 最大回合时长(秒) |
| `ctrl_dt` | 0.01 | 控制时间步(秒) |
| `max_episode_steps` | 1000 | 最大回合步数 |
| `num_hand_dofs` | 24 | 手部总自由度 |
| `num_actuators` | 20 | 驱动关节数量 |
### 奖励参数
| 参数名 | 默认值 | 说明 |
| ---------------------- | ------- | ---------------- |
| `dist_reward_scale` | -10.0 | 位置距离奖励 |
| `rot_reward_scale` | 1.0 | 旋转对齐奖励 |
| `rot_eps` | 0.1 | 旋转奖励 epsilon |
| `action_penalty_scale` | -0.0002 | 动作正则化 |
| `success_tolerance` | 0.1 | 成功容差(弧度) |
| `reach_goal_bonus` | 2.0 | 成功奖励 |
| `fall_dist` | 0.24 | 掉落距离阈值 |
| `fall_penalty` | 0.0 | 掉落惩罚 |
### 重置噪声参数
| 参数名 | 默认值 | 说明 |
| ---------------------- | ------ | ----------------------- |
| `reset_position_noise` | 0.01 | 立方体位置噪声(米) |
| `reset_dof_pos_noise` | 0.2 | 关节位置噪声(弧度) |
| `reset_dof_vel_noise` | 0.0 | 关节速度噪声(弧度/秒) |
### 观测缩放参数
| 参数名 | 默认值 | 说明 |
| --------------- | ------ | ---------------- |
| `vel_obs_scale` | 0.2 | 速度观测缩放因子 |
---
## 参考资料
该环境基于以下经典工作实现:
- **OpenAI Dactyl** (2018):首个成功的手内操作 sim-to-real 迁移
- **Isaac Gym** (2021):高性能 GPU 加速的物理仿真
- **Isaac Lab** (2023):模块化机器人学习框架

View File

@@ -0,0 +1,189 @@
# 容器部署
本文档介绍如何使用 Docker 容器化部署 MotrixLab以简化环境配置并实现快速部署。
## 前置要求
- **Docker****Docker Compose**: [安装文档](https://docs.docker.com/engine/install/)
- **NVIDIA Container Toolkit**: [安装文档](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html#installation)
- **NVIDIA GPU**: 支持 CUDA 12.8 的显卡
## 快速开始
### 1. 克隆项目仓库
```bash
git clone https://github.com/Motphys/MotrixLab.git
cd MotrixLab/docker
```
### 2. 使用 Docker Compose 启动
我们提供了完整的 `docker-compose.yml` 配置文件,支持一键启动训练和 TensorBoard 可视化服务。
```bash
# 启动训练和 TensorBoard 服务
docker compose up -d
```
这将启动以下服务:
- **motrixlab-training**: 训练容器,执行强化学习训练任务
- **motrixlab-tensorboard**: TensorBoard 可视化服务,通过浏览器访问 http://localhost:6006
### 3. 配置训练参数
您可以通过环境变量自定义训练配置:
```bash
# 设置训练后端jax 或 torch
export MOTRIX_TRAIN_BACKEND=jax
# 设置并行环境数量
export MOTRIX_NUM_ENVS=2048
# 设置训练环境名称
export MOTRIX_ENV=cartpole
# 启动服务
docker compose up -d
```
| 环境变量 | 默认值 | 说明 |
| :--------------------- | :--------- | :------------------------- |
| `MOTRIX_TRAIN_BACKEND` | `jax` | 训练后端:`jax``torch` |
| `MOTRIX_NUM_ENVS` | `2048` | 并行环境数量 |
| `MOTRIX_ENV` | `cartpole` | 训练环境名称 |
### 4. 查看训练进度
训练日志会自动保存到 Docker Volume `motrixlab-data` 中。您可以通过以下方式查看:
```bash
# 查看训练容器日志
docker logs -f motrixlab-training
# 访问 TensorBoard
# 浏览器打开: http://localhost:6006
```
### 5. 停止服务
```bash
# 停止所有服务
docker compose down
# 停止服务并删除数据卷
docker compose down -v
```
## 高级用法
### 构建 Docker 镜像
如果您需要自定义镜像,可以从源代码构建:
```bash
# 在项目根目录执行
cd docker
docker build -t motphys/motrixlab:latest .
```
### 运行单个容器
如果您只想运行训练容器而不使用 Docker Compose
```bash
docker run --gpus all \
-v $(pwd)/runs:/root/motrixlab/runs \
motphys/motrixlab:latest \
scripts/train.py --train-backend jax --num-envs 2048 --env cartpole
```
### 持久化训练结果
默认配置使用 Docker Volume `motrixlab-data` 保存训练结果。您可以将其挂载到主机目录:
```bash
# 修改 docker-compose.yml 中的 volumes 配置
volumes:
- ./runs:/root/motrixlab/runs
```
## 镜像说明
我们的 Docker 镜像基于 {bdg-primary-line}`NVIDIA CUDA 12.8.1` 运行时环境,预装了以下组件:
- **UV 包管理器**: 快速、可靠的依赖管理
- **SKRL**: 支持 JAX 和 PyTorch 后端的强化学习库
- **TensorBoard**: 训练过程可视化工具
- **MotrixSim**: 高性能物理仿真引擎
- **MotrixLab**: 完整的强化学习训练框架
镜像层构建过程:
1. **基础环境**: NVIDIA CUDA 12.8.1 Runtime + Ubuntu 24.04
2. **系统依赖**: 安装 UV 包管理器和必要的系统工具
3. **Python 依赖**: 使用 UV 缓存机制快速安装 Python 包
4. **项目代码**: 复制 MotrixLab 源代码并完成依赖安装
## 故障排查
### GPU 不可用
如果容器无法访问 GPU
```bash
# 检查 NVIDIA Docker Runtime
docker run --rm --gpus all nvidia/cuda:12.8.1-base-ubuntu24.04 nvidia-smi
# 确认 NVIDIA Container Toolkit 已正确安装
which nvidia-container-cli
```
### 存储空间不足
清理 Docker 缓存和未使用的镜像:
```bash
# 清理构建缓存
docker builder prune
# 删除未使用的镜像
docker image prune -a
# 清理所有未使用的资源
docker system prune -a
```
## 性能优化
### 使用 UV 缓存加速构建
Dockerfile 使用了 UV 的缓存挂载功能,可以显著加速重建过程:
```bash
# 利用 UV 缓存重新构建
docker build --cache-from motphys/motrixlab:latest -t motphys/motrixlab:latest .
```
### GPU 资源分配
您可以在 `docker-compose.yml` 中指定 GPU 使用数量:
```yaml
deploy:
resources:
reservations:
devices:
- driver: nvidia
device_ids: ["0", "1"] # 使用 GPU 0 和 1
capabilities: [gpu]
```
## 下一步
- 查看 [快速入门教程](hello_motrixlab.md) 了解 MotrixLab 基本用法
- 阅读 [训练示例](../demo/cartpole.md) 学习更多训练任务
- 探索 [基础框架](../tutorial/basic_frame.md) 深入理解框架架构

View File

@@ -5,6 +5,7 @@
:maxdepth: 1
getting_started/installation
getting_started/container_deployment
getting_started/hello_motrixlab
```
@@ -25,16 +26,22 @@ tutorial/training_and_result
:caption: 训练示例
:maxdepth: 1
demo/acrobot
demo/cartpole
demo/pendulum
demo/bounce_ball
demo/dm_walker
demo/dm_cheetah
demo/dm_hopper
demo/dm_reacher
demo/dm_finger
demo/dm_humanoid
demo/bring_ball
demo/locomotion_unitree_go1
demo/locomotion_unitree_go1_rough_terrain
demo/anymal_c
demo/franka_lift_cube
demo/franka_open_cabinet
demo/shadow_hand_repose
```