From 0d2afbf2bb24148c65c4e2f8706e9fe182be1c34 Mon Sep 17 00:00:00 2001
From: "youyuan.chen"
Date: Sun, 26 Jul 2026 00:40:06 +0800
Subject: [PATCH] feat: add Go1 training and MuJoCo deployment
---
.gitattributes | 1 +
README.md | 4 +
deploy/deploy_mujoco/configs/go1.yaml | 43 ++
deploy/deploy_mujoco/deploy_go1.py | 12 +
deploy/deploy_mujoco/deploy_go2.py | 6 +-
deploy/deploy_mujoco/utils.py | 2 +
deploy/pre_train/go1/.gitkeep | 1 +
docs/go1.md | 63 ++
resources/go1/boxes.xml | 696 ++++++++++++++++++
resources/go1/flat.xml | 22 +
resources/go1/go1.xml | 198 +++++
resources/go1/meshes/calf.stl | Bin 0 -> 1447984 bytes
resources/go1/meshes/hip.stl | Bin 0 -> 1505284 bytes
resources/go1/meshes/thigh.stl | Bin 0 -> 793584 bytes
resources/go1/meshes/thigh_mirror.stl | Bin 0 -> 950834 bytes
resources/go1/meshes/trunk.stl | Bin 0 -> 5619284 bytes
resources/go1/stairs.xml | 28 +
resources/go1/stairs_and_slope.xml | 39 +
resources/go1/urdf/go1.urdf | 581 +++++++++++++++
source/robot_lab/robot_lab/assets/unitree.py | 39 +-
.../robot_lab/assets/unitree_actuator.py | 14 +
.../robot_lab/robot_lab/tasks/go1/__init__.py | 22 +
.../robot_lab/tasks/go1/env/__init__.py | 1 +
.../robot_lab/tasks/go1/env/go1_env.py | 14 +
.../robot_lab/robot_lab/tasks/go1/env_cfg.py | 509 +++++++++++++
.../robot_lab/tasks/go1/rsl_rl_cfg.py | 86 +++
26 files changed, 2378 insertions(+), 3 deletions(-)
create mode 100644 .gitattributes
create mode 100644 deploy/deploy_mujoco/configs/go1.yaml
create mode 100644 deploy/deploy_mujoco/deploy_go1.py
create mode 100644 deploy/pre_train/go1/.gitkeep
create mode 100644 docs/go1.md
create mode 100644 resources/go1/boxes.xml
create mode 100644 resources/go1/flat.xml
create mode 100644 resources/go1/go1.xml
create mode 100644 resources/go1/meshes/calf.stl
create mode 100644 resources/go1/meshes/hip.stl
create mode 100644 resources/go1/meshes/thigh.stl
create mode 100644 resources/go1/meshes/thigh_mirror.stl
create mode 100644 resources/go1/meshes/trunk.stl
create mode 100644 resources/go1/stairs.xml
create mode 100644 resources/go1/stairs_and_slope.xml
create mode 100644 resources/go1/urdf/go1.urdf
create mode 100644 source/robot_lab/robot_lab/tasks/go1/__init__.py
create mode 100644 source/robot_lab/robot_lab/tasks/go1/env/__init__.py
create mode 100644 source/robot_lab/robot_lab/tasks/go1/env/go1_env.py
create mode 100644 source/robot_lab/robot_lab/tasks/go1/env_cfg.py
create mode 100644 source/robot_lab/robot_lab/tasks/go1/rsl_rl_cfg.py
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..e4f05d4
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1 @@
+deploy/deploy_mujoco/deploy_go2.py whitespace=cr-at-eol
diff --git a/README.md b/README.md
index 3ee1144..1baaaef 100644
--- a/README.md
+++ b/README.md
@@ -134,6 +134,10 @@ python scripts/rsl_rl/train.py --task=RobotLab-Go2-v0 --headless
python scripts/rsl_rl/play.py --task=RobotLab-Go2-v0
```
+The Go1 adaptation is available on the `go1` branch as
+`RobotLab-Go1-v0`; see [docs/go1.md](docs/go1.md) for its training, export,
+observation, and MuJoCo deployment details.
+
---
### Training with RoboGauge Evaluation
diff --git a/deploy/deploy_mujoco/configs/go1.yaml b/deploy/deploy_mujoco/configs/go1.yaml
new file mode 100644
index 0000000..1c594cb
--- /dev/null
+++ b/deploy/deploy_mujoco/configs/go1.yaml
@@ -0,0 +1,43 @@
+policy_path: "{ROOT_DIR}/deploy/pre_train/go1/policy.pt"
+xml_path: "{ROOT_DIR}/resources/go1/stairs_and_slope.xml"
+
+render_fps: 300
+video_fps: 60
+save_video: false
+
+simulation_duration: 60000000.0
+simulation_dt: 0.002
+control_decimation: 10
+base_init_pos: [0.0, 0.0, 0.34]
+base_init_quat: [1.0, 0.0, 0.0, 0.0]
+
+# Deployment defaults to no extra delay. Training randomizes 0-4 physics steps;
+# this script's delay buffer is measured in 20 ms policy steps instead.
+actuator_delay_min: 0
+actuator_delay_max: 0
+actuator_delay_seed: 0
+
+kps: [28.0, 28.0, 28.0, 28.0, 28.0, 28.0, 28.0, 28.0, 28.0, 28.0, 28.0, 28.0]
+kds: [0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7]
+
+default_angles: [-0.1, 0.8, -1.5, 0.1, 0.8, -1.5,
+ -0.1, 1.0, -1.5, 0.1, 1.0, -1.5]
+
+lin_vel_scale: 2.0
+ang_vel_scale: 0.25
+dof_pos_scale: 1.0
+dof_vel_scale: 0.05
+action_pos_scale: 0.25
+cmd_scale: [1.0, 1.0, 1.0]
+num_actions: 12
+num_obs: 45
+max_cmd: [1.0, 1.0, 1.0]
+cmd_init: [0.5, 0.0, 0.0]
+history_len: 10
+
+mujoco_joint_names: &joint_names
+ [FR_hip_joint, FR_thigh_joint, FR_calf_joint,
+ FL_hip_joint, FL_thigh_joint, FL_calf_joint,
+ RR_hip_joint, RR_thigh_joint, RR_calf_joint,
+ RL_hip_joint, RL_thigh_joint, RL_calf_joint]
+model_joint_names: *joint_names
diff --git a/deploy/deploy_mujoco/deploy_go1.py b/deploy/deploy_mujoco/deploy_go1.py
new file mode 100644
index 0000000..a5fd997
--- /dev/null
+++ b/deploy/deploy_mujoco/deploy_go1.py
@@ -0,0 +1,12 @@
+"""Run an exported Go1 CTS policy in MuJoCo.
+
+The model, observations, actions, and MuJoCo actuators all use the Unitree SDK
+joint order: FR, FL, RR, RL. The exported policy maintains its own history and
+therefore consumes one 45-dimensional observation frame per call.
+"""
+
+from deploy_go2 import main
+
+
+if __name__ == "__main__":
+ main("go1.yaml")
diff --git a/deploy/deploy_mujoco/deploy_go2.py b/deploy/deploy_mujoco/deploy_go2.py
index 1f682bc..627c9d6 100644
--- a/deploy/deploy_mujoco/deploy_go2.py
+++ b/deploy/deploy_mujoco/deploy_go2.py
@@ -12,6 +12,8 @@ Notes:
This script currently uses CONFIG_NAME = "go2.yaml" and does not expose CLI flags.
"""
+from __future__ import annotations
+
import time
from pathlib import Path
@@ -95,9 +97,9 @@ def build_single_obs(features: dict[str, np.ndarray], layout: list[tuple[str, in
return np.concatenate([features[name] for name, _ in layout], axis=0).astype(np.float32, copy=False)
-def main() -> None:
+def main(config_name: str = CONFIG_NAME) -> None:
"""Run MuJoCo simulation and deploy the CTS policy in closed-loop control."""
- cfg = load_config(CONFIG_NAME)
+ cfg = load_config(config_name)
layout = [
("ang_vel", 3),
("gravity", 3),
diff --git a/deploy/deploy_mujoco/utils.py b/deploy/deploy_mujoco/utils.py
index c136f94..f3be708 100644
--- a/deploy/deploy_mujoco/utils.py
+++ b/deploy/deploy_mujoco/utils.py
@@ -1,5 +1,7 @@
"""Shared helpers for MuJoCo deployment scripts."""
+from __future__ import annotations
+
from collections import deque
from pathlib import Path
from types import SimpleNamespace
diff --git a/deploy/pre_train/go1/.gitkeep b/deploy/pre_train/go1/.gitkeep
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/deploy/pre_train/go1/.gitkeep
@@ -0,0 +1 @@
+
diff --git a/docs/go1.md b/docs/go1.md
new file mode 100644
index 0000000..99a5349
--- /dev/null
+++ b/docs/go1.md
@@ -0,0 +1,63 @@
+# Go1 Adaptation
+
+The `go1` branch adds the `RobotLab-Go1-v0` IsaacLab task and a matching
+MuJoCo deployment. It uses the complete Unitree Go1 URDF/MuJoCo model.
+
+## Interface
+
+- Policy joint order: `FR, FL, RR, RL`, with hip, thigh, calf for each leg.
+- Single-frame observation: 45 values in this order:
+ body angular velocity (3), projected gravity (3), velocity command (3),
+ relative joint position (12), joint velocity (12), previous action (12).
+- Actor history: 10 frames, or 450 values.
+- Action: 12 normalized joint-position offsets, scaled by `0.25 rad` and added
+ to the default joint angles.
+- Policy frequency: 50 Hz (`0.005 s` physics step and decimation 4).
+- PD gains: `Kp=28`, `Kd=0.7`; torque is limited to `33.5 Nm`.
+- Training randomizes actuator delay over 0-4 physics steps (0-20 ms). The
+ MuJoCo config defaults to zero extra delay because its delay setting is in
+ 20 ms policy steps.
+
+## Train
+
+Install the editable packages as described in the main README, then run:
+
+```bash
+cd go2_rl_robotlab
+python scripts/rsl_rl/train.py \
+ --task=RobotLab-Go1-v0 \
+ --num_envs=4096 \
+ --max_iterations=5000 \
+ --headless
+```
+
+## Play And Export
+
+`play.py` exports both `policy.pt` and `policy.onnx` into the checkpoint run's
+`exported/` directory before starting the rollout.
+
+```bash
+python scripts/rsl_rl/play.py \
+ --task=RobotLab-Go1-v0 \
+ --num_envs=64 \
+ --checkpoint=/absolute/path/to/model_5000.pt
+```
+
+## MuJoCo
+
+Place the exported TorchScript file at
+`deploy/pre_train/go1/policy.pt`, or edit `policy_path` in
+`deploy/deploy_mujoco/configs/go1.yaml`. Then run:
+
+```bash
+MUJOCO_GL=glfw python deploy/deploy_mujoco/deploy_go1.py
+```
+
+Set `xml_path` in `go1.yaml` to select `flat.xml`, `stairs.xml`, `boxes.xml`,
+or `stairs_and_slope.xml`.
+
+## Actuator Assumption
+
+The Go1 asset publishes a `33.5 Nm` effort limit but does not include measured
+torque-speed knee points. The training actuator therefore uses the known effort
+limit with delayed PD control instead of reusing the Go2-HV torque-speed curve.
diff --git a/resources/go1/boxes.xml b/resources/go1/boxes.xml
new file mode 100644
index 0000000..271958c
--- /dev/null
+++ b/resources/go1/boxes.xml
@@ -0,0 +1,696 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/resources/go1/flat.xml b/resources/go1/flat.xml
new file mode 100644
index 0000000..cb94b63
--- /dev/null
+++ b/resources/go1/flat.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/resources/go1/go1.xml b/resources/go1/go1.xml
new file mode 100644
index 0000000..d98ddf6
--- /dev/null
+++ b/resources/go1/go1.xml
@@ -0,0 +1,198 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+