eetmie/jetson-orin-nano-vla

Benchmarking Vision-Language-Action (VLA) models on an 8GB NVIDIA Jetson Orin Nano

0

stars

52

commits

Python

primary language

Sep 5, 2026

updated

README

jetson-orin-nano-vla

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:

modelupstream checkpoint / initializersplit ONNX bundle
SmolVLA 450Mlerobot/smolvla_baseeetmie/smolvla-base-onnx
X-VLA 0.9Blerobot/xvla-baseeetmie/xvla-base-onnx
EVO1 775M bootstrapOpenGVLab/InternVL3-1B-hf, pinned revisionlocal checksummed export; random action head
EVO1 775M LIBEROzuoxingdong/evo1_liberolocal checksummed export; trained action head

Measured fit

Retained runs use pinned MAXN_SUPER clocks and deterministic synthetic observations. They measure inference cost, not robot-task quality.

model / runtimeviewsp50p95rate
SmolVLA PyTorch FP3221167.93 ms1176.65 ms0.86 Hz
SmolVLA split ONNX FP162189.89 ms190.93 ms5.25 Hz
X-VLA PyTorch FP3232313.50 ms2320.89 ms0.43 Hz
X-VLA split ONNX FP163391.55 ms407.33 ms2.55 Hz
EVO1 bootstrap split ONNX mixed FP161289.18 ms292.12 ms3.45 Hz
EVO1 LIBERO split ONNX mixed FP162414.67 ms424.72 ms2.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.

Parity gate

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 — direction
  • max_abs_diff <= 1% of the reference run's own observed action range — amplitude

Cosine 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.

Run SmolVLA base

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

Run X-VLA base

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

Run EVO1

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.

Documentation

Scope

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.

Contributors

eetmie

52 commits

eetmie/jetson-orin-nano-vla

Benchmarking Vision-Language-Action (VLA) models on an 8GB NVIDIA Jetson Orin Nano

0

stars

52

commits

Python

primary language

Sep 5, 2026

updated

README

jetson-orin-nano-vla

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:

modelupstream checkpoint / initializersplit ONNX bundle
SmolVLA 450Mlerobot/smolvla_baseeetmie/smolvla-base-onnx
X-VLA 0.9Blerobot/xvla-baseeetmie/xvla-base-onnx
EVO1 775M bootstrapOpenGVLab/InternVL3-1B-hf, pinned revisionlocal checksummed export; random action head
EVO1 775M LIBEROzuoxingdong/evo1_liberolocal checksummed export; trained action head

Measured fit

Retained runs use pinned MAXN_SUPER clocks and deterministic synthetic observations. They measure inference cost, not robot-task quality.

model / runtimeviewsp50p95rate
SmolVLA PyTorch FP3221167.93 ms1176.65 ms0.86 Hz
SmolVLA split ONNX FP162189.89 ms190.93 ms5.25 Hz
X-VLA PyTorch FP3232313.50 ms2320.89 ms0.43 Hz
X-VLA split ONNX FP163391.55 ms407.33 ms2.55 Hz
EVO1 bootstrap split ONNX mixed FP161289.18 ms292.12 ms3.45 Hz
EVO1 LIBERO split ONNX mixed FP162414.67 ms424.72 ms2.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.

Parity gate

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 — direction
  • max_abs_diff <= 1% of the reference run's own observed action range — amplitude

Cosine 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.

Run SmolVLA base

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

Run X-VLA base

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

Run EVO1

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.

Documentation

Scope

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.

Contributors

eetmie

52 commits

Languages

Python

93.5%

Shell

6.5%