Control Algorithms for Robotics

Control algorithms convert a desired behavior — a joint angle, a velocity, a trajectory from the path planner — into actuator commands, using feedback from sensors to correct errors and reject disturbances. This page covers the feedback loop, PID control with a runnable simulation, state-space methods (LQR), model predictive control, and how learned controllers compare.


1. The Feedback Loop

Feedback Control Loop Reference rsetpoint Σ e ControllerPID / LQR / MPC u Plantrobot dynamics y Outputposition, speed Sensor+ noise − Disturbances act on the plant; feedback corrects them without needing a perfect model.

The controller sees the error e(t) = r(t) − y(t) between the reference and the measured output, and computes an input u(t). Closed-loop control tolerates model error and disturbances (a gust, a heavier payload) because it reacts to what actually happens. The state measured in feedback typically comes from the estimator described in Perception & SLAM.

2. PID Control

Step Response: Effect of PID Gains 1.0 time → high Kp, low Kd: overshoot, ringing well tuned: fast, small overshoot too damped: slow rise

u(t) = Kp e(t) + Ki ∫ e dτ + Kd de/dt. The proportional term reacts to current error, the integral removes steady-state offset (e.g. gravity on an arm), and the derivative damps oscillation by reacting to the error's rate of change. PID needs no model and is still the most common controller in industry, from motor current loops to drone attitude.

import numpy as np

class PID:
    def __init__(self, kp, ki, kd, u_min=-10, u_max=10):
        self.kp, self.ki, self.kd = kp, ki, kd
        self.u_min, self.u_max = u_min, u_max
        self.integral, self.prev_y = 0.0, None

    def step(self, r, y, dt):
        e = r - y
        d = 0.0 if self.prev_y is None else -(y - self.prev_y) / dt   # derivative on measurement
        self.prev_y = y
        u = self.kp * e + self.ki * self.integral + self.kd * d
        u_sat = np.clip(u, self.u_min, self.u_max)
        if u == u_sat:                                               # anti-windup: integrate only if unsaturated
            self.integral += e * dt
        return u_sat

# Plant: mass on a damped track, m*a = u - c*v
m, c, dt = 1.0, 0.5, 0.01
pos, vel = 0.0, 0.0
pid = PID(kp=8.0, ki=2.0, kd=4.0)
for k in range(1000):
    u = pid.step(r=1.0, y=pos, dt=dt)
    acc = (u - c * vel) / m
    vel += acc * dt; pos += vel * dt
print(f"position after 10 s: {pos:.3f}")

Tuning methods include manual tuning (raise Kp until oscillation, add Kd to damp, add Ki to remove offset), Ziegler-Nichols, and model-based tuning. Cascaded loops (position → velocity → current) are standard in motor drives.

3. State-Space Control and LQR

With a linear model ẋ = A x + B u, the Linear Quadratic Regulator finds the gain K in u = −K x minimizing ∫ (xT Q x + uT R u) dt. Q penalizes state error and R penalizes control effort, giving an intuitive tuning knob. K = R-1 BT P, where P solves the continuous algebraic Riccati equation.

import numpy as np
from scipy.linalg import solve_continuous_are

# Cart-pole linearized about upright (state: x, x_dot, theta, theta_dot)
g, M, mp, l = 9.81, 1.0, 0.1, 0.5
A = np.array([[0, 1, 0, 0],
              [0, 0, -mp * g / M, 0],
              [0, 0, 0, 1],
              [0, 0, (M + mp) * g / (M * l), 0]])
B = np.array([[0], [1 / M], [0], [-1 / (M * l)]])
Q = np.diag([1, 1, 10, 1]); R = np.array([[0.1]])
P = solve_continuous_are(A, B, Q, R)
K = np.linalg.solve(R, B.T @ P)
print("LQR gain:", K.round(2))
print("closed-loop eigenvalues:", np.linalg.eigvals(A - B @ K).round(2))  # all negative real parts = stable

4. Model Predictive Control

Model Predictive Control: Receding Horizon Measure statex(k) Solve QP / NLPmin Σ cost over N stepss.t. dynamics, limits Apply u(k)first input only k ← k + 1shift horizon Explicitly handles constraints (torque limits, obstacles) that PID and LQR cannot, at higher compute cost.

MPC repeatedly solves a finite-horizon optimal control problem online, applies the first input, and re-plans at the next step. It handles input and state constraints directly and can follow a reference trajectory with preview. Costs: a reasonably accurate model, and a solver that finishes within the control period (fast QP solvers such as OSQP, or acados for nonlinear MPC). It is standard on autonomous vehicles, legged robots and process control.

5. Learned Controllers and Trade-offs

MethodNeeds model?ConstraintsTypical use
PIDNoSaturation onlyMotors, single-axis loops
LQRLinear modelNoBalancing, stabilization near an operating point
MPCYesYes, explicitVehicles, legged robots, trajectory tracking
RL policySimulatorVia reward / shieldingLocomotion, dexterous manipulation

RL policies (often trained with PPO in simulation) can learn behaviors that are hard to model, but offer weaker guarantees; deployments often wrap them with a classical low-level controller or a safety filter.

6. Implementing PID on Real Hardware

Discrete PID with Anti-Windup e[k] = r - y sample at Ts P: Kp e proportional I: sum Ki e Ts clamped D: filtered on measurement Sum u_raw Saturate actuator limits Plant motor, arm stop integrating while saturated

On a microcontroller, PID runs at a fixed sample period Ts. The textbook equation becomes u[k] = Kpe[k] + KiTsΣe + Kd(e[k] − e[k−1])/Ts. Four details separate a working controller from one that oscillates or saturates:

Worked example: with Kp = 2, Ki = 1, Kd = 0.1, Ts = 0.01 s, a setpoint of 1.0 and a measurement of 0.8, the error is 0.2. If the previous error was 0.25 and the accumulated integral (before this step) was 0.5, then P = 0.4, I = 1 × (0.5 + 0.2 × 0.01) = 0.502, D = 0.1 × (0.2 − 0.25)/0.01 = −0.5, and u = 0.402. The derivative term is pulling back because the error is shrinking quickly, which is exactly the damping it is meant to provide.

7. Cascaded Control and Stability Margins

Cascaded Loops in a Motor Drive Position loop P or PI, slowest Velocity loop PI, faster Current loop PI, fastest Motor + load encoder feedback

Industrial drives nest loops: the innermost current (torque) loop runs fastest, often at tens of kHz in the drive electronics; a velocity loop wraps it; a position loop wraps that. Each outer loop treats the inner loop as an almost ideal actuator, which only works if the inner loop is several times faster. Tune inside-out: current first, then velocity, then position.

Classical analysis asks how much extra gain or delay the loop tolerates before becoming unstable. Gain margin and phase margin from a Bode plot of the open loop are the standard measures; phase margins of roughly 45–60 degrees are a common design target because they give a well-damped step response. Time delay (communication, computation, sensor filtering) erodes phase margin directly, which is why networked or vision-in-the-loop controllers must be tuned more conservatively.

8. Estimation: Closing the Loop on Noisy Sensors

Controllers such as LQR assume access to the full state, but robots measure only parts of it, with noise. A state estimator fills the gap. For linear systems with Gaussian noise, the Kalman filter is optimal, and by the separation principle the LQR gain and Kalman gain can be designed independently (together, LQG). Nonlinear robots use the extended or unscented Kalman filter, or complementary filters for attitude (fusing gyro integration with accelerometer gravity direction). Poor estimation is a frequent root cause of controller "instability": a lagging velocity estimate behaves like extra delay in the loop.

9. Choosing a Controller

SituationReasonable choiceWhy
Single motor, unknown modelPID (cascaded)No model needed, cheap, well understood
Balancing robot, quadrotor near hoverLQR on a linearized modelHandles coupled states with one gain matrix
Hard limits on states and inputs, preview of the pathMPCConstraints are part of the optimization
Contact-rich manipulation, legged locomotionMPC, whole-body control, or learned policy with a low-level PDHybrid dynamics are hard to model analytically
Model only available as a simulatorReinforcement learning with domain randomizationLearns from simulated experience; needs careful sim-to-real

Learned policies are commonly deployed as high-level controllers that output joint position targets, with a classical PD loop underneath running at a higher rate. Safety layers (torque limits, joint limits, control barrier functions) stay classical regardless.

10. Further Reading

Related: Perception and SLAM, Reinforcement Learning.