| name | mujoco |
| description | MuJoCo 物理仿真开发技能 - 高性能物理引擎、强化学习环境、MJCF 模型、GPU 加速 |
| argument-hint | mujoco仿真 OR 强化学习 OR MJCF模型 OR 机器人控制 |
| user-invocable | true |
MuJoCo Physics Simulation Skill
用于 MuJoCo 物理仿真环境的配置和开发
何时使用
当需要以下帮助时使用此技能:
- 安装和配置 MuJoCo
- 创建 MJCF 模型
- 编写强化学习环境
- 使用 GPU 加速
- 集成 ROS
快速参考
安装 MuJoCo
pip install mujoco-py
pip install mujoco
基本使用
import mujoco
import mujoco.viewer as viewer
model = mujoco.MjModel.from_xml_path("robot.xml")
data = model.data
v = viewer.launch_passive(model, data)
for _ in range(1000):
mujoco.mj_step(model, data)
v.sync()
MJCF 模型
基本结构
<mujoco model="my_robot">
<compiler angle="radian" meshdir="meshes" autolimits="true"/>
<option timestep="0.002" integrator="Euler" iterations="50" tolerance="1e-10"/>
<global>
<gravity gravity="0 0 -9.81"/>
<wind wind="0 0 0"/>
<density density="1.0"/>
<viscosity viscosity="0.0"/>
</global>
<worldbody>
<geom type="plane" size="10 10 0.1" rgba="0.5 0.5 0.5 1" friction="0.4 0.005 0.0001"/>
<light pos="0 0 5" dir="0 0 -1" diffuse="0.8 0.8 0.8" specular="0.3 0.3 0.3"/>
</worldbody>
<actuator>
<motor joint="shoulder" ctrllimited="true" ctrlrange="-50 50" gear="100"/>
</actuator>
</mujoco>
完整机器人示例 - 双足机器人
<mujoco model="biped_robot">
<compiler angle="radian" meshdir="meshes" autolimits="true"/>
<option timestep="0.002" iterations="100" solver="Newton" gravity="0 0 -9.81"/>
<worldbody>
<body name="torso" pos="0 0 1.0">
<freejoint/>
<inertial pos="0 0 0" mass="8" diaginertia="0.1 0.08 0.08"/>
<geom type="capsule" size="0.07 0.2" rgba="0.4 0.4 0.4 1" friction="0.5"/>
<body name="head" pos="0 0 0.25">
<inertial pos="0 0 0" mass="1.5" diaginertia="0.01 0.01 0.01"/>
<geom type="sphere" size="0.1" rgba="0.6 0.6 0.6 1"/>
<camera name="eye" pos="0.05 0 0.05" fovy="90"/>
</body>
<body name="left_hip" pos="0 0.1 -0.2">
<joint name="hip_flexion" type="hinge" axis="1 0 0" range="-90 90" damping="0.1"/>
<inertial pos="0 0 -0.1" mass="2" diaginertia="0.02 0.01 0.02"/>
<geom type="capsule" size="0.04 0.2" rgba="0.3 0.3 0.3 1"/>
<body name="left_knee" pos="0 0 -0.2">
<joint name="knee" type="hinge" axis="1 0 0" range="-150 0" damping="0.1"/>
<inertial pos="0 0 -0.1" mass="1.5" diaginertia="0.015 0.01 0.015"/>
<geom type="capsule" size="0.035 0.2" rgba="0.35 0.35 0.35 1"/>
<body name="left_foot" pos="0 0 -0.2">
<joint name="ankle" type="hinge" axis="1 0 0" range="-45 45" damping="0.05"/>
<inertial pos="0 0 -0.05" mass="0.5" diaginertia="0.005 0.003 0.005"/>
<geom type="box" size="0.06 0.04 0.02" rgba="0.2 0.2 0.2 1" friction="1.0 0.005 0.0001"/>
</body>
</body>
</body>
<body name="right_hip" pos="0 -0.1 -0.2">
<joint name="hip_flexion" type="hinge" axis="1 0 0" range="-90 90" damping="0.1"/>
<inertial pos="0 0 -0.1" mass="2" diaginertia="0.02 0.01 0.02"/>
<geom type="capsule" size="0.04 0.2" rgba="0.3 0.3 0.3 1"/>
<body name="right_knee" pos="0 0 -0.2">
<joint name="knee" type="hinge" axis="1 0 0" range="-150 0" damping="0.1"/>
<inertial pos="0 0 -0.1" mass="1.5" diaginertia="0.015 0.01 0.015"/>
<geom type="capsule" size="0.035 0.2" rgba="0.35 0.35 0.35 1"/>
<body name="right_foot" pos="0 0 -0.2">
<joint name="ankle" type="hinge" axis="1 0 0" range="-45 45" damping="0.05"/>
<inertial pos="0 0 -0.05" mass="0.5" diaginertia="0.005 0.003 0.005"/>
<geom type="box" size="0.06 0.04 0.02" rgba="0.2 0.2 0.2 1" friction="1.0 0.005 0.0001"/>
</body>
</body>
</body>
<body name="left_shoulder" pos="0.15 0 0.15">
<joint name="shoulder_flexion" type="hinge" axis="0 0 1" range="-180 180" damping="0.05"/>
<inertial pos="0 0 0" mass="0.8" diaginertia="0.005 0.005 0.002"/>
<geom type="capsule" size="0.025 0.15" rgba="0.4 0.4 0.4 1"/>
<body name="left_elbow" pos="0 0 -0.15">
<joint name="elbow" type="hinge" axis="0 0 1" range="-150 0" damping="0.05"/>
<inertial pos="0 0 0" mass="0.5" diaginertia="0.003 0.003 0.001"/>
<geom type="capsule" size="0.02 0.12" rgba="0.45 0.45 0.45 1"/>
</body>
</body>
<body name="right_shoulder" pos="0.15 0 0.15">
<joint name="shoulder_flexion" type="hinge" axis="0 0 1" range="-180 180" damping="0.05"/>
<inertial pos="0 0 0" mass="0.8" diaginertia="0.005 0.005 0.002"/>
<geom type="capsule" size="0.025 0.15" rgba="0.4 0.4 0.4 1"/>
<body name="right_elbow" pos="0 0 -0.15">
<joint name="elbow" type="hinge" axis="0 0 1" range="-150 0" damping="0.05"/>
<inertial pos="0 0 0" mass="0.5" diaginertia="0.003 0.003 0.001"/>
<geom type="capsule" size="0.02 0.12" rgba="0.45 0.45 0.45 1"/>
</body>
</body>
</body>
</worldbody>
<actuator>
<motor joint="hip_flexion" ctrllimited="true" ctrlrange="-50 50" gear="50"/>
<motor joint="knee" ctrllimited="true" ctrlrange="-30 30" gear="30"/>
<motor joint="ankle" ctrllimited="true" ctrlrange="-20 20" gear="20"/>
<motor joint="shoulder_flexion" ctrllimited="true" ctrlrange="-20 20" gear="20"/>
<motor joint="elbow" ctrllimited="true" ctrlrange="-15 15" gear="15"/>
</actuator>
<sensor>
<framepos objtype="body" objname="left_foot"/>
<framepos objtype="body" objname="right_foot"/>
<jointpos joint="hip_flexion"/>
<jointpos joint="knee"/>
<jointpos joint="ankle"/>
<gyro site="torso"/>
<accelerometer site="torso"/>
</sensor>
</mujoco>
强化学习环境
使用 Gymnasium
import gymnasium as gym
from gym import spaces
import numpy as np
class MuJoCoEnv(gym.Env):
def __init__(self, model_path="robot.xml"):
super().__init__()
self.model = mujoco.MjModel.from_xml_path(model_path)
self.data = self.model.data
self.action_space = spaces.Box(
low=-1, high=1,
shape=(self.model.nu,),
dtype=np.float32
)
self.observation_space = spaces.Box(
low=-np.inf, high=np.inf,
shape=(self.model.nq + self.model.nv + self.model.nu,),
dtype=np.float32
)
def reset(self, seed=None, options=None):
mujoco.mj_resetData(self.model, self.data)
obs = self._get_obs()
return obs, {}
def step(self, action):
self.data.ctrl[:] = action
mujoco.mj_step(self.model, self.data)
obs = self._get_obs()
reward = self._compute_reward()
done = self._is_done()
return obs, reward, done, False, {}
def _get_obs(self):
return np.concatenate([
self.data.qpos,
self.data.qvel,
self.data.ctrl
])
def _compute_reward(self):
return 0
def _is_done(self):
return False
def render(self):
pass
使用 DM Control
from dm_control import suite
import numpy as np
env = suite.load(domain_name="walker", task_name="run")
action_spec = env.action_spec()
observation_spec = env.observation_spec()
time_step = env.reset()
while not time_step.last():
action = np.random.uniform(action_spec.minimum, action_spec.maximum)
time_step = env.step(action)
print(f"Reward: {time_step.reward}")
控制器
PD 控制器
def pd_control(model, data, kp=1.0, kd=0.5):
"""PD 控制器"""
q_des = np.zeros(model.nq)
qdot_des = np.zeros(model.nv)
q_error = q_des - data.qpos
qdot_error = qdot_des - data.qvel
ctrl = kp * q_error + kd * qdot_error
return ctrl
阻抗控制
def impedance_control(model, data, target_pos, k_p=100, k_d=10):
"""阻抗控制器"""
current_pos = data.body_xpos[-1]
error = target_pos - current_pos
f = k_p * error - k_d * data.cvel
ctrl = np.zeros(model.nu)
return ctrl
GPU 加速
GPU 仿真
print(mujoco.get_platform())
model = mujoco.MjModel.from_xml_path("robot.xml",
nthread=4,
nsubsteps=2)
并行环境
from dm_control import composer
from dm_control import suite
env = suite.load(domain_name="cartpole",
task_name="balance",
visualize_reward=False)
for _ in range(1000):
action = env.action_spec().sample()
time_step = env.step(action)
传感器
读取传感器数据
qpos = data.qpos
qvel = data.qvel
qfrc = data.qfrc
end_effector_pos = data.body_xpos[-1]
contact_force = data.eforce
for i in range(model.ncon):
contact = data.contact[i]
ROS 集成
ROS2 控制器
import rclpy
from rclpy.node import Node
import mujoco
class MuJoCoROS2(Node):
def __init__(self):
super().__init__('mujoco_ros2')
self.model = mujoco.MjModel.from_xml_path('/path/to/robot.xml')
self.data = self.model.data
self.create_subscription(
Float64MultiArray,
'/joint_commands',
self.cmd_callback,
10)
self.timer = self.create_timer(0.002, self.step_callback)
def cmd_callback(self, msg):
self.data.ctrl[:] = msg.data
def step_callback(self):
mujoco.mj_step(self.model, self.data)
常见问题
问题 1: 模型不稳定
解决方案:
- 增加 solver iterations
- 调整 timestep
- 检查质量分布
问题 2: 仿真速度慢
解决方案:
问题 3: 碰撞检测失败
解决方案:
- 检查 geom 类型
- 调整碰撞容差
- 使用正确的摩擦系数
相关资源
另见