Chapter 9: Root Locus Fundamentals

Lesson 3: Asymptotes, Centroid, and Breakaway/Break-In Points

In this lesson we develop the analytical machinery needed to understand how root-locus branches behave far from the origin and along the real axis. We derive formulas for asymptote directions and their centroid, and we show how to compute breakaway and break-in points using polynomial calculus. Computational examples in Python, C++, Java, MATLAB/Simulink, and Wolfram Mathematica demonstrate how these tools are used in tuning feedback gains for robotic actuators and servo systems.

1. Root-Locus Review and Notation

Consider a single-input single-output unity-feedback system with open-loop transfer function \( G(s) = K\,\dfrac{N(s)}{D(s)} \), where \( K \ge 0 \) is a real gain. The closed-loop characteristic equation for unity feedback is

\[ 1 + G(s) = 0 \;\;\Longleftrightarrow\;\; D(s) + K\,N(s) = 0. \]

Let \( n_p \) be the number of (finite) open-loop poles (degree of \( D(s) \)) and \( n_z \) be the number of (finite) open-loop zeros (degree of \( N(s) \)). The closed-loop poles as functions of \( K \) trace the root locus. From Lessons 1–2, you already know:

  • The root locus starts at open-loop poles when \( K = 0 \).
  • The root locus terminates at open-loop zeros or at infinity as \( K \to \infty \).
  • The number of branches equals \( n_p \).
  • Real-axis segments belong to the root locus if the number of real poles and zeros to the right of a point is odd.

In this lesson we focus on:

  • Asymptote directions of branches that go to infinity.
  • The centroid where these asymptotes intersect the real axis.
  • Breakaway and break-in points along the real axis.

2. Asymptote Angles: Derivation

When \( n_p > n_z \), there are \( n_a = n_p - n_z \) branches that go to infinity. These branches approach straight lines in the complex plane called asymptotes. We derive their angles using the root-locus angle condition.

Write the open-loop transfer function (monic polynomials for simplicity)

\[ G(s) = K\frac{N(s)}{D(s)} = K\frac{\prod_{j=1}^{n_z}(s - z_j)}{\prod_{i=1}^{n_p}(s - p_i)}. \]

The root-locus angle condition for positive \( K \) is

\[ \arg\left(\frac{N(s)}{D(s)}\right) = (2k+1)\pi, \quad k \in \mathbb{Z}. \]

For large \(|s|\) (far from all finite poles and zeros), we can approximate the factors:

\[ s - p_i \approx s, \quad s - z_j \approx s, \]

so that

\[ D(s) \approx s^{n_p}, \quad N(s) \approx s^{n_z}, \quad \frac{N(s)}{D(s)} \approx s^{\,n_z - n_p}. \]

Let \( s = r e^{j\theta} \) with \( r \to \infty \). Then

\[ \arg\left(\frac{N(s)}{D(s)}\right) \approx (n_z - n_p)\arg(s) = (n_z - n_p)\theta. \]

Substituting into the angle condition yields

\[ (n_z - n_p)\,\theta = (2k+1)\pi. \]

Since \( n_a = n_p - n_z > 0 \), this is equivalent to

\[ \theta_k = \frac{(2k+1)\pi}{n_p - n_z}, \quad k = 0,1,\dots, n_a - 1. \]

Interpretation. For each \( k \), there is one asymptote at angle \( \theta_k \) with respect to the positive real axis. These angles are equally spaced, spanning all \( n_a \) branches that go to infinity.

3. Centroid of Asymptotes: Derivation

Each asymptote is a straight line in the complex plane. They all intersect the real axis at a common point called the centroid \( \sigma_a \). The standard formula is

\[ \sigma_a = \frac{\displaystyle\sum_{i=1}^{n_p} p_i - \displaystyle\sum_{j=1}^{n_z} z_j}{n_p - n_z}. \]

We sketch a derivation based on polynomial expansions. Let

\[ D(s) = \prod_{i=1}^{n_p}(s - p_i), \qquad N(s) = \prod_{j=1}^{n_z}(s - z_j). \]

Expand into monic polynomials:

\[ D(s) = s^{n_p} + a_1 s^{n_p-1} + \cdots, \quad N(s) = s^{n_z} + b_1 s^{n_z-1} + \cdots. \]

The coefficients \( a_1 \) and \( b_1 \) are related to the pole and zero locations:

\[ a_1 = -\sum_{i=1}^{n_p} p_i, \qquad b_1 = -\sum_{j=1}^{n_z} z_j. \]

The characteristic equation is

\[ D(s) + K N(s) = 0. \]

For large \( K \) and large \(|s|\), the dominant terms come from the highest powers of \( s \):

\[ s^{n_p} + a_1 s^{n_p-1} + K\left(s^{n_z} + b_1 s^{n_z-1}\right) \approx 0. \]

Factor \( s^{n_z} \) and write

\[ s^{n_z}\left( s^{n_p - n_z} + a_1 s^{n_p - n_z - 1} + K + K b_1 s^{-1} \right) \approx 0. \]

The large-\(|s|\) branches correspond to roots of the factor in parentheses. Define \( q = n_p - n_z = n_a \) and consider the polynomial

\[ P_q(s) = s^{q} + a_1 s^{q-1} + K + K b_1 s^{-1}. \]

For asymptotes we are interested in the leading behavior as \( |s| \to \infty \). A standard trick is to shift the coordinate: set \( s = \sigma_a + w \) and choose \( \sigma_a \) such that the coefficient of \( w^{q-1} \) in the expanded polynomial (in powers of \( w \)) vanishes. This enforces that the \( q \) large roots are symmetrically distributed around the vertical line \( \Re(s) = \sigma_a \).

Carrying out the algebra (keeping only the terms that dominate as \( |w| \to \infty \)) shows that the coefficient of \( w^{q-1} \) is proportional to

\[ q\,\sigma_a + a_1 - b_1. \]

Setting this coefficient to zero yields

\[ q\,\sigma_a + a_1 - b_1 = 0 \quad\Longrightarrow\quad \sigma_a = \frac{b_1 - a_1}{q}. \]

Substituting \( a_1 = -\sum p_i \), \( b_1 = -\sum z_j \), and \( q = n_p - n_z \) leads directly to

\[ \sigma_a = \frac{\displaystyle\sum_{i=1}^{n_p} p_i - \displaystyle\sum_{j=1}^{n_z} z_j}{n_p - n_z}, \]

which is the familiar centroid formula. The asymptote lines are then

\[ s(\rho) = \sigma_a + \rho e^{j\theta_k}, \quad \rho \ge 0,\; k=0,\dots,n_a-1. \]

4. Breakaway and Break-In Points

A breakaway point on the real axis is a location where two or more root-locus branches coincide and then leave the real axis as \( K \) increases (forming a complex-conjugate pair). A break-in point is the converse phenomenon: branches from the complex plane re-enter the real axis at that point.

These points correspond to repeated roots of the characteristic equation for some gain value \( K_b \). Let

\[ \Delta(s,K) := D(s) + K N(s). \]

At \( s = s_b \) a repeated root occurs when

\[ \Delta(s_b,K_b) = 0 \quad\text{and}\quad \frac{\partial \Delta}{\partial s}(s_b,K_b) = 0. \]

The first equation gives

\[ K_b = -\frac{D(s_b)}{N(s_b)}, \]

assuming \( N(s_b) \ne 0 \). Differentiating with respect to \( s \),

\[ \frac{\partial \Delta}{\partial s}(s,K) = D'(s) + K N'(s). \]

At \( (s_b,K_b) \) the derivative condition becomes

\[ D'(s_b) + K_b N'(s_b) = 0 \quad\Longrightarrow\quad D'(s_b) - \frac{D(s_b)}{N(s_b)}N'(s_b) = 0. \]

Multiplying by \( N(s_b) \) yields the breakaway polynomial

\[ N(s_b) D'(s_b) - D(s_b) N'(s_b) = 0. \]

Equivalently, define the gain as a function of \( s \) along the characteristic equation:

\[ K(s) = -\frac{D(s)}{N(s)}. \]

Differentiating \( K(s) \) with respect to \( s \),

\[ \frac{dK}{ds} = -\frac{N(s) D'(s) - D(s) N'(s)}{N(s)^2}. \]

Thus breakaway and break-in candidates satisfy

\[ \frac{dK}{ds} = 0 \quad\Longleftrightarrow\quad N(s) D'(s) - D(s) N'(s) = 0. \]

Important practical rule. All real roots of \( N(s)D'(s) - D(s)N'(s) = 0 \) are candidates. A candidate \( s_b \in \mathbb{R} \) is an actual breakaway/break-in point only if:

  • It lies on a real-axis segment that belongs to the root locus (odd-number rule).
  • The corresponding gain \( K(s_b) = -D(s_b)/N(s_b) \) is real and positive.

5. Algorithmic Flow for Asymptotes and Breakaway Points

The following flow illustrates a systematic procedure for constructing asymptotes and finding breakaway/break-in points for a given \( G(s) = K N(s)/D(s) \). This procedure is implemented later in code and is standard in computer-aided control design tools used in robotics.

flowchart TD
  A["Start with G(s) = K N(s)/D(s)"] --> B["Compute open-loop poles p_i and zeros z_j"]
  B --> C["Set np = number of poles, nz = number of zeros"]
  C --> D["If np > nz then qa = np - nz branches to infinity"]
  D --> E["Centroid sigma_a = (sum p_i - sum z_j)/qa"]
  E --> F["Angles theta_k = (2k+1) * pi / qa, k = 0,...,qa-1"]
  F --> G["Mark real-axis segments using odd-number rule"]
  G --> H["Form polynomials D(s), N(s); compute D'(s), N'(s)"]
  H --> I["Solve N(s) D'(s) - D(s) N'(s) = 0 for s"]
  I --> J["Select real solutions on root-locus segments with K(s) > 0"]
  J --> K["Breakaway / break-in points identified"]
        

6. Python Implementation (with Robotics Context)

In Python, an LTI model for a robotic joint (e.g., DC motor with gear reduction) is often represented using the python-control library, which is widely used in robotics education and research. Below we implement:

  • Computation of asymptote centroid and angles.
  • Candidate breakaway points using the derivative condition.
  • A simple check for real-axis root-locus membership.

import numpy as np

def centroid_and_angles(poles, zeros):
    """
    Compute centroid and asymptote angles for root locus of
    G(s) = K * N(s) / D(s).
    poles, zeros: 1D arrays of complex numbers (open-loop poles/zeros).
    """
    poles = np.asarray(poles, dtype=complex)
    zeros = np.asarray(zeros, dtype=complex)
    npoles = len(poles)
    nzeros = len(zeros)

    if nzeros == 0:
        zeros = np.array([], dtype=complex)

    qa = npoles - nzeros  # number of asymptotes
    if qa <= 0:
        raise ValueError("No asymptotes: npoles <= nzeros")

    sigma_a = (np.sum(poles) - np.sum(zeros)) / qa
    angles = [(2*k + 1) * np.pi / qa for k in range(qa)]
    return sigma_a, angles

def poly_from_roots(roots):
    """Return monic polynomial coefficients with given roots."""
    roots = np.asarray(roots, dtype=complex)
    if len(roots) == 0:
        return np.array([1.0])
    return np.poly(roots)  # highest degree first

def breakaway_candidates(poles, zeros, tol_im=1e-6):
    """
    Compute candidate breakaway/break-in points by solving
    N(s) D'(s) - D(s) N'(s) = 0.
    """
    D = poly_from_roots(poles)
    N = poly_from_roots(zeros)

    Dp = np.polyder(D)
    Np = np.polyder(N)

    # P(s) = N(s) D'(s) - D(s) N'(s)
    P = np.polysub(np.polymul(N, Dp), np.polymul(D, Np))
    roots_P = np.roots(P)

    # keep approximately real roots
    real_points = []
    for r in roots_P:
        if abs(r.imag) < tol_im:
            real_points.append(r.real)
    return np.array(sorted(real_points))

def is_on_real_axis_locus(x, poles, zeros, tol=1e-6):
    """
    Check if a real point x lies on the real-axis segment of the root locus
    using the 'odd-number of poles and zeros to the right' rule.
    """
    count = 0
    for p in poles:
        if abs(p.imag) < tol and p.real > x:
            count += 1
    for z in zeros:
        if abs(z.imag) < tol and z.real > x:
            count += 1
    return (count % 2) == 1

def K_of_s(s, poles, zeros):
    """Compute gain K(s) = -D(s)/N(s) for scalar s."""
    D = poly_from_roots(poles)
    N = poly_from_roots(zeros)
    Ds = np.polyval(D, s)
    Ns = np.polyval(N, s)
    return -Ds / Ns

# Example: DC motor position loop (simplified)
poles = [-2.0, -5.0, -20.0]  # open-loop poles
zeros = []                   # assume no open-loop zeros

sigma_a, angles = centroid_and_angles(poles, zeros)
print("Centroid sigma_a =", sigma_a)
print("Asymptote angles (deg) =", [a * 180/np.pi for a in angles])

cands = breakaway_candidates(poles, zeros)
print("Raw real candidates:", cands)

valid_break_points = []
for x in cands:
    if is_on_real_axis_locus(x, poles, zeros):
        Kx = K_of_s(x, poles, zeros)
        if np.isreal(Kx) and Kx > 0:
            valid_break_points.append((x, float(np.real(Kx))))

print("Valid breakaway/break-in points (x, K):")
for x, k in valid_break_points:
    print(f"  s = {x:.4f}, K = {k:.4f}")
      

In a robotics context, the poles and zeros would be obtained from a model of the actuator and load, possibly built using python-control or a robotics toolbox in Python. The computed centroid, asymptote angles, and breakaway points guide how the proportional gain \( K \) affects closed-loop dynamics of the joint.

7. C++ Implementation (Eigen, ROS/Robotics-Oriented)

In C++-based robotic software, controllers are often implemented within frameworks like ros_control or Orocos. The following code illustrates how one could compute breakaway candidates using Eigen for polynomial arithmetic. Here we assume that the open-loop poles and zeros are known from a linearized model of a robotic joint.


#include <iostream>
#include <vector>
#include <complex>
#include <Eigen/Dense>
#include <unsupported/Eigen/Polynomials>

using Scalar = std::complex<double>;

// Build monic polynomial from roots (highest degree first).
Eigen::VectorXcd polyFromRoots(const std::vector<Scalar>& roots) {
  if (roots.empty()) {
    Eigen::VectorXcd p(1);
    p(0) = Scalar(1.0, 0.0);
    return p;
  }
  Eigen::VectorXcd p(1);
  p(0) = Scalar(1.0, 0.0); // start with 1
  for (const auto& r : roots) {
    Eigen::VectorXcd q(p.size() + 1);
    q.setZero();
    for (int i = 0; i < p.size(); ++i) {
      q(i) += -r * p(i);
      q(i + 1) += p(i);
    }
    p = q;
  }
  return p;
}

// Differentiate polynomial p(s) (highest degree first).
Eigen::VectorXcd polyDeriv(const Eigen::VectorXcd& p) {
  int n = p.size() - 1;
  if (n <= 0) {
    Eigen::VectorXcd d(1);
    d(0) = Scalar(0.0, 0.0);
    return d;
  }
  Eigen::VectorXcd d(n);
  for (int i = 0; i < n; ++i) {
    d(i) = Scalar(double(n - i), 0.0) * p(i);
  }
  return d;
}

// Evaluate polynomial p(s) at s using Horner's method.
Scalar polyVal(const Eigen::VectorXcd& p, const Scalar& s) {
  Scalar y = Scalar(0.0, 0.0);
  for (int i = 0; i < p.size(); ++i) {
    y = y * s + p(i);
  }
  return y;
}

// Check if real point x lies on real-axis root-locus segment.
bool isOnRealAxisSegment(double x,
                         const std::vector<Scalar>& poles,
                         const std::vector<Scalar>& zeros,
                         double tol = 1e-8) {
  int count = 0;
  for (const auto& p : poles) {
    if (std::abs(p.imag()) < tol && p.real() > x) {
      ++count;
    }
  }
  for (const auto& z : zeros) {
    if (std::abs(z.imag()) < tol && z.real() > x) {
      ++count;
    }
  }
  return (count % 2) == 1;
}

int main() {
  // Example poles of a robotic joint open-loop model.
  std::vector<Scalar> poles = {
      Scalar(-2.0, 0.0), Scalar(-5.0, 0.0), Scalar(-20.0, 0.0)};
  std::vector<Scalar> zeros;  // no zeros

  Eigen::VectorXcd D = polyFromRoots(poles);
  Eigen::VectorXcd N = polyFromRoots(zeros);

  Eigen::VectorXcd Dp = polyDeriv(D);
  Eigen::VectorXcd Np = polyDeriv(N);

  // P(s) = N(s) D'(s) - D(s) N'(s)
  // Note: for empty zeros, N(s) = 1 and Np(s) = 0.
  int degP = std::max(Dp.size() + N.size() - 2, D.size() + Np.size() - 2);
  Eigen::VectorXcd P = Eigen::VectorXcd::Zero(degP + 1);

  // Convolution helper lambda.
  auto convolve = [](const Eigen::VectorXcd& a,
                     const Eigen::VectorXcd& b) {
    Eigen::VectorXcd c(a.size() + b.size() - 1);
    c.setZero();
    for (int i = 0; i < a.size(); ++i)
      for (int j = 0; j < b.size(); ++j)
        c(i + j) += a(i) * b(j);
    return c;
  };

  Eigen::VectorXcd NDp = convolve(N, Dp);
  Eigen::VectorXcd DNp = convolve(D, Np);
  // P = NDp - DNp
  int offset = P.size() - NDp.size();
  for (int i = 0; i < NDp.size(); ++i) P(i + offset) += NDp(i);
  offset = P.size() - DNp.size();
  for (int i = 0; i < DNp.size(); ++i) P(i + offset) -= DNp(i);

  // Solve P(s) = 0 using Eigen polynomial solver.
  Eigen::PolynomialSolver<std::complex<double>, Eigen::Dynamic> solver;
  solver.compute(P);
  auto rootsP = solver.roots();

  std::cout << "Candidate breakaway/break-in points:\n";
  std::vector<double> realCandidates;
  for (int i = 0; i < rootsP.size(); ++i) {
    Scalar r = rootsP(i);
    if (std::abs(r.imag()) < 1e-6) {
      double x = r.real();
      realCandidates.push_back(x);
      std::cout << "  s = " << x << "\n";
    }
  }

  std::cout << "On real-axis root-locus segments:\n";
  for (double x : realCandidates) {
    if (isOnRealAxisSegment(x, poles, zeros)) {
      std::cout << "  s = " << x << " is on the root locus (real axis).\n";
    }
  }

  return 0;
}
      

This code can be integrated into a ROS node that monitors the motion of a robot joint and uses root-locus-based reasoning for offline gain selection, ensuring that breakaway points remain in a region that yields acceptable damping and overshoot.

8. Java Implementation (Commons Math, Robotics Libraries)

Java-based robotics frameworks (e.g., WPILib for mobile robots) often use linear models and classical design internally. Here is a minimal Java-like snippet using Apache Commons Math to solve for breakaway candidates. The polynomial arithmetic can be adapted to any Java robotics stack.


import org.apache.commons.math3.complex.Complex;
import org.apache.commons.math3.analysis.polynomials.PolynomialFunction;
import org.apache.commons.math3.analysis.solvers.LaguerreSolver;
import java.util.Arrays;

public class RootLocusTools {

    public static PolynomialFunction polyFromRoots(Complex[] roots) {
        // Monic polynomial from roots.
        PolynomialFunction p = new PolynomialFunction(new double[]{1.0});
        for (Complex r : roots) {
            // Multiply by (s - r)
            PolynomialFunction q =
                new PolynomialFunction(new double[]{-r.getReal(), 1.0});
            // Imag part ignored for coefficients; complex roots should appear in conjugate pairs
            p = p.multiply(q);
        }
        return p;
    }

    public static PolynomialFunction polyDeriv(PolynomialFunction p) {
        return p.polynomialDerivative();
    }

    public static Complex[] breakawayCandidates(Complex[] poles, Complex[] zeros) {
        PolynomialFunction D = polyFromRoots(poles);
        PolynomialFunction N = zeros.length == 0
            ? new PolynomialFunction(new double[]{1.0})
            : polyFromRoots(zeros);

        PolynomialFunction Dp = polyDeriv(D);
        PolynomialFunction Np = polyDeriv(N);

        // P(s) = N(s) D'(s) - D(s) N'(s)
        PolynomialFunction NDp = N.multiply(Dp);
        PolynomialFunction DNp = D.multiply(Np);
        PolynomialFunction P = NDp.subtract(DNp);

        LaguerreSolver solver = new LaguerreSolver();
        Complex[] roots = solver.solveAllComplex(P.getCoefficients(), 0.0);

        return roots;
    }

    public static void main(String[] args) {
        Complex[] poles = new Complex[] {
            new Complex(-2.0, 0.0),
            new Complex(-5.0, 0.0),
            new Complex(-20.0, 0.0)
        };
        Complex[] zeros = new Complex[] {}; // none

        Complex[] cand = breakawayCandidates(poles, zeros);
        System.out.println("Breakaway / break-in candidates:");
        Arrays.stream(cand).forEach(c -> {
            if (Math.abs(c.getImaginary()) < 1e-6) {
                System.out.println("  s = " + c.getReal());
            }
        });
    }
}
      

Within a Java robotics library, the candidate breakaway points help engineers decide on acceptable ranges for proportional gain in position-control loops of actuated joints or mobile robot velocity controllers.

9. MATLAB/Simulink and Wolfram Mathematica

MATLAB and Simulink remain standard for industrial and robotic controller design. The Control System Toolbox and Robotics System Toolbox allow you to connect kinematic and dynamic models of manipulators to feedback loops and use root-locus tools for gain tuning.


% MATLAB script: asymptotes and breakaway points
% Example open-loop transfer function for a robotic joint servo.
num = 1;                % no zeros
den = conv([1 2], conv([1 5], [1 20]));  % (s+2)(s+5)(s+20)

sys = tf(num, den);

% Root locus and automatic breakaway visualization
figure;
rlocus(sys); grid on;
title('Root locus with asymptotes for robotic joint servo');

% Asymptotes: poles and zeros
p = pole(sys);
z = zero(sys);

np = length(p);
nz = length(z);
qa = np - nz;
sigma_a = (sum(p) - sum(z)) / qa;
angles = (2*(0:qa-1) + 1) * pi / qa;

disp('Centroid sigma_a = ');
disp(sigma_a);
disp('Asymptote angles (deg) = ');
disp(angles * 180/pi);

% Breakaway candidates via symbolic toolbox
syms s K;
D = poly2sym(den, s);
N = poly2sym(num, s);

eqK = -D / N;
dKds = diff(eqK, s);
candidates = double(solve(dKds == 0, s));

disp('Real candidate breakaway points:');
for k = 1:length(candidates)
    if abs(imag(candidates(k))) < 1e-6
        fprintf('  s = %.4f\n', real(candidates(k)));
    end
end

% In Simulink, the same sys can be used in a feedback loop
% and the SISO Design Tool can display root locus interactively.
      

In Wolfram Mathematica, the ControlSystems functionality provides analogous routines:


(* Mathematica script: asymptotes and breakaway points *)
ClearAll["Global`*"];

(* Open-loop model *)
num = {1};
den = Convolve[{1, 2}, Convolve[{1, 5}, {1, 20}]];

sys = TransferFunctionModel[num/den, s];

(* Root locus plot *)
RootLocusPlot[sys, {k, 0, 500},
  PlotTheme -> "Detailed",
  PlotLabel -> "Robotic joint servo root locus"];

(* Poles and zeros *)
poles = Poles[sys];
zeros = Zeros[sys];

np = Length[poles];
nz = Length[zeros];
qa = np - nz;

sigmaA = (Total[poles] - Total[zeros])/qa;

angles = Table[(2 k + 1) Pi/qa, {k, 0, qa - 1}];

Print["Centroid sigma_a = ", sigmaA];
Print["Asymptote angles (deg) = ",
      N[angles * 180/Pi]];

(* Breakaway candidates *)
D[s_] := FromDigits[den, s];
Nfun[s_] := FromDigits[num, s];

KofS[s_] := -D[s]/Nfun[s];
dKds = D[KofS[s], s];

cand = Solve[dKds == 0, s];
realCand = Select[s /. cand, Im[#] == 0 &];
Print["Real candidate breakaway points: ", N[realCand]];
      

These scripts can be integrated with manipulator models from the Robotics System Toolbox (MATLAB) or Mathematica's multibody libraries, enabling root-locus-based tuning of joint-space controllers.

10. Problems and Solutions

Problem 1 (Asymptotes for a Third-Order System). Consider \( G(s) = \dfrac{K}{s(s+2)(s+4)} \) in unity feedback.
(a) Determine \( n_p \), \( n_z \), the number of asymptotes, and their angles.
(b) Compute the centroid of the asymptotes.

Solution:

(a) The open-loop poles are at \( 0, -2, -4 \), so \( n_p = 3 \). There are no finite zeros, so \( n_z = 0 \). Thus \( n_a = n_p - n_z = 3 \) asymptotes. Their angles are

\[ \theta_k = \frac{(2k+1)\pi}{3}, \quad k = 0,1,2. \]

Hence \( \theta_0 = 60^\circ \), \( \theta_1 = 180^\circ \), \( \theta_2 = 300^\circ \).

(b) The centroid is

\[ \sigma_a = \frac{(0) + (-2) + (-4) - 0}{3} = \frac{-6}{3} = -2. \]

So the three asymptotes intersect the real axis at \( s = -2 \).

Problem 2 (Asymptotes with a Zero). For \( G(s) = K\dfrac{s+1}{s(s+2)(s+5)} \), find the centroid and asymptote angles.

Solution:

Poles: \( 0, -2, -5 \Rightarrow n_p = 3 \). Zero: \( -1 \Rightarrow n_z = 1 \). Thus \( n_a = n_p - n_z = 2 \).

\[ \theta_k = \frac{(2k+1)\pi}{2}, \quad k=0,1 \;\Rightarrow\; \theta_0 = 90^\circ,\; \theta_1 = 270^\circ. \]

The centroid is

\[ \sigma_a = \frac{(0) + (-2) + (-5) - (-1)}{2} = \frac{-6}{2} = -3. \]

Hence the asymptotes are vertical lines passing through \( s = -3 \) with angles \( \pm 90^\circ \).

Problem 3 (Breakaway Point via \( dK/ds = 0 \)). For the system \( G(s) = \dfrac{K}{s(s+4)} \), unity feedback:
(a) Derive \( K(s) \) from the characteristic equation.
(b) Find the real breakaway point on the interval \( (-4,0) \).

Solution:

The characteristic equation is

\[ 1 + \frac{K}{s(s+4)} = 0 \;\Longrightarrow\; s(s+4) + K = 0. \]

(a) Solving for \( K \):

\[ K(s) = -s(s+4) = -s^2 - 4s. \]

(b) Take the derivative:

\[ \frac{dK}{ds} = -2s - 4. \]

Setting \( dK/ds = 0 \) gives

\[ -2s - 4 = 0 \;\Longrightarrow\; s = -2. \]

The point \( s = -2 \) lies between the real poles at \( 0 \) and \( -4 \). The real-axis rule indicates that the segment \( (-4,0) \) is part of the root locus, so \( s = -2 \) is a breakaway point.

Problem 4 (Breakaway Polynomial for a Third-Order System). For \( G(s) = \dfrac{K}{(s+1)(s+3)(s+5)} \):
(a) Write the polynomials \( D(s) \) and \( N(s) \).
(b) Form the breakaway polynomial \( P(s) = N(s)D'(s) - D(s)N'(s) \) and simplify.
(c) Determine the real candidate breakaway points.

Solution:

(a) There are no finite zeros, so \( N(s) = 1 \). The denominator is

\[ D(s) = (s+1)(s+3)(s+5) = s^3 + 9s^2 + 23s + 15. \]

(b) Then

\[ D'(s) = 3s^2 + 18s + 23, \quad N'(s) = 0, \]

so

\[ P(s) = N(s)D'(s) - D(s)N'(s) = D'(s) = 3s^2 + 18s + 23. \]

(c) The candidate breakaway points are the roots of \( P(s) = 0 \):

\[ 3s^2 + 18s + 23 = 0 \;\Longrightarrow\; s = \frac{-18 \pm \sqrt{18^2 - 4\cdot 3 \cdot 23}}{2\cdot 3} = \frac{-18 \pm \sqrt{324 - 276}}{6} = \\ \frac{-18 \pm \sqrt{48}}{6} = \frac{-18 \pm 4\sqrt{3}}{6}. \]

Both roots are real: \( s_1 \approx -1.845 \), \( s_2 \approx -4.155 \). By checking the real-axis segments of the root locus, we retain only those that lie on segments where the odd-number rule holds (this depends on the specific pole positions at \( -1, -3, -5 \)).

Problem 5 (Conceptual: Breakaway vs Asymptotes). Explain qualitatively how the location of the centroid and asymptote angles influences where breakaway points appear for systems with only real poles and no zeros.

Solution:

For systems with only real poles and no zeros, all root-locus branches start on the real axis. As \( K \) increases:

  • Real-axis segments between adjacent poles are candidate locations for breakaway points, determined by \( dK/ds = 0 \).
  • As \( K \to \infty \), the branches must align with the asymptotes, whose centroid and angles are fixed by the pole locations.
  • Breakaway points occur in such a way that the branches leave the real axis and bend toward the asymptotic directions; segments closer to the centroid are more likely to lead to complex-conjugate branches that eventually align with the asymptotes.

This interplay can be summarized as:

flowchart TD
  P1["Real poles placed on real axis"] --> B1["Real-axis segments satisfy odd-number rule"]
  B1 --> B2["Solve dK/ds = 0 on those segments"]
  B2 --> B3["Breakaway points where multiple roots coincide"]
  B3 --> A1["Branches steer toward asymptote lines"]
  A1 --> A2["Asymptote centroid and angles determine far-field geometry"]
        

11. Summary

In this lesson we developed the analytical structure of root loci far from the origin and along the real axis. For systems with \( n_p \) poles and \( n_z \) zeros, we showed that \( n_p - n_z \) branches go to infinity along asymptotes with angles \( \theta_k = \dfrac{(2k+1)\pi}{n_p - n_z} \) and centroid \( \sigma_a = \dfrac{\sum p_i - \sum z_j}{n_p - n_z} \).

We also derived that breakaway and break-in points solve \( dK/ds = 0 \), or equivalently \( N(s)D'(s) - D(s)N'(s) = 0 \), and must lie on real-axis segments belonging to the root locus with positive gain. Algorithmic procedures and multi-language implementations (Python, C++, Java, MATLAB/Simulink, Mathematica) demonstrated how these formulas are used in practice, particularly for tuning robotic actuator loops where gain variation strongly influences closed-loop damping and overshoot.

12. References

  1. Evans, W.R. (1948). Control system synthesis by root locus method. Transactions of the American Institute of Electrical Engineers, 69(1), 66–69.
  2. Evans, W.R. (1950). Graphical analysis of control systems. Transactions of the American Institute of Electrical Engineers, 69(2), 547–551.
  3. Oldenbourg, R.C., & Sartorius, H. (1944). On the influence of zeros and poles of the transfer function on the transient behavior of control systems. Archiv für Elektrotechnik, 38, 424–437.
  4. Truxal, J.G. (1955). On the design of control systems with prescribed root locus. IRE Transactions on Automatic Control, 1(1), 20–28.
  5. MacFarlane, A.G.J. (1961). Root-locus methods in linear system theory. Proceedings of the IEE, 108(45), 653–665.
  6. Prett, D.M., & Garcia, C.E. (1975). Fundamental limitations in the design of root-locus compensators. International Journal of Control, 21(6), 1003–1019.
  7. Chait, Y., Hollot, C.V., & Lavretsky, E. (1996). Root-locus rules for systems with multiple time delays. IEEE Transactions on Automatic Control, 41(4), 584–588.
  8. Fadali, M.S. (1989). Root locus with respect to system parameters. IEEE Transactions on Automatic Control, 34(10), 1123–1126.
  9. Datta, B.N. (1989). Root-clustering and root-locus theory for matrix polynomials. Linear Algebra and its Applications, 109, 33–52.
  10. Saberi, A., & Sannuti, P. (1987). Observer-based root-locus design for linear systems. IEEE Transactions on Automatic Control, 32(5), 412–423.