File size: 12,410 Bytes
2109011 230923e 2109011 e54f451 2109011 e54f451 2109011 | 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 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 | ---
license: cc-by-nc-4.0
language:
- en
pipeline_tag: feature-extraction
tags:
- embeddings
- tactile
- pressure
- force
- fsr
- taxel
- sensor
- robotics
- qwen3-vl
base_model: EximiusLabs/fusion-embedding-2-2b-preview
---
# fusion-embedding-2-tactus
<p align="center">
<img src="assets/tactus-banner.png" alt="Tactus, the tactile sense for Fusion Embedding 2 (2B-Preview), Eximius Labs" width="100%">
</p>
<div align="center">
[](https://github.com/Eximius-Labs/fusion-embedding)
[](https://github.com/Eximius-Labs/fusion-embedding)
[](#license)
[](#)
[](https://github.com/Eximius-Labs/fusion-embedding)
</div>
**Tactus** is the tactile sensor pack for Eximius Labs' fusion-embedding stack. It maps a
short window of pressure-array frames (a 32x32 taxel grid, the signal class produced by
resistive/FSR gloves, e-skins, and instrumented robot hands) into the
[Qwen3-VL-Embedding-2B](https://huggingface.co/Qwen/Qwen3-VL-Embedding-2B) text embedding
space, so touch becomes searchable in plain language: recognition is a text query, not a
trained classifier head.
Tactus reads **low-dimensional pressure arrays**, not optical tactile images. Optical
sensors (GelSight, DIGIT) already have strong models (TVL, UniTouch, Sparsh); the cheap,
widely-shipped resistive arrays did not. To our knowledge Tactus is the first open model
to put this sensor class in a text-aligned, cross-modal embedding space.
Tactus is part of the **fusion-embedding family** alongside
[Tactus Mat](https://huggingface.co/EximiusLabs/fusion-embedding-2-tactus-mat)
(the same pack trained for a 64x32 body pressure mat),
[Tremor](https://huggingface.co/EximiusLabs/fusion-embedding-2-tremor) (motion) and
[Ember](https://huggingface.co/EximiusLabs/fusion-embedding-2-ember) (thermal). Its
embeddings target the canonical readout of
[fusion-embedding-2](https://huggingface.co/EximiusLabs/fusion-embedding-2-2b-preview), so
tactile windows are directly comparable to that model's text, image, video, and audio in
one 2048-d space, and drop into the [Engram](https://github.com/Eximius-Labs/engram)
memory layer (`pip install engram-robomem`) as a first-class sense.
[GitHub](https://github.com/Eximius-Labs/fusion-embedding) | [fusion-embedding-2](https://huggingface.co/EximiusLabs/fusion-embedding-2-2b-preview) | [Live playground](https://www.eximiuslabs.com/playground) | [Family report (arXiv:2607.18666)](https://arxiv.org/abs/2607.18666) | [Tactus report (arXiv:2608.04043)](https://arxiv.org/abs/2608.04043)
## Model Overview
<p align="center">
<img src="assets/tactus_model_overview.png" alt="Tactus architecture: calibrated pressure windows pass through an MAE-pretrained per-frame trunk, a learned frame fusion, and a trained projector into the fusion-embedding shared space, where touch becomes searchable in natural language alongside every other modality" width="880px">
</p>
Tactus is a **trained CNN trunk plus projector** over pressure windows. Each 32x32 frame
passes through a ResNet-18-width trunk (3x3 stem, four stages; 32x32 -> 4x4 spatial map);
the K frames of a grasp window are fused by a learned 1x1 convolution over their
concatenated feature maps, pooled, and projected into the frozen base's 2048-d text space.
The trunk is initialized by masked-autoencoder pretraining (mask 0.6, per-patch normalized
targets) on 144k unlabeled STAG-family pressure frames, then fine-tuned contrastively
against canonical text embeddings of natural grasp phrases.
The design choice that matters is the data path: pressure is normalized with the sensor's
own calibration affine (`clip((raw - 500) / 150, 0, 1)`, the STAG reference preprocessing),
and pretraining stays same-sensor. In our ablations, correct normalization and same-sensor
MAE were worth more than every architecture change combined, while cross-sensor pretraining
pooling gave nothing, consistent with published findings (HTT, TacVerse).
| Feature | Value |
| --- | --- |
| Parameters | ~2.06B frozen Qwen base (text side); **16.2M trained** (13.5M trunk + 2.6M projector) |
| Modality | tactile pressure (32x32 taxel array; 548 active sensors in the training glove) |
| Supported tasks | `zero-shot object recognition from touch`, `text -> touch retrieval` |
| Input | one grasp window `[F, 32, 32]` (F frames, any F; trained at K=8) or a single frame |
| Input scale | STAG calibration affine `clip((raw - 500) / 150, 0, 1)`; uint8 0-255 maps accepted |
| Embedding dimension | 2048 (canonical whitened readout; directly comparable across modalities) |
| Pooling strategy | last-token pooling (text side) |
| Base model | Qwen/Qwen3-VL-Embedding-2B via fusion-embedding-2-2b-preview (frozen) |
| Pretraining | same-sensor MAE, 144k frames incl. unlabeled; supervised test frames excluded |
| Trained components | trunk + conv frame-fusion + projector, 16.2M; shipped as `model.safetensors` |
| Distribution | ~65 MB trained head; the frozen base downloads from its own repository |
## See it in action
**Real held-out grasps, recognized from pressure alone.** Each panel is a genuine STAG test
frame (the most active frame of that class in the held-out split, by total pressure) with
the text query the model matches it against: no camera, no trained classifier head. Across
the full test split the model averages 0.77 top-1 and 0.94 top-3 over 27 such queries.
<p align="center">
<img src="assets/tactus_test_grasps.png" alt="Four real held-out STAG test pressure maps with their text queries: a mug, scissors, a full can, safety glasses, each recognized from the 32x32 pressure pattern alone" width="860px">
</p>
## Training and Evaluation
Tactus trains in two stages on the [STAG](https://stag.csail.mit.edu/) datasets
([Sundaram et al., Nature 2019](https://www.nature.com/articles/s41586-019-1234-z)): a
masked-autoencoder pretrain over every STAG-family pressure frame (classification +
blindfolded + weights + handposes, 144k frames including unlabeled ones, supervised test
frames excluded), then contrastive fine-tuning of the whole head against canonical text
embeddings of grasp phrases, with STAG-style cluster sampling (each training window draws
diverse frames from across a recording rather than consecutive near-duplicates).
Evaluation is 27-way object recognition on **fully held-out test recordings**, scored as
cosine ranking against text queries (open-vocabulary; the model never trains a classifier
head).
| | top-1 (27-way) | top-3 | recording-level top-1 |
| --- | ---: | ---: | ---: |
| **This checkpoint** | **0.817** | **0.951** | 0.741 |
| Recipe mean (4 independent runs) | 0.771 +/- 0.062 | 0.935 | 0.722 |
| Training from scratch (no MAE), mean of 3 | 0.705 | 0.905 | 0.691 |
| STAG 2019 supervised closed-set CNN | 0.76 | - | - |
| chance | 0.037 | 0.111 | 0.037 |
Interpreting these numbers: the recipe's mean exceeds the original paper's supervised CNN
while performing a harder task (open-vocabulary text queries against a frozen language
space, versus a 27-way trained classifier), though by less than one standard error; we
describe the result as **matching to exceeding the original baseline, with best runs at
0.83**, rather than claiming a definitive margin. Top-3 accuracy is stable across every
run. Our evaluation mirrors STAG's cluster-sampling test protocol but is not their
byte-identical harness. Same-sensor MAE pretraining accounts for about +7 points over
training from scratch. Full recipe, ablations, and negative results: `results.json` and
the GitHub repository.
## Usage
<details>
<summary>Requirements</summary>
- `torch` (CUDA recommended), `numpy`, `safetensors`
- `pip install fusion-embedding[hf]` for the text side (the canonical whitened readout
Tactus was trained against; embedding text any other way will misrank)
- The frozen base downloads from `EximiusLabs/fusion-embedding-2-2b-preview`.
</details>
<details open>
<summary>via <code>inference.py</code> (this repository)</summary>
```python
import numpy as np
from inference import TactusEmbedder
ta = TactusEmbedder.from_pretrained("EximiusLabs/fusion-embedding-2-tactus",
revision="v0.1-preview")
# a grasp window: [F, 32, 32] pressure frames (uint8 0-255 or floats in [0, 1]);
# for raw sensor counts pass raw="stag" to apply the calibration affine
window = np.load("grasp.npy")
for text, score in ta.rank(window, ["a mug", "scissors", "a full soda can", "an empty hand"]):
print(f"{score:+.3f} {text}")
# or embed both sides into the shared space directly
p = ta.embed_pressure(window) # 2048-d, L2-normalized
t = ta.embed_text(["holding a mug"]) # canonical text embedding, same space
```
Pressure embeddings land in the same space as fusion-embedding-2's text, image, video, and
audio, and as Tremor's motion, so cross-modal search over a robot session works out of the
box through [Engram](https://github.com/Eximius-Labs/engram). Match text against pressure
through this API rather than embedding text with the raw base model; Tactus was trained
against the canonical whitened readout, and other text paths will misrank.
</details>
## Related models
Tactus joins the fusion-embedding sense packs, all built on
[fusion-embedding-2](https://huggingface.co/EximiusLabs/fusion-embedding-2-2b-preview):
| Model | Sense | Signal |
| --- | --- | --- |
| **This model** | touch | 32x32 pressure/taxel arrays |
| [fusion-embedding-2-tremor](https://huggingface.co/EximiusLabs/fusion-embedding-2-tremor) | motion | 3-axis accelerometer windows |
| [fusion-embedding-2-tremor-g1](https://huggingface.co/EximiusLabs/fusion-embedding-2-tremor-g1) | motion (Unitree G1 head) | robot IMU |
| [fusion-embedding-2-ember](https://huggingface.co/EximiusLabs/fusion-embedding-2-ember) | heat | thermal infrared images |
All packs embed into one 2048-d space, so a query can match across senses. The
[Engram](https://github.com/Eximius-Labs/engram) memory layer (`pip install engram-robomem`)
wires them into a searchable robot session memory with temporal reasoning.
## License
The trained weights in this repository are released under
**[CC-BY-NC-4.0](https://creativecommons.org/licenses/by-nc/4.0/)** (non-commercial).
This reflects the training data's lineage: Tactus is trained on the
[STAG](https://stag.csail.mit.edu/) datasets, which are released for non-commercial
research use. A commercially-clean retrain (on permissively licensed pressure corpora) is
future work; a commercial license may follow.
## Limitations
- **Run-to-run variance.** The training recipe's top-1 varies +/-0.06 across seeds
(0.70-0.83 over four runs). The released checkpoint is a strong draw, and the mean is
reported alongside it. Seed stabilization is active work.
- **One sensor family.** Trained on one glove (STAG's 32x32 grid, 548 taxels). Our
cross-sensor experiments show transfer to other taxel geometries needs fine-tuning, not
zero-shot use; the input path accepts any [F,32,32] window, and other resolutions must
be resampled.
- **27-object vocabulary at eval.** Open-vocabulary means text queries, not tested
open-set generalization to arbitrary unseen object categories; treat novel-category
recognition as unvalidated.
- **Research preview.** Not a production classifier. The intended use is
language-addressable touch inside a multimodal memory, not high-stakes recognition.
- **English text only**, through the canonical readout (`fusion-embedding` package); do
not embed text with the raw base model.
## Citation
If you use Tactus, please cite this repository and the dataset it builds on:
```bibtex
@article{tactus2026,
title = {Tactus: Open-Vocabulary Object Recognition from Low-Cost
Pressure Arrays},
author = {Tonmoy, Abdul Basit},
journal = {arXiv preprint arXiv:2608.04043},
year = {2026}
}
```
Tactus trains on **STAG** (Sundaram et al., *Learning the signatures of the human grasp
using a scalable tactile glove*, Nature 2019); please cite that work when using the
benchmark numbers. The text space is **Qwen3-VL-Embedding-2B**.
|