0 总体概览
总体目标:使用310P算力,实现机械臂抓取。本文档提供了一种较典型的VLA模型方案部署:π0
整体结构:参考开发套件介绍及组网
以千寻机器人为例,硬件系统框架如下图所示。
香橙派AI 套件基于USB3.0实现3个外部相机联接,算力拓展坞承载端侧推理用的模型,推理后通过ROS2与千寻机器人本体交互。
1 环境搭建
支持操作系统:Ubuntu22.04;OpenEuler
NPU:昇腾310P 香橙派AI Studio
表1 组件安装顺序表
组件安装顺序 | 版本 | 安装指导 |
1. Ubuntu | 22.04 | |
2. Firmware和Driver | 24.RC1 | |
3. CANN | 8.2.RC1 | |
4. Python | 3.10.xx | Ubuntu22.04 自带 |
5. Pytorch & torch_npu | 2.5.1 | |
6. aie_bench | 0.0.2 | |
7. ACL Lite | / |
2 π0
2.1 概述
为打造具备人类般物理环境适应性的 AI 系统,Physical Intelligence 公司研发通用机器人端到端VLA模型 π₀
数据训练基础:π₀的训练数据规模大且多元,涵盖 Open X Embodiment 开源机器人操作数据集、互联网规模的视觉 - 语言预训练数据,以及自主收集的 8 种不同机器人(如 UR5e、Franka、双机械臂 Trossen 等)完成灵巧任务的数据集,包含叠衣服、煮咖啡、整理餐桌等多种真实场景任务,旨在让模型形成对物理交互的通用认知;
独特架构设计:以 30 亿参数的预训练视觉 - 语言模型(VLM)为基础,继承互联网级语义理解与视觉识别能力。针对机器人需高频(每秒达 50 次)输出连续电机指令的需求,采用流匹配(扩散模型变体)技术,为预训练 VLM 增加连续动作输出功能,构建出视觉 - 语言 - 动作模型,可实时实现灵巧机器人控制;
功能与应用方式:能控制多种不同机器人,支持直接提示(依据指令即时执行任务)和微调(针对复杂场景优化,类似 LLMs 的后训练)两种应用方式,可完成叠衣服、清理餐桌、组装纸箱等多种高难度物理任务,部分任务(如从洗衣篮叠衣服)此前无机器人系统能成功实现。
官方jax源码实现:π0
2.2 实验目的
了解如何在昇腾310P上实现E2E VLA模型π0模型推理,有效输出双臂动作关节角,支持双臂操作;
2.3 模型输入输出
输入数据:
输入数据名(name) | 数据类型(dtype) | 数据大小(shape) | 数据排布格式 |
observation.images.head | float32 | [N,3,240,320] | N,C,H,W N - batch size C - channel H - height W - width |
observation.images.left_hand | float32 | [N,3,240,320] | N,C,H,W |
observation.images.right_hand | float32 | [N,3,240,320] N - batch size | N,C,H,W |
observation.state | float32 | [N, 16] | N, state_dim |
tasks | string | [N] | N |
输出数据:
输入数据名(name) | 数据类型(dtype) | 数据大小(shape) | 数据排布格式 |
action | float32 | [N, 16] | N, action_dim |
以上是模型推理的输入和输出,输出包括左臂关节、左夹爪、右臂关节、右夹爪。
输入源来自3个相机、任务语言指令及机器人状态,经过编码器、LLM及动作模型得到输出。
2.3 模型加载
2.3.1 步骤1:获取模型框架
Lerobot/π0模型(建议使用0.3.3版本的lerobot框架,lerobot 官网链接:github.com)
为加速推理,建议优化精度FP32→FP16,开源模型lerobot π0 文件调整如下:
在/src/lerobot/policy下的modeling_pi0.py和paligemma_with_expert.py中按ctrl+h,搜索torch.float32并替换为torch.float16
示例使用git拉取
git clone -b v0.3.3 https://github.com/huggingface/lerobot.git
conda create -n lerobot python=3.10 -y
conda activate lerobot
cd lerobot
pip install -e .
pip install pytest transformers==4.52.1 "numpy<2.0"
2.3.2 步骤2:获取lerobot π0模型
因为π0当前仅openpi和lerobot提供源码,推荐使用昇腾已适配的lerobot π0,可以通过huggingface手动下载lerobot π0 模型文件,也可以通过指令下载。
① 手动下载:https://huggingface.co/lerobot/pi0_base/tree/main
② 指令下载:
export HF_ENDPOINT=’https:///hf-mirror.com’
hf download lerobot/pi0_base --local-dir <模型存放路径>
- 下载paligemma-3b的tokenzier(只能手动下载)
下载链接:https://www.modelscope.cn/models/google/paligemma-3b-pt-224
从链接中下载added_tokens.json,special_tokens_map.json,tokenizer.json,tokenizer.model和tokenizer_config.json五个文件至同一个文件夹中
- 在开发板系统上修改lerobot中pi0初始化tokenizer的路径为下载的tokenizer的路径
在src/lerobot/policies/pi0文件夹的modeling_pi0.py文件中,源码固定tokenizer的来源为huggingface,使用时自动下载并加载tokenizer。
实际操作中由于网络问题需手动下载前中并修改路径至本地的tokenizer路径。
在PI0Policy类中的__init__()初始化方法中,将AutoTokenizer.from_pretrained("google/paligemma-3b-pt-224")改为
AutoTokenizer.from_pretrained("下载的tokenizer存放路径")
- 310P不支持bfloat16数据格式,需将代码中转换bfloat16格式的代码注释掉
bfloat16转换代码在src/lerobot/policies/pi0文件夹下的 modeling_pi0.py 和 paligemma_with_expert.py 两个文件中,
CTRL+F 搜索 bfloat16,在对应代码行按CTRL+/ 注释该行代码使其失效,如下是5处需注释掉的代码行
3 在线推理验证
基于MiniPC(Host主机)安装 LeRobot进行在线推理(pytorch在npu上的运行方式 → torch_npu)。使用lerobot框架加载pi0模型,迁移至npu上并推理,基于torch_npu进行在线推理,推理速度预计在430ms。
推理数据来源:① Intelrealsense 相机 x 3;② 本体状态,以千寻机器人双臂+夹爪 16自由度的向量;③ 输入指令,如叠衣服“fold shirt”指令
输出数据:动作指令,如千寻机器人双臂+夹爪16自由度向量
import torch
import torch_npu
from torch_npu.contrib import transfer_to_npu
from lerobot.policies.pi0.modeling_pi0 import PI0Policy
from lerobot
.configs.types import FeatureType, PolicyFeature
import time
def main():
model_path = "/path/to/model/weights"
dtype = torch.float16
# 修改model_path为模型权重路径,from_pretrained方法通过读取权重路径下的config.json文件的配置初始化模型架构,并使用model.safetensors赋予模型预训练权重
policy = PI0Policy.from_pretrained(model_path).to(device="npu")
policy.eval()
# 设置输出格式
policy.config.output_features = {
"action": PolicyFeature(
type=FeatureType.ACTION,
shape=(16,)
)
}
# 设置输入格式
policy.config.input_features = {
"observation.images.top": PolicyFeature(
type=FeatureType.VISUAL,
shape=(1, 3, 224, 224)
),
"observation.images.left_hand": PolicyFeature(
type=FeatureType.VISUAL,
shape=(1, 3, 224, 224)
),
"observation.images.right_hand": PolicyFeature(
type=FeatureType.VISUAL,
shape=(1, 3, 224, 224)
),
"observation.state": PolicyFeature(
type=FeatureType.STATE,
shape=(1, 16)
)
}
with torch.inference_mode():
# 验证模型加载与推理效果
for _ in range(10):
# pi0模型一次推理输出50个action,selection_action将推理得到的action存储至队列中,
# 每次调用从队列中取出一个action返回,直至队列为空再进行新一轮推理,
# 使用reset()方法清空队列使模型每次都进行推理
policy.reset()
observation = {
# 当前输入是随机生成的用于验证的伪数据,
# 输入三路相机:真机验证时可替换为真实图像,图像像素值需手动归一化至0~1之间再输入至模型中
"observation.images.head": torch.rand(1, 3, 224, 224, dtype=dtype).npu(),
"observation.images.left_hand": torch.rand(1, 3, 224, 224, dtype=dtype).npu(),
"observation.images.right_hand": torch.rand(1, 3, 224, 224, dtype=dtype).npu(),
# 输入本体状态:以机器人上半身16个自由度本体状态为例,包括双臂(7*2)+夹爪(1*2)
"observation.state": torch.randn(1, 16, dtype=dtype).npu(),
"task": ["Do something."]
}
start = time.perf_counter()
# 输出控制指令:基于observation输入,推理生成16个自由度输出(以千寻机器人上半身16自由度为例)
action = policy.select_action(observation)
# 输出速度统计
duration = time.perf_counter() - start
print(f"Time cost: {duration * 1000} ms.")
print(action)
if __name__ == '__main__':
main()输出效果上,基于香橙派EP模式,基于torch_npu推理π0模型(lerobot),预期单次推理时间 ~ 430ms