编程#

简介#

本章是 MuJoCo 编程指南。另一独立章节包含 API 参考 文档。MuJoCo 是一个与 Windows、Linux 和 macOS 兼容的动态库,需要处理器支持 AVX 指令。该库通过一个与编译器无关的共享内存 C API 暴露了模拟器的全部功能。它也可以在 C++ 程序中使用。

MuJoCo 代码库根据不同的主要功能领域组织在不同的子目录中

引擎

模拟器(或物理引擎)是用 C 语言编写的。它负责所有运行时计算。

解析器

XML 解析器是用 C++ 编写的。它可以解析 MJCF 模型和 URDF 模型,将它们转换为内部的 mjCModel C++ 对象,该对象通过 mjSpec 暴露给用户。

编译器

编译器是用 C++ 编写的。它接收由解析器构建的 mjCModel C++ 对象,并将其转换为运行时使用的 mjModel C 结构体。

抽象可视化器

抽象可视化器是用 C 语言编写的。它生成一个表示模拟状态的抽象几何实体列表,其中包含实际渲染所需的所有信息。它还提供用于相机和扰动控制的抽象鼠标挂钩。

OpenGL 渲染器

该渲染器是用 C 语言编写的,基于固定功能 OpenGL。它不具备最先进渲染引擎的所有功能(如果需要,可以用这样的引擎替换),但它提供了高效且信息丰富的 3D 渲染。

线程

线程框架(MuJoCo 3.0 中的新功能)是用 C++ 编写并通过 C 语言暴露。它提供了一个 ThreadPool 接口来异步处理任务。要在 MuJoCo 中启用它,请创建一个 ThreadPool 并将其分配给 mjData 中的 thread_pool 字段。

UI 框架

UI 框架是用 C 语言编写的。UI 元素在 OpenGL 中渲染。它有自己的事件机制以及用于键盘和鼠标输入的抽象挂钩。代码示例中它与 GLFW 一起使用,但它也可以与其他窗口库一起使用。

入门#

MuJoCo 是一个开源项目。我们为运行 Windows、Linux 和 macOS 的 x86_64 和 arm64 机器提供了预构建的动态库。这些库可以从 GitHub 发布页面下载。我们鼓励不打算开发或修改 MuJoCo 核心代码的用户使用我们的预构建库,因为这些库与我们定期测试的依赖项版本捆绑在一起,并且受益于为性能而优化的构建标志。我们的预构建库几乎完全自包含,除了标准的 C 运行时之外,不需要任何其他库存在。我们还隐藏了除构成 MuJoCo 公共 API 之外的所有符号,从而确保它可以与任何可能加载到进程中的其他库(包括 MuJoCo 依赖库的其他版本)共存。

预构建的发行版在 Windows 上是一个单独的 .zip 文件,在 macOS 上是 .dmg 文件,在 Linux 上是 .tar.gz 文件。没有安装程序。在 Windows 和 Linux 上,只需将存档解压到您选择的目录中。从 bin 子目录,您现在可以运行预编译的代码示例,例如

Windows:           simulate ..\model\humanoid\humanoid.xml
Linux and macOS:   ./simulate ../model/humanoid/humanoid.xml

目录结构如下所示。用户可以根据需要重新组织它,也可以将动态库安装在其他目录中并相应地设置路径。唯一自动创建的文件是可执行文件目录中的 MUJOCO_LOG.TXT;它包含错误和警告消息,可以随时删除。

bin     - dynamic libraries, executables, MUJOCO_LOG.TXT
doc     - README.txt and REFERENCE.txt
include - header files needed to develop with MuJoCo
model   - model collection
sample  - code samples and CMakeLists.txt needed to build them

在验证模拟器可以工作后,您可能还想重新编译代码示例,以确保您有一个可用的开发环境。我们提供了一个跨平台的 CMake 设置,可用于独立于 MuJoCo 库本身来构建示例应用程序。

在 macOS 上,DMG 磁盘映像包含 MuJoCo.app,您可以双击它来启动 simulate GUI。您也可以将 MuJoCo.app 拖到系统上的 /Application 目录中,就像安装任何其他应用程序一样。除了 MuJoCo.app 应用程序包之外,DMG 还包括 mujoco.framework 子目录,其中包含 MuJoCo 动态库及其所有公共头文件。如果您使用 Xcode,可以将其作为框架依赖项导入到您的项目中。(这也适用于 Swift 项目,无需任何修改)。如果您是手动构建,可以使用 -F-framework mujoco 分别指定头文件搜索路径和库搜索路径。

从源代码构建#

要从源代码构建 MuJoCo,您需要安装 CMake 和一个可用的 C++17 编译器。步骤如下

  1. 克隆 mujoco 仓库:git clone https://github.com/deepmind/mujoco.git

  2. 创建一个新的构建目录并 cd 进入它。

  3. 运行 cmake $PATH_TO_CLONED_REPO 来配置构建。

  4. 运行 cmake --build . 来进行构建。

MuJoCo 的构建系统使用 CMake 的 FetchContent 模块自动从上游仓库通过互联网获取依赖项。

主要的 CMake 设置将构建 MuJoCo 库本身以及所有示例应用程序,但不会构建 Python 绑定。这些绑定有自己的构建说明,可以在文档的 Python 部分找到。

此外,CMake 设置还实现了一个安装阶段,它将复制并组织输出文件到目标目录。

  1. 选择目录:cmake $PATH_TO_CLONED_REPO -DCMAKE_INSTALL_PREFIX=<my_install_dir>

  2. 构建后,使用 cmake --install .进行安装

  3. 如果需要,继续构建 Python 绑定 - 参见 从源代码构建

注释

  • 在 Windows 上构建时,请使用 Visual Studio 2019 或更高版本,并确保已安装 Windows SDK 版本 10.0.22000 或更高版本(更多详情请参见 #862)。

  • 要优化运行时性能,请使用 -DCMAKE_BUILD_TYPE=Release 进行构建。

提示

作为参考,一个可用的构建配置可以在 MuJoCo 的 GitHub 持续集成设置中找到。

构建文档#

如果您希望在本地构建文档,例如为了测试改进文档的拉取请求,请执行以下操作

  1. 克隆 mujoco 仓库:git clone https://github.com/deepmind/mujoco.git

  2. 进入 doc/ 目录:cd mujoco/doc

  3. 安装依赖项:pip install -r requirements.txt
    请注意,MuJoCo Warp API 文档是自动生成的,需要额外的依赖项。详情请参见 .readthedocs.yml

  4. 构建 HTML:make html

  5. 在您选择的浏览器中打开 _build/html/index.html

头文件#

发行版包含几个在所有平台上都相同的头文件。为了使本文档自包含,也可以通过以下链接获得它们。

mujoco.h

这是主头文件,必须包含在使用 MuJoCo 的所有程序中。它定义了所有 API 函数和全局变量,并包含了除 mjxmacro.h 之外的所有其他头文件。

mjmodel.h

定义 C 结构体 mjModel,它是被模拟模型的运行时表示。它还定义了定义 mjModel 所需的一些基本类型和其他结构体。

mjdata.h

定义 C 结构体 mjData,它是所有计算读取输入和写入输出的工作空间。它还定义了定义 mjData 所需的基本类型和其他结构体。

mjvisualize.h

定义抽象可视化器所需的基本类型和结构体。

mjrender.h

定义 OpenGL 渲染器所需的基本类型和结构体。

mjui.h

定义 UI 框架所需的基本类型和结构体。

mjtnum.h

将 MuJoCo 的 mjtNum 浮点类型定义为 doublefloat。参见 mjtNum

mjspec.h

定义用于程序化模型编辑的枚举和结构体。

mjplugin.h

定义引擎插件所需的数据结构。

mjthread.h

定义线程所需的数据结构和函数。

mjmacro.h

定义在用户代码中有用的 C 宏。

mjxmacro.h

此文件是可选的,不被 mujoco.h 包含。它定义了X 宏,可以自动将 mjModel 和 mjData 映射到脚本语言,以及其他需要访问 mjModel 和 mjData 所有字段的操作。

mjexport.h

用于从 MuJoCo 库导出公共符号的宏。客户端代码不应直接使用此头文件。

mjsan.h

使用清理器(sanitizer)插桩构建时所需的定义。

版本和兼容性#

MuJoCo 自 2010 年以来已被广泛使用,并且相当成熟(尽管我们的版本编号方案非常保守)。尽管如此,它仍在积极开发中,我们有许多关于新功能的激动人心的想法,并且也在根据用户反馈进行更改。这导致了建模语言和 API 中不可避免的变化。虽然我们鼓励用户升级到最新版本,但我们认识到这并不总是可行的,特别是当其他开发人员发布依赖于 MuJoCo 的软件时。因此,我们引入了简单的机制来帮助避免版本冲突,如下所述。

如果现有代码是使用某个特定版本的 MuJoCo 开发的,而现在正在使用不同版本进行编译和链接,情况会更微妙。如果该代码中使用的 API 函数的定义发生了变化,编译器或链接器会生成错误。但即使函数定义没有改变,断言软件版本相同仍然是一个好主意。为此,主头文件 (mujoco.h) 定义了符号 mjVERSION_HEADER,库提供了函数 mj_version。因此,可以比较头文件和库的版本

// recommended version check
if (mjVERSION_HEADER!=mj_version())
  complain();

请注意,只有主头文件定义了这个符号。我们假设每个软件版本发布的头文件集合将保持在一起,不会在不同版本之间混合。为了避免浮点比较带来的复杂性,上述符号和函数使用整数,该整数是版本号的 100 倍,例如在软件版本 2.1 中,符号 mjVERSION_HEADER 定义为 210。

命名约定#

API 中定义的所有符号都以前缀“mj”开头。“mj”之后紧跟的字符决定了该符号所属的系列。首先,我们列出对应于类型定义的前缀。

mj

核心模拟数据结构(C 结构体),例如 mjModel。如果前缀之后的所有字符都是大写的,例如 mjMIN,那么这是一个宏或符号(#define)。

mjt

基本类型,例如 mjtGeom。除了 mjtByte 和 mjtNum,该系列中的所有其他定义都是枚举。

mjf

回调函数类型,例如 mjfGeneric

mjv

与抽象可视化相关的数据结构,例如 mjvCamera

mjr

与 OpenGL 渲染相关的数据结构,例如 mjrContext

mjui

与 UI 框架相关的数据结构,例如 mjuiSection

mjs

程序化模型编辑相关的数据结构,例如 mjsJoint

接下来,我们列出对应于函数定义的前缀。请注意,函数前缀总是以下划线结尾。

mj_

核心模拟函数,例如 mj_step。几乎所有此类函数的头两个参数都是指向 mjModel 和 mjData 的指针,可能后面还有其他参数。它们通常将其输出写入 mjData。

mju_

实用函数,例如 mju_mulMatVec。这些函数是自包含的,因为它们的参数中没有 mjModel 和 mjData 指针。

mjv_

与抽象可视化相关的函数,例如 mjv_updateScene

mjr_

与 OpenGL 渲染相关的函数,例如 mjr_render

mjui_

与 UI 框架相关的函数,例如 mjui_update

mjcb_

全局回调函数指针,例如 mjcb_control。用户可以通过将这些全局指针设置为用户定义的函数来安装自定义回调。

mjd_

用于计算导数的函数,例如 mjd_transitionFD

mjs_

用于程序化模型编辑的函数,例如 mjs_addJoint

使用 OpenGL#

MuJoCo 原生 OpenGL 渲染器的使用将在 OpenGL 渲染 中解释。对于渲染,MuJoCo 使用兼容性配置文件的 OpenGL 1.5,并带有 ARB_framebuffer_objectARB_vertex_buffer_object 扩展。OpenGL 符号在首次调用 mjr_makeContext 函数时通过 GLAD 加载。这意味着 MuJoCo 库本身并不显式依赖于 OpenGL,可以在没有 OpenGL 支持的系统上使用,只要不调用 mjr_ 函数。

使用 MuJoCo 内置渲染功能的应用程序负责链接到适当的 OpenGL 上下文创建库,并确保在运行线程上有一个当前活动的 OpenGL 上下文。在 Windows 和 macOS 上,操作系统提供了标准的 OpenGL 库。在 Linux 上,MuJoCo 目前支持用于渲染到 X11 窗口的 GLX、用于无头软件渲染的 OSMesa,以及用于硬件加速无头渲染的 EGL。

在 2.1.4 版本之前,MuJoCo 使用 GLEW 而不是 GLAD 来管理 OpenGL 符号,这需要在构建时根据所使用的 GL 实现链接到不同的 GLEW 库。为了在不需要渲染时避免管理 OpenGL 依赖,“nogl” 版本的库被提供。由于在切换到 GLAD 后 OpenGL 符号现在是在运行时惰性解析的,因此不再提供 “nogl” 库。