Chapter 19: Lead, Lag, and Lead–Lag Compensation

Lesson 4: Bode-Based Design of Lag and Lead–Lag Compensators

In this lesson we develop systematic frequency-domain procedures for designing lag and lead–lag compensators using Bode plots. We combine steady-state error requirements (low-frequency gain), robustness requirements (gain and phase margins), and bandwidth constraints into a coherent design workflow and relate the resulting compensators to robot joint and actuator control loops.

1. Conceptual Overview

In previous lessons of this chapter you studied the basic structures and effects of phase-lead and phase-lag compensators, and in earlier chapters you learned how Bode plots encode magnitude, phase, bandwidth and stability margins of a feedback loop.

In unity-feedback configuration with open-loop transfer function \( L(s) = G_c(s)G(s) \), where \( G(s) \) is the plant and \( G_c(s) \) the controller/compensator, the Bode plot of \( L(\mathrm{j}\omega) \) determines:

  • Low-frequency magnitude and steady-state tracking: position/velocity error constants and disturbance rejection at small frequencies.
  • Gain crossover frequency \( \omega_c \) (where \( |L(\mathrm{j}\omega_c)| = 1 \)), which is strongly correlated with closed-loop bandwidth and speed of response.
  • Phase margin and gain margin, which quantify robustness to gain and phase uncertainties and to time delay.

A lag compensator mainly increases low-frequency gain (reducing steady-state error) while only slightly affecting phase margin and crossover frequency. A lead–lag compensator combines a lead network, which provides additional phase near crossover (improving stability margin and speeding up the response), with a lag network that adjusts low-frequency gain.

In robotic systems (e.g., a DC motor driving a robot joint), lead–lag compensation is commonly used as an outer-loop controller around inner current or velocity loops, designed using frequency-response data of the actuator and transmission.

2. Lag Compensator Model and Frequency Response

A standard lag compensator in the Laplace domain has transfer function

\[ G_{\text{lag}}(s) = K_c \frac{s + z}{s + p}, \quad 0 < p < z, \]

where \( K_c > 0 \) is a constant gain, \( -p \) is the pole and \( -z \) is the zero. Defining

\[ \beta = \frac{z}{p} > 1, \]

one can interpret \( \beta \) as the ratio between the zero and pole locations.

The frequency response at \( s = \mathrm{j}\omega \) is \( G_{\text{lag}}(\mathrm{j}\omega) = K_c \frac{\mathrm{j}\omega + z}{\mathrm{j}\omega + p} \). The magnitude is

\[ \left|G_{\text{lag}}(\mathrm{j}\omega)\right| = K_c \sqrt{\frac{\omega^2 + z^2}{\omega^2 + p^2}}, \]

and the phase is

\[ \phi_{\text{lag}}(\omega) = \arg\!\left(G_{\text{lag}}(\mathrm{j}\omega)\right) = \arctan\!\left( \frac{\omega}{z} \right) - \arctan\!\left( \frac{\omega}{p} \right). \]

Consider the magnitude asymptotes for \( K_c = 1 \):

  • As \( \omega \to 0 \), \( G_{\text{lag}}(0) = \frac{z}{p} = \beta \), so the low-frequency gain is increased by a factor \( \beta \).
  • As \( \omega \to \infty \), \( \left|G_{\text{lag}}(\mathrm{j}\omega)\right| \to 1 \). Thus high-frequency gain is unchanged (0 dB).

In decibels, the low-frequency gain is \( 20 \log_{10} \beta \) dB, and the high-frequency gain is approximately 0 dB. The Bode magnitude asymptotes are therefore:

  • Constant \( 20 \log_{10}\beta \) dB for \( \omega \ll p \).
  • Slope \( -20 \,\text{dB/dec} \) between \( \omega = p \) and \( \omega = z \).
  • Approximately 0 dB for \( \omega \gg z \).

The phase is always negative (lag). The most negative phase occurs at \( \omega = \sqrt{pz} \). Using \( z = \beta p \) and the identity for \( \arctan x - \arctan y \) one can show

\[ \phi_{\text{lag,max}} = -\arctan\!\left( \frac{\beta - 1}{2\sqrt{\beta}} \right), \quad \beta > 1. \]

For typical design values \( \beta \in [2, 20] \), the maximum phase lag is modest (e.g., about \( -4^\circ \) to \( -30^\circ \)), especially if the break frequencies are chosen well below the crossover frequency.

3. Bode-Based Design of a Lag Compensator

We now turn the qualitative insight into a concrete design algorithm. We consider unity feedback with open-loop \( L(s) = G_c(s)G(s) \) and a type-0 plant \( G(s) \) (no integrator). For a unit-step reference, the steady-state error is

\[ e_{\text{ss}} = \frac{1}{1 + K_p}, \quad K_p = \lim_{s \to 0} L(s) = \lim_{s \to 0} G_c(s)G(s). \]

Suppose we already have some compensator \( G_{c,0}(s) \) (for example, a proportional gain or a previously designed lead network) that yields an initial error constant \( K_{p,0} \) and steady-state error \( e_{\text{ss},0} \). We want to reduce the error to a specified value \( e_{\text{ss,des}} \).

The required error constant is obtained from \( e_{\text{ss,des}} = 1/(1+K_{p,\text{des}}) \), so

\[ K_{p,\text{des}} = \frac{1 - e_{\text{ss,des}}}{e_{\text{ss,des}}}. \]

The additional low-frequency gain factor required is

\[ \beta = \frac{K_{p,\text{des}}}{K_{p,0}}, \quad \beta > 1. \]

A lag compensator with \( K_c = 1 \) multiplies the DC gain by \( \beta \):

\[ \lim_{s \to 0} G_{\text{lag}}(s) = \frac{z}{p} = \beta. \]

Therefore, if we cascade \( G_{\text{lag}}(s) \) with the existing compensator, the new error constant becomes approximately \( K_{p,\text{new}} \approx \beta K_{p,0} \).

3.1 Design Steps

  1. Start from the uncompensated or lead-compensated loop. Compute the Bode plot of \( L_0(s) = G_{c,0}(s)G(s) \), the current phase margin \( \text{PM}_0 \), gain crossover frequency \( \omega_{c,0} \), and error constant \( K_{p,0} \).
  2. Determine the required low-frequency gain. From the steady-state error specification compute \( K_{p,\text{des}} \) and the gain factor \( \beta = K_{p,\text{des}}/K_{p,0} \).
  3. Choose the desired crossover frequency. Typically, keep the crossover frequency close to the one achieved by the existing design: set \( \omega_c \approx \omega_{c,0} \), as long as the phase margin is acceptable.
  4. Place the lag zero and pole well below \( \omega_c \). Choose \( \omega_z \approx \omega_c / 10 \) and then

\[ \omega_p = \frac{\omega_z}{\beta}, \quad \beta = \frac{\omega_z}{\omega_p}, \quad 0 < \omega_p < \omega_z. \]

  1. Form the lag network. In normalized form, \( s_z = s/\omega_z \) and \( s_p = s/\omega_p \), the compensator is

\[ G_{\text{lag}}(s) = \frac{s/\omega_z + 1}{s/\omega_p + 1} = \frac{s + \omega_z}{s + \omega_p}. \]

  1. Retune the overall gain. Form the new loop \( L(s) = K_c G_{\text{lag}}(s)G_{c,0}(s)G(s) \) and adjust \( K_c \) such that the magnitude at the desired crossover frequency satisfies \( |L(\mathrm{j}\omega_c)| = 1 \). Because the lag network has approximately 0 dB gain at \( \omega_c \), this retuning is small.
  2. Verify specifications. Compute the Bode plot and check that the phase margin, gain margin, and steady-state error satisfy the requirements. If the phase margin has been reduced too much, decrease \( \beta \) or move \( \omega_z \) further below \( \omega_c \).
flowchart TD
  A["Start with plant G(s) and existing controller G_c0(s)"] --> B["Bode of L0(s) = G_c0(s) G(s)"]
  B --> C["Compute Kp0 and steady-state error ess0"]
  C --> D{"Is ess0 <= ess_des?"}
  D -->|yes| E["Lag not required (or optional fine tuning)"]
  D -->|no| F["Compute beta = Kp_des / Kp0"]
  F --> G["Choose crossover wc and set zero frequency wz = wc / 10"]
  G --> H["Set pole frequency wp = wz / beta (wp < wz)"]
  H --> I["Form G_lag(s) = (s + wz)/(s + wp)"]
  I --> J["Adjust gain Kc so |L(j wc)| = 1"]
  J --> K["Verify Bode margins and steady-state error; iterate if needed"]
        

4. Lead–Lag Compensator Structure

A general lead–lag compensator is the product of a lead network and a lag network (possibly together with an overall gain):

\[ G_c(s) = K_c G_{\text{lead}}(s) G_{\text{lag}}(s), \]

where a typical lead network has

\[ G_{\text{lead}}(s) = \frac{s + z_1}{s + p_1}, \quad 0 < z_1 < p_1, \quad \alpha = \frac{z_1}{p_1} < 1, \]

and the lag network is

\[ G_{\text{lag}}(s) = \frac{s + z_2}{s + p_2}, \quad 0 < p_2 < z_2, \quad \beta = \frac{z_2}{p_2} > 1. \]

For the lead network, one can show that the maximum phase lead is

\[ \phi_{\text{lead,max}} = \arcsin\!\left( \frac{1 - \alpha}{1 + \alpha} \right), \quad 0 < \alpha < 1, \]

occurring at the geometric-mean frequency

\[ \omega_m = \sqrt{z_1 p_1}. \]

For the combined lead–lag compensator, the open-loop magnitude and phase are

\[ |L(\mathrm{j}\omega)| = K_c |G(\mathrm{j}\omega)| |G_{\text{lead}}(\mathrm{j}\omega)| |G_{\text{lag}}(\mathrm{j}\omega)|, \]

\[ \phi_{\text{total}}(\omega) = \phi_G(\omega) + \phi_{\text{lead}}(\omega) + \phi_{\text{lag}}(\omega). \]

The lead network is tuned so that \( \phi_{\text{lead}}(\omega) \) adds positive phase near the desired crossover, increasing the phase margin and bandwidth. The lag network then shapes the low-frequency magnitude (by factor \( \beta \)) with little influence on the phase near crossover by placing its pole and zero well below \( \omega_c \).

In robotic joint control, one commonly designs a lead network to achieve suitable phase margin and bandwidth for joint-position control, then adds a lag network to reduce steady-state position error caused by load torque disturbances or gravity effects.

5. Bode-Based Design of a Lead–Lag Compensator

We now describe a practical workflow for designing a lead–lag compensator using Bode plots, under typical specifications:

  • Desired phase margin \( \text{PM}_{\text{des}} \).
  • Desired (or approximate) bandwidth \( \omega_{c,\text{des}} \).
  • Steady-state error bound \( e_{\text{ss,des}} \) for a given input (e.g., step).

5.1 Step 1: Design the Lead Network

  1. Obtain the Bode plot of the uncompensated plant \( G(s) \). Determine the frequency range where a reasonable crossover frequency \( \omega_{c,\text{des}} \) can be placed (for example, where the slope is about \( -20 \,\text{dB/dec} \)).
  2. Evaluate the phase of \( G(\mathrm{j}\omega_{c,\text{des}}) \), denoted \( \phi_G(\omega_{c,\text{des}}) \). The uncompensated phase margin would be approximately \( \text{PM}_0 = 180^\circ + \phi_G(\omega_{c,\text{des}}) \).
  3. Compute the additional phase lead needed (including a safety allowance of, say, \( 5^\circ \) to \( 10^\circ \)):

\[ \phi_{\text{add}} = \text{PM}_{\text{des}} - \text{PM}_0 + \phi_{\text{margin}}, \]

where \( \phi_{\text{margin}} \) is a small additional angle.

  1. Set \( \phi_{\text{lead,max}} \approx \phi_{\text{add}} \). From the formula in Section 4,

\[ \phi_{\text{lead,max}} = \arcsin\!\left( \frac{1 - \alpha}{1 + \alpha} \right), \]

solve for \( \alpha \) and then choose \( z_1 \) and \( p_1 \) such that \( z_1/p_1 = \alpha \) and \( \omega_m = \sqrt{z_1 p_1} \approx \omega_{c,\text{des}} \). A convenient choice is

\[ z_1 = \frac{\omega_{c,\text{des}}}{\sqrt{\alpha}}, \quad p_1 = \omega_{c,\text{des}}\sqrt{\alpha}. \]

  1. Form \( G_{\text{lead}}(s) = (s + z_1)/(s + p_1) \) and retune the gain \( K_c \) so that \( |K_c G_{\text{lead}}(\mathrm{j}\omega_{c,\text{des}}) G(\mathrm{j}\omega_{c,\text{des}})| = 1 \). Check the new phase margin; it should be close to \( \text{PM}_{\text{des}} \).

5.2 Step 2: Append the Lag Network

After the lead design, compute the error constant \( K_{p,0} \) and resulting steady-state error \( e_{\text{ss},0} \). If it violates the specification, proceed:

  1. Compute \( K_{p,\text{des}} \) and the required factor \( \beta = K_{p,\text{des}} / K_{p,0} \).
  2. Keep the previously chosen crossover frequency \( \omega_c \) (obtained from the lead design). Select lag zero and pole as in Section 3:

\[ \omega_z \approx \frac{\omega_c}{10}, \quad \omega_p = \frac{\omega_z}{\beta}. \]

  1. Form the lag network \( G_{\text{lag}}(s) = (s + \omega_z)/(s + \omega_p) \). Multiply with \( G_{\text{lead}}(s) \) and retune the overall gain \( K_c \) so that the magnitude at \( \omega_c \) is unity.
  2. Verify phase margin, gain margin, and steady-state error using the Bode plot of \( L(s) = K_c G_{\text{lead}}(s) G_{\text{lag}}(s) G(s) \).
flowchart TD
  S["Specs: PM_des, wc_des, ess_des"] --> L1["Bode of plant G(s)"]
  L1 --> L2["Choose wc_des in suitable slope region"]
  L2 --> L3["Compute phi_add and design lead: z1, p1, alpha"]
  L3 --> L4["Tune gain Kc so |Kc G_lead(j wc) G(j wc)| = 1"]
  L4 --> L5["Check PM and bandwidth; adjust if needed"]
  L5 --> L6["Compute Kp0 and ess0"]
  L6 --> D{"Is ess0 <= ess_des?"}
  D -->|yes| KEEP["Final controller: Kc G_lead(s)"]
  D -->|no| LG1["Compute beta = Kp_des / Kp0"]
  LG1 --> LG2["Choose lag zero wz = wc / 10, pole wp = wz / beta"]
  LG2 --> LG3["Form G_lag(s) and recompute L(s) = Kc G_lead(s) G_lag(s) G(s)"]
  LG3 --> LG4["Retune Kc and verify margins and ess; iterate if needed"]
        

6. Python Implementation (Bode-Based Lead–Lag Design)

We illustrate the design on a simplified robot joint model. Consider a DC motor driving a single revolute joint, approximated (after linearization and inner current-loop closure) by a second-order transfer function

\[ G(s) = \frac{K_m}{Js^2 + Bs}, \]

where \( J \) is the reflected inertia, \( B \) the viscous damping, and \( K_m \) the torque constant. A position controller acts on the joint angle using unity feedback.

The following Python code (using the python-control library) constructs the plant, designs a fixed lead–lag compensator (numbers chosen for illustration), and plots Bode and step responses. In robotics, this can be combined with roboticstoolbox to embed the joint model in a multi-DOF manipulator simulation.


import numpy as np
import control as ctl
# If needed: pip install control
# For robotics context: pip install roboticstoolbox-python

# --- Plant: 1-DOF joint approximation ---
J = 0.01   # kg m^2
B = 0.1    # N m s/rad
Km = 0.5   # N m/A (effective gain)

s = ctl.TransferFunction.s
G = Km / (J * s**2 + B * s)

# --- Lead design (numbers chosen to give extra phase near wc) ---
wc_des = 10.0   # desired crossover rad/s
alpha = 0.2     # z1/p1 = alpha < 1 for lead

z1 = wc_des / np.sqrt(alpha)
p1 = wc_des * np.sqrt(alpha)

G_lead = (s + z1) / (s + p1)

# Preliminary gain so that |Kc * G_lead(j wc) * G(j wc)| ≈ 1
# Compute magnitude at wc_des
mag_plant, phase_plant, w = ctl.bode(G, [wc_des], Plot=False)
mag_lead, phase_lead, _ = ctl.bode(G_lead, [wc_des], Plot=False)
Kc = 1.0 / (mag_plant[0] * mag_lead[0])

# --- Lag design to improve steady-state position error ---
# Suppose we want 10x improvement in low-frequency error constants
beta = 10.0
wz2 = wc_des / 10.0
wp2 = wz2 / beta

G_lag = (s + wz2) / (s + wp2)

# Full controller: lead-lag with gain Kc
Gc = Kc * G_lead * G_lag

# Open-loop and closed-loop
L = Gc * G
T = ctl.feedback(L, 1)  # unity feedback

# Bode plot of compensated open-loop
ctl.bode(L, dB=True)

# Step response of joint position
t = np.linspace(0, 2.0, 1000)
t, y = ctl.step_response(T, T=t)

import matplotlib.pyplot as plt
plt.figure()
plt.plot(t, y)
plt.xlabel("Time [s]")
plt.ylabel("Joint position (rad)")
plt.title("Closed-loop step response with lead-lag compensator")
plt.grid(True)
plt.show()
      

In a robotics control stack, Gc can be used inside a joint position controller node (e.g., implemented in C++ or Python with ROS), while the inner loops (current and velocity control) remain in the motor drive or low-level firmware.

7. C++ Implementation (Lag and Lead–Lag Evaluation)

In C++, a common robotics environment is ROS with the ros_control framework. The frequency-domain design (Bode plots, gains, pole/zero positions) is typically done offline (e.g., in Python or MATLAB), and the resulting lead–lag transfer function is implemented as a discrete-time filter inside the controller loop.

The following snippet shows a minimal C++ representation of a continuous lag compensator and a combined lead–lag compensator, together with evaluation of magnitude and phase. Numerical values for poles and zeros would come from the Bode-based design.


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

struct FirstOrderFactor {
    double z; // zero location (for numerator) or pole location (for denominator)
    bool isZero; // true if (s + z) factor in numerator

    std::complex<double> eval(double w) const {
        std::complex<double> jw(0.0, w);
        if (isZero) {
            return jw + z;
        } else {
            return 1.0 / (jw + z);
        }
    }
};

struct LagCompensator {
    double Kc;
    FirstOrderFactor zero;
    FirstOrderFactor pole;

    std::complex<double> eval(double w) const {
        return Kc * zero.eval(w) * pole.eval(w);
    }
};

struct LeadLag {
    double Kc;
    FirstOrderFactor leadZero;
    FirstOrderFactor leadPole;
    FirstOrderFactor lagZero;
    FirstOrderFactor lagPole;

    std::complex<double> eval(double w) const {
        std::complex<double> jw_resp = Kc *
            leadZero.eval(w) * leadPole.eval(w) *
            lagZero.eval(w) * lagPole.eval(w);
        return jw_resp;
    }
};

int main() {
    // Example parameters (from an offline Bode design)
    LagCompensator lag;
    lag.Kc = 1.0;
    lag.zero = {10.0, true};   // (s + 10) in numerator
    lag.pole = {1.0, false};   // 1 / (s + 1) in denominator

    double w = 5.0; // rad/s
    std::complex<double> G_lag = lag.eval(w);
    double mag = std::abs(G_lag);
    double phase = std::arg(G_lag); // radians

    std::cout << "Lag magnitude at w = " << w
              << " rad/s: " << mag << std::endl;
    std::cout << "Lag phase at w = " << w
              << " rad/s: " << phase << " rad" << std::endl;

    return 0;
}
      

In a ROS joint controller, the continuous-time compensator is discretized (e.g., via bilinear transform) and implemented as a difference equation inside the update loop of a ros_control controller. The Bode-based lead–lag design determines the gains and pole/zero locations passed into such a controller.

8. Java Implementation (Lead–Lag Evaluation, WPILib Context)

In Java-based robotics frameworks such as WPILib (used in many mobile robots and FRC systems), control algorithms are often implemented in Java. Below is a simple class that evaluates the continuous-time lead–lag compensator magnitude and phase for given pole/zero parameters. The parameters can be obtained from Bode-based design.


public class LeadLagCompensator {
    private final double K;
    private final double z1, p1;
    private final double z2, p2;

    public LeadLagCompensator(double K, double z1, double p1, double z2, double p2) {
        this.K = K;
        this.z1 = z1;
        this.p1 = p1;
        this.z2 = z2;
        this.p2 = p2;
    }

    public double magnitude(double w) {
        // |(j w + z1)(j w + z2)/(j w + p1)(j w + p2)| = K * sqrt(...)
        double w2 = w * w;
        double num = (w2 + z1 * z1) * (w2 + z2 * z2);
        double den = (w2 + p1 * p1) * (w2 + p2 * p2);
        return K * Math.sqrt(num / den);
    }

    public double phase(double w) {
        // phi = atan(w / z1) + atan(w / z2) - atan(w / p1) - atan(w / p2)
        double phi = Math.atan2(w, z1) + Math.atan2(w, z2)
                   - Math.atan2(w, p1) - Math.atan2(w, p2);
        return phi; // radians
    }
}
      

In a WPILib project, a discrete-time approximation of this compensator can be combined with the library's LinearSystemLoop or PIDController classes to realize outer-loop lead–lag compensation around drivetrain or arm subsystems, using parameters tuned from Bode plots of identified plant models.

9. MATLAB/Simulink Implementation

MATLAB and Simulink are widely used in control and robotics. The following script constructs a plant, a lag compensator, and a lead–lag controller, and visualizes the Bode plot and closed-loop step response. The same transfer functions can be implemented in Simulink using Transfer Fcn blocks. The Robotics System Toolbox can be used to embed the joint dynamics into a full robot model.


% Plant: second-order joint model G(s) = Km / (J s^2 + B s)
J = 0.01;
B = 0.1;
Km = 0.5;

s = tf('s');
G = Km / (J * s^2 + B * s);

% Lead design (parameters from Bode-based procedure)
wc_des = 10;      % rad/s
alpha = 0.2;      % z1/p1 = alpha < 1

z1 = wc_des / sqrt(alpha);
p1 = wc_des * sqrt(alpha);

G_lead = (s + z1) / (s + p1);

% Choose gain Kc so that |L(j wc_des)| ≈ 1
[magG, ~] = bode(G, wc_des);
[magLead, ~] = bode(G_lead, wc_des);
magG = squeeze(magG);
magLead = squeeze(magLead);
Kc = 1 / (magG * magLead);

% Lag design for improved low-frequency error
beta = 10;
wz2 = wc_des / 10;
wp2 = wz2 / beta;
G_lag = (s + wz2) / (s + wp2);

Gc = Kc * G_lead * G_lag;
L = Gc * G;
T = feedback(L, 1);

figure;
margin(L);
title('Bode and margins of lead-lag compensated open-loop');

figure;
step(T);
grid on;
title('Closed-loop step response with lead-lag compensator');
xlabel('Time [s]');
ylabel('Joint position [rad]');

% In Simulink:
% - Implement G(s) as a Transfer Fcn block.
% - Implement G_lead(s) and G_lag(s) as cascaded Transfer Fcn blocks.
% - Use a Step block for reference and a Sum block for the error.
% - Optionally interface with Robotics System Toolbox rigidBodyTree models.
      

In robotic applications, the same lead–lag transfer functions can be applied to each actuated joint, with parameters tuned from joint-specific Bode data (identified via frequency-response experiments).

10. Wolfram Mathematica Implementation

Wolfram Mathematica provides symbolic and numerical tools for transfer functions, Bode plots, and closed-loop analysis. Below we define a plant and a lead–lag compensator and compute its Bode plot and step response.


(* Plant: G(s) = Km / (J s^2 + B s) *)
J = 0.01;
B = 0.1;
Km = 0.5;

G[s_] := Km/(J*s^2 + B*s);

(* Lead parameters *)
wcDes = 10.0;
alpha = 0.2;
z1 = wcDes/Sqrt[alpha];
p1 = wcDes*Sqrt[alpha];
Glead[s_] := (s + z1)/(s + p1);

(* Lag parameters *)
beta = 10.0;
wz2 = wcDes/10.0;
wp2 = wz2/beta;
Glag[s_] := (s + wz2)/(s + wp2);

Kc = 1.0; (* Assume gain chosen from Bode design *)

Gc[s_] := Kc*Glead[s]*Glag[s];
L[s_] := Gc[s]*G[s];

(* Continuous-time transfer function models *)
Ltf = TransferFunctionModel[L[s], s];
Ttf = FeedbackConnect[Ltf, 1]; (* unity feedback *)

(* Bode plot *)
BodePlot[Ltf, {w, 0.1, 100},
  PlotLayout -> {Magnitude, Phase},
  AxesLabel -> {"w [rad/s]", None}
]

(* Step response *)
StepResponsePlot[Ttf, {t, 0, 2},
  AxesLabel -> {"t [s]", "y(t)"}
]
      

For more complex robotic systems, Mathematica can model multibody dynamics symbolically and then linearize around operating points to obtain \( G(s) \) for each joint or axis, to which the same Bode-based lead–lag design can be applied.

11. Problems and Solutions

Problem 1 (DC gain and Bode asymptotes of a lag network). Consider the lag compensator \( G_{\text{lag}}(s) = \frac{s + 5}{s + 1} \).
(a) Compute its DC gain and high-frequency gain.
(b) Sketch its approximate Bode magnitude asymptotes in dB.

Solution:

(a) The DC gain is

\[ G_{\text{lag}}(0) = \frac{0 + 5}{0 + 1} = 5. \]

Thus at low frequency the magnitude is \( 5 \), or in decibels

\[ 20 \log_{10}(5) \approx 14 \,\text{dB}. \]

As \( \omega \to \infty \),

\[ \left|G_{\text{lag}}(\mathrm{j}\omega)\right| \approx \left|\frac{\mathrm{j}\omega}{\mathrm{j}\omega}\right| = 1, \]

so the high-frequency gain is \( 1 \), i.e., 0 dB.

(b) The pole is at \( \omega_p = 1 \,\text{rad/s} \), the zero at \( \omega_z = 5 \,\text{rad/s} \). For \( \omega \ll 1 \), the magnitude is flat at about \( 14 \,\text{dB} \). For \( 1 \lt \omega \lt 5 \), the magnitude decreases with slope \( -20 \,\text{dB/dec} \). For \( \omega \gg 5 \), it flattens at 0 dB.

Problem 2 (Maximum phase lag of a general lag network). Let \( G_{\text{lag}}(s) = (s + z)/(s + p) \) with \( 0 < p < z \), and define \( \beta = z/p > 1 \). Show that the frequency at which the phase lag is most negative is \( \omega_m = \sqrt{pz} \), and derive the expression for the maximum phase lag \( \phi_{\text{lag,max}} \).

Solution:

The phase is

\[ \phi(\omega) = \arctan\!\left( \frac{\omega}{z} \right) - \arctan\!\left( \frac{\omega}{p} \right). \]

Differentiating with respect to \( \omega \) and setting the derivative to zero gives the extremum. We compute

\[ \frac{\mathrm{d}\phi}{\mathrm{d}\omega} = \frac{z}{\omega^2 + z^2} - \frac{p}{\omega^2 + p^2}. \]

Setting \( \mathrm{d}\phi/\mathrm{d}\omega = 0 \) yields

\[ \frac{z}{\omega^2 + z^2} = \frac{p}{\omega^2 + p^2} \quad\Rightarrow\quad z (\omega^2 + p^2) = p (\omega^2 + z^2). \]

Expanding and simplifying,

\[ z\omega^2 + zp^2 = p\omega^2 + pz^2 \quad\Rightarrow\quad (z - p)\omega^2 = pz(z - p). \]

Since \( z \neq p \), we obtain

\[ \omega^2 = pz \quad\Rightarrow\quad \omega_m = \sqrt{pz}. \]

At this frequency, \( \omega_m/z = 1/\sqrt{\beta} \) and \( \omega_m/p = \sqrt{\beta} \), so

\[ \phi_{\text{lag,max}} = \arctan\!\left( \frac{1}{\sqrt{\beta}} \right) - \arctan\!\left( \sqrt{\beta} \right). \]

Using the formula \( \arctan a - \arctan b = \arctan\!\left( \frac{a - b}{1 + ab} \right) \) with \( a = 1/\sqrt{\beta} \), \( b = \sqrt{\beta} \), we obtain

\[ \phi_{\text{lag,max}} = \arctan\!\left( \frac{1/\sqrt{\beta} - \sqrt{\beta}}{1 + 1} \right) = \arctan\!\left( \frac{1 - \beta}{2\sqrt{\beta}} \right) = -\arctan\!\left( \frac{\beta - 1}{2\sqrt{\beta}} \right). \]

This is the maximum negative phase introduced by the lag compensator, which tends to be small for moderate \( \beta \).

Problem 3 (Bode-based lag design for steady-state error). A unity-feedback system has plant \( G(s) = \frac{10}{(s + 1)(s + 2)} \) and a simple proportional controller of gain \( K = 1 \). It is required that the steady-state error to a unit step be less than \( 0.02 \). Design a lag compensator \( G_{\text{lag}}(s) \) using the Bode-based method, assuming that the crossover frequency after compensation should remain close to the uncompensated value and that the phase margin is adequate.

Solution:

For a type-0 system with unity feedback, the position error constant is

\[ K_p = \lim_{s \to 0} K G(s) = G(0) = \frac{10}{(0 + 1)(0 + 2)} = 5. \]

The corresponding steady-state error is \( e_{\text{ss},0} = 1/(1 + 5) = 1/6 \approx 0.167 \), which violates the requirement \( e_{\text{ss}} \leq 0.02 \).

The desired error constant is

\[ e_{\text{ss,des}} = 0.02 \quad\Rightarrow\quad K_{p,\text{des}} = \frac{1 - 0.02}{0.02} = 49. \]

Hence the required gain factor is

\[ \beta = \frac{K_{p,\text{des}}}{K_{p,0}} = \frac{49}{5} \approx 9.8, \]

and we can choose \( \beta \approx 10 \). Let the uncompensated crossover frequency be \( \omega_{c,0} \) (estimated from the plant Bode plot; we keep it unchanged). Choose \( \omega_z = \omega_c / 10 \) and \( \omega_p = \omega_z / \beta \), so

\[ G_{\text{lag}}(s) = \frac{s + \omega_z}{s + \omega_p}, \quad \frac{\omega_z}{\omega_p} = \beta \approx 10. \]

Since the lag network has gain \( \beta \) at low frequency and approximately 0 dB at \( \omega_c \), the new error constant satisfies \( K_{p,\text{new}} \approx \beta K_{p,0} \approx 10 \cdot 5 = 50 \), leading to

\[ e_{\text{ss,new}} \approx \frac{1}{1 + 50} \approx 0.0196 < 0.02. \]

By construction, the effect on phase margin is small because the pole and zero lie a decade below the crossover frequency.

Problem 4 (Combining lead and lag to meet both phase margin and steady-state error). For the same plant \( G(s) = 10/((s + 1)(s + 2)) \), suppose that the uncompensated phase margin is only \( 20^\circ \) at a crossover frequency near \( \omega_{c,0} = 4 \,\text{rad/s} \), while the desired phase margin is \( 55^\circ \) and the steady-state error requirement is again \( e_{\text{ss,des}} \leq 0.02 \). Outline how a lead–lag compensator could be designed to meet both requirements.

Solution:

First, design a lead compensator to achieve the desired phase margin. At \( \omega_{c,\text{des}} = 4 \,\text{rad/s} \), the uncompensated phase margin is \( \text{PM}_0 = 20^\circ \). The additional phase needed is

\[ \phi_{\text{add}} = 55^\circ - 20^\circ + 5^\circ = 40^\circ, \]

including a safety margin of \( 5^\circ \). Set \( \phi_{\text{lead,max}} \approx 40^\circ \) and solve

\[ \phi_{\text{lead,max}} = \arcsin\!\left( \frac{1 - \alpha}{1 + \alpha} \right) \approx 40^\circ \]

for \( \alpha = z_1/p_1 \). Then choose \( z_1 \) and \( p_1 \) such that \( z_1/p_1 = \alpha \) and \( \sqrt{z_1 p_1} \approx 4 \,\text{rad/s} \). For example, \( z_1 = 4/\sqrt{\alpha} \), \( p_1 = 4\sqrt{\alpha} \).

Adjust the gain \( K_c \) so that the magnitude of \( K_c G_{\text{lead}}(\mathrm{j}4) G(\mathrm{j}4) \) is 1, giving crossover near \( 4 \,\text{rad/s} \) and an improved phase margin close to \( 55^\circ \).

Next, compute the resulting error constant \( K_{p,0} \) and \( e_{\text{ss},0} \). If \( e_{\text{ss},0} \) violates the specification, determine \( K_{p,\text{des}} \) and \( \beta = K_{p,\text{des}} / K_{p,0} \), then choose a lag network with \( \omega_z \approx \omega_c / 10 = 0.4 \,\text{rad/s} \) and \( \omega_p = \omega_z / \beta \). Cascading this lag with the lead preserves the crossover and phase margin while increasing the low-frequency gain and reducing steady-state error.

12. Summary

In this lesson we used Bode plots to design lag and lead–lag compensators for linear feedback systems, with emphasis on robotic joint and actuator applications. A lag compensator of the form \( (s + z)/(s + p) \) with \( 0 < p < z \) increases low-frequency gain by a factor \( \beta = z/p \) while leaving the crossover frequency nearly unchanged when its break points are placed well below crossover.

A lead–lag compensator combines a lead network, which injects positive phase near crossover to meet phase margin and bandwidth specifications, with a lag network that tunes steady-state error. The design procedure starts from plant Bode plots, chooses a desired crossover region, designs a lead network to supply the necessary phase margin, then adds a lag network for error-constant shaping. Implementations in Python, C++, Java, MATLAB/Simulink, and Wolfram Mathematica connect these designs directly to robotic control software stacks.

13. References

  1. Bode, H.W. (1945). Network Analysis and Feedback Amplifier Design. Van Nostrand.
  2. Evans, W.R. (1948). Control systems synthesis by root locus method. Transactions of the American Institute of Electrical Engineers, 67(1), 547–551.
  3. Nyquist, H. (1932). Regeneration theory. Bell System Technical Journal, 11(1), 126–147.
  4. Horowitz, I.M. (1963). Synthesis of Feedback Systems. Academic Press.
  5. Rosenbrock, H.H. (1969). The modulus margin and the generalised Nyquist stability criterion. Electrical Engineers, Proceedings of the Institution of, 116(11), 1921–1931.
  6. MacFarlane, A.G.J., & Kouvaritakis, B. (1977). Design of multivariable control systems using the inverse Nyquist array. IEE Proceedings, 124(9), 733–743.
  7. Skogestad, S., & Postlethwaite, I. (1996). Multivariable Feedback Control: Analysis and Design. Wiley. (Chapters on classical loop-shaping and robustness.)
  8. Middleton, R.H., & Goodwin, G.C. (1988). Adaptive control of time-varying plants. IEEE Transactions on Automatic Control, 33(2), 150–155.
  9. Åström, K.J., & Hägglund, T. (1995). PID Controllers: Theory, Design, and Tuning. Instrument Society of America. (Sections on lead–lag and phase-advance/phase-lag design.)
  10. Doyle, J.C., Francis, B.A., & Tannenbaum, A.R. (1992). Feedback Control Theory. Macmillan. (Background on frequency-domain loop-shaping and sensitivity functions.)