Back to blog

Reading texture through motion: velocity modulation in robotic touch

A short research note on why exploratory movement is part of the tactile signal, not a nuisance to be cancelled — and how sliding speed reshapes what a neuromorphic fingertip reports.

There is a habit, inherited from computer vision, of treating a sensor reading as a snapshot: press a fingertip to a surface, record a frame, classify it. Touch does not really work that way. Humans do not identify a fabric by pressing on it; we rub it. The movement is not overhead to be subtracted — it is part of the measurement. This note collects a few things I keep coming back to about how exploratory motion, and sliding speed in particular, shapes the tactile signal. It connects to work I presented at Humanoids 2025 and IROS 2025 on pairing exploratory movement with event-based tactile sensors.

Texture is a temporal signal

When a fingertip slides across a textured surface at velocity , the surface features are converted into a time-varying stimulus at the contact. A ridge pattern with spatial period — the distance between bumps — excites the skin at a temporal frequency that scales with speed:

The consequence is immediate and slightly awkward: the same surface produces a different signal depending on how fast you move. Double the sliding speed and every characteristic frequency doubles. Any representation that is going to be stable across explorations has to account for velocity rather than pretend it is constant. This is why a single static press is such a weak probe — it throws away the axis along which texture actually lives.

For an event-based sensor this coupling is direct. Events are triggered by change, so a faster slide over the same texture packs more events into the same window and shifts their timing. Speed is not a confound layered on top of the texture signal; it is baked into it.

A minimal signal model

It helps to write down the crudest model that still captures the effect. Treat a patch of texture as a sum of spatial components, and let the contact sample it as it moves. A component with spatial frequency (cycles per millimetre) shows up in time as

so its temporal frequency is and its amplitude reflects how pronounced that component is. Real textures are a superposition of many such terms plus noise, but even this one-line model makes the design tension obvious: to compare two textures fairly you either hold fixed, or you estimate and normalise the frequency axis by it. Controlling the exploratory movement is therefore not a convenience — it is what makes the readings comparable at all.

A spike-rate feature, and why it is not enough

The simplest feature you can pull from an event stream is a windowed spike (event) rate — count events in a sliding window and divide by its duration. It is cheap, robust, and a reasonable first descriptor of how “busy” a contact is:

import numpy as np

def spike_rate(event_times_s: np.ndarray, window_s: float, hop_s: float):
    """Windowed event rate (events per second) from a 1-D array of timestamps.

    event_times_s : sorted event timestamps in seconds
    window_s      : analysis window length
    hop_s         : step between successive windows
    returns       : (window_centres_s, rate_hz)
    """
    if event_times_s.size == 0:
        return np.empty(0), np.empty(0)

    t_end = event_times_s[-1]
    starts = np.arange(0.0, max(t_end - window_s, 0.0) + hop_s, hop_s)

    centres = starts + window_s / 2.0
    rate = np.empty(starts.shape)
    for i, t0 in enumerate(starts):
        n = np.count_nonzero((event_times_s >= t0) & (event_times_s < t0 + window_s))
        rate[i] = n / window_s
    return centres, rate

The catch is the velocity coupling from above: overall event rate rises with sliding speed almost regardless of what you are touching. Feed raw rate to a classifier and it will happily learn to read your motor commands instead of the surface. The rate is a fine ingredient, but only once you have either fixed the exploratory velocity or divided it out — the same normalisation the signal model demands.

Movement as an active choice

The framing I find most useful is that the robot is not a passive receiver of a tactile image; it is choosing the measurement. Sliding speed, contact force, and trajectory are all parameters of the sensing process, and picking them well is part of perception rather than a preprocessing step that happens before it.

A few practical consequences I keep in mind:

  • Report the velocity. A tactile dataset without the exploratory motion that produced it is missing an axis of the signal. Log speed and force alongside the events.
  • Prefer controlled or estimated speed. Either hold fixed across trials, or estimate it and normalise features by it. Both beat ignoring it.
  • Let timing carry information. Event intervals, not just counts, encode the frequency content that a spiking readout can use directly.

I am deliberately keeping the claims qualitative here — the exact gains depend heavily on sensor, surface set, and controller, and I would rather point at the mechanism than quote a number out of context. The mechanism is the durable part: in touch, how you move is inseparable from what you feel, and a good tactile system treats movement as a variable it gets to choose.