全局变量#

全局变量和常量定义可分类为

错误回调函数#

所有用户回调函数(即,以 'mjcb' 开头的全局函数指针)最初被设置为 NULL,这会禁用它们并允许执行默认处理。要安装回调函数,只需将相应的全局指针设置为正确类型的用户函数即可。请记住,这些是全局的,不是模型特定的。因此,如果您并行仿真多个模型,它们会使用同一组回调函数。

mju_user_error#

此函数在主错误函数mju_error内部调用。安装后,此函数将覆盖默认错误处理。打印错误消息(或用户希望做的任何其他事情)后,它必须退出程序。MuJoCo 的编写假定 mju_error 不会返回。如果它返回,则软件的行为是未定义的。

extern void (*mju_user_error)(const char*);

mju_user_warning#

此函数在主警告函数mju_warning内部调用。它类似于错误处理程序,但必须在不退出程序的情况下返回。

extern void (*mju_user_warning)(const char*);

内存回调函数#

内存回调函数的目的是允许用户安装自定义的内存分配和释放机制。一个我们发现此功能有用的示例是 MuJoCo 的 MATLAB 包装器,其中 mex 文件需要使用 MATLAB 的内存机制进行永久内存分配。

mju_user_malloc#

如果安装了此函数,MuJoCo 运行时将使用它来分配所需的全部堆内存(而不是使用对齐的 malloc)。用户分配器必须分配在 8 字节边界上对齐的内存。请注意,解析器和编译器是用 C++ 编写的,有时会使用“new”运算符分配内存,这会绕过此机制。

extern void* (*mju_user_malloc)(size_t);

mju_user_free#

如果安装了此函数,MuJoCo 将通过调用此函数来释放其分配的任何堆内存(而不是使用对齐的 free)。

extern void (*mju_user_free)(void*);

物理回调函数#

物理回调函数是修改仿真器行为的主要机制,除了设置各种选项之外。选项控制默认管道的操作,而回调函数在明确定义的位置扩展管道。这使得高级用户能够实现许多我们没有想到的有趣功能,同时仍然利用默认管道。与所有其他回调函数一样,没有自动错误检查——相反,我们假定回调函数作者知道他们在做什么。

自定义物理回调函数通常需要 MJCF 中不标准的参数。这很大程度上是我们为什么在 MJCF 中提供了自定义字段和用户数据数组。其思想是通过输入必要的用户参数来“检测”MJCF 模型,然后编写寻找这些参数并执行相应计算的回调函数。我们强烈建议用户编写回调函数,在访问用户参数之前检查模型是否存在这些参数——这样当加载常规模型时,回调函数会自动禁用,而不是导致软件崩溃。

mjcb_passive#

这用于在关节空间中实现自定义被动力;如果力在笛卡尔空间中更自然地定义,则使用末端执行器雅可比矩阵将其映射到关节空间。这里的“被动”不是指不做正功的力(如物理学中),而只是一个仅取决于位置和速度而不取决于控制的力。MuJoCo 中有由弹簧、阻尼器、介质粘度和密度产生的标准被动力。它们在调用 mjcb_passive 之前在mjData.qfrc_passive中计算。用户回调函数应向此向量添加,而不是覆盖它(否则标准被动力将丢失)。

extern mjfGeneric mjcb_passive;

mjcb_control#

这是最常用的回调函数。它通过写入控制向量mjData.ctrl来实现控制律。它也可以写入mjData.qfrc_appliedmjData.xfrc_applied。写入这些向量的值可以取决于位置、速度以及从中导出的所有其他量,但不能取决于接触力以及在指定控制后计算的其他量。如果回调函数访问后者的字段,它们的值将与当前时间步不对应。

控制回调函数在mj_forwardmj_step内部调用,恰好在需要控制和施加力之前。使用 RK 积分器时,每个步骤将调用 4 次。指定控制和施加力的另一种方法是在mj_step之前设置它们,或使用mj_step1mj_step2。后一种方法允许在mj_step1执行位置和速度计算后设置控制,从而允许在计算控制时利用这些结果(类似于使用 mjcb_control)。然而,在 RK 积分器的子步之间更改控制的唯一方法是定义控制回调函数。

extern mjfGeneric mjcb_control;

mjcb_contactfilter#

此回调函数可用于替换 MuJoCo 的默认碰撞过滤。安装后,此函数会为通过粗略阶段测试(或在 MJCF 中预定义的几何体对)并是近相碰撞候选的每对几何体调用。默认处理使用 contype 和 conaffinity 掩码、父子过滤器以及与焊接体相关的其他一些考虑因素来决定是否应允许碰撞。此回调函数替换了默认处理,但请记住整个机制正在被替换。因此,例如如果您仍然想利用 contype/conaffinity,您必须在回调函数中重新实现它。

extern mjfConFilt mjcb_contactfilter;

mjcb_sensor#

此回调函数填充与用户定义的传感器对应的mjData.sensordata字段。如果安装了此函数且模型包含用户定义的传感器,则会调用它。每个计算阶段(mjSTAGE_POS、mjSTAGE_VEL、mjSTAGE_ACC)调用一次,并且必须填充该阶段的所有用户传感器值。用户定义的传感器在 MJCF 模型中定义了维度和数据类型,回调函数必须遵守这些定义。

extern mjfSensor mjcb_sensor;

mjcb_time#

安装此回调函数可启用内置性能分析器,并将计时统计数据保存在mjData.timer中。返回类型为 mjtNum,时间单位由用户决定。simulate.cc假定单位是 1 毫秒。为了有用,回调函数应使用至少微秒级精度的高分辨率计时器。这是因为要计时的计算非常快。

extern mjfTime mjcb_time;

mjcb_act_dyn#

此回调函数实现自定义激活动力学:它必须返回指定执行器的mjData.act_dot值。这是激活状态向量mjData.act的时间导数。对于具有用户定义动力学(mjDYN_USER)的模型执行器,会调用此函数。如果模型中存在此类执行器但未安装此回调函数,则将其时间导数设置为 0。

extern mjfAct mjcb_act_dyn;

mjcb_act_gain#

此回调函数实现自定义执行器增益:它必须返回mjModel.actuator_gaintype设置为 mjGAIN_USER 的指定执行器的增益。如果模型中存在此类执行器但未安装此回调函数,则将其增益设置为 1。

extern mjfAct mjcb_act_gain;

mjcb_act_bias#

此回调函数实现自定义执行器偏置:它必须返回mjModel.actuator_biastype设置为 mjBIAS_USER 的指定执行器的偏置。如果模型中存在此类执行器但未安装此回调函数,则将其偏置设置为 0。

extern mjfAct mjcb_act_bias;

碰撞表#

mjCOLLISIONFUNC#

按几何体类型索引的成对碰撞函数表。仅使用右上三角形。用户可以用自定义例程替换这些函数指针,从而替换 MuJoCo 的碰撞机制。如果给定条目为 NULL,则相应的几何体类型对无法发生碰撞。请注意,这些函数仅适用于近相碰撞。粗略阶段机制是内置的,无法修改。

extern mjfCollision mjCOLLISIONFUNC[mjNGEOMTYPES][mjNGEOMTYPES];

字符串常量#

这里描述的字符串常量是为了方便用户提供的。它们对应于选项列表的英文名称,可以在 GUI 的菜单或对话框中显示。simulate.cc代码示例说明了如何使用它们。

mjDISABLESTRING#

mjtDisableBit定义的禁用位的名称。

extern const char* mjDISABLESTRING[mjNDISABLE];

mjENABLESTRING#

mjtEnableBit定义的启用位的名称。

extern const char* mjENABLESTRING[mjNENABLE];

mjTIMERSTRING#

mjtTimer定义的 mjData 计时器的名称。

extern const char* mjTIMERSTRING[mjNTIMER];

mjLABELSTRING#

mjtLabel定义的视觉标签模式的名称。

extern const char* mjLABELSTRING[mjNLABEL];

mjFRAMESTRING#

mjtFrame定义的帧可视化模式的名称。

extern const char* mjFRAMESTRING[mjNFRAME];

mjVISSTRING#

mjtVisFlag定义的抽象可视化标志的描述。每个标志有三个字符串,

含义如下

[0]: 标志名称;

[1]: 字符串“0”或“1”,指示标志是否默认开启或关闭,由mjv_defaultOption设置;

[2]: 包含建议的键盘快捷方式的单字符字符串,在simulate.cc中使用。

extern const char* mjVISSTRING[mjNVISFLAG][3];

mjRNDSTRING#

mjtRndFlag定义的 OpenGL 渲染标志的描述。每个标志的三个字符串格式与上述相同,除了这里的默认值由mjv_makeScene设置。

extern const char* mjRNDSTRING[mjNRNDFLAG][3];

数值常量#

许多整数常量已在上面的原始类型中说明。此外,头文件还定义了此处说明的其他几个常量。除非另有说明,下表中的每个条目都在mjmodel.h中定义。请注意,一些扩展的键码在mjui.h中定义,未在下表中显示。它们的名称格式为mjKEY_XXX。它们对应于 GLFW 键码。

符号

描述

mjMINVAL

1E-15

在任何分母中允许的最小值,以及通常在不允许为 0 的任何数学运算中允许的最小值。在几乎所有情况下,MuJoCo 会静默地将较小的值限制在 mjMINVAL。

mjPI

\(\pi\)

\(\pi\)的值。这用于各种三角函数,也用于编译器中从度到弧度的转换。

mjMAXVAL

1E+10

mjData.qpos、mjData.qvel、mjData.qacc 中允许的最大绝对值。API 函数mj_checkPosmj_checkVelmj_checkAcc使用此常量来检测不稳定性。

mjMINMU

1E-5

任何摩擦系数允许的最小值。回想一下,MuJoCo 的接触模型允许包含不同数量的摩擦维度,由condim属性指定。但是,如果包含给定的摩擦维度,则其摩擦不允许小于此常量。较小的值会自动限制在此常量。

mjMINIMP

0.0001

任何约束阻抗允许的最小值。较小的值会自动限制在此常量。

mjMAXIMP

0.9999

任何约束阻抗允许的最大值。较大的值会自动限制在此常量。

mjMAXCONPAIR

50

每对几何体可以生成的最大接触点数。MuJoCo 的内置碰撞函数遵守此限制,用户定义函数也应遵守此限制。此类函数在调用时会提供大小为mjMAXCONPAIR的返回缓冲区;尝试在缓冲区中写入更多接触可能会导致不可预测的行为。

mjMAXTREEDEPTH

50

每个刚体和网格边界体积层次结构的最大深度。如果超出此大限制,会发出警告并且可能无法进行射线投射。对于平衡的层次结构,这意味着 1E15 个边界体积。

mjNEQDATA

11

用于定义每个等式约束的最大实值参数数量。决定mjModel.eq_data的大小。此常量和接下来的五个常量对应于我们尚未完全确定的数组大小。未来可能需要增加它们,以便容纳更复杂的计算所需的额外参数。这就是为什么我们将它们维护为可以轻松更改的符号常量,而不是用于表示四元数的数组大小——后者没有理由更改。

mjNDYN

10

用于定义每个执行器的激活动力学的最大实值参数数量。决定mjModel.actuator_dynprm的大小。

mjNGAIN

10

用于定义每个执行器增益的最大实值参数数量。决定mjModel.actuator_gainprm的大小。

mjNBIAS

10

用于定义每个执行器偏置的最大实值参数数量。决定mjModel.actuator_biasprm的大小。

mjNFLUID

12

椭球模型所需的每个几何体流体交互参数的数量。

mjNREF

2

用于定义每个标量约束的参考加速度的最大实值参数数量。决定所有mjModel.XXX_solref字段的大小。

mjNIMP

5

用于定义每个标量约束阻抗的最大实值参数数量。决定所有mjModel.XXX_solimp字段的大小。

mjNSOLVER

200

可以将求解器统计数据存储在mjData.solver中的迭代次数。此数组用于存储有关约束求解器每次迭代的诊断信息。实际迭代次数由mjData.solver_iter给出。

mjNISLAND

20

可以将求解器统计数据存储在mjData.solver中的岛屿数量。此数组用于存储有关约束求解器每次迭代的诊断信息。实际运行求解器的岛屿数量由mjData.nsolver_island给出。

mjNGROUP

6

可以通过mjvOption启用和禁用其渲染的几何体、站点、关节、肌腱和执行器组的数量。在mjvisualize.h中定义。

mjMAXOVERLAY

500

渲染覆盖文本的最大字符数。在mjvisualize.h中定义。

mjMAXLINE

100

每个二维图形(mjvFigure)的最大线数。在mjvisualize.h中定义。

mjMAXLINEPNT

1000

二维图形中每条线的最大点数。请注意,mjvFigure.linepnt缓冲区长度为2*mjMAXLINEPNT,因为每个点都有 X 和 Y 坐标。在mjvisualize.h中定义。

mjMAXPLANEGRID

200

渲染平面时每个维度的最大网格线数。在mjvisualize.h中定义。

mjNAUX

10

可以在 mjrContext 中分配的辅助缓冲区数量。在mjrender.h中定义。

mjMAXTEXTURE

1000

允许的最大纹理数量。在mjrender.h中定义。

mjMAXTHREAD

128

线程池中可以使用的最大操作系统线程数。在mjthread.h中定义。

mjMAXUISECT

10

最大 UI 部分数量。在mjui.h中定义。

mjMAXUIITEM

200

每个 UI 部分的最大项目数量。在mjui.h中定义。

mjMAXUITEXT

500

UI 字段 ‘edittext’ 和 ‘other’ 中的最大字符数。在mjui.h中定义。

mjMAXUINAME

40

任何 UI 名称中的最大字符数。在mjui.h中定义。

mjMAXUIMULTI

20

UI 组中最大单选和选择项目数。在mjui.h中定义。

mjMAXUIEDIT

5

UI 编辑列表中最大元素数。在mjui.h中定义。

mjMAXUIRECT

15

最大 UI 矩形数。在mjui.h中定义。

mjVERSION_HEADER

332

MuJoCo 头文件的版本;每个发布都会更改。这是一个等于软件版本乘以 100 的整数,因此 210 对应于版本 2.1。在 mujoco.h 中定义。API 函数mj_version返回一个具有相同含义但针对已编译库的数字。

#

mjUSESINGLE#

编译时标志,参见mjtNum

mjDISABLED#

#define mjDISABLED(x) (m->opt.disableflags & (x))

检查是否通过物理选项禁用了给定的标准功能,假设已定义 mjModel* m。x 的类型为mjtDisableBit

mjENABLED#

#define mjENABLED(x) (m->opt.enableflags & (x))

检查是否通过物理选项启用了给定的可选功能,假设已定义 mjModel* m。x 的类型为mjtEnableBit

mjMAX#

#define mjMAX(a,b) (((a) > (b)) ? (a) : (b))

返回最大值。为避免使用 mjtNum 类型进行重复评估,请使用函数mju_max

mjMIN#

#define mjMIN(a,b) (((a) < (b)) ? (a) : (b))

返回最小值。为避免使用 mjtNum 类型进行重复评估,请使用函数mju_min

mjPLUGIN_LIB_INIT#

#define mjPLUGIN_LIB_INIT                                                                 \
  static void _mjplugin_dllmain(void);                                                    \
  mjEXTERNC int __stdcall mjDLLMAIN(void* hinst, unsigned long reason, void* reserved) {  \
    if (reason == 1) {                                                                    \
      _mjplugin_dllmain();                                                                \
    }                                                                                     \
    return 1;                                                                             \
  }                                                                                       \
  static void _mjplugin_dllmain(void)

将插件注册为动态库。有关详细信息,请参见插件注册

X 宏#

大多数用户项目不需要 X 宏。它们内部用于分配模型,也适用于了解如何使用此编程技术的用户。有关实际定义,请参见头文件mjxmacro.h。它们在为脚本语言编写 MuJoCo 包装器时特别有用,因为需要在程序中构建与 MuJoCo 数据结构匹配的动态结构。