Ongoing simulation study of closed-loop vision-language-action control for dual-arm humanoid manipulation — state-free vs state-conditioned inference in NVIDIA IsaacLab.
50 fully randomized trials per variant — object position (8 slots), lighting, background, pegboard location, and robot initial pose all randomized each episode. Task: "Put the yellow paint brush into the crate."
Self-correction (state-free only): In 14% of trials the robot approached the wrong object, then visually re-assessed at the next chunk boundary and redirected to the correct target. Zero self-corrections in the state-conditioned variant.
Wrong arm failure (state-conditioned only): In 24% of trials the robot attempted to grasp a left-side object with the right arm — physically impossible and never demonstrated in training. Joint state conditioning corrupts the spatial reasoning the VLM would otherwise perform from the image.
FFW-SG2 demonstration dataset collected on the physical Robotis SG2 AI Worker via kinesthetic teaching.
"Put the yellow paint brush into the crate."
Robot identifies target among multiple objects on an 8-slot pegboard, selects correct arm by object position, grasps, lifts, transports, and places into crate.
Task: "Put the yellow paint brush into the crate." — object position, lighting, background, pegboard location, and robot initial pose all randomized each episode.
Robot correctly identifies the paint brush, selects the appropriate arm, grasps, and places it into the crate in a single continuous motion.
Robot initially approaches the wrong object, visually re-assesses at the next chunk boundary, then redirects to grasp the correct target.
Both models produce overconfident, spatially erratic trajectories beyond their optimal checkpoints — 200k for state-free, 30k for state-conditioned. This video shows the state-conditioned model at 400k steps.
Video files are hosted via Git LFS in this repository.
Two StarVLA variants fine-tuned on identical data with identical hyperparameters. The only difference is whether proprioceptive joint state is provided as a model input — both during fine-tuning and at inference.
Camera image + language only. No joint positions provided at any stage.
steps_200000_pytorch_model.pt--use_bf16state= argumentCamera image + language + 19 joint positions sin-cos encoded into 38 dimensions.
steps_30000_pytorch_model.ptstate=joint_pos argumentIn scripts/inference/starvla_inference.py, find the get_action call:
action_chunk_norm = starvla_client.get_action(
image=cam_image,
lang=task_description,
# no state= argument
)
action_chunk_norm = starvla_client.get_action(
image=cam_image,
lang=task_description,
state=joint_pos, # ← add this line
)
| Mode | Server command | Bridge call |
|---|---|---|
| State-free | steps_200000 | no state= |
| State-conditioned | steps_30000 | state=joint_pos |
Each joint angle is replaced by its sine and cosine, doubling the dimension. This preserves angular continuity — joints at +π and −π map to the same point in sin-cos space.
# 19 joint angles → 38-dim sin-cos vector
# Groups: left_arm (0-6), left_gripper (7),
# right_arm (8-14), right_gripper (15), head (16-17), lift (18)
def sincos_encode(state): # (19,) → (38,)
parts = []
for sl in [slice(0,7), slice(7,8), slice(8,15),
slice(15,16), slice(16,18), slice(18,19)]:
parts.append(np.sin(state[sl]))
parts.append(np.cos(state[sl]))
return np.concatenate(parts).astype(np.float32)StarVLA was fine-tuned with obs: ["image_0"] and use_proprio: false. Although the training dataset records joint state for every transition, the pipeline deliberately excluded it. The state-free model matches its training distribution exactly at inference. The camera provides implicit proprioception — arm positions are visible, object distances can be estimated from apparent size, and gripper state is directly observable. Any drift in one 16-step chunk is corrected when the next chunk is conditioned on the updated visual scene.
Trained to 400k but best at 200k. Beyond this the model overfits to training positions and fails to generalize to randomized object locations and lighting.
The harder joint state + visual learning problem leads to earlier overfitting. Model degrades rapidly after 30k — producing overconfident, spatially erratic outputs.
Offline action prediction error across training checkpoints — evaluated on 10 dataset episodes without simulation. Shows where each model peaks and degrades.
State-free: Improves steadily from 50k (MAE = 0.100 rad) to optimal at 200k (MAE = 0.071 rad), then degrades gradually — reaching 0.239 rad at 350k.
State-conditioned: Peaks at 30k–50k (MAE ≈ 0.047 rad) then collapses to 0.237 rad at 100k, plateauing at ~0.30 rad from 200k to 400k. By 400k normalized MAE reaches 32% of the action range.
| Metric | State-free best (200k) | State-cond. best (30k) | State-free 400k | State-cond. 400k |
|---|---|---|---|---|
| Overall MAE (rad) | 0.071 | 0.047 | 0.199 | 0.298 |
| Overall RMSE (rad) | 0.110 | 0.073 | 0.269 | 0.401 |
| Normalized MAE (%) | 8.1% | 5.5% | 22.3% | 32.1% |
| Degradation | — | Gradual after 200k | Cliff edge after 50k | |
FastAPI + WebSocket browser interface for submitting tasks, monitoring execution, and controlling the simulation without terminal access.
Free-form language instruction sent to the robot in real time.
Pre-configured buttons for common task descriptions.
Resets IsaacLab and randomizes all scene parameters.
Halts execution — robot holds current pose.
WebSocket shows real-time execution status.
Logs all submitted tasks with timestamps.
python scripts/server.py
# Open: http://localhost:8000The GUI writes instructions to /tmp/groot_task.txt. The inference loop polls this every simulation step at 60 Hz. Special commands __RESET__ and __STOP__ control the environment without interrupting simulation.
Uses StarVLA by the HKUST team · Deployed on Robotis SG2 AI Worker · NVIDIA IsaacLab · Ongoing study
Designed by Sanaullah