🧪 新教程持续更新中 · 从机械臂到传感器,跟着教程从零搭建
跳到主要内容

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 里装东西。本机的 lerobot conda 环境 指向的是另一个仓库副本(lerobot-main),两者互不干扰。
  • 为什么插件都放在 examples/so101_mujoco/:通过官方注册机制接入(register_subclass), 零修改 lerobot 源码;升级上游仅需重新 sync。