VinUniversity

A Stewart platform neck that follows a face

A six-servo Stewart platform built as a neck for the Unitree G1 humanoid, with a camera in its head that keeps a face in view. I designed the electrical system and wrote the tracking and control code.

The neck from the front: a black 3D-printed head with a webcam in its forehead, on a small top plate held by six rods from six red servos on a hexagonal base. The same neck from the side, showing the curved head shell and the rods from the servo arms up to the top plate.
The prototype on the bench: the camera sits in the 3D-printed head, and six servos under the top plate turn and tilt it.

Goal

A humanoid looks more attentive when it turns its head toward the person in front of it. The goal was a neck that does this on its own: a Stewart platform, six servos moving one plate, steered by a camera that tracks a face, within ±15° of yaw and ±10° of pitch. The platform's geometry was tuned in MATLAB, over more than three million configurations, to keep every pose within the servos' range.

What I built

Power and noise

Six JX PDI-6221MG servos run from a 6 V, 10 A switching supply through a PCA9685 PWM driver, commanded by an Arduino Uno. The first design ran everything on a Raspberry Pi 5, which failed from heat after long runs above 75 °C, so the vision moved to a PC and the Arduino kept the real-time servo control.

Moving together, the servos drew peaks above 7 A that pulled the 6 V rail below 4.5 V, resetting the Arduino and making the servos unstable, while noise from shared power and signal lines put jitter on the PWM. I added 1000 µF decoupling capacitors on the power distribution, routed signal and power cables apart, and split the ground into logic and power domains.

The open base: a blue PCA9685 servo board and an Arduino Uno, with servo leads and a USB cable, under the servo plate.
The Arduino Uno and the PCA9685 in the base.
A hand lifts the servo plate above the base; in front lies the metal switching power supply with its wiring.
The servo plate lifted off, and the 6 V, 10 A supply.

Tracking

A Haar cascade finds the face and a CSRT tracker follows it from frame to frame; if the tracker loses the face for more than 10 frames, a fresh detection takes over. The camera is calibrated with a chessboard of 11 × 11 inner corners and 3 cm squares, photographed 44 times, so the face's position is undistorted before it becomes a yaw and a pitch angle.

Control

The angles pass a dead zone of about 0.9°, so the head ignores small shifts, then exponential smoothing (α = 0.3) and clamping to the platform's range, with a tighter limit when both axes move at once. Inverse kinematics turns the head's pose into six servo-arm angles, and those into pulse widths, which go over UART at 115,200 bps, 50 times a second. The Arduino checks each against its servo's limits before writing it to the PCA9685. A bad value falls back to the neutral pulse, a lost face recentres the head, and servo control runs in its own thread, apart from the vision loop.

Diagram. Tracking at 30 FPS: camera, face detection with Haar and CSRT, yaw and pitch angles, then a filter that smooths and clamps them. Control at 50 Hz: kinematics gives six arm angles, limits are checked per servo, and the Arduino drives six servos through a PCA9685. Bad values fall back to neutral; a lost face recentres the head.
From a face in the camera to six servo pulses.

Result

The head follows a face at 30 FPS with 48.6 ms of end-to-end latency. With the power fixes, PWM jitter fell from ±8 µs to ±1.5 µs and the Arduino stopped resetting under full load. These results are from the bench; the platform has not yet been mounted on the G1.

What I learned

  • Sizing a servo supply for peak current, not average: six servos moving together drew more than 7 A.
  • Treating decoupling, cable routing and grounding as part of the design, since they decided whether the controller stayed up.
  • Keeping real-time servo output on a microcontroller and the heavy vision on a separate computer.
  • Making tracking feel steady: the dead zone, smoothing and limits mattered as much as the detector.
  • Turning a head pose into servo commands through a Stewart platform's inverse kinematics.