一、基础术语解释
刚体(Body):仿真中的基本运动单元,具有质量、惯性、位置、姿态等属性,默认不可变形
关节(Joint):约束两个刚体相对运动的组件,通过「限制自由度」实现特定运动(如铰链关节仅允许旋转)
自由度(DOF):刚体在空间的独立运动数量(3 平移 + 3 旋转 = 6 DOF),关节本质是「减少自由度」
几何体(Geom):刚体的碰撞/可视化表征(如球、立方体、胶囊体),用于计算接触力
MJCF/URDF:模型描述文件(XML 格式),定义仿真场景的刚体、关节、约束等所有元素
世界坐标系(Worldbody):仿真世界的全局坐标系,所有刚体都直接/间接关联于此
二、建模标签介绍
建模文件格式为XML格式;
1、世界根节点
<mujoco model="模型名称"> </mujoco>2、仿真计算配置
compiler节点
<compiler angle="radian/degree" autolimits="true" >compiler节点中定义的包括angle(角度单位)/radian(弧度单位),autolimits(受力限制)等,常用的就像上面这样写就行,规定角度单位为弧度制,受力限制开启。角度单位为弧度制是机器人开发的常用单位制。
option节点
设置场景中的属性选项
<option timestep="0.002" gravity="0 0 -9.81" integrator="implicitfast" density="1.225" viscosity="1.8e-5"/>- timestep代表仿真走一步的时间,也就是运行一次之后仿真计算出timestep时长后的世界,单位秒。timestep是一定要规定的,不然仿真不知道如何计算
- gravity 重力加速度
- wind 风在三个方向的速度
- magnetic="0 -0.5 0"世界磁场,影响磁力传感器
- density 介质密度,水,空气等,单位kg/m³
- viscosity介质粘度
- integrator=[Euler/RK4/implicit/implicitfast]积分器,默认欧拉,用于仿真世界每步就求解计算,各个优势见下图,影响仿真的精度
- solver=[PGS, CG, Newton]求解器配置,默认牛顿
- iterations="100" 约束求解器最大迭代次数,按需配置。 求解器其他配置:
积分器比较:
3、可视化配置
visual节点
<visual> <global realtime="1"/> <quality shadowsize="16384" numslices="28" offsamples="4" /> <headlight diffuse="1 1 1" specular="0.5 0.5 0.5" active="1" /> <rgba fog="0 1 0 1" haze="1 0 0 1"/> </visual>- global:realtime仿真速度比例,在simulate中可以使用,大于1的按1计算
- quality:画面质量,shadowsize: 阴影效果,数值越大渲染越精细
- headlight:和simulate中自由相机相同方向的光源 ,diffuse:头灯的亮度, specular:反射的光的颜色
- map:鼠标影响操作
- scale:渲染缩放
- rgba:fog 迷雾颜色;haze 地平线颜色
4、资源配置
配置接下来场景中的资源文件
<asset> <mesh name="tetrahedron" vertex="0 0 0 1 0 0 0 1 0 0 0 1" /> <mesh file="card.obj" /> <texture type="2d" file="./king_of_clubs.png" /> <material name="king_of_clubs" texture="king_of_clubs" /> <hfield name="agent_eval_gym" file="agent_eval_gym.png" size="10 10 1 1" /> <texture type="skybox" file="../asset/desert.png" gridsize="3 4" gridlayout=".U..LFRB.D.." /> <texture name="plane" type="2d" builtin="checker" rgb1=".1 .1 .1" rgb2=".9 .9 .9" width="512" height="512" mark="cross" markrgb=".8 .8 .8" /> <material name="plane" reflectance="0.3" texture="plane" texrepeat="1 1" texuniform="true"/> <material name="box" rgba="0 0.5 0 1" emission="0"/> </asset>几何资源 mesh
默认长度单位是米(meters, m),对应的质量单位是千克(kg)
- vertex通过坐标点构造几何体
- file加载obj或者stl模型文件,不指定name默认为文件名, scale 缩放,默认为以m为单位
- hfield通过高度图加载几何体,高度场,通过图片加载, size:缩放
纹理/材质资源
- texture 可以通过加载png对物体进行贴图,使用方法texture->material
- material 材质,可以指定纹理,颜色,反射,发光等
- skybox texture的类型,直接加载即可 天空盒演示:
<texture type="skybox" builtin="gradient" rgb1="1 1 1" rgb2="0.6 0.8 1" width="256" height="256"/>5、worldbody
场景中的根节点,所有之前配置的属性,或者资源文件可以在这里进行配置,从而交给mujoco渲染
geom
- type="[plane/hfield/sphere/capsule/ellipsoid/cylinder/box/mesh/sdf]
- size="0 0 0"(三个参数根据type选择填写)
- pos="0 0 0"(位置)
- priority="0"(碰撞优先级)
- material="xxx"(材质名)
- rgba="0 0 0 0"(几何体颜色,比材质省资源)
- friction="1 0.005 0.0001"(滑动,扭矩,滚动摩擦系数)
- mass(质量,单位kg,它和密度只能有一个),density="0"(密度,单位kg/m³,它和质量拼了)
- shellinertia=[true/false](开了就是质量集中在边缘,关了就是均匀密度)
- fromto="0 0 0 0 0 0"(类似旋转通常代替旋转+长度,只能用于胶囊、盒子、圆柱体和椭球体,前三个是point1,后三个point2,几何体的Z轴正方向为point2->point1)
- quat, axisangle, xyaxes, zaxis, eulerquat:wxyz,isaac gym:xyzweuler:xyz
地板(plane)演示:
<texture name="grid" type="2d" builtin="checker" width="2048" height="2048" rgb1=".3 .4 .8" rgb2=".9 .9 .9" /> <geom name="ground" type="plane" size="100 100 .01" material="grid" />site
简易版geom,不作为碰撞体积和质量计算,只能使用简易几何体,适用于在某些小部位安装传感器或者小结构渲染等,其属性和geom非常相近
body
在运动仿真过程中我们要实现整个机器人模型,也就是身体(骨骼+关节)拼接出来及对应body,gemo和joint,多个body嵌套就是机器人整体,整体也是呈树状嵌套。在添加joint之前我们先学习一下mujoco中body的坐标树规则,这个和ros的tf树很像,可以类比。机器人对于世界有一个坐标,机器人每个坐标系都是基于上一个坐标系的相对位置,其中body在循环嵌套,每一层中的gemo都是对于这一层的body的相对位置,每个body的坐标都是对于上一个body的相对位置。这和tf树模式几乎差不多,就如下图一样:
joint
定义关节连接,将body之间连接在一起,使其可以进行活动。这么说吧,body中的所有geom为一个整体然后joint是连接这些整体的。就是body和body靠joint活动,body中只能有一个joint用来连接当前body和上一层body。再根本一点就是joint对于上一层body是相对静止的,当前body与joint是在运动。
<!-- 支撑柱 --> <body name="support" pos="0 0 0.1"> <geom type="cylinder" mass="100" size="0.05 0.5" rgba="0.2 0.2 0.2 1"/> <!-- 水平杆 --> <body name="rotay_am" pos="0 0 0.51"> <joint type="hinge" name="pivot" pos="0 0 0" axis="0 0 1" damping="0.001" frictionloss="0.0" stiffness="0.5"/> <geom type="capsule" mass="0.01" fromto="0 0 0 0.2 0 0" size="0.01" rgba="0.8 0.2 0.2 0.5"/> <!-- 摆 --> <body name="pendulum" pos="0.2 0 0"> <joint type="hinge" name="ph" pos="0 0 0" axis="1 0 0" damping="0.001" frictionloss="0.0" /> <geom type="capsule" mass="0.005" fromto="0 0 0 0 0 -0.3" size="0.01" rgba="0.8 0.2 0.2 1" /> <!-- 配重 --> <geom type="sphere" mass="0.01" size="0.03" pos="0 0 -0.3" rgba="0.2 0.8 0.2 1" /> </body> </body> </body>friction
friction有三个参数分别是滑动摩擦,转动摩擦,滚动摩擦系数
option(椭圆/金字塔)
cone=[pyramidal, elliptic]摩擦力近似计算方法,默认pyramidal计算速度快,elliptic效果更好 impratio="1" 椭圆摩擦的比例,更高的数值摩擦力会更硬一些,防止打滑,不建议在使用pyramidal的时候调大,适合机械臂抓取打滑时调整参数
actuator
是连接控制指令与机器人关节 / 刚体的 "驱动桥梁",用于将外部控制信号(如ctrl数组中的数值)转换为仿真中的力 / 扭矩 / 位置约束,驱动模型运动(如关节旋转、机械臂伸缩)。
- 输入:控制信号(范围通常可通过ctrlrange限制)
- 输出:力、扭矩或位置 / 速度约束(依执行器类型而定)
- 常用简洁类型:
- motor:最常用,输出扭矩驱动关节(适用于旋转 / 平移关节)
- position:位置伺服执行器,驱动关节跟踪目标位置
- velocity:速度伺服执行器,驱动关节保持目标速度
light 灯光节点
节点用于在仿真场景中定义光源,核心作用是照亮场景、增强 3D 视觉效果,让模型和几何形状的轮廓、细节更清晰可见(不影响物理仿真过程,仅作用于视觉渲染)。
- 通常嵌套在 节点下(全局光源),也可嵌套在其他 节点下(随刚体运动的局部光源)。
- 核心作用:提供视觉渲染的光照支持,无物理仿真相关影响。
- 常用光源类型:通过type属性指定,默认类型为directional(平行光)。
- directional:平行光(如太阳光),无衰减,光线沿指定方向均匀照射整个场景。
- point:点光源(如灯泡),从某一点向所有方向发射光线,光线强度随距离衰减。
- spot:聚光灯,从某一点向指定方向发射锥形光束,仅照亮锥形区域。
- pos:光源的位置(适用于point/spot类型,directional类型无需指定,仅需方向)。
- dir:光源的照射方向(适用于directional/spot类型,格式为x y z)。
- rgba:光源的颜色与强度(格式为r g b a,取值范围[0,1],a通道此处通常对应光照强度)。
- castshadow:是否投射阴影(true/false,默认通常为false,开启后视觉效果更真实但略耗渲染性能)。
<!-- 1. 平行光(directional):模拟太阳光,照亮整个场景 --> <light name="sun_light" type="directional" dir="-1 -1 -1" <!-- 从右上方向左下方照射 --> rgba="1 0.9 0.8 1" <!-- 暖白色光,强度1 --> castshadow="true"/> <!-- 开启阴影 -->tendon 肌腱
tendon用于模拟柔性肌腱 / 绳索 / 缆线的力学行为,核心作用是传递力(而非直接产生力),连接模型中的多个关节、刚体或站点(site),实现类似人体肌腱、机器人钢缆的联动效果(如通过肌腱拉动多个关节协同运动,或约束刚体间的相对运动)。
- 力学属性:柔性为主,可设置刚度、阻尼、长度限制等,不具备刚体的刚性约束,受力时会产生微小变形并传递张力。
- 核心作用:传递张力、实现多部件联动、约束部件运动范围,不直接驱动模型(需配合 actuator 执行器提供驱动力)。
- 归属:直接在 mujoco 根节点下配置(与 、 同级),通过 标签定义。
- 常用类型(通过type属性指定):
- spatial:最常用,空间肌腱,可连接任意数量的站点(site)、关节,支持复杂空间路径。
- muscle:肌肉肌腱,模拟骨骼肌的主动收缩特性,可直接接收控制信号产生张力(无需额外 motor 执行器)。
- wire:线缆肌腱,简化版空间肌腱,适用于直线传递张力的场景。
spatial
使用tendon组合关节驱动的时候,要使用tendon下面的spatial节点。spatial是类似一种像肌肉一样的驱动方式,比如线驱灵巧手等。如下图所示的驱动方式,通过每个site来拉住关节驱动。
传感器
常见有相机传感器,关节角度传感器,关节速度传感器,激光测距传感器等
三、核心架构
- 静态模型:MjModel存储仿真场景的静态结构,一旦加载不再变化;内容包括:机器人几何形状、关节类型(旋转 / 平移 / 球铰等)、材质参数(密度 / 摩擦系数)、约束(关节限位 / 力约束)、传感器(力 / 位置 / 视觉传感器)、灯光 / 相机等;加载方式:从 XML/URDF 文件加载(推荐 XML,MuJoCo 原生格式),或通过 API 动态构建。
- 动态数据:MjData存储仿真过程中的动态状态,每一步仿真都会更新;内容包括:关节位置(qpos)、关节速度(qvel)、控制输入(ctrl)、接触力(contact)、传感器数据(sensordata)、物体位姿等;是用户交互的核心:读取仿真状态、设置控制指令(如关节力矩)都通过MjData实现。