07 · 常见问题与经验
本流程实际踩过的坑,按现象速查。
环境类
| 现象 | 原因与解法 |
|---|---|
uv sync 报 failed to persist temporary file ... os error 17(跨盘) | 本机 uv 缓存目录跨盘的 Windows 特例。所有 uv 命令前加 export UV_CACHE_DIR='C:\Users\admin\AppData\Local\Temp\uv-cache' |
控制台刷几十行 libtorchcodec_core*.dll 加载失败 | 噪音警告:torchcodec 加载失败后自动回退 pyav。实测(smoke [5])pyav 编解码视频数据集都正常,状态数据集和视频数据集都不受影响 |
python 打开 Microsoft Store | 用 uv 管理的 Python;别用 Store 版 |
lerobot-train 报 accelerate is required but not installed | 初始安装时漏了 training extra——按 01 的 uv sync 命令补上 --extra training 后重试(01 的一次性安装已包含,按 01 装完不会遇到) |
遥操类
| 现象 | 原因与解法 |
|---|---|
| 键盘控制"很慢" | --teleop.rate 默认 60 单位/秒偏保守;提到 150 手感正常(全行程约 1.3s) |
启动日志刷 clamped to be safe WARNING | 限速器追赶过程中的正常输出,到位即停 |
| 主臂居中时仿真臂偏几度 | 标定范围不对称导致的固定偏置——用 so101_leader_trim 自动微调(05) |
| 连接瞬间手臂突然运动 | 是设计行为:真机上扭矩并朝中点/主动臂姿态移动;保持手边留空间 |
| Ctrl-C 退出后手臂变软下坠 | 正常:断开时关闭扭矩,手扶一下 |
| 遥操/录制期间打字会驱动手臂 | 键盘监听全局且不吞键:任何窗口敲到映射键(含拼音字母)都会进按键队列。键盘模式遥操/录制时别打字;主动臂模式无此问题 |
录制类
| 现象 | 原因与解法 |
|---|---|
q 退出后,会话期间按的字母"一下子全吐在命令行" | Windows 控制台输入缓冲的积压回显;启动器已内置 drain_pending_keys() 清理(旧会话才有此现象) |
| 某回合 action span 全为 0 | 空录(人没动)——录前先动一下,或事后删除该回合 |
| 回合开头 1 秒误差很大 | 收敛段:开录瞬间从动臂还在初始位姿,主动臂已停在别处;把主动臂事前放到中位附近可避免 |
--dataset.root 配成父目录后数据集"不见了" | root 就是数据集目录本身;每场录制换一个新 root |
Esc 和 q 的区别 | q 只停录制;Esc 还会断开键盘遥操。两者都能干净收尾(已修复),习惯用 q |
保存时 ValueError: You must add one or several frames... 进程带着报错退出 | 回合间隙里多按了 →/n(最常见:保存+双路视频编码停顿几十秒、控制台看着像卡住,手痒连按了几次),标志滞留到下一回合开头被吃掉 → 0 帧空回合,上游保存空回合时崩溃(lerobot 已知边界)。已存回合不受影响、数据完好;重开会话续录即可。已加防护(2026-10-16):record.py 在每个回合开始时清掉间隙期滞留的 →/← 标志(录制中按键照常生效),保存前会打印 saving the episode + encoding videos now... 提示;回归测试 smoke_test.py [7] |
开录瞬间 KeyError: 'wrist'(带图像数据集) | 相机首帧还没渲染完就被录制循环读了观测;已修复(2026-10-16):机器人插件 connect() 现在会等第一帧画面就绪再返回 |
带视频的脚本报 BrokenProcessPool / Invalid argument: '<stdin>' | 视频编码走多进程池,子进程要靠文件路径重新导入入口模块——把录制脚本用 python - <<EOF(stdin)跑就会崩。把脚本存成真实 .py 文件再跑即可(真实入口 record.py 不受影响) |
保存回合时 SvtMalloc[fatal]: allocate memory failed ... av.error.MemoryError: [Errno 12] ... 'avcodec_open2(libsvtav1)',整场会话退出 | 上游默认编码器 libsvtav1 在双相机(wrist+top)两路编码并发打开时一次性大块内存分配失败(仿真+预览窗占用下更易触发;2026-10-16 实测踩过)。已修复:record.py 默认注入 --dataset.rgb_encoder.vcodec=h264(双路 h264 并发编码实测通过;显式传 vcodec 可覆盖)。已保存回合无损;崩溃可能在数据集目录留下 tmp*/ 和孤立 parquet(按 run2 的方式清理) |
录制中画面变卡顿(尤其按 → 之后),但操作其实没延迟 | 卡的是保存/编码窗口:编码进程默认吃满 CPU(双路视频并发),同时仿真线程还在渲染 5 个画面(核显更明显)。控制回路本身不受影响——以 cadence 数字为准(实测全程 29.97Hz、0 tick 超预算)。已缓解(2026-10-16):record.py 默认 --dataset.encoder_threads=2(每路编码限 2 线程);相机预览窗刷新降到 15Hz(--robot.preview_fps)。回合越短,保存窗口占比越大、感受越卡;想彻底消除停顿可用 --dataset.streaming_encoding=true(边录边编码,上游推荐,待实测) |
保存回合时编码器报内存分配失败、整场退出(svtav1 的 SvtMalloc、x264 的 malloc ... failed、avcodec_open2 报错都属此类) | 本机系统提交内存(commit)长期逼近上限(2026-10-16 实测 105.9GB / 119.7GB,已连续开机 29 天)。每次保存新起 2 个编码进程(各自装载 torch/av,commit 尖峰大),在悬崖边并发启动就会翻车。已缓解:record.py 现在给编码加失败自动重试一次(瞬时失败不再丢回合),保存期日志刷屏也已静音(av.logging.set_libav_level + HF 进度条)。根治 = 重启机器(清理长跑积累的 commit / 内核泄漏;用户态进程只占 27GB,其余在内核/驱动层,杀不掉);自查:Get-Counter '\Memory\Committed Bytes' vs '\Memory\Commit Limit' |
硬件类
| 现象 | 原因与解法 |
|---|---|
| COM 口号和上次不一样 | 串口号随插拔/换口变化,每次先列端口确认(03) |
| 只读检查提示缺舵机 | 接线/供电问题;先检查驱动板与线序,别急着标定 |
shoulder_lift 方向与直觉相反(仿真) | 该模型的正方向朝下,映射前先验符号(02) |
设计说明(为什么这样做)
- MuJoCo 会改写网格顶点数据:
<mesh>加载后,mjModel.mesh_vert存的是网格自身坐标系里的 顶点(原点被重定到顶点重心、轴向被重排),不再是文件原始坐标——直接用它算包围盒/套 CAD 尺寸会 得到错误结果(渲染显示不受影响)。要拿 CAD 真实几何,用原始文件解析(preview_mount.py/step_to_stl.py里的做法)。踩过一次:支架真实尺寸 54.3 × 35.0 × 75.0 mm。 - MuJoCo 相机的取景方向是它坐标系的 −Z:
<camera>元素不朝自身 +Z(镜头凸起方向)看。第一版 相机模块把镜头建在 +Z、元素朝向 identity → 画面实际从 PCB 背面"倒看"出去,镜头指向和画面方向 正好相反(调参时"转的方向和画面对不上"的根源;2026-10-16 用红/蓝板对照渲染测试定位)。 修复:相机元素绕 Y 转 180°(view.quat = RPY(0,180,0),preview_mount / adjust_camera / 机器人插件 三处统一);adjust_camera.py新增 "sim_cam live view" 实时画面窗口,调镜头所见即所得。 - 官方教程 MJCF 的夹爪是"鸟喙式"点接触爪:两片齿尖闭合到 ~2.3 mm 点接触、几乎没有可用夹持面。 系统物理实验(2026-10-16,数百组)结论:方块放在齿口附近任意位置,都会在约 100° 的闭合扫掠中被铲走/楔出,无法夹起(16–34 mm 方块均如此;机械行程与力矩本身正常)。禁止用"补碰撞片"的方式修——曾试过给两爪补齿板(能显著改善夹持),但那是真机上不存在的几何,训练出的策略会依赖它、造成 sim2real 失真,已撤除。正确的修法是用真机的爪部几何替换官方模型的爪(如 menagerie 的 SO-ARM101 或自家 CAD 重建),物理参数则应保持与真机一致。
- 官方默认接触参数太"软",会造成物理穿模:
solref时间常数默认 20 ms,快速/薄的接触 (方块落到薄爪面上、闭合扫掠)会"还没来得及产生力"就互相穿过——症状就是"方块直接穿过爪面掉下去"。 修复(2026-10-16):接触参数硬化——harden_mesh_contacts在编译后把全部网格碰撞体的solref硬化到 menagerie 齿面同款(0.01 s),方块接触同样处理。纯物理保真度修复,不添加任何几何。 - 仿真机器人已迁移到 mujoco_menagerie 的 SO-ARM100 模型(2026-10-16):原教程 zip 的 MJCF 是 运动学演示品、爪无法夹取;menagerie 模型按真机 CAD 处理——爪部有专用碰撞齿面与硬接触参数, 四齿位(浅→深)实测均能顶停+夹住+提起 34mm 方块。迁移要点:模型 vendored 在
assets/menagerie_so_arm100/(Apache-2.0,含 LICENSE);关节映射与单位符号见MODEL_JOINT(逐关节对照旧模型的世界运动测定;wrist_roll 符号待实机遥操复核);模型 Base 绕 Z 转 +90° 使其 工作正面朝 +x;支架改挂 Fixed_Jaw(6 号舵机)侧面(先解析搜索定位,2026-10-16 由用户对照实机 照片用adjust_mount.py --model menagerie手工微调定稿:[0.1, -0.7, 24.7]mm、RPY [0.34, -27.20, 89.51]°)。旧教程模型与工具保留未动,可随时对照。 - 为什么用 uv 项目环境而不是 conda:
.venv与项目同目录、由uv.lock锁定版本、删目录即回收, 和机器上的 conda 环境完全隔离;uv run从不往激活的 conda 里装东西。本机的lerobotconda 环境 指向的是另一个仓库副本(lerobot-main),两者互不干扰。 - 为什么插件都放在
examples/so101_mujoco/:通过官方注册机制接入(register_subclass), 零修改 lerobot 源码;升级上游仅需重新 sync。

