Back to Sensors & Actuators Series

Robotic Joint Actuators: Harmonic Drive, QDD, SEA & FOC

April 10, 2026 Wasil Zafar 19 min read

The muscles of every robot — joint actuators define whether a robot is precise, compliant, or powerful. Master harmonic drives, direct-drive, SEA transmissions, FOC control, and practical code.

Contents

  1. Overview & Types
  2. Working Principle
  3. Typical Joint Actuator Specs
  4. Driver Circuits & Electronics
  5. Control Methods
  6. Code Example — Arduino & ESP32
  7. Real-World Applications
  8. Advantages by Type
  9. Limitations & Considerations

Overview & Types

Robotic joint actuators are the muscles of every robot arm, legged robot, and humanoid. Each joint requires a motor-transmission-sensor package optimized for that joint’s specific demands — torque, speed, backdrivability, and compliance. The choice between a geared servo and a direct-drive motor, or between a rigid link and a series elastic actuator, defines the robot’s capability, safety, and personality.

Key Insight: The trend in modern robotics is toward quasi-direct-drive actuators — high-torque motors with low-ratio gears (5:1–10:1) — because they’re backdrivable. Backdrivability means a human can push the robot arm aside, enabling safe human-robot collaboration without expensive force/torque sensors.

Types

  • Geared Servo Actuator: Brushless motor + harmonic drive (100:1–160:1) or cycloidal reducer. Very high torque density, zero backlash. Standard in industrial robot arms (FANUC, ABB). Not backdrivable.
  • Direct-Drive Motor: Large-diameter, high-torque BLDC motor with no gearbox. No backlash, fully backdrivable, transparent force control. Lower torque density than geared. Used in MIT Cheetah, research arms.
  • Quasi-Direct-Drive (QDD): High-torque BLDC + low-ratio planetary (5:1–10:1). Compromise — good torque density AND backdrivability. Used in legged robots (Unitree, Boston Dynamics).
  • Series Elastic Actuator (SEA): Motor + gearbox + compliant spring element. The spring acts as a force sensor and energy store. Inherently safe for human interaction. Used in rehabilitation robots and prosthetics (MIT SEA, Meka).
  • Cable/Tendon-Driven: Remote motors connected to joints via cables/tendons. Motors placed at base (reduces inertia), but cable stretch and routing add complexity. Used in surgical robots (da Vinci), dexterous hands.
  • Hydraulic Rotary Actuator: Hydraulic motor or vane actuator at joint. Highest power density. Used in heavy-duty robots (Boston Dynamics Atlas early versions, excavators).
  • Pneumatic Muscle (PAM): McKibben muscles or pneumatic cylinders. Lightweight, compliant, high power-to-weight. Used in rehabilitation exoskeletons and bio-inspired robots.

Working Principle

Harmonic Drive (Strain Wave)

  1. Wave Generator: Elliptical cam rotates inside a flexible spline (flex spline), deforming it.
  2. Tooth Engagement: The deformed flex spline meshes with the circular spline (rigid outer ring). The flex spline has 2 fewer teeth than the circular spline.
  3. Reduction: Each wave generator revolution advances the flex spline by 2 teeth, giving reduction ratios of 30:1 to 320:1. Zero backlash due to multi-tooth engagement.

Series Elastic Actuator

A known-stiffness spring between motor output and joint link. Joint torque = spring stiffness × spring deflection, measured by an encoder. This turns a stiff motor into a force-controlled actuator. Benefits: force sensing without load cells, energy storage for walking, shock absorption, inherent impact safety.

Robotic Joint Actuator Comparison

TypeTorque DensityBackdrivableBandwidthBest For
Harmonic Drive★★★★★NoMediumIndustrial arms, high precision
Direct Drive★★Yes ★★★★★HighForce control, haptics, research
Quasi-Direct (QDD)★★★Yes ★★★★HighLegged robots, cobots
SEA★★★★Yes ★★★Low-MedSafe HRI, prosthetics, walking
Cable-Driven★★★ (remote)PartialMediumDexterous hands, surgical

Typical Joint Actuator Specifications

ParameterIndustrial (Harmonic)QDD (Legged Robot)SEA (Cobot/Rehab)
Motor TypeFrameless BLDCOutrunner BLDCBLDC + gearbox
Gear Ratio100:1–160:16:1–10:150:1–100:1 + spring
Peak Torque50–1000 Nm20–80 Nm10–100 Nm
Continuous Torque20–300 Nm5–20 Nm5–30 Nm
Max Speed6–60 RPM (output)20–200 RPM10–60 RPM
Position Resolution0.001°0.01°0.01° (+ force)
Weight (actuator)0.5–10 kg0.2–2 kg0.5–5 kg
Voltage24–48 VDC24–48 VDC24–48 VDC

Driver Circuits & Electronics

FOC Motor Driver

Field-Oriented Control (FOC) is standard for robotic joint BLDC motors. Measures phase currents, transforms to d-q frame, runs inner current loops at 10–40 kHz. Controllers: ODrive, Moteus, SimpleFOC, TI LAUNCHXL-F28069M.

Encoder Interface

High-resolution absolute encoders (14–19 bit) on both motor and output sides. Motor-side encoder for commutation; output-side encoder for joint position (avoids gear backlash error). Common interfaces: SPI, BiSS-C, SSI, ABZ incremental.

Current Sensing

Inline shunt resistors or hall-effect sensors measure phase current for torque control (τ = Kt × Iq). 12–16 bit ADC at 10+ kHz sampling rate.

Safety Architecture: Collaborative robots require dual-channel safety: torque limiting (motor current), velocity limiting (encoder rate), and collision detection (torque observer). Both channels must agree, or the joint locks.

Control Methods

Cascaded PID (Position → Velocity → Current)

Standard industrial approach. Inner current loop (10–40 kHz) → velocity loop (1–5 kHz) → position loop (100–1000 Hz). Provides stiff, accurate position tracking. Not naturally compliant.

Impedance Control

Controls the relationship between force and position: the joint behaves like a virtual spring-damper. Essential for safe human-robot interaction. Requires torque sensing (SEA spring, current-based estimation, or F/T sensor).

Torque (Current) Control

Direct torque control via motor current (τ = Kt × Iq). Used in direct-drive and QDD robots. Requires backdrivable actuator. Enables gravity compensation, force-guided teaching, and compliant manipulation.

Code Example — Arduino & ESP32

Arduino: Hobby Servo Joint with PID Position Control

// Precision servo joint with external encoder feedback
// Standard hobby servo → PWM on D9
// External encoder (AS5600, I2C) → actual position
// PID corrects for servo deadband and load drift

#include <Wire.h>
#include <Servo.h>

#define AS5600_ADDR 0x36
Servo jointServo;

float Kp = 0.5, Ki = 0.01, Kd = 0.1;
float integral = 0, prevError = 0;
float targetAngle = 90;  // degrees

void setup() {
    Serial.begin(9600);
    Wire.begin();
    jointServo.attach(9);
    jointServo.write(90);
    Serial.println("Servo Joint PID Controller");
    Serial.println("Send angle (0-180):");
}

float readEncoder() {
    Wire.beginTransmission(AS5600_ADDR);
    Wire.write(0x0E);  // Angle register
    Wire.endTransmission(false);
    Wire.requestFrom(AS5600_ADDR, 2);
    int raw = (Wire.read() << 8) | Wire.read();
    return (raw / 4096.0) * 360.0;
}

void loop() {
    if (Serial.available()) {
        float angle = Serial.parseFloat();
        if (angle >= 0 && angle <= 180) {
            targetAngle = angle;
            integral = 0;
            Serial.print("Target: "); Serial.println(angle);
        }
    }

    float actual = readEncoder();
    // Map encoder 0-360 to servo 0-180 range (adjust for mounting)
    float mappedActual = actual / 2.0;  // Simplified mapping

    float error = targetAngle - mappedActual;
    integral += error * 0.02;  // dt ≈ 20ms
    integral = constrain(integral, -30, 30);
    float derivative = (error - prevError) / 0.02;
    prevError = error;

    float output = targetAngle + Kp * error + Ki * integral + Kd * derivative;
    output = constrain(output, 0, 180);
    jointServo.write((int)output);

    static unsigned long lastPrint = 0;
    if (millis() - lastPrint > 200) {
        Serial.print("Target: "); Serial.print(targetAngle, 1);
        Serial.print(" Actual: "); Serial.print(mappedActual, 1);
        Serial.print(" Error: "); Serial.println(error, 2);
        lastPrint = millis();
    }
    delay(20);
}

ESP32: BLDC Joint with FOC Torque Control

// ESP32 BLDC joint actuator with SimpleFOC
// Motor: gimbal BLDC (e.g., GB2208)
// Driver: DRV8302 or SimpleFOC shield
// Encoder: AS5048A (SPI)

#include <Arduino.h>
// Note: Requires SimpleFOC library installation
// #include <SimpleFOC.h>

// Simplified FOC concept (pseudo-code structure)
// In real implementation, use SimpleFOC library

#define PWM_A 25
#define PWM_B 26
#define PWM_C 27
#define ENCODER_CS 5   // SPI chip select for AS5048A

float motorAngle = 0;
float targetTorque = 0;  // Nm
float Kt = 0.05;  // Torque constant (Nm/A)

void setup() {
    Serial.begin(115200);
    pinMode(PWM_A, OUTPUT);
    pinMode(PWM_B, OUTPUT);
    pinMode(PWM_C, OUTPUT);

    Serial.println("BLDC Joint Torque Controller");
    Serial.println("Commands:");
    Serial.println("  T[value] - Set torque (e.g., T0.5)");
    Serial.println("  P[value] - Set position (e.g., P90)");
    Serial.println("  Z - Zero torque (compliant mode)");
}

float readEncoderAngle() {
    // In real code: SPI read from AS5048A
    // Returns 0-360 degrees
    return motorAngle;  // Placeholder
}

void setPhaseVoltages(float Ua, float Ub, float Uc) {
    // In real code: set PWM duty cycles
    // Ua, Ub, Uc are 0-1.0 normalized voltages
    analogWrite(PWM_A, (int)(Ua * 255));
    analogWrite(PWM_B, (int)(Ub * 255));
    analogWrite(PWM_C, (int)(Uc * 255));
}

void foc_step(float targetIq) {
    // Simplified FOC concept:
    // 1. Read rotor angle (encoder)
    float angle = readEncoderAngle();

    // 2. Clarke + Park transform on measured currents
    //    (requires current sensors - omitted for clarity)

    // 3. PI current controller to compute Vd, Vq

    // 4. Inverse Park + SVM to compute phase voltages
    float elAngle = angle * 7;  // 7 pole pairs example
    float rad = elAngle * PI / 180.0;

    // Simplified inverse Park (Vd=0, Vq proportional to desired Iq)
    float Vq = targetIq * 2.0;  // Simplified gain
    float Va = -Vq * sin(rad);
    float Vb = -Vq * sin(rad - 2.094);  // -120°
    float Vc = -Vq * sin(rad + 2.094);  // +120°

    // Normalize to 0-1
    float vmin = min(min(Va,Vb),Vc);
    float vmax = max(max(Va,Vb),Vc);
    float range = vmax - vmin;
    if (range < 0.01) range = 0.01;

    setPhaseVoltages((Va-vmin)/range, (Vb-vmin)/range, (Vc-vmin)/range);
}

void loop() {
    if (Serial.available()) {
        char cmd = Serial.read();
        if (cmd == 'T' || cmd == 't') {
            targetTorque = Serial.parseFloat();
            Serial.printf("Torque: %.2f Nm\n", targetTorque);
        } else if (cmd == 'Z' || cmd == 'z') {
            targetTorque = 0;
            Serial.println("Zero torque (compliant)");
        }
    }

    float targetIq = targetTorque / Kt;
    foc_step(targetIq);

    // Update simulated angle (in real code: read encoder)
    motorAngle += 0.1;
    if (motorAngle > 360) motorAngle = 0;

    delay(1);  // ~1 kHz loop (real FOC runs at 10-40 kHz)
}

Real-World Applications

Robotic Arms & Legs

  • Industrial 6-DOF arms (harmonic drives)
  • Quadruped legs (QDD, e.g., MIT Mini Cheetah)
  • Humanoid joints (Agility, Tesla Optimus)
  • Collaborative robots / cobots (SEA)

Specialized

  • Surgical robot joints (cable-driven, da Vinci)
  • Prosthetic knee/ankle (SEA, impedance control)
  • Exoskeleton hip/knee (pneumatic muscle, SEA)
  • Space manipulator joints (harmonic drive)

Advantages by Type

ComparisonAdvantageLimitation
Harmonic vs PlanetaryZero backlash, compact, high ratioNot backdrivable, expensive, limited life under shock
Direct-Drive vs GearedPerfect backdrivability, fast force control, no backlashLow torque density, large heavy motors
QDD vs Direct-DriveBetter torque density, still backdrivableSome gearing losses, planetary has backlash
SEA vs RigidInherent force sensing, shock protection, safe HRILower bandwidth, spring adds weight/length
Cable vs CoaxialMotor mass at base (lower limb inertia)Cable stretch, routing constraints, friction

Limitations & Considerations

  • Thermal Limits: Joint actuator torque is limited by motor thermal capacity. Continuous operation near peak torque overheats windings. Heat sinking and thermal management are critical.
  • Reflected Inertia: High gear ratios multiply rotor inertia by N². A 100:1 harmonic drive multiplies motor inertia 10,000×, making the joint feel “heavy” and limiting impact rejection.
  • Backlash: Planetary and spur gear trains have backlash (0.1–1°). Harmonic drives have near-zero backlash but cost 5–20× more. Backlash causes position oscillation in stiff control modes.
  • Compliance vs. Accuracy: Compliant actuators (SEA, direct-drive) sacrifice absolute position accuracy for force transparency. Applications needing sub-0.01° precision still require stiff harmonic drive actuators.
  • Cable Routing: Cable-driven joints need careful cable path design, tensioning, and fatigue-resistant cables (Dyneema/spectra). Cable replacement is maintenance-intensive.
  • Cost: A single harmonic drive actuator module (motor + HD + encoder + driver) costs $500–$5,000. A 6-DOF arm with 6 such joints represents significant BOM cost.