[software] 添加16DOF早期训练仿真与Sim2Real闭环

This commit is contained in:
2026-07-21 16:15:14 +08:00
parent 9bd22225f9
commit e9e2c946b3
681 changed files with 137221 additions and 8 deletions
+15
View File
@@ -0,0 +1,15 @@
# 第一代强化学习与仿真工程
`rc_mjlab/` 是 16DOF 轮足机器人的第一代自包含训练与仿真工程。
## 内容
- `src/robot`Flat、Rough、Crawl 训练任务和自定义 MDP
- `mjcf`:轮足机器人 MuJoCo 模型和网格
- `mujoco_sim`:不依赖策略的独立 MuJoCo/MPC 调试工具
- `sim2sim`:策略加载、交互控制和比赛地形验证
- `mjlab`:固定版本的本地训练框架依赖
- `model_rough.pt``model_crawl.pt`:对应的早期策略权重
- `pyproject.toml``uv.lock`Python 环境与依赖锁定
工程命令和任务说明见 [`rc_mjlab/README.md`](rc_mjlab/README.md),本地依赖来源见 [`rc_mjlab/DEPENDENCIES.md`](rc_mjlab/DEPENDENCIES.md)。
@@ -0,0 +1,44 @@
# 依赖说明
## Python 环境
- Python `>=3.10`
- `uv` 依赖管理
- MuJoCo development wheel
- `mjlab[cu128]`
- PyTorch CUDA 12.8 环境
- `pynput`
精确解析结果保存在 `uv.lock`。项目使用本地可编辑 `mjlab`
```toml
[tool.uv.sources]
mjlab = { path = "mjlab", editable = true }
```
## mjlab 来源
- 上游仓库:`https://github.com/mujocolab/mjlab.git`
- 基准提交:`0040979763ab43bc1220812c9de4bc74e2631f42`
- 基准日期:`2026-04-28`
- 上游许可证:Apache-2.0,许可证文件保留在 `mjlab/LICENSE`
早期工程在该基准上保留了 3 处本地修改:
1. `mjlab/pyproject.toml`:增加清华 PyPI 镜像。
2. `mjlab/src/mjlab/envs/mdp/dr/actuator.py`:让 effort limit 随机化支持轮子使用的 velocity/motor actuator。
3. `mjlab/src/mjlab/scene/scene.py`:通过 XML 字符串加载场景,以适配当时的场景组合方式。
本次归档保留修改后的完整工作树,但不包含上游 `.git`、本地 `.venv`、缓存和生成日志。
## 基本入口
`05_software/train/rc_mjlab` 下执行:
```bash
uv sync
uv run train Robot-Flat-v0
uv run play Robot-Rough-v0
```
GPU、CUDA、MuJoCo development wheel 和驱动版本必须满足 `pyproject.toml``uv.lock` 的约束。
+222
View File
@@ -0,0 +1,222 @@
# rc_mjlab
基于 [mjlab](https://github.com/google-deepmind/mjlab) 框架的四轮腿混合机器人强化学习训练与部署部署项目,面向机器人竞赛场景(如越障、匍匐、斜坡、台阶等复合任务)。
---
## 🛠️ 项目简介
本项目针对一台 **4 腿 × 3 关节 + 4 驱动轮(轮腿混合)** 的移动机器人,在 MuJoCo 物理引擎中利用 PPO 算法进行多任务运动控制策略训练。
系统设计特点包括:
1. **高保真动力学步进**:物理仿真计算步长设为 **`2ms` (0.002s)**,为碰撞、地面力学传递提供极高的解算频宽与稳定性。
2. **50Hz 控制决策循环**:通过在环境中设置 `decimation = 10`,策略决策周期为 `20ms` ($0.002\text{s} \times 10 = 0.02\text{s}$),即控制决策频率为 **`50Hz`**,完全对齐真机控制周期。
3. **混合滤波执行器**
- 腿部 12 个位置控制关节采用位置 PD 伺服($K_p=40, K_d=1$),并叠加截止频率为 **`5Hz`** 的低通滤波器进行动作平滑,减小高频机械抖动。
- 轮部 4 个速度驱动关节采用阻尼速度伺服($K_d=0.5$),叠加截止频率为 **`15Hz`** 的低通速度滤波器,保证转速响应的灵敏度。
4. **大规模并行加速**:利用 GPU 并行(通过 Warp 和 MuJoCo GPU 物理管线),支持最多 $4096$ 环境同时训练,并包含对动作变化率、关节加速度的惩罚项以平抑噪声。
---
## 📦 项目结构
```
rc_mjlab/
├── src/robot/ # RL 训练任务包(主体代码)
│ ├── __init__.py # 任务注册(Robot-Flat-v0 / Robot-Rough-v0 / Robot-Crawl-v0
│ ├── robot_cfg.py # 机器人物理参数(PD 增益、执行器上限、碰撞属性)
│ ├── config/
│ │ ├── env_cfgs.py # 三套环境完整配置(观测、奖励、事件、地形、终止条件)
│ │ └── rl_cfg.py # PPO 超参数(网络结构、学习率、折扣因子等)
│ ├── mdp/
│ │ ├── rewards.py # 自定义奖励函数(速度追踪、姿态约束、接触、越障反射惩罚等)
│ │ ├── curriculums.py # 地形关卡课程(严格速度约束版)+ 自适应速度范围
│ │ ├── lowpass_actions.py # 低通滤波动作包装(腿 5 Hz / 轮 15 Hz IIR 滤波)
│ │ ├── disturbances.py # 持续外力扰动(一阶低通滤波平滑随机外力/扭矩)
│ │ ├── mode_command.py # 离散步态模式命令(保留扩展用)
│ │ └── only_positive_rewards.py # HIMLoco 风格:每步总奖励截断为 ≥ 0,防止消极逃避
│ └── terrains/
│ └── competition_terrains.py # 竞赛自定义地形(高墙障碍、低杆障碍)
├── sim2sim/ # Sim2Sim 物理部署与高精度交互回放工具
│ ├── nav_sim2sim.py # 主程序:2D Pygame 交互面板 + 全自动多地形导航追踪
│ ├── sim2sim.py # 简易版键盘调试工具
│ ├── interface/
│ │ └── mujoco_io.py # MuJoCo 输入输出与传感器、低通滤波器接口
│ ├── tools/
│ │ └── math_utils.py # 姿态重力等数学转换
│ ├── policy/ # 保存的 pt 策略权重
│ └── terrain/
│ └── scene_terrain.xml # 完整越障比赛场地的物理 XML 定义
├── mjcf/
│ ├── wheelleg.xml # 机器人 MuJoCo 模型(含网格引用)
│ ├── scene.xml # mjlab 场景入口文件
│ └── meshes/ # STL/OBJ 碰撞与外观网格
├── mujoco_sim/ # 独立 MPC 仿真调试工具(不依赖 RL 训练)
├── logs/ # 训练日志(rsl_rl 格式,按任务名/日期/checkpoint 归档)
├── pyproject.toml # 项目依赖(uv 管理,含清华镜像源加速)
└── uv.lock # 精确依赖锁定文件
```
---
## 🚀 常用命令
### 1. 训练与回放
```bash
# 运行平地基础训练 (Robot-Flat-v0)
uv run train Robot-Flat-v0
# 运行多障碍复杂地形训练 (Robot-Rough-v0),可从 Flat 的Checkpoint热启动
uv run train Robot-Rough-v0 --agent.resume True --agent.experiment-name robot_flat
# 运行爬坡与匍匐限高任务 (Robot-Crawl-v0)
uv run train Robot-Crawl-v0
# 使用默认 20 个并行环境回放最新 checkpoint 效果
uv run play Robot-Rough-v0
```
### 2. 交互式 Sim2Sim 自动导航仪表盘
我们提供了一个强大的 GUI 交互和全自动障碍赛追踪平台,位于 `sim2sim` 目录下:
```bash
# 启动 2D 交互导航平台
cd sim2sim
uv run python nav_sim2sim.py
```
---
## 🖥️ 交互式自动导航平台 (sim2sim/nav_sim2sim.py)
该平台包含一个 **Pygame 2D HUD 监控面板** 和一个 **实时 MuJoCo 3D 渲染器**,支持对仿真参数和任务执行的精细控制。
### 1. 按钮面板分区与布局
面板在垂直方向进行了高紧凑性排版,避免控件重叠,并在底端留有安全间距:
* **【预设任务列表】**(按物理穿越顺序排列):
- **S形绕杆 (Slalom)**:绕过红蓝两色障碍杆路径。
- **限高下蹲 (Crawl)**:降低机身高度穿过低杆障碍。
- **砂砾碎石 (Gravel)**:平稳低速通过多颗粒非结构碎石坑。
- **高墙越障 (Wall)**:高速度冲向障碍高墙,利用前轮攀爬反射爬越。
- **台阶攀爬 (Stairs)**:攀越分段式台阶。
- **斜坡木桥 (Bridge)**:穿过A坡并稳健从B坡落地。
- **障碍赛大满贯 (Grand)**:**科技紫**圆角高亮按钮。点击后,机器人将以**顺时针**方向,自动、连贯且闭环地一次性穿越上述全部 6 个核心比赛障碍,并在木桥落地后,通过安全通道直角返航至起终点。
* **【系统与视图控制】**
- **清除与停止 (Stop)**:一键紧急停止并重置当前目标航点。
- **视角居中 (Center)**:一键锁定相机随机器人机身移动。
- **物理流速三联排 (倍速- / 标准 / 倍速+)**:在不破坏物理计算数值稳定性的前提下,实现对仿真总体时间的平滑加速与慢放(支持 `0.2x` ~ `5.0x`,可随时点击“标准”一键归位 `1.0x`)。
* **【目标微调与命令终端】**
- 拥有高精度航点微调发令键。
- 底部命令行支持输入 `speed <倍率>` 更改仿真速度,或者输入 `grand` 直接开启大满贯。
---
## 📊 机器人系统规格参数
### 1. 机器人本体参数
| 参数项 | 基准数值 | 说明 |
|---|---|---|
| **物理步长 ($dt_{physics}$)** | `0.002s` (2ms) | 底层 MuJoCo 求解器步长,物理精度极高 |
| **控制决策频率 ($Freq_{ctrl}$)** | `50Hz` (20ms) | $decimation = 10$,环境每 10 个子步进行一次交互决策 |
| **单轮仿真时长** | `30.0s` | 最大决策步数上限为 $30.0 / 0.02 = 1500$ 步 |
| **腿部控制** | 位置 PD 伺服 | 目标关节角限幅 ±0.25 rad,叠加 **5Hz** 低通滤波器 |
| **轮部控制** | 阻尼速度伺服 | 目标速度限幅 ±10.0 rad/s,叠加 **15Hz** 低通滤波器 |
| **结构形式** | 4腿 × 3关节 + 4轮 | 腿:hip abduction, hip pitch, knee;轮半径 0.1m,左右轮距 0.32m |
| **关节扭矩上限** | 17.0 Nm | 关节最大输出力矩(训练时含 80%~100% 随机缩放) |
| **最大关节角速度** | 13.0 rad/s | 关节最大运动速度限制 |
### 2. 状态观测空间 (Actor Obs, 53维)
网络输入包含 $6$ 步历史数据,并在训练时注入均匀高斯噪声以提升泛化能力:
| 观测项目 | 维度 | 缩放比例 | 噪声范围 |
|---|---|---|---|
| 基座角速度 (ang_vel) | 3 | 0.25 | $[-0.2, 0.2]$ rad/s |
| 投影重力向量 (projected_gravity) | 3 | 1.0 | $[-0.05, 0.05]$ |
| 指令速度 (vx, vy, wz/heading) | 3 | 1.0 | — |
| 腿部关节相对角度 (joint_pos_rel) | 12 | 1.0 | $[-0.01, 0.01]$ rad |
| 腿部关节角速度 (joint_vel) | 12 | 0.05 | $[-1.5, 1.5]$ rad/s |
| 轮子角速度 (wheel_vel) | 4 | 0.05 | $[-1.0, 1.0]$ rad/s |
| 上一步动作缓存 (last_actions) | 16 | 1.0 | — |
> **Critic 附加观测**:包含高精度基座物理线速度、轮地实际接触状态、以及 $1.6\text{m} \times 1.0\text{m}$ 分辨率为 $0.08\text{m}$ 的高度雷达扫描网格,提供大范围越障感知。
---
## ⚖️ 奖惩体系设计 (Robot-Rough-v0)
复杂地形任务采用 **“仅正奖励截断”** 机制(即每步累加的总奖励若小于0则强制截断为0),防止机器人在困难关卡早期选择倒下自杀来规避负惩罚。
### 1. 运动追踪与状态惩罚
| 奖励/惩罚项 | 权重 (Weight) | 适用函数 / 物理意义 |
|---|---|---|
| **track_lin_vel** | `+4.5` | L1 范数水平线速度跟踪奖励,平缓高速漂移 |
| **track_ang_vel** | `+2.0` | 偏航角速度指数跟踪奖励 |
| **stand_still** | `-2.0` | 当速度指令为 0 时,严厉惩罚关节多余晃动,保持稳立 |
| **joint_pos_penalty** | `-0.8` | 当速度指令为 0 时,惩罚关节角度偏离初始对齐姿态,维持高刚度 |
| **roll_penalty** | `-1.0` | 机身横滚角 (Roll) 倾斜惩罚,抑制左右倾倒抖动 |
| **pitch_penalty** | `-1.5` | 俯仰角 (Pitch) 死区惩罚,限制仰角不超过 29 度,抑制越障瞬间前轮翘头和后翻 |
| **base_height_l2** | `-0.5` | 机身高度偏离 0.36m 惩罚(基于高度扫描均值,允许自适应高低) |
### 2. 能量正则与平滑惩罚 (平抑高频抖动)
| 奖励/惩罚项 | 权重 (Weight) | 适用函数 / 物理意义 |
|---|---|---|
| **action_rate_curriculum** | `-0.005` | 动作变化率 L2 惩罚,迫使连续两个决策步的输出动作变化平滑 |
| **joint_torques** | `-1.0e-4` | 关节输出扭矩 L2 正则,降低电机总发热和冲击性载荷 |
| **leg_joint_acc_l2** | `-2.5e-7` | 限制腿部 12 关节**角加速度**,直接抑制关节高频电磁和机械震荡 |
| **wheel_joint_acc_l2** | `-2.5e-9` | 限制 4 个驱动轮的**角加速度**,平缓轮速切换,降低打滑振荡 |
| **joint_pos_limits** | `-0.2` | 极度接近关节极限限位阻挡时的硬惩罚 |
### 3. 接触反射与安全约束
| 奖励/惩罚项 | 权重 (Weight) | 适用函数 / 物理意义 |
|---|---|---|
| **feet_contact_without_cmd** | `+0.1` | 当速度指令为 0 时,鼓励四轮保持稳定接地的正向收益 |
| **body_collision** | `-1.0` | 腿部连杆(大腿、小腿)触地碰撞惩罚,迫使抬腿跨越障碍 |
| **base_collision** | `-5.0` | 机身/底盘硬撞障碍物时的严厉惩罚,逼迫机器人学会抬起前轮支撑攀爬 |
| **is_terminated** | `0.0` | 关闭越障任务的提早终止,允许机器人跌倒后自行挣扎起立,提高生存极限 |
---
## 🌀 域随机化 (Domain Randomization)
为了使训练的控制策略具有卓越的零样本真机部署能力,在环境重置及仿真运行中注入了高强度的域随机化参数:
| 随机化项目 | 扰动操作 | 随机范围 |
|---|---|---|
| **机身质心偏移 (base_com)** | 加法 | X, Y, Z 三轴分别随机偏置 `[-0.05, 0.05]` 米 |
| **角度传感器零偏 (encoder_bias)** | 加法 | 关节传感器绝对偏置 `[-0.015, 0.015]` rad (约 $\pm 0.85^{\circ}$) |
| **几何表面摩擦力 (body_friction)** | 绝对值 | 地面及机器人碰撞几何体摩擦力在 `[0.3, 1.2]` 均匀随机 |
| **关节摩擦阻尼 (joint_friction)** | 乘法 | 所有旋转轴关节运动阻尼摩擦在原值的 `[0.7, 1.3]` 倍间随机 |
| **关节传动刚度 (actuator_stiffness)** | 乘法 | Kp 刚度系数在原值的 `[0.9, 1.1]` 对数均匀范围内随机缩放 |
| **关节传动阻尼 (actuator_damping)** | 乘法 | Kd 阻尼系数在原值的 `[0.9, 1.1]` 对数均匀范围内随机缩放 |
| **力矩输出上限 (actuator_effort_limit)**| 乘法 | 最大输出扭矩极限随机在原值的 `[0.8, 1.0]` 倍均匀缩放 |
| **负载质量 (payload_mass)** | 加法 | 在机身处添加载荷质量,扰动范围在 `[-1.0, 3.0]` kg |
| **瞬时侧向推撞 (push_robot)** | 脉冲 | 每隔 `[5.0, 10.0]` 秒,瞬间施加 X/Y 轴 `[-0.5, 0.5]` m/s 冲击速度 |
| **一阶低通持续风阻 (continuous_disturbance)** | 连续 | 机身持续叠加随机外力(±15N)与力矩(±10Nm),低通周期 0.5s |
---
## 🏆 多地形关卡难度控制 (Robot-Rough-v0)
共有 8 种子地形按照比例混合,通过自适应升级距离控制关卡难度的推进:
| 地形名称 | 混合比例 (Proportion) | 最大配置难度 |
|---|---|---|
| **平地 (flat)** | `5%` | 作为初始安定性恢复区域 |
| **金字塔台阶 (pyramid_stairs)** | `25%` | 最大阶梯高度上限 `0.30` 米,级宽 0.30m |
| **倒金字塔台阶 (pyramid_stairs_inv)** | `10%` | 最大倒台阶高度上限 `0.30` 米,级宽 0.30m |
| **随机高度网格 (random_grid)** | `10%` | 最大网格方块起伏上限 `0.30` 米 |
| **随机粗糙地形 (random_rough)** | `5%` | 地表最大颗粒随机噪声起伏 `0.06` 米 |
| **柏林噪声地形 (perlin_noise)** | `5%` | 大范围高平缓起伏最大高度 `0.06` 米 |
| **越障高墙地形 (rc_wall)** | `25%` | 自定义跳跃垂直高墙,最大墙高上限 `0.45` 米 |
| **平台斜坡地形 (sloped_terrain)** | `15%` | 最大坡度限制 `0.325` (约 $18.5^{\circ}$) |
> **地形升级规则**:当机器人朝指令方向行进距离超过当前地块的一半(4米),且实际行进距离大于速度指令对应期望距离的 45% 时,该环境关卡等级 +1。
> **地形降级规则**:当指令速度大于 0.1m/s 但实际行进距离小于期望距离的 25%,或者实际移动不足 2.0米时,环境难度等级 -1。
Binary file not shown.
+22
View File
@@ -0,0 +1,22 @@
<mujoco model="wheelleg_scene">
<include file="wheelleg.xml"/>
<option timestep="0.002" gravity="0 0 -9.81" integrator="implicitfast"/>
<visual>
<headlight diffuse="0.6 0.6 0.6" ambient="0.3 0.3 0.3"/>
<global azimuth="120" elevation="-20"/>
</visual>
<asset>
<texture type="skybox" builtin="gradient" rgb1="0.3 0.5 0.7" rgb2="0 0 0" width="512" height="3072"/>
<texture type="2d" name="groundplane" builtin="checker" mark="edge"
rgb1="0.2 0.3 0.4" rgb2="0.1 0.2 0.3" markrgb="0.8 0.8 0.8" width="300" height="300"/>
<material name="groundplane" texture="groundplane" texuniform="true" texrepeat="5 5" reflectance="0.2"/>
</asset>
<worldbody>
<light pos="0 0 3" dir="0 0 -1" directional="true"/>
<geom name="floor" size="0 0 0.05" type="plane" material="groundplane" friction="0.8 0.05 0.01"/>
</worldbody>
</mujoco>
@@ -0,0 +1,327 @@
<mujoco model="go2w scene">
<include file="C:/Users/31560/Documents/00_legged/new_rl/rc_mjlab/mjcf/wheelleg.xml"/>
<statistic center="3.7 -9.0 0.4" extent="5.0"/>
<visual>
<headlight diffuse="0.6 0.6 0.6" ambient="0.3 0.3 0.3" specular="0 0 0"/>
<rgba haze="0.15 0.25 0.35 1"/>
<global azimuth="90" elevation="-20"/>
</visual>
<asset>
<texture type="skybox" builtin="gradient" rgb1="0.3 0.5 0.7" rgb2="0 0 0" width="512" height="3072"/>
<texture type="2d" name="groundplane" builtin="checker" mark="edge" rgb1="0.2 0.3 0.4" rgb2="0.1 0.2 0.3" markrgb="0.8 0.8 0.8" width="300" height="300"/>
<material name="groundplane" texture="groundplane" texuniform="true" texrepeat="5 5" reflectance="0.2"/>
<hfield name="perlin_hfield" size="1.0 0.75 0.2 0.2" file="C:/Users/31560/Documents/00_legged/new_rl/rc_mjlab/sim2sim/terrain/height_field.png"/>
<hfield name="image_hfield" size="1.0 1.0 0.02 0.1" file="C:/Users/31560/Documents/00_legged/new_rl/rc_mjlab/sim2sim/terrain/unitree_hfield.png"/>
</asset>
<worldbody>
<light pos="0 0 1.5" dir="0 0 -1" directional="true" />
<geom name="floor" size="0 0 0.05" type="plane" material="groundplane" />
<!-- 30cm高墙:旋转90度,沿x轴方向放置,并与T型楼梯中心线 y=-3.50 对齐 -->
<geom pos="1.8 -7.0 0.15"
type="box"
size="0.025 0.5 0.15"
quat="0.7071068 0.0 0.0 0.7071068"
rgba="1.0 0.9 0.4 1.0"/>
<!-- 沙砾碎木坑:x正方向边界与10度斜坡+x边界对齐,y正边界距斜坡y负边界4m -->
<geom pos="4.8361 -12.5 0.075"
type="box"
size="0.5 0.5 0.075"
quat="0.0 0.0 0.0 1.0"
rgba="0.75 0.72 0.55 1.0"/>
<geom pos="5.8361 -12.0 0.075"
type="box"
size="0.5 1.0 0.075"
quat="0.0 0.0 0.0 1.0"
rgba="0.75 0.72 0.55 1.0"/>
<!-- 限高杆 -->
<geom pos="6.2 -9.0 0.155"
type="cylinder"
size="0.025 0.155"
quat="1.0 0.0 0.0 0.0"
rgba="0.8 0.1 0.1 1.0" />
<geom pos="5.2 -9.0 0.155"
type="cylinder"
size="0.025 0.155"
quat="1.0 0.0 0.0 0.0"
rgba="0.8 0.1 0.1 1.0" />
<geom pos="5.7 -9.0 0.325"
type="cylinder"
size="0.015 0.5"
quat="0.7071068 0.0 0.7071068 0.0"
rgba="1.0 0.9 0.4 1.0"/>
<!-- 1m × 1m 正方形颜色块,出发区-->
<geom pos="3.7 -9.0 0.0"
type="box"
size="0.5 0.5 0.001"
rgba="1.0 0.0 0.0 0.35"
contype="0"
conaffinity="0" />
<!-- 10cm梯形台阶:T型楼梯,最高平台与 x=5.7 y=-3.5 平台在y轴方向对齐 -->
<geom pos="1.80 -4.75 0.05" type="box" size="0.15 0.5 0.05" quat="0.7071068 0.0 0.0 0.7071068" rgba="0.75 0.72 0.55 1.0" />
<geom pos="1.80 -4.45 0.15" type="box" size="0.15 0.5 0.05" quat="0.7071068 0.0 0.0 0.7071068" rgba="0.75 0.72 0.55 1.0"/>
<geom pos="1.80 -4.15 0.25" type="box" size="0.15 0.5 0.05" quat="0.7071068 0.0 0.0 0.7071068" rgba="0.75 0.72 0.55 1.0"/>
<!-- 最高平台:y = -3.50,与目标平台y轴对齐 -->
<geom pos="1.80 -3.50 0.35" type="box" size="0.5 0.5 0.05" quat="0.7071068 0.0 0.0 0.7071068" rgba="0.75 0.72 0.55 1.0"/>
<geom pos="1.80 -2.85 0.25" type="box" size="0.15 0.5 0.05" quat="0.7071068 0.0 0.0 0.7071068" rgba="0.75 0.72 0.55 1.0"/>
<geom pos="1.80 -2.55 0.15" type="box" size="0.15 0.5 0.05" quat="0.7071068 0.0 0.0 0.7071068" rgba="0.75 0.72 0.55 1.0"/>
<geom pos="1.80 -2.25 0.05" type="box" size="0.15 0.5 0.05" quat="0.7071068 0.0 0.0 0.7071068" rgba="0.75 0.72 0.55 1.0"/>
<!-- 顶部平台向 +x 方向连接地面的10cm台阶,同样y轴移动到 -3.50 -->
<geom pos="2.45 -3.50 0.25" type="box" size="0.15 0.5 0.05" quat="1.0 0.0 0.0 0.0" rgba="0.75 0.72 0.55 1.0"/>
<geom pos="2.75 -3.50 0.15" type="box" size="0.15 0.5 0.05" quat="1.0 0.0 0.0 0.0" rgba="0.75 0.72 0.55 1.0"/>
<geom pos="3.05 -3.50 0.05" type="box" size="0.15 0.5 0.05" quat="1.0 0.0 0.0 0.0" rgba="0.75 0.72 0.55 1.0"/>
<!-- 斜坡木桥A木桥B -->
<geom pos="1.8 -0.88 0.1" type="box" size="0.40 0.5 0.005" quat="0.701836 0.086175 -0.086175 0.701836" rgba="0.75 0.72 0.55 1.0"/>
<geom pos="1.8 0.0 0.10" type="box" size="0.5 0.5 0.10" quat="1.0 0.0 0.0 0.0" rgba="0.75 0.72 0.55 1.0"/>
<geom pos="2.65 0.0 0.10" type="box" size="0.2 0.5 0.10" quat="1.0 0.0 0.0 0.0" rgba="0.75 0.72 0.55 1.0"/>
<geom pos="3.2 0.0 0.10" type="box" size="0.2 0.5 0.10" quat="1.0 0.0 0.0 0.0" rgba="0.75 0.72 0.55 1.0"/>
<geom pos="3.75 0.0 0.10" type="box" size="0.2 0.5 0.10" quat="1.0 0.0 0.0 0.0" rgba="0.75 0.72 0.55 1.0"/>
<geom pos="4.3 0.0 0.10" type="box" size="0.2 0.5 0.10" quat="1.0 0.0 0.0 0.0" rgba="0.75 0.72 0.55 1.0"/>
<geom pos="4.85 0.0 0.10" type="box" size="0.2 0.5 0.10" quat="1.0 0.0 0.0 0.0" rgba="0.75 0.72 0.55 1.0"/>
<geom pos="5.7 -0.5 0.10" type="box" size="0.5 1.0 0.10" quat="1.0 0.0 0.0 0.0" rgba="0.75 0.72 0.55 1.0"/>
<geom pos="4.8002 -1.0 0.0951"
type="box"
size="0.4133 0.5 0.005"
quat="0.992546 0.0 -0.121869 0.0"
rgba="0.75 0.72 0.55 1.0"/>
<geom pos="5.35 -2.25 0.10" type="box" size="0.1 0.75 0.10" quat="1.0 0.0 0.0 0.0" rgba="0.75 0.72 0.55 1.0"/>
<geom pos="5.65 -2.25 0.10" type="box" size="0.1 0.75 0.10" quat="1.0 0.0 0.0 0.0" rgba="0.75 0.72 0.55 1.0"/>
<geom pos="5.95 -2.25 0.10" type="box" size="0.1 0.75 0.10" quat="1.0 0.0 0.0 0.0" rgba="0.75 0.72 0.55 1.0"/>
<geom pos="5.7 -3.5 0.10" type="box" size="0.5 0.5 0.10" quat="1.0 0.0 0.0 0.0" rgba="0.75 0.72 0.55 1.0"/>
<!-- 10度斜坡:宽4m,斜坡 y正方向边缘 与平台 y正方向边缘 对齐 -->
<geom pos="4.6338 -5.0 0.0951"
type="box"
size="0.5759 2.0 0.005"
quat="0.9961947 0.0 -0.0871557 0.0"
rgba="0.75 0.72 0.55 1.0"/>
<!-- 新建10度斜坡:宽3m,高端与前一个10度斜坡高端衔接,向+x方向下坡 -->
<geom pos="5.7681 -5.5 0.0951"
type="box"
size="0.5759 1.5 0.005"
quat="0.9961947 0.0 0.0871557 0.0"
rgba="0.75 0.72 0.55 1.0"/>
<!--绕杆-->
<!-- 直径1m圆形颜色块,仅显示,不碰撞 -->
<geom pos="1.8 -10.1 0.0"
type="cylinder"
size="0.1 0.001"
rgba="1.0 0.0 0.0 0.35"
contype="0"
conaffinity="0" />
<geom pos="3.2 -12.5 0.0"
type="cylinder"
size="0.1 0.001"
rgba="1.0 0.0 0.0 0.35"
contype="0"
conaffinity="0" />
<geom pos="1.55 -12.75 0.0"
type="cylinder"
size="0.1 0.001"
rgba="1.0 0.0 0.0 0.35"
contype="0"
conaffinity="0" />
<!-- 原杆 -->
<geom pos="1.8 -10.5 0.02"
type="cylinder"
size="0.05 0.02"
quat="1.0 0.0 0.0 0.0"
rgba="0.75 0.72 0.55 1.0" />
<geom pos="1.8 -10.5 0.37"
type="cylinder"
size="0.015 0.33"
quat="1.0 0.0 0.0 0.0"
rgba="0.75 0.72 0.55 1.0" />
<!-- y轴负方向第1根:间隔1m -->
<geom pos="1.8 -11.5 0.02"
type="cylinder"
size="0.05 0.02"
quat="1.0 0.0 0.0 0.0"
rgba="0.75 0.72 0.55 1.0" />
<geom pos="1.8 -11.5 0.37"
type="cylinder"
size="0.015 0.33"
quat="1.0 0.0 0.0 0.0"
rgba="0.75 0.72 0.55 1.0" />
<!-- y轴负方向第2根:继续间隔1m -->
<geom pos="1.8 -12.5 0.02"
type="cylinder"
size="0.05 0.02"
quat="1.0 0.0 0.0 0.0"
rgba="0.75 0.72 0.55 1.0" />
<geom pos="1.8 -12.5 0.37"
type="cylinder"
size="0.015 0.33"
quat="1.0 0.0 0.0 0.0"
rgba="0.75 0.72 0.55 1.0" />
<!-- x轴正方向第3根:继续间隔1m -->
<geom pos="2.8 -12.5 0.02"
type="cylinder"
size="0.05 0.02"
quat="1.0 0.0 0.0 0.0"
rgba="0.75 0.72 0.55 1.0" />
<geom pos="2.8 -12.5 0.37"
type="cylinder"
size="0.015 0.33"
quat="1.0 0.0 0.0 0.0"
rgba="0.75 0.72 0.55 1.0" />
<!--===================================================================其他障碍=====================================================================================-->
<!-- 5cm台阶 -->
<geom pos="1.0 2.0 0.025" type="box" size="0.15 1.0 0.025" quat="1.0 0.0 0.0 0.0" />
<geom pos="1.3 2.0 0.075" type="box" size="0.15 1.0 0.025" quat="1.0 0.0 0.0 0.0" />
<geom pos="1.6 2.0 0.125" type="box" size="0.15 1.0 0.025" quat="1.0 0.0 0.0 0.0" />
<geom pos="1.9 2.0 0.175" type="box" size="0.15 1.0 0.025" quat="1.0 0.0 0.0 0.0" />
<geom pos="2.2 2.0 0.225" type="box" size="0.15 1.0 0.025" quat="1.0 0.0 0.0 0.0" />
<geom pos="2.5 2.0 0.275" type="box" size="0.15 1.0 0.025" quat="1.0 0.0 0.0 0.0" />
<geom pos="2.8 2.0 0.325" type="box" size="0.15 1.0 0.025" quat="1.0 0.0 0.0 0.0" />
<geom pos="3.45 2.0 0.375" type="box" size="0.5 1.0 0.025" quat="1.0 0.0 0.0 0.0" />
<geom pos="4.1 2.0 0.325" type="box" size="0.15 1.0 0.025" quat="1.0 0.0 0.0 0.0" />
<geom pos="4.4 2.0 0.275" type="box" size="0.15 1.0 0.025" quat="1.0 0.0 0.0 0.0" />
<geom pos="4.7 2.0 0.225" type="box" size="0.15 1.0 0.025" quat="1.0 0.0 0.0 0.0" />
<geom pos="5.0 2.0 0.175" type="box" size="0.15 1.0 0.025" quat="1.0 0.0 0.0 0.0" />
<geom pos="5.3 2.0 0.125" type="box" size="0.15 1.0 0.025" quat="1.0 0.0 0.0 0.0" />
<geom pos="5.6 2.0 0.075" type="box" size="0.15 1.0 0.025" quat="1.0 0.0 0.0 0.0" />
<geom pos="5.9 2.0 0.025" type="box" size="0.15 1.0 0.025" quat="1.0 0.0 0.0 0.0" />
<!-- 斜坡 -->
<geom pos="2.0 4.0 0.1" type="box" size="1.5 0.75 0.005" quat="0.9950041652780258 0.0 -0.09983341664682815 0.0" />
<geom pos="1.4 6.0 0.165" type="box" size="0.1 0.75 0.0049999999999999975" quat="1.0 0.0 0.0 0.0"/>
<geom pos="1.6 6.0 0.275" type="box" size="0.1 0.75 0.0049999999999999975" quat="1.0 0.0 0.0 0.0"/>
<geom pos="1.8 6.0 0.385" type="box" size="0.1 0.75 0.0049999999999999975" quat="1.0 0.0 0.0 0.0"/>
<geom pos="2.0 6.0 0.495" type="box" size="0.1 0.75 0.0049999999999999975" quat="1.0 0.0 0.0 0.0"/>
<geom pos="2.2 6.0 0.605" type="box" size="0.1 0.75 0.0049999999999999975" quat="1.0 0.0 0.0 0.0"/>
<geom pos="2.4 6.0 0.715" type="box" size="0.1 0.75 0.0049999999999999975" quat="1.0 0.0 0.0 0.0"/>
<geom pos="2.5999999999999996 6.0 0.825" type="box" size="0.1 0.75 0.0049999999999999975" quat="1.0 0.0 0.0 0.0"/>
<geom pos="2.8 6.0 0.9349999999999999" type="box" size="0.1 0.75 0.0049999999999999975" quat="1.0 0.0 0.0 0.0"/>
<geom pos="3.0 6.0 1.045" type="box" size="0.1 0.75 0.0049999999999999975" quat="1.0 0.0 0.0 0.0"/>
<geom pos="-2.3179973398407565 5.173660321080885 -0.25" type="box" size="0.2568216778785459 0.2608020098770089 0.2619541072037832" quat="0.9930658271270357 -0.05910360995856133 -0.06731065544310916 0.0761334482746007"/>
<geom pos="-2.3179973398407565 5.3620612607436735 -0.25" type="box" size="0.23778028947050467 0.26051225137569556 0.27137457425982286" quat="0.9959802827127009 0.07435995796871331 0.0004862731479656538 -0.04993632582444846"/>
<geom pos="-2.3179973398407565 5.545897059602109 -0.25" type="box" size="0.23841994611378936 0.2717839884518381 0.22585827399286504" quat="0.9983504429181294 -0.004811901627841528 0.03471877670768104 -0.045473566737405234"/>
<geom pos="-2.3179973398407565 5.7436240471772795 -0.25" type="box" size="0.2552179019048769 0.2548992578792955 0.22547735976326444" quat="0.9968270877924189 -0.029673908987198697 0.06777847718526858 -0.029347814214192768"/>
<geom pos="-2.3179973398407565 5.940214647011584 -0.25" type="box" size="0.24313116620329878 0.2372064979204117 0.26079933745117434" quat="0.9952106364954509 0.05088987714749159 -0.07605843245051555 -0.03436748846516202"/>
<geom pos="-2.3179973398407565 6.165430585901471 -0.25" type="box" size="0.24786042386990592 0.2322559052231109 0.2644037606269708" quat="0.9936075351397807 -0.05017393314139304 0.06986162224674641 -0.07311632022760194"/>
<geom pos="-2.3179973398407565 6.315657865031069 -0.25" type="box" size="0.23704265198840277 0.24982080672772003 0.2530694373586838" quat="0.9981716459301547 0.036179123385437884 0.04523497974247521 0.017269420947002005"/>
<geom pos="-2.3179973398407565 6.489372835072359 -0.25" type="box" size="0.2647428927965494 0.2716292502682415 0.23725049444938928" quat="0.9954041516289313 0.019099981466976248 0.07663366510923347 0.05415761257454444"/>
<geom pos="-2.094119617957536 5.194943631570213 -0.25" type="box" size="0.23176840693038148 0.23782936054799508 0.2282032657053922" quat="0.9973366591969123 0.030692664684553082 -0.030015392527106853 0.058962910104125923"/>
<geom pos="-2.094119617957536 5.441090326561234 -0.25" type="box" size="0.2602142310926322 0.27213502289176367 0.2574009440402366" quat="0.9948915480473169 0.023650461407535205 0.08508706956405496 -0.04890453856469255"/>
<geom pos="-2.094119617957536 5.642958951230403 -0.25" type="box" size="0.24800055056479955 0.24050676557282252 0.23522489807277194" quat="0.9912055235117067 0.06188914817453858 -0.09720856678264424 -0.0650525790586179"/>
<geom pos="-2.094119617957536 5.884810142659838 -0.25" type="box" size="0.24637516954806898 0.24364583504893206 0.2682443460752295" quat="0.9964495083946477 -0.07467561549070643 -0.038754439691442995 0.003165924091257204"/>
<geom pos="-2.094119617957536 6.129893093768145 -0.25" type="box" size="0.2378958269703999 0.25045408022075055 0.24760364656411665" quat="0.9946240462872651 -0.03963038800955788 -0.08917648605658504 0.03464091840526007"/>
<geom pos="-2.094119617957536 6.31135792935651 -0.25" type="box" size="0.2612154064649683 0.2252849660353503 0.26933214617336004" quat="0.997742809172301 0.019590451180868298 0.06391648942914147 -0.006339033565912353"/>
<geom pos="-2.094119617957536 6.4905285510291915 -0.25" type="box" size="0.22768983323309258 0.23025468157122184 0.2748062344121069" quat="0.9940843963100783 0.05105793020576152 0.009164090402224958 -0.0954218016127878"/>
<geom pos="-2.094119617957536 6.650993287072798 -0.25" type="box" size="0.25443787917913946 0.24575387105878618 0.22934424641420587" quat="0.9953832160779188 -0.0075142647566912866 0.08305501342257929 0.04751477371219154"/>
<geom pos="-1.8951777534978893 5.178742263102535 -0.25" type="box" size="0.256127371544264 0.24353861032614957 0.2714578153598507" quat="0.996547165679354 -0.008558846106514282 0.009384988866828401 0.08205129318749771"/>
<geom pos="-1.8951777534978893 5.353646654030374 -0.25" type="box" size="0.23858897994497189 0.2426691342857623 0.26961659613969635" quat="0.997689480058865 0.014145078555906384 0.009115651940537827 -0.06582190381793727"/>
<geom pos="-1.8951777534978893 5.575640096199311 -0.25" type="box" size="0.24430646334884096 0.2676093509240798 0.23693271670520474" quat="0.9976019172675967 -0.06794745094616256 0.006187887696065785 -0.011630503849579829"/>
<geom pos="-1.8951777534978893 5.728196634759373 -0.25" type="box" size="0.25668697148716296 0.2743986770827004 0.23696403861156407" quat="0.9946311966964959 -0.0774649076913635 0.05866511796477466 0.03558615698054331"/>
<geom pos="-1.8951777534978893 5.954288148947323 -0.25" type="box" size="0.2748179458028994 0.25407956175122554 0.25142548243710355" quat="0.9927720663552536 0.03885622734718657 0.06180632563910765 0.09525647469886914"/>
<geom pos="-1.8951777534978893 6.198076908897641 -0.25" type="box" size="0.23522918501552104 0.2714895927340788 0.23659922178360912" quat="0.9944408196408429 0.027722532803612636 -0.06883505448003607 -0.07470376618171105"/>
<geom pos="-1.8951777534978893 6.356335079330304 -0.25" type="box" size="0.253243646653926 0.26648639763264487 0.22751627090926196" quat="0.9924345646356405 0.06351743627133029 0.09661714031088077 -0.041283149154730255"/>
<geom pos="-1.8951777534978893 6.6037178705715744 -0.25" type="box" size="0.2664884535468762 0.26472237049442093 0.2545826559482188" quat="0.996208812433608 0.04792667434016892 0.03088022810200046 -0.06570728596343135"/>
<geom pos="-1.7450143557797366 5.181798049538029 -0.25" type="box" size="0.22764974830145798 0.2314500042225232 0.26635647118774647" quat="0.996420562587967 -0.02530598413067966 -0.01712092616039989 -0.07881968983996092"/>
<geom pos="-1.7450143557797366 5.396539066742657 -0.25" type="box" size="0.24515338305934362 0.25502436912192245 0.23509532716059323" quat="0.9974817825235419 0.033698559354477776 -0.06057332552735373 -0.01501242370995589"/>
<geom pos="-1.7450143557797366 5.5477605493550115 -0.25" type="box" size="0.2368415768982088 0.2653984778068547 0.25193186806340717" quat="0.9933816957092091 -0.04426535864216467 0.0892264769079807 0.057201577537394625"/>
<geom pos="-1.7450143557797366 5.764238738853998 -0.25" type="box" size="0.257475541143157 0.25587521442146555 0.2684267956125346" quat="0.9955849335110497 0.004076118120639651 -0.09299366924131539 0.012091439447074191"/>
<geom pos="-1.7450143557797366 5.942956213887727 -0.25" type="box" size="0.23647345784635188 0.22779489919605103 0.2690566454457882" quat="0.9997372307105926 0.020286738832439623 -0.010113822112874779 0.003410038259163467"/>
<geom pos="-1.7450143557797366 6.162981335139796 -0.25" type="box" size="0.2336152227884161 0.23785626414299832 0.26272786991330355" quat="0.9954569549676405 0.08638675499005252 -0.03150236191317218 -0.024705881136540285"/>
<geom pos="-1.7450143557797366 6.344025407207907 -0.25" type="box" size="0.2364006101773331 0.23674709170116234 0.2660167000427503" quat="0.9941020005048972 -0.09350614404282417 -0.05493059192638792 0.0006660998579442658"/>
<geom pos="-1.7450143557797366 6.5791872438688825 -0.25" type="box" size="0.259653062502181 0.26359758888480966 0.27170867851854713" quat="0.9955751902075182 0.06572529509454274 0.04059253213564211 -0.05350207998588654"/>
<geom pos="-1.4950537649717406 5.196975242498044 -0.25" type="box" size="0.24902209995429173 0.24604186796843594 0.26555264385759036" quat="0.9981753741369879 0.027059282981497578 0.02078151255996191 0.049818133312398136"/>
<geom pos="-1.4950537649717406 5.415093649392617 -0.25" type="box" size="0.22561317519118573 0.23246623591498758 0.2516053992906602" quat="0.9961431033663982 -0.019679813255757937 0.07777937635153075 0.035524515199325105"/>
<geom pos="-1.4950537649717406 5.596072881787104 -0.25" type="box" size="0.2545347271371952 0.2527292932516396 0.272364707011277" quat="0.9987990019474599 -0.0468132050914785 0.002764373695484487 -0.01419280718860587"/>
<geom pos="-1.4950537649717406 5.788444207457658 -0.25" type="box" size="0.257823578756761 0.22815201323013437 0.2506904868770564" quat="0.9907800223935689 0.08207700037219429 -0.06679273748567588 -0.08459931119619979"/>
<geom pos="-1.4950537649717406 5.962479724512656 -0.25" type="box" size="0.23447002037921025 0.260091883647859 0.2613547781123637" quat="0.994185747243896 -0.045779429335849345 -0.09537527521663794 -0.020062420196245392"/>
<geom pos="-1.4950537649717406 6.137620949716146 -0.25" type="box" size="0.25502378303486756 0.24137626830945555 0.26521755821448284" quat="0.9954511067004865 0.04827241542514884 0.023378972724717166 -0.07874193109224191"/>
<geom pos="-1.4950537649717406 6.345742058941403 -0.25" type="box" size="0.23763376291279575 0.27259418014745557 0.24184880568666417" quat="0.9979730938550316 -0.0521706328108408 -0.03256129013590577 0.01636127740178204"/>
<geom pos="-1.4950537649717406 6.548966807280673 -0.25" type="box" size="0.23004532593424165 0.24736965888987583 0.22917624237245732" quat="0.993938322382385 -0.041286377558295506 -0.09233464220936707 0.04308549844056845"/>
<geom pos="-1.2872521554407157 5.194072124237239 -0.25" type="box" size="0.2725857334366114 0.23611730648841156 0.25109418723334265" quat="0.9870880287314421 -0.09538067591152324 -0.0888119213223197 -0.09312460914696315"/>
<geom pos="-1.2872521554407157 5.418639818976418 -0.25" type="box" size="0.2326397456179607 0.2609646699674687 0.2717115772948157" quat="0.9928206111485406 -0.07383059897166898 -0.08473752136579614 0.040936892980589765"/>
<geom pos="-1.2872521554407157 5.655974569843163 -0.25" type="box" size="0.22633109461398734 0.25911291311168594 0.23532484499883452" quat="0.9947769304653071 -0.023834507399340135 0.09176246279588879 -0.037820963666801724"/>
<geom pos="-1.2872521554407157 5.8981628648303595 -0.25" type="box" size="0.27278934520816167 0.2559269445001904 0.26076472835929454" quat="0.9936318869346414 0.0561019165840355 0.09234219275279033 0.0319557140415977"/>
<geom pos="-1.2872521554407157 6.064939027275534 -0.25" type="box" size="0.2481756437845515 0.2613413397088905 0.24788858471207542" quat="0.9992310163557966 0.006919915638721734 0.03652449975321466 -0.012468024618680441"/>
<geom pos="-1.2872521554407157 6.288670079370122 -0.25" type="box" size="0.2574127585385611 0.27445220033632356 0.22507618952620437" quat="0.9984337612791753 0.04947883993440395 -0.0010074967830211658 -0.026093173185657285"/>
<geom pos="-1.2872521554407157 6.4987760234638605 -0.25" type="box" size="0.2442462188069663 0.2639082925274208 0.24918893213917415" quat="0.9910480688126146 0.08639971284060838 -0.0903343762232188 -0.04688832899783648"/>
<geom pos="-1.2872521554407157 6.675611985491267 -0.25" type="box" size="0.2507168814441121 0.26699708557208374 0.26588306060638556" quat="0.9968882348111167 0.009466759168649483 -0.06920917552433178 0.03652831489763918"/>
<geom pos="-1.0678149575697586 5.238251070535694 -0.25" type="box" size="0.2331754586513582 0.22873009754409884 0.2593258638743009" quat="0.9962563091989393 0.014506022500180732 0.069646748226122 0.049114887295595266"/>
<geom pos="-1.0678149575697586 5.471732496077581 -0.25" type="box" size="0.2653495693182789 0.26581370557074685 0.2509273010188512" quat="0.9948019811445705 -0.05898118120008214 0.04034485064897968 -0.07254330845220838"/>
<geom pos="-1.0678149575697586 5.691153717662407 -0.25" type="box" size="0.26309077142424103 0.26536949948987093 0.26566703066149744" quat="0.998331608401392 -0.025703385975953945 -0.05139460706256987 0.005650661991725779"/>
<geom pos="-1.0678149575697586 5.938910564562482 -0.25" type="box" size="0.23082606038737274 0.23890770539441533 0.25941695887199245" quat="0.99040745217393 -0.09494180013051996 0.05600240658814475 -0.08332384846283197"/>
<geom pos="-1.0678149575697586 6.13746533389903 -0.25" type="box" size="0.2676431215498913 0.2569308659994288 0.24597694927356487" quat="0.9955894165044442 0.04511524606234168 -0.003741035154326279 -0.08217258042101841"/>
<geom pos="-1.0678149575697586 6.328213254628996 -0.25" type="box" size="0.24188540919954635 0.25556145122229207 0.2605619987765001" quat="0.9929731934387934 -0.06598945456828725 -0.06809928840246085 0.07079629875087447"/>
<geom pos="-1.0678149575697586 6.554891603524267 -0.25" type="box" size="0.23121916641107804 0.25266417867731916 0.25489063309084503" quat="0.9984565221200774 -0.02714563973423854 0.029423903667849492 0.03849573446816443"/>
<geom pos="-1.0678149575697586 6.718482966003368 -0.25" type="box" size="0.27418971733780156 0.2623437838864593 0.23694037285314332" quat="0.9968347573500278 0.015128289848683302 0.06990516881209438 0.03471121949050888"/>
<geom pos="-0.8851136474992356 5.233272057743225 -0.25" type="box" size="0.2587161160845902 0.2542459313914242 0.25268742624288776" quat="0.9956323623605605 0.07455213252171443 -0.05585558926184348 0.006191260373025539"/>
<geom pos="-0.8851136474992356 5.410759300563648 -0.25" type="box" size="0.24019625793101548 0.2509280955260936 0.26698317271101046" quat="0.9960056830073374 0.025487333399660517 0.08516393482003458 -0.008377318140719903"/>
<geom pos="-0.8851136474992356 5.622546965631826 -0.25" type="box" size="0.22527085609750916 0.22924847380626232 0.23073331588883172" quat="0.9982201065088221 0.016292210993739946 0.013620740418279952 0.05572843307423328"/>
<geom pos="-0.8851136474992356 5.856118124892678 -0.25" type="box" size="0.26833255247166926 0.2512767990265972 0.2502231376336179" quat="0.9914910532543448 0.0657880493114159 0.05073139628229043 -0.10021850784978792"/>
<geom pos="-0.8851136474992356 6.010914595891683 -0.25" type="box" size="0.24926441451407527 0.22868800964152894 0.26501630221174116" quat="0.990736605756697 -0.0765632176593298 -0.09876375004658954 0.05314859727296924"/>
<geom pos="-0.8851136474992356 6.1657945570092965 -0.25" type="box" size="0.26823427325895977 0.263134568634285 0.23692064318485426" quat="0.9903439387899988 0.07219524819688558 0.09310840228148876 0.07305856872598579"/>
<geom pos="-0.8851136474992356 6.383066094410735 -0.25" type="box" size="0.23772929143507357 0.2619329708548053 0.23258884134606547" quat="0.9928463525385446 0.07348810370848206 0.09252710448645944 -0.017156742103069993"/>
<geom pos="-0.8851136474992356 6.551482176174038 -0.25" type="box" size="0.25127741834221506 0.25307864976328337 0.234931895271364" quat="0.994062479132312 -0.084918495271965 -0.05565932062022146 -0.03912386445844099"/>
<geom pos="-0.6441452943469552 5.193190826541208 -0.25" type="box" size="0.27016649011158844 0.23778885128164629 0.25859862297032477" quat="0.9957774962333289 0.08893738517887846 -0.021654911548168992 0.006955883744530942"/>
<geom pos="-0.6441452943469552 5.407266358883468 -0.25" type="box" size="0.24982888074520473 0.26972381569065607 0.2275629646713632" quat="0.9942571418988088 0.02444442288698024 0.050336521935401994 -0.09122193010664256"/>
<geom pos="-0.6441452943469552 5.56363948710079 -0.25" type="box" size="0.24725848381417467 0.2326432801330426 0.2476341019968084" quat="0.9935769557551848 -0.05688836927692267 -0.06858315894908604 0.0697488117593134"/>
<geom pos="-0.6441452943469552 5.716461923308758 -0.25" type="box" size="0.226746163574222 0.25188961955216527 0.24650452053954758" quat="0.9981029078160676 0.03471313574303335 -0.0493522060742233 -0.012245136651074443"/>
<geom pos="-0.6441452943469552 5.896430073001983 -0.25" type="box" size="0.25284949298017617 0.23421620066432108 0.2621382648463894" quat="0.9996413412447853 0.009523771195346772 -0.02374945051322109 -0.007902547492127014"/>
<geom pos="-0.6441452943469552 6.110845613879558 -0.25" type="box" size="0.23421403581041014 0.2504556848552827 0.24096555776925194" quat="0.9982371379292613 0.05906199571247059 0.004184466367765714 0.004097238396071534"/>
<geom pos="-0.6441452943469552 6.301410327752269 -0.25" type="box" size="0.2296817145699627 0.2701766916372966 0.22803599234835198" quat="0.9993879202059675 0.00903361239651759 0.0071600522792900426 -0.03302896372607247"/>
<geom pos="-0.6441452943469552 6.470340592771366 -0.25" type="box" size="0.2742166750011587 0.23990439594655139 0.2609404931878803" quat="0.9954980192986956 -0.06477558432537366 -0.03478863652617152 0.059812774691783824"/>
<geom pos="-0.43033316974190594 5.176946043237525 -0.25" type="box" size="0.2511344405622137 0.26383180387822514 0.2729516287367074" quat="0.9939152287364423 -0.054017256979398534 -0.08418383902399898 -0.0461273810376057"/>
<geom pos="-0.43033316974190594 5.409693792302493 -0.25" type="box" size="0.23878438774624536 0.22858057493504688 0.24808981791323623" quat="0.9942721168135948 -0.06322741578652484 -0.032958930763236916 -0.0796175891553822"/>
<geom pos="-0.43033316974190594 5.573593446642387 -0.25" type="box" size="0.2647545698926724 0.25215736713350106 0.25522885339490087" quat="0.9971918839448468 -0.004732654353889047 0.07222000940536273 0.019241071144380294"/>
<geom pos="-0.43033316974190594 5.819531161619798 -0.25" type="box" size="0.2538318010250847 0.23661725487197 0.26323696729639623" quat="0.9929867679849618 0.07588268800385974 -0.046355180482866284 -0.07791208834634974"/>
<geom pos="-0.43033316974190594 6.047888701789067 -0.25" type="box" size="0.25684720236482583 0.25568474221031684 0.24397094296107352" quat="0.9925256546500537 -0.08214715587137877 0.06615741576234473 0.06138294537877935"/>
<geom pos="-0.43033316974190594 6.283676056613722 -0.25" type="box" size="0.2432692787269645 0.2742601402399693 0.2689467974776609" quat="0.9989897410981501 0.0047037010179340685 0.0014590493232283363 -0.04466814919444852"/>
<geom pos="-0.43033316974190594 6.458239009480634 -0.25" type="box" size="0.2474330649412728 0.2551435998627988 0.23002773988805483" quat="0.9982311862818315 0.0506459597703481 0.025989046975463247 -0.01714802993392417"/>
<geom pos="-0.43033316974190594 6.703309377175586 -0.25" type="box" size="0.2301029552870502 0.2556223065028505 0.2349557527965884" quat="0.9948672058648923 -0.034182171957127715 -0.0030330068097560517 -0.09519255582537542"/>
<geom type="hfield" hfield="perlin_hfield" pos="-1.5 4.0 0.0" quat="1.0 0.0 0.0 0.0"/>
<geom type="hfield" hfield="image_hfield" pos="-1.5 2.0 0.0" quat="0.7073882691671998 0.0 0.0 -0.706825181105366"/>
</worldbody>
</mujoco>
@@ -0,0 +1,157 @@
<mujoco model="wheelleg">
<compiler angle="radian" meshdir="meshes/"/>
<default>
<geom margin="0"/>
</default>
<asset>
<mesh name="base_link" content_type="model/stl" file="base_link.STL"/>
<mesh name="fl_hip_abduction_Link" content_type="model/stl" file="fl_hip_abduction_Link.STL"/>
<mesh name="fl_hip_pitch_Link" content_type="model/stl" file="fl_hip_pitch_Link.STL"/>
<mesh name="fl_knee_Link" content_type="model/stl" file="fl_knee_Link.STL"/>
<mesh name="fl_wheel_Link" content_type="model/stl" file="fl_wheel_Link.STL"/>
<mesh name="fr_hip_abduction_Link" content_type="model/stl" file="fr_hip_abduction_Link.STL"/>
<mesh name="fr_hip_pitch_Link" content_type="model/stl" file="fr_hip_pitch_Link.STL"/>
<mesh name="fr_knee_Link" content_type="model/stl" file="fr_knee_Link.STL"/>
<mesh name="fr_wheel_Link" content_type="model/stl" file="fr_wheel_Link.STL"/>
<mesh name="rl_hip_abduction_Link" content_type="model/stl" file="rl_hip_abduction_Link.STL"/>
<mesh name="rl_hip_pitch_Link" content_type="model/stl" file="rl_hip_pitch_Link.STL"/>
<mesh name="rl_knee_Link" content_type="model/stl" file="rl_knee_Link.STL"/>
<mesh name="rl_wheel_Link" content_type="model/stl" file="rl_wheel_Link.STL"/>
<mesh name="rr_hip_abduction_Link" content_type="model/stl" file="rr_hip_abduction_Link.STL"/>
<mesh name="rr_hip_pitch_Link" content_type="model/stl" file="rr_hip_pitch_Link.STL"/>
<mesh name="rr_knee_Link" content_type="model/stl" file="rr_knee_Link.STL"/>
<mesh name="rr_wheel_Link" content_type="model/stl" file="rr_wheel_Link.STL"/>
</asset>
<worldbody>
<body name="base_link">
<inertial pos="0.1517 0.0002 0.0542" mass="3.5" diaginertia="0.0215 0.0904 0.0985"/>
<joint type="free"/>
<geom type="mesh" contype="0" conaffinity="0" group="1" density="0" rgba="0.75294 0.75294 0.75294 1" mesh="base_link"/>
<geom size="0.178 0.1175 0.073" pos="0.1518 0 0.054" type="box" rgba="0.75294 0.75294 0.75294 1"/>
<body name="fl_hip_abduction_Link" pos="0.32826 0.066172 0.053981">
<inertial pos="0.0488 -0.0026 0.0007" mass="0.5" diaginertia="0.0003 0.0006 0.0005"/>
<joint name="fl_hip_abduction_joint" pos="0 0 0" axis="1 0 0" range="-0.436 0.611" actuatorfrcrange="-17 17" damping="0.01" frictionloss="0.01" armature="0.0042"/>
<geom type="mesh" contype="0" conaffinity="0" group="1" density="0" rgba="0.75294 0.75294 0.75294 1" mesh="fl_hip_abduction_Link"/>
<body name="fl_hip_pitch_Link" pos="0.06389 -0.027344 0.00010727" quat="0.999997 -0.0025023 0 0">
<inertial pos="0.0019 0.1119 -0.048" mass="0.935" diaginertia="0.0062 0.0064 0.001"/>
<joint name="fl_hip_pitch_joint" pos="0 0 0" axis="0 1 0" range="-2.58 2.58" actuatorfrcrange="-17 17" damping="0.01" frictionloss="0.01" armature="0.0042"/>
<geom type="mesh" contype="0" conaffinity="0" group="1" density="0" rgba="0.75294 0.75294 0.75294 1" mesh="fl_hip_pitch_Link"/>
<geom size="0.046 0.048" pos="0 0.048 0" quat="0.707105 0.707108 0 0" type="cylinder" rgba="0.75294 0.75294 0.75294 1"/>
<geom size="0.0435 0.0115 0.06" pos="0 0.1155 -0.06" type="box" rgba="0.75294 0.75294 0.75294 1"/>
<body name="fl_knee_Link" pos="0 0.1035 -0.25" quat="0.999997 0.0025023 0 0">
<inertial pos="0.0002 0.0242 -0.1539" mass="0.651" fullinertia="0.0042 0.0045 0.0005 0 0 0.0002"/>
<joint name="fl_knee_joint" pos="0 0 0" axis="0 1 0" range="-2.65 2.65" actuatorfrcrange="-17 17" damping="0.01" frictionloss="0.01" armature="0.0042"/>
<geom type="mesh" contype="0" conaffinity="0" group="1" density="0" rgba="0.75294 0.75294 0.75294 1" mesh="fl_knee_Link"/>
<geom size="0.0475 0.015" pos="0 0.025 -0.20011" quat="0.707105 0.707108 0 0" type="cylinder" rgba="0.75294 0.75294 0.75294 1"/>
<geom size="0.015 0.0125 0.06" pos="0 0.0125 -0.09" type="box" rgba="0.75294 0.75294 0.75294 1"/>
<body name="fl_wheel_Link" pos="0 0.014699 -0.20011">
<inertial pos="-0.0002 0.0407 -0.0001" mass="0.53" diaginertia="0.0017 0.0032 0.0017"/>
<joint name="fl_wheel_joint" pos="0 0 0" axis="0 1 0" actuatorfrcrange="-17 17" damping="0.01" frictionloss="0.01" armature="0.0042"/>
<geom type="mesh" contype="0" conaffinity="0" group="1" density="0" rgba="0.75294 0.75294 0.75294 1" mesh="fl_wheel_Link"/>
<geom size="0.1 0.015" pos="0 0.04074 0" quat="0.707105 0.707108 0 0" type="cylinder" rgba="0.75294 0.75294 0.75294 1"/>
</body>
</body>
</body>
</body>
<body name="fr_hip_abduction_Link" pos="0.32826 -0.065853 0.054034">
<inertial pos="0.0488 0.0026 0.0008" mass="0.5" diaginertia="0.0003 0.0006 0.0005"/>
<joint name="fr_hip_abduction_joint" pos="0 0 0" axis="1 0 0" range="-0.611 0.436" actuatorfrcrange="-17 17" damping="0.01" frictionloss="0.01" armature="0.0042"/>
<geom type="mesh" contype="0" conaffinity="0" group="1" density="0" rgba="0.75294 0.75294 0.75294 1" mesh="fr_hip_abduction_Link"/>
<body name="fr_hip_pitch_Link" pos="0.06389 0.027311 -0.00036027" quat="0.999976 -0.00686995 0 0">
<inertial pos="-0.0019 -0.1119 -0.048" mass="0.935" diaginertia="0.0062 0.0064 0.001"/>
<joint name="fr_hip_pitch_joint" pos="0 0 0" axis="0 1 0" range="-2.58 2.58" actuatorfrcrange="-17 17" damping="0.01" frictionloss="0.01" armature="0.0042"/>
<geom type="mesh" contype="0" conaffinity="0" group="1" density="0" rgba="0.75294 0.75294 0.75294 1" mesh="fr_hip_pitch_Link"/>
<geom size="0.046 0.048" pos="0 -0.048 0" quat="0.707105 0.707108 0 0" type="cylinder" rgba="0.75294 0.75294 0.75294 1"/>
<geom size="0.0435 0.0115 0.06" pos="0 -0.1155 -0.06" type="box" rgba="0.75294 0.75294 0.75294 1"/>
<body name="fr_knee_Link" pos="-0.00075079 -0.1035 -0.25" quat="0.999976 0.00686995 0 0">
<inertial pos="-0.0002 -0.0242 -0.1539" mass="0.651" fullinertia="0.0042 0.0045 0.0005 0 0 0.0001"/>
<joint name="fr_knee_joint" pos="0 0 0" axis="0 1 0" range="-2.65 2.65" actuatorfrcrange="-17 17" damping="0.01" frictionloss="0.01" armature="0.0042"/>
<geom type="mesh" contype="0" conaffinity="0" group="1" density="0" rgba="0.75294 0.75294 0.75294 1" mesh="fr_knee_Link"/>
<geom size="0.0475 0.015" pos="0 -0.025 -0.1998" quat="0.707105 0.707108 0 0" type="cylinder" rgba="0.75294 0.75294 0.75294 1"/>
<geom size="0.015 0.0125 0.06" pos="0 -0.0125 -0.09" type="box" rgba="0.75294 0.75294 0.75294 1"/>
<body name="fr_wheel_Link" pos="0 -0.018447 -0.1998">
<inertial pos="0.0002 -0.0407 -0.0001" mass="0.53" diaginertia="0.0017 0.0032 0.0017"/>
<joint name="fr_wheel_joint" pos="0 0 0" axis="0 1 0" actuatorfrcrange="-17 17" damping="0.01" frictionloss="0.01" armature="0.0042"/>
<geom type="mesh" contype="0" conaffinity="0" group="1" density="0" rgba="0.75294 0.75294 0.75294 1" mesh="fr_wheel_Link"/>
<geom size="0.1 0.015" pos="0 -0.040735 0" quat="0.707105 0.707108 0 0" type="cylinder" rgba="0.75294 0.75294 0.75294 1"/>
</body>
</body>
</body>
</body>
<body name="rl_hip_abduction_Link" pos="-0.024743 0.066141 0.054034">
<inertial pos="-0.0488 -0.0026 -0.0008" mass="0.5" diaginertia="0.0003 0.0006 0.0005"/>
<joint name="rl_hip_abduction_joint" pos="0 0 0" axis="1 0 0" range="-0.436 0.611" actuatorfrcrange="-17 17" damping="0.01" frictionloss="0.01" armature="0.0042"/>
<geom type="mesh" contype="0" conaffinity="0" group="1" density="0" rgba="0.75294 0.75294 0.75294 1" mesh="rl_hip_abduction_Link"/>
<body name="rl_hip_pitch_Link" pos="-0.06389 -0.027309 0.00045509">
<inertial pos="0.0019 0.1119 -0.048" mass="0.935" diaginertia="0.0062 0.0064 0.001"/>
<joint name="rl_hip_pitch_joint" pos="0 0 0" axis="0 1 0" range="-2.58 2.58" actuatorfrcrange="-17 17" damping="0.01" frictionloss="0.01" armature="0.0042"/>
<geom type="mesh" contype="0" conaffinity="0" group="1" density="0" rgba="0.75294 0.75294 0.75294 1" mesh="rl_hip_pitch_Link"/>
<geom size="0.046 0.048" pos="0 0.048 0" quat="0.707105 0.707108 0 0" type="cylinder" rgba="0.75294 0.75294 0.75294 1"/>
<geom size="0.0435 0.0115 0.06" pos="0 0.1155 -0.06" type="box" rgba="0.75294 0.75294 0.75294 1"/>
<body name="rl_knee_Link" pos="0 0.099459 -0.25163">
<inertial pos="0.0002 0.0242 -0.1539" mass="0.651" fullinertia="0.0042 0.0045 0.0005 0 0 -0.0003"/>
<joint name="rl_knee_joint" pos="0 0 0" axis="0 1 0" range="-2.65 2.65" actuatorfrcrange="-17 17" damping="0.01" frictionloss="0.01" armature="0.0042"/>
<geom type="mesh" contype="0" conaffinity="0" group="1" density="0" rgba="0.75294 0.75294 0.75294 1" mesh="rl_knee_Link"/>
<geom size="0.0475 0.015" pos="0 0.025 -0.20027" quat="0.707105 0.707108 0 0" type="cylinder" rgba="0.75294 0.75294 0.75294 1"/>
<geom size="0.015 0.0125 0.06" pos="0 0.0125 -0.09" type="box" rgba="0.75294 0.75294 0.75294 1"/>
<body name="rl_wheel_Link" pos="0 0.012475 -0.20027">
<inertial pos="-0.0002 0.0407 -0.0001" mass="0.53" diaginertia="0.0017 0.0032 0.0017"/>
<joint name="rl_wheel_joint" pos="0 0 0" axis="0 1 0" actuatorfrcrange="-17 17" damping="0.01" frictionloss="0.01" armature="0.0042"/>
<geom type="mesh" contype="0" conaffinity="0" group="1" density="0" rgba="0.75294 0.75294 0.75294 1" mesh="rl_wheel_Link"/>
<geom size="0.1 0.015" pos="0 0.040737 0" quat="0.707105 0.707108 0 0" type="cylinder" rgba="0.75294 0.75294 0.75294 1"/>
</body>
</body>
</body>
</body>
<body name="rr_hip_abduction_Link" pos="-0.024743 -0.065884 0.053981">
<inertial pos="-0.0488 0.0026 0.0008" mass="0.5" diaginertia="0.0003 0.0006 0.0005"/>
<joint name="rr_hip_abduction_joint" pos="0 0 0" axis="1 0 0" range="-0.611 0.436" actuatorfrcrange="-17 17" damping="0.01" frictionloss="0.01" armature="0.0042"/>
<geom type="mesh" contype="0" conaffinity="0" group="1" density="0" rgba="0.75294 0.75294 0.75294 1" mesh="rr_hip_abduction_Link"/>
<body name="rr_hip_pitch_Link" pos="-0.06389 0.027341 0.00041625">
<inertial pos="-0.002 -0.1111 -0.0498" mass="0.935" diaginertia="0.0062 0.0064 0.001"/>
<joint name="rr_hip_pitch_joint" pos="0 0 0" axis="0 1 0" range="-2.58 2.58" actuatorfrcrange="-17 17" damping="0.01" frictionloss="0.01" armature="0.0042"/>
<geom type="mesh" contype="0" conaffinity="0" group="1" density="0" rgba="0.75294 0.75294 0.75294 1" mesh="rr_hip_pitch_Link"/>
<geom size="0.046 0.048" pos="0 -0.048 0" quat="0.707105 0.707108 0 0" type="cylinder" rgba="0.75294 0.75294 0.75294 1"/>
<geom size="0.0435 0.0115 0.06" pos="0 -0.1155 -0.06" type="box" rgba="0.75294 0.75294 0.75294 1"/>
<body name="rr_knee_Link" pos="-0.00075079 -0.099408 -0.25165">
<inertial pos="-0.0002 -0.0225 -0.1541" mass="0.651" fullinertia="0.0042 0.0045 0.0005 0 0 -0.0001"/>
<joint name="rr_knee_joint" pos="0 0 0" axis="0 1 0" range="-2.65 2.65" actuatorfrcrange="-17 17" damping="0.01" frictionloss="0.01" armature="0.0042"/>
<geom type="mesh" contype="0" conaffinity="0" group="1" density="0" rgba="0.75294 0.75294 0.75294 1" mesh="rr_knee_Link"/>
<geom size="0.0475 0.015" pos="0 -0.025 -0.20027" quat="0.707105 0.707108 0 0" type="cylinder" rgba="0.75294 0.75294 0.75294 1"/>
<geom size="0.015 0.0125 0.06" pos="0 -0.0125 -0.09" type="box" rgba="0.75294 0.75294 0.75294 1"/>
<body name="rr_wheel_Link" pos="0 -0.012435 -0.20027">
<inertial pos="0.0002 -0.0407 -0.0005" mass="0.53" diaginertia="0.0017 0.0032 0.0017"/>
<joint name="rr_wheel_joint" pos="0 0 0" axis="0 1 0" actuatorfrcrange="-17 17" damping="0.01" frictionloss="0.01" armature="0.0042"/>
<geom type="mesh" contype="0" conaffinity="0" group="1" density="0" rgba="0.75294 0.75294 0.75294 1" mesh="rr_wheel_Link"/>
<geom size="0.1 0.015" pos="0 -0.040737 0" quat="0.707105 0.707108 0 0" type="cylinder" rgba="0.75294 0.75294 0.75294 1"/>
</body>
</body>
</body>
</body>
<body name="imu_link" pos="0.1518 0 0.127">
<inertial pos="0 0 0" mass="0" diaginertia="0 0 0"/>
</body>
</body>
</worldbody>
<actuator>
<general name="fl_hip_abduction_joint" joint="fl_hip_abduction_joint" ctrlrange="-17 17" forcerange="-17 17" gainprm="120" biasprm="0 -8 -8"/>
<general name="fl_hip_pitch_joint" joint="fl_hip_pitch_joint" ctrlrange="-17 17" forcerange="-17 17" gainprm="120" biasprm="0 -8 -8"/>
<general name="fl_knee_joint" joint="fl_knee_joint" ctrlrange="-17 17" forcerange="-17 17" gainprm="120" biasprm="0 -8 -8"/>
<general name="fl_wheel_joint" joint="fl_wheel_joint" ctrlrange="-17 17" forcerange="-17 17" gainprm="0.5"/>
<general name="fr_hip_abduction_joint" joint="fr_hip_abduction_joint" ctrlrange="-17 17" forcerange="-17 17" gainprm="120" biasprm="0 -8 -8"/>
<general name="fr_hip_pitch_joint" joint="fr_hip_pitch_joint" ctrlrange="-17 17" forcerange="-17 17" gainprm="120" biasprm="0 -8 -8"/>
<general name="fr_knee_joint" joint="fr_knee_joint" ctrlrange="-17 17" forcerange="-17 17" gainprm="120" biasprm="0 -8 -8"/>
<general name="fr_wheel_joint" joint="fr_wheel_joint" ctrlrange="-17 17" forcerange="-17 17" gainprm="0.5"/>
<general name="rl_hip_abduction_joint" joint="rl_hip_abduction_joint" ctrlrange="-17 17" forcerange="-17 17" gainprm="120" biasprm="0 -8 -8"/>
<general name="rl_hip_pitch_joint" joint="rl_hip_pitch_joint" ctrlrange="-17 17" forcerange="-17 17" gainprm="120" biasprm="0 -8 -8"/>
<general name="rl_knee_joint" joint="rl_knee_joint" ctrlrange="-17 17" forcerange="-17 17" gainprm="120" biasprm="0 -8 -8"/>
<general name="rl_wheel_joint" joint="rl_wheel_joint" ctrlrange="-17 17" forcerange="-17 17" gainprm="0.5"/>
<general name="rr_hip_abduction_joint" joint="rr_hip_abduction_joint" ctrlrange="-17 17" forcerange="-17 17" gainprm="120" biasprm="0 -8 -8"/>
<general name="rr_hip_pitch_joint" joint="rr_hip_pitch_joint" ctrlrange="-17 17" forcerange="-17 17" gainprm="120" biasprm="0 -8 -8"/>
<general name="rr_knee_joint" joint="rr_knee_joint" ctrlrange="-17 17" forcerange="-17 17" gainprm="120" biasprm="0 -8 -8"/>
<general name="rr_wheel_joint" joint="rr_wheel_joint" ctrlrange="-17 17" forcerange="-17 17" gainprm="0.5"/>
</actuator>
</mujoco>
@@ -0,0 +1,19 @@
---
allowed-tools: Bash(git checkout --branch:*), Bash(git add:*), Bash(git status:*), Bash(git push:*), Bash(git commit:*), Bash(gh pr create:*)
description: Commit, push, and open a PR
---
## Context
- Current git status: !`git status`
- Current git diff (staged and unstaged changes): !`git diff HEAD`
- Current branch: !`git branch --show-current`
## Your task
Based on the above changes:
1. Create a new branch if on main
2. Create a single commit with an appropriate message
3. Push the branch to origin
4. Create a pull request using `gh pr create`
5. You have the capability to call multiple tools in a single response. You MUST do all of the above in a single message. Do not use any other tools or do anything else. Do not send any other text or messages besides these tool calls.
@@ -0,0 +1,18 @@
---
allowed-tools: Bash(uv lock), Bash(git checkout:*), Bash(git add:*), Bash(git status:*), Bash(git push:*), Bash(git commit:*), Bash(gh pr create:*), Edit, Read
description: Update the mujoco-warp dependency to a given commit
---
Update the mujoco-warp dependency to commit $ARGUMENTS.
Steps:
1. Read `pyproject.toml` and find the `mujoco-warp` line under `[tool.uv.sources]`.
2. Use Edit to replace the current `rev = "..."` value with `rev = "$ARGUMENTS"` on that line.
3. Run `uv lock` to regenerate the lockfile.
4. Create and switch to a new branch named `update-mjwarp/<first-8-chars-of-hash>` (e.g. `update-mjwarp/e28c6038`).
5. Stage `pyproject.toml` and `uv.lock`, then commit with message: `Update mujoco-warp to <first-8-chars-of-hash>`.
6. Push the branch and open a PR with title `Update mujoco-warp to <first-8-chars-of-hash>`.
Important:
- The commit hash is required. If `$ARGUMENTS` is empty, ask the user for a commit hash.
- Do NOT modify anything else in `pyproject.toml`.
@@ -0,0 +1,33 @@
{
"permissions": {
"allow": [
"Bash(make:*)",
"Bash(uv run:*)",
"Bash(uv lock:*)",
"Bash(uv sync:*)",
"Bash(uv add:*)",
"Bash(git:*)",
"Bash(gh:*)",
"WebSearch",
"Skill(commit-push-pr)",
"Skill(pr-review-toolkit:review-pr)"
]
},
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": "uv run ruff format"
}
]
}
]
},
"enabledPlugins": {
"code-simplifier@claude-plugins-official": true,
"pr-review-toolkit@claude-plugins-official": true
}
}
@@ -0,0 +1,34 @@
# Large runtime directories
.venv/
logs/
wandb/
artifacts/
benchmark_results/
dist/
# Build/cache
__pycache__/
*.pyc
.ruff_cache/
.pytest_cache/
.uv-cache/
*.egg-info/
# Git/CI
.git/
.github/
.gitignore
.pre-commit-config.yaml
# IDE/local
.vscode/
.claude/
notebooks/
# Docker
Dockerfile
.dockerignore
# Docs build artifacts
docs/source/_build/
docs/source/generated/
@@ -0,0 +1,95 @@
name: tests
on:
push:
branches: [main]
paths-ignore:
- '**.md'
- '**.rst'
- 'docs/**'
- 'Makefile'
- 'LICENSE'
- 'scripts/benchmarks/**'
pull_request:
branches: [main]
paths-ignore:
- '**.md'
- '**.rst'
- 'docs/**'
- 'Makefile'
- 'LICENSE'
- 'scripts/benchmarks/**'
env:
UV_FROZEN: "1"
jobs:
lint-format:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup uv
uses: astral-sh/setup-uv@v6
with:
enable-cache: true
version: "0.9.27"
- name: Run lint
run: uvx ruff@0.14.14 check --diff
- name: Run format
run: uvx ruff@0.14.14 format --diff
tests:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.10", "3.11", "3.12", "3.13"]
steps:
- uses: actions/checkout@v4
- name: Setup uv
uses: astral-sh/setup-uv@v6
with:
python-version: ${{ matrix.python-version }}
enable-cache: true
version: "0.9.27"
- name: Restore Warp kernel cache
uses: actions/cache@v4
with:
path: ~/.cache/warp
key: warp-kernels-${{ runner.os }}-${{ runner.arch }}-${{ matrix.python-version }}-${{ hashFiles('uv.lock', 'mjlab/**/*.py') }}
restore-keys: |
warp-kernels-${{ runner.os }}-${{ runner.arch }}-${{ matrix.python-version }}-
- name: Test with python ${{ matrix.python-version }}
run: uv run --extra cpu pytest
pyright:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.10", "3.11", "3.12", "3.13"]
steps:
- uses: actions/checkout@v4
- name: Setup uv
uses: astral-sh/setup-uv@v6
with:
python-version: ${{ matrix.python-version }}
enable-cache: true
version: "0.9.27"
- name: Test with python ${{ matrix.python-version }}
run: uv run --extra cpu pyright
ty-check:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.10", "3.11", "3.12", "3.13"]
steps:
- uses: actions/checkout@v4
- name: Setup uv
uses: astral-sh/setup-uv@v6
with:
python-version: ${{ matrix.python-version }}
enable-cache: true
version: "0.9.27"
- name: Type check with python ${{ matrix.python-version }}
run: uv run --extra cpu ty check
@@ -0,0 +1,91 @@
name: Docker
on:
workflow_dispatch:
push:
branches:
- "main"
pull_request:
types:
- opened
- reopened
- synchronize
- ready_for_review
concurrency:
group: docker-${{ github.ref }}
cancel-in-progress: true
defaults:
run:
shell: bash
env:
FORCE_COLOR: 1
REGISTRY: ghcr.io
IMAGE_NAME: mujocolab/mjlab
permissions:
id-token: write
packages: write
jobs:
check_paths:
runs-on: ubuntu-22.04
outputs:
build: ${{ steps.filter.outputs.any }}
steps:
- uses: actions/checkout@v6
- id: filter
uses: dorny/paths-filter@v3
with:
list-files: shell
filters: |
any:
- ".github/workflows/docker.yml"
- "Dockerfile"
build:
needs: check_paths
if: ${{ needs.check_paths.outputs.build == 'true' }}
runs-on: ubuntu-22.04
steps:
- name: Checkout repo
uses: actions/checkout@v6
- name: Setup Docker buildx
uses: docker/setup-buildx-action@v3
- name: Log into registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract Docker metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=ref,event=branch
type=raw,value=latest,enable={{is_default_branch}}
- name: Build and push Docker image
uses: docker/build-push-action@v6
with:
context: .
push: ${{ github.ref == 'refs/heads/main' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: |
type=gha
type=registry,ref=ghcr.io/mujocolab/mjlab/mjlab:buildcache
cache-to: |
type=gha,mode=max
type=registry,ref=ghcr.io/mujocolab/mjlab/mjlab:buildcache,mode=max
platforms: linux/amd64
@@ -0,0 +1,45 @@
name: docs
on:
push:
branches:
- main
tags:
- 'v*'
permissions:
contents: write
env:
UV_FROZEN: "1"
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-python@v5
with:
python-version: '3.13'
- name: Install uv
uses: astral-sh/setup-uv@v4
- name: Build Sphinx Documentation
run: uv run --group docs sphinx-multiversion docs docs/_build
- name: Add root redirect
run: echo '<meta http-equiv="refresh" content="0; url=main/index.html">' > docs/_build/index.html
- name: Remove Sphinx build artifacts
run: find docs/_build -type d -name .doctrees -exec rm -rf {} +
- name: Deploy to GitHub Pages
uses: peaceiris/actions-gh-pages@v4
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./docs/_build/
keep_files: true
@@ -0,0 +1,30 @@
name: "Publish"
on:
push:
tags:
- v*
jobs:
run:
runs-on: ubuntu-latest
environment:
name: pypi
permissions:
id-token: write
contents: read
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install uv
uses: astral-sh/setup-uv@v6
- name: Install Python 3.13
run: uv python install 3.13
- name: Build
run: uv build
- name: Smoke test (wheel)
run: uv run --isolated --no-project --with dist/*.whl tests/smoke_test.py
- name: Smoke test (source distribution)
run: uv run --isolated --no-project --with dist/*.tar.gz tests/smoke_test.py
- name: Publish
run: uv publish
@@ -0,0 +1,19 @@
wandb/
logs/
onnx/
videos/
__pycache__/
MUJOCO_LOG.TXT
debug.py
.vscode/
*.ipynb_checkpoints/
motions/
*_rerun*
artifacts/
.venv/
render_robots.py
benchmark_results/
# Documentation outputs.
**/_build/*
**/generated/*
@@ -0,0 +1,10 @@
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
# Ruff version.
rev: v0.14.14
hooks:
# Run the linter.
- id: ruff-check
args: [ --fix ]
# Run the formatter.
- id: ruff-format
@@ -0,0 +1 @@
3.13
@@ -0,0 +1 @@
CLAUDE.md
@@ -0,0 +1,60 @@
# This CITATION.cff file was generated with cffinit.
# Visit https://bit.ly/cffinit to generate yours today!
cff-version: 1.2.0
title: >-
mjlab: A Lightweight Framework for GPU-Accelerated Robot Learning
message: >-
If you use this software, please cite it using the
metadata from this file.
type: software
authors:
- given-names: Kevin
family-names: Zakka
email: zakka@berkeley.edu
- given-names: Brent
family-names: Yi
email: brentyi@berkeley.edu
- given-names: Qiayuan
family-names: Liao
email: qiayuanl@berkeley.edu
- given-names: Louis
family-names: Le Lay
email: le.lay.louis@gmail.com
- given-names: Koushil
family-names: Sreenath
- given-names: Pieter
family-names: Abbeel
repository-code: 'https://github.com/mujocolab/mjlab'
keywords:
- mujoco
- mujoco-warp
- simulation
- reinforcement-learning
- robotics
license: Apache-2.0
commit: e2f33c6fb49caa26ec11f7b2de3c0c9aba71e9fd
version: 1.3.0
date-released: '2026-04-14'
preferred-citation:
type: article
title: >-
mjlab: A Lightweight Framework for GPU-Accelerated Robot Learning
authors:
- given-names: Kevin
family-names: Zakka
- given-names: Qiayuan
family-names: Liao
- given-names: Brent
family-names: Yi
- given-names: Louis
family-names: Le Lay
- given-names: Koushil
family-names: Sreenath
- given-names: Pieter
family-names: Abbeel
year: 2026
url: https://arxiv.org/abs/2601.22074
identifiers:
- type: arxiv
value: 2601.22074
@@ -0,0 +1,60 @@
# Development Workflow
**Always use `uv run`, not python**.
```sh
# 1. Make changes.
# 2. Type check.
uv run ty check # Fast
uv run pyright # More thorough, but slower
# 3. Run tests.
uv run pytest tests/ # Single suite
uv run pytest tests/<test_file>.py # Specific file
# 4. Format and lint before committing.
uv run ruff format
uv run ruff check --fix
```
We've bundled common commands into a Makefile for convenience.
```sh
make format # Format and lint
make type # Type-check
make check # make format && make type
make test-fast # Run tests excluding slow ones
make test # Run the full test suite
make docs # Build documentation
```
Always run `make check` before committing. This runs formatting, linting,
and type checking. Do not commit code that fails type checking.
Before creating a PR, ensure all checks pass with `make test`.
When making user-facing changes, add an entry to `docs/source/changelog.rst`
under the "Upcoming version (not yet released)" section using
Added/Changed/Fixed categories. Reference issues with `:issue:\`123\``
(renders as a link to the GitHub issue).
# Commits and PRs
- Put `Fixes #<number>` at the end of the commit message body, not in
the title.
- PR body should be plain, concise prose. No section headers, checklists,
or structured templates. Describe the problem, what the change does, and
any non-obvious tradeoffs. A good PR description reads like a short
paragraph to a colleague, not a form.
- PR and commit messages are rendered on GitHub, so don't hard-wrap them
at 88 columns. Let each sentence flow on one line.
Some style guidelines to follow:
- Line length limit is 88 columns. This applies to code, comments, and docstrings.
- Avoid local imports unless they are strictly necessary (e.g. circular imports).
- Tests should follow these principles:
- Use functions and fixtures; do not use test classes.
- Favor targeted, efficient tests over exhaustive edge-case coverage.
- Prefer running individual tests rather than the full test suite to improve iteration speed.
@@ -0,0 +1,25 @@
# Contributing
Bug fixes and documentation improvements are always welcome. For new features, please open an issue first so we can discuss whether it fits and work out the design, as we're intentional about keeping the scope focused.
## Workflow
1. Fork the repository and create a feature branch.
2. Make your changes.
3. Ensure formatting, type checking, and tests pass: `make test-all`.
4. Submit a pull request.
Type checking (`make type`) is required, PRs that don't pass will be blocked. You can optionally install pre-commit hooks (`pre-commit install`) to catch issues early.
## Changelog
Add entries to the "Upcoming version" section in `docs/source/changelog.rst` under the appropriate category (Added / Changed / Fixed), following [Keep a Changelog](https://keepachangelog.com/) conventions.
## Getting Help
- **Issues**: https://github.com/mujocolab/mjlab/issues
- **Discussions**: https://github.com/mujocolab/mjlab/discussions
## License
By contributing, you agree your contributions will be licensed under Apache 2.0.
@@ -0,0 +1,36 @@
# Refer to uv-docker-example:
# https://github.com/astral-sh/uv-docker-example/blob/main/standalone.Dockerfile
# Note that we use uv to launch, so we omit the second half of the example (non-UV final image)
FROM nvidia/cuda:12.8.0-runtime-ubuntu24.04
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y \
git \
curl \
libegl-dev \
&& rm -rf /var/lib/apt/lists/*
ENV UV_COMPILE_BYTECODE=1
ENV UV_LINK_MODE=copy
ENV UV_PYTHON_PREFERENCE=only-managed
RUN uv python install 3.13
WORKDIR /app
RUN --mount=type=cache,target=/root/.cache/uv \
--mount=type=bind,source=uv.lock,target=uv.lock \
--mount=type=bind,source=pyproject.toml,target=pyproject.toml \
uv sync --locked --no-install-project --no-editable --no-dev
ADD . /app
RUN --mount=type=cache,target=/root/.cache/uv \
uv sync --locked --no-editable --no-dev
ENV MUJOCO_GL=egl
EXPOSE 8080
CMD ["uv", "run", "python", "tests/smoke_test.py"]
+202
View File
@@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2025, The mjlab Developers
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
+66
View File
@@ -0,0 +1,66 @@
.PHONY: sync
sync:
uv sync --all-extras --all-packages --group dev
.PHONY: format
format:
uv run ruff format
uv run ruff check --fix
.PHONY: type
type:
uv run ty check
uv run pyright
.PHONY: check
check: format type
.PHONY: test
test:
uv run pytest
.PHONY: test-fast
test-fast:
uv run pytest -m "not slow"
.PHONY: test-cpu
test-cpu:
FORCE_CPU=1 uv run pytest
.PHONY: test-cpu-fast
test-cpu-fast:
FORCE_CPU=1 uv run pytest -m "not slow"
.PHONY: test-all
test-all: check test
.PHONY: build
build:
uv build
uv run --isolated --no-project --with dist/*.whl tests/smoke_test.py
uv run --isolated --no-project --with dist/*.tar.gz tests/smoke_test.py
@echo "Build and import test successful"
.PHONY: docs
docs:
uv run --group docs sphinx-build -j auto docs docs/_build
.PHONY: docs-multiversion
docs-multiversion:
uv run --group docs sphinx-multiversion docs docs/_build
.PHONY: docs-watch
docs-watch:
uv run --group docs sphinx-autobuild -j auto docs docs/_build
.PHONY: publish-test
publish-test: build
uv publish --publish-url https://test.pypi.org/legacy/
.PHONY: publish
publish: build
uv publish
.PHONY: docker-build
docker-build:
docker build -t mjlab:latest .
+140
View File
@@ -0,0 +1,140 @@
![Project banner](https://raw.githubusercontent.com/mujocolab/mjlab/main/docs/source/_static/mjlab-banner.jpg)
# mjlab
[![GitHub Actions](https://img.shields.io/github/actions/workflow/status/mujocolab/mjlab/ci.yml?branch=main)](https://github.com/mujocolab/mjlab/actions/workflows/ci.yml?query=branch%3Amain)
[![Documentation](https://github.com/mujocolab/mjlab/actions/workflows/docs.yml/badge.svg)](https://mujocolab.github.io/mjlab/)
[![License](https://img.shields.io/github/license/mujocolab/mjlab)](https://github.com/mujocolab/mjlab/blob/main/LICENSE)
[![Nightly Benchmarks](https://img.shields.io/badge/Nightly-Benchmarks-blue)](https://mujocolab.github.io/mjlab/nightly/)
[![PyPI](https://img.shields.io/pypi/v/mjlab)](https://pypi.org/project/mjlab/)
[![PyPI downloads](https://img.shields.io/pypi/dm/mjlab?color=blue)](https://pypistats.org/packages/mjlab)
mjlab combines [Isaac Lab](https://github.com/isaac-sim/IsaacLab)'s manager-based API with [MuJoCo Warp](https://github.com/google-deepmind/mujoco_warp), a GPU-accelerated version of [MuJoCo](https://github.com/google-deepmind/mujoco).
The framework provides composable building blocks for environment design,
with minimal dependencies and direct access to native MuJoCo data structures.
## Getting Started
mjlab requires an NVIDIA GPU for training. macOS is supported for evaluation only.
**Try it now:**
Run the demo (no installation needed):
```bash
uvx --from mjlab --refresh demo
```
Or try in [Google Colab](https://colab.research.google.com/github/mujocolab/mjlab/blob/main/notebooks/demo.ipynb) (no local setup required).
**Install from source:**
```bash
git clone https://github.com/mujocolab/mjlab.git && cd mjlab
uv run demo
```
For alternative installation methods (PyPI, Docker), see the [Installation Guide](https://mujocolab.github.io/mjlab/main/source/installation.html).
## Training Examples
### 1. Velocity Tracking
Train a Unitree G1 humanoid to follow velocity commands on flat terrain:
```bash
uv run train Mjlab-Velocity-Flat-Unitree-G1 --env.scene.num-envs 4096
```
**Multi-GPU Training:** Scale to multiple GPUs using `--gpu-ids`:
```bash
uv run train Mjlab-Velocity-Flat-Unitree-G1 \
--gpu-ids "[0, 1]" \
--env.scene.num-envs 4096
```
See the [Distributed Training guide](https://mujocolab.github.io/mjlab/main/source/training/distributed_training.html) for details.
Evaluate a policy while training (fetches latest checkpoint from Weights & Biases):
```bash
uv run play Mjlab-Velocity-Flat-Unitree-G1 --wandb-run-path your-org/mjlab/run-id
```
### 2. Motion Imitation
Train a humanoid to mimic reference motions. See the [motion imitation guide](https://mujocolab.github.io/mjlab/main/source/training/motion_imitation.html) for preprocessing setup.
```bash
uv run train Mjlab-Tracking-Flat-Unitree-G1 --registry-name your-org/motions/motion-name --env.scene.num-envs 4096
uv run play Mjlab-Tracking-Flat-Unitree-G1 --wandb-run-path your-org/mjlab/run-id
```
### 3. Sanity-check with Dummy Agents
Use built-in agents to sanity check your MDP before training:
```bash
uv run play Mjlab-Your-Task-Id --agent zero # Sends zero actions
uv run play Mjlab-Your-Task-Id --agent random # Sends uniform random actions
```
When running motion-tracking tasks, add `--registry-name your-org/motions/motion-name` to the command.
## Documentation
Full documentation is available at **[mujocolab.github.io/mjlab](https://mujocolab.github.io/mjlab/)**.
## Development
```bash
make test # Run all tests
make test-fast # Skip slow tests
make format # Format and lint
make docs # Build docs locally
```
For development setup: `uvx pre-commit install`
## Citation
mjlab is used in published research and open-source robotics projects. See the [Research](https://mujocolab.github.io/mjlab/main/source/research.html) page for publications and projects, or share your own in [Show and Tell](https://github.com/mujocolab/mjlab/discussions/categories/show-and-tell).
If you use mjlab in your research, please consider citing:
```bibtex
@misc{zakka2026mjlablightweightframeworkgpuaccelerated,
title={mjlab: A Lightweight Framework for GPU-Accelerated Robot Learning},
author={Kevin Zakka and Qiayuan Liao and Brent Yi and Louis Le Lay and Koushil Sreenath and Pieter Abbeel},
year={2026},
eprint={2601.22074},
archivePrefix={arXiv},
primaryClass={cs.RO},
url={https://arxiv.org/abs/2601.22074},
}
```
## License
mjlab is licensed under the [Apache License, Version 2.0](LICENSE).
### Third-Party Code
Some portions of mjlab are forked from external projects:
- **`src/mjlab/utils/lab_api/`** — Utilities forked from [NVIDIA Isaac
Lab](https://github.com/isaac-sim/IsaacLab) (BSD-3-Clause license, see file
headers)
Forked components retain their original licenses. See file headers for details.
## Acknowledgments
mjlab wouldn't exist without the excellent work of the Isaac Lab team, whose API
design and abstractions mjlab builds upon.
Thanks to the MuJoCo Warp team — especially Erik Frey and Taylor Howell — for
answering our questions, giving helpful feedback, and implementing features
based on our requests countless times.
@@ -0,0 +1,76 @@
# Releasing
## Pre-release checklist
1. Bump `version` in `pyproject.toml`.
2. Update `version` and `date-released` in `CITATION.cff`.
3. Update the "Upcoming version (not yet released)" heading in `docs/source/changelog.rst` to the new version number and date.
4. Commit the version bump, then create an annotated tag:
```sh
git tag -a vX.Y.Z -m "Release vX.Y.Z"
git push origin vX.Y.Z
```
## Build and verify
Clean previous build artifacts, then build:
```sh
rm -rf dist/
make build
```
This runs `uv build` to produce a wheel and sdist in `dist/`, then smoke-tests
both artifacts in isolated environments.
## Test on TestPyPI (optional but recommended)
Upload to TestPyPI first to catch packaging issues before the real release:
```sh
UV_PUBLISH_TOKEN=<your-testpypi-token> make publish-test
```
Then verify the upload works end-to-end. Use `--index-strategy unsafe-best-match`
because TestPyPI won't have all dependencies and uv needs to fall back to real
PyPI for them:
```sh
uvx --extra-index-url https://test.pypi.org/simple/ \
--index-strategy unsafe-best-match \
--from mjlab \
demo
```
Note: TestPyPI requires a separate account and token from real PyPI.
Generate one at https://test.pypi.org/manage/account/token/.
## Publish to PyPI
```sh
UV_PUBLISH_TOKEN=<your-pypi-token> make publish
```
Generate a token at https://pypi.org/manage/account/token/.
## Post-release
Verify the release installs and runs correctly. Use `--refresh` to bypass
the `uvx` cache (which may still hold the TestPyPI version):
```sh
uvx --refresh --from mjlab demo
```
## Releasing from a past tag
If the tag has already been created and HEAD has moved ahead, check out the
tag before building:
```sh
git checkout vX.Y.Z
make build
make publish
git checkout main
```
@@ -0,0 +1,13 @@
{% if versions %}
<div class="sidebar-version-switcher">
<label class="sidebar-version-label" for="version-select">Version</label>
<select id="version-select" class="sidebar-version-select" onchange="location = this.value;">
{%- for item in versions.branches %}
<option value="{{ item.url }}" {% if item == current_version %}selected{% endif %}>{{ item.name }}</option>
{%- endfor %}
{%- for item in versions.tags|reverse %}
<option value="{{ item.url }}" {% if item == current_version %}selected{% endif %}>{{ item.name }}</option>
{%- endfor %}
</select>
</div>
{% endif %}
@@ -0,0 +1,200 @@
import os
import sys
import sphinx_book_theme
sys.path.insert(0, os.path.abspath("../src"))
sys.path.insert(0, os.path.abspath("../src/mjlab"))
project = "mjlab"
copyright = "2025, The mjlab Developers"
author = "The mjlab Developers"
extensions = [
"sphinx.ext.autodoc",
"sphinx.ext.autosummary",
"autodocsumm",
"myst_parser",
"sphinx.ext.napoleon",
"sphinxemoji.sphinxemoji",
"sphinx.ext.intersphinx",
"sphinx.ext.mathjax",
"sphinx.ext.todo",
"sphinx.ext.viewcode",
"sphinxcontrib.bibtex",
"sphinxcontrib.icon",
"sphinx_copybutton",
"sphinx_design",
"sphinx_tabs.tabs",
"sphinx_multiversion",
"sphinx.ext.extlinks",
]
extlinks = {
"issue": (
"https://github.com/mujocolab/mjlab/issues/%s",
"#%s",
),
}
mathjax3_config = {
"tex": {
"inlineMath": [["\\(", "\\)"]],
"displayMath": [["\\[", "\\]"]],
},
}
panels_add_bootstrap_css = False
panels_add_fontawesome_css = True
source_suffix = {
".rst": "restructuredtext",
".md": "markdown",
}
nitpick_ignore = [
("py:obj", "slice(None)"),
]
nitpick_ignore_regex = [
(r"py:.*", r"pxr.*"),
(r"py:.*", r"trimesh.*"),
]
# emoji style
sphinxemoji_style = "twemoji"
autodoc_typehints = "signature"
autoclass_content = "class"
autodoc_class_signature = "separated"
autodoc_member_order = "bysource"
autodoc_inherit_docstrings = True
bibtex_bibfiles = ["source/_static/refs.bib"]
autosummary_generate = True
autosummary_generate_overwrite = False
autodoc_default_options = {
"member-order": "bysource",
}
intersphinx_mapping = {
"python": ("https://docs.python.org/3", None),
}
exclude_patterns = [
"_build",
"_redirect",
"_templates",
"Thumbs.db",
".DS_Store",
"README.md",
"licenses/*",
]
autodoc_mock_imports = [
"matplotlib",
"scipy",
"carb",
"warp",
"pxr",
"h5py",
"hid",
"prettytable",
"tqdm",
"tensordict",
"trimesh",
"toml",
"mjviser",
"mujoco_warp",
"gymnasium",
"rsl_rl",
"viser",
"wandb",
"torchvision",
]
suppress_warnings = [
"ref.python",
"docutils",
]
language = "en"
html_title = "mjlab Documentation"
html_theme_path = [sphinx_book_theme.get_html_theme_path()]
html_theme = "sphinx_book_theme"
html_favicon = "source/_static/favicon.ico"
html_show_copyright = True
html_show_sphinx = False
html_last_updated_fmt = ""
html_static_path = ["source/_static"]
html_css_files = ["css/custom.css"]
html_theme_options = {
"path_to_docs": "docs/",
"collapse_navigation": True,
"repository_url": "https://github.com/mujocolab/mjlab",
"use_repository_button": True,
"use_issues_button": True,
"use_edit_page_button": True,
"show_toc_level": 2,
"use_sidenotes": True,
"logo": {
"text": "mjlab Documentation",
},
"icon_links": [
{
"name": "Benchmarks",
"url": "https://mujocolab.github.io/mjlab/nightly/",
"icon": "fa-solid fa-chart-line",
"type": "fontawesome",
},
],
"icon_links_label": "Quick Links",
}
templates_path = [
"_templates",
]
smv_remote_whitelist = r"^.*$"
smv_branch_whitelist = os.getenv("SMV_BRANCH_WHITELIST", r"^(main|devel)$")
smv_tag_whitelist = os.getenv("SMV_TAG_WHITELIST", r"^v[1-9]\d*\.\d+\.\d+$")
html_sidebars = {
"**": [
"navbar-logo.html",
"search-field.html",
"versioning.html",
"sbt-sidebar-nav.html",
]
}
def skip_member(app, what, name, obj, skip, options):
exclusions = ["from_dict", "to_dict", "replace", "copy", "validate", "__post_init__"]
if name in exclusions:
return True
return None
def process_signature(app, what, name, obj, options, signature, return_annotation):
"""Suppress the ugly __init__ signature for dataclass Cfg classes."""
if what == "class" and "exclude-members" in options:
if "__init__" in options["exclude-members"]:
return ("", None)
return None
def process_docstring(app, what, name, obj, options, lines):
"""Strip auto-generated dataclass docstrings (e.g. 'ClassName(*, ...)')."""
import dataclasses
if what == "class" and dataclasses.is_dataclass(obj):
if lines and lines[0].startswith(f"{obj.__name__}("):
lines.clear()
def setup(app):
app.connect("autodoc-skip-member", skip_member)
app.connect("autodoc-process-signature", process_signature)
app.connect("autodoc-process-docstring", process_docstring)
@@ -0,0 +1,128 @@
Welcome to mjlab!
=================
.. figure:: source/_static/mjlab-banner.jpg
:width: 100%
:alt: mjlab
mjlab is a lightweight, open-source framework for robot learning that
combines GPU-accelerated simulation with composable environments and minimal
setup friction. It adopts the manager-based API introduced by
`Isaac Lab <https://github.com/isaac-sim/IsaacLab>`_, where users compose
modular building blocks for observations, rewards, and events, and pairs it
with `MuJoCo Warp <https://github.com/google-deepmind/mujoco_warp>`_ for
GPU-accelerated physics. The result is a framework installable with a single
command, requiring minimal dependencies, and providing direct access to
native `MuJoCo <https://github.com/google-deepmind/mujoco>`_ data
structures.
**Key features:**
- **Composable environments:** users define observations, rewards,
terminations, and other MDP terms as modular building blocks
- **Minimal dependencies:** single-command install via ``uv``, low startup
latency
- **Direct MuJoCo data structures:** native ``MjModel``/``MjData`` access
with no translation layers
- **PyTorch-native:** observations, rewards, and actions are PyTorch
tensors backed by zero-copy GPU memory sharing
For more on the design decisions behind mjlab, see :doc:`source/motivation`.
**Try it now** (no installation needed):
.. code-block:: bash
uvx --from mjlab --refresh demo
Table of Contents
-----------------
.. toctree::
:maxdepth: 1
:caption: User Guide
source/installation
source/tutorials
source/contributing
.. toctree::
:maxdepth: 1
:caption: Concepts
source/architecture_overview
source/entity/index
source/actuators
source/sensors/index
source/scene
source/terrain
.. toctree::
:maxdepth: 1
:caption: The Manager Layer
source/environment_config
source/observations
source/actions
source/rewards
source/terminations
source/commands
source/events
source/randomization
source/curriculum
source/metrics
source/recorders
.. toctree::
:maxdepth: 1
:caption: Training & Debugging
source/training/rsl_rl
source/viewers
source/training/distributed_training
source/training/cloud
source/debugging/nan_guard
source/debugging/export_scene
.. toctree::
:maxdepth: 2
:caption: API Reference
source/api/index
.. toctree::
:maxdepth: 1
:caption: Further Reading
source/motivation
source/migration_isaac_lab
source/faq
source/research
source/changelog
License & citation
------------------
mjlab is licensed under the Apache License, Version 2.0.
Please refer to the `LICENSE file <https://github.com/mujocolab/mjlab/blob/main/LICENSE/>`_ for details.
If you use mjlab in your research, we would appreciate a citation:
.. code-block:: bibtex
@article{Zakka_mjlab_A_Lightweight_2026,
author = {Zakka, Kevin and Liao, Qiayuan and Yi, Brent and Le Lay, Louis and Sreenath, Koushil and Abbeel, Pieter},
title = {{mjlab: A Lightweight Framework for GPU-Accelerated Robot Learning}},
url = {https://arxiv.org/abs/2601.22074},
year = {2026}
}
Acknowledgments
---------------
mjlab would not exist without the excellent work of the Isaac Lab team, whose API design
and abstractions mjlab builds upon.
Thanks also to the MuJoCo Warp team — especially Erik Frey and Taylor Howell — for
answering our questions, giving helpful feedback, and implementing features based
on our requests countless times.
Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 253 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 285 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 751 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

@@ -0,0 +1,172 @@
/*
* PyData Sphinx Theme Option A (Indigo/Teal)
* Aesthetic: modern lab indigo primary, teal accent, neutral grays
*/
/* LIGHT THEME */
html[data-theme="light"] {
/* Brand */
--pst-color-primary: #4F46E5;
/* Indigo-600 */
--pst-color-secondary: #14B8A6;
/* Teal-500 */
--pst-color-secondary-highlight: #2DD4BF;
/* Teal-400 */
/* Links / code links */
--pst-color-inline-code-links: #0D9488;
/* Teal-600 */
--pst-color-link: var(--pst-color-primary);
--pst-color-link-hover: #4338CA;
/* Indigo-700 */
/* Semantic */
--pst-color-info: var(--pst-color-secondary);
--pst-color-info-highlight: var(--pst-color-secondary);
--pst-color-info-bg: #D1FAE5;
/* Teal-50 */
--pst-color-attention: #F59E0B;
/* Amber-500 */
--pst-color-target: #EEF2FF;
/* Indigo-50 */
/* Text */
--pst-color-text-base: #1F2937;
/* Slate-800 */
--pst-color-text-muted: #6B7280;
/* Slate-500 */
/* Surfaces */
--pst-color-background: #FFFFFF;
--pst-color-on-background: #FFFFFF;
--pst-color-surface: #F3F4F6;
/* Gray-100 */
--pst-color-on-surface: #E5E7EB;
/* Gray-200 */
--pst-color-shadow: #D1D5DB;
--pst-color-border: #E5E7EB;
/* Inline code */
--pst-color-inline-code: #0D9488;
/* Teal-600 */
/* Tables / hovers */
--pst-color-table-row-hover-bg: #EEF2FF;
/* Indigo-50 */
/* Accent (sparingly) */
--pst-color-accent: #10B981;
/* Emerald-500 */
}
/* DARK THEME */
html[data-theme="dark"] {
/* Brand */
--pst-color-primary: #A5B4FC;
/* Indigo-300/200 mix for readability */
--pst-color-secondary: #5EEAD4;
/* Teal-300 */
--pst-color-secondary-highlight: #2DD4BF;
/* Links / code links */
--pst-color-inline-code-links: #93C5FD;
/* Indigo-300 */
--pst-color-link: var(--pst-color-primary);
--pst-color-link-hover: #818CF8;
/* Indigo-400 */
/* Semantic */
--pst-color-info: var(--pst-color-secondary);
--pst-color-info-highlight: var(--pst-color-secondary);
--pst-color-info-bg: #042F2E;
/* Deep teal */
--pst-color-attention: #F59E0B;
--pst-color-target: #1B1C2A;
/* Indigo-tinted surface */
/* Text */
--pst-color-text-base: #E5E7EB;
/* Gray-200 */
--pst-color-text-muted: #9CA3AF;
/* Gray-400 */
/* Surfaces */
--pst-color-background: #0B0C10;
/* Deep graphite */
--pst-color-on-background: #12131A;
--pst-color-surface: #111827;
/* Slate-900 */
--pst-color-on-surface: #1F2937;
/* Slate-800 */
--pst-color-shadow: #0F172A;
--pst-color-border: #2A2D3A;
/* Inline code */
--pst-color-inline-code: #5EEAD4;
/* Teal-300 */
/* Tables / hovers */
--pst-color-table-row-hover-bg: #1B1C2A;
/* Accent */
--pst-color-accent: #34D399;
/* Emerald-400 */
}
/* General tweaks */
a {
text-decoration: none !important;
}
.bd-header-announcement a,
.bd-header-version-warning a {
color: #5EEAD4;
}
.form-control {
border-radius: 0 !important;
border: none !important;
outline: none !important;
}
.navbar-brand,
.navbar-icon-links {
padding-top: 0rem !important;
padding-bottom: 0rem !important;
}
/* Version switcher */
.sidebar-version-switcher {
display: flex;
align-items: center;
gap: 0.5rem;
padding: 0.4rem 1rem;
margin-bottom: 0.5rem;
}
.sidebar-version-label {
font-size: 0.8rem;
font-weight: 600;
color: var(--pst-color-text-muted);
white-space: nowrap;
}
.sidebar-version-select {
flex: 1;
font-size: 0.8rem;
padding: 0.25rem 0.5rem;
border: 1px solid var(--pst-color-border);
border-radius: 4px;
background: var(--pst-color-background);
color: var(--pst-color-text-base);
cursor: pointer;
}
.sidebar-version-select:hover {
border-color: var(--pst-color-primary);
}
/* Sidebar section spacing */
.bd-sidebar .navbar-icon-links {
padding: 0 1rem 0.25rem !important;
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 442 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 838 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 751 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 335 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 93 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 150 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 109 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 125 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 923 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 178 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 707 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 338 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 733 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 936 KiB

@@ -0,0 +1,173 @@
.. _actions:
Actions
=======
Actions define how the policy controls the simulation. The action
manager receives the policy's output tensor each step, splits it across
registered action terms, and routes each slice to the appropriate
entity's actuators. Each term maps a contiguous segment of the policy
output to a control mode (position, velocity, effort) on a set of
joints, tendons, or sites.
.. code-block:: python
from mjlab.envs.mdp.actions import JointPositionActionCfg
actions = {
"joint_pos": JointPositionActionCfg(
entity_name="robot",
actuator_names=(".*",), # regex matching actuator names
scale=0.5,
use_default_offset=True, # action 0 = default pose
),
}
Common parameters
-----------------
All action types share a base set of parameters inherited from
``BaseActionCfg``.
``entity_name`` identifies the scene entity to control. ``actuator_names``
is a tuple of regex patterns matched against actuator (or tendon/site)
names to select the controlled targets.
``scale`` multiplies the raw policy output before any offset is applied.
It accepts a scalar or a dict mapping actuator name patterns to
per-target values. This keeps policy outputs in a normalized range while
mapping to physically meaningful units. ``offset`` is added after
scaling; joint action types also provide ``use_default_offset``, which
automatically loads the entity's default joint positions or velocities
as the offset so that a raw output of zero produces the default pose.
``clip`` optionally clamps the processed action (after scale and offset)
before it reaches the actuator. It accepts a dict mapping actuator name
patterns to ``(min, max)`` tuples, resolved the same way as ``scale``
and ``offset``.
.. code-block:: python
JointPositionActionCfg(
entity_name="robot",
actuator_names=(".*",),
scale=0.5,
clip={".*_hip_.*": (-1.0, 1.0), ".*_knee_.*": (-0.5, 2.0)},
)
Actions are written to actuator targets on every decimation substep
(physics step), not just once per policy step. This is in contrast to
observation delay, which operates in units of policy steps.
Action types
------------
.. list-table::
:header-rows: 1
:widths: 28 72
* - Type
- Description
* - ``JointPositionAction``
- Sets joint position targets. With ``use_default_offset=True``
(the default), a policy output of zero commands the default pose.
Encoder bias from ``dr.encoder_bias`` is subtracted automatically
so that randomized offsets propagate correctly to the control
command.
* - ``RelativeJointPositionAction``
- Sets joint position targets relative to the current joint positions.
The target is ``current_pos + action * scale``, so a policy output of
zero holds the robot in place regardless of its current configuration.
* - ``JointVelocityAction``
- Sets joint velocity targets. ``use_default_offset=True`` uses the
default joint velocities (typically zero).
* - ``JointEffortAction``
- Sets joint effort (torque) targets directly. No default offset.
* - ``TendonLengthAction``
- Sets tendon length targets. Targets are resolved by matching
``actuator_names`` against tendon names.
* - ``TendonVelocityAction``
- Sets tendon velocity targets.
* - ``TendonEffortAction``
- Sets tendon effort targets.
* - ``SiteEffortAction``
- Applies forces and torques at named sites. Useful for
quadrotors and drones where thrust is applied at rotor sites
rather than through joint actuators.
Task-space actions
------------------
``DifferentialIKAction`` converts Cartesian position and orientation
commands into joint-space position targets via damped least-squares
inverse kinematics. One IK step is executed per decimation substep, so
the end-effector tracks the target continuously across substeps rather
than only at policy frequency.
The action dimension is selected automatically based on configuration:
- ``orientation_weight == 0``: **3D** (position only)
- ``orientation_weight > 0, use_relative_mode=True``: **6D** (delta
position + delta axis-angle)
- ``orientation_weight > 0, use_relative_mode=False``: **7D** (absolute
position + quaternion)
All objectives (position, orientation, joint limits, posture) are
stacked into a single DLS system. Setting a weight to zero disables
that objective with no overhead in the solve.
The ``compute_dq()`` method returns joint displacements without writing
to actuator targets, enabling multi-iteration IK in standalone scripts
outside of RL training.
Action dimensions and history
------------------------------
The total action dimension presented to the policy is the sum of each
registered term's ``action_dim``. For joint, tendon, and site actions
this equals the number of matched targets. For ``DifferentialIKAction``
it is 3, 6, or 7 depending on the active objectives.
The action manager tracks the three most recent action vectors:
``action``, ``prev_action``, and ``prev_prev_action``. Observation terms
such as ``last_action`` and reward terms such as ``action_rate_l2`` and
``action_acc_l2`` read from these buffers. Action history is zeroed on
environment reset so that episode boundaries do not leak information.
Multiple action terms
---------------------
An environment can register any number of terms. The action manager
concatenates their dimensions in registration order, splits the
policy's output tensor at the corresponding boundaries, and routes
each slice independently.
.. code-block:: python
from mjlab.envs.mdp.actions import (
JointPositionActionCfg,
JointVelocityActionCfg,
)
actions = {
"arm_joints": JointPositionActionCfg(
entity_name="robot",
actuator_names=(".*_arm_.*",),
scale=0.5,
),
"wheel_joints": JointVelocityActionCfg(
entity_name="robot",
actuator_names=(".*_wheel_.*",),
scale=10.0,
),
}
The policy outputs a tensor whose width equals the total number of
matched targets across all terms. Terms can also target different
entities, for example one term for a robot and another for an object
being manipulated.
@@ -0,0 +1,450 @@
.. _actuators:
Actuators
=========
Actuators convert high-level commands (position, velocity, effort) into
low-level efforts that drive joints. They are configured through the
``articulation`` field of :ref:`EntityCfg <entity>`. mjlab provides
**built-in** actuators that leverage the physics engine's implicit
integration for best stability, and **explicit** actuators for custom
control laws and actuator dynamics.
Quick start
-----------
Basic PD control with ``BuiltinPositionActuator``, the most common
starting point.
.. code-block:: python
from mjlab.actuator import BuiltinPositionActuatorCfg
from mjlab.entity import EntityCfg, EntityArticulationInfoCfg
robot_cfg = EntityCfg(
spec_fn=lambda: load_robot_spec(),
articulation=EntityArticulationInfoCfg(
actuators=(
BuiltinPositionActuatorCfg(
target_names_expr=(".*_hip_.*", ".*_knee_.*"),
stiffness=80.0,
damping=10.0,
effort_limit=100.0,
),
),
),
)
Add delay fields directly on any actuator config to model communication
latency.
.. code-block:: python
from mjlab.actuator import BuiltinPositionActuatorCfg
BuiltinPositionActuatorCfg(
target_names_expr=(".*",),
stiffness=80.0,
damping=10.0,
delay_min_lag=2, # Minimum 2 physics steps
delay_max_lag=5, # Maximum 5 physics steps
)
Built-in vs explicit actuators
------------------------------
The key design decision when configuring actuators is whether to use
**built-in** or **explicit** types. The difference comes down to how
MuJoCo's integrator handles velocity-dependent forces.
**Built-in actuators** (``BuiltinPositionActuator``,
``BuiltinVelocityActuator``, ``BuiltinMotorActuator``,
``BuiltinMuscleActuator``) create native MuJoCo actuator elements in the
MjSpec. The physics engine computes the control law and integrates
velocity-dependent damping forces implicitly. This provides the best
numerical stability, particularly with high gains or large timesteps.
**Explicit actuators** (``IdealPdActuator``, ``DcMotorActuator``,
``LearnedMlpActuator``) compute torques in user code and forward them
through a ``<motor>`` actuator acting as a passthrough. Because the
integrator cannot account for the velocity derivatives of these
externally computed forces, they are less numerically robust than built-in
types. Use explicit actuators when you need custom control laws or actuator
dynamics that cannot be expressed with built-in types (e.g.,
velocity-dependent torque limits, learned actuator networks).
The two approaches match closely in the linear, unconstrained regime at
small timesteps. At larger timesteps or higher gains, built-in actuators
are more forgiving.
**Integrator choice.** mjlab places damping inside the actuator rather than
in joints. The ``euler`` integrator treats joint damping implicitly but
actuator damping explicitly, limiting stability. The ``implicitfast``
integrator treats all known velocity-dependent forces implicitly, handling
both proportional and damping terms of the actuator without additional cost.
.. note::
mjlab defaults to ``implicitfast``, as it is MuJoCo's recommended
integrator and provides superior stability for actuator-side damping.
Actuator types
--------------
All actuator configs share a few common fields inherited from
``ActuatorCfg``:
- ``target_names_expr``: Tuple of regex patterns matched against joint
names (or tendon/site names when using a different
``transmission_type``).
- ``armature``: Reflected rotor inertia added to the target joint.
- ``frictionloss``: Static friction (stiction) modeled as a constraint
on the target joint. See MuJoCo's
`frictionloss <https://mujoco.readthedocs.io/en/stable/XMLreference.html#body-joint-frictionloss>`_.
Built-in actuators
^^^^^^^^^^^^^^^^^^
Built-in actuators use MuJoCo's native actuator types via the MjSpec API.
**BuiltinPositionActuator**: Creates ``<position>`` actuators for PD
control.
**BuiltinVelocityActuator**: Creates ``<velocity>`` actuators for velocity
control.
**BuiltinMotorActuator**: Creates ``<motor>`` actuators for direct torque
control.
**BuiltinMuscleActuator**: Creates ``<muscle>`` actuators for
biologically-inspired muscle dynamics with force-length-velocity
characteristics.
.. code-block:: python
from mjlab.actuator import BuiltinPositionActuatorCfg, BuiltinVelocityActuatorCfg
# Mobile manipulator: PD for arm joints, velocity control for wheels.
actuators = (
BuiltinPositionActuatorCfg(
target_names_expr=(".*_shoulder_.*", ".*_elbow_.*", ".*_wrist_.*"),
stiffness=100.0,
damping=10.0,
effort_limit=150.0,
),
BuiltinVelocityActuatorCfg(
target_names_expr=(".*_wheel_.*",),
damping=20.0,
effort_limit=50.0,
),
)
Explicit actuators
^^^^^^^^^^^^^^^^^^
Explicit actuators compute efforts and forward them to an underlying
``<motor>`` actuator acting as a passthrough. See
`Built-in vs explicit actuators`_ above for stability implications.
**IdealPdActuator**: Implements an ideal PD controller. Computes torques
as ``tau = Kp * pos_error + Kd * vel_error``.
**DcMotorActuator**: Extends ``IdealPdActuator`` with velocity-dependent
torque saturation to model DC motor torque-speed curves (back-EMF
effects). Implements a linear torque-speed curve: maximum torque at zero
velocity, zero torque at maximum velocity.
**LearnedMlpActuator**: Neural network-based actuator that uses a
trained MLP to predict torque outputs from joint state history. Useful
when analytical models cannot capture complex actuator dynamics like
delays, nonlinearities, and friction effects. Inherits DC motor
velocity-based torque limits.
.. code-block:: python
from mjlab.actuator import IdealPdActuatorCfg, DcMotorActuatorCfg
# Ideal PD for hips, DC motor model with torque-speed curve for knees.
actuators = (
IdealPdActuatorCfg(
target_names_expr=(".*_hip_.*",),
stiffness=80.0,
damping=10.0,
effort_limit=100.0,
),
DcMotorActuatorCfg(
target_names_expr=(".*_knee_.*",),
stiffness=80.0,
damping=10.0,
effort_limit=25.0, # Continuous torque limit
saturation_effort=50.0, # Peak torque at stall
velocity_limit=30.0, # No-load speed (rad/s)
),
)
XML actuators
^^^^^^^^^^^^^
XML actuators wrap actuators already defined in your robot's XML file. The
config finds existing actuators by matching their ``target`` joint name
against the ``target_names_expr`` patterns. Each joint must have exactly one
matching actuator.
**XmlActuator**: Wraps any actuator already defined in the XML. The
actuator type (position, velocity, motor, muscle) is auto detected from
the XML element, or you can set ``command_field`` explicitly.
.. code-block:: python
from mjlab.actuator import XmlActuatorCfg
# Robot XML already has:
# <actuator>
# <position name="hip_joint" joint="hip_joint" kp="100"/>
# </actuator>
# Wrap existing XML actuators.
actuators = (
XmlActuatorCfg(target_names_expr=("hip_joint",)),
)
Actuator delays
^^^^^^^^^^^^^^^
Any actuator config supports inline delay fields for modeling command
latency. On a real robot, the onboard PD loop runs at KHz with direct
encoder access, but the position target from the policy arrives late due
to inference time and communication bus cycles. Actuator
delay models this: the command target is delayed, but the control law
still sees fresh joint state.
This is distinct from observation delay, which models sensor pipeline
latency (stale state going into the policy). Together they cover both
legs of the round trip: sensor to policy to motor.
.. code-block:: python
from mjlab.actuator import IdealPdActuatorCfg
# Add 2-5 step delay to position commands.
actuators = (
IdealPdActuatorCfg(
target_names_expr=(".*",),
stiffness=80.0,
damping=10.0,
delay_min_lag=2,
delay_max_lag=5,
delay_hold_prob=0.3, # 30% chance to keep current lag
delay_update_period=10, # Resample lag every 10 steps
),
)
Each step, a lag is sampled uniformly from ``[delay_min_lag,
delay_max_lag]``. Delays are quantized to physics timesteps. For
example, with 500Hz physics (2ms/step), ``delay_min_lag=2`` represents
a 4ms minimum delay.
Authoring actuator configs
--------------------------
Since actuator parameters are uniform within each config, use separate
actuator configs for joints that need different parameters:
.. code-block:: python
from mjlab.actuator import BuiltinPositionActuatorCfg
# G1 humanoid with different gains per joint group.
G1_ACTUATORS = (
BuiltinPositionActuatorCfg(
target_names_expr=(".*_hip_.*", "waist_yaw_joint"),
stiffness=180.0,
damping=18.0,
effort_limit=88.0,
armature=0.0015,
),
BuiltinPositionActuatorCfg(
target_names_expr=("left_hip_pitch_joint", "right_hip_pitch_joint"),
stiffness=200.0,
damping=20.0,
effort_limit=88.0,
armature=0.0015,
),
BuiltinPositionActuatorCfg(
target_names_expr=(".*_knee_joint",),
stiffness=150.0,
damping=15.0,
effort_limit=139.0,
armature=0.0025,
),
BuiltinPositionActuatorCfg(
target_names_expr=(".*_ankle_.*",),
stiffness=40.0,
damping=5.0,
effort_limit=25.0,
armature=0.0008,
),
)
This design choice reflects a deliberate simplification in mjlab: each
``ActuatorCfg`` represents a single actuator type (e.g., a specific
motor/gearbox model) applied uniformly across all joints it drives.
Hardware parameters such as ``armature`` (reflected rotor inertia) and
``gear`` describe properties of the actuator hardware, even though they
are implemented in MuJoCo as joint or actuator fields. In other frameworks
(like Isaac Lab), these fields may accept ``float | dict[str, float]`` to
support per-joint variation. mjlab instead encourages one config per
actuator type or per joint group, keeping the hardware model physically
consistent and explicit. The main trade-off is verbosity in special cases,
such as parallel linkages, where per-joint overrides could have been
convenient, but the benefit is clearer semantics and simpler maintenance.
See :ref:`actions` for how action terms route policy outputs to actuators
(including DifferentialIK for task-space control), and
:ref:`domain_randomization` for randomizing gains and effort limits.
Computing hardware parameters
------------------------------
This section is relevant when configuring actuators from real motor
datasheets. If you are using manually tuned gains, you can skip ahead.
mjlab provides utilities in ``mjlab.utils.actuator`` to compute actuator
parameters from physical motor specifications. This is particularly
useful for computing reflected inertia (``armature``) and deriving
appropriate control gains from hardware datasheets.
**Example: Unitree G1 motor configuration**
.. code-block:: python
from math import pi
from mjlab.utils.actuator import (
reflected_inertia_from_two_stage_planetary,
ElectricActuator
)
# Motor specs from manufacturer datasheet.
ROTOR_INERTIAS_7520_14 = (
0.489e-4, # Motor rotor inertia (kg*m**2)
0.098e-4, # Planet carrier inertia
0.533e-4, # Output stage inertia
)
GEARS_7520_14 = (
1, # First stage (motor to planet)
4.5, # Second stage (planet to carrier)
1 + (48/22), # Third stage (carrier to output)
)
# Compute reflected inertia at joint output.
# J_reflected = J_motor*(N1*N2)**2 + J_carrier*N2**2 + J_output.
ARMATURE_7520_14 = reflected_inertia_from_two_stage_planetary(
ROTOR_INERTIAS_7520_14, GEARS_7520_14
)
# Create motor spec container.
ACTUATOR_7520_14 = ElectricActuator(
reflected_inertia=ARMATURE_7520_14,
velocity_limit=32.0, # rad/s at joint
effort_limit=88.0, # N*m continuous torque
)
# Derive PD gains from natural frequency and damping ratio.
NATURAL_FREQ = 10 * 2*pi # 10 Hz bandwidth.
DAMPING_RATIO = 2.0 # Overdamped, see note below.
STIFFNESS = ARMATURE_7520_14 * NATURAL_FREQ**2
DAMPING = 2 * DAMPING_RATIO * ARMATURE_7520_14 * NATURAL_FREQ
# Use in actuator config.
from mjlab.actuator import BuiltinPositionActuatorCfg
actuator = BuiltinPositionActuatorCfg(
target_names_expr=(".*_hip_pitch_joint",),
stiffness=STIFFNESS,
damping=DAMPING,
effort_limit=ACTUATOR_7520_14.effort_limit,
armature=ACTUATOR_7520_14.reflected_inertia,
)
.. note::
The example uses ``DAMPING_RATIO = 2.0``
(overdamped) rather than the critically damped value of 1.0. This is
because the reflected inertia calculation only accounts for the motor's
rotor inertia, not the apparent inertia of the links being moved. In
practice, the total effective inertia at the joint is higher than just
the reflected motor inertia, so using an overdamped ratio provides
better stability margins when the true system inertia is
underestimated.
**Parallel linkage approximation:**
For joints driven by parallel linkages (like the G1's ankles with dual
motors), the effective armature in the nominal configuration can be
approximated as the sum of the individual motor armatures:
.. code-block:: python
# Two 5020 motors driving ankle through parallel linkage.
G1_ACTUATOR_ANKLE = BuiltinPositionActuatorCfg(
target_names_expr=(".*_ankle_pitch_joint", ".*_ankle_roll_joint"),
stiffness=STIFFNESS_5020 * 2,
damping=DAMPING_5020 * 2,
effort_limit=ACTUATOR_5020.effort_limit * 2,
armature=ACTUATOR_5020.reflected_inertia * 2,
)
Extending: custom actuators
----------------------------
All actuators implement a unified ``compute()`` interface that receives an
``ActuatorCmd`` (containing position, velocity, and effort targets) and
returns control signals for the low-level MuJoCo actuators driving each
joint.
**Core interface:**
.. code-block:: python
def compute(self, cmd: ActuatorCmd) -> torch.Tensor:
"""Convert high-level commands to control signals.
Args:
cmd: Command containing position_target, velocity_target,
effort_target (each is a [num_envs, num_targets] tensor
or None)
Returns:
Control signals for this actuator
([num_envs, num_targets] tensor)
"""
**Lifecycle hooks:**
- ``edit_spec``: Modify MjSpec before compilation (add actuators, set
gains)
- ``initialize``: Post-compilation setup (resolve indices, allocate
buffers)
- ``reset``: Per-environment reset logic
- ``update``: Pre-step updates
- ``compute``: Convert commands to control signals
**Properties:**
- ``target_ids``: Tensor of local target indices controlled by this
actuator
- ``target_names``: List of target names controlled by this actuator
- ``ctrl_ids``: Tensor of global control input indices for this actuator
``IdealPdActuator`` is the recommended base class for custom explicit
actuators. ``DcMotorActuator`` and ``LearnedMlpActuator`` are both
built on top of it and serve as examples of the extension pattern.
@@ -0,0 +1,141 @@
mjlab.actuator
==============
.. automodule:: mjlab.actuator
.. rubric:: Classes
.. hlist::
:columns: 3
- :class:`Actuator`
- :class:`ActuatorCfg`
- :class:`ActuatorCmd`
- :class:`BuiltinActuatorGroup`
- :class:`BuiltinMotorActuator`
- :class:`BuiltinMotorActuatorCfg`
- :class:`BuiltinPositionActuator`
- :class:`BuiltinPositionActuatorCfg`
- :class:`BuiltinVelocityActuator`
- :class:`BuiltinVelocityActuatorCfg`
- :class:`BuiltinMuscleActuator`
- :class:`BuiltinMuscleActuatorCfg`
- :class:`XmlActuator`
- :class:`XmlActuatorCfg`
- :class:`IdealPdActuator`
- :class:`IdealPdActuatorCfg`
- :class:`DcMotorActuator`
- :class:`DcMotorActuatorCfg`
- :class:`LearnedMlpActuator`
- :class:`LearnedMlpActuatorCfg`
Base
----
.. autoclass:: Actuator
:members:
:show-inheritance:
.. autoclass:: ActuatorCfg
:members:
:exclude-members: __init__
:undoc-members:
.. autoclass:: ActuatorCmd
:members:
:exclude-members: __init__
:undoc-members:
Builtin Actuators
-----------------
.. autoclass:: BuiltinActuatorGroup
:members:
:show-inheritance:
.. autoclass:: BuiltinMotorActuator
:members:
:show-inheritance:
.. autoclass:: BuiltinMotorActuatorCfg
:members:
:exclude-members: __init__
:undoc-members:
.. autoclass:: BuiltinPositionActuator
:members:
:show-inheritance:
.. autoclass:: BuiltinPositionActuatorCfg
:members:
:exclude-members: __init__
:undoc-members:
.. autoclass:: BuiltinVelocityActuator
:members:
:show-inheritance:
.. autoclass:: BuiltinVelocityActuatorCfg
:members:
:exclude-members: __init__
:undoc-members:
.. autoclass:: BuiltinMuscleActuator
:members:
:show-inheritance:
.. autoclass:: BuiltinMuscleActuatorCfg
:members:
:exclude-members: __init__
:undoc-members:
XML Actuators
-------------
.. autoclass:: XmlActuator
:members:
:show-inheritance:
.. autoclass:: XmlActuatorCfg
:members:
:exclude-members: __init__
:undoc-members:
Ideal PD Actuator
-----------------
.. autoclass:: IdealPdActuator
:members:
:show-inheritance:
.. autoclass:: IdealPdActuatorCfg
:members:
:exclude-members: __init__
:undoc-members:
DC Motor Actuator
-----------------
.. autoclass:: DcMotorActuator
:members:
:show-inheritance:
.. autoclass:: DcMotorActuatorCfg
:members:
:exclude-members: __init__
:undoc-members:
Learned MLP Actuator
--------------------
.. autoclass:: LearnedMlpActuator
:members:
:show-inheritance:
.. autoclass:: LearnedMlpActuatorCfg
:members:
:exclude-members: __init__
@@ -0,0 +1,45 @@
mjlab.entity
============
.. automodule:: mjlab.entity
.. rubric:: Classes
.. hlist::
:columns: 3
- :class:`Entity`
- :class:`EntityCfg`
- :class:`EntityArticulationInfoCfg`
- :class:`EntityIndexing`
- :class:`EntityData`
Entity
------
.. autoclass:: Entity
:members:
:show-inheritance:
.. autoclass:: EntityCfg
:members:
:exclude-members: __init__
:undoc-members:
.. autoclass:: EntityArticulationInfoCfg
:members:
:exclude-members: __init__
:undoc-members:
EntityIndexing
--------------
.. autoclass:: EntityIndexing
:members:
EntityData
----------
.. autoclass:: EntityData
:members:
@@ -0,0 +1,36 @@
mjlab.envs
==========
.. automodule:: mjlab.envs
.. rubric:: Classes
.. hlist::
:columns: 3
- :class:`ManagerBasedRlEnv`
- :class:`ManagerBasedRlEnvCfg`
- :data:`VecEnvObs`
- :data:`VecEnvStepReturn`
ManagerBasedRlEnv
-----------------
.. autoclass:: ManagerBasedRlEnv
:members:
:show-inheritance:
.. autoclass:: ManagerBasedRlEnvCfg
:members:
:exclude-members: __init__
:undoc-members:
VecEnvObs
---------
.. autodata:: VecEnvObs
VecEnvStepReturn
----------------
.. autodata:: VecEnvStepReturn
@@ -0,0 +1,19 @@
API Reference
=============
This section provides detailed API documentation for all public modules in mjlab.
.. toctree::
:maxdepth: 1
envs
scene
sim
entity
actuator
sensor
managers
terrains
rl
viewer
tasks
@@ -0,0 +1,208 @@
mjlab.managers
==============
.. automodule:: mjlab.managers
.. rubric:: Classes
.. hlist::
:columns: 3
- :class:`ManagerBase`
- :class:`ManagerTermBase`
- :class:`ManagerTermBaseCfg`
- :class:`SceneEntityCfg`
- :class:`ActionManager`
- :class:`ActionTerm`
- :class:`ActionTermCfg`
- :class:`ObservationManager`
- :class:`ObservationGroupCfg`
- :class:`ObservationTermCfg`
- :class:`RewardManager`
- :class:`RewardTermCfg`
- :class:`TerminationManager`
- :class:`TerminationTermCfg`
- :class:`CommandManager`
- :class:`NullCommandManager`
- :class:`CommandTerm`
- :class:`CommandTermCfg`
- :class:`CurriculumManager`
- :class:`NullCurriculumManager`
- :class:`CurriculumTermCfg`
- :class:`EventManager`
- :class:`EventMode`
- :class:`EventTermCfg`
- :class:`MetricsManager`
- :class:`NullMetricsManager`
- :class:`MetricsTermCfg`
- :class:`RecorderManager`
- :class:`NullRecorderManager`
- :class:`RecorderTerm`
- :class:`RecorderTermCfg`
Base
----
.. autoclass:: ManagerBase
:members:
:show-inheritance:
.. autoclass:: ManagerTermBase
:members:
:show-inheritance:
.. autoclass:: ManagerTermBaseCfg
:members:
:exclude-members: __init__
:undoc-members:
.. autoclass:: SceneEntityCfg
:members:
:exclude-members: __init__
:undoc-members:
Action Manager
--------------
.. autoclass:: ActionManager
:members:
:show-inheritance:
.. autoclass:: ActionTerm
:members:
:show-inheritance:
.. autoclass:: ActionTermCfg
:members:
:exclude-members: __init__
:undoc-members:
Observation Manager
-------------------
.. autoclass:: ObservationManager
:members:
:show-inheritance:
.. autoclass:: ObservationGroupCfg
:members:
:exclude-members: __init__
:undoc-members:
.. autoclass:: ObservationTermCfg
:members:
:exclude-members: __init__
:undoc-members:
Reward Manager
--------------
.. autoclass:: RewardManager
:members:
:show-inheritance:
.. autoclass:: RewardTermCfg
:members:
:exclude-members: __init__
:undoc-members:
Termination Manager
-------------------
.. autoclass:: TerminationManager
:members:
:show-inheritance:
.. autoclass:: TerminationTermCfg
:members:
:exclude-members: __init__
:undoc-members:
Command Manager
---------------
.. autoclass:: CommandManager
:members:
:show-inheritance:
.. autoclass:: NullCommandManager
:members:
:show-inheritance:
.. autoclass:: CommandTerm
:members:
:show-inheritance:
.. autoclass:: CommandTermCfg
:members:
:exclude-members: __init__
:undoc-members:
Curriculum Manager
------------------
.. autoclass:: CurriculumManager
:members:
:show-inheritance:
.. autoclass:: NullCurriculumManager
:members:
:show-inheritance:
.. autoclass:: CurriculumTermCfg
:members:
:exclude-members: __init__
:undoc-members:
Event Manager
-------------
.. autoclass:: EventManager
:members:
:show-inheritance:
.. autoclass:: EventMode
:members:
:undoc-members:
.. autoclass:: EventTermCfg
:members:
:exclude-members: __init__
:undoc-members:
Metrics Manager
---------------
.. autoclass:: MetricsManager
:members:
:show-inheritance:
.. autoclass:: NullMetricsManager
:members:
:show-inheritance:
.. autoclass:: MetricsTermCfg
:members:
:exclude-members: __init__
Recorder Manager
----------------
.. autoclass:: RecorderManager
:members:
:show-inheritance:
.. autoclass:: NullRecorderManager
:members:
:show-inheritance:
.. autoclass:: RecorderTerm
:members:
:show-inheritance:
.. autoclass:: RecorderTermCfg
:members:
:exclude-members: __init__
:undoc-members:
@@ -0,0 +1,52 @@
mjlab.rl
========
.. automodule:: mjlab.rl
.. rubric:: Classes
.. hlist::
:columns: 3
- :class:`MjlabOnPolicyRunner`
- :class:`RslRlVecEnvWrapper`
- :class:`RslRlOnPolicyRunnerCfg`
- :class:`RslRlPpoAlgorithmCfg`
- :class:`RslRlModelCfg`
- :class:`RslRlBaseRunnerCfg`
Runner
------
.. autoclass:: MjlabOnPolicyRunner
:members:
:show-inheritance:
.. autoclass:: RslRlVecEnvWrapper
:members:
:show-inheritance:
Configuration
-------------
.. autoclass:: RslRlOnPolicyRunnerCfg
:members:
:exclude-members: __init__
:undoc-members:
.. autoclass:: RslRlPpoAlgorithmCfg
:members:
:exclude-members: __init__
:undoc-members:
.. autoclass:: RslRlModelCfg
:members:
:exclude-members: __init__
:undoc-members:
.. autoclass:: RslRlBaseRunnerCfg
:members:
:exclude-members: __init__
@@ -0,0 +1,23 @@
mjlab.scene
===========
.. automodule:: mjlab.scene
.. rubric:: Classes
.. hlist::
:columns: 3
- :class:`Scene`
- :class:`SceneCfg`
Scene
-----
.. autoclass:: Scene
:members:
.. autoclass:: SceneCfg
:members:
:exclude-members: __init__
:undoc-members:

Some files were not shown because too many files have changed in this diff Show More