MuJoCo 是一个物理引擎,用于使用contacts进行详细、高效的刚体模拟。
mujoco-py
允许使用 Python 3 中的 MuJoCo。
该库已更新为与 2021 年 10 月 18 日发布的 MuJoCo 2.1 版兼容。
目前支持以下平台:
Dockerfile
for the canonical list of system dependencies.以下平台已弃用且不受支持:
0.5
分支。 最新版本是 0.5.7
,可以使用 pip install mujoco-py==0.5.7
安装。mujoco210
directory into ~/.mujoco/mujoco210
.If you want to specify a nonstandard location for the package,
use the env variable MUJOCO_PY_MUJOCO_PATH
.
mujoco-py
要将 mujoco-py
包含在您自己的包中,请将其添加到您的要求中,如下所示:
mujoco-py<2.2,>=2.1
要以交互方式使用“mujoco-py”,请执行以下步骤:
$ pip3 install -U 'mujoco-py<2.2,>=2.1'
$ python3
import mujoco_py
import os
mj_path = mujoco_py.utils.discover_mujoco()
xml_path = os.path.join(mj_path, 'model', 'humanoid.xml')
model = mujoco_py.load_model_from_path(xml_path)
sim = mujoco_py.MjSim(model)
print(sim.data.qpos)
# [0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
sim.step()
print(sim.data.qpos)
# [-2.09531783e-19 2.72130735e-05 6.14480786e-22 -3.45474715e-06
# 7.42993721e-06 -1.40711141e-04 -3.04253586e-04 -2.07559344e-04
# 8.50646247e-05 -3.45474715e-06 7.42993721e-06 -1.40711141e-04
# -3.04253586e-04 -2.07559344e-04 -8.50646247e-05 1.11317030e-04
# -7.03465386e-05 -2.22862221e-05 -1.11317030e-04 7.03465386e-05
# -2.22862221e-05]
有关高级用法,请参阅 完整文档。
安装时的常见错误是:
raise ImportError("Failed to load GLFW3 shared library.")
当 glfw
python 包无法找到 GLFW 动态库时会发生这种情况。
MuJoCo 附带了它自己的这个库的副本,可以在安装过程中使用。
将 mujoco bin 目录的路径添加到动态加载器:
LD_LIBRARY_PATH=$HOME/.mujoco/mujoco210/bin pip install mujoco-py
这在没有 GLFW 包的 Ubuntu 14.04 上特别有用。
因为 mujoco_py
已经编译了需要链接到提供的 MuJoCo 二进制文件的本机代码,所以它正在安装
在 linux 上可能比纯 Python 源代码包更具挑战性。
要在 Ubuntu 上安装 mujoco-py,请确保已安装以下库:
sudo apt install libosmesa6-dev libgl1-mesa-glx libglfw3
如果您安装了上述库,但仍然看到找不到 -lGL
的错误,很可能您需要直接创建符号链接:
sudo ln -s /usr/lib/x86_64-linux-gnu/libGL.so.1 /usr/lib/x86_64-linux-gnu/libGL.so
要运行提供的单元和集成测试:
make test
要测试 GPU 支持的渲染,请运行:
make test_gpu
目前这在一定程度上取决于内部 OpenAI 基础设施,但如果您为自己的设置更改“Makefile”参数,它应该会运行。
mujoco_py.load_model_from_path
(路径)
从路径加载模型。
mujoco_py.load_model_from_xml
(xml_string)
从包含 XML 标记的字符串加载并返回 PyMjModel 模型。将用于在模型中创建返回的模型的 XML 字符串.xml。
mujoco_py.load_model_from_mjb
(路径)
从编码的 MJB 字节加载并返回 PyMjModel 模型。MJB是一种MuJoCo自定义格式,包括网格/纹理等资源。
类mujoco_py.MjSim
(model, data=None, nsubsteps=1, udd_callback=None)
MjSim 表示一个正在运行的模拟,包括其状态。
与 Gym的 MujocoEnv
类似,它在内部包装了一个PyMjModel
和一个 PyMjData
。
参数: 型号 :PyMjModel
要模拟的模型。
数据 :PyMjData
模拟状态的可选容器。如果出现以下情况,将创建
.None
nsubsteps : int
每次调用 step()
时要运行的 MuJoCo 步骤的可选数量。缓冲区每步只能交换一次。
udd_callback : fn(MjSim
) -> dict
用户定义动态的可选回调。 在每次调用 step() 时,它都会在 sim.udd_state 中接收一个包含当 前用户定义的动态状态的 MjSim 对象 sim,并在应用用户定义的动态后返回下一个 udd_state。 这很有用,例如 对于在历史状态函数上运行的奖励函数。
属性
方法
get_state
()
返回模拟器状态的副本。
render
()
从摄像机渲染视图,并将图像作为 numpy.ndarray 返回。
Args: - width (int): 所需的图像宽度。- 高度(整型):所需的图像高度。- camera_name(str):模型中相机的名称。如果无,则免费将使用相机。
深度(布尔):如果为 True,则返回深度缓冲区返回:- rgb(uint8 数组):来自相机的图像缓冲区 - 深度(浮点数组):来自相机的深度缓冲区(仅返回)如果深度 = 真)
reset
()
重置仿真数据并清除缓冲区。
save
()
将模拟器模型和状态作为 MuJoCo XML 或 MJB 文件保存到文件中。当前状态将另存为模型文件中的关键帧。这对于使用 MuJoCo 的模拟实用程序进行调试非常有用。
请注意,这不会保存作为 MjSimState 一部分的 UDD 状态,因为 MuJoCo 本身不支持该状态。如果要将模型与UDD状态一起保存,则应在MjModel上使用get_xml或get_mjb方法以及MjSim.get_state,并使用例如pickle保存它们。
参数:- 文件(IO 流):要将模型写入的流。- 格式:要使用的格式(“xml”或“mjb”) - keep_inertials(bool):如果为False,则删除所有<惯性>由 MuJoco 自动派生的 geoms 属性。请注意,这也会删除用户提供的那些。
set_state
()
从 MjSimState 设置状态。如果 MjSimState 以前是从 numpy 数组中解压的,请考虑set_state_from_flattened,因为防御性副本是内部循环中的大量开销。
Args: - value (MjSimState): 所需的状态。- call_forward:可选择调用 sim.forward()。在以下情况下默认调用:
设置udd_callback。
set_state_from_flattened
()
此帮助器方法从数组设置状态,而无需防御性副本。
step
()
通过调用mj_step
来推进模拟。
如果 qpos
或qvel
被直接修改,则如果用户udd_callback
需要访问在转发动态期间设置的 MuJoCo 状态,则需要在 step()
之前调用 forward()。
类mujoco_py.MjSimState
表示模拟器状态的快照。
这包括时间,qpos,qvel,act和udd_state。
属性
方法
mujoco_py.ignore_mujoco_warnings
()[来源]
用于在某个范围内关闭 mujoco 警告异常的类。适用于大型矢量化部署。
PyMjData
相关类是从 MuJoCo C 头文件自动生成的。有关此过程的详细信息,请参阅自动生成的包装器。因此,它们的结构直接遵循MuJoCo结构。
类mujoco_py.PyMjData
属性act
act_dot
active_contacts_efc_pos
actuator_force
actuator_length
actuator_moment
actuator_velocity
body_jacp
body_jacr
body_xmat
body_xpos
body_xquat
body_xvelp
body_xvelr
cacc
cam_xmat
cam_xpos
cdof
cdof_dot
cfrc_ext
cfrc_int
cinert
contact
crb
ctrl
cvel
efc_AR
efc_AR_colind
efc_AR_rowadr
efc_AR_rownnz
efc_D
efc_J
efc_JT
efc_JT_colind
efc_JT_rowadr
efc_JT_rownnz
efc_J_colind
efc_J_rowadr
efc_J_rownnz
efc_R
efc_aref
efc_b
efc_diagApprox
efc_force
efc_frictionloss
efc_id
efc_margin
efc_solimp
efc_solref
efc_state
efc_type
efc_vel
energy
geom_jacp
geom_jacr
geom_xmat
geom_xpos
geom_xvelp
geom_xvelr
light_xdir
light_xpos
maxuse_con
maxuse_efc
maxuse_stack
mocap_pos
mocap_quat
nbuffer
ncon
ne
nefc
nf
nstack
pstack
qLD
qLDiagInv
qLDiagSqrtInv
qM
qacc
qacc_unc
qacc_warmstart
qfrc_actuator
qfrc_applied
qfrc_bias
qfrc_constraint
qfrc_inverse
qfrc_passive
qfrc_unc
qpos
qvel
sensordata
set_joint_qpos
set_joint_qvel
set_mocap_pos
set_mocap_quat
site_jacp
site_jacr
site_xmat
site_xpos
site_xvelp
site_xvelr
solver
solver_fwdinv
solver_iter
solver_nnz
subtree_angmom
subtree_com
subtree_linvel
ten_length
ten_moment
ten_velocity
ten_wrapadr
ten_wrapnum
time
timer
userdata
warning
wrap_obj
wrap_xpos
xanchor
xaxis
xfrc_applied
ximat
xipos
方法
get_body_jacp
(name)
获取与给定名称的主体对应的 jacp 中的条目
get_body_jacr
(name)
获取与给定名称的主体对应的 jacr 中的条目
get_body_ximat
(name)
获取与给定名称的主体对应的 ximat 中的条目
get_body_xipos
(name)
获取与给定名称的主体对应的 xipos 中的条目
get_body_xmat
(name)
获取与给定名称的主体对应的 xmat 中的条目
get_body_xpos
(name)
获取与给定名称的主体对应的 xpos 中的条目
get_body_xquat
(name)
获取与给定名称的主体对应的 xquat 中的条目
get_body_xvelp
(name)
获取与给定名称的主体对应的 xvelp 中的条目
get_body_xvelr
(name)
获取与给定名称的主体对应的 xvelr 中的条目
get_cam_xmat
(name)
获取 xmat 中与给定名称的 cam 对应的条目
get_cam_xpos
(name)
获取 xpos 中与给定名称的 cam 对应的条目
get_camera_xmat
(name)
获取xmat中与给定名称的相机对应的条目
get_camera_xpos
(name)
获取xpos中与给定名称的相机对应的条目
get_geom_jacp
(name)
获取与给定名称的geom对应的jacp中的条目
get_geom_jacr
(name)
获取与给定名称的geom对应的jacr中的条目
get_geom_xmat
(name)
获取与给定名称的geom对应的xmat中的条目
get_geom_xpos
(name)
获取与给定名称的geom对应的xpos中的条目
get_geom_xvelp
(name)
获取与给定名称的geom对应的xvelp中的条目
get_geom_xvelr
(name)
获取与给定名称的geom对应的xvelr中的条目
get_joint_qpos
(name)
获取与给定名称的关节对应的 qpos 中的条目
get_joint_qvel
(name)
获取与给定名称的关节对应的 qvel 中的条目
get_joint_xanchor
(name)
获取与给定名称的关节对应的 xanchor 条目
get_joint_xaxis
(name)
获取与给定名称的关节对应的 xaxis 条目
get_light_xdir
(name)
获取与给定名称的灯光对应的 xdir 中的条目
get_light_xpos
(name)
获取与给定名称的灯对应的 xpos 中的条目
get_mocap_pos
(name)
获取与给定名称的mocap对应的pos中的条目
get_mocap_quat
(name)
获取与给定名称的动作捕捉对应的 quat 条目
get_site_jacp
(name)
获取与给定名称的站点对应的 jacp 中的条目
get_site_jacr
(name)
获取与给定名称的站点对应的 jacr 中的条目
get_site_xmat
(name)
获取与给定名称的站点对应的 xmat 中的条目
get_site_xpos
(name)
获取与给定名称的站点对应的 xpos 中的条目
get_site_xvelp
(name)
获取与给定名称的站点对应的 xvelp 中的条目
get_site_xvelr
(name)
获取与给定名称的站点对应的 xvelr 中的条目
classmujoco_py.MjSimPool
保留多个 MjSim 的池,并允许并行快速步进它们。
参数: sim : MjSim
列表组成池的模拟器列表。
nsubsteps:
要在 step()
上运行的子步骤数。各个模拟器的nsubstep
将被忽略。
属性
方法
staticcreate_from_sim
()
通过克隆提供sim
的nsims
总共次数来创建 MjSimPool
。返回创建的 MjSimPool
。
参数:sim : MjSim
要克隆的原型。
nsims : int
要创建的克隆数。
forward
()
并行调用所有模拟mj_forward
。如果指定 nsims
,则仅转发第一个 nsims
模拟器。
reset
()
重置池中的所有模拟。如果指定了 nsims
,则仅重置第一个 nsims
模拟器。
step
()
并行调用所有模拟,并按照创建池时的指定进行调用。
mj_step
nsubsteps
如果指定了nsims
,则仅对第一个 nsims
模拟器进行步进。
classmujoco_py.MjViewerBasic
(sim)[来源]
一个简单的显示 GUI,显示带有鼠标可移动摄像头的 MjSim
场景。
MjViewer
扩展了此类以提供更复杂的播放和交互控件。
参数:sim : MjSim
要显示的模拟器。
属性
方法
render
()[来源]
将当前模拟状态呈现到屏幕或屏幕外缓冲区。在主循环中调用它。
classmujoco_py.MjViewer
(sim)[来源]
扩展 MjViewerBasic
以添加视频录制、交互式时间和交互控件。
键绑定如下所示:
ipdb
调试器。 参数:sim : MjSim
要显示的模拟器。
属性
方法
render
()[来源]
将当前模拟状态呈现到屏幕或屏幕外缓冲区。在主循环中调用它。
mujoco-py
高级功能的示例:body_interaction.py
: 显示碰撞体之间的相互作用#!/usr/bin/env python3
"""
身体如何相互作用的例子。 为了身体能够移动它需要有关节。 在这个例子中,“机器人”是一个红球
带有 X 和 Y 滑动接头(以及不受控制的 Z 滑动接头)。
在地板上,有一个带有 X 和 Y 滑动接头的圆柱体,所以它可以被机器人推来推去。 还有一个没有接头的盒子。 由于
盒子没有关节,是固定的,不能推来推去。
"""
from mujoco_py import load_model_from_xml, MjSim, MjViewer
import math
import os
MODEL_XML = """
<?xml version="1.0" ?>
<mujoco>
<option timestep="0.005" />
<worldbody>
<body name="robot" pos="0 0 1.2">
<joint axis="1 0 0" damping="0.1" name="slide0" pos="0 0 0" type="slide"/>
<joint axis="0 1 0" damping="0.1" name="slide1" pos="0 0 0" type="slide"/>
<joint axis="0 0 1" damping="1" name="slide2" pos="0 0 0" type="slide"/>
<geom mass="1.0" pos="0 0 0" rgba="1 0 0 1" size="0.15" type="sphere"/>
<camera euler="0 0 0" fovy="40" name="rgb" pos="0 0 2.5"></camera>
</body>
<body mocap="true" name="mocap" pos="0.5 0.5 0.5">
<geom conaffinity="0" contype="0" pos="0 0 0" rgba="1.0 1.0 1.0 0.5" size="0.1 0.1 0.1" type="box"></geom>
<geom conaffinity="0" contype="0" pos="0 0 0" rgba="1.0 1.0 1.0 0.5" size="0.2 0.2 0.05" type="box"></geom>
</body>
<body name="cylinder" pos="0.1 0.1 0.2">
<geom mass="1" size="0.15 0.15" type="cylinder"/>
<joint axis="1 0 0" name="cylinder:slidex" type="slide"/>
<joint axis="0 1 0" name="cylinder:slidey" type="slide"/>
</body>
<body name="box" pos="-0.8 0 0.2">
<geom mass="0.1" size="0.15 0.15 0.15" type="box"/>
</body>
<body name="floor" pos="0 0 0.025">
<geom condim="3" size="1.0 1.0 0.02" rgba="0 1 0 1" type="box"/>
</body>
</worldbody>
<actuator>
<motor gear="2000.0" joint="slide0"/>
<motor gear="2000.0" joint="slide1"/>
</actuator>
</mujoco>
"""
model = load_model_from_xml(MODEL_XML) # 从包含 XML标记的字符串加载并返回 PyMjModel模型。
sim = MjSim(model) # MjSim 表示一个正在运行的模拟,包括其状态。
viewer = MjViewer(sim) # 要显示的模拟器。
t = 0
while True:
sim.data.ctrl[0] = math.cos(t / 10.) * 0.01
sim.data.ctrl[1] = math.sin(t / 10.) * 0.01
t += 1
sim.step() # 通过调用`mj_step`来推进仿真。
viewer.render() # 从摄像机渲染视图,并将图像作为 numpy.ndarray 返回。
if t > 100 and os.getenv('TESTING') is not None:
break
# getenv():获取环境变量,如果不存在则返回None。
disco_fetch.py
: 展示了如何使用 TextureModder
来随机化对象纹理#!/usr/bin/env python3
"""
Displays robot fetch at a disco party.
显示disco派对上的机器人取物。
"""
from mujoco_py import load_model_from_path, MjSim, MjViewer
from mujoco_py.modder import TextureModder
import os
model = load_model_from_path("xmls/fetch/main.xml")
sim = MjSim(model)
viewer = MjViewer(sim)
modder = TextureModder(sim) # TextureModder用来随机化对象纹理
t = 0
while True:
for name in sim.model.geom_names:
modder.rand_all(name)
# modder.py : 创建MuJoCo模拟后更改纹理和材料的实用程序,允许超快速的场景生成。
# rand_all(name):随机生成许多东西。
viewer.render() # 从摄像机渲染视图,并将图像作为 numpy.ndarray 返回。
t += 1 # 仿真的时间步
if t > 100 and os.getenv('TESTING') is not None:
break
internal_functions.py
: 显示如何调用原始 mujoco 函数,如 mjv_room2model
#!/usr/bin/env python3
"""
展示如何从 MuJoCo 访问内部函数。
"""
from mujoco_py import load_model_from_xml, MjSim, functions
import numpy as np
MODEL_XML = """
<?xml version="1.0" ?>
<mujoco>
<option timestep="0.005" />
<worldbody>
<body name="robot" pos="0 0 1.2">
<joint axis="1 0 0" damping="0.1" name="robot:slide0" pos="0 0 0" type="slide"/>
<geom mass="1.0" pos="0 0 0" rgba="1 0 0 1" size="0.15" type="sphere"/>
</body>
</worldbody>
</mujoco>
"""
model = load_model_from_xml(MODEL_XML)
sim = MjSim(model)
print("Nicely exposed function:\n") # 很好暴露的功能
print(sim.model.get_xml())
print("\nversus MuJoCo internals:\n\n") #
functions.mj_saveLastXML("/tmp/saved.xml", model, "", 0)
with open("/tmp/saved.xml", "r") as f:
print(f.read())
sim.render(100, 100)
modelpos = np.zeros(3)
modelquat = np.zeros(4)
roompos = np.ones(3)
roomquat = np.array([1., 0., 1., 0.])
functions.mjv_room2model(modelpos, modelquat, roompos,
roomquat, sim.render_contexts[0].scn)
print("\n\nAnother internal function, mjv_room2model:")
print("modelpos = %s, modelquat = %s" % (str(modelpos), str(modelquat)))
res = np.zeros(9)
functions.mju_quat2Mat(res, roomquat)
print("\n\nAnother internal function, mju_quat2Mat:\n%s" % res)
markers_demo.py
: 显示如何将仅可视化的几何图形添加到查看器#!/usr/bin/env python
# demonstration of markers (visual-only geoms)
import math
import time
import os
import numpy as np
from mujoco_py import load_model_from_xml, MjSim, MjViewer
MODEL_XML = """
<?xml version="1.0" ?>
<mujoco>
<worldbody>
<body name="box" pos="0 0 0.2">
<geom size="0.15 0.15 0.15" type="box"/>
<joint axis="1 0 0" name="box:x" type="slide"/>
<joint axis="0 1 0" name="box:y" type="slide"/>
</body>
<body name="floor" pos="0 0 0.025">
<geom size="1.0 1.0 0.02" rgba="0 1 0 1" type="box"/>
</body>
</worldbody>
</mujoco>
"""
model = load_model_from_xml(MODEL_XML)
sim = MjSim(model)
viewer = MjViewer(sim)
step = 0 # 运行多少时间步
while True:
t = time.time() # 开始运行时间
x, y = math.cos(t), math.sin(t)
viewer.add_marker(pos=np.array([x, y, 1]),
label=str(t))
viewer.render()
step += 1
if step > 100 and os.getenv('TESTING') is not None:
break
serialize_model.py
: 显示如何保存和恢复模型"""
有时通过网络发送 mujoco 模型或将其保存到嵌入了所有资产的文件中很有用。
显示如何保存和恢复模型
"""
import mujoco_py
# The binary MJB format is preferable, since it includes assets like
# textures and meshes.二进制 MJB 格式是可取的,因为它包括资产,例如纹理和网格。
model = mujoco_py.load_model_from_path("xmls/claw.xml")
mjb_bytestring = model.get_mjb()
model_from_binary = mujoco_py.load_model_from_mjb(mjb_bytestring)
assert model.nbody == model_from_binary.nbody
# XML is preferable to MJB when readability and backward compatibility are
# important.当可读性和向后兼容性很重要时,XML 比 MJB 更可取。
xml_string = model.get_xml()
model_from_xml = mujoco_py.load_model_from_xml(xml_string)
assert model.nbody == model_from_xml.nbody
setting_state.py
: 显示如何将模拟重置为给定状态#!/usr/bin/env python3
"""
如何在执行期间修改 MuJoCo qpos 的示例。
"""
import os
from mujoco_py import load_model_from_xml, MjSim, MjViewer
MODEL_XML = """
<?xml version="1.0" ?>
<mujoco>
<worldbody>
<body name="box" pos="0 0 0.2">
<geom size="0.15 0.15 0.15" type="box"/>
<joint axis="1 0 0" name="box:x" type="slide"/>
<joint axis="0 1 0" name="box:y" type="slide"/>
</body>
<body name="floor" pos="0 0 0.025">
<geom size="1.0 1.0 0.02" rgba="0 1 0 1" type="box"/>
</body>
</worldbody>
</mujoco>
"""
def print_box_xpos(sim):
print("box xpos:", sim.data.get_body_xpos("box"))
model = load_model_from_xml(MODEL_XML)
sim = MjSim(model)
viewer = MjViewer(sim)
states = [{'box:x': +0.8, 'box:y': +0.8},# 状态
{'box:x': -0.8, 'box:y': +0.8},
{'box:x': -0.8, 'box:y': -0.8},
{'box:x': +0.8, 'box:y': -0.8},
{'box:x': +0.0, 'box:y': +0.0}]
# MjModel.joint_name2id returns the index of a joint in
# MjData.qpos.
x_joint_i = sim.model.get_joint_qpos_addr("box:x") # 获取关节位置地址
y_joint_i = sim.model.get_joint_qpos_addr("box:y")
print_box_xpos(sim) # 打印位置
while True:
for state in states: # 状态
sim_state = sim.get_state() # 返回模拟器状态
sim_state.qpos[x_joint_i] = state["box:x"] # x_joint_i位置
sim_state.qpos[y_joint_i] = state["box:y"] # y_joint_i位置
sim.set_state(sim_state) #设置状态
sim.forward() # 向前推进仿真
print("updated state to", state) # 更新状态到
print_box_xpos(sim) # 打印盒子的位置
viewer.render() # 可视化
if os.getenv('TESTING') is not None:
break
tosser.py
: 展示了一个简单的驱动物体分拣机器人应用程序#!/usr/bin/env python3
"""
展示如何将胶囊扔到容器中。
"""
from mujoco_py import load_model_from_path, MjSim, MjViewer
import os
model = load_model_from_path("xmls/tosser.xml")
sim = MjSim(model)
viewer = MjViewer(sim)
sim_state = sim.get_state()
while True:
sim.set_state(sim_state)
for i in range(1000):
if i < 150:
sim.data.ctrl[:] = 0.0
else:
sim.data.ctrl[:] = -1.0
sim.step()
viewer.render()
if os.getenv('TESTING') is not None:
break
有关高级用法,请参阅 完整文档。