← All work
2023 · Royal College of Art · Physical computing

Gesture

A new approach to passwords: a lock with no keypad, that reads four hand gestures and the exact angle each one turns to. It opens only when all four are right.

Machine learning Gesture recognition Arduino Physical computing

Project overview

A device exploring a new approach to passwords: a smart-lock structure that uses machine learning to recognise gestures. Each small circular ring corresponds to the angle of a finger and is driven by its own servo. When all the gestures are correct, the lock opens.

A keypad password is something the user knows, which means anyone standing behind them can know it as well. This one is something the user performs, in the air, at a distance. The distinguishing information is not only which gesture is made but how far it is turned, so the password is four gestures each carrying a continuous angle, and all four have to land.

The whole interaction: a hand turns in the air, the matching ring turns with it

My contributions

Design point

The design logic is that each gesture corresponds to a circle, and the rotation angle of the gesture controls the actual rotation of that circle. When all four gestures are rotated to their specified angle, the iris structure rotates open and the internal push rod pushes the locked item out.

The interface is the mechanism. No screen reports progress, because the ring is the readout: it tracks the user's hand continuously, so the distance still to travel is visible in the object itself and can be corrected in real time.

A strip of five photographs of a hand against a grey background: one finger, two fingers, three fingers, four fingers and an open palm, each with a double-headed arrow showing the rotation the gesture controls
The vocabulary. Four counted gestures, each mapped to a ring, plus the open palm that commits the sequence. The arrows are the second dimension: the amount of rotation is as much of the password as the gesture itself.

Technical implementation

The signal chain

Four tools, five stages, one continuous path from a hand in the air to a servo horn holding a specific number of degrees.

handVision OSCProcessingWekinator ProcessingArduinoservo, in degrees
openFrameworks logo 01
Vision OSC Input hand signals, use VisionOSC to recognise hand gestures, and output signals to Processing.
Processing logo 02
Processing Collect the OSC messages and convert them into binary signals Wekinator can analyse.
Wekinator logo 03
Wekinator Two models on the same input: classification to identify which gesture, and a custom regression to read the exact degree of rotation.
Arduino logo 04
Arduino Receives both signals and drives the precise rotation of a specific servo according to gesture and degree, achieving mechanical control.

Stage three is where the lock gets its resolution. A single classifier would have produced a device with four states. Running classification and regression on the same input stream gives every gesture a continuous value alongside its identity, so the password space is four gestures multiplied by an angle rather than four gestures alone.

Recognition running live: the hand is tracked on camera and turned into a stream of values before it ever reaches the lock

Hardware

The device consists of four SG92R micro servos, one MG996R servo, one MG995R servo, and an Arduino, addressed through a PCA9685 driver.

An SG92R micro servo: a small blue and pink plastic servo with three wires
SG92R × 4 · micro servo Controls the motion of the disc and connecting rod. One per finger ring.
An MG996R servo: a black digital high-torque servo with a metal output spline
MG996R × 1 · continuous rotation Rotates continuously; used to control the opening and closing of the iris structure.
An MG995 servo: a black high-speed servo with a metal output spline
MG995R × 1 · high speed Controls the movement of the telescopic structure that pushes the locked item out.

The wire protocol

Wekinator emits a new prediction many times a second, and the microcontroller has to act on each one without ever getting confused about where a message starts. The format that solves this is deliberately the dumbest one available: a fixed four-byte frame, no delimiters, no handshake, nothing to parse.

byte 0 3 gesture id
bytes 1–3 0 8 5 angle in degrees, zero-padded to three digits

Fixed width is what makes Serial.available() >= 4 a sufficient test for a complete message. Zero-padding removes the only ambiguity a variable-length angle would introduce, so the firmware never has to look for a terminator, never blocks waiting for one, and cannot desynchronise from a dropped byte for longer than a single frame.

Three decisions behind the firmware

Firmware sketch, in full
#include "PCA9685.h"
#include <Wire.h>
ServoDriver servo;
const int servoR1Pin = 1;
const int servoR2Pin = 2;
const int servoR3Pin = 3;
const int servoR4Pin = 4;
const int servoDoorPin = 5;
const int servoR6Pin = 6;
const int minValidAngle = 20;
const int maxValidAngle = 180;

void setup() {
  Wire.begin();
  Serial.begin(9600);
  servo.init(0x7f);
}

void loop() {
  static bool servoDoorMoved = false;
  if (Serial.available() >= 4) {
    char classification = Serial.read();
    int angle = 0;
    for (int i = 0; i < 3; i++) {
      char digit = Serial.read();
      if (digit >= '0' && digit <= '9') angle = angle * 10 + (digit - '0');
    }
    switch (classification) {
      case '1': servo.setAngle(servoR1Pin, angle); break;
      case '2': servo.setAngle(servoR2Pin, angle); break;
      case '3': servo.setAngle(servoR3Pin, angle); break;
      case '4': servo.setAngle(servoR4Pin, angle); break;
      case '5':
        if (!servoDoorMoved) {
          // open once, then latch: predictions keep arriving after the
          // sequence completes and the iris must not be driven again
          servo.setAngle(servoDoorPin, 180);
          delay(5000);
          servo.setAngle(servoR6Pin, 179);
          delay(2000);
          servo.setAngle(servoR6Pin, 90);
          servoDoorMoved = true;
        }
        break;
    }
  }
}

Structure

The mechanism was drawn, sectioned and laser cut, then assembled around the servo positions.

Two CAD views of the device: a wireframe showing the concentric ring plate with the servo bank and linkages behind it, and a second view of the assembled front face
CAD: rings at the front, servo bank behind
A technical section drawing of the device: exploded layer stack on the left with dimensions, and a coloured cutaway on the right showing the push rod in red and the base in blue
Section: the layer stack and the push rod that ejects the item
A close-up of the device's front face at a raking angle: concentric laser-cut rings standing proud of a white panel, each with its own shadow
The laser-cut ring stack, raking light
The finished device standing on a white surface: a square panel with concentric rings, a dark iris at the centre and small black markers at ring positions
At rest, all rings home
The back of the device: the servo bank in a row, wiring loom and the Arduino behind the ring panel
Behind the panel: the servo bank and loom

In use

Each gesture, held in front of the device, moves its own ring.

A hand held in front of the device with one finger extended, the corresponding ring turned to its position
A hand pointing towards the device with markers moved to a new position on the rings
A hand with two fingers extended in front of the device, another ring rotated
A hand with fingers spread in front of the device, several ring markers now at their target angles
An open palm held above the device, the gesture that commits the sequence

Demonstrated

The five clips below are the sequence in order, shown and tested with people who had never used the device before.

Each gesture unlocks one layer. The first gesture, held at its angle, releases the first lock; the second releases the second, and so on through the fourth. The fifth gesture, the open palm, commits the sequence: the iris rotates open, the push rod extends, and the ball drops out. Nothing happens at all until every layer before it has been cleared, so a wrong angle anywhere in the chain simply leaves the mechanism where it was.

Lock 1
Lock 2
Lock 3
Lock 4
Lock 5 · the lock opens
← Entropy Illustrator →