File size: 3,926 Bytes
7848e16
04af0e2
 
 
 
7848e16
 
 
 
04af0e2
7848e16
 
04af0e2
7848e16
04af0e2
 
7848e16
04af0e2
7848e16
 
04af0e2
 
 
7848e16
 
1537ea1
7848e16
 
 
 
04af0e2
 
7848e16
1537ea1
04af0e2
 
 
 
7848e16
 
04af0e2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7848e16
1537ea1
7848e16
04af0e2
 
 
 
 
 
 
 
 
7848e16
1537ea1
7848e16
 
04af0e2
1537ea1
04af0e2
7848e16
 
04af0e2
 
 
 
 
 
 
 
ec12548
04af0e2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
---
license: other
license_name: gemma-terms-of-use
license_link: https://ai.google.dev/gemma/terms
library_name: n0vtla
tags:
  - robotics
  - vision-language-action
  - tactile
  - pi0.5
---

# $\mathcal{N}_0$-VTLA — pretrained base

Pretrained base weights for [N0-VTLA](https://github.com/neoteai/N0-VTLA), a
vision–tactile–language–action policy: a π0.5-style VLA with a latent tactile pathway.

## Files

```
model.safetensors   the full checkpoint (~8.25 GB): π0.5 VLM, flow-matching action expert,
                    latent tactile predictor, and frozen DINOv2, in one state dict
config.json         architecture summary
```

## Load

```python
from huggingface_hub import snapshot_download
import safetensors.torch as st
from n0vtla.training.config import get_config
from n0vtla.models_pytorch.n0vtla_policy import N0VTLAPolicy

ckpt = snapshot_download("NeoteAI/n0-vtla-base")
cfg = get_config("vtla_tactile_posttrain")
model = N0VTLAPolicy(cfg.model).eval().cuda()
missing, unexpected = st.load_model(model, f"{ckpt}/model.safetensors", strict=False, device="cuda")
assert not unexpected, unexpected
```

`missing` is expected to contain exactly
`paligemma_with_expert.paligemma.model.language_model.embed_tokens.weight`: it is tied to
`lm_head.weight` and safetensors stores tied weights once. `unexpected` must be empty.

In practice you do not call this yourself — point `VTLA_PRETRAINED_CHECKPOINT` at the download
directory and use the post-training recipe:

```bash
hf download NeoteAI/n0-vtla-base --local-dir checkpoints/n0-vtla-base
export VTLA_PRETRAINED_CHECKPOINT="$PWD/checkpoints/n0-vtla-base"
```

See **Post-training on your own robot data** in the
[repository README](https://github.com/neoteai/N0-VTLA).

## Normalization statistics

**Not included, by design.** Normalization depends on your dataset, robot action layout, and
delta-action convention, so it has to be computed on your own data:

```bash
python scripts/compute_canonical_norm.py \
  --repo-id /path/to/your/canonical_dataset \
  --robot flexiv \
  --train-config-name vtla_tactile_posttrain \
  --asset-id your_asset_id
```

The result lands in `assets/vtla_tactile_posttrain/<asset-id>/norm_stats.json`, and
`VTLA_ASSET_ID` must match the `--asset-id` you used.

## Action format

The policy outputs normalized element-wise delta actions. To run them on a robot:

1. **De-normalize** in the same element-wise (subtraction) space the model was trained in.
   The quantile inverse is `x = (x_norm + 1) / 2 * (q99 - q01) + q01`, applied to the active
   dims only — 10 for single-arm, 20 for dual-arm.
2. **Add back to the current state**, `abs = state + delta`, on the delta dims. Grippers and
   padding are already absolute. This is the standard `AbsoluteActions` step; there is no
   relative-rotation or rotation-matrix math, because the rotation delta is element-wise.
3. **Execute the full chunk.** The action horizon is 50 — execute all 50 steps before
   requesting the next prediction. Executing fewer clips the tail of the chunk, which is where
   the grasp-closing motion lives, and the gripper will look stuck open.

### 32-dim action/state layout

```
left arm  [0:10]:  xyz [0:3],   rot6d [3:9],   gripper [9]
right arm [10:20]: xyz [10:13], rot6d [13:19], gripper [19]
[20:32]:           reserved / unused
```

Rotation is rot6d, not quaternion or Euler. On disk the `action` field is the absolute
end-effector pose; the training transforms form the delta target as `action[t+k] - state[t]`.

## License

These weights are derived from Google's PaliGemma/Gemma parameters and are therefore made
available under the [Gemma Terms of Use](https://ai.google.dev/gemma/terms) and the
[Gemma Prohibited Use Policy](https://ai.google.dev/gemma/prohibited_use_policy), **not** under
the CC BY-SA 4.0 licence that covers the source code. This is inherited from the base model, not
a restriction added on top.