[software] 添加16DOF早期训练仿真与Sim2Real闭环
@@ -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` 的约束。
|
||||
@@ -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。
|
||||
@@ -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"]
|
||||
@@ -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.
|
||||
@@ -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 .
|
||||
@@ -0,0 +1,140 @@
|
||||

|
||||
|
||||
# mjlab
|
||||
|
||||
[](https://github.com/mujocolab/mjlab/actions/workflows/ci.yml?query=branch%3Amain)
|
||||
[](https://mujocolab.github.io/mjlab/)
|
||||
[](https://github.com/mujocolab/mjlab/blob/main/LICENSE)
|
||||
[](https://mujocolab.github.io/mjlab/nightly/)
|
||||
[](https://pypi.org/project/mjlab/)
|
||||
[](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.
|
||||
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 1.5 MiB |
|
After Width: | Height: | Size: 253 KiB |
|
After Width: | Height: | Size: 104 KiB |
|
After Width: | Height: | Size: 285 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 751 KiB |
|
After Width: | Height: | Size: 1.9 MiB |
|
After Width: | Height: | Size: 78 KiB |
|
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;
|
||||
}
|
||||
|
After Width: | Height: | Size: 442 KiB |
|
After Width: | Height: | Size: 838 KiB |
|
After Width: | Height: | Size: 76 KiB |
|
After Width: | Height: | Size: 1.3 MiB |
|
After Width: | Height: | Size: 751 KiB |
|
After Width: | Height: | Size: 1.9 MiB |
|
After Width: | Height: | Size: 335 KiB |
|
After Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 67 KiB |
|
After Width: | Height: | Size: 72 KiB |
|
After Width: | Height: | Size: 93 KiB |
|
After Width: | Height: | Size: 94 KiB |
|
After Width: | Height: | Size: 90 KiB |
|
After Width: | Height: | Size: 150 KiB |
|
After Width: | Height: | Size: 109 KiB |
|
After Width: | Height: | Size: 85 KiB |
|
After Width: | Height: | Size: 114 KiB |
|
After Width: | Height: | Size: 125 KiB |
|
After Width: | Height: | Size: 923 KiB |
|
After Width: | Height: | Size: 178 KiB |
|
After Width: | Height: | Size: 707 KiB |
|
After Width: | Height: | Size: 338 KiB |
|
After Width: | Height: | Size: 1.1 MiB |
|
After Width: | Height: | Size: 733 KiB |
|
After Width: | Height: | Size: 46 KiB |
|
After Width: | Height: | Size: 1.1 MiB |
|
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:
|
||||