☰
MuJoCo保姆级教程:从二连杆机械臂建模到强化学习实战
2026/10/17 5:01:46 网站建设 项目流程

我见过太多想转具身智能的朋友,第一步就卡在 MuJoCo 上。不是装不上,就是装上了不知道下一步干什么,翻了一堆教程最后还是在跑官方 demo。网上关于 MuJoCo 的资料确实不少,但多数都断在"能跑起来"这一步,真正从机器人建模仿真一路走到强化学习训练的完整链路,很少有人系统地讲。这篇教程我打算换个思路:不罗列官网文档,而是以一个二连杆机械臂为贯穿案例,从零开始写模型、跑仿真、搭强化学习环境,最后把训练代码跑通。适合刚接触 MuJoCo 的学生,也适合想从传统机器人切入具身智能的工程师,按顺序读完并动手操作,你能获得一套完整可复用的方法和踩坑经验。

1. 为什么这套教程选 MuJoCo——物理引擎的取舍与底层逻辑

很多人上来就问:PyBullet 不也行吗?Webots 不是更完整吗?为什么非 MuJoCo 不可。我的答案是:如果你目标是具身智能方向的研究或落地,MuJoCo 几乎是绕不开的基础设施。它解决的问题很纯粹——以足够高的精度模拟刚体之间的接触、碰撞、关节运动和动力学响应,为强化学习提供一个"不贵"的试错环境。真实机器人训练一次的成本高得离谱,仿真器的意义就是把试错成本压到最低,而 MuJoCo 在这一点的效率表现几乎是最好的。

1.1 MuJoCo 相比其他物理引擎的显著优势

先看一段我自己的对比结论,不代表绝对优劣,只谈实际体验。

  • 计算效率:MuJoCo 的求解器在接触计算上做了大量优化,一份中等复杂度的机器人模型,普通笔记本就能跑到实时甚至超实时。我在同一台机器上对比过 PyBullet 和 MuJoCo,同样的机械臂模型,MuJoCo 的单步耗时大约低 30% 到 50%。强化学习训练动辄几十万步,这个差距会被放大得很明显。
  • 接触稳定性:模型里两个零件一碰就穿模、反弹、抖动,应该是用物理引擎最头疼的事了。MuJoCo 的求解器对接触约束处理得非常稳,默认参数下大多数场景不会出现致命穿透。
  • 数值单位与建模思路:MuJoCo 使用 SI 单位制,力、力矩、加速度的表达非常规范,这让从仿真到真实机器人的参数迁移少了一层换算烦恼。
  • 开源免费:2021 年底 MuJoCo 被 DeepMind 收购后对全行业免费开放,Python 绑定也逐步完善,现在只需要pip install mujoco就能用。

这不是说其他引擎没用。PyBullet 的 URDF 生态成熟,Webots 自带完整传感器模型,这些在某些场景下更方便。但如果你是做强化学习方向,MuJoCo 是大多数论文默认的基准平台,跑通它之后看论文、复现结果会顺畅很多。

1.2 这套教程的主线设计思路

为了不让你停留在"会跑 demo"的假熟练,我设计了下面这条主线:

  1. 从零编写一个二连杆机械臂的 MJCF 模型文件,理解机器人建模的核心概念。
  2. 编写 Python 脚本控制模型运动,理解 MuJoCo 的数据交互机制。
  3. 接入 Gymnasium,把机械臂到达目标点的任务封装成标准强化学习环境。
  4. 使用 Stable-Baselines3 训练一个控制策略,并验证效果。

这样一套走下来,你就同时掌握了建模、控制和训练三个环节。这也正好对应具身智能里最常见的三种工作:搭环境、写控制器、训策略。

提示:如果你只对其中一个环节感兴趣,也可以直接跳到对应章节。但强烈建议按顺序过一遍,因为很多参数和代码片段会在后文反复复用。

2. Windows 11 下 MuJoCo 环境安装实录——版本选择与报错排查

标题既然挂了"保姆级",我最想帮你省时间的地方就是安装。MuJoCo 在 Windows 11 上的安装流程经过多个版本迭代后,现在已经简单很多,但依然有不少细节会绊倒人。我按自己的实际操作过程写一遍,连同我踩过的坑一起列出来。

2.1 Python 环境准备与安装步骤

我推荐使用conda管理环境,避免多个项目之间的依赖冲突。打开 Anaconda Prompt 或终端,依次执行:

conda create -n mujoco_env python=3.10 conda activate mujoco_env pip install mujoco

这里选择 Python 3.10 不是因为新版本不行,而是 3.10 对科学计算生态的兼容最稳。我实际测试过 3.11 和 3.12 也没什么大问题,但如果后续要装稳定版 PyTorch,3.10 的坑最少。

安装完成后,在 Python 里验证一下:

import mujoco print(mujoco.__version__)

能正常输出版本号就说明核心库装好了。接下来验证渲染能力,MuJoCo 自带的 viewer 可以直接查看模型:

python -c "import mujoco.viewer; print('viewer ok')"

这一步主要检查 OpenGL 相关依赖是否正常。如果你运行这段代码报错,最常见的三个原因和处理方式我在下面单独讲。

2.2 高频报错的定位与解决

报错一:缺少依赖库glfw或opengl32.dll相关异常

新版mujoco的 PyPI 包已经内置了 Windows 下需要的运行时,但某些精简版系统会缺 Visual C++ Redistributable。解决办法是去微软官网下载并安装最新的 Visual C++ Redistributable,装完重启终端即可。

报错二:打开 viewer 时提示无法创建窗口

这通常不是 MuJoCo 的问题,而是显卡驱动或 OpenGL 版本问题。先把显卡驱动更新到最新;如果还是不行,检查是不是在远程桌面或虚拟机里运行,这种环境 OpenGL 支持通常不完整,建议换物理机测试。

报错三:ModuleNotFoundError: No module named 'mujoco'

多半是pip安装到了别的环境。执行pip list | grep mujoco确认包所在环境,再用python -m pip install mujoco强制装到当前 Python 解释器对应的环境中。

2.3 旧版 mujoco-py 与新版的取舍

网上很多教程还在讲mujoco-py的安装,甚至要配置编译环境、复制 dll 文件,这些在 2.3.0 之后的新版绝对不推荐。我建议直接使用官方统一后的包名mujoco,它不再需要单独的 Python 绑定层,安装和使用体验都干净很多。

对比维度新版 mujoco旧版 mujoco-py
安装复杂度pip install mujoco一步完成需要编译和配置路径
官方维护状态持续维护基本只做兼容性维护
物理引擎版本MuJoCo 3.x 及以上MuJoCo 2.x 为主
渲染能力内置 viewer,体验更好依赖外部 mjviewer

所以如果你在搜索引擎里看到 2021 年以前的安装教程,建议直接跳过安装部分,只参考建模思路。

3. 从空白 XML 到能动的模型——MJCF 建模思路与实操

建模是整个仿真链路里最"物理"的环节。你需要把一台真实的或设计好的机器人,用数学和图形化语言描述给仿真器。我在这一章会从零搭建一个简单的二连杆机械臂,截面可能不长,但每一步都解释为什么这么写,避免你看完只会抄代码、不会改。

3.1 为什么要用 MJCF 而不是直接写 URDF

机器人领域最常见的模型格式是 URDF,很多人的第一反应是用 URDF。但 MuJoCo 官方推荐的 MJCF 格式在写模型时明显更舒服,原因有三个:

  1. 默认值更智能:MJCF 里大部分物理参数都有合理的默认值,你只需要在需要调整的地方显式声明,模型会更精简。
  2. 层级表达更直观:body嵌套body形成运动链,关节和惯性参数直接写在对应 body 下,非常好读。
  3. 支持快速调试:修改 XML 后可以热加载,不用像 URDF 那样反复转换。

直接把机械臂的 CAD 模型导入软件转 URDF 再给 MuJoCo 用,也不是不行,但手写 MJCF 能帮你建立对模型的掌控感——你很清楚每个参数的作用,这对后续模型修改和问题定位帮助很大。

3.2 二连杆机械臂模型的最小实现

我创建了一个文件simple_arm.xml,内容如下:

<mujoco model="simple_arm"> <compiler angle="radian"/> <option gravity="0 0 -9.81"/> <worldbody> <body name="base" pos="0 0 0"> <geom name="base_plate" type="cylinder" size="0.08 0.02" pos="0 0 0.02" mass="1.0"/> <joint name="joint1" type="hinge" axis="0 0 1" pos="0 0 0.04"/> <body name="link1" pos="0 0 0.04"> <geom name="link1_visual" type="box" size="0.03 0.03 0.25" pos="0 0 0.25" mass="0.8"/> <joint name="joint2" type="hinge" axis="0 1 0" pos="0 0 0.5"/> <body name="link2" pos="0 0 0.5"> <geom name="link2_visual" type="box" size="0.03 0.03 0.25" pos="0 0 0.25" mass="0.6"/> </body> </body> </body> </worldbody> </mujoco>

我来逐段解释关键点。

<compiler angle="radian"/>表示角度单位用弧度,这样和强化学习里常见的角速度、角加速度单位保持一致。<option gravity="0 0 -9.81"/>设置重力加速度,z轴负方向。

<worldbody>是模型世界的根节点,相当于真实世界的地面坐标系。在里面放一个base底座,geom type="cylinder"是几何体的圆柱体,size="0.08 0.02"第一个值是半径、第二个值是半高度,mass控制质量。

关节部分是最关键的。<joint name="joint1" type="hinge" axis="0 0 1"/>表示绕 z 轴旋转,这也意味着机械臂在水平面上运动。joint2用axis="0 1 0"绕 y 轴旋转,让第二根臂可以在垂直方向抬升。之所以第一个关节不用axis="0 1 0"的典型排列,是想演示一个在现实中常见但初学者容易忽略的点:多关节机械臂的运动并不一定都在同一平面内。

你可能会奇怪为什么geom的pos和body的pos看起来重复设置。这是因为body的坐标系是相对父节点的,geom的pos又是相对所在body的。建模时务必理清楚每一层坐标系的相对关系,这是模型不漂移的前提。

3.3 加载模型并让机械臂动起来

模型文件建好后,下一步是在 Python 里加载它并查看效果:

import mujoco model = mujoco.MjModel.from_xml_path("simple_arm.xml") data = mujoco.MjData(model) for i in range(1000): data.ctrl[0] = 0.5 data.ctrl[1] = -0.2 mujoco.mj_step(model, data) if i % 100 == 0: print(data.qpos)

这里data.ctrl是执行器的控制输入,但注意我目前的模型里还没有定义执行器,所以直接运行会报错。继续往下看,下一步就把执行器补上。

MuJoCo 的核心交互对象是model和data。model描述物理世界的不变属性(几何、质量、关节轴),data保存当前状态(位置、速度、控制量、传感器读数)。每一步物理更新用mj_step推进。理解这两个对象的区别,后面写控制器才不会懵。

3.4 给机械臂添加执行器与传感器

要让机械臂动起来,需要在模型里定义执行器。在<worldbody>后面加入:

<actuator> <motor joint="joint1" ctrlrange="-1 1" gear="2"/> <motor joint="joint2" ctrlrange="-1 1" gear="2"/> </actuator>

motor表示力矩电机,ctrlrange是控制量的输出范围,gear相当于减速比。添加后重新加载模型,data.ctrl就能真正驱动关节运动了。

想读取模型状态信息,可以用内置传感器:

<sensor> <jointpos joint="joint1"/> <jointvel joint="joint1"/> <jointpos joint="joint2"/> <jointvel joint="joint2"/> </sensor>

这样在 Python 里就能通过data.sensordata拿到关节位置和速度。传感器数据是后面强化学习中构造观测空间的重要来源。

注意:如果你把gear设置成 1,在调试时可能觉得电机无力,尤其是考虑重力的垂直关节。这个参数不是随便填的,真实电机有减速比约束,仿真里也要尽可能贴近物理实际,否则训练出的策略很可能无法迁移到真机。

4. 仿真不只能看不能碰:数据交互与控制器设计

模型文件写好后,很多教程就停在让它自己转两下。但实际做机器人控制的时候,我们需要频繁地读取状态、计算控制量、设置目标位置,甚至实时修改模型参数。这一章就讲清楚这些"交互"到底怎么做。

4.1 sim 内部状态与外部控制指令的对应关系

MuJoCo 中最重要的概念就是data.qpos和data.qvel,前者记录广义位置(关节角度),后者记录广义速度(关节角速度)。当你用data.ctrl发送力矩指令后,求解器会根据当前qpos、qvel、执行器输出和外力算出下一步的状态。

看一下具体的控制代码逻辑:

import numpy as np import mujoco model = mujoco.MjModel.from_xml_path("simple_arm.xml") data = mujoco.MjData(model) target_qpos = np.array([0.5, -0.3]) for step in range(3000): # 简单的PD控制:根据位置误差计算目标力矩 kp = 30.0 kd = 2.0 error = target_qpos - data.qpos data.ctrl = kp * error - kd * data.qvel mujoco.mj_step(model, data)

这段代码的含义是:如果当前关节角度离目标位置远,就给一个大一点的力矩把它推过去;同时考虑角速度,避免到达目标后来回震荡。PD 控制是机器人控制里最基础也最实用的方法,后面强化学习训练出来的策略,本质上也是在学一个更聪明的"控制器"。

4.2 使用 viewer 进行可视化调试

命令行跑模型看不到效果,不直观。MuJoCo 提供了 Python API 来启动交互式查看器:

import mujoco import mujoco.viewer model = mujoco.MjModel.from_xml_path("simple_arm.xml") data = mujoco.MjData(model) with mujoco.viewer.launch_passive(model, data) as viewer: for step in range(10000): data.ctrl = [0.3, -0.2] mujoco.mj_step(model, data) viewer.sync()

launch_passive会打开一个可视化窗口,你可以在里面旋转视角、查看接触点、观察关节状态。渲染部分依赖 OpenGL,如果你的环境是远程服务器,可能需要虚拟显示方案,但 Windows 本地一般没问题。

在这个阶段,我建议你多拖动鼠标观察模型运动是否合理:杆子会不会穿模、关节是否朝预期方向旋转、接近奇异位形时是否出现剧烈抖动。这些"看得见的异常"往往比数值调试更容易定位问题。

4.3 离线渲染保存训练过程

很多时候我们需要把训练过程录下来做展示或复盘,MuJoCo 支持离屏渲染。流程是创建一个离屏渲染上下文,然后逐步渲染图像:

import mujoco import imageio model = mujoco.MjModel.from_xml_path("simple_arm.xml") data = mujoco.MjData(model) renderer = mujoco.Renderer(model, height=480, width=640) frames = [] for step in range(500): data.ctrl = [0.3, -0.2] mujoco.mj_step(model, data) if step % 2 == 0: renderer.update_scene(data) frames.append(renderer.render()) imageio.mimsave("sim_output.gif", frames, fps=30)

这段代码会把仿真过程保存成 gif。注意update_scene每次都要调用,否则图像不会更新。离线渲染的帧率一般比实时渲染慢,但胜在稳定可控,适合批量生成数据。

4.4 接触与碰撞的调试技巧

模型里如果有接触不稳定的情况,最快的方法是打开接触几何体显示。在 viewer 里可以通过 UI 面板勾选显示 contact,查看接触点的位置、法向量和穿透深度。

接触穿透通常由三种原因导致:几何体尺寸设计不合理、碰撞组配置错误、时间步长过大。时间步长是常见元凶,默认0.002秒一般够用,但如果模型中有高速运动部件,需要减小时间步长到0.0005或0.001。这个参数在反复调试中最容易忽略,我特意多次提醒。

5. 让机器人"学会"一件事:MuJoCo 强化学习环境搭建与训练

模型会动了,控制器也会写了,接下来是重头戏——用强化学习让机械臂自己学着完成目标。这里我会直接对接强化学习社区的标准接口 Gymnasium,然后调用现成算法库完成训练,整个过程你可以直接抄作业。

5.1 为什么需要 Gymnasium 这种标准接口

MuJoCo 本身不提供"任务"的概念,它只负责物理计算。但强化学习需要的是:一个智能体(机械臂)、一个观测空间、一个动作空间、一个奖励函数,以及"重置到初始状态"的能力。Gymnasium 正是为了把环境封装成统一接口而存在的,它让同一套算法可以随意切换到不同任务。

生态里的gymnasium.envs.mujoco其实已经封装了很多 MuJoCo 环境,比如HalfCheetah-v4、Walker2d-v4、Humanoid-v4等。这些环境可以快速跑通算法,但缺少"你自定义机器人"的灵活性。因此我以自建二连杆机械臂为例,演示怎么把 MJCF 模型改造成一个标准强化学习环境。

5.2 把二连杆机械臂封装成 Gymnasium 环境

先安装所需依赖:

pip install gymnasium stable-baselines3

然后创建simple_arm_env.py:

import numpy as np import mujoco import gymnasium as gym from gymnasium import spaces class SimpleArmEnv(gym.Env): def __init__(self, xml_path="simple_arm.xml"): super().__init__() self.model = mujoco.MjModel.from_xml_path(xml_path) self.data = mujoco.MjData(self.model) # 观测:两个关节角度 + 两个关节角速度 + 末端位置 + 目标位置 obs_dim = 2 + 2 + 2 + 2 self.observation_space = spaces.Box(low=-np.inf, high=np.inf, shape=(obs_dim,), dtype=np.float32) self.action_space = spaces.Box(low=-1.0, high=1.0, shape=(2,), dtype=np.float32) self.goal = np.array([0.5, 0.5]) # 目标位置,这里先用固定点 def _get_obs(self): end_pos = self._forward_kinematics(self.data.qpos) return np.concatenate([ self.data.qpos, self.data.qvel, end_pos, self.goal ]).astype(np.float32) def _forward_kinematics(self, qpos): l1 = 0.5 l2 = 0.5 x = l1 * np.sin(qpos[0]) + l2 * np.sin(qpos[0] + qpos[1]) y = -l1 * np.cos(qpos[0]) - l2 * np.cos(qpos[0] + qpos[1]) return np.array([x, y]) def reset(self, seed=None, options=None): super().reset(seed=seed) self.data.qpos = [0.0, 0.0] self.data.qvel = [0.0, 0.0] mujoco.mj_forward(self.model, self.data) return self._get_obs(), {} def step(self, action): self.data.ctrl[:] = np.clip(action, -1.0, 1.0) mujoco.mj_step(self.model, self.data) obs = self._get_obs() end_pos = obs[4:6] dist = np.linalg.norm(end_pos - self.goal) reward = -dist terminated = bool(dist < 0.05) truncated = False return obs, reward, terminated, truncated, {} def render(self): pass

这段代码有几个关键点:

  1. 重置时用mj_forward更新初始状态,确保动力学一致性。
  2. 观测向量拼接了关节角度、角速度、末端位置和目标位置,信息量足够算法学到一个合理策略。
  3. 奖励函数用负距离,简单直接。如果你想要更平滑的训练曲线,可以加上对动作幅度的惩罚项。
  4. 动作空间规范化到[-1, 1],符合大多数强化学习算法对输出的期望。

5.3 用 SB3 训练第一个策略

环境封装完成后,使用 Stable-Baselines3 的 SAC 或 PPO 训练都可以。我以 SAC 为例,因为它对连续动作控制效果通常很好:

from stable_baselines3 import SAC from stable_baselines3.common.env_checker import check_env from stable_baselines3.common.callbacks import EvalCallback env = SimpleArmEnv() check_env(env) model = SAC( "MlpPolicy", env, learning_rate=3e-4, buffer_size=200_000, batch_size=256, tau=0.005, gamma=0.99, verbose=1 ) eval_callback = EvalCallback(env, best_model_save_path="./logs/", eval_freq=2000, n_eval_episodes=5) model.learn(total_timesteps=200_000, callback=eval_callback) model.save("simple_arm_sac")

check_env这一步很多人会跳过,但它能帮你提前发现接口实现错误。训练过程中你会看到ep_rew_mean逐渐上升,说明机械臂末端离目标越来越近。200k 步在普通 CPU 上可能跑一段时间,有 GPU 的话会快很多。

5.4 训练结果验证与常见问题

训练完成后加载模型测试:

import numpy as np model = SAC.load("simple_arm_sac.zip") env = SimpleArmEnv() obs, _ = env.reset() for _ in range(500): action, _ = model.predict(obs, deterministic=True) obs, reward, terminated, truncated, _ = env.step(action) if terminated: print("到达目标点!") break

我踩过的两个典型问题,提前给你排雷:

  1. 训练时奖励不涨,甚至越来越低:先检查是不是目标点设在机械臂根本够不到的位置。二连杆的工作空间是半径为臂长之和的圆盘,目标点必须在这个范围内。我一开始把目标放在[0.8, 0.8],机械臂无论怎么动都差一大截,奖励曲线自然上不去。
  2. 训练到后面出现剧烈抖动:多半是奖励函数里没有对动作幅度做惩罚,算法学会了高频抖动来"投机"。应对方法是在奖励里减去例如0.1 * np.sum(action**2)。

5.5 常见强化学习算法与 MuJoCo 任务的匹配

对于刚开始接触强化学习的人来说,看到那堆算法名称容易懵。我整理了一个极简选择表:

算法适用场景是否适合 MuJoCo 连续控制学习成本
Q-Learning / DQN离散动作空间不适合低
DDPG连续动作空间可以但训练不稳定中
PPO连续/离散都行非常常用,稳定中
SAC连续动作空间效果通常最好中
TD3连续动作空间类似 SAC,偏保守中

如果你刚入门,PPO 是最稳妥的选择;如果追求单任务性能上限,SAC 往往更快更稳。不要一上来就同时调算法、调奖励、调超参数,那样出了问题根本定位不到是哪部分导致的。

6. 走出仿真:具身智能进阶路线与 Sim2Real 避坑

训练完一个机械臂成功到达目标点,你已经跑通了整套链路。但如果目标是具身智能方向,这其实只是起点。真机部署、多传感器融合、Sim2Real 迁移才是真正拉开差距的地方。这一章我讲几条实际有用的路径和避坑方向。

6.1 从仿真策略到真实机器人的差距

训练时模型里的质量、摩擦系数、阻尼参数都是我们设置的理想值,真实机械臂和仿真模型的差距可能非常大。最直接的做法是仔细观察真实机器人的关节摩擦特性,手动把仿真里的参数校准到接近真实数据,但完全一致几乎不可能。

一个相对可行的思路是:利用随机化训练。在 MuJoCo 里,每次reset时随机修改摩擦力、质量、控制延迟等参数,让策略学会"不管真实参数往哪偏都能工作"。这种做法在学术上叫 domain randomization,是 Sim2Real 里比较主流的手段。

6.2 数据采集与模型复用

真实机器人上更实际的问题不是"策略不够聪明",而是"数据不够用"。MuJoCo 的优势在于可以快速批量生成数据,比如用不同初始状态和控制策略跑大量轨迹,把关节角度、角速度、力矩、末端位姿保存下来,用于训练逆动力学模型或视觉模型。

这里建议你在生成数据时,除了保存关节信息,也把渲染图像存下来,为后续视觉强化学习做准备。视觉输入能让策略适应更复杂的任务,但训练成本会显著上升。新手可以先从状态输入做起,跑通之后再叠加视觉。

6.3 具身智能还需要补哪些课

从 MuJoCo 入手只是拿到了具身智能的第一块积木,后面肯定绕不开这些方向:

  • 机器人学基础:齐次变换、运动学、动力学、轨迹规划。这些是理解模型底层原理的地基,也是面试几乎必考的部分。
  • 强化学习进阶:策略梯度、价值函数、多智能体强化学习、离线强化学习。尤其是离线强化学习,真实机器人数据获取困难,用离线数据训练是重要的研究方向。
  • 大语言模型与机器人结合:现在具身智能的热点已经延伸到用语言指令驱动机器人规划。MuJoCo 里也可以接一个语言模型输出高层指令,再把指令翻译成底层控制目标。
  • ROS 与真机部署:仿真是高效的研发手段,但最终要落到真机上。ROS、控制总线和传感器驱动迟早要学。

6.4 多智能体与 MJX:下一阶段的扩展方向

如果你已经能熟练完成单机械臂训练,可以尝试多机械臂协作任务。MuJoCo 支持多模型联合仿真,多个机械臂共享世界模型,每个智能体有独立的观测和动作空间,算法则需要改用多智能体强化学习框架,训练复杂度会明显上升。

另一个值得关注的方向是 MuJoCo 的 JAX 版本MJX。它能把仿真放到 GPU 上并行运行,同时跑成百上千个环境实例,训练速度提升一个量级。不过 MJX 目前的 API 和原生 MuJoCo 有差异,建议先在原生 MuJoCo 上把流程彻底跑通,再考虑迁移到 MJX 做大规模并行训练。

我自己的实践体会是:任何脱离具体任务的参数调整都是在浪费时间。MuJoCo 的好处在于,你可以在非常短的时间内把一个想法变成能看的仿真结果,但真正有价值的是你从结果里读出了什么、改了什么、为什么这么改。把每一步的"为什么"记下来,你会比单纯跑通 100 个 demo 收获更多。最后再分享一个小技巧:每当模型或训练出现诡异的问题,别急着改参数,先用 MuJoCo 自带的建模工具检查模型文件是否有 warning,再用 viewer 观察物理行为是否合理。把现象观察清楚,问题往往就已经解决了一半。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询