Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion docs/sphinx/source/en/2-user_guide/2-algorithms/3-sac.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ CPU and XPU training are unsupported; there is no alternate replay pipeline.

```bash
uv run train --algo sac --task g1_walk_flat --sim mujoco
uv run train --algo sac --task g1_walk_rough --sim motrix training.no_play=true
```

## Key Fields
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Manager-Based runtime. Unitree production variants live in the downstream
## Core reference tasks

- Go2 joystick: `go2_joystick_flat`
- G1 walking: `g1_walk_flat`, `g1_walk_rough`
- G1 walking: `g1_walk_flat`
- G1 motion tracking reference profiles: see {doc}`2-motion_tracking`

```bash
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ These three paths correspond to three lifecycle classes:
| --- | --- | --- | --- | --- | --- |
| `Go2JoystickFlat` | Hydra `events:` terms | Yes: owner YAML declares reset events | root-state reset + `pd_gains` kp/kd | none | `src/unilab/conf/ppo/task/go2_joystick_flat/base.yaml` |
| `G1WalkFlat` | Hydra `events:` terms | Yes: Hydra `EventTermCfg` + Manager-Based reset terms | root-state reset + kp/kd via `pd_gains` | none | `g1/manager_terms.py` |
| `G1WalkRough` | Hydra `events:` terms | Yes: same Manager-Based event terms as `G1WalkFlat` | root-state reset + kp/kd via `pd_gains` | none | `g1/manager_terms.py` |
| `G1MotionTracking` | Hydra command term | Yes: Hydra `MotionCommandCfg` + Manager-Based command reset | motion frame, root pose/velocity, and joint-position sampling | none | `motion_tracking/common/manager_terms.py` |
| `G1WBTObs` | Hydra `events:` terms | Yes: same motion command + Hydra `EventTermCfg` | motion reset plus mass/COM/PD/friction/encoder-bias events | interval velocity kick | `motion_tracking/g1/manager_terms.py` |
| `AllegroInhandRotation` | Hydra `events:` terms | Yes: Hydra `EventTermCfg` + Manager-Based reset term | entity-scoped hand/ball reset | none | `allegro_inhand/manager_terms.py` |
Expand All @@ -45,7 +44,6 @@ These three paths correspond to three lifecycle classes:
| --- | --- | --- | --- |
| `Go2JoystickFlat` | base xy/yaw and base qvel via `reset_root_state_uniform`; command sampling; kp/kd via `pd_gains` | none | event terms declared and enabled by default in `src/unilab/conf/ppo/task/go2_joystick_flat/base.yaml` |
| `G1WalkFlat` | base xy/yaw and base qvel via `reset_root_state_uniform`; command sampling with a planar dead zone; `gait_phase` sampling; kp/kd randomization via `pd_gains` | none | kp/kd enabled on mujoco owners by default; disabled on motrix/mjwarp owners |
| `G1WalkRough` | Same as `G1WalkFlat` (shared owner bases, rough scene) | none | Same defaults as `G1WalkFlat` |
| `G1MotionTracking` | Motion-command frame sampling; root pose perturbation `x/y/z/roll/pitch/yaw`; root velocity perturbation `x/y/z/roll/pitch/yaw`; joint-position noise clipped through the public entity soft limits; action-manager state reset | none | `pose_range`, `velocity_range`, and `joint_position_range` have non-zero perturbations in the base owner |
| `G1WBTObs` | Same motion reset plus base mass, base COM, PD gain, foot friction, and encoder-bias event terms | `push_by_setting_velocity` | The WBT owner explicitly enables all listed event terms; unsupported capabilities raise rather than fall back |
| `AllegroInhandRotation` | Entity-scoped hand/ball reset; an explicitly configured grasp cache is sampled, otherwise `null` explicitly selects the model home pose; optional `joint_noise`, `ball_velocity_noise`, and `ball_z_offset` | none | owner YAML explicitly selects the home pose and zero reset noise; a configured missing or malformed cache fails closed |
Expand Down Expand Up @@ -132,7 +130,6 @@ The ownership boundary and MJWarp/CPU executor split are recorded in
## Related Tasks

- {doc}`G1 Motion Tracking <../4-tasks/2-motion_tracking>`: confirm motion assets and replay first before enabling DR.
- {doc}`Go2 Rough Terrain <../4-tasks/1-locomotion>`: common items are mass, COM, friction, and push.

For the backend capability boundary, see
{doc}`Domain Randomization Contract </en/4-developer_guide/2-contracts/4-dr_contract>`.
19 changes: 7 additions & 12 deletions docs/sphinx/source/en/2-user_guide/6-terrain/1-procedural.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,10 @@ env:
seed: 42
```

UniLab does not retain a procedural-terrain production owner. The retained
`g1_walk_rough` task uses the static-heightfield form of the same cold-path
scene contract, while generator composition itself is covered by core terrain
and backend materialization tests.
UniLab does not retain a procedural-terrain production owner. Generator
composition and backend materialization are covered by core terrain and
materialization tests; task owners that enable the capability carry their own
training evidence.

## Materialization boundary

Expand All @@ -47,15 +47,10 @@ During `registry.make(...)`:
Step and reset never parse robot XML or inspect asset metadata. They consume
cached IDs and public backend capabilities.

## Example
## Owner integration

Use the retained rough-scene reference task:

```bash
uv run train --algo sac --task g1_walk_rough --sim mujoco training.no_play=true
```

Custom owners can tune the terrain grid and seed through Hydra:
Select a task owner that declares `env.scene.terrain`, then tune the terrain
grid and seed through Hydra:

```text
env.scene.terrain.generator.num_rows=4
Expand Down
Original file line number Diff line number Diff line change
@@ -1,25 +1,23 @@
# Heightfield Import

Heightfield terrain is configured through `SceneCfg` and the terrain generator,
then materialized by the backend on the init path. The committed user-facing
example is the retained `g1_walk_rough` scene.
then materialized by the backend on the init path. Core tests exercise the
contract with a generated heightfield scene.

## Files To Read

- `src/unilab/terrains/heightfield_terrains.py`
- `unisim.terrain.generator`
- `src/unilab/assets/robots/g1/scene_rough.xml`
- `src/unilab/tasks/locomotion/common/height_scan.py`
- `tests/utils/test_xml_utils.py`
- `unisim.backend.mujoco.xml`
- `unisim.backend.motrix.scene`

## Smoke Commands

```bash
uv run train --algo sac --task g1_walk_rough --sim mujoco \
algo.max_iterations=2 \
algo.num_envs=64 \
training.no_play=true
uv run pytest tests/utils/test_xml_utils.py \
-k materialize_mujoco_hfield_attached_scene
```

Height scan IDs and offsets are cached during env initialization; hot paths call
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,14 +101,14 @@ Disallowed on hot paths:
- Probing backend-private scene methods instead of using explicit contracts.
- Regenerating terrain after env construction.

## Go2 Rough Terrain Evidence
## Terrain Contract Evidence

The current procedural terrain user-facing path is Go2 rough terrain:
The core repository keeps the terrain contract and its materialization tests,
but it does not own a production rough-terrain task:

- Task owner: `src/unilab/tasks/locomotion/g1/manager_terms.py`
- Terrain generator: `unisim.terrain.generator`
- MuJoCo materializer: `unisim.backend.mujoco.xml`
- Motrix materializer: `unisim.backend.motrix.scene`
- Owner YAMLs: `src/unilab/conf/sac/task/g1_walk_rough/{mujoco,motrix}.yaml`
- Contract coverage: `tests/utils/test_xml_utils.py`

User instructions are in {doc}`../../2-user_guide/6-terrain/1-procedural`.
1 change: 0 additions & 1 deletion docs/sphinx/source/en/5-reference/5-support_matrix.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,6 @@ rendering/playback paths remain unsupported.
| APPO (torch) | `g1_flip_tracking` (G1 flip tracking) | Tested | - | Tested | - | - | - | - | - |
| APPO (torch) | `allegro_inhand` (Allegro in-hand) | Tested | - | Tested | - | - | - | - | - |
| SAC (torch) | `g1_walk_flat` (G1 walk flat) | Tested | Tested | Tested | Tested | Tested | Configured | Tested | - |
| SAC (torch) | `g1_walk_rough` (G1 walk rough) | Tested | - | Tested | - | - | - | - | - |
| SAC (torch) | `g1_motion_tracking` (G1 motion tracking) | Tested | Configured | Tested | - | - | - | - | - |
| SAC (torch) | `g1_flip_tracking` (G1 flip tracking) | Tested | - | Registered | - | - | - | - | - |
| SAC (torch) | `g1_wbt_obs` (g1 wbt obs) | Tested | - | Registered | - | - | - | - | - |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ submission。CPU 与 XPU training 不受支持,也不存在第二套 replay pi

```bash
uv run train --algo sac --task g1_walk_flat --sim mujoco
uv run train --algo sac --task g1_walk_rough --sim motrix training.no_play=true
```

## 关键字段
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ runtime。Unitree production 变体由下游 `unitree_rl_unilab` 包维护。
## 核心参考任务

- Go2 joystick: `go2_joystick_flat`
- G1 walking: `g1_walk_flat`, `g1_walk_rough`
- G1 walking: `g1_walk_flat`
- G1 motion tracking 参考配置:见 {doc}`2-motion_tracking`

```bash
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ Manager-Based event term 是唯一 DR 声明路径:
| --- | --- | --- | --- | --- | --- |
| `Go2JoystickFlat` | Hydra `events:` term | 是:owner YAML 声明 reset event | root-state reset + `pd_gains` kp/kd | 无 | `src/unilab/conf/ppo/task/go2_joystick_flat/base.yaml` |
| `G1WalkFlat` | Hydra `events:` term | 是:Hydra `EventTermCfg` + Manager-Based reset term | root-state reset + 经 `pd_gains` 的 kp/kd | 无 | `g1/manager_terms.py` |
| `G1WalkRough` | Hydra `events:` term | 是:与 `G1WalkFlat` 相同的 Manager-Based event term | root-state reset + 经 `pd_gains` 的 kp/kd | 无 | `g1/manager_terms.py` |
| `G1MotionTracking` | Hydra command term | 是:Hydra `MotionCommandCfg` + Manager-Based command reset | motion frame、root pose/velocity 与 joint-position 采样 | 无 | `motion_tracking/common/manager_terms.py` |
| `G1WBTObs` | Hydra `events:` term | 是:同一 motion command + Hydra `EventTermCfg` | motion reset 加 mass/COM/PD/friction/encoder-bias event | interval velocity kick | `motion_tracking/g1/manager_terms.py` |
| `AllegroInhandRotation` | Hydra `events:` term | 是:Hydra `EventTermCfg` + Manager-Based reset term | entity 范围的手/球 reset | 无 | `allegro_inhand/manager_terms.py` |
Expand All @@ -41,7 +40,6 @@ Manager-Based event term 是唯一 DR 声明路径:
| --- | --- | --- | --- |
| `Go2JoystickFlat` | 经 `reset_root_state_uniform` 的 base xy/yaw 与 base qvel;command 采样;经 `pd_gains` 的 kp/kd | 无 | event term 在 `src/unilab/conf/ppo/task/go2_joystick_flat/base.yaml` 中默认声明并启用 |
| `G1WalkFlat` | 经 `reset_root_state_uniform` 的 base xy/yaw 与 base qvel;带平面死区的 command 采样;`gait_phase` 采样;经 `pd_gains` 的 kp/kd 随机化 | 无 | mujoco owner 默认启用 kp/kd;motrix/mjwarp owner 默认禁用 |
| `G1WalkRough` | 与 `G1WalkFlat` 相同(共享 owner base,rough 场景) | 无 | 与 `G1WalkFlat` 相同的默认值 |
| `G1MotionTracking` | Motion-command frame 采样;root 位姿扰动 `x/y/z/roll/pitch/yaw`;root 速度扰动 `x/y/z/roll/pitch/yaw`;通过 public entity soft limit clip 的关节位置噪声;action-manager 状态 reset | 无 | base owner 中 `pose_range`、`velocity_range` 与 `joint_position_range` 默认有非零扰动 |
| `G1WBTObs` | 同一 motion reset 加 base mass、base COM、PD gain、足端摩擦和 encoder-bias event term | `push_by_setting_velocity` | WBT owner 显式启用上述全部 event term;能力不支持时直接报错,不回退 |
| `AllegroInhandRotation` | entity 范围的手/球 reset;显式配置 grasp cache 时进行采样,否则以 `null` 显式选择模型 home pose;可选 `joint_noise`、`ball_velocity_noise` 与 `ball_z_offset` | 无 | owner YAML 显式选择 home pose 与零 reset 噪声;配置的 cache 缺失或格式错误时 fail-closed |
Expand Down Expand Up @@ -119,7 +117,6 @@ Reset-time model-field DR 保持在已选 identity 内。其 canonical 或 per-e
## 相关任务

- {doc}`G1 Motion Tracking <../4-tasks/2-motion_tracking>`:开启 DR 前先确认 motion 资产和 replay。
- {doc}`Go2 Rough Terrain <../4-tasks/1-locomotion>`:常见的是 mass、COM、friction、push。

有关后端能力边界,请参阅
{doc}`Domain Randomization Contract </zh_CN/4-developer_guide/2-contracts/4-dr_contract>`。
17 changes: 6 additions & 11 deletions docs/sphinx/source/zh_CN/2-user_guide/6-terrain/1-procedural.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ env:
seed: 42
```

UniLab 不保留 procedural-terrain production owner。保留的 `g1_walk_rough`
任务使用同一冷路径 scene contract 的静态 heightfield 形式;generator 组合
本身由核心 terrain 与 backend materialization 测试覆盖
UniLab 不保留 procedural-terrain production owner。generator 组合与 backend
materialization 由核心 terrain 和 materialization 测试覆盖;启用该能力的
task owner 需要自行持有训练证据

## 物化边界

Expand All @@ -44,15 +44,10 @@ UniLab 不保留 procedural-terrain production owner。保留的 `g1_walk_rough`
step 和 reset 不解析机器人 XML,也不检查 asset metadata;它们只消费缓存
ID 和公开 backend capability。

## 示例
## Owner 集成

使用保留的 rough-scene reference task:

```bash
uv run train --algo sac --task g1_walk_rough --sim mujoco training.no_play=true
```

自定义 owner 可以通过 Hydra 调整 terrain 网格与 seed:
选择声明了 `env.scene.terrain` 的 task owner,然后通过 Hydra 调整 terrain
网格与 seed:

```text
env.scene.terrain.generator.num_rows=4
Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,21 @@
# 高度场导入

高度场地形通过 `SceneCfg` 和地形生成器进行配置,然后在 init 路径上由后端实例化。已提交的面向用户示例是保留的 `g1_walk_rough` 场景
高度场地形通过 `SceneCfg` 和地形生成器进行配置,然后在 init 路径上由后端实例化。核心测试使用生成式 heightfield 场景覆盖该契约

## 需要阅读的文件

- `src/unilab/terrains/heightfield_terrains.py`
- `unisim.terrain.generator`
- `src/unilab/assets/robots/g1/scene_rough.xml`
- `src/unilab/tasks/locomotion/common/height_scan.py`
- `tests/utils/test_xml_utils.py`
- `unisim.backend.mujoco.xml`
- `unisim.backend.motrix.scene`

## 冒烟命令

```bash
uv run train --algo sac --task g1_walk_rough --sim mujoco \
algo.max_iterations=2 \
algo.num_envs=64 \
training.no_play=true
uv run pytest tests/utils/test_xml_utils.py \
-k materialize_mujoco_hfield_attached_scene
```

高度扫描的 ID 和偏移在 env 初始化期间缓存;热路径调用后端高度 scanner contract,而不是解析 XML 或 asset 元数据。
Original file line number Diff line number Diff line change
Expand Up @@ -94,14 +94,14 @@ materializer。
- 探测 backend 私有的场景方法,而不使用明确的契约。
- 在 env 构造完成后重新生成地形。

## Go2 崎岖地形证据
## 地形契约证据

当前面向用户的程序化地形路径是 Go2 崎岖地形:
核心仓库保留 terrain contract 与 materialization 测试,但不再持有
production rough-terrain 任务:

- Task owner:`src/unilab/tasks/locomotion/g1/manager_terms.py`
- 地形生成器:`unisim.terrain.generator`
- MuJoCo materializer:`unisim.backend.mujoco.xml`
- Motrix materializer:`unisim.backend.motrix.scene`
- Owner YAML:`src/unilab/conf/sac/task/g1_walk_rough/{mujoco,motrix}.yaml`
- 契约覆盖:`tests/utils/test_xml_utils.py`

用户使用说明见 {doc}`../../2-user_guide/6-terrain/1-procedural`。
1 change: 0 additions & 1 deletion docs/sphinx/source/zh_CN/5-reference/5-support_matrix.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,6 @@ uv run scripts/generate_support_matrix.py --write
| APPO (torch) | `g1_flip_tracking` (G1 flip tracking) | Tested | - | Tested | - | - | - | - | - |
| APPO (torch) | `allegro_inhand` (Allegro in-hand) | Tested | - | Tested | - | - | - | - | - |
| SAC (torch) | `g1_walk_flat` (G1 walk flat) | Tested | Tested | Tested | Tested | Tested | Configured | Tested | - |
| SAC (torch) | `g1_walk_rough` (G1 walk rough) | Tested | - | Tested | - | - | - | - | - |
| SAC (torch) | `g1_motion_tracking` (G1 motion tracking) | Tested | Configured | Tested | - | - | - | - | - |
| SAC (torch) | `g1_flip_tracking` (G1 flip tracking) | Tested | - | Registered | - | - | - | - | - |
| SAC (torch) | `g1_wbt_obs` (g1 wbt obs) | Tested | - | Registered | - | - | - | - | - |
Expand Down
56 changes: 0 additions & 56 deletions scripts/benchmark/env/benchmark_env_step.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

# Single task + backend:
uv run scripts/benchmark/env/benchmark_env_step.py task=g1_walk_flat/motrix
uv run scripts/benchmark/env/benchmark_env_step.py task=g1_walk_rough/mujoco

# mjwarp backend (Phase 1: g1_walk_flat only) requires extra deps:
uv run --with mujoco-warp --with warp-lang \\
Expand Down Expand Up @@ -185,44 +184,6 @@ def _ppo_owner_yaml_cfg(
)


def _sac_owner_yaml_cfg(
task_id: str,
backend: str,
env_cfg_cls: Callable[[], Any],
config_overrides: list[str],
) -> Any:
yaml_backend = _hydra_yaml_backend(backend)
return _owner_yaml_cfg(
config_root="sac",
algo_name="sac",
overrides=[f"task={task_id}/{yaml_backend}"],
config_overrides=config_overrides,
env_cfg_cls=env_cfg_cls,
)


def _materialize_g1_rough_benchmark_scene() -> str:
import shutil
import xml.etree.ElementTree as ET

source_dir = ROOT_DIR / "src" / "unilab" / "assets" / "robots" / "g1"
output_dir = Path("/tmp/unilab_benchmark_g1_rough_scene")
output_dir.mkdir(parents=True, exist_ok=True)

for name in ("g1.xml",):
shutil.copy2(source_dir / name, output_dir / name)
for name in ("assets", "textures", "hfields"):
shutil.copytree(source_dir / name, output_dir / name, dirs_exist_ok=True)

tree = ET.parse(source_dir / "scene_rough.xml")
hfield = tree.getroot().find("./asset/hfield[@name='hfield']")
if hfield is not None:
hfield.set("file", "hfields/hfield.png")
output_path = output_dir / "scene_rough.xml"
tree.write(output_path)
return str(output_path)


def _manager_env_cls() -> Callable[..., Any]:
from unilab.envs import make_manager_based_rl_env

Expand All @@ -241,12 +202,6 @@ def _g1_flat_cfg(backend: str, config_overrides: list[str]) -> Any:
return _ppo_owner_yaml_cfg("g1_walk_flat", backend, ManagerBasedRlEnvCfg, config_overrides)


def _g1_rough_cfg(backend: str, config_overrides: list[str]) -> Any:
from unilab.envs import ManagerBasedRlEnvCfg

return _sac_owner_yaml_cfg("g1_walk_rough", backend, ManagerBasedRlEnvCfg, config_overrides)


def _g1_motion_tracking_cfg(backend: str, config_overrides: list[str]) -> Any:
from unilab.envs import ManagerBasedRlEnvCfg

Expand Down Expand Up @@ -279,14 +234,6 @@ def _g1_walk_env_cls() -> type:
env_cls_factory=_g1_walk_env_cls,
backends=("mujoco", "motrix", "mjwarp"),
),
"g1_rough": TaskConfig(
task_id="g1_walk_rough",
env_name="G1WalkRough",
cfg_factory=_g1_rough_cfg,
env_cls_factory=_g1_walk_env_cls,
aliases=("sac/g1_walk_rough",),
backends=("mujoco", "motrix", "mjwarp"),
),
"g1_mt": TaskConfig(
task_id="g1_motion_tracking",
env_name="G1MotionTracking",
Expand All @@ -305,7 +252,6 @@ def _g1_walk_env_cls() -> type:
"go2": "#54A24B",
"g1": "#F58518",
"g1_mt": "#B279A2",
"g1_rough": "#E45756",
}
BACKEND_STYLES = {
"mujoco": {"marker": "o", "linestyle": "-", "hatch": "//"},
Expand Down Expand Up @@ -653,8 +599,6 @@ def _short_task_label(task_name: str) -> str:
name = task_name.lower()
if "motiontracking" in name:
return "g1_mt"
if "rough" in name and name.startswith("g1"):
return "g1_rough"
for prefix in ("go2", "g1"):
if name.startswith(prefix):
return prefix
Expand Down
12 changes: 5 additions & 7 deletions scripts/tools/support_matrix.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,17 +81,15 @@
_TASK_ORDER = {
"go2_joystick_flat": 0,
"g1_walk_flat": 1,
"g1_walk_rough": 2,
"g1_motion_tracking": 3,
"g1_flip_tracking": 4,
"x2_wall_flip_tracking": 5,
"allegro_inhand": 6,
"allegro_sac": 7,
"g1_motion_tracking": 2,
"g1_flip_tracking": 3,
"x2_wall_flip_tracking": 4,
"allegro_inhand": 5,
"allegro_sac": 6,
}
_TASK_LABELS = {
"go2_joystick_flat": "Go2 joystick",
"g1_walk_flat": "G1 walk flat",
"g1_walk_rough": "G1 walk rough",
"g1_motion_tracking": "G1 motion tracking",
"g1_flip_tracking": "G1 flip tracking",
"x2_wall_flip_tracking": "X2 wall flip tracking",
Expand Down
Binary file removed src/unilab/assets/robots/g1/hfields/hfield.png
Binary file not shown.
Loading
Loading