Skip to main content

ONNX 部署指南

本文档介绍 ACT 和 SmolVLA 策略模型在 SpacemiT K3 开发板上的 ONNX 部署方法,覆盖模型导出、量化、Python 推理、C++ 推理、离线验证和 SO-101 真机运行。

1. 方案概述

ACT 策略以多路相机图像和机械臂关节状态为输入,输出一段动作序列(action chunk)。ACT ONNX 部署使用单个完整图,完整数据通路如下:

ACT ONNX pipeline

SmolVLA 策略以多路相机图像、机械臂关节状态和任务文本为输入,输出 action chunk。SmolVLA ONNX 部署使用 4 个子图串联,完整数据通路如下:

SmolVLA ONNX pipeline

ONNX 图只负责神经网络前向推理。以下步骤由 Python / C++ 运行时在图外完成:

  • 图像、关节状态归一化;
  • SmolVLA 任务文本 token 和 KV cache 管理;
  • action 反归一化;
  • SO-101 舵机标定值与 LeRobot 动作空间转换;
  • action queue 播放。

2. 硬件清单

硬件说明
x86 主机推荐用于 PyTorch checkpoint 导出 ONNX、模型量化
SpacemiT K3 开发板推理平台
SO-101 Follower 机械臂通过 USB 串口控制 Feetech 总线舵机
俯视相机 top camera示例设备号为 /dev/video15
手腕相机 wrist camera示例设备号为 /dev/video13

3. 场景一:ACT 部署指南

3.1 环境搭建

3.1.1 获取代码

K3 板端示例路径以 ~/spacemit_robot 为例:

cd ~
mkdir -p spacemit_robot
cd spacemit_robot

repo init -u https://github.com/spacemit-robotics/manifest.git \
-b main -m default.xml \
--repo-url=https://gitee.com/spacemit-robotics/git-repo
repo sync -j4
repo start robot-dev --all

进入 ACT / SmolVLA ONNX 示例目录:

cd ~/spacemit_robot/components/thirdparty/lerobot/examples/onnx_inference

3.1.2 K3 C++ 环境

安装 SpacemiT ORT SDK:

sudo apt-get update
sudo apt-get install -y spacemit-onnxruntime python3-spacemit-ort

安装后应能找到以下文件:

/usr/include/spacemit_ort_env.h
/usr/lib/libonnxruntime.so
/usr/lib/libspacemit_ep.so

如果没有安装系统包,也可以单独下载并解压 SpaceMIT ORT SDK,然后在 CMake 时指定外部路径:

cmake .. -DSPACEMIT_ORT_DIR=/path/to/spacemit-ort-sdk

该路径下需要包含:

/path/to/spacemit-ort-sdk/include/spacemit_ort_env.h
/path/to/spacemit-ort-sdk/lib/libonnxruntime.so
/path/to/spacemit-ort-sdk/lib/libspacemit_ep.so

如果直接运行 act_benchmarkact_evaluate 时使用外部 SDK,还需要:

export LD_LIBRARY_PATH=/path/to/spacemit-ort-sdk/lib:$LD_LIBRARY_PATH

3.1.3 K3 Python 环境

Python 真机入口依赖 LeRobot、Feetech 驱动、safetensors 和 SpaceMIT EP。复用 Python 3.12 虚拟环境 ~/.lerobot-venv。若尚未安装 uv,先参考《真机训练推理》完成安装。

K3 运行环境不安装 xslimxslim 依赖 opencv-python,与 LeRobot 使用的 opencv-python-headless 共享 cv2 目录并产生文件冲突。模型量化在 x86 主机执行。

source "$HOME/.local/bin/env"
uv venv ~/.lerobot-venv --python 3.12 --seed --allow-existing
source ~/.lerobot-venv/bin/activate
python --version
python -m pip --version

cd ~/spacemit_robot/components/thirdparty/lerobot/examples/onnx_inference
python -m pip install -r requirements-act.txt

python -m pip list | grep '^opencv'
python -m pip check

--seed 会在新环境中预装 pip,--allow-existing 会保留现有环境中的软件包。python --version 应输出 Python 3.12。python -m pip 始终使用当前虚拟环境的 pip,避免 pip3 误用系统 Python 并触发 externally-managed-environment。OpenCV 软件包列表中只应包含 opencv-python-headless

3.1.4 x86 导出与量化环境

模型导出建议在有完整 PyTorch / LeRobot 环境的 x86 主机执行:

conda create -n lerobot-venv python=3.12 -y
conda activate lerobot-venv

cd ~/spacemit_robot/components/thirdparty/lerobot/examples/onnx_inference
python -m pip install -r requirements-act-pc.txt

requirements-act-pc.txt 已包含 ACT 导出、ONNX 对比和 INT8 动态量化所需依赖。

3.2 前置准备

3.2.1 PyTorch 模型生成

参考《真机训练推理》章节,完成 ACT 模型的数采和训练,并将训练好的 ACT checkpoint 放到:

~/spacemit_robot/components/thirdparty/lerobot/examples/onnx_inference/models/pytorch/act/checkpoints/100000/pretrained_model/
├── config.json
├── model.safetensors
├── policy_preprocessor.json
├── policy_preprocessor_step_3_normalizer_processor.safetensors
├── policy_postprocessor.json
└── policy_postprocessor_step_0_unnormalizer_processor.safetensors

3.2.2 ONNX 导出

在 x86 主机执行:

python tools/act_pytorch_to_onnx.py \
--checkpoint models/pytorch/act/checkpoints/100000/pretrained_model \
--output-dir models/onnx/act-fp32

导出产物:

models/onnx/act-fp32/act.onnx

模型输入输出:

名称Shape说明
images(B, n_cam, 3, H, W)已归一化图像,float32
state(B, state_dim)已归一化关节状态,float32
actions(B, chunk_size, action_dim)已归一化动作序列,float32

下载基于《真机训练推理》导出和量化的模型,可复现本文的基准测试。

3.2.3 精度验证

3.2.3.1 仅运行 ONNX

K3 或 x86 均可执行。K3 上可打开 SpaceMIT EP:

python tools/compare_act_onnx.py \
--model-dir models/onnx/act-fp32 \
--checkpoint models/pytorch/act/checkpoints/100000/pretrained_model \
--use-spacemit-ep \
--ep-threads 8 \
--ep-affinity "8;9;10;11;12;13;14;15"
3.2.3.2 与 PyTorch 对比

在有 PyTorch / LeRobot 的机器上执行:

python tools/compare_act_onnx.py \
--model-dir models/onnx/act-fp32 \
--checkpoint models/pytorch/act/checkpoints/100000/pretrained_model \
--cpu \
--with-torch

也可以在 x86 上保存参考输出,再拷贝到 K3 对比:

# X86 生成输出
python tools/compare_act_onnx.py \
--model-dir models/onnx/act-fp32 \
--checkpoint models/pytorch/act/checkpoints/100000/pretrained_model \
--cpu \
--with-torch \
--save-ref /tmp/act_ref.npy

# K3 运行对比
python tools/compare_act_onnx.py \
--model-dir models/onnx/act-fp32 \
--checkpoint models/pytorch/act/checkpoints/100000/pretrained_model \
--use-spacemit-ep \
--ep-threads 8 \
--ep-affinity "8;9;10;11;12;13;14;15" \
--ref-npy /tmp/act_ref.npy

3.2.4 INT8 量化

在 x86 主机使用 xslim 动态量化生成 INT8 模型:

mkdir -p models/onnx/act-int8

python -m xslim \
-i models/onnx/act-fp32/act.onnx \
-o models/onnx/act-int8/act.q.onnx

xslim 2.x 未指定配置文件且不传 --fp16 时,默认执行 INT8 动态量化。

量化产物:

models/onnx/act-int8/act.q.onnx

3.3 部署推理

3.3.1 C++ 部署

3.3.1.1 导出 C++ 运行所需统计参数

act_evaluate 需要归一化参数和 SO-101 标定参数:

python tools/export_norm_stats.py \
--checkpoint models/pytorch/act/checkpoints/100000/pretrained_model \
--output models/onnx/act-fp32/act_norm_stats.txt
3.3.1.2 生成离线测试输入
python tools/make_act_test_inputs.py \
--model-dir models/onnx/act-fp32 \
--stats models/onnx/act-fp32/act_norm_stats.txt \
--out-dir cpp/inputs

生成文件:

cpp/inputs/images.npy
cpp/inputs/state_deg.npy
cpp/inputs/ref_action0.txt
3.3.1.3 离线测试构建
cd ~/spacemit_robot/components/thirdparty/lerobot/examples/onnx_inference/cpp
rm -rf build && mkdir build && cd build
cmake ..
make -j$(nproc)

如果使用外部 SDK:

cmake .. -DSPACEMIT_ORT_DIR=/path/to/spacemit-ort-sdk
make -j$(nproc)
3.3.1.4 离线测试
cd ~/spacemit_robot/components/thirdparty/lerobot/examples/onnx_inference/cpp/build

./act_benchmark ../../models/onnx/act-int8/act.q.onnx \
--images-npy ../inputs/images.npy \
--state-npy ../inputs/state_deg.npy \
-s -t 8 -a "8;9;10;11;12;13;14;15" \
-n 20 -w 3
3.3.1.5 真机运行

真机运行需要启用 ACT_ROBOT_HW,并确保能访问 components/peripherals/motor

cd ~/spacemit_robot/components/thirdparty/lerobot/examples/onnx_inference/cpp
rm -rf build && mkdir build && cd build
cmake .. -DACT_ROBOT_HW=ON
make act_evaluate -j$(nproc)

运行:

cd ~/spacemit_robot/components/thirdparty/lerobot/examples/onnx_inference/cpp/build

./act_evaluate ../../models/onnx/act-int8/act.q.onnx \
--stats ../../models/onnx/act-fp32/act_norm_stats.txt \
--port /dev/ttyACM0 --camera top=15 --camera wrist=13 \
--fps 30 --episode-time 180 \
-s -t 8 -a "8;9;10;11;12;13;14;15"

参数解释:

参数说明默认值
--statsact_norm_stats.txt 路径必填
--portSO-101 串口/dev/ttyACM0
--camera NAME=IDX相机名到 /dev/videoIDX 的映射
--fps控制循环频率30
--episode-time单次运行时长,单位秒180
-s, --spacemit启用 SpaceMIT EP关闭
-t, --threadsEP / ORT 线程数4
-a, --affinityEP 线程亲和性
--dry-run只算动作,不下发电机关闭
--verbose打印每步状态和动作关闭

3.3.2 Python 部署

3.3.2.1 离线测试
source ~/.lerobot-venv/bin/activate
cd ~/spacemit_robot/components/thirdparty/lerobot/examples/onnx_inference

python python/act_benchmark.py \
--model-dir models/onnx/act-int8 \
--checkpoint models/pytorch/act/checkpoints/100000/pretrained_model \
--use-spacemit-ep \
--ep-threads 8 \
--ep-affinity "8;9;10;11;12;13;14;15" \
--warmup 5 \
--iters 20
3.3.2.2 真机运行
source ~/.lerobot-venv/bin/activate
cd ~/spacemit_robot/components/thirdparty/lerobot/examples/onnx_inference

python python/act_evaluate.py \
--model-dir models/onnx/act-int8 \
--checkpoint models/pytorch/act/checkpoints/100000/pretrained_model \
--port /dev/ttyACM0 \
--camera top=15 \
--camera wrist=13 \
--use-spacemit-ep \
--ep-threads 8 \
--ep-affinity "8;9;10;11;12;13;14;15" \
--episode-time 180

3.4 效果展示

如图是 ACT Python 真机运行的效果,对比 PyTorch 版本,由于 Chunk 推理时延的大幅降低,动作块之间衔接流畅了很多。

act-onnx

4. 场景二:SmolVLA 部署指南

SmolVLA ONNX 部署包含 FP32 导出、FP16 量化、FP16 图修复、数值对比和真机运行。K3 真机部署推荐使用 C++ FP16 图修复版模型;Python 路径用于 FP32 离线验证和调试。

4.1 环境搭建

K3 Python 推理和数值对比复用 Python 3.12 虚拟环境 ~/.lerobot-venv。以下命令会通过 uv 补齐 pip,并保留环境中已经安装的软件包:

K3 运行环境不安装 xslim。SmolVLA 的 FP16 转换和图修复在 x86 主机执行。

source "$HOME/.local/bin/env"
uv venv ~/.lerobot-venv --python 3.12 --seed --allow-existing
source ~/.lerobot-venv/bin/activate
python --version
python -m pip --version

cd ~/spacemit_robot/components/thirdparty/lerobot/examples/onnx_inference
python -m pip install -r requirements-smolvla.txt

python -m pip list | grep '^opencv'
python -m pip check

python --version 应输出 Python 3.12。不要使用系统 pip3。OpenCV 软件包列表中只应包含 opencv-python-headless

x86 导出、量化和数值对比环境:

conda create -n lerobot-venv python=3.12 -y
conda activate lerobot-venv

cd ~/spacemit_robot/components/thirdparty/lerobot/examples/onnx_inference
python -m pip install -r requirements-smolvla-pc.txt

C++ 真机入口需要 K3 上安装构建依赖:

sudo apt-get update
sudo apt-get install -y build-essential cmake pkg-config libopencv-dev

4.2 前置准备

进入 ONNX 示例目录:

cd ~/spacemit_robot/components/thirdparty/lerobot/examples/onnx_inference

可直接下载已发布的 SmolVLA 2 路相机模型用于复现:

mkdir -p models/pytorch models/onnx /tmp/smolvla_models

curl -L \
https://archive.spacemit.com/spacemit-ai/model_zoo/vla/smolvla/models/pytorch/so101_smolvla_pick_green_cube_2cam.tar.gz \
-o /tmp/smolvla_models/so101_smolvla_pick_green_cube_2cam.tar.gz
curl -L \
https://archive.spacemit.com/spacemit-ai/model_zoo/vla/smolvla/models/onnx/so101_smolvla_pick_green_cube_2cam_100k_fp32.tar.gz \
-o /tmp/smolvla_models/so101_smolvla_pick_green_cube_2cam_100k_fp32.tar.gz
curl -L \
https://archive.spacemit.com/spacemit-ai/model_zoo/vla/smolvla/models/onnx/so101_smolvla_pick_green_cube_2cam_100k_fp16_surgeried.tar.gz \
-o /tmp/smolvla_models/so101_smolvla_pick_green_cube_2cam_100k_fp16_surgeried.tar.gz

tar -xzf /tmp/smolvla_models/so101_smolvla_pick_green_cube_2cam.tar.gz -C models/pytorch
tar -xzf /tmp/smolvla_models/so101_smolvla_pick_green_cube_2cam_100k_fp32.tar.gz -C models/onnx
tar -xzf /tmp/smolvla_models/so101_smolvla_pick_green_cube_2cam_100k_fp16_surgeried.tar.gz -C models/onnx

ln -sfn so101_smolvla_pick_green_cube_2cam_100k_fp32 models/onnx/smolvla-fp32
ln -sfn so101_smolvla_pick_green_cube_2cam_100k_fp16_surgeried models/onnx/smolvla-fp16-surgeried
mkdir -p models/pytorch/smolvla/checkpoints/100000
ln -sfn ../../../so101_smolvla_pick_green_cube_2cam/checkpoints/100000/pretrained_model \
models/pytorch/smolvla/checkpoints/100000/pretrained_model

K3 上运行 FP16 图修复版模型时需要补丁版 SpacemiT ORT SDK:

mkdir -p /tmp/smolvla_models

curl -L \
https://archive.spacemit.com/spacemit-ai/model_zoo/vla/smolvla/spacemit-ort-sdk/spacemit-ort.riscv64.2.0.4_yyx.tar.gz \
-o /tmp/smolvla_models/spacemit-ort.riscv64.2.0.4_yyx.tar.gz

tar -xzf /tmp/smolvla_models/spacemit-ort.riscv64.2.0.4_yyx.tar.gz -C ~

[!NOTE]

SmolVLA FP16 图修复版需要在补丁版 SpacemiT ORT SDK 上运行。若使用系统 SpaceMIT EP、普通 ONNX Runtime 或 CPU 运行 FP16,可能出现数值漂移或溢出。Python 调试使用 FP32 模型。

4.3 导出 ONNX FP32

如果使用自行训练的 SmolVLA checkpoint,将 checkpoint 放到:

~/spacemit_robot/components/thirdparty/lerobot/examples/onnx_inference/models/pytorch/smolvla/checkpoints/100000/pretrained_model/
├── config.json
├── model.safetensors
├── policy_preprocessor.json
├── policy_postprocessor.json
└── train_config.json

在 x86 主机执行导出:

python tools/export_smolvla_4model_to_onnx.py \
--checkpoint models/pytorch/smolvla/checkpoints/100000/pretrained_model \
--output-dir models/onnx/smolvla-fp32 \
--num-cameras 2 \
--validate-load

导出产物:

models/onnx/smolvla-fp32/
├── vision_encoder.onnx
├── connector.onnx
├── prefill_lm.onnx
└── denoise_step.onnx

--num-cameras 表示 ONNX 模型的相机槽位数,应与训练时使用的相机数量或 empty camera 配置一致。例如 2 路相机训练时设置为 2,3 路相机训练时设置为 3

4.4 FP16 量化与图修复

先将 FP32 ONNX 转换为 FP16:

python tools/convert_smolvla_fp32_to_fp16.py \
--input-dir models/onnx/smolvla-fp32 \
--output-dir models/onnx/smolvla-fp16

直接将整个 SmolVLA 图转成 FP16 后,部分视觉注意力、归一化和索引更新相关子图容易出现数值漂移。尤其是 prefill_lmdenoise_step 中的 RMSNorm 子图会参与语言模型和扩散去噪的关键计算,误差会在多步 denoise 中累积,最终可能表现为 action 异常、抓取失败甚至 FP16 溢出。因此需要在 FP16 模型上执行图修复,保留主要算子的 FP16 加速,同时把敏感子图改成更稳定的形式。

执行 FP16 图修复:

python tools/surgery_smolvla_fp16.py \
--input-dir models/onnx/smolvla-fp16 \
--output-dir models/onnx/smolvla-fp16-surgeried

当前图修复内容包括:

  • vision_encoder:将 self-attention 核心融合为 VisionSelfAttnNHWC,并将 MLP 中的 GELU 近似子图替换为 ONNX Gelu(approximate="tanh")
  • prefill_lm / denoise_step:将 RMSNorm 子图中的关键计算提升为 FP32,并把 scatter 写入算子降解为等价子图;
  • 保持 connector 等主要前向计算仍为 FP16,以保留 K3 上的推理速度收益。

图修复后的目录仍包含 4 个 ONNX 子图:

models/onnx/smolvla-fp16-surgeried/
├── vision_encoder.onnx
├── connector.onnx
├── prefill_lm.onnx
└── denoise_step.onnx

4.5 精度验证

在 x86 主机上使用 CPU 对比 FP32 与 FP16 图修复版输出:

python tools/compare_smolvla_onnx.py \
--fp32-dir models/onnx/smolvla-fp32 \
--fp16-dir models/onnx/smolvla-fp16-surgeried \
--cpu \
--num-cameras 2 \
--denoise-steps 10

K3 上的 FP16 验证需要同时加载补丁版 libonnxruntime.solibspacemit_ep.so,因此使用 4.8.2 节的 C++ EP204 数值检查作为 K3 验收步骤。不要在 Python 进程中通过 --spacemit-ort-dir 加载补丁版 SDK。

4.6 导出 C++ 运行时元数据

C++ 真机入口需要任务文本、归一化参数、相机顺序、action chunk 参数和 SO-101 标定。首次部署或更换机械臂后,先校准 follower:

lerobot-calibrate \
--robot.type=so101_follower \
--robot.port=/dev/ttyACM0 \
--robot.id=my_awesome_follower_arm

确认标定文件存在:

ls ~/.cache/huggingface/lerobot/calibration/robots/so_follower/my_awesome_follower_arm.json

导出 smolvla_runtime.txt

python tools/export_smolvla_runtime.py \
--checkpoint models/pytorch/smolvla/checkpoints/100000/pretrained_model \
--output models/onnx/smolvla_runtime.txt \
--task "Place the green cube into the box" \
--num-cameras 2 \
--calibration ~/.cache/huggingface/lerobot/calibration/robots/so_follower/my_awesome_follower_arm.json
  • --task 需要与训练和部署任务一致。
  • 在线推理时,--camera 名称需要与 checkpoint 的图像 key 后缀一致,例如 observation.images.top 对应 topobservation.images.wrist 对应 wrist

4.7 Python 推理

Python SmolVLA 路径使用 FP32 模型进行离线验证或 dry-run 调试。K3 上运行 FP32 模型时需要传入 --cpu-denoisedenoise_step 使用 CPU EP,其余 3 个子图使用 SpaceMIT EP。FP16 图修复版模型通过 C++ 路径部署,因为 FP16 数值正确性依赖补丁版 SpacemiT ORT SDK 和对应 EP 配置。

运行前先确认以下文件存在:

cd ~/spacemit_robot/components/thirdparty/lerobot/examples/onnx_inference

ls models/onnx/smolvla-fp32/vision_encoder.onnx
ls models/onnx/smolvla-fp32/connector.onnx
ls models/onnx/smolvla-fp32/prefill_lm.onnx
ls models/onnx/smolvla-fp32/denoise_step.onnx
ls models/pytorch/smolvla/checkpoints/100000/pretrained_model/config.json

4.7.1 离线基准测试

离线基准测试不连接机械臂和相机,使用合成 observation 运行完整 4-model pipeline。该模式用于验证模型加载、EP 是否可用,以及统计 full-inference 延迟。

source ~/.lerobot-venv/bin/activate
cd ~/spacemit_robot/components/thirdparty/lerobot/examples/onnx_inference

python python/smolvla_evaluate.py \
--no-robot --iters 1 \
--model-dir models/onnx/smolvla-fp32 \
--checkpoint models/pytorch/smolvla/checkpoints/100000/pretrained_model \
--use-spacemit-ep \
--cpu-denoise \
--ep-threads 8 --ep-affinity "8;9;10;11;12;13;14;15" \
--warmup 1 \
--denoise-steps 10 \
--n-action-steps 50 \
--infer-every-tick \
--print-actions

关键参数:

参数说明默认值
--no-robot使用合成 observation,不连接机械臂和相机关闭
--model-dirSmolVLA fp32 ONNX 目录models/onnx/smolvla-fp32
--checkpointSmolVLA pretrained_model 目录models/pytorch/smolvla/checkpoints/100000/pretrained_model
--use-spacemit-ep使用 SpaceMIT EP默认开启
--cpu强制使用 CPU EP,用于诊断关闭
--cpu-denoiseFP32 denoise_step 使用 CPU,其余子图仍使用 SpaceMIT EP关闭
--warmup正式计时前的合成输入 warmup 次数0
--infer-every-tick每轮都完整推理,用于测 full-inference 延迟关闭
--denoise-steps每次推理调用 denoise_step 的次数10
--n-action-steps每次推理后放入 action queue 的动作步数读取 checkpoint

不加 --infer-every-tick 时,脚本会复用 action queue 中尚未消费的动作,后续循环可能不重新跑完整模型,因此不能用来统计 full-inference 延迟。

4.7.2 dry-run 调试

dry-run 会连接真实机械臂和相机、读取真实 observation,但不会下发动作给电机。首次上机建议先用 --max-iters 1 检查相机、串口、模型输出和 action 数值范围。

python python/smolvla_evaluate.py \
--dry-run --max-iters 1 \
--port /dev/ttyACM0 \
--camera top=/dev/video15 --camera wrist=/dev/video13 \
--camera-fps 30 --camera-fourcc MJPG \
--use-spacemit-ep \
--cpu-denoise \
--ep-threads 8 --ep-affinity "8;9;10;11;12;13;14;15" \
--model-dir models/onnx/smolvla-fp32 \
--checkpoint models/pytorch/smolvla/checkpoints/100000/pretrained_model \
--denoise-steps 10 \
--n-action-steps 50 \
--print-actions

dry-run 常用检查项:

  • 相机路径是否正确,例如 top=/dev/video15wrist=/dev/video13
  • --camera 名称是否与训练数据和 smolvla_runtime.txt 的图像 key 后缀一致;
  • 第一帧 action 是否有限值,是否明显超出机械臂动作范围;
  • --denoise-steps--n-action-steps 是否与后续 C++ 真机部署配置一致。

4.8 C++ 真机部署

C++ 路径是 SmolVLA 在 K3 上的推荐部署方式。默认运行 models/onnx/smolvla-fp16-surgeried,并通过 run_smolvla_robot_pipeline.sh 使用补丁版 SpacemiT ORT SDK、EP 线程和绑核配置。

4.8.1 构建

构建前确认补丁版 SDK 已解压,并且模型和 runtime metadata 已准备好:

ls ~/spacemit-ort.riscv64.2.0.4_yyx/lib/libonnxruntime.so
ls ~/spacemit-ort.riscv64.2.0.4_yyx/lib/libspacemit_ep.so
ls ~/spacemit_robot/components/thirdparty/lerobot/examples/onnx_inference/models/onnx/smolvla-fp16-surgeried/
ls ~/spacemit_robot/components/thirdparty/lerobot/examples/onnx_inference/models/onnx/smolvla_runtime.txt

构建 SmolVLA C++ 真机入口:

cd ~/spacemit_robot/components/thirdparty/lerobot/examples/onnx_inference/cpp
./build_smolvla_robot_cpp.sh EP204

构建产物:

cpp/build_smolvla_robot/smolvla_robot_pipeline

4.8.2 K3 FP16 数值检查

先使用合成输入运行无硬件检查。该命令不打开机械臂和相机,也不下发电机动作:

cd ~/spacemit_robot/components/thirdparty/lerobot/examples/onnx_inference/cpp

DRY_RUN=1 WARMUP=1 ./run_smolvla_robot_pipeline.sh \
--warmup-only \
--debug-numerics

检查日志中 4 个 ONNX 子图均成功创建 SpaceMIT EP session,10 次 denoise_stepbad 计数均为 0

4.8.3 dry-run 安全检查

真机执行前先进行 dry-run。该模式会打开相机和机械臂、读取真实状态和图像,但不会下发动作:

./run_smolvla_robot_pipeline.sh \
--port /dev/ttyACM0 \
--camera top=15 \
--camera wrist=13 \
--dry-run \
--max-iters 1 \
--n-action-steps 25 \
--print-actions

dry-run 通过后,再进入基准测试或真机运行。

4.8.4 完整推理基准测试

运行完整推理基准测试时打开 --infer-every-tick,避免 action queue 复用动作。该模式每个控制周期都会重新采集 observation 并执行完整 4-model pipeline,用于统计真实推理耗时。

cd ~/spacemit_robot/components/thirdparty/lerobot/examples/onnx_inference/cpp

./run_smolvla_robot_pipeline.sh \
--port /dev/ttyACM0 \
--camera top=15 \
--camera wrist=13 \
--dry-run \
--warmup 1 \
--max-iters 3 \
--infer-every-tick \
--n-action-steps 50
  • --warmup 1 表示正式计时前先用合成输入跑 1 次推理,减少首次运行的模型初始化影响。
  • --max-iters 3 表示只运行 3 个控制周期,适合基准测试。
  • --dry-run 禁止下发电机动作,但仍采集真实 observation 并执行完整推理。

4.8.5 真机运行

./run_smolvla_robot_pipeline.sh \
--port /dev/ttyACM0 \
--camera top=15 \
--camera wrist=13 \
--n-action-steps 25 \
--print-actions

参数解释:

参数说明默认值
--model-dirSmolVLA ONNX 目录models/onnx/smolvla-fp16-surgeried
--runtimesmolvla_runtime.txt 路径models/onnx/smolvla_runtime.txt
--portSO-101 串口/dev/ttyACM0
--camera NAME=IDX相机名到 /dev/videoIDX 的映射
--n-action-steps每次推理后放入 action queue 的动作步数读取 runtime
--denoise-stepsdenoise 循环次数,数值越大越慢10
--infer-every-tick每个控制周期都完整推理,用于基准测试关闭
--dry-run只算动作,不下发电机关闭
--print-actions打印动作脚本默认开启

--n-action-steps 会影响 action queue 刷新频率。推荐从 25 开始测试;若动作过于频繁地重新规划,可适当增大该值,若需要更快响应环境变化,可适当减小该值。

4.8.6 多相机模型

2 路相机模型示例使用 topwrist。如果训练时使用 3 路相机,导出 ONNX 和 smolvla_runtime.txt 时也需要使用对应相机数量,并在运行时传入对应相机映射。

3 路相机模型示例:

./run_smolvla_robot_pipeline.sh \
--model-dir models/onnx/smolvla-3cam-fp16-surgeried \
--runtime models/onnx/smolvla_runtime_3cam.txt \
--port /dev/ttyACM0 \
--camera camera1=3 \
--camera camera2=1 \
--camera camera3=5 \
--dry-run \
--max-iters 1 \
--print-actions

4.9 效果展示

如图是 C++ SmolVLA 真机运行的效果,--n-action-steps 设置为 35。

SmolVLA ONNX 真机运行效果

5. K3 实测参考

延迟会随固件、ORT SDK、模型和散热状态变化。以下数据只用于估算量级,不作为当前版本的性能验收结果。

5.1 Python 性能测试数据

模型配置平均延迟
act-fp32EP 8 线程1290.0 ms
act-int8EP 8 线程210.9 ms
smolvla-fp32EP 8 线程 + CPU denoise8762.5 ms

5.2 C++ 性能测试数据

模型配置平均延迟
act-fp32EP 8 线程1288.3 ms
act-int8EP 8 线程247.2 ms
smolvla-fp32EP 8 线程9023.9 ms
smolvla-fp16EP204 8 线程1113.2 ms

SmolVLA 数据使用 2 路相机模型和 --denoise-steps 10,统计完整推理平均耗时,不包含模型加载。

使用仓库提供的 K3 性能门禁复测推荐路径:

source ~/.lerobot-venv/bin/activate
cd ~/spacemit_robot/components/thirdparty/lerobot/examples/onnx_inference

bash test/test_act_k3_performance.sh
bash test/test_smolvla_k3_performance.sh

ACT 脚本默认执行 3 次 warmup 和 20 次 INT8 测量,平均延迟阈值为 500 ms。SmolVLA 脚本使用合成输入、EP204、1 次 warmup 和 3 次 FP16 测量,平均延迟阈值为 1600 ms。两个脚本通过时都会输出 PERF_OK

2026 年 8 月 10 日在 K3 复测时,ACT INT8 平均延迟为 247.226 ms,SmolVLA FP16 平均延迟为 1113.167 ms,均通过性能门禁。

6. 常见问题

6.1 ACT 和 SmolVLA 应该选择哪个部署入口?

ACT 推荐优先使用 Python 或 C++ INT8 模型,端到端延迟更低。SmolVLA 推荐使用 C++ FP16 图修复版模型,Python 路径主要用于 FP32 离线验证和 dry-run 调试。

6.2 SmolVLA FP16 为什么必须使用补丁版 SpacemiT ORT SDK?

SmolVLA FP16 对部分算子数值更敏感。补丁版 SDK 配合 FP16 图修复版模型验证过数值正确性;使用系统 SpaceMIT EP、普通 ONNX Runtime 或 CPU 运行 FP16,可能出现数值漂移或溢出。

6.3 --camera 名称应该怎么填?

--camera 名称必须与训练数据和模型 metadata 中的图像 key 后缀一致。例如训练时使用 observation.images.topobservation.images.wrist,部署时应传 --camera top=15 --camera wrist=13

6.4 --n-action-steps 会影响什么?

该参数控制每次推理后放入 action queue 的动作步数。值越大,推理结果复用时间越长、动作更连续但响应变慢;值越小,重新规划更频繁、响应更快但可能增加抖动。SmolVLA 真机建议从 25 开始调试。

6.5 如何确认机械臂标定文件可用?

C++ 真机运行前需要导出包含 SO-101 标定的 runtime metadata。先执行 lerobot-calibrate,再确认 ~/.cache/huggingface/lerobot/calibration/robots/so_follower/<robot_id>.json 存在,并在 export_smolvla_runtime.py 中通过 --calibration 指向该文件。

6.6 K3 导入 cv2 时为什么提示 gapi_wip_gst_GStreamerPipeline 不存在?

该错误表示 K3 虚拟环境同时安装了 opencv-pythonopencv-python-headless。两个发行包会向同一个 cv2 目录写入不同版本的 Python 文件和二进制扩展。

以下命令会卸载 K3 虚拟环境中的 xslim 和两个 OpenCV 发行包,然后重新安装 LeRobot 使用的 headless 版本。不要在 x86 导出和量化环境执行这组命令。

source "$HOME/.local/bin/env"
uv venv ~/.lerobot-venv --python 3.12 --seed --allow-existing
source ~/.lerobot-venv/bin/activate
python -m pip uninstall -y xslim opencv-python opencv-python-headless
python -m pip install \
--index-url https://mirrors.aliyun.com/pypi/simple \
opencv-python-headless==4.12.0.88

python -c 'import cv2; print(cv2.__version__, hasattr(cv2, "VideoCapture"))'
python -m pip list | grep '^opencv'
python -m pip check

验证输出应显示 OpenCV 版本为 4.12.0VideoCaptureTrue,并且软件包列表中只有 opencv-python-headless