这个系列文章用来记录 Google DeepMind 发布的 Mujoco
仿真平台的使用过程,Mujoco 是具身智能领域中非常知名的仿真平台,以简单易用的API和精准的物理引擎而著称(PS:原来Google能写好API文档啊),也是我平时使用最多的仿真平台,相比较于Gazebo、Isaac Sim 等仿真器而言至少对我来说非常高效,能够在初期快速验证模型性能以及配置文件,下面是几个我常用的仿真平台对比:
仿真平台 | 开发公司 | 渲染 | 物理引擎 | 主要优势 | 典型用途 |
---|---|---|---|---|---|
MuJoCo | DeepMind (原Roboti) | 中 | MuJoCo | 精确的物理建模、速度快、适合优化 | 强化学习、控制算法研究 |
Gazebo | Open Robotics | 中 | ODE, Bullet 等 | 与 ROS 深度集成、功能丰富 | 机器人系统集成、SLAM、导航 |
Isaac Sim | NVIDIA | 强 | PhysX(GPU支持) | 高保真渲染、多传感器仿真、数字孪生 | 机器人感知、数字孪生建模 |
Isaac Gym | NVIDIA | 弱 | PhysX(GPU加速) | 多环境并行、用于大规模RL训练 | 强化学习 |
作为系列文章的第一篇是安装与部署,整个系列将聚焦仿真这一方向,在部署到真机前实现模型验证。
1. 前期准备工作
前期准备工作主要是检查你的硬件条件,虽然官方文档中提到了对OpenGL的需求,但如果你的OS内核没有过于古老的情况下是不用理会的。
- Github 仓库:https://github.com/google-deepmind/mujoco
- 官方文档:https://mujoco.readthedocs.io/en/stable/overview.html
这里以我个人的平台为例,具体配置如下:
- OS:Ubuntu 20.04 Desktop
- CPU:12th Gen Intel® Core™ i7-12700K
- Memory:Sumsung DDR4 32*2 GB
- GPU:NVIDIA GeForce RTX 3060 Super 12 GB
- CUDA Version:12.2
- GPU Driver:535.183.01
- Mujoco Version:3.3.2
后续会在GPU服务器上部署仿真平台并训练模型,如果没有特殊说明的情况下都是以上述配置进行实验。
虽然官方没有说明有关仿真平台的硬件要求,但我个人建议CPU使用12代及其以上型号、内存不低于32GB、显卡在3060及其以上,因为后面会有博客教你如何在Mujoco上使用模型进行推理,如果你的显卡显存不够的话几个经典模型是跑不起来的。
2. 编译与部署
Mujoco 提供了Release和source两种部署方式,支持 Windows、MacOS、Linux 三大平台,自己编译与直接拉取二进制文件效果一样,两种方式二选一。
2.1 源码编译
- 官方提供的编译文档:Building from source
拉取源码
$ git clone git@github.com:google-deepmind/mujoco.git
因为编译过程中会使用到 cmake 的 FetchContent
从网上拉取需要的组件,所以需要你确保梯子可用。
编译源码
$ cd mujoco
$ mkdir build && cd build
$ cmake .....
-- Looking for IceConnectionNumber in ICE
-- Looking for IceConnectionNumber in ICE - found
-- mujoco::FindOrFetch: Using FetchContent to retrieve `glfw3` - Done
-- mujoco::FindOrFetch: checking for targets in package `mujoco`
-- mujoco::FindOrFetch: checking for targets in package `mujoco` - found
-- mujoco::FindOrFetch: checking for targets in package `glfw3`
-- mujoco::FindOrFetch: checking for targets in package `glfw3` - found
-- Configuring done
-- Generating done
-- Build files have been written to: /home/gaohao/Downloads/mujoco/build
上面的操作没有报错的可以继续执行编译命令:
$ cmake --build . # 【不推荐】官方编译命令
$ make -j$(nproc) # 【推荐】多线程编译
$ make install```
2.2 下载二进制文件
直接在官方 Github 仓库的 Release 中下载即可:
下载好后直接解压:
$ tar -zxvf mujoco-3.3.2-linux-x86_64.tar.gz
然后在 ~/.bashrc
文件的末尾添加以下内容:
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:~/Downloads/mujoco-3.3.2/bin
2.3 安装 python 库
这里建议使用conda管理python环境,根据官网介绍需要使用 3.8 及其以上版本,我这里使用 3.10:
$ conda create --name mujoco python=3.10
$ pip install mujoco
2.4 验证安装效果
新建一个python脚本并添加下面的内容用来加载mujoco自带的一个xml模型文件 humanoid.xml
,在安装/编译位置的 model
文件夹中
import mujoco# 你的实际安装路径
model_path = '~/Downloads/mujoco-3.3.2/model/humanoid/humanoid.xml'
model = mujoco.MjModel.from_xml_path(model_path)
data = mujoco.MjData(model)
print(data)
# 调用计时API确保其他组件正常安装
for _ in range(1000): mujoco.mj_step(model, data)print("Test done.")
运行示例:
(mujoco) $ python test.py<mujoco._structs.MjData object at 0x7ff67c1471b0>
Test done.
能够正确打印 data 的数据类型则说明安装成功。
2.5 验证仿真器 simulate
在确保上面的API验证没有报错的前提下需要验证仿真器是否能够正常运行:
$ cd mujoco/bin
$ ./simulate ../model/humanoid/humaniod.xml
运行后会弹出仿真器,此时你需要确认以下几点是可用的:
- 小人在没有干预的情况下逐渐躺到在地面;
- 右侧打开
Control
面板拖动控制条,小人对应的关节是可动的;
3. 使用 URDF 文件
如果你有机器人的开发经验,特别是在ROS平台上,那么通常用得最多的是 urdf
或 xacro
,但 mujoco 原生并不支持 urdf
格式的文件,需要将其转换为 xml
后使用。
3.1 获取机器人 urdf 文件
这里推荐一个 Github 仓库 Awesome Robot Descriptions
里面有很多开源的机器人模型文件。
- Github 仓库链接:Awesome Robot Descriptions
这里以 Gen2
这个机械臂模型为例,直接点击 URDF
进入对应的仓库:
你可以将整个仓库下载下来也可以用浏览器插件下载一部分,这里为了方便我直接将 example-robot-data/robots/kinova_description
这个文件夹拷贝了一份到 mujoco-3.3.2
目录下,当前文件结构如下:
$ cd ~/Downloads/mujoco-3.3.2
$ tree -L 1
.
├── bin
├── demo.py
├── include
├── kinova_description # 从 example-robot-data/robots/ 拷贝过来的文件夹
├── lib
├── model
├── MUJOCO_LOG.TXT
├── sample
├── simulate
└── THIRD_PARTY_NOTICES
进入kinova_description/robots
检查一下 kinova.urdf
文件的link树是否完整:
$ cd kinova_description/robots
$ check_urdf kinova.urdfrobot name is: kinova
---------- Successfully Parsed XML ---------------
root Link: base has 1 child(ren)child(1): j2s6s200_link_basechild(1): j2s6s200_link_1child(1): j2s6s200_link_2child(1): j2s6s200_link_3child(1): j2s6s200_link_4child(1): j2s6s200_link_5child(1): j2s6s200_link_6child(1): j2s6s200_end_effectorchild(2): j2s6s200_link_finger_1child(1): j2s6s200_link_finger_tip_1child(3): j2s6s200_link_finger_2child(1): j2s6s200_link_finger_tip_2
只要没有报错则说明文件 urdf 的link树是正确的,那么就可以进行后续操作。
【Note】:这一步一定要去做,因为后面有些问题就是由于link树没有正确连接导致的,但urdf 文件本身排查起来很累,所以在使用前就检查连接合法性是最合适的。
3.2 [可选] 转换 mesh 文件
如果你的机器人模型文件引用的 mesh 文件是 stl
格式,则可以直接跳过这一段,这里为了更全面的演示我特意找的是 dae
格式的文件。
将 dae
文件转换为 stl
有很多种方法,我常用的方法有以下三种,前两种是可能的偷懒方法,其中第三种是一定可行的,之所以说是可能的偷懒方法是因为这两种转化方式的成功与否完全取决于厂商是否规范和运气。但无论如何都需要对原始文件进行备份:
$ cp -r meshes/ meshes_mujoco/
对于偷懒方法而言,使用后直接跳到 3.3
小节完成 urdf 文件修改后即可执行 3.4
小节验证是否可用,如果不可用则跳回来在剩下两个方法中再选一个尝试。
3.2.1 可能的偷懒方法一
第一种可能的偷懒方法是直接修改文件后缀名,使用下面的命令可以直接将 dae
后缀修改为 stl
后缀:
$ cd meshes_mujoco
$ for file in *.dae; do mv "$file" "${file%.dae}.stl"; done
3.3.2 可能的偷懒方法二
第二种可能的偷懒方法是用python脚本批量修改,需要安装依赖库:
$ pip install trimesh pyglet
我这里提供了一个python脚本:
import os
import sys
import trimeshdef convert_dae_to_stl(folder_path):if not os.path.isdir(folder_path):print(f"路径无效:{folder_path}")return# 获取所有 .dae 文件dae_files = [f for f in os.listdir(folder_path) if f.lower().endswith('.dae')]if not dae_files:print("未找到 .dae 文件。")returnfor dae_file in dae_files:dae_path = os.path.join(folder_path, dae_file)stl_path = os.path.join(folder_path, os.path.splitext(dae_file)[0] + '.stl')try:mesh = trimesh.load(dae_path)if mesh.is_empty:print(f"跳过空模型:{dae_file}")continuemesh.export(stl_path)print(f"转换成功:{dae_file} -> {os.path.basename(stl_path)}")except Exception as e:print(f"转换失败:{dae_file},错误信息:{e}")if __name__ == '__main__':if len(sys.argv) < 2:print("用法:python convert.py <文件夹路径>")else:convert_dae_to_stl(sys.argv[1])
通过下面的命令使用,运行后会在 meshes_mujoco/
文件夹下生成同名但格式不同的mesh文件:
$ cd meshes_mujoco/
$ python conv.py ./
3.2.3 绝对可行的方法
最保险和稳妥的方法是使用第三方工具将文件转换成 stl
格式并保存,这里推荐使用开源工具 meshlab
,这个方式比较麻烦的点在于需要一个一个手动转换后保存:
- Meshlab 官网链接:https://www.meshlab.net
进入后在 Download
页面中选择合适的版本下载。
打开软件后直接按照下面的步骤操作:
File
->Import Mesh..
;File
->Export Mesh As..
;- 在弹出的对话框中选择
.stl
格式并保存;
【Note】:因为 mujoco 在使用mesh文件时紧支持表面不超过 200000
个渲染面的文件,如果你在后面运行时出现了相关报错还可以按照下面的步骤减少渲染面个数:
Filters
->Remeshing, Simplication and Reconstruction
->Simplication: Quadric Edge Collaspe Decimation
;- 在弹出的界面中将渲染面改到合适的范围;
3.3 修改 urdf 文件
然后编辑 kinova.urdf
文件,总共需要做2步操作:
- 将
mesh
file 的搜索路径改为相对路径; - 修改
.dae
文件后缀为.stl
; - 添加 mujoco 的 mesh 文件搜索路径;
3.2.1 修改 mesh file 的搜索路径
打开urdf文件后将里面的 package://example-robot-data/robots/kinova_description/meshes
批量替换成 ../meshes_mujoco
:
3.2.2 修改 .dae 文件后缀为 .stl
如果你的urdf文件本身用的就是 stl
后缀就不用执行这一步;如果是跟着我的示例就需要执行,同样是批量查找并替换:
3.2.3 添加 mujoco mesh 重定向信息
在文件末尾处添加以下字段以让mujoco能够找到 mesh 文件:
【Note】:添加的部分一定要在 <robot>...</robot>
标签内。
<robot>...<mujoco><compiler balanceinertia="true" discardvisual="false" meshdir="../meshes_mujoco"/></mujoco>
</robot>
3.4 运行 urdf 转换命令
此时你的kinova_description
文件结构如下:
$ cd mujoco-3.3.2/kinova_description/
$ tree -L 1.
├── meshes # 原始的dae文件夹
├── meshes_mujoco # 转换成stl的文件夹
├── README.md
├── robots
└── srdf
运行转换命令:
(mujoco) $ cd ../
(mujoco) $ ./bin/compile kinova_description/robots/kinova.urdf kinova_description/robots/kinova.xml...
WARNING: Geom with duplicate name '' encountered in URDF, creating an unnamed geom.
WARNING: Geom with duplicate name '' encountered in URDF, creating an unnamed geom.
WARNING: Geom with duplicate name '' encountered in URDF, creating an unnamed geom.
WARNING: Geom with duplicate name '' encountered in URDF, creating an unnamed geom.
Done.
First compile: 0.1349s
Second compile: 0.02025s
输出上面的样子则表明转换成功。
3.4.1 可能的报错一:
如果运行后发现有以下报错:
Error: number of faces should be between 1 and 200000 in STL file 'kinova_description/robots/../meshes_mujoco/base.stl'; perhaps this is an ASCII file?
有两种可能性:
- 不能直接通过修改文件后缀的方式,跳回到
3.2.3
老老实实用最稳妥的方式一个一个手动转化吧; - 文件的 mesh 渲染面体太多了,跳回到
3.2.3
中修改渲染面的个数;
3.4.2 可能的报错二:
如果运行后发现有以下报错:
Error: Error opening file 'kinova_description/robots/base.stl': No such file or directory
通常是应为没有执行 3.2.3
步导致的,在urdf中添加字段让 mujoco 完成重定向。
3.4.3 可能的报错三:
如果运行后发现有以下报错:
...
Plugins registered by library 'libelasticity.so':mujoco.elasticity.cablemujoco.elasticity.shell
ERROR: could not initialize GLFW
通常是因为没有使用虚拟环境导致的,使用正确的conda环境,在我这里是mujoco
:
$ conda activate mujoco
如果仍然是这个报错,检测你的命令是否输错了:
$ ./bin/simulate # 错误
$ ./bin/compile # 正确
3.5 打开仿真器 simulate
在确保转换成功后就可以打开仿真器查看机器人模型了,仿真器使用的是 xml
格式的文件,如果打开的是 urdf
则会报错。
$ cd mujoco-3.3.2
$ ./bin/simulate kinova_description/robots/kinova.xml