MuJoCo键盘控制球体移动教程:实时记录位姿附代码
2026-03-27 来源:EEWorld 论坛
MuJoCo键盘控制球体移动教程:实时记录位姿附代码
本文将介绍如何在MuJoCo仿真环境中添加一个球体,并通过键盘方向键控制其x、y、z方向移动,同时实时记录球体的位置和姿态。教程包含完整的XML场景描述和Python代码实现,适合初学者学习MuJoCo基础操作和交互控制。
一、场景设置:XML描述
首先,创建一个MuJoCo XML文件,定义场景中的地面和球体。球体通过自由关节(freejoint)连接,允许在三维空间中自由移动。以下为XML代码:
<mujoco>
<visual>
<headlight diffuse="0.6 0.6 0.6" ambient="0.3 0.3 0.3" specular="0 0 0"/>
<rgba haze="0.15 0.25 0.35 1"/>
<global azimuth="140" elevation="-30"/>
</visual>
<asset>
<texture type="skybox" builtin="gradient" rgb1="0.3 0.5 0.7" rgb2="0 0 0" width="512" height="3072"/>
<texture type="2d" name="groundplane" builtin="checker" mark="edge" rgb1="0.2 0.3 0.4" rgb2="0.1 0.2 0.3"
markrgb="0.8 0.8 0.8" width="300" height="300"/>
<material name="groundplane" texture="groundplane" texuniform="true" texrepeat="5 5" reflectance="0.2"/>
</asset>
<worldbody>
<geom name="floor" size="0 0 0.05" type="plane" material="groundplane"/>
<body name="ball" pos="0 0 1">
<freejoint name="free_joint"/>
<geom type="sphere" size="0.2" rgba="1 0 0 1" mass="1"/>
</body>
</worldbody>
</mujoco>该代码创建了一个带纹理的地面和一个红色球体,初始位置在(0,0,1)。
二、键盘控制:使用pynput库
通过Python的pynput库监听键盘事件,实现上下左右方向键控制球体x、y移动,Alt左键和Alt右键控制z移动。代码如下:
from pynput import keyboard
key_states = {
keyboard.Key.up: False,
keyboard.Key.down: False,
keyboard.Key.left: False,
keyboard.Key.right: False,
keyboard.Key.alt_l: False,
keyboard.Key.alt_r: False,
}
def on_press(key):
if key in key_states:
key_states[key] = True
def on_release(key):
if key in key_states:
key_states[key] = False
listener = keyboard.Listener(on_press=on_press, on_release=on_release)
listener.start()三、完整代码:整合MuJoCo仿真与键盘控制
将XML场景和键盘控制结合,使用MuJoCo的Python接口进行仿真循环。在循环中,根据按键状态更新球体位置,并打印实时位姿。注意,需要关闭重力以防止球体下落。完整代码如下:
import mujoco
import mujoco.viewer
import numpy as np
from pynput import keyboard
key_states = {
keyboard.Key.up: False,
keyboard.Key.down: False,
keyboard.Key.left: False,
keyboard.Key.right: False,
keyboard.Key.alt_l: False,
keyboard.Key.alt_r: False,
}
def on_press(key):
if key in key_states:
key_states[key] = True
def on_release(key):
if key in key_states:
key_states[key] = False
listener = keyboard.Listener(on_press=on_press, on_release=on_release)
listener.start()
XML = """
<mujoco>
<visual>
<headlight diffuse="0.6 0.6 0.6" ambient="0.3 0.3 0.3" specular="0 0 0"/>
<rgba haze="0.15 0.25 0.35 1"/>
<global azimuth="140" elevation="-30"/>
</visual>
<asset>
<texture type="skybox" builtin="gradient" rgb1="0.3 0.5 0.7" rgb2="0 0 0" width="512" height="3072"/>
<texture type="2d" name="groundplane" builtin="checker" mark="edge" rgb1="0.2 0.3 0.4" rgb2="0.1 0.2 0.3"
markrgb="0.8 0.8 0.8" width="300" height="300"/>
<material name="groundplane" texture="groundplane" texuniform="true" texrepeat="5 5" reflectance="0.2"/>
</asset>
<worldbody>
<geom name="floor" size="0 0 0.05" type="plane" material="groundplane"/>
<body name="ball" pos="0 0 1">
<freejoint name="free_joint"/>
<geom type="sphere" size="0.2" rgba="1 0 0 1" mass="1"/>
</body>
</worldbody>
</mujoco>
"""
model = mujoco.MjModel.from_xml_string(XML)
model.opt.gravity = (0, 0, 0)
data = mujoco.MjData(model)
class CustomViewer:
def __init__(self, model, data):
self.handle = mujoco.viewer.launch_passive(model, data)
self.pos = 0.0001
def is_running(self):
return self.handle.is_running()
def sync(self):
self.handle.sync()
@property
def cam(self):
return self.handle.cam
@property
def viewport(self):
return self.handle.viewport
def run_loop(self):
while self.is_running():
ball_body_name = "ball"
pos = data.body(ball_body_name).xpos
quat = data.body(ball_body_name).xquat
print(f"Position: {pos}, Orientation: {quat}")
if key_states[keyboard.Key.up]:
data.qpos[0] += self.pos
if key_states[keyboard.Key.down]:
data.qpos[0] -= self.pos
if key_states[keyboard.Key.left]:
data.qpos[1] += self.pos
if key_states[keyboard.Key.right]:
data.qpos[1] -= self.pos
if key_states[keyboard.Key.alt_l]:
data.qpos[2] += self.pos
if key_states[keyboard.Key.alt_r]:
data.qpos[2] -= self.pos
mujoco.mj_step(model, data)
self.sync()
viewer = CustomViewer(model, data)
viewer.cam.distance = 3
viewer.cam.azimuth = 0
viewer.cam.elevation = -30
viewer.run_loop()四、常见问题:为什么Alt R无法控制z方向运动?
在默认情况下,MuJoCo开启重力(z轴方向),球体会自然下落。要解决此问题,需将重力设置为零,代码中添加:model.opt.gravity = (0, 0, 0)。这样,键盘控制即可在z轴生效。
五、总结
本教程演示了MuJoCo中球体的创建、键盘交互控制和位姿实时记录。通过此基础示例,可扩展用于机器人仿真、运动控制等场景。如需查看原帖详细内容(含视频和图片),请访问:MuJoCo 可视化键盘控制球体及位姿实时记录,附代码!
原帖子内容来源:https://bbs.eeworld.com.cn/thread-1310774-1-1.html
相关文章




