Haptic proximity radar (continuous direction and distance)
A continuous, distance-modulated haptic example. A draggable target sits on a radar disc around the wearer: its direction selects which body zone fires and its distance sets the intensity.
- Source:
examples/haptic_proximity_radar/on GitHub - Hardware required: Teslasuit 4R, connected and powered.
- Run:
python -m examples.haptic_proximity_radar.mainfrom the repository root (needs the[gui]extra). - Live demo: see Haptic Proximity Radar on the Teslasuit research demo page.
What it shows#
This is the continuous analogue of the discrete arrow-key cues in Haptic navigation. The operator sees a top-down view of the wearer at the centre of a disc and drags a target anywhere inside it. The suit fires a continuous haptic cue whose:
- Channel (which body zone fires) is selected by the angle from the wearer to the target.
- Intensity (pulse width × amplitude) is driven by the radial distance: close = strong, far = silent.
Capabilities demonstrated:
HapticLibrarysubclass:ProximityHapticsdeclares four namedCustomPlayableslots:belly,back,left_shoulder,right_shoulder.- Per-slot intensity multipliers: the strategy writes
amplitude_multandpulse_width_multon each slot every cycle, instead of only togglingIsMuted. - Custom
ControlMessage:ProximityControlMessagecarries the target position (obj_x,obj_y) and a master intensity. - Haptic only output: no EMS is produced;
self.ems_outputis pre-muted in the strategy's__init__.
Project layout#
examples/haptic_proximity_radar/
├── main.py ── orchestrator.launch()
├── proximity_radar_strategy.py ── ProximityRadarStrategy(ControlStrategyBase)
├── proximity_radar_types.py ── ProximityControlMessage + ProximityHaptics
└── gui/
├── main.py ── GUI process entry point
└── radar_tab.py ── radar disc, draggable target, zone tableConcept#
N (forward)
belly
│
W ──────────●────────── E (right shoulder)
(left shoulder) │
│
back
S- The wearer is the dot at the disc centre.
- The target can be dragged anywhere within radius
R. - Direction picks the body zone, with a cosine-weighted blend on the boundaries so adjacent zones crossfade smoothly.
- Distance sets the strength of the cue. At
r ≥ 0.95·Rall zones are muted.
Signal mapping#
Let (x, y) be the target position relative to the wearer and R
the disc radius.
r = clamp(|p| / R, 0, 1)θ = atan2(y, x)(0 = right / east; π/2 = forward / north)prox = clamp(1 − r, 0, 1)- Per zone with centre angle
θ_zone:w_zone = max(0, cos(θ − θ_zone))²amp_mult = master · prox · w_zonepw_mult = 0.5 + 0.5 · proxIsMuted = (prox == 0) or (w_zone < ε)
Cardinal positions excite exactly one zone; 45° positions excite the two neighbours at equal weight (about 0.5 each).
Bone / channel mapping (Teslasuit 4R)#
Same map as Haptic navigation, verified on the reference suit:
| Body area | bone_id | Channels | Direction (θ_zone) |
|---|---|---|---|
| Abdomen (belly) | 8 | 0..7 | forward (+π/2) |
| Back | 11 | 0..7 | backward (−π/2) |
| Left upper-arm front | 12 | 0..2 | left (+π) |
| Right upper-arm front | 14 | 0..2 | right (0) |
Running it#
python -m examples.haptic_proximity_radar.mainA top-down radar window appears with a draggable target. Drag it around the disc to change which body zone fires and how strong the cue is.
| Key | Action |
|---|---|
| Drag | Move the target |
| Arrow keys | Nudge the target (Shift + arrow for a larger step) |
| Space | Toggle orbit mode |
| 0 | Re-centre the target |
, / . | Lower / raise master intensity |
| Esc | Stop all zones |
Press Ctrl-C in the launching shell to exit.
Safety notes#
This example drives haptic output only; EMS output is muted for the whole session. Esc stops all zones immediately, and the cues are also stopped when the window loses focus. Start with a low master intensity and raise it only if the wearer reports the cue as too subtle.
See Safety for the framework's safety guarantees.
See also#
- Examples → Haptic navigation: the discrete version of this example
- Examples → Vestibular training: the same zone layout driven by postural sway
- Concepts → Messaging, HapticLibrary
examples/haptic_proximity_radar/README.md: operational README
