Recipes and measurements for running public base VLA models on an 8 GB Jetson Orin Nano Super. The repository has two deployable base-model profiles and one explicitly nondeployable EVO1 infrastructure profile:
| model | upstream checkpoint / initializer | split ONNX bundle |
|---|---|---|
| SmolVLA 450M | lerobot/smolvla_base | eetmie/smolvla-base-onnx |
| X-VLA 0.9B | lerobot/xvla-base | eetmie/xvla-base-onnx |
| EVO1 775M bootstrap | OpenGVLab/InternVL3-1B-hf, pinned revision | local checksummed export; random action head |
| EVO1 775M LIBERO | zuoxingdong/evo1_libero | local checksummed export; trained action head |
Retained runs use pinned MAXN_SUPER clocks and deterministic synthetic observations. They measure inference cost, not robot-task quality.
| model / runtime | views | p50 | p95 | rate |
|---|---|---|---|---|
| SmolVLA PyTorch FP32 | 2 | 1167.93 ms | 1176.65 ms | 0.86 Hz |
| SmolVLA split ONNX FP16 | 2 | 189.89 ms | 190.93 ms | 5.25 Hz |
| X-VLA PyTorch FP32 | 3 | 2313.50 ms | 2320.89 ms | 0.43 Hz |
| X-VLA split ONNX FP16 | 3 | 391.55 ms | 407.33 ms | 2.55 Hz |
| EVO1 bootstrap split ONNX mixed FP16 | 1 | 289.18 ms | 292.12 ms | 3.45 Hz |
| EVO1 LIBERO split ONNX mixed FP16 | 2 | 414.67 ms | 424.72 ms | 2.41 Hz |
The split bundles fit because the large policies are divided into independently built TensorRT engines. A whole-policy TensorRT build exceeds the board's unified-memory budget. Full memory, power, CPU, thermal, validity, and per-graph measurements are in the generated results.
Speed is only worth measuring if the actions survive the conversion. On this board that
is a live question rather than a formality: compute 8.7 makes FP16 the only fast reduced
precision available, and a blanket FP16 cast is exactly what collapsed SmolVLA's SigLIP
vision tower to cosine 0.805 elsewhere. Every backend is therefore handed the same
seeded observations and the same injected noise (bench/obs.py), so the action chunks
line up element by element rather than only in distribution.
The gate is two conditions, and both must hold:
cosine >= 0.999 — directionmax_abs_diff <= 1% of the reference run's own observed action range — amplitudeCosine alone hides a scale error, and an absolute difference means nothing without a range, so the difference is normalised against the range the reference policy actually commands. That keeps the number comparable across policies with different action spaces.
The measured values are in the results. The short version: the converted models reproduce their reference actions to cosine 0.9993 or better, and within 0.49 % of the action range on the executed action — X-VLA to 0.04 %. Later steps in a long chunk drift further, so a deployment that runs the whole horizon open-loop should look at the full-chunk figure there too.
python -m bench parity results/smolvla-base.torch.json results/smolvla-base.ort.json \
--reference smolvla-base.torch
It exits nonzero on a miss, and refuses any pair whose observations or injected noise differ rather than reporting a cosine against a sequence the reference never saw. EVO1 is the one model with no deployable PyTorch reference at all, so it is checked against a native fixture carried inside its bundle, which fails closed during load.
scripts/00_host_prep.sh
scripts/10_env_torch.sh
scripts/11_env_ort.sh
scripts/fetch_models.sh smolvla-base
MODEL=smolvla-base scripts/run_all.sh
scripts/00_host_prep.sh
scripts/13_env_torch_xvla.sh
scripts/11_env_ort.sh
scripts/fetch_models.sh xvla-base
MODEL=xvla-base scripts/run_all.sh
Both EVO1 bundles come from the companion Spark workflow and are copied over whole, so
fetch_models.sh has nothing to download. evo1-bootstrap has a randomly initialized
action head: it measures infrastructure only and must never control a robot.
evo1-libero is trained (zuoxingdong/evo1_libero),
and its actions mean something for LIBERO's embodiment and nothing else.
scripts/00_host_prep.sh
scripts/11_env_ort.sh
BUNDLE=~/bundles/evo1-libero-split
CACHE=~/.cache/jetson-orin-nano-vla/evo1-libero-trt
.venv-ort/bin/python scripts/check_evo1_fixture.py --bundle $BUNDLE --cache-dir $CACHE
.venv-ort/bin/python -m bench ort-split --model evo1-libero \
--bundle $BUNDLE --cache-dir $CACHE --iters 100
Substitute evo1-bootstrap and its own bundle and cache for the bootstrap run. The
first run builds TensorRT engines serially and takes several minutes; later runs reuse
the cache. python -m bench models has the per-model contracts.
This repository downloads, runs, and compares two public base checkpoints and the nondeployable EVO1 export profile. It does not contain training, fine-tuning, robot control, camera capture, or a trained EVO1 action head. TensorRT engines are built on the Jetson and are never copied between machines; the ONNX bundles are the portable artifacts.
Repository code is MIT. Model weights and derived exports retain their respective upstream licenses; consult each model card before redistribution.
52 commits
Python
93.5%
Shell
6.5%
Recipes and measurements for running public base VLA models on an 8 GB Jetson Orin Nano Super. The repository has two deployable base-model profiles and one explicitly nondeployable EVO1 infrastructure profile:
| model | upstream checkpoint / initializer | split ONNX bundle |
|---|---|---|
| SmolVLA 450M | lerobot/smolvla_base | eetmie/smolvla-base-onnx |
| X-VLA 0.9B | lerobot/xvla-base | eetmie/xvla-base-onnx |
| EVO1 775M bootstrap | OpenGVLab/InternVL3-1B-hf, pinned revision | local checksummed export; random action head |
| EVO1 775M LIBERO | zuoxingdong/evo1_libero | local checksummed export; trained action head |
Retained runs use pinned MAXN_SUPER clocks and deterministic synthetic observations. They measure inference cost, not robot-task quality.
| model / runtime | views | p50 | p95 | rate |
|---|---|---|---|---|
| SmolVLA PyTorch FP32 | 2 | 1167.93 ms | 1176.65 ms | 0.86 Hz |
| SmolVLA split ONNX FP16 | 2 | 189.89 ms | 190.93 ms | 5.25 Hz |
| X-VLA PyTorch FP32 | 3 | 2313.50 ms | 2320.89 ms | 0.43 Hz |
| X-VLA split ONNX FP16 | 3 | 391.55 ms | 407.33 ms | 2.55 Hz |
| EVO1 bootstrap split ONNX mixed FP16 | 1 | 289.18 ms | 292.12 ms | 3.45 Hz |
| EVO1 LIBERO split ONNX mixed FP16 | 2 | 414.67 ms | 424.72 ms | 2.41 Hz |
The split bundles fit because the large policies are divided into independently built TensorRT engines. A whole-policy TensorRT build exceeds the board's unified-memory budget. Full memory, power, CPU, thermal, validity, and per-graph measurements are in the generated results.
Speed is only worth measuring if the actions survive the conversion. On this board that
is a live question rather than a formality: compute 8.7 makes FP16 the only fast reduced
precision available, and a blanket FP16 cast is exactly what collapsed SmolVLA's SigLIP
vision tower to cosine 0.805 elsewhere. Every backend is therefore handed the same
seeded observations and the same injected noise (bench/obs.py), so the action chunks
line up element by element rather than only in distribution.
The gate is two conditions, and both must hold:
cosine >= 0.999 — directionmax_abs_diff <= 1% of the reference run's own observed action range — amplitudeCosine alone hides a scale error, and an absolute difference means nothing without a range, so the difference is normalised against the range the reference policy actually commands. That keeps the number comparable across policies with different action spaces.
The measured values are in the results. The short version: the converted models reproduce their reference actions to cosine 0.9993 or better, and within 0.49 % of the action range on the executed action — X-VLA to 0.04 %. Later steps in a long chunk drift further, so a deployment that runs the whole horizon open-loop should look at the full-chunk figure there too.
python -m bench parity results/smolvla-base.torch.json results/smolvla-base.ort.json \
--reference smolvla-base.torch
It exits nonzero on a miss, and refuses any pair whose observations or injected noise differ rather than reporting a cosine against a sequence the reference never saw. EVO1 is the one model with no deployable PyTorch reference at all, so it is checked against a native fixture carried inside its bundle, which fails closed during load.
scripts/00_host_prep.sh
scripts/10_env_torch.sh
scripts/11_env_ort.sh
scripts/fetch_models.sh smolvla-base
MODEL=smolvla-base scripts/run_all.sh
scripts/00_host_prep.sh
scripts/13_env_torch_xvla.sh
scripts/11_env_ort.sh
scripts/fetch_models.sh xvla-base
MODEL=xvla-base scripts/run_all.sh
Both EVO1 bundles come from the companion Spark workflow and are copied over whole, so
fetch_models.sh has nothing to download. evo1-bootstrap has a randomly initialized
action head: it measures infrastructure only and must never control a robot.
evo1-libero is trained (zuoxingdong/evo1_libero),
and its actions mean something for LIBERO's embodiment and nothing else.
scripts/00_host_prep.sh
scripts/11_env_ort.sh
BUNDLE=~/bundles/evo1-libero-split
CACHE=~/.cache/jetson-orin-nano-vla/evo1-libero-trt
.venv-ort/bin/python scripts/check_evo1_fixture.py --bundle $BUNDLE --cache-dir $CACHE
.venv-ort/bin/python -m bench ort-split --model evo1-libero \
--bundle $BUNDLE --cache-dir $CACHE --iters 100
Substitute evo1-bootstrap and its own bundle and cache for the bootstrap run. The
first run builds TensorRT engines serially and takes several minutes; later runs reuse
the cache. python -m bench models has the per-model contracts.
This repository downloads, runs, and compares two public base checkpoints and the nondeployable EVO1 export profile. It does not contain training, fine-tuning, robot control, camera capture, or a trained EVO1 action head. TensorRT engines are built on the Jetson and are never copied between machines; the ONNX bundles are the portable artifacts.
Repository code is MIT. Model weights and derived exports retain their respective upstream licenses; consult each model card before redistribution.
52 commits
Python
93.5%
Shell
6.5%