Chapter 12: Advanced PID Design and Implementation

Lesson 2: PID Design Using Frequency-Response Methods

This lesson develops a rigorous frequency-domain framework for designing PID controllers. We describe how the proportional, integral, and derivative terms shape the open-loop frequency response \( L(\mathrm{j}\omega) \) of the plant–controller combination in order to meet bandwidth, stability margin, and steady-state accuracy constraints. We derive analytical equations for PID parameters for a first-order plant and illustrate practical implementations in Python, C++, Java, MATLAB/Simulink, and Wolfram Mathematica, with emphasis on robotic actuators such as DC motor joints.

1. Frequency-Response Perspective on PID Design

Consider a unity-feedback loop with plant transfer function \( G(s) \) and controller transfer function \( C(s) \). The open-loop transfer function is

\[ L(s) = C(s)G(s). \]

The closed-loop transfer functions from reference to output and from disturbance (at the plant input) to output are, respectively,

\[ T(s) = \frac{C(s)G(s)}{1 + C(s)G(s)}, \quad S(s) = \frac{1}{1 + C(s)G(s)}. \]

Designing in the frequency domain means specifying properties of the complex function \( L(\mathrm{j}\omega) \), obtained by evaluating \( L(s) \) on the imaginary axis \( s = \mathrm{j}\omega \):

\[ L(\mathrm{j}\omega) = C(\mathrm{j}\omega)G(\mathrm{j}\omega) = \left\lvert L(\mathrm{j}\omega) \right\rvert \mathrm{e}^{\mathrm{j}\varphi_L(\omega)}. \]

The key design quantities are:

  • Gain crossover frequency \( \omega_c \): the frequency where \( \lvert L(\mathrm{j}\omega_c)\rvert = 1 \). This is approximately the closed-loop bandwidth.
  • Phase margin \( \varphi_m \):

    \[ \varphi_m = \pi + \varphi_L(\omega_c), \]

    where \( \varphi_L(\omega_c) \) is the open-loop phase at crossover. A larger phase margin corresponds to better damping and robustness.
  • Low-frequency gain of \( L(\mathrm{j}\omega) \), which determines steady-state tracking and disturbance-rejection quality, as previously studied via steady-state error and system type.

PID design in the frequency domain seeks \( C(s) \) such that \( L(\mathrm{j}\omega) \) has: (i) sufficient gain at low frequency for small steady-state error, (ii) a desired crossover frequency \( \omega_c \) (bandwidth), and (iii) adequate phase margin \( \varphi_m \) for robustness.

flowchart TD
  A["Specify plant model G(s)"] --> B["Choose controller structure: P / PI / PID"]
  B --> C["Set design targets: omega_c, phase margin, low freq gain"]
  C --> D["Compute plant frequency response G(j*omega_c)"]
  D --> E["Solve for PID parameters from magnitude and phase equations"]
  E --> F["Evaluate closed-loop response (time and frequency)"]
  F -->|specs satisfied| G["Deploy controller on actuator (e.g. robot joint)"]
  F -->|specs not satisfied| C
        

2. Frequency Response of PID Controllers

In parallel (or non-interacting) form, a continuous-time PID controller is

\[ C_{PID}(s) = K_p + \frac{K_i}{s} + K_d s. \]

An equivalent parameterization widely used in control and robotics is

\[ C_{PID}(s) = K_p\!\left(1 + \frac{1}{T_i s} + T_d s\right), \quad K_i = \frac{K_p}{T_i}, \quad K_d = K_p T_d. \]

Evaluating on the imaginary axis \( s = \mathrm{j}\omega \), we obtain the complex frequency response. For the purely proportional, integral, and derivative parts:

\[ \begin{aligned} C_P(\mathrm{j}\omega) &= K_p, &\quad \lvert C_P(\mathrm{j}\omega)\rvert &= K_p, &\quad \varphi_P(\omega) &= 0, \\ C_I(\mathrm{j}\omega) &= \frac{K_i}{\mathrm{j}\omega} = -\mathrm{j}\,\frac{K_i}{\omega}, &\quad \lvert C_I(\mathrm{j}\omega)\rvert &= \frac{K_i}{\omega}, &\quad \varphi_I(\omega) &= -\frac{\pi}{2}, \\ C_D(\mathrm{j}\omega) &= K_d \mathrm{j}\omega, &\quad \lvert C_D(\mathrm{j}\omega)\rvert &= K_d \omega, &\quad \varphi_D(\omega) &= \frac{\pi}{2}. \end{aligned} \]

For the full PID controller in parallel form, we have

\[ \begin{aligned} C_{PID}(\mathrm{j}\omega) &= K_p + \frac{K_i}{\mathrm{j}\omega} + K_d \mathrm{j}\omega \\ &= K_p - \mathrm{j}\,\frac{K_i}{\omega} + \mathrm{j}\,K_d \omega \\ &= K_p + \mathrm{j}\!\left(K_d \omega - \frac{K_i}{\omega}\right). \end{aligned} \]

Thus the real and imaginary parts, magnitude, and phase are

\[ \begin{aligned} \Re\!\left\{C_{PID}(\mathrm{j}\omega)\right\} &= K_p, \\ \Im\!\left\{C_{PID}(\mathrm{j}\omega)\right\} &= K_d \omega - \frac{K_i}{\omega}, \\ \lvert C_{PID}(\mathrm{j}\omega)\rvert &= \sqrt{K_p^2 + \left(K_d \omega - \frac{K_i}{\omega}\right)^2}, \\ \varphi_{PID}(\omega) &= \arctan\!\left( \frac{K_d \omega - \frac{K_i}{\omega}}{K_p} \right). \end{aligned} \]

Qualitatively:

  • The integral term dominates at low frequency \( \omega \to 0 \), giving large magnitude and phase close to \( -\pi/2 \), which improves steady-state accuracy but reduces phase.
  • The derivative term dominates at high frequency, increasing magnitude and adding phase lead (towards \( +\pi/2 \)), which can improve phase margin near crossover but also amplifies measurement noise.

3. Loop Transfer Function, Phase Margin, and Bandwidth Constraints

Given a plant \( G(s) \) with frequency response \( G(\mathrm{j}\omega) = \lvert G(\mathrm{j}\omega)\rvert \mathrm{e}^{\mathrm{j}\varphi_G(\omega)} \), the loop transfer function is

\[ L(\mathrm{j}\omega) = C_{PID}(\mathrm{j}\omega) G(\mathrm{j}\omega) = \lvert C_{PID}(\mathrm{j}\omega)\rvert \lvert G(\mathrm{j}\omega)\rvert \mathrm{e}^{\mathrm{j}\left( \varphi_{PID}(\omega) + \varphi_G(\omega) \right)}. \]

We define the gain crossover frequency \( \omega_c \) as the solution of

\[ \lvert L(\mathrm{j}\omega_c)\rvert = \lvert C_{PID}(\mathrm{j}\omega_c)\rvert \lvert G(\mathrm{j}\omega_c)\rvert = 1. \]

The open-loop phase at crossover is \( \varphi_L(\omega_c) = \varphi_{PID}(\omega_c) + \varphi_G(\omega_c) \), and the phase margin is

\[ \varphi_m = \pi + \varphi_L(\omega_c). \]

A typical PID frequency-domain design problem is:

\[ \text{Given } G(s),\ \omega_c^{\star},\ \varphi_m^{\star} \text{, find } K_p, K_i, K_d \text{ such that } \begin{cases} \lvert L(\mathrm{j}\omega_c^{\star})\rvert = 1, \\ \varphi_L(\omega_c^{\star}) = -\pi + \varphi_m^{\star}, \\ \text{low-frequency gain of } L(\mathrm{j}\omega) \\ \text{meets tracking/disturbance specs.} \end{cases} \]

Exact analytical solutions are often complex; instead, control engineers use approximate analytical rules (e.g., placing controller zeros relative to plant poles) and software-aided iteration. However, even purely numerical design rests on the analytical relations derived above.

4. Analytical PID Design for a First-Order Plant

Consider a first-order plant, a common model for DC motors and robot joints:

\[ G(s) = \frac{K}{T s + 1}, \]

where \( K > 0 \) is the static gain and \( T > 0 \) is the time constant. Its frequency response is

\[ G(\mathrm{j}\omega) = \frac{K}{1 + \mathrm{j}\omega T} = \frac{K(1 - \mathrm{j}\omega T)}{1 + (\omega T)^2}, \]

so that

\[ \lvert G(\mathrm{j}\omega)\rvert = \frac{K}{\sqrt{1 + (\omega T)^2}}, \quad \varphi_G(\omega) = -\arctan(\omega T). \]

Using the ideal form \( C_{PID}(s) = K_p\left(1 + \frac{1}{T_i s} + T_d s\right) \), we have at \( \omega = \omega_c \)

\[ C_{PID}(\mathrm{j}\omega_c) = K_p\!\left( 1 - \frac{\mathrm{j}}{\omega_c T_i} + \mathrm{j}\omega_c T_d \right) = K_p\!\left( 1 + \mathrm{j}\left( \omega_c T_d - \frac{1}{\omega_c T_i} \right) \right). \]

Hence

\[ \lvert C_{PID}(\mathrm{j}\omega_c)\rvert = K_p \sqrt{ 1 + \left( \omega_c T_d - \frac{1}{\omega_c T_i} \right)^2 }, \quad \varphi_{PID}(\omega_c) = \arctan\!\left( \omega_c T_d - \frac{1}{\omega_c T_i} \right). \]

The loop magnitude at \( \omega_c \) is

\[ \lvert L(\mathrm{j}\omega_c)\rvert = \lvert C_{PID}(\mathrm{j}\omega_c)\rvert \lvert G(\mathrm{j}\omega_c)\rvert = K_p \sqrt{ 1 + \left( \omega_c T_d - \frac{1}{\omega_c T_i} \right)^2 } \frac{K}{\sqrt{1 + (\omega_c T)^2}}. \]

The gain-crossover condition \( \lvert L(\mathrm{j}\omega_c)\rvert = 1 \) yields

\[ K_p = \frac{\sqrt{1 + (\omega_c T)^2}} {K\sqrt{ 1 + \left( \omega_c T_d - \frac{1}{\omega_c T_i} \right)^2 }}. \]

The loop phase at crossover is

\[ \varphi_L(\omega_c) = \varphi_{PID}(\omega_c) + \varphi_G(\omega_c) = \arctan\!\left( \omega_c T_d - \frac{1}{\omega_c T_i} \right) - \arctan(\omega_c T). \]

Imposing the desired phase margin \( \varphi_m^{\star} \) gives the phase equation

\[ \arctan\!\left( \omega_c T_d - \frac{1}{\omega_c T_i} \right) - \arctan(\omega_c T) = -\pi + \varphi_m^{\star}. \]

Together, the magnitude and phase equations define a nonlinear system in \( T_i \) and \( T_d \), from which \( K_p \) follows explicitly. In practice, one often chooses \( T_i \) and \( T_d \) relative to the plant time constant (for example \( T_i \approx T \) and \( T_d \approx T/4 \)) and then computes \( K_p \) from the magnitude equation. The resulting design is then refined numerically.

Steady-state error. For a unit-step reference with Laplace transform \( R(s) = 1/s \), the error transform is \( E(s) = S(s)R(s) \). The final value theorem gives

\[ e_{\mathrm{ss}} = \lim_{t \to \infty} e(t) = \lim_{s \to 0} sE(s) = \lim_{s \to 0} \frac{1}{1 + C_{PID}(s)G(s)}. \]

As \( s \to 0 \), the integral term dominates \( C_{PID}(s) \approx K_p/(T_i s) \), so \( C_{PID}(s)G(s) \approx K_p K/(T_i s) \), which tends to infinity. Therefore \( S(0) = 0 \) and \( e_{\mathrm{ss}} = 0 \), confirming that including integral action yields zero steady-state error for step inputs in a first-order plant without intrinsic integrators.

5. Algorithmic Design Flow

The preceding equations suggest an iterative procedure that is easily automated in software. The flowchart below summarizes a typical frequency-response-based PID design loop used for robotic actuators and servo drives.

flowchart TD
  S["Start with plant model G(s)"] --> SPEC["Define targets: omega_c, phi_m, tracking"]
  SPEC --> INIT["Choose initial Ti and Td (e.g. scaled from plant time constants)"]
  INIT --> KP["Compute Kp from magnitude equation at omega_c"]
  KP --> EVAL["Evaluate L(j*omega) (margins, bandwidth, low freq gain)"]
  EVAL -->|specs satisfied| DONE["Store Kp, Ki, Kd and implement in code/hardware"]
  EVAL -->|specs not satisfied| ADJ["Adjust Ti, Td or omega_c"]
  ADJ --> INIT
        

6. Python Implementation with python-control

In Python, the python-control library is widely used in both academic control courses and robotics prototyping. Combined with robotics libraries such as roboticstoolbox, it allows us to model a robot joint as a simple plant and design a PID controller by shaping the open-loop frequency response.


import numpy as np
import control as ct  # python-control library
# (Optional) robotics-specific libraries:
# import roboticstoolbox as rtb

# First-order plant approximating a robot joint actuator:
#   G(s) = K / (T s + 1)
K = 20.0   # static gain
T = 0.1    # time constant (s)
G = ct.tf([K], [T, 1.0])

# Desired specifications
omega_c_des = 40.0          # rad/s (desired bandwidth)
pm_des_deg = 60.0           # desired phase margin (deg)
pm_des = pm_des_deg * np.pi / 180.0

def pid_tf(Kp, Ki, Kd):
    """Ideal PID transfer function C(s) = Kp + Ki/s + Kd s."""
    s = ct.tf([1.0, 0.0], [1.0])
    return Kp + Ki / s + Kd * s

def loop_margins(Kp, Ki, Kd):
    """Return crossover frequency and phase margin of the loop."""
    C = pid_tf(Kp, Ki, Kd)
    L = C * G
    gm, pm, wcg, wcp = ct.margin(L)  # gain margin, phase margin, crossover freqs
    return wcg, wcp, pm

# Simple search over Ti, Td around the plant time constant
Ti_candidates = [0.05, 0.1, 0.2]   # integral time candidates
Td_candidates = [0.02, 0.05, 0.08] # derivative time candidates

best = None
for Ti in Ti_candidates:
    for Td in Td_candidates:
        # compute Ki, Kd from Kp, Ti, Td relations
        # Step 1: compute Kp from magnitude equation at omega_c_des
        w = omega_c_des
        # plant magnitude |G(jw)|
        magG = K / np.sqrt(1.0 + (w * T)**2)
        # PID magnitude factor sqrt(1 + (w Td - 1/(w Ti))^2)
        factor = np.sqrt(1.0 + (w * Td - 1.0 / (w * Ti))**2)
        Kp = np.sqrt(1.0 + (w * T)**2) / (K * factor)
        Ki = Kp / Ti
        Kd = Kp * Td

        wcg, wcp, pm = loop_margins(Kp, Ki, Kd)

        # score: closeness to desired phase margin and bandwidth
        if wcp is None:  # no crossover found
            continue
        score = abs(wcp - omega_c_des) / omega_c_des + abs(pm - pm_des)
        if best is None or score < best["score"]:
            best = dict(Ti=Ti, Td=Td, Kp=Kp, Ki=Ki, Kd=Kd,
                        wcp=wcp, pm=pm, score=score)

print("Best design:", best)

# Controller suitable for deployment in a robot joint torque or position loop:
C_pid = pid_tf(best["Kp"], best["Ki"], best["Kd"])
L = C_pid * G
ct.bode(L)  # visualize loop shape
      

The resulting (Kp, Ki, Kd) can be transferred into a lower-level real-time controller running on a microcontroller or within a robotics middleware stack (e.g., ROS) that drives the robot joint.

7. C++ Implementation for Frequency-Response Evaluation

In C++-based robotic systems (for example, those built on ROS and ros_control), PID controllers are often implemented in time domain. Nevertheless, the frequency-domain design can be prototyped in C++ by explicitly evaluating \( L(\mathrm{j}\omega) \) using <complex>. The tuned gains are then passed to classes such as control_toolbox::Pid for online control.


#include <iostream>
#include <complex>
#include <vector>
#include <cmath>

int main() {
    using std::complex;
    using std::cout;
    using std::endl;

    const double K = 20.0;  // plant gain
    const double T = 0.1;   // plant time constant

    // PID parameters obtained from analytical or Python-based design
    double Kp = 1.1;
    double Ki = 11.0;
    double Kd = 0.02;

    // Frequency grid (rad/s)
    std::vector<double> omega = {1.0, 5.0, 10.0, 20.0, 40.0, 80.0};

    for (double w : omega) {
        complex<double> jw(0.0, w);

        // Plant: G(s) = K / (T s + 1)
        complex<double> G = K / (T * jw + 1.0);

        // PID: C(s) = Kp + Ki/s + Kd s, evaluated at s = j w
        complex<double> C = Kp + Ki / jw + Kd * jw;

        complex<double> L = C * G;

        double mag = std::abs(L);
        double phase = std::arg(L); // radians

        cout << "w = " << w
             << " |L(jw)| = " << mag
             << " phase(deg) = " << phase * 180.0 / M_PI
             << endl;
    }

    return 0;
}

/*
In a ROS-based robotic controller, the tuned gains Kp, Ki, Kd can be
used directly as:

  control_toolbox::Pid pid;
  pid.initPid(Kp, Ki, Kd, i_max, i_min);

The frequency-domain analysis above validates bandwidth and margins
before deploying the gains to the real robot.
*/
      

8. Java Implementation and Robotic Libraries

Many educational and industrial robots (for example, those in the FRC ecosystem) use Java and the WPILib framework, which includes a PIDController class. Frequency-domain design can be done offline in Java, and the resulting gains can be injected into PIDController.


// Example: evaluate PID loop frequency response for a first-order plant
// and print approximate crossover frequency and phase margin.
//
// For robotics, the tuned gains can be used with
//   import edu.wpi.first.math.controller.PIDController;

public class PIDFrequencyDesigner {

    // Plant G(s) = K / (T s + 1)
    static double[] plantReIm(double K, double T, double w) {
        double denom = 1.0 + (w * T) * (w * T);
        double re = K / denom;
        double im = -K * w * T / denom;
        return new double[]{re, im};
    }

    // PID C(s) = Kp + Ki/s + Kd s at s = j w
    static double[] pidReIm(double Kp, double Ki, double Kd, double w) {
        double re = Kp;
        double im = Kd * w - Ki / w;
        return new double[]{re, im};
    }

    static double mag(double re, double im) {
        return Math.sqrt(re * re + im * im);
    }

    static double phase(double re, double im) {
        return Math.atan2(im, re); // radians
    }

    public static void main(String[] args) {
        double K = 20.0;
        double T = 0.1;

        // Gains from design (for example, derived analytically or using Python)
        double Kp = 1.1;
        double Ki = 11.0;
        double Kd = 0.02;

        // Sweep frequency and approximate crossover
        double omegaC = 0.0;
        double phaseAtC = 0.0;
        double prevMag = Double.POSITIVE_INFINITY;
        for (double w = 1.0; w <= 200.0; w += 1.0) {
            double[] g = plantReIm(K, T, w);
            double[] c = pidReIm(Kp, Ki, Kd, w);

            double reL = g[0] * c[0] - g[1] * c[1];
            double imL = g[0] * c[1] + g[1] * c[0];
            double magL = mag(reL, imL);

            if (magL <= 1.0 && prevMag > 1.0) {
                omegaC = w;
                phaseAtC = phase(reL, imL);
                break;
            }
            prevMag = magL;
        }

        double pm = Math.PI + phaseAtC; // radians
        System.out.println("Approx crossover omega_c = " + omegaC + " rad/s");
        System.out.println("Approx phase margin = " + pm * 180.0 / Math.PI + " deg");

        // Use these gains in a WPILib controller:
        // PIDController controller = new PIDController(Kp, Ki, Kd);
    }
}
      

This Java code mirrors the analytical relations derived earlier and connects naturally to Java-based robotics frameworks by supplying validated gains to their PID implementations.

9. MATLAB/Simulink Implementation

MATLAB's Control System Toolbox and Simulink provide built-in primitives for frequency-response-based design. The script below constructs the first-order plant, defines an ideal PID controller, and evaluates the loop margins. The same PID block can be dropped into a Simulink diagram driving a robotic actuator model.


% First-order plant G(s) = K / (T s + 1)
K = 20;
T = 0.1;
s = tf('s');
G = K / (T*s + 1);

% Desired crossover and phase margin
omega_c_des = 40;           % rad/s
pm_des = 60;                % degrees

% Choose Ti and Td relative to plant time constant
Ti = T;          % integral time
Td = T/4;        % derivative time

% Compute Kp from the magnitude equation at omega_c_des
w = omega_c_des;
magG = abs(freqresp(G, w));
factor = sqrt(1 + (w*Td - 1/(w*Ti))^2);
Kp = sqrt(1 + (w*T)^2) / (K * factor);
Ki = Kp / Ti;
Kd = Kp * Td;

C = Kp + Ki/s + Kd*s;
L = C*G;

[gm, pm, wcg, wcp] = margin(L);
fprintf('Designed Kp=%.3f Ki=%.3f Kd=%.3f\n', Kp, Ki, Kd);
fprintf('Achieved phase margin %.2f deg at %.2f rad/s\n', pm, wcp);

figure;
margin(L); grid on; title('Loop frequency response with PID');

% In Simulink:
%  - Insert a Transfer Fcn block with numerator [K] and denominator [T 1].
%  - Insert a PID Controller block and set Kp, Ki, Kd as computed.
%  - Use the Bode plot and linear analysis tools to verify margins.
      

10. Wolfram Mathematica Implementation

Wolfram Mathematica provides symbolic and numerical tools for frequency response and PID tuning via TransferFunctionModel and BodePlot. This allows exact manipulation of the expressions derived in earlier sections.


(* First-order plant G(s) = K / (T s + 1) *)
K = 20.0;
T = 0.1;
s = LaplaceTransformVariable;
G = TransferFunctionModel[K/(T*s + 1), s];

(* Ideal PID controller C(s) = Kp + Ki/s + Kd s *)
pid[Kp_, Ki_, Kd_] := TransferFunctionModel[Kp + Ki/s + Kd*s, s];

(* Example gains from analytical design *)
Kp = 1.1;
Ki = 11.0;
Kd = 0.02;

C = pid[Kp, Ki, Kd];
L = Series[TransferFunctionModel[C["Function"][s] G["Function"][s], s], {s, 0, 0}];

(* Bode plot of loop transfer function *)
BodePlot[{C, G, C*G},
 PlotLegends -> {"PID C(s)", "Plant G(s)", "Loop L(s)"},
 GridLines -> Automatic]

(* Numerical phase margin and gain crossover *)
Needs["ControlSystems`"]
{gm, pm, wcg, wcp} = Margin[C*G];
Print["Phase margin (deg) = ", pm*180./Pi, " at omega = ", wcp, " rad/s"];
      

Symbolic capabilities also allow Mathematica to solve the nonlinear design equations for \( T_i \) and \( T_d \) directly for simple plants, offering insight into how PID zeros should be placed relative to plant poles.

11. Problems and Solutions

Problem 1 (Frequency Response of Ideal PID): Starting from \( C_{PID}(s) = K_p + \frac{K_i}{s} + K_d s \), derive explicit expressions for \( \lvert C_{PID}(\mathrm{j}\omega)\rvert \) and \( \varphi_{PID}(\omega) \).

Solution: Substituting \( s = \mathrm{j}\omega \) gives

\[ C_{PID}(\mathrm{j}\omega) = K_p + \frac{K_i}{\mathrm{j}\omega} + K_d \mathrm{j}\omega = K_p - \mathrm{j}\frac{K_i}{\omega} + \mathrm{j}K_d \omega = K_p + \mathrm{j}\left( K_d \omega - \frac{K_i}{\omega} \right). \]

Hence the real and imaginary parts are \( K_p \) and \( K_d \omega - \frac{K_i}{\omega} \), so

\[ \lvert C_{PID}(\mathrm{j}\omega)\rvert = \sqrt{ K_p^2 + \left( K_d \omega - \frac{K_i}{\omega} \right)^2 }, \quad \varphi_{PID}(\omega) = \arctan\!\left( \frac{ K_d \omega - \frac{K_i}{\omega} }{K_p} \right). \]

Problem 2 (Numerical Design for a First-Order Plant): For the plant \( G(s) = \frac{2}{0.5 s + 1} \), target a crossover frequency \( \omega_c = 4 \,\mathrm{rad/s} \). Choose \( T_i = 0.5 \) and \( T_d = 0.125 \) and compute the proportional gain \( K_p \) required to enforce \( \lvert L(\mathrm{j}\omega_c)\rvert = 1 \) with \( C_{PID}(s) = K_p (1 + \frac{1}{T_i s} + T_d s) \). Then compute the corresponding phase margin.

Solution: Here \( K = 2 \) and \( T = 0.5 \). At \( \omega_c = 4 \) we have

\[ \omega_c T = 4 \cdot 0.5 = 2, \quad 1 + (\omega_c T)^2 = 1 + 4 = 5, \quad \sqrt{1 + (\omega_c T)^2} = \sqrt{5}. \]

With \( T_i = 0.5 \) and \( T_d = 0.125 \),

\[ \omega_c T_d = 4 \cdot 0.125 = 0.5, \quad \frac{1}{\omega_c T_i} = \frac{1}{4 \cdot 0.5} = \frac{1}{2} = 0.5, \]

so

\[ \omega_c T_d - \frac{1}{\omega_c T_i} = 0.5 - 0.5 = 0, \quad \sqrt{ 1 + \left( \omega_c T_d - \frac{1}{\omega_c T_i} \right)^2 } = 1. \]

The gain equation from Section 4 simplifies to

\[ K_p = \frac{\sqrt{1 + (\omega_c T)^2}} {K \cdot 1} = \frac{\sqrt{5}}{2} \approx 1.118. \]

The plant phase at \( \omega_c \) is

\[ \varphi_G(\omega_c) = -\arctan(\omega_c T) = -\arctan(2) \approx -1.107 \text{ rad} \approx -63.4^\circ. \]

From the choice \( \omega_c T_d - \frac{1}{\omega_c T_i} = 0 \), the PID phase is

\[ \varphi_{PID}(\omega_c) = \arctan(0) = 0. \]

Thus

\[ \varphi_L(\omega_c) = \varphi_{PID}(\omega_c) + \varphi_G(\omega_c) \approx -63.4^\circ, \quad \varphi_m = 180^\circ + \varphi_L(\omega_c) \approx 116.6^\circ. \]

The obtained phase margin is very large and can be reduced by adjusting \( T_i \) and \( T_d \) if a specific target value is desired.

Problem 3 (Integral Action and Zero Steady-State Error): Consider a unity-feedback system with plant \( G(s) \) and controller \( C_{PID}(s) = K_p + \frac{K_i}{s} + K_d s \). Show that if \( G(s) \) is strictly proper and bounded at \( s = 0 \) (no integrators), then the closed-loop step steady-state error is zero.

Solution: For a unit step \( R(s) = 1/s \) and error \( E(s) = S(s)R(s) = \frac{1}{1 + C_{PID}(s)G(s)} \cdot \frac{1}{s} \), the final value theorem gives

\[ e_{\mathrm{ss}} = \lim_{s \to 0} \frac{1}{1 + C_{PID}(s)G(s)}. \]

As \( s \to 0 \), \( C_{PID}(s) \approx K_i/s \) because the integral term dominates, and \( G(s) \to G(0) = K_0 \) is finite. Thus

\[ C_{PID}(s)G(s) \approx \frac{K_i K_0}{s}, \]

which diverges to \( +\infty \) in magnitude as \( s \to 0 \). Therefore \( 1 + C_{PID}(s)G(s) \) tends to infinity, so \( e_{\mathrm{ss}} = 0 \). This is the classic result that adding integral action turns a type 0 plant into a type 1 closed-loop system for reference tracking.

Problem 4 (Effect of Pure Derivative on Steady-State Error): Suppose the controller is purely derivative, \( C_D(s) = K_d s \), and the plant is type 0 with \( G(s) \) finite at \( s = 0 \). Show that derivative action alone cannot change the steady-state error to a unit-step input.

Solution: For \( C_D(s) = K_d s \), the loop transfer function is \( L(s) = K_d s G(s) \). As \( s \to 0 \), \( L(s) \to 0 \) because \( G(s) \) is finite and the factor \( s \) tends to zero. Therefore,

\[ S(s) = \frac{1}{1 + L(s)} \to 1 \quad \text{as } s \to 0, \]

so the error transform for a unit-step input is \( E(s) \approx 1/s \) near the origin. The final value theorem then gives \( e_{\mathrm{ss}} = 1 \), the same as the open-loop value for a type 0 plant. Thus derivative action alone does not improve step steady-state error; integral action is necessary.

Problem 5 (High-Frequency Behavior of PID Loop): For the first-order plant \( G(s) = \frac{K}{T s + 1} \) and ideal PID controller \( C_{PID}(s) = K_p + \frac{K_i}{s} + K_d s \), characterize the asymptotic behavior of \( \lvert L(\mathrm{j}\omega)\rvert \) as \( \omega \to \infty \). Explain the implication for measurement noise.

Solution: As \( \omega \to \infty \), the plant frequency response satisfies

\[ G(\mathrm{j}\omega) = \frac{K}{1 + \mathrm{j}\omega T} \approx \frac{K}{\mathrm{j}\omega T} = -\mathrm{j}\,\frac{K}{\omega T}, \]

so \( \lvert G(\mathrm{j}\omega)\rvert \approx \frac{K}{\omega T} \). For the PID controller, the derivative term dominates:

\[ C_{PID}(\mathrm{j}\omega) \approx K_d \mathrm{j}\omega, \quad \lvert C_{PID}(\mathrm{j}\omega)\rvert \approx K_d \omega. \]

Therefore the loop magnitude behaves as

\[ \lvert L(\mathrm{j}\omega)\rvert = \lvert C_{PID}(\mathrm{j}\omega)\rvert \lvert G(\mathrm{j}\omega)\rvert \approx K_d \omega \cdot \frac{K}{\omega T} = \frac{K K_d}{T}, \]

which tends to a constant at high frequency. If an additional derivative filter is not used, the loop does not attenuate high-frequency sensor noise, leading to noise amplification in the control signal. This is one reason why practical PID implementations use a filtered derivative, which will be analyzed in a subsequent lesson.

12. Summary

In this lesson we expressed PID control in the frequency domain and showed how the proportional, integral, and derivative terms shape the open-loop frequency response \( L(\mathrm{j}\omega) \). We derived explicit formulas for the magnitude and phase of an ideal PID controller, related them to gain crossover and phase margin, and obtained analytical design relations for first-order plants typical of robotic actuators. We also illustrated how these frequency-response relations translate into concrete implementations in Python, C++, Java, MATLAB/Simulink, and Wolfram Mathematica. The frequency domain viewpoint prepares the ground for deeper treatments of Bode and Nyquist analysis in later chapters.

13. References

  1. Åström, K.J., & Hägglund, T. (1984). Automatic tuning of simple regulators with specifications on phase and amplitude margins. Automatica, 20(5), 645–651.
  2. Åström, K.J., Hang, C.C., Persson, P., & Ho, W.K. (1992). Towards intelligent PID control. Automatica, 28(1), 1–9.
  3. Ho, W.K., Åström, K.J., Hang, C.C., & Lim, B. (1995). Robust PID design based on frequency response. IEE Proceedings - Control Theory and Applications, 142(2), 143–152.
  4. Skogestad, S. (2003). Simple analytic rules for model reduction and PID controller tuning. Journal of Process Control, 13(4), 291–309.
  5. Åström, K.J., & Hägglund, T. (2006). Advanced PID Control. ISA – The Instrumentation, Systems, and Automation Society.