Haptics ◆ UAV teleoperation ◆ Control barrier functions ◆ University of Toronto ◆ IEEE RA-L 2025

AeroHaptix

Feel the obstacle, fly the drone. A wearable suit with 32 vibration units renders obstacle directions on the upper body, and a control barrier function per obstacle (MultiCBF) decides which unit vibrates and how hard. Below: the suit in 3-D with every motor where the perceptual study put it, a live 3-D feed of the flights with the barriers drawn around the obstacles, a playground for the barrier maths, the paper's numbers, and a simulated re-run of the study with the released algorithm.

Teaser (23 s): the suit, the exploded vibration unit, the study set-up with the RC controller, a hidden obstacle felt through the shoulder, and the three conditions flown through the same tunnel: RC controller alone, haptic joystick, AeroHaptix.

32
vibration units
voice-coil actuators, 32 × 22 mm, on the upper body; positions from a 10-person perceptual study
2.5ms
chain latency
two-byte UART messages at 115.2 kbaud, 125 µs per hop, 20 units on a chain
16 × 4 × 2
intensities · frequencies · waveforms
per unit, from a PIC16F18313 driving a DRV8837 H-bridge
−31%
collisions
7.5 → 5.2 per flight, no feedback → AeroHaptix, 12 participants (p < 0.05)
−44%
input disagreement
3.55 → 2.0 m/s² between what the pilot commanded and the safe input (p < 0.01)
82/100
haptic usefulness
versus 57 for the force-feedback joystick (p < 0.001); no extra workload over flying with nothing

In one strip

First-person view of the simulated tunnel with green, yellow and blue obstacles and a top-down inset
1 · Sense

Every obstacle gets a barrier

The drone is a double integrator. Each cube, sphere, pillar and wall gets a barrier function hi(q) ≥ 0 (a super-ellipsoid or a half-space), and the second-order barrier condition turns into one linear inequality on the acceleration input per obstacle.

Level sets of the barrier for a sphere and a cube, and the admissible half-planes in the input plane
2 · Decide

MultiCBF: one safe input per obstacle

If the pilot's input violates obstacle i's inequality, the closest input that satisfies it is computed for that obstacle alone. The size of the correction is the vibration intensity; the direction to the obstacle picks the actuator. Several obstacles can be felt at once.

A participant with the suit, a red circle marking the vibrating shoulder unit
3 · Feel

The body is the display

Vibration on the body leaves the hands free: the pilot keeps a normal RC controller, so the feedback cannot fight the input the way a force-feedback joystick does, and obstacles out of the camera's view are still felt.

The suit, in three dimensions

Thirty-two voice-coil units on a stretch garment, wired as four chains. Each unit is where the perceptual study said a given obstacle direction is felt: four rings of eight directions, polar angle 30°, 60°, 90° and 120° from straight up, every 45° around. The scene below places every unit by shooting its direction ray out of a torso model and stretching the exit point onto the shoulder line, chest, ribs and hips (the paper's Fig. 5 layout). Hover a unit to read it, move the pointer around the body to put an obstacle there, or link the suit to the flight replay further down.

INTERACTIVE 3-D · THE ACTUATOR LAYOUT

Where each obstacle direction lands on the body

Loading the scene…

Ring colours: 30° shoulder line · 60° chest and upper back · 90° ribs and waist · 120° hips and lower back. Directions further down (150°) were dropped: participants could not feel "below" on the upper body, so in the study obstacles under the drone were mapped to the lower-back units.

INTERACTIVE 3-D · ONE UNIT

Inside a vibration unit

Cap, PCB, rectangular enclosure, the voice-coil actuator, the cloth of the garment, and a bottom ring that press-fits through the fabric so a unit can be moved anywhere. Drag the slider to explode it.

Diagram of the suit with power converter, MCU and vibration units, and the exploded unit
From the paper's video: power converter and MCU on the upper back, units on the front and back, and the exploded unit (cap, PCB, enclosure, VCA, cloth layer, bottom ring).
  • Actuator: PUI Audio HD-VA3222 voice coil, 32 × 22 mm, 80 to 500 Hz, 2.52 g peak-to-peak at 133 Hz and 1.5 Vrms.
  • Driver: PIC16F18313 microcontroller and DRV8837 H-bridge on a custom board: 16 intensity levels, 4 frequencies, 2 waveforms, started and stopped by a UART command.
  • Chains: a central unit, a power converter and up to 20 units per chain. A command carries a target address that each unit decrements before passing it on: 125 µs per hop, 2.5 ms across 20 units. The released direction table shows the 32 units on four chains of 12, 7, 5 and 8.
The AeroHaptix suit on a mannequin, front
The suit: units on a blue stretch garment, the controller on the shoulder.
The AeroHaptix suit, back, with the controller and the chained units
The back: MCU, power converter and the wired chains.
Chain connection diagram: control unit, connector, vibration units with addresses 0 to 15
Chain topology, from the VibraForge toolkit the same lab built around this hardware.
HARDWARE

The vibration units, up close

Dozens of units with their status LEDs on a garment: the same chained hardware, as productised in the VibraForge toolkit (CHI 2025).

LAYOUT

From directions on a sphere to positions on a body

The 32 sampled directions and where each is felt on the torso model, colour-coded by ring.

Where do you feel "up-left-behind"?

A uniform ring of actuators around the waist does not give uniform coverage of directions: proprioception is biased. So the layout came from data. Ten participants wore a 46-unit grid (18 on the front, 18 on the back, three on each side of the waist, two on each shoulder, 8 cm apart) and a Meta Quest 2 headset. Each trial buzzed one unit; the participant pointed a controller ray in the direction they felt it from and clicked. 46 units × 5 repetitions × 10 people gave 2,300 position-to-direction pairs.

An MLP (five hidden layers of 64, ReLU) learned the inverse map, from a direction (ϑ, φ) on the sphere to a body position, with a total-variation penalty for smoothness. Then 32 directions were sampled uniformly (ϑ ∈ {30°, 60°, 90°, 120°}, φ every 45°) and pushed through the network. The result puts units on the more curved parts of the body, shoulders and waist, and drops the lowest ring because nobody could feel "below" on the upper body. Toggle the 46-unit study grid in the scene above to see both layouts on one body.

The 32 directions on the sphere and the front and back body maps with motor ids
The 32 directions and the body map used on this page (motor ids from the released direction table, positions from the torso model). The exact garment positions of the paper's Fig. 5 were not released; the model reproduces the rings, not the millimetres.

MultiCBF: a barrier per obstacle, a cue per barrier

The drone is modelled as a double integrator with state x = [q, q̇] and the acceleration command u as input. Every obstacle bi gets a barrier function that is positive outside it and zero on its safety boundary:

walls: h(q) = n̂ · (q − qb)  ·  cubes and spheres: h(q) = Σk ((qk − qb,k) / ak)n − 1  (n = 4 for cubes, 2 for spheres, a = size + 0.717 m)

Because u acts on the acceleration, the barrier has relative degree two and the exponential CBF condition is used:

ḧ + k2 ḣ + k1 h ≥ 0  ⇔  ∇h · u + [ Σk n(n−1) zkn−2 q̇k2/ak2 + k2 ∇h · q̇ + k1 h ] ≥ 0  =:  Ai u + bi ≥ 0

One linear inequality in u per obstacle. The global safe input is the QP that projects the pilot's uref onto all of them at once, which is what earlier CBF haptics rendered as a single force. MultiCBF instead computes a local safe input for each obstacle whose inequality uref violates:

usafe,i = argmin ½‖u − uref‖² s.t. Ai u + bi ≥ 0  =  uref − (Ai uref + bi) Ai / ‖Ai‖²  ·  Ij = ‖Kv(usafe,i − uref)‖  ·  j = argmaxk r̂k · (qb,i − q)/‖qb,i − q‖

The correction's size is the vibration intensity of the actuator whose direction r̂j best matches the direction to the obstacle. In the released code k1 = k2 = 6, Kv = 3 duty levels per m/s² (clipped to the 16 levels), an obstacle is considered within 5 m of its shell, and the two strongest units are kept per frame. The drone tracked the pilot's own velocity command; the cues informed, they never overrode.

One obstacle, step by step (9 s): the drone holds a forward stick and passes a cube. Top left: the level sets of h and the operator's input (white) against the local safe input (green). Top right: the admissible half-plane A·u + b ≥ 0 in the input plane moving with the state. Bottom: h, ḣ and the duty of the unit that fires, and the body map. The drone enters the barrier shell (h < 0) but never the cube: the shell is padded by 0.717 m plus the obstacle's size.

INTERACTIVE · THE BARRIER PLAYGROUND

Drag everything and watch the inequalities move

A top view with the study's obstacle types. Drag the drone, the tip of its velocity, the tip of the operator's stick, or any obstacle. The input plane shows every in-range half-space, uref, the global QP solution and each obstacle's local safe input; the ring shows which of the eight horizontal units MultiCBF drives. Preview flies the current stick for four seconds with and without the CBF filter; Animate lets you steer live by dragging the stick.

Live 3-D feed: the tunnel, the barriers, the cues

The study tunnel, 5 × 5 × 50 m with four walls and fifteen random obstacles, rebuilt in 3-D from the simulated study below. Every obstacle wears its barrier shell (h = 0): grey when idle, brighter when in range, yellow when the pilot's input violates it and a unit fires, red when the drone is inside it. The arrows are the velocity (blue), the pilot's input (white) and the safe input (green). Switch between the chase camera, the operator's first-person camera (which always faces +x, so the right and upward tunnels are flown blind), a top view and a free orbit; the inset always shows the other view. The body map on the side and the suit above, when linked, show the units MultiCBF drives at that instant.

INTERACTIVE 3-D · REPLAY OR FLY IT YOURSELF

Loading…

0.0 s
Loading the flights…

The replays are the simulated study's flights on one tunnel per direction (seed 4) with no feedback and with the cues. In fly it yourself, the same MultiCBF loop runs in your browser at 50 Hz: seed 0 is the replay's tunnel, other seeds are new tunnels of the same recipe. Plug in an Xbox controller and the sticks map as in the study.

What the paper measured

Twelve participants (seven with UAV experience) flew a simulated quadrotor through cluttered tunnels in Microsoft AirSim, 70 minutes each. Three feedback conditions in a Latin square: NA, an Xbox controller and no feedback; FSC, a Novint Falcon haptic joystick rendering the single-CBF correction as a force; VSC, the Xbox controller plus AeroHaptix driven by MultiCBF. Three flying directions per condition, each a 5 × 5 × 50 m tunnel with four walls and fifteen cubes, spheres and cylinders placed at random: forward, with the front camera looking where the drone goes; right and upward, where the camera looks +x and the obstacles arrive from the side or from above, mostly unseen.

Measured per flight: total distance, number of collisions, and input disagreement, the mean of ‖uref − usafe‖. Subjectively: NASA-TLX, four Likert questions on sense of control, and a situational-awareness probe: at a random 10 to 40 m the simulation paused and the participant listed the obstacles they perceived, split into visible ones and ones felt only through haptics.

Participant in the suit flying the simulated drone at a desk
▶ Full paper video

Objective results by feedback condition (left group) and by flying direction (right group), mean ± SEM, values read off the paper's Fig. 7 (± 0.2). Both AeroHaptix (VSC) and the force joystick (FSC) reduced collisions against no feedback, only VSC reduced the disagreement between the pilot and the safe input, and flying right or upward tripled the collisions of flying forward. Hover a bar for its value.

Left: the force joystick cost physical demand and effort; the suit did not, and scored far higher on "how much did the haptic feedback help". Right: participants reported more obstacles they had only felt with AeroHaptix than with the joystick (situational awareness), and more in the blind directions.

H1

Fewer collisions, less disagreement

Against no feedback, VSC cut collisions (p < 0.05) and input disagreement (p < 0.01). Accepted.

H2

Blind directions are where it matters

Flying right or upward caused about three times the collisions of flying forward (p < 0.01), and that is where haptic obstacles were reported most. Accepted.

H5

More awareness than a joystick

More felt-only obstacles were reported with VSC than with FSC (p < 0.05). Accepted. Workload (H3) and sense of control (H4) did not differ significantly between the two haptic conditions, though physical demand and effort favoured the suit.

The study, re-run in simulation

The paper's simulator was AirSim on a Windows laptop with the physical suit on a person; neither is on this page. What is here is the released algorithm, re-implemented and verified (barrier gradients against finite differences, the QP against SLSQP), driving a 50 Hz simulation of the same tunnel recipe with a modelled operator instead of a human. The operator sees obstacles through a 90° front camera and a weaker, later top-down inset; reacts to visual obstacles after 0.35 s and to cues after 0.35 s by pushing the stick away from the actuator's own direction; and flies at 2 m/s with a 0.15 s stick lag. Twenty-four tunnels per direction, the same tunnels for both conditions, 1,332 flights in all counting the sweeps. Numbers below are means ± SEM over tunnels.

The modelled operator reproduces the paper's pattern: forward is easiest, right and upward are worst without feedback, the cues cut collisions and disagreement in every direction. The size of the haptic benefit is larger than with real people (the model reacts to every strong cue), and the sweeps below show how quickly it shrinks as the operator gets slower or the cue gets weaker. Flights with cues are slower: the modelled operator brakes when a cue comes from ahead.

conditiondirectiontunnelscollisionsdistance [m]|u_ref − u_safe| [m/s²]time [s]cue on [% frames]
no feedbackforward242.92 ± 0.2155.4 ± 0.25.13 ± 0.2329.6 ± 0.10
no feedbackright245.71 ± 0.3254.7 ± 0.37.46 ± 0.4731.0 ± 0.30
no feedbackupward245.92 ± 0.3554.7 ± 0.37.61 ± 0.4931.3 ± 0.30
AeroHaptix cuesforward240.54 ± 0.1557.8 ± 0.33.01 ± 0.1038.0 ± 0.280
AeroHaptix cuesright240.67 ± 0.2057.1 ± 0.33.87 ± 0.1942.0 ± 0.485
AeroHaptix cuesupward240.83 ± 0.2657.2 ± 0.43.75 ± 0.1742.5 ± 0.586
← swipe the table →
FORWARD · NO FEEDBACK

Forward, nothing on the body

Chase view with the barrier shells, the body map, the top view and the timeline of h and duty. The operator sees what is ahead and still clips a few obstacles.

FORWARD · AEROHAPTIX

Forward, with the cues

The same tunnel, the same operator model. Units fire when the input violates a shell (yellow), and the path bends before the shell turns red.

SIDE BY SIDE

Top view race, forward

No feedback against AeroHaptix on the same tunnel: collisions as yellow crosses, the disagreement as it accumulates.

RIGHT · NO FEEDBACK

Sideways and blind

The tunnel runs to the right of the camera; obstacles are only noticed on the top-down inset, late.

RIGHT · AEROHAPTIX

Sideways, felt through the side units

The ribs-and-waist ring on the right side does most of the work here.

SIDE BY SIDE

Top view race, right

The blind direction is where the cues buy the most.

UPWARD · NO FEEDBACK

Climbing blind

Obstacles come from above the camera's view.

UPWARD · AEROHAPTIX

Climbing, felt through the shoulders

The shoulder-line ring fires for what is ahead along the climb; the lower-back units for what is below.

LOOP

Ten seconds in the chase view

The clip on the publication card.

Sweeps: what the benefit depends on

How many actuators? Cues quantised to 8 or 16 directions point up to 37° or 27° away from the obstacle and the operator dodges the wrong way more often; 32 directions (14° mean error) get most of what an exact direction gives. The 48-direction grid includes the ring the paper dropped and does not help.

Angular error of the cue for the same layouts, the geometric reason behind the left panel.

The operator matters more than the algorithm. Collisions against the delay between a cue and the stick response, for three intensity gains. A pilot who needs 0.8 s loses most of the benefit; a stronger gain (Kv = 6) buys some of it back. The dashed line is no feedback.

Barrier gains and padding. Small gains (k = 2) fire the cue too late to help; the paper's k = 6 is on the knee. More padding fires earlier and reduces collisions a little, at the price of a suit that buzzes most of the time and a much larger disagreement (12 m/s² at k = 12, 1.2 m).

How often a unit is on for the same sweep: the study's settings keep a unit active about 84 % of the frames in these dense tunnels.

Field of view barely matters; where the camera points does. Widening the front camera from 60° to 120° changes little in any direction, because the right and upward tunnels put the obstacles outside any forward-facing view.

Body maps with the number of frames each actuator fired, per tunnel direction
Which units fire, summed over the 24 VSC flights per direction. Forward: the front ring and the shoulder line (walls and obstacles ahead). Right: the right-side units. Upward: the shoulder line for what lies ahead along the climb, the lower back for what is below.
Time series of one flight: minimum barrier value, input disagreement, and a raster of the 32 actuators' duty
One VSC flight, frame by frame: the minimum h over obstacles, the disagreement, and the duty raster of the 32 units ordered by ring and azimuth. Cues come in bursts of a second or two, mostly one or two units at a time.
1

The algorithm is cheap and exact

With a 3-D input, the QP over all in-range constraints is solved exactly by enumerating the active sets of at most three rows, with a bound that prunes rows that cannot be active. Under 2 ms per 50 Hz frame in Python with fifteen obstacles and four walls, and it runs in your browser above.

2

Units of the input are the study's

The released code feeds the ECBF with u = vcmd − v, a velocity increment per frame rather than an acceleration, and applies the same to the drone. The re-run keeps this convention so the numbers are comparable; it is why the disagreement is reported in m/s² but scales with the stick.

3

What this cannot claim

No human, no AirSim physics, no real vibration perception: the operator model is a proxy whose parameters set the size of every effect. The paper's numbers stand on their own; the re-run shows the mechanism and which knobs it is sensitive to.

Reproduce

Everything on this page comes from one small Python package and a handful of scripts; there are no trained weights. The package holds the barriers, the exact QP, the released 32-direction table, the tunnel generator, the operator model and the 50 Hz loop; the scripts run the campaign in shards, draw the figures, render the videos and export the scene JSON the 3-D feed plays.

# AeroHaptix/experiments
python -m pytest -q tests                      # gradients vs finite differences, QP vs SLSQP, layout, cues, flights
python run_study.py main   --seeds 24 --shard 0 --nshards 3   # x3 shards
python run_study.py sweeps --seeds 12 --shard 0 --nshards 4   # x4 shards
python run_study.py merge                      # out/study.json + the summary tables
python make_figures.py                         # docs/figures/*.pdf, site PNGs, results JSON, numbers.tex
python make_videos.py --which all              # out/video/*.mp4 -> assets/videos/
python export_web.py                           # assets/data/aerohaptix_scene.json for the 3-D feed
cd ../docs && make                             # aerohaptix.pdf, the technical report

Files. aerohaptix/cbf.py (SuperEllipsoid, Cylinder, Plane, local_safe, global_safe), suit.py (Layout, render_cues, the torso model), world.py (Tunnel), pilot.py (the operator), sim.py (fly). The browser twin is assets/js/aerohaptix_cbf.js; the scenes are aerohaptix_scene3d.js (three.js), the playground aerohaptix_playground.js, the charts aerohaptix_plots.js.

Seeds. Tunnels are seeded per (direction, seed); the operator's noise is seeded per tunnel, so a flight is a deterministic function of (direction, seed, condition) and the same tunnels are flown under every condition.

The paper's own code (AirSim client, Falcon bindings, the ECBF classes and the BLE tactile module) is at huangbj16/DroneSimulation; the actuator direction table on this page is that repository's ActuatorDirections_norm.txt.

Technical report (PDF): the derivations, the solver, the operator model, every figure with its numbers, and the limitations.

Credits

AeroHaptix: A Wearable Vibrotactile Feedback System for Enhancing Collision Avoidance in UAV Teleoperation. Bingjian Huang, Zhecheng Wang, Qilong Cheng, Siyi Ren, Hanfeng Cai, Antonio Alvarez Valdivia, Karthik Mahadevan and Daniel Wigdor. IEEE Robotics and Automation Letters, 2025 (arXiv 2407.12105, July 2024). Dynamic Graphics Project, University of Toronto.

The hardware line continues as VibraForge (CHI 2025), an open-source toolkit for large vibrotactile arrays. Teaser video, study frames and the chain diagrams are from the paper and its video; the 3-D suit, the playground, the flights, the re-run figures and the report on this page are mine, built on the released code. The single-CBF haptic teleoperation MultiCBF extends is Zhang, Yang and Khurshid, IEEE Transactions on Haptics 13(1), 2020.