跳转至

🔧 MuJoCo 后端

OrcaGym 的 Euler 模式直接使用 MuJoCo 作为物理引擎。环境初始化时自动完成模型加载。

完整可运行代码见 OrcaPlayground examples/euler/。

模型加载

模型加载在环境初始化时自动完成,无需手动操作:

# 离线模式:从本地 XML 文件加载
env = MyEnv(
    model_xml_path="path/to/scene.xml",
    skip_grpc_load=True,   # True = 离线模式,直接加载本地 XML
)

# 在线模式:通过 gRPC 从 OrcaStudio 获取模型 XML
env = MyEnv(
    model_xml_path="path/to/scene.xml",
    skip_grpc_load=False,  # False(默认)= 在线模式
)

内部流程: 1. 加载 XML → 创建 MuJoCo 实例(mjModel + mjData) 2. 查询并填充 Model / Data 信息 3. 初始化所有字典(body, joint, actuator, ...) 4. 缓存初始状态到 init_qpos / init_qvel

资源缓存

MuJoCo 模型依赖的 mesh 和 hfield 文件会缓存在 ~/.orcagym/tmp/ 目录。

仿真控制

步进控制

# ✅ 推荐:do_simulation(原子操作,自动同步 data)
env.do_simulation(ctrl, n_frames=20)
# 等价于:set_ctrl → mj_step(20) → _sync_view

# 手动控制(需要自己同步)
env.set_ctrl(ctrl)
env.mj_step(nstep=20)
env._sync_view()           # 同步状态视图

# 前向计算(刷新派生量,不推进时间)
env.mj_forward()

# 纯 MuJoCo 步进
env.mj_step(nstep=20)

ctrl 设置

# ctrl 是模型执行器的控制输入,长度 = model.nu
ctrl = np.zeros(env.model.nu, dtype=np.float64)
env.do_simulation(ctrl, env.frame_skip)

求解器配置

通过 env.sim_config 读写求解器参数:

# 读写单个参数
env.sim_config.timestep = 0.002
env.sim_config.iterations = 100
env.sim_config.integrator = 0       # 0=Euler, 1=RK4
env.sim_config.gravity = np.array([0., 0., -9.81])

# 批量设置
env.sim_config.load_from_dict({
    "integrator": 0,
    "iterations": 100,
})

# 导出配置
config = env.sim_config.to_dict()

关键参数

参数 类型 默认值 说明
timestep float 0.002 物理步长(秒)
iterations int 100 求解器迭代次数
integrator int 0 0=Euler, 1=RK4
gravity ndarray [0,0,-9.81] 重力加速度

时间步长 vs 控制频率

物理步长 (timestep)    = 0.001 秒  # 物理引擎每步的时间(默认)
控制步长 (frame_skip)  = 20       # 每次 step() 执行多少物理步
环境步长 (dt)          = 0.02 秒  # timestep × frame_skip
控制频率               = 50 Hz    # 1 / dt
print(f"物理步长: {env.sim_config.timestep:.4f}s")
print(f"frame_skip: {env.frame_skip}")
print(f"控制步长: {env.dt:.4f}s")
print(f"控制频率: {1.0/env.dt:.1f}Hz")

G1 标准配置

G1 人形机器人使用以下标准参数(来自 Euler 示例):

参数 值 说明
time_step 0.001 物理步长 1ms
frame_skip 20 每控制周期 20 物理步
dt 0.02s 控制频率 50Hz

调试与性能分析

# 查看接触数(Euler 路径用 query_contact_simple 获取接触列表长度)
contacts = env.query_contact_simple()
print(f"接触数: {len(contacts)}")

# 查看模型信息(Euler 路径下 OrcaGymModel 不暴露 nbody/njnt/nsite,
# 改用 len() 获取字典大小;ngeom/nq/nv/nu 为 model_info 中的字段)
print(f"nq={env.model.nq}, nv={env.model.nv}, nu={env.model.nu}")
print(f"ngeom={env.model.ngeom}")
print(f"nbody={len(env.model.get_body_names())}")
print(f"njnt={len(env.model.get_joint_dict())}")