Official StarVLA repository
This guide is based on the official StarVLA codebase by the HKUST team. Clone from github.com/starVLA/starVLA. This deployment on the Robotis SG2 AI Worker in NVIDIA IsaacLab was designed by Sanaullah.
Requirements
| Component | Version | Notes |
|---|---|---|
| Docker | 24.0+ | Primary installation method |
| NVIDIA Container Toolkit | latest | Required for GPU access in Docker |
| CUDA driver | 580+ | CUDA 12.8 runtime inside container |
| GPU VRAM | 32 GB recommended | RTX 5090 tested ยท 16 GB minimum |
| RAM | 64 GB+ | For dataset loading |
| Storage | 200 GB+ | Image + checkpoints + dataset |
| OS (host) | Ubuntu 22.04 | Container base is also Ubuntu 22.04 |
The policy server loads Qwen2.5-VL-3B (3B params) plus the DiT-B action head (150M params). With bfloat16 this requires ~16 GB VRAM. 32 GB is recommended for stable 60 Hz inference alongside IsaacLab.
Installation
1. Clone the official repository
git clone https://github.com/starVLA/starVLA
cd starVLA2. Build the Docker image
The Dockerfile uses nvidia/cuda:12.8.0-devel-ubuntu22.04 as base and installs Python 3.10, PyTorch nightly, FFmpeg, libav, and all dependencies automatically.
docker build -t starvla:latest .First build takes 15โ30 minutes. PyTorch nightly (~4 GB) is downloaded fresh. Subsequent builds use the Docker layer cache.
3. Run the container
docker run -it --gpus all \
-v /path/to/checkpoints:/workspace/starVLA/results \
-v /path/to/dataset:/workspace/starVLA/2-folder-one-camera-dataset \
-v /path/to/pretrained:/workspace/starVLA/playground/Pretrained_models \
-p 5555:5555 \
-p 8000:8000 \
--name starvla \
starvla:latestdocker start -ai starvla
What the Dockerfile installs
| Component | Version / source |
|---|---|
| Base image | nvidia/cuda:12.8.0-devel-ubuntu22.04 |
| Python | 3.10 via apt-get |
| PyTorch | 2.12.0.dev20260407+cu128 (nightly) |
| torchvision | 0.27.0.dev20260407+cu128 (nightly) |
| FFmpeg + libavcodec | system โ apt-get |
| All Python deps | starVLA_requirements.txt |
| StarVLA | pip install -e . (editable) |
All experiments were run inside Docker. Conda may require additional system libraries (FFmpeg, libavcodec) to be installed manually via apt-get.
1. Clone the official repository
git clone https://github.com/starVLA/starVLA
cd starVLA2. Install system dependencies
sudo apt-get install -y \
libavcodec-dev libavformat-dev libswscale-dev \
libavutil-dev ffmpeg \
libgl1-mesa-glx libglib2.0-03. Create conda environment
conda create -n starvla python=3.10 -y
conda activate starvla4. Install PyTorch nightly with CUDA 12.8
pip install torch==2.12.0.dev20260407+cu128 \
torchvision==0.27.0.dev20260407+cu128 \
--index-url https://download.pytorch.org/whl/nightly/cu1285. Install StarVLA dependencies
# Filter out torch/torchvision (already installed above)
grep -v -E "^(torch==|torchvision==|triton==|starVLA==)" \
starVLA_requirements.txt > /tmp/filtered_reqs.txt
pip install -r /tmp/filtered_reqs.txt
pip install -e .Dataset structure
2-folder-one-camera-dataset/
โโโ meta/
โ โโโ info.json # 2000 episodes, 10 fps, feature definitions
โ โโโ modality.json # joint group layout
โ โโโ stats_gr00t.json # normalization statistics (min/max/mean/std)
โโโ data/
โ โโโ chunk-000/ # episodes 0โ999
โ โ โโโ episode_000000.parquet
โ โ โโโ ...
โ โโโ chunk-001/ # episodes 1000โ1999
โโโ videos/
โโโ chunk-000/
โโโ observation.images.cam_head/
โโโ episode_000000.mp4 # AV1 codec, 376ร672 @ 10 fps
โโโ ...| Field | Shape | Description |
|---|---|---|
action | (19,) | Joint position targets โ float32 |
observation.state | (19,) | Current joint positions โ float32 |
observation.images.cam_head | 376ร672ร3 | RGB video @ 10 fps โ AV1 codec |
task_index | int64 | Task ID โ 0 = paint brush into crate |
Videos use AV1 encoding. The Docker image installs libavcodec-dev and av==12.3.0 (PyAV) automatically. OpenCV cannot decode AV1 without hardware support.
Fine-tuning
All fine-tuning scripts are in examples/FFWSG2/train_files/. The VLM backbone (qwen_vl_interface) is frozen throughout โ only the DiT-B action head is trained.
Script: examples/FFWSG2/train_files/run_ffw_sg2_train.sh
export WANDB_MODE=disabled
export MASTER_ADDR=localhost
export MASTER_PORT=29500
export RANK=0 WORLD_SIZE=1 LOCAL_RANK=0
export PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True
accelerate launch \
--mixed_precision bf16 --num_processes 1 \
starVLA/training/train_starvla.py \
--config_yaml ./examples/FFWSG2/train_files/starvla_ffw_sg2.yaml \
--framework.name QwenGR00T \
--framework.qwenvl.base_vlm playground/Pretrained_models/Qwen2.5-VL-3B-Instruct-Action \
--datasets.vla_data.data_root_dir . \
--datasets.vla_data.data_mix ffw_sg2 \
--datasets.vla_data.per_device_batch_size 1 \
--datasets.vla_data.video_backend pyav \
--trainer.freeze_modules 'qwen_vl_interface' \
--trainer.max_train_steps 400000 \
--trainer.save_interval 5000 \
--trainer.logging_frequency 10 \
--trainer.eval_interval 100 \
--run_root_dir ./results/Checkpoints \
--run_id ffw_sg2_400k_fp32Despite training to 400k, use steps_200000_pytorch_model.pt for deployment. Beyond 200k the model overfits and produces overconfident trajectories on randomized scenes.
Script: examples/FFWSG2/train_files/run_ffw_sg2_state_train.sh
export WANDB_MODE=disabled
export MASTER_ADDR=localhost
export MASTER_PORT=29500
export RANK=0 WORLD_SIZE=1 LOCAL_RANK=0
export PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True
accelerate launch \
--mixed_precision bf16 --num_processes 1 \
starVLA/training/train_starvla.py \
--config_yaml ./examples/FFWSG2/train_files/starvla_ffw_sg2_state.yaml \
--framework.name QwenGR00T \
--framework.qwenvl.base_vlm playground/Pretrained_models/Qwen2.5-VL-3B-Instruct-Action \
--datasets.vla_data.data_root_dir . \
--datasets.vla_data.data_mix ffw_sg2 \
--datasets.vla_data.per_device_batch_size 1 \
--datasets.vla_data.video_backend pyav \
--trainer.freeze_modules 'qwen_vl_interface' \
--trainer.max_train_steps 400000 \
--trainer.save_interval 5000 \
--trainer.logging_frequency 10 \
--trainer.eval_interval 100 \
--run_root_dir ./results/Checkpoints \
--run_id ffw_sg2_400k_state_fp32Despite training to 400k, use steps_30000_pytorch_model.pt. The model degrades rapidly after 30k due to the harder joint state + visual learning problem.
Script: examples/FFWSG2/train_files/run_ffw_sg2_state_30k.sh โ trains directly to 30k steps, saving every 2k.
export WANDB_MODE=disabled
export MASTER_ADDR=localhost
export MASTER_PORT=29500
export RANK=0 WORLD_SIZE=1 LOCAL_RANK=0
export PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True
accelerate launch \
--mixed_precision bf16 --num_processes 1 \
starVLA/training/train_starvla.py \
--config_yaml ./examples/FFWSG2/train_files/starvla_ffw_sg2_state.yaml \
--framework.name QwenGR00T \
--framework.qwenvl.base_vlm playground/Pretrained_models/Qwen2.5-VL-3B-Instruct-Action \
--datasets.vla_data.data_root_dir . \
--datasets.vla_data.data_mix ffw_sg2 \
--datasets.vla_data.per_device_batch_size 1 \
--datasets.vla_data.video_backend pyav \
--trainer.freeze_modules 'qwen_vl_interface' \
--trainer.max_train_steps 30000 \
--trainer.save_interval 2000 \
--trainer.logging_frequency 10 \
--trainer.eval_interval 100 \
--run_root_dir ./results/Checkpoints \
--run_id ffw_sg2_30k_stateUse this script if you only need the state-conditioned model โ it stops at the optimal checkpoint automatically.
Training configuration summary
| Hyperparameter | State-free | State-conditioned |
|---|---|---|
| Config yaml | starvla_ffw_sg2.yaml | starvla_ffw_sg2_state.yaml |
| run_id | ffw_sg2_400k_fp32 | ffw_sg2_400k_state_fp32 |
| Training steps | 400,000 | 400,000 (or 30,000) |
| Optimal checkpoint | 200,000 | 30,000 |
| Save interval | 5,000 | 5,000 / 2,000 steps |
| Batch size | 1 | 1 |
| Mixed precision | bf16 | bf16 |
| VLM backbone | frozen | frozen |
| Video backend | pyav | pyav |
| Hardware | 1ร NVIDIA RTX 5090 32GB | |
Checkpoint structure
results/Checkpoints/
โโโ ffw_sg2_400k_fp32/ # state-free 400k run
โ โโโ config.yaml
โ โโโ dataset_statistics.json
โ โโโ summary.jsonl
โ โโโ checkpoints/
โ โ โโโ steps_5000_pytorch_model.pt
โ โ โโโ steps_10000_pytorch_model.pt
โ โ โโโ ... # every 5000 steps
โ โ โโโ steps_400000_pytorch_model.pt
โ โโโ final_model/
โ โโโ pytorch_model.pt
โโโ ffw_sg2_400k_state_fp32/ # state-conditioned 400k run
โ โโโ # same structure
โโโ ffw_sg2_30k_state/ # state-conditioned 30k run
โโโ checkpoints/
โโโ steps_2000_pytorch_model.pt
โโโ ... # every 2000 steps
โโโ steps_30000_pytorch_model.ptPolicy server
The policy server runs inside the Docker container and exposes a WebSocket endpoint on port 5555, mapped to the host via -p 5555:5555.
pkill -f server_policy && sleep 3
python deployment/model_server/server_policy.py \
--ckpt_path results/Checkpoints/ffw_sg2_400k_fp32/\
checkpoints/steps_200000_pytorch_model.pt \
--port 5555 \
--use_bf16pkill -f server_policy && sleep 3
# No --use_bf16 flag โ state model uses float32
python deployment/model_server/server_policy.py \
--ckpt_path results/Checkpoints/ffw_sg2_400k_state_fp32/\
checkpoints/steps_30000_pytorch_model.pt \
--port 5555Look for INFO: server listening on 0.0.0.0:5555. The WebSocket handshake error on first connect is normal.
| Argument | Default | Description |
|---|---|---|
--ckpt_path | required | Path to .pt checkpoint file |
--port | 10093 | WebSocket port |
--use_bf16 | False | bfloat16 precision โ use for nostate model only |
--idle_timeout | 1800 | Seconds before idle shutdown |
IsaacLab inference bridge
Runs outside the Docker container in the IsaacLab environment. Connects to the policy server at 172.17.0.2:5555 (Docker bridge network IP).
cd /workspace/robotis_lab
python scripts/inference/starvla_inference.py \
--task RobotisSG2-PaintBrush-v0 \
--starvla_host 172.17.0.2 \
--starvla_port 5555 \
--step_hz 60 \
--chunk_size 16| Argument | Default | Description |
|---|---|---|
--task | required | IsaacLab registered task name |
--starvla_host | 172.17.0.2 | Docker bridge network IP of container |
--starvla_port | 5555 | WebSocket port |
--step_hz | 60 | Control rate in Hz |
--chunk_size | 16 | Action chunk length in steps |
--robot_type | FFW_SG2 | Robot platform |
Terminal 1 (Docker): policy server ยท Terminal 2 (host): inference bridge ยท Terminal 3 (host): web GUI. Start in this order.
Web GUI
python scripts/server.py
# Open browser: http://localhost:8000| Endpoint | Method | Description |
|---|---|---|
/api/task | POST | Submit natural language task instruction |
/api/reset | POST | Reset IsaacLab environment |
/api/stop | POST | Stop current task execution |
/api/status | GET | Current robot and server status |
/ws | WebSocket | Real-time status updates |
The GUI writes to /tmp/groot_task.txt. The inference bridge polls this every simulation step at 60 Hz. __RESET__ and __STOP__ are special control commands.