IB-Robot 工作区初始化深度指南:scripts/setup 模块化装配、Setup Profile 依赖作用域与 LeRobot 补丁分发机制
IB-Robot 工作区初始化深度指南:scripts/setup 模块化装配、Setup Profile 依赖作用域与 LeRobot 补丁分发机制
scripts/setup/ 是 IB-Robot(openEuler Embedded 面向具身智能场景的 AI 机器人执行框架)工作区初始化模块的集中承载目录,由 scripts/setup.sh 统一加载。本指南以该目录的说明文档为核心,结合仓库内实现代码,系统讲解 setup 脚本的模块职责划分、full / inference 两个 Setup Profile 的依赖作用域差异、cuda / cann / cpu 加速器轴的依赖落位策略,以及以 INDEX.yaml 为单一事实源的 LeRobot 补丁分发与多 tag 管理机制。读完本文,你将能够:正确选用 profile 与加速器参数完成一套 ROS 2 Humble 工作区的可复现初始化;理解 CANN Torch ABI 的覆盖顺序与约束保护原理;掌握如何预览、新增、升级 LeRobot 补丁栈并对失败模式进行快速定位。
一、scripts/setup 的定位与模块总览
IB-Robot 工作区的初始化是一个跨 OS、跨加速器、跨 Python 版本的大型装配过程,被拆分为若干单一职责的 shell 模块,全部挂在 scripts/setup.sh 之下。脚本开头通过 source 依次加载基础设施、子模块、rosdep、venv、benchmark 与平台探测模块:
source "${SCRIPT_DIR}/setup/common.sh"
source "${SCRIPT_DIR}/setup/submodules.sh"
source "${SCRIPT_DIR}/setup/ros_third_party.sh"
source "${SCRIPT_DIR}/setup/rosdep.sh"
source "${SCRIPT_DIR}/setup/python_venv.sh"
source "${SCRIPT_DIR}/setup/benchmark_profile.sh"
source "${SCRIPT_DIR}/setup/detect.sh"
source "${SCRIPT_DIR}/setup/lerobot_patches.sh"
各模块的职责如下表(与目录内 README.md 保持一致,路径均为仓库根目录相对路径):
| 文件 | 职责 |
|---|---|
| rosdep.sh | 包含虚拟环境的路径解析、早期建立以及 rosdepc/rosdep 初始化。 |
| submodules.sh | Git submodule 的状态探测和自动同步。 |
| python_venv.sh | 完整建立和配置最终的 Python 环境以及包安装,包括 colcon 及 NumPy 的版本锁定。 |
| benchmark_profile.sh | --with-benchmark 专属的 Ubuntu GPU 前置检查、PyTorch CUDA profile、Torch/TorchVision/TorchCodec 与 provider ABI 约束;要求 NVIDIA driver >= 560.28.03,不依赖本机 nvcc,并隔离 GraspGen。 |
| common.sh | 通用工具函数,例如日志格式、run_cmd 与 ask_yn、sudo 会话等基础设施提取。 |
| detect.sh | OS / 架构 / Python 探测;解析 IBR_HOST_* 与 IBR_LEROBOT_PROFILES。 |
| verify_env.sh | 独立环境验证库;暴露 verify_ros / verify_colcon / verify_numpy_compat / verify_lerobot / verify_tracing 及入口 verify_env。 |
platforms/<id>.sh |
各平台的包管理器、ROS 源、platform_lerobot_profiles() 默认值。 |
| lerobot_patches.sh | 驱动 git am 将精选的 lerobot 补丁栈应用到 libs/lerobot。 |
| lerobot_resolve_active.py | 从 INDEX.yaml 解析当前生效的 lerobot tag;并交叉校验对应 manifest.yaml。 |
| lerobot_filter_series.py | 读取 manifest.yaml + 主机事实,输出真正适用的补丁序列。 |
| tests/test_lerobot_filter.sh | 锁定 3 平台基准矩阵 + tag 绑定用例的回归 fixture。 |
| tests/test_cann_torch_versions.sh | 无需安装 CANN,验证 CANN 版本探测与 openEuler Torch ABI 选择。 |
| tests/test_openeuler_cv_bridge_abi.sh | 验证 openEuler 安装匹配 OpenCV 4.13 的 cv_bridge RPM。 |
英文原版见 README.en.md。
1.1 入口脚本的常用参数与环境变量
setup.sh 的 --help 输出给出了完整的参数面,常用的包括:
| 参数 | 说明 |
|---|---|
-y, --yes |
自动确认所有交互提示(缺失子模块自动初始化、已存在子模块更新默认跳过、fork 装配默认跳过)。 |
--profile NAME |
依赖作用域:full(默认)/ inference;也可用环境变量 IBR_SETUP_PROFILE 指定,优先级 --profile > IBR_SETUP_PROFILE > full。 |
--platform ID |
覆盖平台(OS)探测,已知平台为 ubuntu-22.04、openeuler-embedded-24.03、openharmony-5.1.0-musl。 |
--accel ID |
覆盖加速器探测(等价环境变量 ACCEL_OVERRIDE),已知加速器为 cuda / cann / cpu。当主机同时存在 NVIDIA GPU 与昇腾 NPU 时,setup 拒绝猜测,必须显式指定。 |
--lerobot-profiles CSV |
覆盖 lerobot 补丁 profile 选择(如 core,ros,hardware,ascend),优先级最高,会覆盖 IBR_LEROBOT_PROFILES 环境变量。 |
--with-benchmark |
安装 Ubuntu 22.04 x86_64 GPU LIBERO 评测 profile,固定经校验的 PyTorch/TorchCodec CUDA ABI。 |
--with-diagnostics |
仅为离线 speech_direction_report CLI 安装 Plotly/Matplotlib(运行时节点不需要)。 |
--only-patch |
跳过依赖与 venv 装配,只应用受管的 LeRobot 补丁栈(配合 IBR_LEROBOT_FORCE_REBUILD=1 可从记录的上游 base 重建)。 |
--skip-verify |
跳过最终的 ROS/Python 验证阶段。 |
脚本内部还内置了一批可覆盖的镜像/网络环境变量(源码默认值):SETUP_ROSDISTRO_INDEX_URL(清华 rosdistro 索引)、SETUP_ROSDEP_DEFAULT_SOURCES_URL(rosdep 源列表)、SETUP_PIP_INDEX_URL / SETUP_PIP_TRUSTED_HOST(华为云 PyPI 镜像)。此外 setup.sh 会设置 export PYTHONNOUSERSITE=1,与 build.sh / .shrc_local 保持一致,避免 pip install --user 遗留的 ~/.local 包让"安装时视图"与"构建/运行时视图"不一致。
1.2 环境预检
在进入主流程前,check_foreign_env() 会拒绝两类污染环境:激活中的 Conda 环境(与 ROS 2 依赖尤其是 Python 库存在已知冲突),以及指向非工作区 venv 的 VIRTUAL_ENV(脚本要求 deactivate)。这是保证"可复现装配"的第一道闸门。
二、Setup Profile:依赖范围参数化
setup.sh 通过 --profile <name>(或环境变量 IBR_SETUP_PROFILE)控制依赖安装范围:
| Profile | 用途 |
|---|---|
full(默认) |
完整开发工作区:硬件、遥操作、感知、抓取、语音、仿真与开发工具全量安装。 |
inference |
仅运行策略推理的最小运行时,面向端边协同推理验证主机。 |
inference profile 相对 full 的差异可以从 setup.sh 的 setup_profile_rosdep_paths() 与 python_venv.sh 的 full_profile 分支逐一印证:
- submodules:只初始化
libs/lerobot(跳过 LiDAR / bringup 子模块与 ROS 第三方 patch 栈)。对应 submodules.sh 中的submodules=("libs/lerobot")收窄逻辑,以及setup.sh主流程中跳过ensure_ros_third_party_patch_stacks的分支。 - rosdep:范围收窄到
ibrobot_msgs、tensormsg、inference_manifest、torch_models、inference_service、model_utils、dataset_tools;robot_config仍需构建(承载 SSOT YAML)但不参与 rosdep 解析,避免拉入 nav2 / slam_toolbox / gz / 相机 / 雷达等 bringup 依赖。这一收窄正是setup_profile_rosdep_paths()中inference分支返回的显式路径列表。 - Python venv:跳过
hardware.txt、WebPhone、dev-tools.txt、voice-tts、perception(SAM2 / Grounding-DINO / RAM++ / SigLIP2 与审计 wheel)、FullSubNet、GraspGen、pre-commit / gitlint 钩子;Ubuntu 侧只安装 requirements/inference.txt(ONNX 工具链),openEuler 侧仍安装完整的 OS 依赖,与 CANN 匹配的torch_npu由加速器轴安装;lerobot editable 安装去掉仅服务于遥操作的kinematicsextra(对应 python_venv.sh 中lerobot_extras的组装逻辑)。 - CANN Torch ABI:LeRobot 按自身声明正常安装(含所选 extras),随后由
accel-cann-8.1.txt(已真机验证的 2.5.1 三元组)或accel-cann-8.3.txt(官方配套的 2.8.0 三元组)按检测到的 CANN 版本覆盖,再由对应constraints-cann-<release>.txt经PIP_CONSTRAINT保护其后每一步 pip。requirements/openeuler-24.03.txt 只负责 OS 包。 - OpenCV / cv_bridge ABI:openEuler aarch64 同时安装
opencv>=4.13.0与ros-humble-cv-bridge>=3.2.1-2.oe2403;后者是针对 OpenCV 4.13 重新构建的 RPM。环境校验在工作区 Python 中执行 BGR/RGB 转换、非连续数组及 mono8/mono16/32FC1 往返(见 verify_env.sh 的verify_openeuler_cv_bridge_abi),不要求将 NumPy 1.x 兼容的cv2wheel 升到 4.13,也不拒绝后续兼容的 RPM 修订。 - 验证:跳过 tracing 校验(lttng / tracetools 属于全工作区诊断能力),并跳过 Ubuntu 平台的 tracing 工具安装钩子(
platform_post_install_rosdeps)。
端边协同推理验证主机的典型用法:
# 端边协同推理验证主机:
./scripts/setup.sh --yes --profile inference
./scripts/build.sh --packages-up-to inference_service
setup.sh 在结束时还会根据 profile 输出不同的完成提示:inference 会提示"Build the inference subset with: ./scripts/build.sh --packages-up-to inference_service"。
三、加速器轴依赖落位:cuda / cann / cpu
SETUP_ACCEL_ID(cuda / cann / cpu)由 detect.sh 中的 detect_accel_id() 探测设备得出(nvidia-smi -L / /dev/davinci[0-9]*,不看工具包),实现在 scripts/setup/accels/<id>.sh。这一点非常关键:仅安装了 CUDA/CANN 工具包用于交叉编译或模型转换的主机不会被判定为持有该加速器;同理,--accel 可以在设备缺失或未透传的主机上强制安装某个运行时。
探测函数的设计还考虑了细节场景:_accel_has_nvidia_gpu() 与 _accel_has_ascend_npu() 拆成两个独立函数以便测试以 shell 函数形式打桩;Ascend 侧探测 /dev/davinci[0-9]* 设备节点而非依赖 npu-smi 是否在 PATH 上(这是 Ascend 310P openEuler 板卡的实际情况)。当两个加速器设备同时存在时,setup 会报错并提示 Set ACCEL_OVERRIDE=cuda or ACCEL_OVERRIDE=cann,拒绝在两者间猜测。
下表是各加速器当前实际的依赖来源(即"现状",而非理想形态):
cuda |
cann |
cpu |
|
|---|---|---|---|
accel_requirements |
无(Torch 由 LeRobot 解析,再由 install_graspgen_torch_abi 固定到 2.7.1+cu126 以匹配预编译 pointnet2_ops wheel) |
accel-cann-8.1.txt / accel-cann-8.3.txt(按检测到的版本);其他已探到的版本不安装、setup 继续,报官方配套版本并在结束摘要提示手工配置;未探到 toolkit 则同样不装 |
无 |
accel_pip_constraints |
无 | constraints-cann-8.1.txt / constraints-cann-8.3.txt(按版本) |
无 |
accel_post_requirements |
无 | 8.1 / 8.3 卸载 torchcodec(aarch64 wheel 的 ABI 绑定在更新的 Torch 上,但其元数据不声明 torch 依赖,pip 察觉不到) |
无 |
accel_supports_torch_grasp |
是 | 否(pointnet2_ops 无昇腾构建) |
否 |
accel_verify_runtime |
无 | verify_cann_runtime_versions(8.1 / 8.3,按版本) |
无 |
各轴实现分别位于 accels/cuda.sh、accels/cann.sh 与 accels/cpu.sh。cann.sh 中 _cann_supported_abi_release() 用锚定版本族匹配(8.1|8.1.* 匹配 8.1 与 8.1.RC1,但不会误匹配 8.10;8.3 同理排除 8.30),并记录了昇腾官方为各 CANN 版本提供的 torch_npu 配套列表,用于给不支持版本的运维提示。
3.1 已知的不对称(勿误读为违规)
- CUDA 侧没有自己的 requirements 文件。CUDA Torch 来自 LeRobot 的依赖解析,再被
install_graspgen_torch_abi固定;该固定只为服务仓库内预编译的pointnet2_opswheel(无 nvcc 主机可走免编译路径;有 nvcc 则保留源码构建路径)。 requirements/manipulation.txt仍含spconv-cu120、torch-scatter等 CUDA 包。该文件只由install_graspgen_pip安装,而那一步受accel_supports_torch_grasp把关,因此实际只在cuda上执行;但它位于 OS 无关的文件里,尚未迁入accel-cuda*.txt。- CANN 8.1 与 8.3 自动安装,其余版本留给操作者。8.1 的三元组经 Ascend310P 真机验证;8.3 的三元组取自昇腾官方配套表(
torch_npu2.8.0 恒要求 torch 2.8.0)并核实了 cp310/cp311 的 aarch64 wheel 可用性,但尚未上真机。其他 CANN 版本一律不装 NPU 后端且 setup 继续(保留 LeRobot 已装的普通 Torch,不中止半装的工作区):一个 pin 不可能通吃多个版本(树内曾用的 2.10.0.post4 其实是 9.1.0 的配套)。此时 setup 结束摘要会提示"NPU 运行期待手工配置",引导操作者核对昇腾官方版本配套查询(CANN / Torch / torch_npu / torchvision 配套表),再使用工作区venv/bin/python -m pip安装(不要用系统 pip)。新增自动安装的版本需补齐三元组、约束文件和末尾校验三件套。 - 约束的启用时机在 LeRobot 之后。CANN 8.1 的 Torch 2.5.1 低于 LeRobot 声明的
>=2.7,提前启用会让 LeRobot 自身解析直接失败;因此顺序是"LeRobot 正常解析 → 覆盖 Torch → 启用约束保护其后所有步骤"。8.3 的 2.8.0 在声明区间内,无需例外,但沿用同一顺序。8.1 的覆盖是一个已验证的兼容例外,包元数据检查会报冲突。
从 python_venv.sh 的实现可以看到这条顺序被严格编排:先 install_lerobot_editable,随即 install_accel_requirements 覆盖 Torch,之后 accel_post_requirements 卸载 ABI 不兼容的 torchcodec,最后把 accel_pip_constraints 的输出追加进函数局部的 PIP_CONSTRAINT 并 export,保护其后每一次 pip 安装及 build 子进程。
四、CANN 依赖文件分工与 Torch ABI 覆盖顺序
CANN 轴的依赖被拆成"功能安装清单"与"版本约束"两类文件(均位于 requirements/ 下):
| 文件 | 使用方式 |
|---|---|
| accel-cann-8.1.txt | 加速器轴:CANN 8.1 的 Torch 2.5.1 / Torch-NPU 2.5.1 / TorchVision 0.20.1(真机验证),任何 OS 上检测到昇腾即安装。 |
| constraints-cann-8.1.txt | 版本约束,不是功能安装清单;通过函数局部的 PIP_CONSTRAINT 保护每次 pip 安装及子进程,安装结束后核验全部受保护版本。 |
| accel-cann-8.3.txt | 加速器轴:CANN 8.3 的 Torch 2.8.0 / Torch-NPU 2.8.0 / TorchVision 0.23.0(官方配套 + aarch64 wheel 核实,未上真机),任何 OS 上检测到昇腾即安装。 |
| constraints-cann-8.3.txt | 同 8.1 约束文件的职责,按 8.3 的三元组。 |
两个 profile 都先正常安装 LeRobot(含所选 extras),再由 accel-cann-<release>.txt 覆盖为对应 CANN 版本的配套版本,随后约束才生效并保护其后每一次 pip 安装。accel-cann-*.txt 内部用 -c constraints-cann-<release>.txt 自带约束,且显式 install(而非仅 constrain)约束文件中 pin 的每个版本——这一点有实测教训背书:约束只在不覆盖已装版本时才生效,早期曾出现真机 310P 上 transformers 停留在 LeRobot 的 5.5.4 而末尾校验失败的漂移,因此文件注释明确要求"Keep this list in step with the constraint file"。
Torch ABI、Transformers、tokenizers、safetensors、Pillow 和 OpenCV wheel 的版本约束与 profile 无关。NumPy 沿用仓库既有的最终 ROS ABI 恢复步骤,安装结束后固定并核验为 1.26.4;full 的 Rerun 元数据要求 NumPy 2,因此不将 NumPy 加入全过程约束。Transformers 5.3.0 是当前冻结精度的兼容选择,本轮不解决其已知安全公告;模型升级和其他模型兼容性验证另行安排。
末尾校验 verify_cann_runtime_versions() 会在 venv 内依次做两件事:其一,用 verify_cann_torch_abi 精确比对 torch / torch_npu / torchvision 三个包的 __version__ 是否等于该 CANN 版本要求的完整三元组;其二,逐行读取约束文件,用 importlib.metadata 校验每个被约束包的已装版本,最后额外确认 numpy==1.26.4。这一校验在 tests/test_cann_torch_versions.sh 中有完整的打桩测试覆盖(含"Transformers 漂移但 Torch 三元组正确也要拒绝""NumPy 未恢复成 1.26.4 也要拒绝"两条负向用例)。
4.1 torchcodec 的 ABI 陷阱
LeRobot 在 aarch64 上的基础依赖包含 torchcodec>=0.11.0,但该 wheel 的元数据不声明对 torch 的依赖,导致在 accel-cann-*.txt 把 Torch 降级后,pip 既不会主动卸载它,pip check 也保持安静——而其编译扩展实际 ABI 绑定在更新的 Torch 上,运行时会加载失败。因此 cann.sh 的 accel_post_requirements() 显式卸载 torchcodec,让 LeRobot 回退到由 av>=15,<16(PyAV)提供的解码路径。卸载时对 pip 命令做了严格约束:只允许把以 install 结尾的 runner 最后一个词换成 uninstall,避免用数组替换把解释器路径中含 "install" 子串的情况改坏。
五、LeRobot 补丁分发:多 tag 单一事实源与平台过滤
libs/lerobot 在 third_party/patches/lerobot/<tag>/ 下为每一个支持的上游 tag 提供一份补丁序列。决定哪个 tag 当前生效的单一事实源是 third_party/patches/lerobot/INDEX.yaml。当前树内布局为:active_tag: v0.6.0(supported_tags 指向 v0.6.0 目录、上游 commit 30da8e687a6dfc617fcd94afc367ac7071c376ce、约定分支 ibrobot/lerobot-v0.6.0-patched);v0.5.1 已被移入 archived_tags 保留作历史参考(仍承载着尚未移植到 v0.6.0 的完整训练特性补丁集)。
在生效的 tag 内,并非每个补丁都适用于所有主机。应用器通过 lerobot_filter_series.py 过滤原始 series.txt,按 v0.6.0/manifest.yaml 中独立声明的谓词为每个补丁打门:
python_min/python_max— 上下界区间(>=3.10、<3.11等),支持 PEP 440 风格的<=/>=/</>/==/!=/~=运算符;profiles— 与当前 profile 集合做交集。
例如 v0.6.0 的 0001 号补丁(Python 3.11 兼容)声明 python_max: "<3.12" 且 profiles 含 core, ros, hardware, dev, openeuler;0002/0003 进一步声明 python_max: "<3.11"——因此在默认 Python 3.11 的 openEuler 主机上 0002/0003 会被自动 SKIP。
当前 profile 集合按以下优先级解析(高优先在前),对应 detect.sh 的 resolve_lerobot_profiles():
setup.sh的--lerobot-profiles core,ascend,...CLI 参数(导出为IBR_LEROBOT_PROFILES_CLI);- 环境变量
IBR_LEROBOT_PROFILES=core,ascend,...; - 当前平台脚本的
platform_lerobot_profiles回调(如 openEuler 平台默认core,ros,hardware,openeuler); - 兜底默认
core,ros,hardware,dev(等价于 Ubuntu 22.04 基线)。
5.1 硬件上电常用覆盖
# 在桌面端验证推理一致性时,强制启用 Ascend NPU 补丁:
./scripts/setup.sh --yes --lerobot-profiles core,ros,hardware,ascend
# 把 OpenHarmony 设备当作 vanilla core 目标拉起:
./scripts/setup.sh --yes --lerobot-profiles core
# 显式跳过过滤(兜底逃生口——直接照搬 series.txt,
# 即便补丁与主机事实不匹配也会被应用):
IBR_LEROBOT_FORCE_UNFILTERED=1 ./scripts/setup.sh --yes
注意:IBR_LEROBOT_FORCE_UNFILTERED=1 只绕过平台过滤,不会绕过 INDEX.yaml 的 tag 解析与 libs/lerobot HEAD 绑定校验(_lerobot_validate_head_commit 在 shell 层无条件执行)。
5.2 诊断过滤器
应用器会打印 [CTX] python=X.Y profiles=... 审计行,以及每个补丁的 KEEP / SKIP 决策。要在不动 libs/lerobot 的前提下预览:
IBR_HOST_PYTHON_VERSION=3.11 \
IBR_LEROBOT_PROFILES=core,ros,hardware,openeuler \
python3 scripts/setup/lerobot_filter_series.py \
--manifest third_party/patches/lerobot/v0.6.0/manifest.yaml \
--series third_party/patches/lerobot/v0.6.0/series.txt
该命令把被保留的补丁文件名逐行写到 stdout,把每条 KEEP/SKIP 及其原因写到 stderr。lerobot_patches.sh 的 lerobot_compute_filtered_series() 会把这个审计输出镜像给用户(log_info 逐行展示),随后用过滤后的序列驱动 git am。
5.3 何时新增一个补丁
- 把补丁文件放到当前生效 tag 的目录下(
third_party/patches/lerobot/<active_tag>/;<active_tag>由INDEX.yaml.active_tag当前指向决定)。 - 追加到该 tag 的
series.txt。 - 在同目录的
manifest.yaml中注册一条patches[]条目,显式声明python_min/python_max/profiles谓词。先按已知最稳的窄集合声明;在更多平台验证后再放宽。 - 给 scripts/setup/tests/test_lerobot_filter.sh 加一条 fixture,让 pre-commit 钩子能挡住意外扩散范围。
六、多 tag 布局:INDEX.yaml 不变量与升级流程
INDEX.yaml 是 setup 脚本目标 lerobot tag 的单一事实源。每个 tag 拥有独立的补丁目录 + 一份 manifest.yaml,重新声明绑定,让解析器能在漂移时 fail-closed:
third_party/patches/lerobot/
├── INDEX.yaml # active_tag + supported_tags + archived_tags
├── v0.6.0/ # 当前 active tag,每个支持的 tag 一个目录
│ ├── manifest.yaml # 声明 lerobot_tag + lerobot_commit_range
│ ├── series.txt
│ └── 0001-*.patch ...
└── v0.7.0/ # (示例:未来 tag 并存添加)
└── ...
解析器 lerobot_resolve_active.py 在成功时向 stdout 输出一组 KEY=value 赋值(LEROBOT_TAG、LEROBOT_DIR、LEROBOT_BASE_COMMIT_MIN/MAX、LEROBOT_BRANCH_NAME、LEROBOT_MANIFEST、LEROBOT_SERIES、LEROBOT_UPSTREAM_REPO);lerobot_patches.sh 的 _lerobot_resolve_active() 刻意不 eval 输出,而是逐行严格白名单解析,作为纵深防御。解析器强制以下不变量:
| 不变量 | 失败模式 |
|---|---|
INDEX.active_tag 必须命中某个 supported_tags[] 条目 |
解析器退出 1,提示 "active_tag not found" |
生效条目的 dir 必须存在且包含 manifest.yaml + series.txt |
解析器退出 1,提示 "directory does not exist" |
INDEX.supported_tags[i].upstream_commit 必须等于 manifest.lerobot_commit_range.min |
解析器退出 1,提示 "INDEX vs manifest mismatch" |
INDEX.active_tag 不得出现在 archived_tags[] 中 |
解析器退出 1,提示 "archived tag" |
应用补丁前 libs/lerobot HEAD 必须落在 manifest.lerobot_commit_range 内 |
过滤器退出 1,提示 "HEAD not in commit_range" |
前四项在解析器内校验;最后一项在 lerobot_filter_series.py::_validate_head_commit 与 shell 层 _lerobot_validate_head_commit 双重执行——后者保证即使 IBR_LEROBOT_FORCE_UNFILTERED=1 短路了 Python 过滤,HEAD 绑定契约依然成立。
6.1 升级到新 lerobot tag
- 将
libs/lerobot子模块升到新的上游 tip,记下其 sha 为<NEW_COMMIT>。 - 创建
third_party/patches/lerobot/<NEW_TAG>/,把需要的补丁基于<NEW_COMMIT>rebase 一遍(不再适用的 drop / port)。撰写一份新的manifest.yaml:lerobot_tag: <NEW_TAG> lerobot_commit_range: min: <NEW_COMMIT> max: <NEW_COMMIT> # 当你接受上游 fast-forward 时再放宽 - 在
INDEX.yaml的supported_tags[]追加一条指向新目录的条目,upstream_commit一致,branch_name唯一(约定:ibrobot/lerobot-<NEW_TAG>-patched)。 - 把
INDEX.yaml.active_tag翻到<NEW_TAG>。可选:若旧 tag 不再维护,把它的条目从supported_tags[]移到archived_tags[]——归档项保留在树内便于审计,但解析器拒绝使用。 - 在 scripts/setup/tests/test_lerobot_filter.sh 加上新 tag 的 fixture 覆盖,并跑一遍回归套件;解析器与各平台过滤器用例都必须通过后才能提交。
6.2 失败模式速查
| 现象 | 原因 | 修复 |
|---|---|---|
lerobot_filter_series.py failed with exit 1,"PyYAML required but missing" |
venv 缺 python3-yaml |
在工作区 venv 内 pip install pyyaml,或设 IBR_LEROBOT_FORCE_UNFILTERED=1 跳过过滤。 |
failed to parse manifest,退出 1 |
manifest.yaml 格式错误 |
lint YAML;应用器按设计 fail-closed。 |
lerobot_resolve_active.py failed,"active_tag not found" |
INDEX.yaml.active_tag 与任何 supported_tags[] 条目都不匹配 |
添加条目,或修正 active_tag 值。 |
lerobot_resolve_active.py failed,"INDEX vs manifest mismatch" |
INDEX.supported_tags[i].upstream_commit 与 manifest.lerobot_commit_range.min 不一致 |
修改任一方使其同步;二者必须保持一致。 |
libs/lerobot HEAD ... is not in the manifest commit_range |
子模块 HEAD 已偏离当前 tag 声明的范围 | 要么 checkout 到期望 base,要么放宽 manifest range,要么新增一个 tag 目录并翻转 INDEX.yaml.active_tag。 |
| 工作树脏,应用器中止 | libs/lerobot 内有本地编辑 |
stash/commit 这些编辑,或设 IBR_LEROBOT_FORCE_REBUILD=1 丢弃并从头重建打过补丁的分支。 |
从 lerobot_patches.sh 的 ensure_lerobot_patch_stack_applied() 还可以看到幂等细节:当已存在的 patched 分支上补丁数与过滤后的期望数一致时直接返回"already applied";少于期望数时用 tail 截取剩余序列增量 git am;多于期望数(或 FORCE_REBUILD)时则从 base_commit 重建分支。若 libs/lerobot 处于一个完全不受管的分叉上(不在约定分支、HEAD 不在 commit_range),会打印详细诊断(当前 HEAD/分支/origin/版本行)并建议 IBR_LEROBOT_FORCE_REBUILD=1 ./scripts/setup.sh。
七、环境验证层:verify_env.sh 与回归测试
verify_env.sh 被 setup.sh 的 verify_setup() 在末尾 source 并调用 verify_env,提供了一组独立、可组合的验证函数:
| 函数 | 验证内容 |
|---|---|
verify_ros |
source ROS 2 setup 脚本后,用 venv Python import rclpy,确认 --system-site-packages 建出的 venv 能访问 ROS 2 包。 |
verify_rosdep |
检查 venv 内 rosdep --help 可运行。 |
verify_colcon |
以 PYTHONNOUSERSITE=1 python3 -m colcon --help 复现 build.sh 的调用方式。 |
verify_numpy_compat |
校验 Empy 3.x(em.BUFFERED_OPT,rosidl_adapter 需要)与 NumPy 处于 1.26.x 系列。 |
verify_lerobot |
venv 内 import lerobot 成功。 |
verify_pygraphviz / verify_openeuler_yaml_cpp_abi |
openEuler 平台专属:pygraphviz 可导入、/usr/lib64/libyaml-cpp.so.0.7 存在。 |
verify_openeuler_cv_bridge_abi |
openEuler aarch64:rpm -q opencv ros-humble-cv-bridge 后,在工作区 Python 内完成 cv_bridge 的 BGR/RGB 转换、非连续数组、mono8/mono16/32FC1 全往返断言。 |
verify_tracing |
full profile 下检查 lttng / babeltrace / ros2 trace / tracetools-analysis 等(inference 自动跳过)。 |
围绕这套装配逻辑,scripts/setup/tests/ 提供了三组无硬件回归测试,可在 pre-commit 与轻量 CI 容器中运行:
- test_lerobot_filter.sh:用环境变量 mock 主机事实(
IBR_HOST_PYTHON_VERSION、IBR_LEROBOT_PROFILES),锁定 Ubuntu 22.04 / py3.10、openEuler / py3.11、OpenHarmony / py3.12 三个平台的过滤矩阵,并覆盖 tag 绑定(HEAD==range.min 通过、HEAD 越界 fail-closed)、解析器多 tag 选择与 archived tag 拒绝、shell 层 validator 的负向用例。fixture 特意复用归档的 v0.5.1 manifest 以获得"内容完整"的稳定样本,树内 active_tag 则由"in-tree INDEX 解析到 v0.6.0"的单条基线断言覆盖。 - test_cann_torch_versions.sh:完全不打 pip,通过构造伪 CANN 目录(
version.cfg/ascend_toolkit_install.info/version.info)验证版本族探测(8.1.RC1 识别、8.10 不误匹配 8.1)、CANN 8.1/8.3 各自的 requirements 与 constraints 选择、空结果触发ACCEL_NPU_PENDING_MANUAL_CONFIG延迟状态、accel_post_requirements的 install→uninstall 词替换安全性、以及verify_cann_runtime_versions对 Transformers / NumPy 漂移的拒绝。 - test_openeuler_cv_bridge_abi.sh:验证 openEuler 安装匹配 OpenCV 4.13 的
cv_bridgeRPM。
八、实践建议
- 优先用
--yes起步、按需加参:./scripts/setup.sh --yes走full全量开发工作区;纯推理验证主机用--profile inference,可显著收窄 rosdep、子模块与 venv 安装面。 - 双加速器主机必须显式
--accel:setup 拒绝在 CUDA 与昇腾之间猜测,ACCEL_OVERRIDE是文档中建议的、不会失效的出路。 - CANN 版本不在 8.1/8.3 时不要恐慌:setup 不会中止半装工作区,但 NPU 后端不可用;按结束摘要指引核对昇腾配套表,用
venv/bin/python -m pip手工安装匹配的三元组即可。 - 新增/升级 lerobot 补丁时始终同步三处:补丁文件 +
series.txt+manifest.yaml谓词,再补一条回归 fixture;INDEX.yaml的任何漂移都会被解析器 fail-closed 拦下。
本文涉及的所有模块、脚本、配置与测试均可在当前仓库对应路径下直接查阅,作为二次开发的起点。