Chapter 10: Root Locus Design Techniques

Lesson 3: Adding Real Poles and Zeros for Desired Dynamics

This lesson develops systematic methods for modifying the open-loop transfer function by adding real poles and zeros so that the root locus passes through desired closed-loop pole locations implied by time-domain specifications. We use the root-locus angle and magnitude conditions, derive algebraic requirements on compensator pole/zero locations, and show how such compensators can be implemented and simulated in Python, C++, Java, MATLAB/Simulink, and Wolfram Mathematica, with brief links to robotic joint control models.

1. Role of Added Real Poles and Zeros in Root-Locus Design

In previous chapters, we learned to map time-domain specifications (e.g., overshoot, settling time) into desired regions of the complex \( s \)-plane, and to select a scalar gain \( K \) from the root locus of a given plant \( G(s) \). Sometimes, no purely proportional gain \( K \) yields closed-loop poles that lie inside the desired region. We then introduce an additional dynamic block (a compensator) with transfer function \( C(s) \), so that the open-loop transfer function becomes \( L(s) = K\,C(s)\,G(s) \).

In this lesson we restrict attention to compensators whose poles and zeros lie on the real axis:

\[ C(s) = K_c \frac{\prod_{i=1}^{m_c} (s - z_{c,i})}{\prod_{j=1}^{n_c} (s - p_{c,j})}, \quad z_{c,i},\,p_{c,j} \in \mathbb{R}. \]

For unity feedback with \( H(s) = 1 \), the closed-loop characteristic equation is

\[ 1 + K\,C(s)\,G(s) = 0. \]

Adding a real zero (a factor of the form \( s - z_c \) with real \( z_c \)) tends to “attract” root-locus branches toward that point and can increase damping or speed. Adding a real pole (a factor in the denominator) tends to “repel” branches and usually slows the response, but may improve steady-state accuracy (for example, a pole at the origin increases the system type).

The overall design process can be summarized as:

flowchart TD
  S["Time specs (zeta, omega_n, Ts, Mp)"] --> P["Plant G(s)"]
  P --> RL0["Plot root locus of G(s)"]
  RL0 --> CHECK0["Does locus pass desired poles?"]
  CHECK0 -->|yes| GAIN["Choose gain K from root locus"]
  CHECK0 -->|no| MODIFY["Add real zero and/or pole: C(s)"]
  MODIFY --> RL1["Plot root locus of C(s)G(s)"]
  RL1 --> CHECK1["Does new locus meet specs?"]
  CHECK1 -->|yes| IMPLEMENT["Implement C(s) with actuators/robot drives"]
  CHECK1 -->|no| MODIFY
        

2. Effect of a Single Real Zero on Root Locus and Dynamics

Consider a plant with open-loop transfer function \( G(s) \) whose poles are at \( p_1, \dots, p_n \) and zeros at \( z_1, \dots, z_m \). The root locus of \( K G(s) \) consists of points \( s \) in the complex plane satisfying the angle and magnitude conditions

\[ \angle G(s) = (2k+1)\pi,\quad k \in \mathbb{Z}, \qquad |K G(s)| = 1. \]

Now add a compensator with a single real zero at \( s = z_c \), where \( z_c \) is a real number (usually negative to maintain stability of the open-loop poles). The new open-loop transfer function is

\[ L(s) = K \frac{(s - z_c) \prod_{i=1}^{m} (s - z_i)} {\prod_{j=1}^{n} (s - p_j)}. \]

For a candidate closed-loop pole location \( s_d \), denote by \( \angle(\cdot) \) the complex argument. Before adding the zero, the angle of \( G(s_d) \) is

\[ \angle G(s_d) = \sum_{i=1}^{m} \angle(s_d - z_i) - \sum_{j=1}^{n} \angle(s_d - p_j). \]

After adding the zero at \( z_c \), the angle becomes

\[ \angle L(s_d) = \angle G(s_d) + \angle(s_d - z_c). \]

Thus, if \( s_d \) was not on the original locus (the angle condition failed), we can choose \( z_c \) so that the additional term \( \angle(s_d - z_c) \) corrects the angle error and moves \( s_d \) onto the modified root locus of \( L(s) \).

Time-domain behavior can be understood via second-order approximations. Suppose that, after compensation, the dominant closed-loop poles are approximately \( s_{1,2} = -\zeta \omega_n \pm j\,\omega_n \sqrt{1-\zeta^2} \). Ignoring non-dominant poles, the closed-loop transfer function from reference input to output can often be approximated as

\[ T(s) \approx \frac{\omega_n^2 (s - z_c)}{s^2 + 2\zeta \omega_n s + \omega_n^2}, \]

where the real zero \( z_c \) slightly reshapes the transient response. A zero placed far to the left (large negative \( z_c \)) has a small effect and the response resembles the standard second-order response. A zero placed closer to the imaginary axis typically yields a faster initial rise but can increase overshoot.

On the real axis, the root-locus rule (segments lie where the number of real poles and zeros to the right is odd) is also modified: adding a real zero changes which intervals belong to the locus and can “bend” branches toward desirable regions of the \( s \)-plane.

3. Effect of a Single Real Pole and Dominant-Pole Approximation

Now consider adding a real pole at \( s = p_c \), usually chosen as a negative real number. The compensator has the form

\[ C(s) = \frac{1}{s - p_c}, \quad p_c \in \mathbb{R}. \]

The open-loop transfer function becomes \( L(s) = K G(s)/(s - p_c) \). The additional pole modifies the angle condition by subtracting the term \( \angle(s_d - p_c) \), pushing root-locus branches away from \( p_c \). In practice, we often place this pole far to the left so that its associated closed-loop pole is non-dominant.

Suppose that after adding both a real zero \( z_c \) and a real pole \( p_c \), the closed-loop characteristic polynomial is approximated by

\[ (s^2 + 2\zeta \omega_n s + \omega_n^2)(s - p_c) = s^3 + a_2 s^2 + a_1 s + a_0. \]

When \( |p_c| \) is large compared to \( \omega_n \), one root of this cubic is located near \( s = p_c \) (far from the imaginary axis), and the other two roots remain close to the desired complex-conjugate pair. This justifies treating the third pole as non-dominant and using second-order formulas for settling time and overshoot, e.g.,

\[ T_s \approx \frac{4}{\zeta \omega_n}, \qquad M_p \approx \exp\!\left( -\frac{\pi \zeta}{\sqrt{1-\zeta^2}} \right). \]

Real poles introduced by sensors, actuators, or deliberate compensator design therefore must be placed sufficiently far to the left to avoid degrading the desired dominant dynamics. Conversely, intentionally placing a pole closer to the imaginary axis can deliberately slow down the system or improve steady-state properties (for example, an additional pole at the origin).

4. Root-Locus-Based Design Example with a Real Zero

Consider the plant

\[ G(s) = \frac{1}{s(s+2)}. \]

This type of transfer function can arise from a simplified rotational joint model in robotics, where one pole is due to inertia and the other due to viscous damping. Assume unity feedback and reference input a unit step. We wish to design a compensator such that the dominant closed-loop poles have \( \zeta = 0.5 \) and approximately \( T_s \approx 2 \) seconds (2 % settling time).

From the standard settling-time approximation \( T_s \approx 4 / (\zeta \omega_n) \), we choose \( \omega_n = 4 \), so the desired dominant poles are

\[ s_{d} = -\zeta \omega_n \pm j\,\omega_n \sqrt{1-\zeta^2} = -2 \pm j\,2\sqrt{3} \approx -2 \pm j\,3.464. \]

We first check whether these poles lie on the root locus of the uncompensated plant \( K G(s) \). With poles at \( 0 \) and \( -2 \) and no finite zeros, the angle condition at \( s_d = -2 + j\,3.464 \) is

\[ \angle G(s_d) = -\angle(s_d - 0) - \angle(s_d + 2). \]

Geometrically, \( s_d - 0 = -2 + j\,3.464 \) has angle approximately \( 120^\circ \), and \( s_d + 2 = j\,3.464 \) has angle \( 90^\circ \). Thus

\[ \angle G(s_d) \approx -(120^\circ + 90^\circ) = -210^\circ, \]

which is not an odd multiple of \( 180^\circ \), so \( s_d \) does not lie on the original root locus.

We now add a real zero at \( s = -z_c \) with \( z_c > 0 \), i.e.,

\[ C(s) = (s + z_c), \quad L(s) = K \frac{s + z_c}{s(s+2)}. \]

The new angle at \( s_d \) is

\[ \angle L(s_d) = \angle G(s_d) + \angle(s_d + z_c). \]

To satisfy the root-locus angle condition \( \angle L(s_d) = -180^\circ \), we require

\[ \angle(s_d + z_c) \approx -180^\circ - (-210^\circ) = 30^\circ. \]

Writing \( s_d + z_c = (z_c - 2) + j\,3.464 \), the angle is

\[ \angle(s_d + z_c) = \arctan\!\left( \frac{3.464}{z_c - 2} \right). \]

Setting this equal to \( 30^\circ \), we obtain

\[ \tan(30^\circ) = \frac{3.464}{z_c - 2} \quad \Rightarrow \quad z_c - 2 \approx \frac{3.464}{\tan(30^\circ)} \approx 6, \quad z_c \approx 8. \]

Thus we place the compensator zero at \( s = -8 \), to the left of both plant poles. The magnitude condition of the root locus then determines the required gain \( K \). At \( s_d \), ignoring \( K \),

\[ |L(s_d)| = K \frac{|s_d + 8|}{|s_d|\,|s_d + 2|} = 1 \quad\Rightarrow\quad K = \frac{|s_d|\,|s_d + 2|}{|s_d + 8|}. \]

With \( z_c = 8 \) and the numerical values of \( s_d \), this yields a specific controller gain \( K \). In practice, we would verify the resulting response using time-domain simulation and possibly adjust \( z_c \) slightly to account for higher-order dynamics or model uncertainty.

We may also add a real pole at \( s = -p_c \) (with \( p_c \) sufficiently negative) to obtain a proper compensator \( C(s) = K (s+z_c)/(s+p_c) \) and to limit high-frequency gain, while keeping the third closed-loop pole far from the dominant pair.

flowchart TD
  PLANT["Plant: G(s) = 1/(s(s+2))"] --> SPECS["Specs: zeta = 0.5, Ts = 2 s"]
  SPECS --> TARGET["Compute target poles: sd = -2 +/- j 3.464"]
  TARGET --> ANGLE["Check angle condition for G(s) at sd"]
  ANGLE --> ZCHOOSE["Choose real zero at s = -8 to fix angle"]
  ZCHOOSE --> KCHOOSE["Use magnitude condition to compute K"]
  KCHOOSE --> VERIFY["Verify closed-loop response via simulation"]
        

5. Python / Robotics-Oriented Implementation

We now implement the above design using Python and the python-control library, which is commonly used in robotics research for linear control design and analysis. The same structure can represent, for example, a single robotic joint linearized around an operating point.


import numpy as np
import control as ctl  # python-control library
# (pip install control)

# Plant: G(s) = 1 / (s (s + 2))
G = ctl.TransferFunction([1.0], [1.0, 2.0, 0.0])

# Desired dominant pole parameters
zeta = 0.5
wn = 4.0
sd = -zeta * wn + 1j * wn * np.sqrt(1.0 - zeta**2)  # -2 + j*3.464...

# Compensator zero chosen analytically
zc = 8.0
Cz = ctl.TransferFunction([1.0, zc], [1.0])  # C(s) = s + 8

# Open-loop with compensator (without the gain K yet)
L_base = Cz * G

# Use magnitude condition to compute gain K so that sd is on the locus
# For L(s) = K * L_base(s), we need |K * L_base(sd)| = 1
# so K = 1 / |L_base(sd)|
num_eval = np.polyval(L_base.num[0][0], sd)
den_eval = np.polyval(L_base.den[0][0], sd)
L_val = num_eval / den_eval
K = 1.0 / abs(L_val)

print(f"Designed gain K ≈ {K:.3f}")

# Closed-loop transfer function with unity feedback
C = K * Cz
T = ctl.feedback(C * G, 1)

# Inspect dominant poles, step response, and classical performance metrics
print("Closed-loop poles:", ctl.pole(T))

t, y = ctl.step_response(T)
info = ctl.step_info(T)
print("Step info:", info)

# In a robotics context, G(s) could be obtained from a joint model, e.g.,
# using the Robotics Toolbox for Python, then linearized and passed into
# the same design workflow.
      

This script computes the compensator gain \( K \) from the magnitude condition, constructs the closed-loop transfer function, and evaluates its step response and performance indices such as overshoot and settling time. Replacing G with a linearized robotic joint model would follow the same pattern.

6. C++, Java, MATLAB/Simulink, and Mathematica Implementations

6.1 C++: Computing Gain for a Real-Zero Compensator

In C++, we can compute the gain \( K \) for the chosen zero using <complex>. Libraries such as Eigen and ROS-based control frameworks can then incorporate this computation into a real-time robot controller.


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

int main() {
    // Desired dominant pole sd = -2 + j*3.464...
    std::complex<double> sd(-2.0, 3.464101615);

    // Compensator zero: zc = 8  (zero at s = -8)
    double zc = 8.0;

    // For L(s) = K (s + zc) / (s (s + 2)), magnitude condition gives
    // K = |s (s + 2)| / |s + zc| evaluated at s = sd.
    std::complex<double> num = sd * (sd + 2.0);
    std::complex<double> den = sd + zc;

    double mag_ratio = std::abs(num) / std::abs(den);
    double K = mag_ratio;

    std::cout << "Designed gain K ≈ " << K << std::endl;
    return 0;
}
      

6.2 Java: Gain Computation without Complex Arithmetic Libraries

In Java, we can perform the same magnitude computation using real and imaginary parts directly. This can be embedded into a robot control stack using, for example, WPILib or other robotics frameworks.


public class RealZeroDesign {
    public static void main(String[] args) {
        // Desired dominant pole sd = -2 + j*3.464...
        double sr = -2.0;
        double si =  3.464101615;
        double zc =  8.0;    // zero at s = -8

        // Magnitudes needed for K = |s (s + 2)| / |s + zc|
        double abs_s = Math.hypot(sr, si);
        double abs_s_plus_2 = Math.hypot(sr + 2.0, si);
        double abs_s_plus_zc = Math.hypot(sr + zc, si);

        double K = (abs_s * abs_s_plus_2) / abs_s_plus_zc;
        System.out.println("Designed gain K ≈ " + K);
    }
}
      

6.3 MATLAB/Simulink: Root-Locus Design Workflow

MATLAB with Control System Toolbox and Robotics System Toolbox is widely used in robotics. The following script constructs the plant, adds a zero, and visualizes the root locus and step response. A Simulink model can be built to reflect the same block structure.


% Plant and compensator zero
s = tf('s');
G = 1 / (s * (s + 2));
zc = 8;              % zero at s = -8
Cz = (s + zc);       % C(s) = s + 8

% Open-loop without gain
Lbase = Cz * G;

% Desired dominant pole
zeta = 0.5;
wn = 4.0;
sd = -zeta * wn + 1j * wn * sqrt(1 - zeta^2);

% Gain from magnitude condition
Lval = evalfr(Lbase, sd);
K = 1 / abs(Lval);

% Closed-loop system
C = K * Cz;
T = feedback(C * G, 1);

% Visualizations
figure; rlocus(C * G); grid on; title('Root locus with real zero at -8');
figure; step(T); grid on; title('Closed-loop step response');

% Simulink notes:
% 1. In Simulink, place blocks for G(s) and C(s), and close the loop with unity feedback.
% 2. Use Transfer Fcn blocks for 1/(s(s+2)) and (s+8).
% 3. Parameter K can be implemented as a Gain block.
      

6.4 Mathematica: Root Locus and Closed-Loop Response

Mathematica provides symbolic and numeric tools to analyze the same design using TransferFunctionModel and RootLocusPlot.


s =.Symbol["s"];

(* Plant and compensator zero *)
G = TransferFunctionModel[1/(s (s + 2)), s];
zc = 8;
Cz = TransferFunctionModel[s + zc, s];

Lbase = Cz * G;

(* Desired dominant pole *)
zeta = 0.5;
wn = 4.0;
sd = -zeta*wn + I*wn*Sqrt[1 - zeta^2];

(* Gain from magnitude condition *)
Lval = TransferFunctionEvaluate[Lbase, sd];
K = 1/Abs[Lval];

C = K*Cz;
T = SystemsModelFeedback[C*G, 1];

(* Root locus and step response *)
RootLocusPlot[C*G, {K, 0, 200}]
StepResponsePlot[T, {0, 10}]
      

These implementations show how adding real poles and zeros is reflected in software used for robotics and control design, while the underlying mathematical design remains rooted in root locus theory.

7. Problems and Solutions

Problem 1 (Angle Condition with a Real Zero): Consider the plant \( G(s) = 1/(s(s+4)) \) with unity feedback. Desired dominant poles are \( s_d = -3 \pm j\,4 \). Show that these poles are not on the root locus of \( K G(s) \), and determine a real zero location \( z_c \) such that \( s_d \) lies on the root locus of \( K (s + z_c) G(s) \).

Solution:

For \( G(s) = 1/(s(s+4)) \), the poles are at \( 0 \) and \( -4 \). For \( s_d = -3 + j\,4 \),

\[ \angle G(s_d) = -\angle(s_d - 0) - \angle(s_d + 4). \]

Geometrically, \( s_d = -3 + j\,4 \) has angle approximately \( 126.87^\circ \), and \( s_d + 4 = 1 + j\,4 \) has angle approximately \( 75.96^\circ \). Thus

\[ \angle G(s_d) \approx -(126.87^\circ + 75.96^\circ) \approx -202.83^\circ, \]

which is not equal to an odd multiple of \( 180^\circ \), so \( s_d \) is not on the original root locus. Adding a compensator zero at \( s = -z_c \) gives

\[ L(s) = K \frac{s + z_c}{s(s+4)}. \]

The new angle at \( s_d \) is

\[ \angle L(s_d) = \angle G(s_d) + \angle(s_d + z_c). \]

To satisfy \( \angle L(s_d) = -180^\circ \), we require

\[ \angle(s_d + z_c) \approx -180^\circ - (-202.83^\circ) = 22.83^\circ. \]

With \( s_d + z_c = (z_c - 3) + j\,4 \), we require

\[ \tan(22.83^\circ) = \frac{4}{z_c - 3} \quad \Rightarrow \quad z_c - 3 = \frac{4}{\tan(22.83^\circ)}. \]

Evaluating the right-hand side numerically yields a positive value, so \( z_c \) is greater than \( 3 \) (the zero lies to the left of both poles on the real axis). This places the desired complex poles on the new root locus.

Problem 2 (Magnitude Condition and Gain Selection): For the plant and compensator in Problem 1, once \( z_c \) has been chosen, derive the formula for the gain \( K \) as a function of \( s_d \) and \( z_c \), and explain why this uses the magnitude condition.

Solution:

For \( L(s) = K (s + z_c)/(s(s+4)) \), the magnitude condition at \( s_d \) is

\[ |K L_0(s_d)| = 1 \quad \text{where} \quad L_0(s) = \frac{s + z_c}{s(s+4)}. \]

Thus

\[ K = \frac{1}{|L_0(s_d)|} = \frac{|s_d|\,|s_d + 4|}{|s_d + z_c|}. \]

This ensures that the closed-loop characteristic equation \( 1 + K L_0(s) = 0 \) is satisfied at \( s = s_d \), so that \( s_d \) is a closed-loop pole.

Problem 3 (Effect of Far-Left Real Pole): Consider the third-order characteristic polynomial

\[ (s^2 + 2\zeta \omega_n s + \omega_n^2)(s + p_c), \]

with \( \zeta = 0.5 \), \( \omega_n = 4 \), and \( p_c = 40 \). Show that one root lies near \( s = -40 \) and explain why the other two roots remain close to the original second-order pair.

Solution:

Expanding gives

\[ (s^2 + 4 s + 16)(s + 40) = s^3 + 44 s^2 + 176 s + 640. \]

Because \( p_c = 40 \) is large compared to \( \omega_n = 4 \), we expect one root close to \( s = -40 \). Indeed, by evaluating the polynomial at \( s = -40 \), the cubic term \( s^3 \) dominates, and a more detailed root computation (for example, via numerical methods) confirms the presence of a root near \( -40 \). The remaining two roots are only weakly perturbed from the second-order roots at \( -2 \pm j\,3.464 \), justifying the dominant-pole approximation.

Problem 4 (Steady-State Error and Real Poles): A unity-feedback system has plant \( G(s) = 1/(s+1) \). We wish to reduce the steady-state error to a unit ramp input, so we consider adding a real pole at the origin and a real zero at \( s = -z_c \). Qualitatively describe how \( C(s) = (s + z_c)/s \) changes:

  1. the system type and steady-state error,
  2. the shape of the root locus,
  3. potential effects on transient response.

Solution:

(i) Adding a pole at the origin increases the system type by one. For a ramp input, the steady-state error for a type 1 system is finite and proportional to the inverse of the velocity error constant, so this compensator can greatly reduce steady-state error compared to the original type 0 plant.

(ii) The extra pole at the origin introduces a new starting point for the root locus, while the real zero modifies the real-axis segments according to the “odd number of poles and zeros to the right” rule. The locus will tend to start at the origin and move toward the real zero and infinity, reshaping trajectories so that suitable branches can pass through desired regions of the \( s \)-plane.

(iii) The pole at the origin tends to slow the response and may increase overshoot, while the zero can partly compensate by adjusting damping and rise time. Careful placement of \( z_c \) and choice of gain \( K \) are required to balance improved steady-state accuracy against transient performance.

Problem 5 (Design Logic for Choosing Pole vs Zero): For a given plant, you find that increasing gain along the root locus improves the speed but leads to excessive overshoot and the closed-loop poles eventually cross into the right half-plane. Explain in which situations you would:

  1. add a real zero to the left of the plant poles,
  2. add a real pole far to the left,
  3. add a real pole near the origin.

Solution:

Adding a real zero to the left of existing poles typically bends the root locus toward that zero, allowing complex poles with improved damping to be obtained at moderate gain. This is suitable when the main problem is insufficient damping and overshoot, while maintaining or increasing speed.

Adding a real pole far to the left can be used to obtain a proper compensator and to limit high frequency gain without greatly disturbing the dominant poles. This is appropriate when implementation constraints require a physically realizable controller and when high-frequency noise must be attenuated.

Adding a real pole near the origin increases system type and improves steady-state accuracy for low-order polynomial inputs (e.g., steps and ramps), but often slows the transient response and may cause overshoot. This is used when steady-state error is the dominant concern and some loss in speed can be tolerated.

8. Summary

In this lesson we used the root-locus angle and magnitude conditions to design compensators with real poles and zeros, ensuring that the closed-loop poles pass through target locations implied by time-domain specifications. We studied how a real zero can attract root-locus branches and improve damping or speed, while a real pole tends to repel branches and often slows the response unless placed far to the left as a non-dominant pole. We developed a detailed design example and showed implementations in Python, C++, Java, MATLAB/Simulink, and Mathematica, with a view toward robotic joint control. These ideas form the basis for more structured compensator families (such as phase lead and lag) studied in later chapters.

9. References

  1. Evans, W. R. (1950). Graphical analysis of control systems. Transactions of the American Institute of Electrical Engineers, 69(1), 127–132.
  2. Evans, W. R. (1954). Control system synthesis by root-locus method. Transactions of the American Institute of Electrical Engineers, Part II, 73(3), 238–246.
  3. Bode, H. W. (1945). Network analysis and feedback amplifier design. Bell System Technical Journal, 24(1), 1–33.
  4. Nichols, N. B. (1947). Theory of servomechanisms. Bell System Technical Journal, 26(1), 1–49.
  5. Tsypkin, Ya. Z. (1958). On the root locus method in the theory of automatic control. Automation and Remote Control, 19(4), 311–322.
  6. Leitmann, G. (1961). On the root-locus method of Evans. International Journal of Control, 3(1), 1–17.
  7. Jury, E. I. (1964). A simplified stability criterion for linear discrete systems. Proceedings of the IRE, 50(6), 1493–1500.
  8. Zames, G. (1966). On the input-output stability of time-varying nonlinear feedback systems. IEEE Transactions on Automatic Control, 11(2), 228–238.