链接
2021年10月18日DeepMind收购并开源了MuJoCo软件(之前都是收费的,最早由Roboti LLC开发),MuJoCo:Multi-Joint dynamics with Contact
MuJoCo是一个带有C API的C/C库,面向研究人员和开发人员。运行时模拟模块被调优为最大限度地提高性能,并对由内置XML解析器和编译器预先分配的低级数据结构进行操作。用户使用原生的MJCF场景描述语言定义模型–这是一种设计为尽可能具有人类可读性和可编辑性的XML文件格式。也可以加载URDF模型文件。该库包括带有原生GUI的交互式可视化,在OpenGL中渲染。MuJoCo进一步公开了大量用于计算与物理相关的量的效用函数。
MuJoCo可用于实现基于模型的计算,如控制综合、状态估计、系统辨识、机构设计、通过逆动力学进行数据分析,以及用于机器学习应用的并行采样。它还可以用作更传统的模拟器,包括游戏和交互式虚拟环境。
void mj_step(const mjModel*m,mjData*d);
交互式仿真和可视化
本机3D可视化工具提供网格和几何图元、纹理、反射、阴影、雾、透明度、线框、天框、立体可视化(在支持四缓冲OpenGL的视频卡上)的渲染。此功能用于生成3D渲染,帮助用户深入了解物理仿真,包括可视化辅助工具,例如自动生成的模型骨架、等效惯性框、接触位置和法线、可分为法向和切向分量的接触力、外部扰动力、局部框架、关节和执行机构轴以及文本标签。可视化工具期望一个具有OpenGL渲染上下文的通用窗口,从而允许用户采用他们选择的GUI库。MuJoCo随附的代码样例Simulation ate.cc展示了如何使用GLFW库实现这一点。一个相关的可用性特性是能够“接触”模拟,推动对象,并查看物理响应。用户选择将施加外力和扭矩的物体,并查看扰动及其动态结果的实时渲染。这可用于直观地调试模型、测试反馈控制器的响应或将模型配置为所需的姿势。
强大而直观的建模语言
独创的MJCF建模语言(类似于URDF,都是XML格式文件),但是可阅读性更强。
复合柔性对象的自动生成等等
在MuJoCo中有几个被称为“模型”的实体。用户在用MJCF或URDF编写的XML文件中定义模型。然后,该软件可以在不同的介质(文件或内存)和不同的描述级别(高或低)上创建同一模型的多个实例。所有组合都有可能,如下表所示:
- | High level | Low level |
---|---|---|
File | MJCF/URDF(XML) | MJB(binary) |
Memory | mjCModel(C++ class) | mjModel(C struct) |
所有运行时计算都是使用mjModel执行的,mjModel太复杂了,无法手动创建。这就是为什么我们有两个层次的建模。高层的存在是为了方便用户:其唯一目的是将其编译成可在其上执行计算的低级模型。生成的mjModel可以加载并保存到二进制文件(MJB)中,但是这些文件是特定于版本的,不能反编译,因此应该始终将模型作为XML文件进行维护。(低级的存在是为了能让计算机识别并直接运行,类似于C/C++语言的链接和编译器,把.c/.cpp代码链接编译成二进制代码.o从而可以直接用计算机运行的。
(内部)C++类mjCModel与MJCF文件格式大致一一对应。XML解析器解释MJCF或URDF文件并创建相应的mjCModel。原则上,用户可以通过编程方式创建mjCModel,然后将其保存到MJCF或编译。但是,该功能尚未公开,因为C++ API不能从独立于编译器的库导出。有一个围绕它开发C包装器的计划,但目前解析器和编译器总是一起调用,并且只能用XML创建模型。(后期可能会使用C++类来开发模型,但是现在还没有实现)
获取mjModel的路径一般如下(3种方法):
下面是MuJoCo的MJCF格式的一个简单模型。它定义了固定到世界的平面、更好地照亮对象和投射阴影的灯光,以及具有6个自由度的浮动长方体(这就是“自由”关节的作用)。
helloj.xml
<mujoco>
<worldbody>
<light diffuse=".5 .5 .5" pos="0 0 3" dir="0 0 -1"/>
<geom type="plane" size="1 1 0.1" rgba=".9 0 0 1"/>
<body pos="0 0 1">
<joint type="free"/>
<geom type="box" size=".1 .2 .3" rgba="0 .9 0 1"/>
body>
worldbody>
mujoco>
如果对这个模型进行模拟,盒子就会掉到地上。下面给出了没有渲染被动动力学的基本仿真代码。
hello.c
#include "mujoco.h"
#include "stdio.h"
char error[1000];
mjModel* m;
mjData* d;
int main(void)
{
// load model from file and check for errors
m = mj_loadXML("hello.xml", NULL, error, 1000);
if( !m )
{
printf("%s\n", error);
return 1;
}
// make data corresponding to model
d = mj_makeData(m);
// run simulation for 10 seconds
while( d->time<10 )
mj_step(m, d);
// free model and data
mj_deleteData(d);
mj_deleteModel(m);
return 0;
}
从技术上讲,这是一个C文件,但它也是一个合法的C++文件。事实上,MuJoCo API与C和C++都兼容。通常情况下,用户代码将用C++语言编写,因为它增加了方便性,并且不会因为计算瓶颈在已经高度优化的模拟器中而牺牲效率。
函数mj_step是将模拟状态推进一个时间步长的顶层函数。当然,这个例子只是一个被动动力系统。当用户指定控制或施加力并开始与系统交互时,事情会变得更加有趣。
接下来,我们提供一个更详细的示例,说明MJCF的几个特性。
example.xml
<mujoco model="example">
<compiler coordinate="global"/>
<default>
<geom rgba=".8 .6 .4 1"/>
default>
<asset>
<texture type="skybox" builtin="gradient" rgb1="1 1 1" rgb2=".6 .8 1"
width="256" height="256"/>
asset>
<worldbody>
<light pos="0 1 1" dir="0 -1 -1" diffuse="1 1 1"/>
<body>
<geom type="capsule" fromto="0 0 1 0 0 0.6" size="0.06"/>
<joint type="ball" pos="0 0 1"/>
<body>
<geom type="capsule" fromto="0 0 0.6 0.3 0 0.6" size="0.04"/>
<joint type="hinge" pos="0 0 0.6" axis="0 1 0"/>
<joint type="hinge" pos="0 0 0.6" axis="1 0 0"/>
<body>
<geom type="ellipsoid" pos="0.4 0 0.6" size="0.1 0.08 0.02"/>
<site name="end1" pos="0.5 0 0.6" type="sphere" size="0.01"/>
<joint type="hinge" pos="0.3 0 0.6" axis="0 1 0"/>
<joint type="hinge" pos="0.3 0 0.6" axis="0 0 1"/>
body>
body>
body>
<body>
<geom type="cylinder" fromto="0.5 0 0.2 0.5 0 0" size="0.07"/>
<site name="end2" pos="0.5 0 0.2" type="sphere" size="0.01"/>
<joint type="free"/>
body>
worldbody>
<tendon>
<spatial limited="true" range="0 0.6" width="0.005">
<site site="end1"/>
<site site="end2"/>
spatial>
tendon>
mujoco>
这个模型是一个7自由度的手臂,“握住”一根绳子,另一端系着一个圆柱体。绳子被实现为有长度限制的肌腱。肩部有球状关节,肘部和手腕有一对铰链关节。气缸内的盒子表示一个自由的“接头”。XML中的外层Body元素是必需的WorldBody。请注意,在两个实体之间使用多个关节不需要创建虚拟实体。
MJCF文件包含指定模型所需的最少信息。胶囊是由空间中的线段定义的-在这种情况下,只需要胶囊的半径。车身骨架的位置和方向是从它们所属的几何图形推断出来的。惯性特性是在均匀密度假设下从几何形状中推断出来的。之所以命名这两个位置,是因为腱定义需要引用它们,但没有命名其他位置。仅为铰链关节定义关节轴,而不为球关节定义关节轴。碰撞规则是自动定义的。摩擦属性、重力、模拟时间步长等设置为其默认值。顶部指定的默认几何图形颜色适用于所有几何图形。
除了将编译后的模型保存为二进制MJB格式外,我们还可以将其保存为MJCF或人类可读的文本;请分别参阅examplesave.xml和exampleaved.txt。XML版本与原始版本类似,而文本版本包含来自mjModel的所有信息。将文本版本与XML版本进行比较,可以看出模型编译器为我们做了多少工作。
本节简要描述了MuJoCo模型中可以包含的所有元素。稍后,我们将更详细地解释底层计算、在MJCF中元素的特定表现方式以及它们在mjModel中的表示。
每种模型都有下面列出的三组选项。他们总是被包括在内。如果未在XML文件中指定它们的值,则使用默认值。这些选项的设计使得用户可以在每个模拟时间步长之前更改它们的值。但是,在时间步长内,所有选项都不应更改。
mjOption:此结构包含影响物理模拟的所有选项。它用于选择算法并设置其参数,启用和禁用模拟管道的不同部分,以及调整系统级物理属性(如重力,模拟失重的环境,或者物体浮力和重力平衡的环境)。
mjVisual:此结构包含所有可视化选项。还有其他OpenGL渲染选项,但这些选项与会话相关,不是模型的一部分。
mjStatistic:此结构包含由编译器计算的有关模型的统计信息:平均体重、模型的空间范围等。包含该结构是为了提供信息,还因为可视化工具将其用于自动缩放。
资产本身并不是模型元素。模型图元可以参照它们,在这种情况下,资源会以某种方式修改参照图元的属性。一个资源可以被多个模型元素引用。由于包含资产的唯一目的是引用它,并且只能按名称进行引用,因此每个资产都有一个名称(如果适用,可以从文件名推断出名称)。相反,常规元素的名称可以保留为未定义。
MuJoCo模拟运动通常受约束的刚体集合的动力学。系统状态以关节坐标表示,实体被显式组织到运动学树中。除了顶级的“WORLD”实体之外,每个实体都有一个唯一的父实体。不允许使用运动学回路;如果需要回路运动类型,则应使用相等约束对其进行建模。因此,MuJoCo模型的主干是由嵌套实体定义形成的一个或多个运动学树;孤立的浮体算作一棵树。下面列出的其他几个元素在主体中定义,并属于该主体。这与后面列出的不能与单个实体关联的独立元素形成对比。
在这里,我们描述了不属于单个实体的模型元素,因此在运动学树之外进行了描述。
读者可能有其他物理模拟器和相关约定的经验,以及与MuJoCo不一致的一般编程实践。这有可能造成混乱。本节的目标是先发制人地澄清最容易混淆的方面;它介于常见问题解答和有关选定主题的教程之间。我们将需要参考文档后面介绍的材料,但是下面的文本尽可能自成体系,具有介绍性。