Adaptive acquisition with OpenTac-Xampling¶
OpenTac-Xampling reduces the number of taxel reads required per frame by concentrating measurements around contact. A coarse-to-fine search identifies taxels above a threshold, then expands into their neighbours. This trades complete spatial sampling in each frame for a higher update rate when contact occupies only part of the sensor.
XAMP_M = 32 captures it in this example. The displayed 996 updates/s is the measured rate of that recording.Enable adaptive acquisition¶
Measure the unloaded baseline before enabling Xampling. The following commands select either a search budget with contact expansion or a fixed total sampling budget:
uv run opentac view --xampling 64 # 64 search reads, then grow around every contact
uv run opentac view --xampling 128 --fixed # exactly 128 reads per frame, for a steady frame rate
from opentac.device import Sensor
s = Sensor()
s.zero() # nothing touching: measures each taxel's zero and noise
s.xampling(budget=128) # XAMP_M = 128, TAC_MODE = xamp_grow (grow=False for xamp_fixed)
frame = s.read()
frame.mask # True for the taxels read this frame
frame.taxels # counts above the zero; NaN where not read
s.raster() # back to reading every taxel
In the viewer, taxels not read this frame are drawn blue, and b zeroes the
board again.
Search budget versus total budget¶
| Mode | TAC_MODE |
Reads per frame |
|---|---|---|
| grow (default) | xamp_grow (2) |
XAMP_M search reads, plus every taxel growth reaches: expansion continues over the detected contact beyond the search budget |
| fixed | xamp_fixed (1) |
exactly XAMP_M, growth included: a steady frame rate, but contact coverage is incomplete if it requires more reads than the budget |
Both modes reserve at least XAMP_SEARCH_MIN reads for searching before expanding detected contacts. This prevents previously detected contact from consuming the entire frame budget. Contact taxels found in one frame are prioritised in the next.
Settings¶
| Parameter | Default | Meaning |
|---|---|---|
XAMP_M |
128 | the budget: reads per frame (fixed) or search reads (grow) |
XAMP_THRESH |
30 | counts above a taxel's own noise that count as contact |
XAMP_SEARCH_MIN |
30 | search reads before any growth |
XAMP_ZERO_FRAMES |
64 | raster frames the zero measures noise over |
XAMP_BUMP_FILL |
0 | 1: growth reads each contact taxel's whole shear bump |
XAMP_CONFIRM_US |
50 | a reading that would trigger is read again after this extra settle |
A taxel triggers when its baseline-subtracted reading exceeds its measured noise plus XAMP_THRESH. Restarting the board, changing the sensor, or changing ROW_SETTLE_US, MUX_SETTLE_US or gain invalidates this baseline. Xampling pauses until the baseline is measured again.
Measured frame rates¶
Fixed-mode measurements on a 32 × 32 sensor (1024 taxels), MUX_SETTLE_US 8, IMU off,
including USB transfer. Two rounds each, averaged (2026-09-14).
XAMP_M |
16 | 32 | 64 | 128 | 256 | 512 | 1024 | raster |
|---|---|---|---|---|---|---|---|---|
| frames/s | 1286 | 954 | 627 | 376 | 209 | 113 | 58 | 67 |
| Relative to raster | 19x | 14x | 9.3x | 5.6x | 3.1x | 1.7x | 0.9x | 1x |
Grow mode has no single frame rate: with nothing touching it reads XAMP_M
taxels like fixed mode, and each taxel that growth reads adds roughly 13 to 16 µs.
With the IMU on, its reads take about 40% of the frame time.
In grow mode at XAMP_M 128, a new 2 × 2 press was reached by the search after
1.1 frames on average and 7 frames at worst (32 × 32 sensor, hands-off
measurement of the search pattern).